bump release
[linux-2.6.git] / linux-2.6-820-megaraid.patch
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
4 @@ -2,26 +2,23 @@
5   *
6   *             Linux MegaRAID driver for SAS based RAID controllers
7   *
8 - * Copyright (c) 2003-2005  LSI Logic Corporation.
9 + * Copyright (c) 2009  LSI Corporation.
10   *
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.
17   *
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.
24   *
25 - * Authors:
26 - *     (email-id : megaraidlinux@lsi.com)
27 - *     Sreenivas Bagalkote
28 - *     Sumant Patro
29 - *     Bo Yang
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.
33   *
34 - * List of supported controllers
35 - *
36 - * OEM Product Name                    VID     DID     SSVID   SSID
37 - * --- ------------                    ---     ---     ----    ----
38 + * Send feedback to <Bo.Yang@lsi.com>
39   */
40  
41  #include <linux/kernel.h>
42 @@ -33,12 +30,14 @@
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>
49  #include <linux/fs.h>
50  #include <linux/compat.h>
51  #include <linux/blkdev.h>
52  #include <linux/mutex.h>
53 +#include <linux/poll.h>
54  
55  #include <scsi/scsi.h>
56  #include <scsi/scsi_cmnd.h>
57 @@ -46,10 +45,27 @@
58  #include <scsi/scsi_host.h>
59  #include "megaraid_sas.h"
60  
61 +/*
62 + * poll_mode_io:1- schedule complete completion from q cmd
63 + */
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)");
68 +
69 +/*
70 + * Number of sectors per IO command
71 + * Will be set in megasas_init_mfi if user does not provide
72 + */
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");
77 +
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");
83  
84  /*
85   * PCI ID table for all supported controllers
86 @@ -60,6 +76,16 @@ static struct pci_device_id megasas_pci_
87         /* xscale IOP */
88         {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078R)},
89         /* ppc IOP */
90 +       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
91 +       /* ppc IOP */
92 +       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
93 +       /* gen2*/
94 +       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
95 +       /* gen2*/
96 +       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)},
97 +       /* skinny*/
98 +       {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)},
99 +       /* skinny*/
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);
108 +
109 +
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;
114 +
115 +/* define lock for aen poll */
116 +spinlock_t poll_aen_lock;
117  
118  static u32 megasas_dbg_lvl;
119  
120 +static void
121 +megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
122 +                    u8 alt_status);
123 +
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);
134 +
135 +
136  /**
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
140  static inline void
141  megasas_enable_intr_xscale(struct megasas_register_set __iomem * regs)
142  {
143 -       writel(1, &(regs)->outbound_intr_mask);
144 +       writel(0, &(regs)->outbound_intr_mask);
145  
146         /* Dummy readl to force pci flush */
147         readl(&regs->outbound_intr_mask);
148 @@ -169,21 +221,27 @@ static int 
149  megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
150  {
151         u32 status;
152 +       u32 mfiStatus = 0;
153         /*
154          * Check if it is our interrupt
155          */
156         status = readl(&regs->outbound_intr_status);
157  
158 -       if (!(status & MFI_OB_INTR_STATUS_MASK)) {
159 -               return 1;
160 -       }
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;
165  
166         /*
167          * Clear the interrupt by writing back the same value
168          */
169 +       if (mfiStatus)
170         writel(status, &regs->outbound_intr_status);
171  
172 -       return 0;
173 +       /* Dummy readl to force pci flush */
174 +       readl(&regs->outbound_intr_status);
175 +
176 +       return mfiStatus;
177  }
178  
179  /**
180 @@ -193,10 +251,69 @@ megasas_clear_intr_xscale(struct megasas
181   * @regs :                     MFI register set
182   */
183  static inline void 
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,
187 +               u32 frame_count,
188 +               struct megasas_register_set __iomem *regs)
189  {
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);
195 +}
196 +
197 +/**
198 + * megasas_adp_reset_xscale -  For controller reset
199 + * @regs:                              MFI register set
200 + */
201 +static int 
202 +megasas_adp_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
203 +{
204 +        u32 i;
205 +       u32 pcidata;
206 +       writel(MFI_ADP_RESET, &regs->inbound_doorbell);
207 +
208 +       for (i=0; i < 3; i++)
209 +               msleep(1000); /* sleep for 3 secs */
210 +       pcidata =0;
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);
215 +               pcidata &= ~0x2;
216 +               pci_write_config_dword(instance->pdev, MFI_1068_PCSR_OFFSET, pcidata);
217 +
218 +               for (i=0; i<2; i++)
219 +                       msleep(1000); /* need to wait 2 secs again */
220 +
221 +               pcidata =0;
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);
226 +                       pcidata = 0;
227 +                       pci_write_config_dword(instance->pdev, MFI_1068_FW_HANDSHAKE_OFFSET, pcidata);
228 +               }
229 +       }
230 +       return 0;
231 +}
232 +
233 +/**
234 + * megasas_check_reset_xscale -        For controller reset check
235 + * @regs:                              MFI register set
236 + */
237 +static int 
238 +megasas_check_reset_xscale(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
239 +{
240 +       u32 consumer;
241 +       consumer = *instance->consumer;
242 +
243 +       if ((instance->adprecovery != MEGASAS_HBA_OPERATIONAL) && (*instance->consumer == MEGASAS_ADPRESET_INPROG_SIGN)) {
244 +               return 1;
245 +       }
246 +
247 +       return 0;
248  }
249  
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,
257  };
258  
259  /**
260 @@ -227,7 +346,7 @@ megasas_enable_intr_ppc(struct megasas_r
261  {
262         writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
263      
264 -       writel(~0x80000004, &(regs)->outbound_intr_mask);
265 +       writel(~0x80000000, &(regs)->outbound_intr_mask);
266  
267         /* Dummy readl to force pci flush */
268         readl(&regs->outbound_intr_mask);
269 @@ -270,7 +389,7 @@ megasas_clear_intr_ppc(struct megasas_re
270         status = readl(&regs->outbound_intr_status);
271  
272         if (!(status & MFI_REPLY_1078_MESSAGE_INTERRUPT)) {
273 -               return 1;
274 +               return 0;
275         }
276  
277         /*
278 @@ -278,7 +397,10 @@ megasas_clear_intr_ppc(struct megasas_re
279          */
280         writel(status, &regs->outbound_doorbell_clear);
281  
282 -       return 0;
283 +       /* Dummy readl to force pci flush */
284 +       readl(&regs->outbound_doorbell_clear);
285 +
286 +       return 1;
287  }
288  /**
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
292   */
293  static inline void 
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,
297 +               u32 frame_count,
298 +               struct megasas_register_set __iomem *regs)
299  {
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);
305 +}
306 +
307 +/**
308 + * megasas_adp_reset_ppc -     For controller reset
309 + * @regs:                              MFI register set
310 + */
311 +static int 
312 +megasas_adp_reset_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
313 +{
314 +       return 0;
315 +}
316 +
317 +/**
318 + * megasas_check_reset_ppc -   For controller reset check
319 + * @regs:                              MFI register set
320 + */
321 +static int 
322 +megasas_check_reset_ppc(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
323 +{
324 +       return 0;
325  }
326  
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,
334 +};
335 +
336 +/**
337 + * megasas_enable_intr_skinny -        Enables interrupts
338 + * @regs:                      MFI register set
339 + */
340 +static inline void
341 +megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs)
342 +{
343 +       writel(0xFFFFFFFF, &(regs)->outbound_intr_mask);
344 +
345 +       /* write ~0x00000005 (4 & 1) to the intr mask*/
346 +       writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
347 +
348 +       /* Dummy readl to force pci flush */
349 +       readl(&regs->outbound_intr_mask);
350 +}
351 +
352 +/**
353 + * megasas_disable_intr_skinny -       Disables interrupt
354 + * @regs:                      MFI register set
355 + */
356 +static inline void
357 +megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs)
358 +{
359 +       u32 mask = 0xFFFFFFFF;
360 +       writel(mask, &regs->outbound_intr_mask);
361 +       /* Dummy readl to force pci flush */
362 +       readl(&regs->outbound_intr_mask);
363 +}
364 +
365 +/**
366 + * megasas_read_fw_status_reg_skinny - returns the current FW status value
367 + * @regs:                      MFI register set
368 + */
369 +static u32
370 +megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs)
371 +{
372 +       return readl(&(regs)->outbound_scratch_pad);
373 +}
374 +
375 +/**
376 + * megasas_clear_interrupt_skinny -    Check & clear interrupt
377 + * @regs:                              MFI register set
378 + */
379 +static int
380 +megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
381 +{
382 +       u32 status;
383 +       u32 mfiStatus = 0;
384 +
385 +       /*
386 +        * Check if it is our interrupt
387 +        */
388 +       status = readl(&regs->outbound_intr_status);
389 +
390 +       if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) {
391 +               return 0;
392 +       }
393 +
394 +       
395 +       /*
396 +        * Check if it is our interrupt
397 +        */
398 +       if ((megasas_read_fw_status_reg_gen2( regs) & MFI_STATE_MASK ) == MFI_STATE_FAULT ){
399 +                mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
400 +        }else
401 +               mfiStatus |=  MFI_INTR_FLAG_REPLY_MESSAGE;
402 +
403 +       /*
404 +        * Clear the interrupt by writing back the same value
405 +        */
406 +       writel(status, &regs->outbound_intr_status);
407 +
408 +       /*
409 +       * dummy read to flush PCI
410 +       */
411 +       readl(&regs->outbound_intr_status);
412 +
413 +       return mfiStatus;
414 +}
415 +
416 +/**
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
421 + */
422 +static inline void
423 +megasas_fire_cmd_skinny(struct megasas_instance *instance,
424 +                       dma_addr_t frame_phys_addr,
425 +                       u32 frame_count,
426 +                       struct megasas_register_set __iomem *regs)
427 +{
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);
434 +       /*msleep(5);*/
435 +}
436 +
437 +/**
438 + * megasas_check_reset_skinny -        For controller reset check
439 + * @regs:                              MFI register set
440 + */
441 +static int 
442 +megasas_check_reset_skinny(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
443 +{
444 +       return 0;
445 +}
446 +
447 +static struct megasas_instance_template megasas_instance_template_skinny = {
448 +
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,
456 +};
457 +
458 +
459 +/**
460 +*      The following functions are defined for gen2 (deviceid : 0x78 0x79)
461 +*      controllers
462 +*/
463 +
464 +/**
465 + * megasas_enable_intr_gen2 -  Enables interrupts
466 + * @regs:                      MFI register set
467 + */
468 +static inline void
469 +megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
470 +{
471 +       writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
472 +
473 +       /* write ~0x00000005 (4 & 1) to the intr mask*/
474 +       writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
475 +
476 +       /* Dummy readl to force pci flush */
477 +       readl(&regs->outbound_intr_mask);
478 +}
479 +
480 +/**
481 + * megasas_disable_intr_gen2 - Disables interrupt
482 + * @regs:                      MFI register set
483 + */
484 +static inline void
485 +megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
486 +{
487 +       u32 mask = 0xFFFFFFFF;
488 +       writel(mask, &regs->outbound_intr_mask);
489 +       /* Dummy readl to force pci flush */
490 +       readl(&regs->outbound_intr_mask);
491 +}
492 +
493 +/**
494 + * megasas_read_fw_status_reg_gen2 - returns the current FW status value
495 + * @regs:                      MFI register set
496 + */
497 +static u32
498 +megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
499 +{
500 +       return readl(&(regs)->outbound_scratch_pad);
501 +}
502 +
503 +/**
504 + * megasas_clear_interrupt_gen2 -      Check & clear interrupt
505 + * @regs:                              MFI register set
506 + */
507 +static int
508 +megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
509 +{
510 +       u32 status;
511 +        u32 mfiStatus = 0;
512 +       /*
513 +        * Check if it is our interrupt
514 +        */
515 +       status = readl(&regs->outbound_intr_status);
516 +
517 +        if (status & MFI_GEN2_ENABLE_INTERRUPT_MASK)
518 +        {
519 +                mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
520 +        }
521 +        if (status & MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT)
522 +        {
523 +                mfiStatus |= MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
524 +        }
525 +
526 +       /*
527 +        * Clear the interrupt by writing back the same value
528 +        */
529 +        if (mfiStatus)
530 +       writel(status, &regs->outbound_doorbell_clear);
531 +
532 +       /* Dummy readl to force pci flush */
533 +       readl(&regs->outbound_intr_status);
534 +
535 +        return mfiStatus;
536 +
537 +}
538 +/**
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
543 + */
544 +static inline void
545 +megasas_fire_cmd_gen2(struct megasas_instance *instance,
546 +                       dma_addr_t frame_phys_addr,
547 +                       u32 frame_count,
548 +                       struct megasas_register_set __iomem *regs)
549 +{
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);
555 +}
556 +
557 +/**
558 + * megasas_adp_reset_gen2 -    For controller reset
559 + * @regs:                              MFI register set
560 + */
561 +static int 
562 +megasas_adp_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem * reg_set)
563 +{
564 +       u32                     retry = 0, delay = 0;
565 +       u32                     HostDiag;
566 +       u32                     *seq_offset = &reg_set->seq_offset;
567 +       u32                     *hostdiag_offset = &reg_set->host_diag;
568 +    
569 +       if ( instance->instancet ==  &megasas_instance_template_skinny ){
570 +               seq_offset = &reg_set->fusion_seq_offset;
571 +               hostdiag_offset = &reg_set->fusion_host_diag;
572 +       }
573 +
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);
580 +       
581 +       msleep(1000);
582 +
583 +       HostDiag = (u32)readl(hostdiag_offset);
584 +
585 +       while ( !( HostDiag & DIAG_WRITE_ENABLE) )
586 +       {
587 +               msleep(100);
588 +               HostDiag = (u32)readl(hostdiag_offset);
589 +               printk("ADP_RESET_GEN2: retry time=%x, hostdiag=%x\n", retry, HostDiag);
590 +               
591 +               if (retry++ >= 100) 
592 +                       return 1;
593 +
594 +}
595 +
596 +       printk("ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
597 +
598 +       writel((HostDiag | DIAG_RESET_ADAPTER), hostdiag_offset);
599 +
600 +       for (delay=0; delay<10; delay++) 
601 +       {
602 +               msleep(1000);
603 +       }
604 +       
605 +       HostDiag = (u32)readl(hostdiag_offset);
606 +       while ( ( HostDiag & DIAG_RESET_ADAPTER) )
607 +       {
608 +               msleep(100);
609 +               HostDiag = (u32)readl(hostdiag_offset);
610 +               printk("ADP_RESET_GEN2: retry time=%x, hostdiag=%x\n", retry, HostDiag);
611 +               
612 +               if (retry++ >= 1000) 
613 +                       return 1;
614 +
615 +       }
616 +       return 0;
617 +}
618 +
619 +/**
620 + * megasas_check_reset_gen2 -  For controller reset check
621 + * @regs:                              MFI register set
622 + */
623 +static int 
624 +megasas_check_reset_gen2(struct megasas_instance *instance, struct megasas_register_set __iomem * regs)
625 +{
626 +       if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
627 +               return 1;
628 +       }
629 +
630 +       return 0;
631 +}
632 +
633 +static struct megasas_instance_template megasas_instance_template_gen2 = {
634 +       
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,
642  };
643  
644  /**
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
648  */
649  
650  /**
651 @@ -328,13 +786,17 @@ megasas_issue_polled(struct megasas_inst
652         /*
653          * Issue the frame using inbound queue port
654          */
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);
658  
659         /*
660          * Wait for cmd_status to change
661          */
662         for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) {
663                 rmb();
664 +               //FW using xor/copy as soon as we enable cpx
665 +               if ( instance->cpx_supported )
666 +                       megasas_handle_cpx_requests( instance);
667                 msleep(1);
668         }
669  
670 @@ -359,10 +821,10 @@ megasas_issue_blocked_cmd(struct megasas
671  {
672         cmd->cmd_status = ENODATA;
673  
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);
677  
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);
681  
682         return 0;
683  }
684 @@ -404,13 +866,15 @@ megasas_issue_blocked_abort_cmd(struct m
685         cmd->sync_cmd = 1;
686         cmd->cmd_status = 0xFF;
687  
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);
691  
692         /*
693          * Wait for this cmd to complete
694          */
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);
698 +       cmd->sync_cmd = 0;
699 +
700  
701         megasas_return_cmd(instance, cmd);
702         return 0;
703 @@ -513,14 +977,66 @@ megasas_make_sgl64(struct megasas_instan
704         return sge_count;
705  }
706  
707 - /**
708 - * megasas_get_frame_count - Computes the number of frames
709 - * @sge_count          : number of sg elements
710 +/**
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
715 + *
716 + * If successful, this function returns the number of SG elements. Otherwise,
717 + * it returnes -1.
718 + */
719 +static int
720 +megasas_make_sgl_skinny(struct megasas_instance *instance,
721 +               struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
722 +{
723 +       int i;
724 +       int sge_count;
725 +       struct scatterlist *os_sgl;
726 +
727 +       /*
728 +        * Return 0 if there is no data transfer
729 +        */
730 +       if (!scp->request_buffer || !scp->request_bufflen)
731 +               return 0;
732 +
733 +       if (!scp->use_sg) {
734 +               mfi_sgl->sge_skinny[0].phys_addr = pci_map_single(instance->pdev,
735 +                                                            scp->
736 +                                                            request_buffer,
737 +                                                            scp->
738 +                                                            request_bufflen,
739 +                                                            scp->
740 +                                                            sc_data_direction);
741 +
742 +               mfi_sgl->sge_skinny[0].length = scp->request_bufflen;
743 +
744 +               return 1;
745 +       }
746 +
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);
750 +
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;
755 +       }
756 +
757 +       return sge_count;
758 +}
759 +
760 + /**
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
764   *
765   * Returns the number of frames required for numnber of sge's (sge_count)
766   */
767  
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)
771  {
772         int num_cnt;
773         int sge_bytes;
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);
777  
778 +       if (instance->flag_ieee) {
779 +               sge_sz = sizeof(struct megasas_sge_skinny);
780 +       }
781 +
782         /*
783 -       * Main frame can contain 2 SGEs for 64-bit SGLs and
784 -       * 3 SGEs for 32-bit SGLs
785 -       */
786 -       if (IS_DMA64)
787 -               num_cnt = sge_count - 2;
788 -       else
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
794 +        */
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;
800 +               else
801 +                       num_cnt = sge_count - 2;
802 +       } else {
803 +               if (instance->flag_ieee == 1) {
804 +                       num_cnt = sge_count - 1;
805 +               } else if (IS_DMA64)
806 +                       num_cnt = sge_count - 2;
807 +               else
808 +                       num_cnt = sge_count - 3;
809 +       }
810  
811         if(num_cnt>0){
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;
816  
817 +       if (instance->flag_ieee == 1) {
818 +               flags |= MFI_FRAME_IEEE;
819 +       }
820 +
821         /*
822          * Prepare the DCDB frame
823          */
824 @@ -592,15 +1129,31 @@ megasas_build_dcdb(struct megasas_instan
825         pthru->lun = scp->device->lun;
826         pthru->cdb_len = scp->cmd_len;
827         pthru->timeout = 0;
828 +       pthru->pad_0 = 0;
829         pthru->flags = flags;
830         pthru->data_xfer_len = scp->request_bufflen;
831  
832         memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
833  
834         /*
835 +       * If the command is for the tape device, set the
836 +       * pthru timeout to the os layer timeout value.
837 +       */
838 +       if (scp->device->type == TYPE_TAPE) {
839 +               if ((scp->request->timeout / HZ) > 0xFFFF)
840 +                       pthru->timeout = 0xFFFF;
841 +               else
842 +                       pthru->timeout = scp->request->timeout / HZ;
843 +       }
844 +
845 +       /*
846          * Construct SGL
847          */
848 -       if (IS_DMA64) {
849 +       if (instance->flag_ieee == 1) {
850 +               pthru->flags |= MFI_FRAME_SGL64;
851 +               pthru->sge_count = megasas_make_sgl_skinny(instance, scp,
852 +                                                     &pthru->sgl);
853 +       } else if (IS_DMA64) {
854                 pthru->flags |= MFI_FRAME_SGL64;
855                 pthru->sge_count = megasas_make_sgl64(instance, scp,
856                                                       &pthru->sgl);
857 @@ -608,6 +1161,10 @@ megasas_build_dcdb(struct megasas_instan
858                 pthru->sge_count = megasas_make_sgl32(instance, scp,
859                                                       &pthru->sgl);
860  
861 +       if (pthru->sge_count > instance->max_num_sge) {
862 +               printk("megasas: build_dcdb error, two many SGE\n");
863 +               return 0;
864 +       }
865         /*
866          * Sense info specific
867          */
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.
871          */
872 -       cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
873 +       cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count,
874 +                                                       PTHRU_FRAME);
875  
876         return cmd->frame_count;
877  }
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
881   * @scp:               SCSI command
882 - * @cmd:               Command to to be prepared
883 + * @cmd:               Command to be prepared
884   *
885   * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
886   */
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;
890  
891 +       if (instance->flag_ieee == 1) {
892 +               flags |= MFI_FRAME_IEEE;
893 +       }
894 +
895         /*
896          * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
897          */
898 @@ -719,12 +1281,20 @@ megasas_build_ldio(struct megasas_instan
899         /*
900          * Construct SGL
901          */
902 -       if (IS_DMA64) {
903 +       if (instance->flag_ieee) {
904 +               ldio->flags |= MFI_FRAME_SGL64;
905 +               ldio->sge_count = megasas_make_sgl_skinny(instance, scp,
906 +                                             &ldio->sgl);
907 +       } else if (IS_DMA64) {
908                 ldio->flags |= MFI_FRAME_SGL64;
909                 ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
910         } else
911                 ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
912  
913 +        if (ldio->sge_count > instance->max_num_sge) {
914 +               printk("megasas: build_ld_io  error, sge_count = %x\n", ldio->sge_count);
915 +               return 0;
916 +       }
917         /*
918          * Sense info specific
919          */
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.
923          */
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);
927  
928         return cmd->frame_count;
929  }
930 @@ -841,14 +1412,25 @@ megasas_queue_command(struct scsi_cmnd *
931         u32 frame_count;
932         struct megasas_cmd *cmd;
933         struct megasas_instance *instance;
934 +       unsigned long flags;
935  
936         instance = (struct megasas_instance *)
937             scmd->device->host->hostdata;
938  
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;
943  
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;
951 +       }
952 +
953 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
954 +
955         scmd->scsi_done = done;
956         scmd->result = 0;
957  
958 @@ -893,7 +1475,14 @@ megasas_queue_command(struct scsi_cmnd *
959          */
960         atomic_inc(&instance->fw_outstanding);
961  
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);
965 +       /*
966 +        * Check if we have pend cmds to be completed
967 +        */
968 +       if (poll_mode_io && atomic_read(&instance->fw_outstanding))
969 +               tasklet_schedule(&instance->isr_tasklet);
970 +
971  
972         return 0;
973  
974 @@ -904,211 +1493,1527 @@ megasas_queue_command(struct scsi_cmnd *
975         return 0;
976  }
977  
978 +static struct megasas_instance *megasas_lookup_instance(u16 host_no)
979 +{
980 +       int i;
981 +
982 +       for (i = 0; i < megasas_mgmt_info.max_index; i++) {
983 +
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];
987 +       }
988 +
989 +       return NULL;
990 +}
991 +
992  static int megasas_slave_configure(struct scsi_device *sdev)
993  {
994 +       u16             pd_index = 0;
995 +       struct  megasas_instance *instance ;
996 +
997 +       instance = megasas_lookup_instance(sdev->host->host_no);
998 +
999         /*
1000 -        * Don't export physical disk devices to the disk driver.
1001 -        *
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.
1005 -        */
1006 -       if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
1007 +       * Don't export physical disk devices to the disk driver.
1008 +       *
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.
1012 +       */
1013 +       if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) {
1014 +               if (sdev->type == TYPE_TAPE) {
1015 +                       sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
1016 +                       return 0;
1017 +               } else if (sdev->type == TYPE_DISK) {
1018 +               
1019 +                       pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
1020 +               
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;
1024 +                               return 0;
1025 +                       }
1026 +               }
1027                 return -ENXIO;
1028 +       }
1029  
1030         /*
1031 -        * The RAID firmware may require extended timeouts.
1032 -        */
1033 -       if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
1034 -               sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
1035 +       * The RAID firmware may require extended timeouts.
1036 +       */
1037 +       sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
1038         return 0;
1039  }
1040  
1041 -/**
1042 - * megasas_wait_for_outstanding -      Wait for all outstanding cmds
1043 - * @instance:                          Adapter soft state
1044 - *
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.
1048 - */
1049 -static int megasas_wait_for_outstanding(struct megasas_instance *instance)
1050 +static void megaraid_sas_kill_hba(struct megasas_instance *instance)
1051  {
1052 -       int i;
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))
1056 +       {
1057 +               writel(MFI_STOP_ADP,
1058 +                       &instance->reg_set->reserved_0);
1059 +       } else {
1060 +               writel(MFI_STOP_ADP,
1061 +                       &instance->reg_set->inbound_doorbell);
1062 +       }
1063 +}
1064  
1065 -       for (i = 0; i < wait_time; i++) {
1066  
1067 -               int outstanding = atomic_read(&instance->fw_outstanding);
1068  
1069 -               if (!outstanding)
1070 -                       break;
1071  
1072 -               if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
1073 -                       printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
1074 -                              "commands to complete\n",i,outstanding);
1075 -               }
1076 +void xor_gen_15x1(u32 *buff_ptrs[16], u32 bytes)
1077 +{
1078 +    u32    off, words;
1079 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14, *s15;
1080  
1081 -               msleep(1000);
1082 -       }
1083 +    d   = buff_ptrs[0];
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];
1099  
1100 -       if (atomic_read(&instance->fw_outstanding)) {
1101 -               /*
1102 -               * Send signal to FW to stop processing any pending cmds.
1103 -               * The controller will be taken offline by the OS now.
1104 -               */
1105 -               writel(MFI_STOP_ADP,
1106 -                               &instance->reg_set->inbound_doorbell);
1107 -               megasas_dump_pending_frames(instance);
1108 -               instance->hw_crit_error = 1;
1109 -               return FAILED;
1110 -       }
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];
1114  
1115 -       return SUCCESS;
1116  }
1117  
1118 -/**
1119 - * megasas_generic_reset -     Generic reset routine
1120 - * @scmd:                      Mid-layer SCSI command
1121 - *
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.
1125 - */
1126 -static int megasas_generic_reset(struct scsi_cmnd *scmd)
1127 +
1128 +void xor_gen_14x1(u32 *buff_ptrs[15], u32 bytes)
1129  {
1130 -       int ret_val;
1131 -       struct megasas_instance *instance;
1132 +    u32    off, words;
1133 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14;
1134  
1135 -       instance = (struct megasas_instance *)scmd->device->host->hostdata;
1136 +    d   = buff_ptrs[0];
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];
1151  
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];
1157  
1158 -       if (instance->hw_crit_error) {
1159 -               printk(KERN_ERR "megasas: cannot recover from previous reset "
1160 -                      "failures\n");
1161 -               return FAILED;
1162 -       }
1163 +}
1164  
1165 -       ret_val = megasas_wait_for_outstanding(instance);
1166 -       if (ret_val == SUCCESS)
1167 -               printk(KERN_NOTICE "megasas: reset successful \n");
1168 -       else
1169 -               printk(KERN_ERR "megasas: failed to do reset\n");
1170  
1171 -       return ret_val;
1172 +void xor_gen_13x1(u32 *buff_ptrs[14], u32 bytes)
1173 +{
1174 +    u32    off, words;
1175 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13;
1176 +
1177 +    d   = buff_ptrs[0];
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];
1191 +
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];
1195 +
1196  }
1197  
1198 -/**
1199 - * megasas_reset_timer - quiesce the adapter if required
1200 - * @scmd:              scsi cmnd
1201 - *
1202 - * Sets the FW busy flag and reduces the host->can_queue if the
1203 - * cmd has not been completed within the timeout period.
1204 - */
1205 -static enum
1206 -scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
1207 -{
1208 -       struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
1209 -       struct megasas_instance *instance;
1210 -       unsigned long flags;
1211  
1212 -       if (time_after(jiffies, scmd->jiffies_at_alloc +
1213 -                               (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
1214 -               return EH_NOT_HANDLED;
1215 -       }
1216 +void xor_gen_12x1(u32 *buff_ptrs[13], u32 bytes)
1217 +{
1218 +    u32    off, words;
1219 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12;
1220  
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);
1225 +    d   = buff_ptrs[0];
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];
1238  
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];
1245  
1246 -               spin_unlock_irqrestore(instance->host->host_lock, flags);
1247 -       }
1248 -       return EH_RESET_TIMER;
1249  }
1250  
1251 -/**
1252 - * megasas_reset_device -      Device reset handler entry point
1253 - */
1254 -static int megasas_reset_device(struct scsi_cmnd *scmd)
1255 +
1256 +void xor_gen_11x1(u32 *buff_ptrs[12], u32 bytes)
1257  {
1258 -       int ret;
1259 +    u32    off, words;
1260 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11;
1261  
1262 -       /*
1263 -        * First wait for all commands to complete
1264 -        */
1265 -       ret = megasas_generic_reset(scmd);
1266 +    d   = buff_ptrs[0];
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];
1278 +
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];
1282  
1283 -       return ret;
1284  }
1285  
1286 -/**
1287 - * megasas_reset_bus_host -    Bus & host reset handler entry point
1288 - */
1289 -static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
1290 +
1291 +void xor_gen_10x1(u32 *buff_ptrs[11], u32 bytes)
1292  {
1293 -       int ret;
1294 +    u32    off, words;
1295 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10;
1296  
1297 -       /*
1298 -        * First wait for all commands to complete
1299 -        */
1300 -       ret = megasas_generic_reset(scmd);
1301 +    d   = buff_ptrs[0];
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];
1312 +
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];
1316  
1317 -       return ret;
1318  }
1319  
1320 -/**
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
1326 - */
1327 -static int
1328 -megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
1329 -                sector_t capacity, int geom[])
1330 +
1331 +void xor_gen_9x1(u32 *buff_ptrs[10], u32 bytes)
1332  {
1333 -       int heads;
1334 -       int sectors;
1335 -       sector_t cylinders;
1336 -       unsigned long tmp;
1337 -       /* Default heads (64) & sectors (32) */
1338 -       heads = 64;
1339 -       sectors = 32;
1340 +    u32    off, words;
1341 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1342  
1343 -       tmp = heads * sectors;
1344 -       cylinders = capacity;
1345 +    d   = buff_ptrs[0];
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];
1355  
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];
1360  
1361 -       /*
1362 -        * Handle extended translation size for logical drives > 1Gb
1363 -        */
1364 +}
1365  
1366 -       if (capacity >= 0x200000) {
1367 -               heads = 255;
1368 -               sectors = 63;
1369 -               tmp = heads*sectors;
1370 -               cylinders = capacity;
1371 -               sector_div(cylinders, tmp);
1372 -       }
1373  
1374 -       geom[0] = heads;
1375 -       geom[1] = sectors;
1376 -       geom[2] = cylinders;
1377 +void xor_gen_8x1(u32 *buff_ptrs[9], u32 bytes)
1378 +{
1379 +    u32    off, words;
1380 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8;
1381 +
1382 +    d   = buff_ptrs[0];
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];
1391 +
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];
1394  
1395 -       return 0;
1396  }
1397  
1398 -/**
1399 - * megasas_service_aen -       Processes an event notification
1400 - * @instance:                  Adapter soft state
1401 +
1402 +void xor_gen_7x1(u32 *buff_ptrs[8], u32 bytes)
1403 +{
1404 +    u32    off, words;
1405 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7;
1406 +
1407 +    d   = buff_ptrs[0];
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];
1415 +
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];
1418 +
1419 +}
1420 +
1421 +
1422 +void xor_gen_6x1(u32 *buff_ptrs[7], u32 bytes)
1423 +{
1424 +    u32    off, words;
1425 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6;
1426 +
1427 +    d   = buff_ptrs[0];
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];
1434 +
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];
1437 +
1438 +}
1439 +
1440 +
1441 +void xor_gen_5x1(u32 *buff_ptrs[6], u32 bytes)
1442 +{
1443 +    u32    off, words;
1444 +    u32    *d, *s1, *s2, *s3, *s4, *s5;
1445 +
1446 +    d   = buff_ptrs[0];
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];
1452 +
1453 +    for (words = bytes/4, off=0; words>0; words--, off++)
1454 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off];
1455 +
1456 +}
1457 +
1458 +
1459 +void xor_gen_4x1(u32 *buff_ptrs[5], u32 bytes)
1460 +{
1461 +    u32    off, words;
1462 +    u32    *d, *s1, *s2, *s3, *s4;
1463 +
1464 +    d   = buff_ptrs[0];
1465 +    s1  = buff_ptrs[1];
1466 +    s2  = buff_ptrs[2];
1467 +    s3  = buff_ptrs[3];
1468 +    s4  = buff_ptrs[4];
1469 +
1470 +    for (words = bytes/4, off=0; words>0; words--, off++)
1471 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off];
1472 +
1473 +}
1474 +
1475 +
1476 +void xor_gen_3x1(u32 *buff_ptrs[4], u32 bytes)
1477 +{
1478 +    u32    off, words;
1479 +    u32    *d, *s1, *s2, *s3;
1480 +
1481 +    d   = buff_ptrs[0];
1482 +    s1  = buff_ptrs[1];
1483 +    s2  = buff_ptrs[2];
1484 +    s3  = buff_ptrs[3];
1485 +
1486 +    for (words = bytes/4, off=0; words>0; words--, off++)
1487 +        d[off] = s1[off] ^ s2[off] ^ s3[off];
1488 +
1489 +}
1490 +
1491 +
1492 +void xor_gen_2x1(u32 *buff_ptrs[3], u32 bytes)
1493 +{
1494 +    u32    off, words;
1495 +    u32    *d, *s1, *s2;
1496 +
1497 +    d   = buff_ptrs[0];
1498 +    s1  = buff_ptrs[1];
1499 +    s2  = buff_ptrs[2];
1500 +
1501 +    for (words = bytes/4, off=0; words>0; words--, off++)
1502 +        d[off] = s1[off] ^ s2[off];
1503 +    
1504 +}
1505 +
1506 +
1507 +void xor_gen_1x1(u32 *buff_ptrs[2], u32 bytes)
1508 +{
1509 +    u32    off, words;
1510 +    u32    *d, *s1;
1511 +
1512 +    d   = buff_ptrs[0];
1513 +    s1  = buff_ptrs[1];
1514 +
1515 +    for (words = bytes/4, off=0; words>0; words--, off++)
1516 +        d[off] = s1[off];
1517 +
1518 +}
1519 +
1520 +
1521 +u8 xor_chk_15x1(u32 *buff_ptrs[16], u32 bytes)
1522 +{
1523 +    u32    off, words;
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;
1526 +
1527 +    d   = buff_ptrs[0];
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];
1543 +
1544 +
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];
1548 +        if (r) {
1549 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1550 +            d[off] ^= r;
1551 +        }
1552 +    }
1553 +    return xor_result;
1554 +}
1555 +
1556 +
1557 +u8 xor_chk_14x1(u32 *buff_ptrs[15], u32 bytes)
1558 +{
1559 +    u32    off, words;
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;
1562 +
1563 +    d   = buff_ptrs[0];
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];
1578 +
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];
1582 +        if (r) {
1583 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1584 +            d[off] ^= r;
1585 +        }
1586 +    }
1587 +    return xor_result;
1588 +
1589 +}
1590 +
1591 +
1592 +u8 xor_chk_13x1(u32 *buff_ptrs[14], u32 bytes)
1593 +{
1594 +    u32    off, words;
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;
1597 +
1598 +    d   = buff_ptrs[0];
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];
1612 +
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];
1616 +        if (r) {
1617 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1618 +            d[off] ^= r;
1619 +        }
1620 +    }
1621 +    return xor_result;
1622 +
1623 +}
1624 +
1625 +
1626 +u8 xor_chk_12x1(u32 *buff_ptrs[13], u32 bytes)
1627 +{
1628 +    u32    off, words;
1629 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12;
1630 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1631 +
1632 +    d   = buff_ptrs[0];
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];
1645 +
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];
1649 +        if (r) {
1650 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1651 +            d[off] ^= r;
1652 +        }
1653 +    }
1654 +    return xor_result;
1655 +
1656 +}
1657 +
1658 +
1659 +u8 xor_chk_11x1(u32 *buff_ptrs[12], u32 bytes)
1660 +{
1661 +    u32    off, words;
1662 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11;
1663 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1664 +
1665 +    d   = buff_ptrs[0];
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];
1677 +
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];
1681 +        if (r) {
1682 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1683 +            d[off] ^= r;
1684 +        }
1685 +    }
1686 +    return xor_result;
1687 +
1688 +}
1689 +
1690 +
1691 +u8 xor_chk_10x1(u32 *buff_ptrs[11], u32 bytes)
1692 +{
1693 +    u32    off, words;
1694 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10;
1695 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1696 +
1697 +    d   = buff_ptrs[0];
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];
1708 +
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];
1712 +        if (r) {
1713 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1714 +            d[off] ^= r;
1715 +        }
1716 +    }
1717 +    return xor_result;
1718 +}
1719 +
1720 +
1721 +u8 xor_chk_9x1(u32 *buff_ptrs[10], u32 bytes)
1722 +{
1723 +    u32    off, words;
1724 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1725 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1726 +
1727 +    d   = buff_ptrs[0];
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];
1737 +
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];
1741 +        if (r) {
1742 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1743 +            d[off] ^= r;
1744 +        }
1745 +    }
1746 +    return xor_result;
1747 +}
1748 +
1749 +
1750 +u8 xor_chk_8x1(u32 *buff_ptrs[9], u32 bytes)
1751 +{
1752 +    u32    off, words;
1753 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8;
1754 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1755 +
1756 +    d   = buff_ptrs[0];
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];
1765 +
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];
1768 +        if (r) {
1769 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1770 +            d[off] ^= r;
1771 +        }
1772 +    }
1773 +    return xor_result;
1774 +}
1775 +
1776 +
1777 +u8 xor_chk_7x1(u32 *buff_ptrs[8], u32 bytes)
1778 +{
1779 +    u32    off, words;
1780 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7;
1781 +    u8    xor_result = MR_CPX_STATUS_SUCCESS;
1782 +
1783 +    d   = buff_ptrs[0];
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];
1791 +
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];
1794 +        if (r) {
1795 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1796 +            d[off] ^= r;
1797 +        }
1798 +    }
1799 +    return xor_result;
1800 +
1801 +}
1802 +
1803 +
1804 +u8 xor_chk_6x1(u32 *buff_ptrs[7], u32 bytes)
1805 +{
1806 +    u32    off, words;
1807 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6;
1808 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1809 +
1810 +    d   = buff_ptrs[0];
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];
1817 +
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];
1820 +        if (r) {
1821 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1822 +            d[off] ^= r;
1823 +        }
1824 +    }
1825 +    return xor_result;
1826 +}
1827 +
1828 +
1829 +u8 xor_chk_5x1(u32 *buff_ptrs[6], u32 bytes)
1830 +{
1831 +    u32    off, words;
1832 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5;
1833 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1834 +
1835 +    d   = buff_ptrs[0];
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];
1841 +
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];
1844 +        if (r) {
1845 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1846 +            d[off] ^= r;
1847 +        }
1848 +    }
1849 +    return xor_result;
1850 +}
1851 +
1852 +
1853 +u8 xor_chk_4x1(u32 *buff_ptrs[5], u32 bytes)
1854 +{
1855 +    u32    off, words;
1856 +    u32    r, *d, *s1, *s2, *s3, *s4;
1857 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1858 +
1859 +    d   = buff_ptrs[0];
1860 +    s1  = buff_ptrs[1];
1861 +    s2  = buff_ptrs[2];
1862 +    s3  = buff_ptrs[3];
1863 +    s4  = buff_ptrs[4];
1864 +
1865 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1866 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off];
1867 +        if (r) {
1868 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1869 +            d[off] ^= r;
1870 +        }
1871 +    }
1872 +    return xor_result;
1873 +}
1874 +
1875 +
1876 +u8 xor_chk_3x1(u32 *buff_ptrs[4], u32 bytes)
1877 +{
1878 +    u32    off, words;
1879 +    u32    r, *d, *s1, *s2, *s3;
1880 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1881 +
1882 +    d   = buff_ptrs[0];
1883 +    s1  = buff_ptrs[1];
1884 +    s2  = buff_ptrs[2];
1885 +    s3  = buff_ptrs[3];
1886 +
1887 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1888 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off];
1889 +        if (r) {
1890 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1891 +            d[off] ^= r;
1892 +        }
1893 +    }
1894 +    return xor_result;
1895 +}
1896 +
1897 +
1898 +u8 xor_chk_2x1(u32 *buff_ptrs[3], u32 bytes)
1899 +{
1900 +    u32    off, words;
1901 +    u32    r, *d, *s1, *s2;
1902 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1903 +
1904 +    d   = buff_ptrs[0];
1905 +    s1  = buff_ptrs[1];
1906 +    s2  = buff_ptrs[2];
1907 +
1908 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1909 +        r = d[off] ^ s1[off] ^ s2[off];
1910 +        if (r) {
1911 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1912 +            d[off] ^= r;
1913 +        }
1914 +    }
1915 +    return xor_result;
1916 +}
1917 +
1918 +
1919 +u8 xor_chk_1x1(u32 *buff_ptrs[2], u32 bytes)
1920 +{
1921 +    u32    off, words;
1922 +    u32    *d, *s1;
1923 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1924 +
1925 +    d   = buff_ptrs[0];
1926 +    s1  = buff_ptrs[1];
1927 +
1928 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1929 +        if (d[off] != s1[off]) {
1930 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1931 +            d[off] = s1[off];
1932 +        }
1933 +    }
1934 +    return xor_result;
1935 +}
1936 +
1937 +
1938 +XOR_LOW_LEVEL_GEN_FUNC  xor_gen_funcs[MAX_MR_ROW_SIZE] = {
1939 +    xor_gen_1x1,
1940 +    xor_gen_2x1,
1941 +    xor_gen_3x1,
1942 +    xor_gen_4x1,
1943 +    xor_gen_5x1,
1944 +    xor_gen_6x1,
1945 +    xor_gen_7x1,
1946 +    xor_gen_8x1,
1947 +    xor_gen_9x1,
1948 +    xor_gen_10x1,
1949 +    xor_gen_11x1,
1950 +    xor_gen_12x1,
1951 +    xor_gen_13x1,
1952 +    xor_gen_14x1,
1953 +    xor_gen_15x1,
1954 + };
1955 +
1956 +XOR_LOW_LEVEL_CHECK_FUNC  xor_check_funcs[MAX_MR_ROW_SIZE] = {
1957 +    xor_chk_1x1,
1958 +    xor_chk_2x1,
1959 +    xor_chk_3x1,
1960 +    xor_chk_4x1,
1961 +    xor_chk_5x1,
1962 +    xor_chk_6x1,
1963 +    xor_chk_7x1,
1964 +    xor_chk_8x1,
1965 +    xor_chk_9x1,
1966 +    xor_chk_10x1,
1967 +    xor_chk_11x1,
1968 +    xor_chk_12x1,
1969 +    xor_chk_13x1,
1970 +    xor_chk_14x1,
1971 +    xor_chk_15x1,
1972 +};
1973 +
1974 +inline static u8 megasas_scan_set_bit(u32 bitmap)
1975 +{
1976 +    u8  bit = 0;
1977 +
1978 +    while (bitmap) {
1979 +        if (bitmap & 1)
1980 +            return bit;
1981 +
1982 +        bitmap >>= 1;
1983 +        bit++;
1984 +    }
1985 +    return ~0;
1986 +}
1987 +
1988 +
1989 +/**
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.        
1994 + *     
1995 + * @return 0 on success != 0 on failure
1996 + * 
1997 + */
1998 +static u8 megasas_do_cpx_xor( struct mr_cpx_xor_descriptor *xor_des, const u8 *host_mem, const  u32 host_mem_len)
1999 +{
2000 +
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;
2007 +       
2008 +
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;
2012 +       else 
2013 +               dest_idx = xor_des->q_idx;
2014 +
2015 +       buf_ptr_list[0] = (u32 *)(host_mem + xor_des->buff_list[dest_idx]);
2016 +       
2017 +       is_op_gen = MR_CPX_XOR_OP_IS_GEN(xor_des->op);
2018 +
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;
2022 +       }
2023 +
2024 +       /*
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[].
2029 +        */
2030 +       if ( !is_op_gen)
2031 +               buff_valid_bit_map &= ~(1<<xor_des->p_idx);
2032 +       
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;;
2040 +               }
2041 +               buff_valid_bit_map &= ~(1 <<bit);
2042 +       }
2043 +       //call the xor gen fuctions.
2044 +       if ( is_op_gen )
2045 +       (*xor_gen_funcs[buf_idx-2])(buf_ptr_list, tx_count);
2046 +       else
2047 +               status = (*xor_check_funcs[buf_idx-2])(buf_ptr_list, tx_count);
2048 +       
2049 +       return status;
2050 +}
2051 +
2052 +static u8 megasas_copy( struct page *page, u32 page_offset, u32 sge_offset, u8 *host_ptr, u32 len, u8 dir)
2053 +{
2054 +       u8 *page_addr;
2055 +       u32 off;
2056 +       u32 bytes_copied;
2057 +       u32 remaining;
2058 +
2059 +       remaining = len;
2060 +       off = page_offset+sge_offset;
2061 +
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 ){
2065 +
2066 +               bytes_copied = min((size_t)remaining, (size_t)(PAGE_SIZE - (off & ~PAGE_MASK)));
2067 +
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;;
2072 +               }
2073 +               if ( dir == MR_CPX_DIR_WRITE )
2074 +                       memcpy( host_ptr, page_addr+(off & ~PAGE_MASK), bytes_copied );
2075 +               else 
2076 +                       memcpy( page_addr+(off & ~PAGE_MASK), host_ptr, bytes_copied );
2077 +       
2078 +               kunmap_atomic ( page_addr, KM_SOFTIRQ0 );
2079 +
2080 +               host_ptr += bytes_copied;
2081 +               remaining -= bytes_copied;
2082 +               off += bytes_copied;
2083 +       }
2084 +       
2085 +       return MR_CPX_STATUS_SUCCESS;
2086 +}
2087 +/**
2088 + * megasas_do_cpx_copy - Completes the copy opreation 
2089 + * @instance           : Driver soft state.
2090 + * @cpy_des            : input for copying the data.
2091 + *     
2092 + * @return 0 on success != 0 on failure
2093 + * 
2094 + */
2095 +static u8 megasas_do_cpx_copy( struct megasas_instance *instance, struct mr_cpx_copy_descriptor *cpy_des)
2096 +{
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;
2106 +
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;
2110 +       }
2111 +       
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;
2116 +
2117 +       host_skip_count_handled = 0;
2118 +       row_idx = 0;
2119 +       fw_ptr = NULL;
2120 +       row_remaining_length =0;
2121 +       os_sgl = (struct scatterlist *)os_cmd->request_buffer;
2122 +
2123 +       for ( os_sge_idx=0; os_sge_idx < sge_cnt; os_sge_idx++, os_sgl++ ){
2124 +               
2125 +               os_sge_len = sg_dma_len(os_sgl);
2126 +
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;
2134 +                       continue;
2135 +               }
2136 +               
2137 +               if ( !host_skip_count_handled )
2138 +                       continue;
2139 +               
2140 +               for( ;total_remaining_len &&  row_idx < MAX_MR_ROW_SIZE ; row_idx++ ){
2141 +
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;
2145 +                       }
2146 +
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) ) )
2149 +                            break;
2150 +                       
2151 +                       total_remaining_len -= MIN(os_sge_len, row_remaining_length);
2152 +                       
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;
2157 +                               break;
2158 +                       }else{
2159 +                               os_sge_len -= row_remaining_length;
2160 +                               os_sge_offset += row_remaining_length;
2161 +                               row_remaining_length =0;
2162 +                       }
2163 +
2164 +               }
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);
2168 +               
2169 +               if( total_remaining_len == 0 || status == MR_CPX_STATUS_FAILURE )
2170 +                       break;
2171 +       }
2172 +
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);
2176 +               
2177 +       return status;
2178 +       
2179 +}
2180 +/**
2181 + * megasas_handle_cpx_requests - Manages the fw queues 
2182 + * @instance           : Driver soft state.
2183 + *     
2184 + * @return 0 on success != 0 on failure
2185 + * 
2186 + */
2187 +static int megasas_handle_cpx_requests( struct megasas_instance *instance)
2188 +{
2189 +       struct mr_cpx_request_queue *req_q = instance->cpx_request_queue;
2190 +       u32 producer_idx, consumer_idx;
2191 +       u8 retval = 0;
2192 +       unsigned long flags;
2193 +
2194 +       producer_idx = req_q->producer_idx;
2195 +       consumer_idx = req_q->consumer_idx;
2196 +       
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;
2200 +
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 );
2203 +               
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 );
2207 +               else{
2208 +                       printk("Fatal Error : Got invalid descriptor type...\n");
2209 +                       retval = MR_CPX_STATUS_FAILURE;
2210 +                       break;
2211 +               }
2212 +
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;
2216 +
2217 +               //notify fw.
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);
2222 +
2223 +               //take care of wrap around case.
2224 +               consumer_idx++;
2225 +               if ( consumer_idx == instance->cpx_dscrptr_cnt )
2226 +                       consumer_idx = 0;
2227 +               
2228 +       }
2229 +               req_q->consumer_idx = producer_idx;
2230 +       
2231 +       return 0;
2232 +}
2233 +
2234 +/**
2235 + * megasas_complete_cmd_dpc     -      Returns FW's controller structure
2236 + * @instance_addr:                     Address of adapter soft state
2237 + *
2238 + * Tasklet to complete cmds
2239 + */
2240 +static void megasas_complete_cmd_dpc(unsigned long instance_addr)
2241 +{
2242 +       u32 producer;
2243 +       u32 consumer;
2244 +       u32 context;
2245 +       struct megasas_cmd *cmd;
2246 +       struct megasas_instance *instance =
2247 +                               (struct megasas_instance *)instance_addr;
2248 +       unsigned long flags;
2249 +
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);
2254 +               return;
2255 +       }
2256 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
2257 +
2258 +       spin_lock_irqsave(&instance->completion_lock, flags);
2259 +
2260 +       producer = *instance->producer;
2261 +       consumer = *instance->consumer;
2262 +
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);
2267 +                       BUG();
2268 +               }
2269 +
2270 +               cmd = instance->cmd_list[context];
2271 +
2272 +               megasas_complete_cmd(instance, cmd, DID_OK);
2273 +
2274 +               consumer++;
2275 +               if (consumer == (instance->max_fw_cmds + 1)) {
2276 +                       consumer = 0;
2277 +               }
2278 +       }
2279 +
2280 +       *instance->consumer = producer;
2281 +
2282 +       spin_unlock_irqrestore(&instance->completion_lock, flags);
2283 +       
2284 +
2285 +
2286 +       if ( instance->cpx_supported )
2287 +               megasas_handle_cpx_requests( instance);
2288 +
2289 +       /*
2290 +        * Check if we can restore can_queue
2291 +        */
2292 +       if (instance->flag & MEGASAS_FW_BUSY
2293 +               && time_after(jiffies, instance->last_time + 5 * HZ)
2294 +               && atomic_read(&instance->fw_outstanding) < 17) {
2295 +
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;
2304 +               } else
2305 +                       instance->host->can_queue =
2306 +                               instance->max_fw_cmds - MEGASAS_INT_CMDS;
2307 +
2308 +               spin_unlock_irqrestore(instance->host->host_lock, flags);
2309 +       }
2310 +}
2311 +
2312 +static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
2313 +static void process_fw_state_change_wq(struct work_struct *work); 
2314 +
2315 +void megasas_do_ocr(struct megasas_instance *instance)
2316 +{
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))
2320 +       {
2321 +               *instance->consumer     = MEGASAS_ADPRESET_INPROG_SIGN;
2322 +       }
2323 +
2324 +       instance->instancet->disable_intr(instance->reg_set);
2325 +       instance->adprecovery   = MEGASAS_ADPRESET_SM_INFAULT;
2326 +       instance->issuepend_done = 0;
2327 +
2328 +       atomic_set(&instance->fw_outstanding, 0);
2329 +       megasas_internal_reset_defer_cmds(instance);
2330 +       process_fw_state_change_wq(&instance->work_init); 
2331 +}
2332 +
2333 +
2334 +/**
2335 + * megasas_wait_for_outstanding -      Wait for all outstanding cmds
2336 + * @instance:                          Adapter soft state
2337 + *
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.
2341 + */
2342 +static int megasas_wait_for_outstanding(struct megasas_instance *instance)
2343 +{
2344 +       int i, sl;
2345 +       u32 reset_index;
2346 +       u32 wait_time = MEGASAS_RESET_WAIT_TIME;
2347 +       u8 adprecovery;
2348 +       unsigned long flags;
2349 +       struct list_head clist_local;
2350 +       struct megasas_cmd *reset_cmd;
2351 +       u32 fw_state;
2352 +       u8 kill_adapter_flag;
2353 +
2354 +
2355 +       // If we are in-process if internal reset, we should wait for that process to
2356 +       // complete
2357 +       spin_lock_irqsave(&instance->hba_lock, flags);
2358 +       adprecovery = instance->adprecovery;
2359 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
2360 +
2361 +       if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
2362 +
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);
2369 +
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++) {
2372 +                       msleep(1000);
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)
2378 +                               break;
2379 +               }
2380 +
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);
2387 +                       return FAILED;
2388 +               }
2389 +
2390 +               printk("megasas: HBA internal reset condition discovered to be cleared.\n");
2391 +
2392 +               // Send the pending commands back to the OS with reset condition
2393 +               reset_index     = 0;
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);
2403 +                       }
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);
2409 +                       }
2410 +                       else {
2411 +                               printk("megasas: %p unexpected command on the internal reset defer list.\n", reset_cmd);
2412 +                       }
2413 +                       reset_index++;
2414 +               }
2415 +
2416 +               printk("megaraid_sas: All pending commands have been cleared for reset condition.\n");
2417 +
2418 +               return SUCCESS;
2419 +       }
2420 +
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);
2425 +
2426 +               if (!outstanding)
2427 +                       break;
2428 +
2429 +               if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
2430 +                       printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
2431 +                              "commands to complete\n",i,outstanding);
2432 +                       /*
2433 +                        * Call cmd completion routine. Cmd to be
2434 +                        * be completed directly without depending on isr.
2435 +                        */
2436 +                       megasas_complete_cmd_dpc((unsigned long)instance);
2437 +               }
2438 +
2439 +               msleep(1000);
2440 +       }
2441 +
2442 +       i = 0;
2443 +       kill_adapter_flag = 0;
2444 +       do {
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);
2448 +                       if (i == 3) {
2449 +                               kill_adapter_flag = 2;
2450 +                               break;
2451 +                       } 
2452 +                        megasas_do_ocr(instance);
2453 +                       kill_adapter_flag = 1;
2454 +                        printk("megasas: waiting_for_outstanding: after issue OCR. \n");
2455 +
2456 +                        /* wait for 5 secs to let the FW finish all the pending cmds*/
2457 +                        for (sl=0; sl<10; sl++)
2458 +                                msleep(500);
2459 +               }
2460 +               i++;
2461 +       } while (i <= 3);
2462 +
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");
2468 +
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);
2472 +
2473 +                               if (!outstanding)
2474 +                                       return SUCCESS;
2475 +                                msleep(1000);
2476 +                       }
2477 +               } 
2478 +       }
2479 +
2480 +       if (atomic_read(&instance->fw_outstanding) || (kill_adapter_flag == 2)) {
2481 +               printk("megaraid_sas: pending commands remain even after reset handling.\n");
2482 +               /*
2483 +               * Send signal to FW to stop processing any pending cmds.
2484 +               * The controller will be taken offline by the OS now.
2485 +               */
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);
2492 +               } else {
2493 +                       writel(MFI_STOP_ADP,
2494 +                               &instance->reg_set->inbound_doorbell);
2495 +               }
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);
2500 +               return FAILED;
2501 +       }
2502 +
2503 +       printk("megaraid_sas: no more pending commands remain after reset handling.\n");
2504 +
2505 +       return SUCCESS;
2506 +}
2507 +
2508 +/**
2509 + * megasas_generic_reset -     Generic reset routine
2510 + * @scmd:                      Mid-layer SCSI command
2511 + *
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.
2515 + */
2516 +static int megasas_generic_reset(struct scsi_cmnd *scmd)
2517 +{
2518 +       int ret_val;
2519 +       struct megasas_instance *instance;
2520 +
2521 +       instance = (struct megasas_instance *)scmd->device->host->hostdata;
2522 +
2523 +       scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
2524 +                scmd->serial_number, scmd->cmnd[0], scmd->retries);
2525 +
2526 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
2527 +               printk(KERN_ERR "megasas: cannot recover from previous reset "
2528 +                      "failures\n");
2529 +               return FAILED;
2530 +       }
2531 +
2532 +       ret_val = megasas_wait_for_outstanding(instance);
2533 +       if (ret_val == SUCCESS)
2534 +               printk(KERN_NOTICE "megasas: reset successful \n");
2535 +       else
2536 +               printk(KERN_ERR "megasas: failed to do reset\n");
2537 +
2538 +       return ret_val;
2539 +}
2540 +
2541 +/**
2542 + * megasas_reset_timer - quiesce the adapter if required
2543 + * @scmd:              scsi cmnd
2544 + *
2545 + * Sets the FW busy flag and reduces the host->can_queue if the
2546 + * cmd has not been completed within the timeout period.
2547 + */
2548 +static enum
2549 +scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
2550 +{
2551 +       struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
2552 +       struct megasas_instance *instance;
2553 +       unsigned long flags;
2554 +
2555 +       if (time_after(jiffies, scmd->jiffies_at_alloc +
2556 +                               (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
2557 +               return EH_NOT_HANDLED;
2558 +       }
2559 +
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);
2564 +
2565 +               instance->host->can_queue = 16;
2566 +               instance->last_time = jiffies;
2567 +               instance->flag |= MEGASAS_FW_BUSY;
2568 +
2569 +               spin_unlock_irqrestore(instance->host->host_lock, flags);
2570 +       }
2571 +       return EH_RESET_TIMER;
2572 +}
2573 +
2574 +/**
2575 + * megasas_reset_device -      Device reset handler entry point
2576 + */
2577 +static int megasas_reset_device(struct scsi_cmnd *scmd)
2578 +{
2579 +       int ret;
2580 +
2581 +       /*
2582 +        * First wait for all commands to complete
2583 +        */
2584 +       ret = megasas_generic_reset(scmd);
2585 +
2586 +       return ret;
2587 +}
2588 +
2589 +/**
2590 + * megasas_reset_bus_host -    Bus & host reset handler entry point
2591 + */
2592 +static int megasas_reset_bus_host(struct scsi_cmnd *scmd)
2593 +{
2594 +       int ret;
2595 +
2596 +       /*
2597 +        * First wait for all commands to complete
2598 +        */
2599 +       ret = megasas_generic_reset(scmd);
2600 +
2601 +       return ret;
2602 +}
2603 +
2604 +/**
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
2610 + */
2611 +static int
2612 +megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev,
2613 +                sector_t capacity, int geom[])
2614 +{
2615 +       int heads;
2616 +       int sectors;
2617 +       sector_t cylinders;
2618 +       unsigned long tmp;
2619 +       /* Default heads (64) & sectors (32) */
2620 +       heads = 64;
2621 +       sectors = 32;
2622 +
2623 +       tmp = heads * sectors;
2624 +       cylinders = capacity;
2625 +
2626 +       sector_div(cylinders, tmp);
2627 +
2628 +       /*
2629 +        * Handle extended translation size for logical drives > 1Gb
2630 +        */
2631 +
2632 +       if (capacity >= 0x200000) {
2633 +               heads = 255;
2634 +               sectors = 63;
2635 +               tmp = heads*sectors;
2636 +               cylinders = capacity;
2637 +               sector_div(cylinders, tmp);
2638 +       }
2639 +
2640 +       geom[0] = heads;
2641 +       geom[1] = sectors;
2642 +       geom[2] = cylinders;
2643 +
2644 +       return 0;
2645 +}
2646 +
2647 +static void megasas_aen_polling(struct work_struct *work);
2648 +
2649 +/**
2650 + * megasas_service_aen -       Processes an event notification
2651 + * @instance:                  Adapter soft state
2652   * @cmd:                       AEN command completed by the ISR
2653   *
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
2656  static void
2657  megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
2658  {
2659 +       unsigned long flags;
2660         /*
2661          * Don't signal app if it is just an aborted previously registered aen
2662          */
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);
2670 +       }
2671         else
2672                 cmd->abort_aen = 0;
2673  
2674         instance->aen_cmd = NULL;
2675         megasas_return_cmd(instance, cmd);
2676 +
2677 +       if ((instance->unload == 0) && ((instance->issuepend_done == 1))) {
2678 +               struct megasas_aen_event *ev;
2679 +               ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2680 +               if (!ev) {
2681 +                       printk(KERN_ERR "megasas_service_aen: out of memory\n");
2682 +               } else {
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);
2688 +               }
2689 +       }
2690  }
2691  
2692 +static int megasas_slave_alloc(struct scsi_device *sdev)
2693 +{
2694 +       u16             pd_index = 0;
2695 +       struct megasas_instance *instance ;
2696 +       instance = megasas_lookup_instance(sdev->host->host_no);
2697 +
2698 +       if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) &&
2699 +               (sdev->type == TYPE_DISK)) {
2700 +               /*
2701 +                * Open the OS scan to the SYSTEM PD
2702 +                */
2703 +               pd_index =
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 ==
2708 +                       TYPE_DISK)) {
2709 +                       return 0;
2710 +               }
2711 +
2712 +               return -ENXIO;
2713 +       }
2714 +       return 0;
2715 +}
2716 +
2717 +
2718  /*
2719   * Scsi host template for megaraid_sas driver
2720   */
2721  static struct scsi_host_template megasas_template = {
2722  
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
2733  
2734         return;
2735  }
2736 -
2737  /**
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;
2742  
2743         if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
2744 -               if (IS_DMA64)
2745 +               if (instance->flag_ieee) {
2746 +                       buf_h = cmd->frame->io.sgl.sge_skinny[0].phys_addr;
2747 +
2748 +               } else if (IS_DMA64)
2749                         buf_h = cmd->frame->io.sgl.sge64[0].phys_addr;
2750                 else
2751                         buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
2752         } else {
2753 -               if (IS_DMA64)
2754 +               if (instance->flag_ieee) {
2755 +                       buf_h = cmd->frame->pthru.sgl.sge_skinny[0].phys_addr;
2756 +
2757 +               } else if (IS_DMA64)
2758                         buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr;
2759                 else
2760                         buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr;
2761 @@ -1233,6 +3190,7 @@ megasas_unmap_sgbuf(struct megasas_insta
2762         return;
2763  }
2764  
2765 +
2766  /**
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,
2771                      u8 alt_status)
2772  {
2773 +       unsigned long flags;
2774         int exception = 0;
2775         struct megasas_header *hdr = &cmd->frame->hdr;
2776  
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;
2780 +
2781         if (cmd->scmd)
2782                 cmd->scmd->SCp.ptr = NULL;
2783  
2784 @@ -1338,6 +3301,12 @@ megasas_complete_cmd(struct megasas_inst
2785         case MFI_CMD_SMP:
2786         case MFI_CMD_STP:
2787         case MFI_CMD_DCMD:
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);
2793 +               }
2794  
2795                 /*
2796                  * See if got an event notification
2797 @@ -1364,39 +3333,286 @@ megasas_complete_cmd(struct megasas_inst
2798  }
2799  
2800  /**
2801 + * megasas_issue_pending_cmds_again -  issue all pending cmds
2802 + *                                     in FW again because of the fw reset
2803 + * @instance:                          Adapter soft state
2804 + */
2805 +static inline void
2806 +megasas_issue_pending_cmds_again(struct megasas_instance *instance)
2807 +{
2808 +       struct megasas_cmd *cmd;
2809 +       struct list_head clist_local;
2810 +       union megasas_evt_class_locale class_locale;
2811 +       unsigned long flags;
2812 +       u32 seq_num;
2813 +
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);
2818 +
2819 +       while (!list_empty(&clist_local)) {
2820 +               cmd     = list_entry((&clist_local)->next, struct megasas_cmd, list);
2821 +               list_del_init(&cmd->list);
2822 +
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);
2825 +
2826 +                       cmd->retry_for_fw_reset++;
2827 +
2828 +                       // If a command has continuously been tried multiple times and causing
2829 +                       // a FW reset condition, no further recoveries should be performed on
2830 +                       // the controller
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);
2834 +
2835 +                               instance->adprecovery   = MEGASAS_HW_CRITICAL_ERROR;
2836 +                              return;
2837 +                       }
2838 +               }
2839 +
2840 +               if (cmd->sync_cmd == 1) {
2841 +                       if (cmd->scmd) {
2842 +                               printk("megaraid_sas: unexpected SCSI command attached to internal command!\n");
2843 +                       }
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);
2851 +               }
2852 +               else {
2853 +                       printk("megasas: %p unexpected command on the internal reset defer list while re-issue!!\n", cmd);
2854 +               }
2855 +       }
2856 +
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;
2862 +       }
2863 +
2864 +       /*
2865 +       * Initiate AEN (Asynchronous Event Notification)
2866 +       */
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;
2871 +
2872 +       megasas_register_aen(instance, seq_num, class_locale.word);
2873 +
2874 +
2875 +}
2876 +
2877 +/**
2878 + * Move the internal reset pending commands to a deferred queue.
2879 + *
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
2883 + * commands.
2884 + **/
2885 +static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
2886 +{
2887 +        struct megasas_cmd *cmd;
2888 +        int i;
2889 +        u32 max_cmd = instance->max_fw_cmds;
2890 +        u32 defer_index;
2891 +        unsigned long flags;
2892 +
2893 +        defer_index     = 0;
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);
2903 +                        }
2904 +                        defer_index++;
2905 +                        list_add_tail(&cmd->list, &instance->internal_reset_pending_q);
2906 +                }
2907 +        }
2908 +        spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
2909 +}
2910 +
2911 +
2912 +static void 
2913 +process_fw_state_change_wq(struct work_struct *work) 
2914 +{
2915 +       struct megasas_instance *instance =
2916 +               container_of(work, struct megasas_instance, work_init);
2917 +        u32 wait;
2918 +        unsigned long flags;
2919 +
2920 +        if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
2921 +                printk("megaraid_sas: error, unexpected adapter recovery state %x in %s\n", instance->adprecovery, __FUNCTION__);
2922 +                return ;
2923 +        }
2924 +
2925 +       if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
2926 +               printk("megaraid_sas: FW detected to be in fault state, restarting it...\n");
2927 +
2928 +               instance->instancet->disable_intr(instance->reg_set);
2929 +                atomic_set(&instance->fw_outstanding, 0);
2930 +
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 );
2934 +
2935 +               printk("megaraid_sas: FW was restarted successfully, initiating next stage...\n");
2936 +
2937 +               printk("megaraid_sas: HBA recovery state machine, state 2 starting...\n");
2938 +
2939 +                /*waitting for about 20 second before start the second init*/
2940 +                for(wait = 0; wait < 30; wait++)
2941 +                        msleep(1000);
2942 +
2943 +                if (megasas_transition_to_ready(instance))
2944 +                {
2945 +                        printk("megaraid_sas: out: controller is not in ready state\n");
2946 +
2947 +                        megaraid_sas_kill_hba(instance);
2948 +                       instance->adprecovery   = MEGASAS_HW_CRITICAL_ERROR;
2949 +                        return ;
2950 +                }
2951 +
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))
2955 +                {
2956 +                        *instance->consumer = *instance->producer;
2957 +                } else {
2958 +                        *instance->consumer = 0;
2959 +                        *instance->producer = 0;
2960 +                }
2961 +
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);
2966 +                       }
2967 +               }
2968 +
2969 +               // Transition the FW to operational state
2970 +               megasas_issue_init_mfi(instance);
2971 +
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);
2979 +
2980 +               printk("megaraid_sas: second stage of reset complete, FW is ready now.\n");
2981 +
2982 +               megasas_issue_pending_cmds_again(instance);
2983 +               instance->issuepend_done = 1;
2984 +
2985 +
2986 +       }
2987 +       return ;
2988 +}
2989 +
2990 +/**
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
2997   */
2998  static int
2999  megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
3000  {
3001 -       /*
3002 -        * Check if it is our interrupt
3003 -        * Clear the interrupt 
3004 -        */
3005 -       if(instance->instancet->clear_intr(instance->reg_set))
3006 +       u32 mfiStatus;
3007 +       u32 fw_state;
3008 +
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;
3013 +        }
3014 +
3015 +       // Clear the interrupt on the HBA
3016 +       if((mfiStatus = instance->instancet->clear_intr(instance->reg_set)) == 0) {
3017                 return IRQ_NONE;
3018 +       }
3019  
3020 -       if (instance->hw_crit_error)
3021 -               goto out_done;
3022 -        /*
3023 -        * Schedule the tasklet for cmd completion
3024 -        */
3025 +       instance->mfiStatus = mfiStatus;
3026 +
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;
3031 +
3032 +                if (fw_state != MFI_STATE_FAULT) {
3033 +                        printk("megaraid_sas: fw state while internal state change operational, state:%x\n", fw_state);
3034 +                }
3035 +
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");
3038 +
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))
3042 +                                       {
3043 +                                       *instance->consumer     = MEGASAS_ADPRESET_INPROG_SIGN;
3044 +                               }
3045 +
3046 +
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;
3050 +
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);
3055 +
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;
3061 +               }
3062 +               else {
3063 +                       printk("megaraid_sas: fw state while internal state changes, state:%x, disableOCR=%x\n",
3064 +                               fw_state, instance->disableOnlineCtrlReset);
3065 +               }
3066 +       }
3067 +
3068 +       // Schedule the tasklet for cmd completion
3069         tasklet_schedule(&instance->isr_tasklet);
3070 -out_done:
3071         return IRQ_HANDLED;
3072  }
3073 -
3074  /**
3075   * megasas_isr - isr entry point
3076   */
3077  static irqreturn_t megasas_isr(int irq, void *devp)
3078  {
3079 -       return megasas_deplete_reply_queue((struct megasas_instance *)devp,
3080 -                                          DID_OK);
3081 +       struct megasas_instance *instance;
3082 +       unsigned long flags;
3083 +       irqreturn_t     rc;
3084 +      
3085 +       if ( atomic_read( &(( (struct megasas_instance *)devp)->fw_reset_no_pci_access )) )
3086 +                return IRQ_HANDLED;
3087 +
3088 +       instance = (struct megasas_instance *)devp;
3089 +
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);
3093 +
3094 +       return rc;
3095  }
3096  
3097  /**
3098 @@ -1415,6 +3631,7 @@ megasas_transition_to_ready(struct megas
3099         u8 max_wait;
3100         u32 fw_state;
3101         u32 cur_state;
3102 +       u32 abs_state, curr_abs_state;
3103  
3104         fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
3105  
3106 @@ -1424,6 +3641,8 @@ megasas_transition_to_ready(struct megas
3107  
3108         while (fw_state != MFI_STATE_READY) {
3109  
3110 +               abs_state = instance->instancet->read_fw_status_reg(instance->reg_set);
3111 +
3112                 switch (fw_state) {
3113  
3114                 case MFI_STATE_FAULT:
3115 @@ -1435,18 +3654,36 @@ megasas_transition_to_ready(struct megas
3116                         /*
3117                          * Set the CLR bit in inbound doorbell
3118                          */
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)) {
3125 +
3126 +                               writel(
3127 +                                 MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3128 +                                       &instance->reg_set->reserved_0);
3129 +                       } else {
3130 +                               writel(
3131 +                                   MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3132 +                                       &instance->reg_set->inbound_doorbell);
3133 +                       }
3134  
3135 -                       max_wait = 2;
3136 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3137                         cur_state = MFI_STATE_WAIT_HANDSHAKE;
3138                         break;
3139  
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);
3149 +                       } else 
3150 +                               writel(MFI_INIT_HOTPLUG,
3151 +                                       &instance->reg_set->inbound_doorbell);
3152  
3153 -                       max_wait = 10;
3154 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3155                         cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
3156                         break;
3157  
3158 @@ -1455,9 +3692,17 @@ megasas_transition_to_ready(struct megas
3159                          * Bring it to READY state; assuming max wait 10 secs
3160                          */
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);
3169 +                       } else 
3170 +                               writel(MFI_RESET_FLAGS,
3171 +                                       &instance->reg_set->inbound_doorbell);
3172  
3173 -                       max_wait = 10;
3174 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3175                         cur_state = MFI_STATE_OPERATIONAL;
3176                         break;
3177  
3178 @@ -1465,32 +3710,32 @@ megasas_transition_to_ready(struct megas
3179                         /*
3180                          * This state should not last for more than 2 seconds
3181                          */
3182 -                       max_wait = 2;
3183 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3184                         cur_state = MFI_STATE_UNDEFINED;
3185                         break;
3186  
3187                 case MFI_STATE_BB_INIT:
3188 -                       max_wait = 2;
3189 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3190                         cur_state = MFI_STATE_BB_INIT;
3191                         break;
3192  
3193                 case MFI_STATE_FW_INIT:
3194 -                       max_wait = 20;
3195 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3196                         cur_state = MFI_STATE_FW_INIT;
3197                         break;
3198  
3199                 case MFI_STATE_FW_INIT_2:
3200 -                       max_wait = 20;
3201 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3202                         cur_state = MFI_STATE_FW_INIT_2;
3203                         break;
3204  
3205                 case MFI_STATE_DEVICE_SCAN:
3206 -                       max_wait = 20;
3207 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3208                         cur_state = MFI_STATE_DEVICE_SCAN;
3209                         break;
3210  
3211                 case MFI_STATE_FLUSH_CACHE:
3212 -                       max_wait = 20;
3213 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3214                         cur_state = MFI_STATE_FLUSH_CACHE;
3215                         break;
3216  
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) &  
3220                                         MFI_STATE_MASK ;
3221 +               curr_abs_state =
3222 +               instance->instancet->read_fw_status_reg(instance->reg_set);
3223  
3224 -                       if (fw_state == cur_state) {
3225 +                       if (abs_state == curr_abs_state) {
3226                                 msleep(1);
3227                         } else
3228                                 break;
3229 @@ -1516,12 +3763,12 @@ megasas_transition_to_ready(struct megas
3230                 /*
3231                  * Return error if fw_state hasn't changed after max_wait
3232                  */
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);
3237                         return -ENODEV;
3238                 }
3239 -       };
3240 +       }
3241         printk(KERN_INFO "megasas: FW now in Ready state\n");
3242  
3243         return 0;
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);
3247  
3248 +       if (instance->flag_ieee) {
3249 +               sge_sz = sizeof(struct megasas_sge_skinny);
3250 +       }
3251 +
3252         /*
3253          * Calculated the number of 64byte frames required for SGL
3254          */
3255         sgl_sz = sge_sz * instance->max_num_sge;
3256         frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
3257 +       frame_count = 15;
3258  
3259         /*
3260          * We need one extra frame for the MFI command
3261 @@ -1655,7 +3907,15 @@ static int megasas_create_frame_pool(str
3262                         return -ENOMEM;
3263                 }
3264  
3265 +               memset(cmd->frame, 0, total_sz);
3266 +
3267                 cmd->frame->io.context = cmd->index;
3268 +
3269 +               /*
3270 +                * Initialize pad_0 to 0, otherwise it could corrupt
3271 +                * the value of context and cause FW crash
3272 +                */
3273 +               cmd->frame->io.pad_0 = 0;
3274         }
3275  
3276         return 0;
3277 @@ -1714,8 +3974,7 @@ static int megasas_alloc_cmds(struct meg
3278          * Allocate the dynamic array first and then allocate individual
3279          * commands.
3280          */
3281 -       instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd,
3282 -                                    GFP_KERNEL);
3283 +       instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL);
3284  
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));
3290                 cmd->index = i;
3291 +               cmd->scmd = NULL;
3292                 cmd->instance = instance;
3293  
3294                 list_add_tail(&cmd->list, &instance->cmd_pool);
3295 @@ -1763,6 +4023,181 @@ static int megasas_alloc_cmds(struct meg
3296         return 0;
3297  }
3298  
3299 +/*
3300 + * megasas_get_pd_list_info -  Returns FW's pd_list structure
3301 + * @instance:                          Adapter soft state
3302 + * @pd_list:                           pd_list structure
3303 + *
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.
3307 + */
3308 +static int
3309 +megasas_get_pd_list(struct megasas_instance *instance)
3310 +{
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;
3317 +
3318 +       cmd = megasas_get_cmd(instance);
3319 +
3320 +       if (!cmd) {
3321 +               printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
3322 +               return -ENOMEM;
3323 +       }
3324 +
3325 +       dcmd = &cmd->frame->dcmd;
3326 +
3327 +       ci = pci_alloc_consistent(instance->pdev,
3328 +                 MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
3329 +
3330 +       if (!ci) {
3331 +               printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
3332 +               megasas_return_cmd(instance, cmd);
3333 +               return -ENOMEM;
3334 +       }
3335 +
3336 +       memset(ci, 0, sizeof(*ci));
3337 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3338 +
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;
3346 +       dcmd->pad_0 = 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);
3351 +
3352 +       if (!megasas_issue_polled(instance, cmd)) {
3353 +               ret = 0;
3354 +       } else {
3355 +               ret = -1;
3356 +       }
3357 +
3358 +       /*
3359 +       * the following function will get the instance PD LIST.
3360 +       */
3361 +
3362 +       pd_addr = ci->addr;
3363 +
3364 +       if ( ret == 0 &&
3365 +               (ci->count <
3366 +                 (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
3367 +
3368 +               memset(instance->pd_list, 0,
3369 +                       MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
3370 +
3371 +               for (pd_index = 0; pd_index < ci->count; pd_index++) {
3372 +
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;
3379 +                       pd_addr++;
3380 +               }
3381 +       }
3382 +
3383 +       pci_free_consistent(instance->pdev,
3384 +                               MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
3385 +                               ci, ci_h);
3386 +               
3387 +
3388 +       megasas_return_cmd(instance, cmd);
3389 +       
3390 +       return ret;
3391 +}
3392 +/**
3393 + * megasas_get_ld_list_info -  Returns FW's ld_list structure
3394 + * @instance:                          Adapter soft state
3395 + * @ld_list:                           ld_list structure
3396 + *
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.
3400 + */
3401 +static int
3402 +megasas_get_ld_list(struct megasas_instance *instance)
3403 +{
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;
3409 +
3410 +       cmd = megasas_get_cmd(instance);
3411 +
3412 +       if (!cmd) {
3413 +               printk(KERN_DEBUG "megasas (megasas_get_ld_list): Failed to get cmd\n");
3414 +               return -ENOMEM;
3415 +       }
3416 +
3417 +       dcmd = &cmd->frame->dcmd;
3418 +
3419 +       ci = pci_alloc_consistent(instance->pdev, sizeof(struct MR_LD_LIST), &ci_h);
3420 +
3421 +       if (!ci) {
3422 +               printk(KERN_DEBUG "Failed to alloc mem for megasas_get_ld_list\n");
3423 +               megasas_return_cmd(instance, cmd);
3424 +               return -ENOMEM;
3425 +       }
3426 +
3427 +       memset(ci, 0, sizeof(*ci));
3428 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3429 +
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);
3439 +       dcmd->pad_0  = 0;
3440 +
3441 +       if (!megasas_issue_polled(instance, cmd)) {
3442 +               ret = 0;
3443 +
3444 +       } else {
3445 +               ret = -1;
3446 +       }
3447 +
3448 +       /*
3449 +       * the following function will get the instance PD LIST.
3450 +       */
3451 +
3452 +       if ( (ret == 0) && (ci->ldCount <= (MAX_LOGICAL_DRIVES))){
3453 +               
3454 +               memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3455 +
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;
3460 +                       }
3461 +                                                               
3462 +               }
3463 +
3464 +       }
3465 +
3466 +       pci_free_consistent(instance->pdev, sizeof(struct MR_LD_LIST), ci, ci_h); 
3467 +               
3468 +
3469 +       megasas_return_cmd(instance, cmd);
3470 +
3471 +       return ret;
3472 +}
3473 +
3474  /**
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;
3480         dcmd->timeout = 0;
3481 +       dcmd->pad_0 = 0;
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
3486         return ret;
3487  }
3488  
3489 +
3490  /**
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
3496   *
3497 - * Tasklet to complete cmds
3498 + * @return 0 on success non-zero on failure.
3499   */
3500 -static void megasas_complete_cmd_dpc(unsigned long instance_addr)
3501 +static int megasas_check_cpx_support( struct megasas_instance *instance)
3502 +{
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;
3507 +       int retval = 0;
3508 +               
3509 +       cmd = megasas_get_cmd(instance);
3510 +       if (!cmd) {
3511 +               printk(KERN_DEBUG "megasas (get_host_mem_addr): Failed to get cmd\n");
3512 +               return -ENOMEM;
3513 +       }
3514 +
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);
3519 +               return -ENOMEM;
3520 +       }
3521 +
3522 +       dcmd = &cmd->frame->dcmd;
3523 +       dcmd->flags = 0;
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);
3531 +
3532 +       retval = megasas_issue_polled ( instance, cmd );
3533 +       
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");
3540 +                       retval = 1;
3541 +               }
3542 +       } else {
3543 +               printk("megasas: cpx is not supported.\n");
3544 +               retval = 1;
3545 +       }
3546 +       
3547 +       
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);
3550 +       
3551 +       return retval;
3552 +}
3553 +
3554 +/**
3555 + * megasas_send_cpx_queue_data : Sends the queue setup info to fw.
3556 + * @instance:          Adapter soft state
3557 + *
3558 + * @return 0 on success non-zero on failure.
3559 + */
3560 +
3561 +static int megasas_send_cpx_queue_data( struct megasas_instance *instance )
3562 +{
3563 +
3564 +       struct megasas_cmd *cmd;
3565 +       struct megasas_dcmd_frame *dcmd;
3566 +       int retval = 0;
3567 +       
3568 +       cmd = megasas_get_cmd(instance);
3569 +       if (!cmd) {
3570 +               printk(KERN_DEBUG "megasas (get_host_mem_addr): Failed to get cmd\n");
3571 +               return -ENOMEM;
3572 +       }
3573 +
3574 +       //initialize dcmd data
3575 +       dcmd = &cmd->frame->dcmd;
3576 +       dcmd->flags = 0;
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;
3585 +
3586 +       retval = megasas_issue_polled ( instance, cmd );
3587 +       
3588 +       megasas_return_cmd( instance, cmd);
3589 +       
3590 +       if ( retval == 0 ){
3591 +               instance->cpx_request_queue->consumer_idx = instance->cpx_request_queue->producer_idx = 0;
3592 +               instance->cpx_supported = 1;
3593 +       }
3594 +       
3595 +       return retval;
3596 +}
3597 +
3598 +static u32 megasas_get_cpx_mem_len( u16 max_fw_cmds )
3599 +{
3600 +       return (sizeof( struct mr_cpx_request_queue ) + sizeof( union mr_cpx_descriptor ) * ( max_fw_cmds) );
3601 +}
3602 +
3603 +static u32 megasas_remove_cpx( struct megasas_instance *instance)
3604 +{
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;
3611 +       
3612 +       return 0;
3613 +}
3614 +
3615 +/* should have host_mem_phys intialized before calling this function.*/        
3616 +static int megasas_init_cpx( struct megasas_instance *instance)
3617 +{
3618 +
3619 +       //map address
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;
3624 +       }
3625 +               
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;
3631 +       }
3632 +               
3633 +       //initialize queues
3634 +       instance->cpx_dscrptr = (union mr_cpx_descriptor *)((u8*)instance->cpx_request_queue + (  sizeof(instance->cpx_request_queue->consumer_idx)*2  ));
3635 +
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;
3640 +       }
3641 +                       
3642 +       return 0;
3643 +
3644 +error_unload:
3645 +       megasas_remove_cpx( instance );
3646 +       return -1;
3647 +}
3648 +
3649 +/**
3650 + * megasas_issue_init_mfi -    Initializes the FW
3651 + * @instance:          Adapter soft state
3652 + *
3653 + * Issues the INIT MFI cmd
3654 + */
3655 +static int
3656 +megasas_issue_init_mfi(struct megasas_instance *instance)
3657  {
3658 -       u32 producer;
3659 -       u32 consumer;
3660         u32 context;
3661 +
3662         struct megasas_cmd *cmd;
3663 -       struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
3664 -       unsigned long flags;
3665  
3666 -       /* If we have already declared adapter dead, donot complete cmds */
3667 -       if (instance->hw_crit_error)
3668 -               return;
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;
3673  
3674 -       producer = *instance->producer;
3675 -       consumer = *instance->consumer;
3676 +       /*
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
3681 +        *
3682 +        * We will not get a NULL command below. We just created the pool.
3683 +        */
3684 +       cmd = megasas_get_cmd(instance);
3685  
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);
3691  
3692 -               cmd = instance->cmd_list[context];
3693 +       init_frame_h = cmd->frame_phys_addr;
3694 +       initq_info_h = init_frame_h + 64;
3695 +
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;
3700 +
3701 +       initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
3702 +       initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
3703 +
3704 +       initq_info->producer_index_phys_addr_lo = instance->producer_h;
3705 +       initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
3706 +
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;
3710 +
3711 +       init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
3712 +
3713 +       /*
3714 +        * disable the intr before firing the init frame to FW
3715 +        */
3716 +       instance->instancet->disable_intr(instance->reg_set);
3717 +
3718 +       /*
3719 +        * Issue the init frame in polled mode
3720 +        */
3721 +
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;
3726 +       }
3727  
3728 -               megasas_complete_cmd(instance, cmd, DID_OK);
3729 +       megasas_return_cmd(instance, cmd);
3730  
3731 -               consumer++;
3732 -               if (consumer == (instance->max_fw_cmds + 1)) {
3733 -                       consumer = 0;
3734 -               }
3735 -       }
3736 +       return 0;
3737  
3738 -       *instance->consumer = producer;
3739 +fail_fw_init:
3740 +       return -EINVAL;
3741 +}
3742  
3743 -       /*
3744 -        * Check if we can restore can_queue
3745 -        */
3746 -       if (instance->flag & MEGASAS_FW_BUSY
3747 -               && time_after(jiffies, instance->last_time + 5 * HZ)
3748 -               && atomic_read(&instance->fw_outstanding) < 17) {
3749 +/**
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
3755 + */
3756 +static inline void
3757 +megasas_start_timer(struct megasas_instance *instance,
3758 +                       struct timer_list *timer,
3759 +                       void *fn, unsigned long interval)
3760 +{
3761 +       init_timer(timer);
3762 +       timer->expires = jiffies + interval;
3763 +       timer->data = (unsigned long)instance;
3764 +       timer->function = fn;
3765 +       add_timer(timer);
3766 +}
3767  
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;
3772 +/**
3773 + * megasas_io_completion_timer - Timer fn
3774 + * @instance_addr:     Address of adapter soft state
3775 + *
3776 + * Schedules tasklet for cmd completion
3777 + * if poll_mode_io is set
3778 + */
3779 +static void
3780 +megasas_io_completion_timer(unsigned long instance_addr)
3781 +{
3782 +       struct megasas_instance *instance =
3783 +                       (struct megasas_instance *)instance_addr;
3784  
3785 -               spin_unlock_irqrestore(instance->host->host_lock, flags);
3786 -       }
3787 +       if (atomic_read(&instance->fw_outstanding))
3788 +               tasklet_schedule(&instance->isr_tasklet);
3789  
3790 +       /* Restart timer */
3791 +       if (poll_mode_io)
3792 +               mod_timer(&instance->io_completion_timer,
3793 +                       jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
3794  }
3795  
3796  /**
3797 @@ -1893,22 +4547,24 @@ static int megasas_init_mfi(struct megas
3798         u32 reply_q_sz;
3799         u32 max_sectors_1;
3800         u32 max_sectors_2;
3801 +       u32 tmp_sectors;
3802         struct megasas_register_set __iomem *reg_set;
3803 -
3804 -       struct megasas_cmd *cmd;
3805         struct megasas_ctrl_info *ctrl_info;
3806 -
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;
3811 -
3812         /*
3813          * Map the message registers
3814          */
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);
3821 +       } else {
3822 +               instance->base_addr = pci_resource_start(instance->pdev, 0);
3823 +       }
3824  
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");
3830                 return -EBUSY;
3831         }
3832 @@ -1924,9 +4580,18 @@ static int megasas_init_mfi(struct megas
3833  
3834         switch(instance->pdev->device)
3835         {
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;
3840                         break;
3841 +               case PCI_DEVICE_ID_LSI_SAS1078GEN2:
3842 +               case PCI_DEVICE_ID_LSI_SAS0079GEN2:
3843 +                       instance->instancet = &megasas_instance_template_gen2;
3844 +                       break;
3845 +               case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
3846 +               case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
3847 +                       instance->instancet = &megasas_instance_template_skinny;
3848 +                       break;
3849                 case PCI_DEVICE_ID_LSI_SAS1064R:
3850                 case PCI_DEVICE_ID_DELL_PERC5:
3851                 default:
3852 @@ -1979,52 +4644,29 @@ static int megasas_init_mfi(struct megas
3853                 goto fail_reply_queue;
3854         }
3855  
3856 -       /*
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
3861 -        *
3862 -        * We will not get a NULL command below. We just created the pool.
3863 -        */
3864 -       cmd = megasas_get_cmd(instance);
3865 -
3866 -       init_frame = (struct megasas_init_frame *)cmd->frame;
3867 -       initq_info = (struct megasas_init_queue_info *)
3868 -           ((unsigned long)init_frame + 64);
3869 -
3870 -       init_frame_h = cmd->frame_phys_addr;
3871 -       initq_info_h = init_frame_h + 64;
3872 -
3873 -       memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
3874 -       memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
3875 -
3876 -       initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
3877 -       initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
3878 -
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");
3884  
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;
3890  
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); 
3894  
3895 -       /*
3896 -        * disable the intr before firing the init frame to FW
3897 -        */
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;
3902 +       
3903 +       /** for passthrough
3904 +       * the following function will get the PD LIST.
3905 +       */
3906  
3907 -       /*
3908 -        * Issue the init frame in polled mode
3909 -        */
3910 -       if (megasas_issue_polled(instance, cmd)) {
3911 -               printk(KERN_DEBUG "megasas: Failed to init firmware\n");
3912 -               goto fail_fw_init;
3913 -       }
3914 +       memset(instance->pd_list, 0, MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
3915 +       megasas_get_pd_list(instance);
3916  
3917 -       megasas_return_cmd(instance, cmd);
3918 +       memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3919 +       megasas_get_ld_list(instance);
3920  
3921         ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
3922  
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.
3926          */
3927 +       tmp_sectors = 0;
3928         if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
3929  
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;
3933  
3934 -               instance->max_sectors_per_req = (max_sectors_1 < max_sectors_2)
3935 -                   ? max_sectors_1 : max_sectors_2;
3936 -       } else
3937 -               instance->max_sectors_per_req = instance->max_num_sge *
3938 -                   PAGE_SIZE / 512;
3939 +               tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
3940 +                instance->disableOnlineCtrlReset = ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
3941 +       }
3942 +
3943 +       instance->max_sectors_per_req = instance->max_num_sge *
3944 +                                               PAGE_SIZE / 512;
3945 +       if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
3946 +               instance->max_sectors_per_req = tmp_sectors;
3947  
3948         kfree(ctrl_info);
3949  
3950 @@ -2055,12 +4701,17 @@ static int megasas_init_mfi(struct megas
3951         * Setup tasklet for cmd completion
3952         */
3953  
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);
3958 +
3959 +       /* Initialize the cmd completion timer */
3960 +       if (poll_mode_io)
3961 +               megasas_start_timer(instance, &instance->io_completion_timer,
3962 +                               megasas_io_completion_timer,
3963 +                               MEGASAS_COMPLETION_TIMER_INTERVAL);
3964         return 0;
3965  
3966        fail_fw_init:
3967 -       megasas_return_cmd(instance, cmd);
3968  
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);
3973  
3974        fail_ioremap:
3975 -       pci_release_regions(instance->pdev);
3976 +       pci_release_selected_regions(instance->pdev,
3977 +                                    pci_select_bars(instance->pdev, IORESOURCE_MEM));
3978  
3979         return -EINVAL;
3980  }
3981 @@ -2092,7 +4744,10 @@ static void megasas_release_mfi(struct m
3982  
3983         iounmap(instance->reg_set);
3984  
3985 -       pci_release_regions(instance->pdev);
3986 +       megasas_remove_cpx( instance );
3987 +
3988 +       pci_release_selected_regions(instance->pdev,
3989 +                                    pci_select_bars(instance->pdev, IORESOURCE_MEM));
3990  }
3991  
3992  /**
3993 @@ -2140,6 +4795,7 @@ megasas_get_seq_num(struct megasas_insta
3994         dcmd->sge_count = 1;
3995         dcmd->flags = MFI_FRAME_DIR_READ;
3996         dcmd->timeout = 0;
3997 +       dcmd->pad_0 = 0;
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.
4004                          */
4005 +                       printk(KERN_INFO "%s[%d]: already registered\n",
4006 +                               __FUNCTION__, instance->host->host_no);
4007                         return 0;
4008                 } else {
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;
4013         dcmd->timeout = 0;
4014 +       dcmd->pad_0 = 0;
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);
4022  
4023 +       if (instance->aen_cmd != NULL) {
4024 +               megasas_return_cmd(instance, cmd);
4025 +               return 0;
4026 +       }
4027 +
4028         /*
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
4032         /*
4033          * Issue the aen registration frame
4034          */
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);
4038  
4039         return 0;
4040  }
4041 @@ -2304,6 +4970,30 @@ static int megasas_start_aen(struct mega
4042                                     class_locale.word);
4043  }
4044  
4045 +static ssize_t
4046 +sysfs_max_sectors_read(struct kobject *kobj, struct bin_attribute *bin_attr,
4047 +                       char *buf, loff_t off, size_t count)
4048 +{
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;
4053 +
4054 +       count = sprintf(buf,"%u\n", instance->max_sectors_per_req);
4055 +
4056 +       return count+1;
4057 +}
4058 +
4059 +static struct bin_attribute sysfs_max_sectors_attr = {
4060 +       .attr = {
4061 +               .name = "max_sectors",
4062 +               .mode = S_IRUSR|S_IRGRP|S_IROTH,
4063 +               .owner = THIS_MODULE,
4064 +       },
4065 +       .size = 7,
4066 +       .read = sysfs_max_sectors_read,
4067 +};
4068 +
4069  /**
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)
4074  {
4075         struct Scsi_Host *host = instance->host;
4076 +       u32             error;
4077  
4078         /*
4079          * Export parameters required by SCSI mid-layer
4080          */
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)) {
4086 +               host->can_queue =
4087 +                       instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
4088 +       } else
4089 +               host->can_queue =
4090 +                       instance->max_fw_cmds - MEGASAS_INT_CMDS;
4091         host->this_id = instance->init_id;
4092         host->sg_tablesize = instance->max_num_sge;
4093 +       
4094 +       if (instance->fw_support_ieee)
4095 +               instance->max_sectors_per_req = MEGASAS_MAX_SECTORS_IEEE;
4096 +       /*
4097 +        * Check if the module parameter value for max_sectors can be used
4098 +        */
4099 +       if (max_sectors && max_sectors < instance->max_sectors_per_req)
4100 +               instance->max_sectors_per_req = max_sectors;
4101 +       else {
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;
4109 +                       } else {
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);
4113 +                       }
4114 +               }
4115 +       }
4116 +
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
4124                 return -ENODEV;
4125         }
4126  
4127 +        /*
4128 +        * Create sysfs entries for module paramaters
4129 +        */
4130 +       error = sysfs_create_bin_file(&instance->host->shost_classdev.kobj,
4131 +                       &sysfs_max_sectors_attr);
4132 +       if (error) {
4133 +               printk(KERN_INFO "megasas: Error in creating the sysfs entry max_sectors.\n");
4134 +               goto out_remove_host;
4135 +       }
4136 +
4137         /*
4138          * Trigger SCSI to scan our drives
4139          */
4140         scsi_scan_host(host);
4141         return 0;
4142 +
4143 +out_remove_host:
4144 +        scsi_remove_host(host);
4145 +        return error;
4146 +
4147 +}
4148 +
4149 +static int
4150 +megasas_set_dma_mask(struct pci_dev *pdev)
4151 +{
4152 +       /*
4153 +        * All our contollers are capable of performing 64-bit DMA
4154 +        */
4155 +       if (IS_DMA64) {
4156 +               if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
4157 +
4158 +                       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4159 +                               goto fail_set_dma_mask;
4160 +               }
4161 +       } else {
4162 +               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4163 +                       goto fail_set_dma_mask;
4164 +       }
4165 +       return 0;
4166 +
4167 +fail_set_dma_mask:
4168 +       return 1;
4169  }
4170  
4171  /**
4172 @@ -2375,19 +5133,8 @@ megasas_probe_one(struct pci_dev *pdev, 
4173  
4174         pci_set_master(pdev);
4175  
4176 -       /*
4177 -        * All our contollers are capable of performing 64-bit DMA
4178 -        */
4179 -       if (IS_DMA64) {
4180 -               if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
4181 -
4182 -                       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4183 -                               goto fail_set_dma_mask;
4184 -               }
4185 -       } else {
4186 -               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4187 -                       goto fail_set_dma_mask;
4188 -       }
4189 +       if (megasas_set_dma_mask(pdev))
4190 +               goto fail_set_dma_mask;
4191  
4192         host = scsi_host_alloc(&megasas_template,
4193                                sizeof(struct megasas_instance));
4194 @@ -2399,6 +5146,7 @@ megasas_probe_one(struct pci_dev *pdev, 
4195  
4196         instance = (struct megasas_instance *)host->hostdata;
4197         memset(instance, 0, sizeof(*instance));
4198 +       atomic_set( &instance->fw_reset_no_pci_access, 0 );
4199  
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, 
4203  
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;      
4211  
4212         instance->evt_detail = pci_alloc_consistent(pdev,
4213                                                     sizeof(struct
4214 @@ -2429,6 +5182,7 @@ megasas_probe_one(struct pci_dev *pdev, 
4215          * Initialize locks and queues
4216          */
4217         INIT_LIST_HEAD(&instance->cmd_pool);
4218 +       INIT_LIST_HEAD(&instance->internal_reset_pending_q);
4219  
4220         atomic_set(&instance->fw_outstanding,0);
4221  
4222 @@ -2436,9 +5190,12 @@ megasas_probe_one(struct pci_dev *pdev, 
4223         init_waitqueue_head(&instance->abort_cmd_wait_q);
4224  
4225         spin_lock_init(&instance->cmd_pool_lock);
4226 +       spin_lock_init(&instance->hba_lock);
4227 +
4228 +       spin_lock_init(&instance->completion_lock);
4229 +       spin_lock_init(&poll_aen_lock);
4230  
4231 -       sema_init(&instance->aen_mutex, 1);
4232 -       sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
4233 +       mutex_init(&instance->aen_mutex);
4234  
4235         /*
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;
4240  
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);
4245 +       } else
4246 +               sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
4247 +
4248         megasas_dbg_lvl = 0;
4249         instance->flag = 0;
4250 +       instance->unload = 1;
4251         instance->last_time = 0;
4252 +       instance->disableOnlineCtrlReset = 1;
4253 +
4254 +       INIT_WORK(&instance->work_init, process_fw_state_change_wq);
4255  
4256         /*
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;
4261  
4262 +       instance->unload = 0;
4263         return 0;
4264  
4265        fail_start_aen:
4266 @@ -2541,83 +5310,266 @@ static void megasas_flush_cache(struct m
4267         struct megasas_cmd *cmd;
4268         struct megasas_dcmd_frame *dcmd;
4269  
4270 -       cmd = megasas_get_cmd(instance);
4271 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
4272 +               return;
4273 +
4274 +       cmd = megasas_get_cmd(instance);
4275 +
4276 +       if (!cmd)
4277 +               return;
4278 +
4279 +       dcmd = &cmd->frame->dcmd;
4280 +
4281 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4282 +
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;
4288 +       dcmd->pad_0 = 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;
4292 +
4293 +       megasas_issue_blocked_cmd(instance, cmd);
4294 +
4295 +       megasas_return_cmd(instance, cmd);
4296 +
4297 +       return;
4298 +}
4299 +
4300 +/**
4301 + * megasas_shutdown_controller -       Instructs FW to shutdown the controller
4302 + * @instance:                          Adapter soft state
4303 + * @opcode:                            Shutdown/Hibernate
4304 + */
4305 +static void megasas_shutdown_controller(struct megasas_instance *instance,
4306 +                                       u32 opcode)
4307 +{
4308 +       struct megasas_cmd *cmd;
4309 +       struct megasas_dcmd_frame *dcmd;
4310 +
4311 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
4312 +               return;
4313 +
4314 +       cmd = megasas_get_cmd(instance);
4315 +
4316 +       if (!cmd)
4317 +               return;
4318 +
4319 +       if (instance->aen_cmd)
4320 +               megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
4321 +
4322 +       dcmd = &cmd->frame->dcmd;
4323 +
4324 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4325 +
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;
4331 +       dcmd->pad_0 = 0;
4332 +       dcmd->data_xfer_len = 0;
4333 +       dcmd->opcode = opcode;
4334 +
4335 +       megasas_issue_blocked_cmd(instance, cmd);
4336 +
4337 +       megasas_return_cmd(instance, cmd);
4338 +
4339 +       return;
4340 +}
4341 +
4342 +#ifdef CONFIG_PM
4343 +/**
4344 + * megasas_suspend -   driver suspend entry point
4345 + * @pdev:              PCI device structure
4346 + * @state:             PCI power state to suspend routine
4347 + */
4348 +static int
4349 +megasas_suspend(struct pci_dev *pdev, pm_message_t state)
4350 +{
4351 +       struct Scsi_Host *host;
4352 +       struct megasas_instance *instance;
4353 +
4354 +       instance = pci_get_drvdata(pdev);
4355 +       host = instance->host;
4356 +       instance->unload = 1;
4357 +
4358 +       if (poll_mode_io)
4359 +               del_timer_sync(&instance->io_completion_timer);
4360 +
4361 +       megasas_flush_cache(instance);
4362 +       megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
4363 +
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;
4371 +       }
4372 +
4373 +       tasklet_kill(&instance->isr_tasklet);
4374 +
4375 +       pci_set_drvdata(instance->pdev, instance);
4376 +       instance->instancet->disable_intr(instance->reg_set);
4377 +       free_irq(instance->pdev->irq, instance);
4378 +
4379 +       pci_save_state(pdev);
4380 +       pci_disable_device(pdev);
4381 +
4382 +       pci_set_power_state(pdev, pci_choose_state(pdev, state));
4383 +
4384 +       return 0;
4385 +}
4386 +
4387 +/**
4388 + * megasas_resume-      driver resume entry point
4389 + * @pdev:               PCI device structure
4390 + */
4391 +static int
4392 +megasas_resume(struct pci_dev *pdev)
4393 +{
4394 +       int rval;
4395 +       struct Scsi_Host *host;
4396 +       struct megasas_instance *instance;
4397 +
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);
4403 +
4404 +       /*
4405 +        * PCI prepping: enable device set bus mastering and dma mask
4406 +        */
4407 +       rval = pci_enable_device(pdev);
4408 +
4409 +       if (rval) {
4410 +               printk(KERN_ERR "megasas: Enable device failed\n");
4411 +               return rval;
4412 +       }
4413 +
4414 +       pci_set_master(pdev);
4415 +
4416 +       if (megasas_set_dma_mask(pdev))
4417 +               goto fail_set_dma_mask;
4418  
4419 -       if (!cmd)
4420 -               return;
4421 +       /*
4422 +        * Initialize MFI Firmware
4423 +        */
4424  
4425 -       dcmd = &cmd->frame->dcmd;
4426 +       *instance->producer = 0;
4427 +       *instance->consumer = 0;
4428  
4429 -       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4430 +       atomic_set(&instance->fw_outstanding, 0);
4431  
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;
4440 +       /*
4441 +        * We expect the FW state to be READY
4442 +        */
4443 +       if (megasas_transition_to_ready(instance))
4444 +               goto fail_ready_state;
4445  
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);
4451 +               }else
4452 +                       instance->cpx_request_queue->consumer_idx = instance->cpx_request_queue->producer_idx = 0;
4453 +       }
4454  
4455 -       megasas_return_cmd(instance, cmd);
4456 +       if (megasas_issue_init_mfi(instance))
4457 +               goto fail_init_mfi;
4458  
4459 -       return;
4460 -}
4461 +       tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
4462 +                       (unsigned long)instance);
4463  
4464 -/**
4465 - * megasas_shutdown_controller -       Instructs FW to shutdown the controller
4466 - * @instance:                          Adapter soft state
4467 - */
4468 -static void megasas_shutdown_controller(struct megasas_instance *instance)
4469 -{
4470 -       struct megasas_cmd *cmd;
4471 -       struct megasas_dcmd_frame *dcmd;
4472 +       /*
4473 +        * Register IRQ
4474 +        */
4475 +       if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
4476 +               "megasas", instance)) {
4477 +               printk(KERN_ERR "megasas: Failed to register IRQ\n");
4478 +               goto fail_irq;
4479 +       }
4480  
4481 -       cmd = megasas_get_cmd(instance);
4482 +       instance->instancet->enable_intr(instance->reg_set);
4483  
4484 -       if (!cmd)
4485 -               return;
4486 +       /*
4487 +        * Initiate AEN (Asynchronous Event Notification)
4488 +        */
4489 +       if (megasas_start_aen(instance))
4490 +               printk(KERN_ERR "megasas: Start AEN failed\n");
4491  
4492 -       if (instance->aen_cmd)
4493 -               megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
4494 +       /* Initialize the cmd completion timer */
4495 +       if (poll_mode_io)
4496 +               megasas_start_timer(instance, &instance->io_completion_timer,
4497 +                               megasas_io_completion_timer,
4498 +                               MEGASAS_COMPLETION_TIMER_INTERVAL);
4499 +       instance->unload = 0;
4500  
4501 -       dcmd = &cmd->frame->dcmd;
4502 +       return 0;
4503  
4504 -       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4505 +fail_irq:
4506 +fail_init_mfi:
4507 +       if (instance->evt_detail)
4508 +               pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
4509 +                               instance->evt_detail,
4510 +                               instance->evt_detail_h);
4511  
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);
4526  
4527 -       megasas_issue_blocked_cmd(instance, cmd);
4528 +fail_set_dma_mask:
4529 +fail_ready_state:
4530  
4531 -       megasas_return_cmd(instance, cmd);
4532 +       pci_disable_device(pdev);
4533  
4534 -       return;
4535 +       return -ENODEV;
4536  }
4537 +#else
4538 +#define megasas_suspend        NULL
4539 +#define megasas_resume NULL
4540 +#endif
4541  
4542  /**
4543   * megasas_detach_one -        PCI hot"un"plug entry point
4544   * @pdev:              PCI device structure
4545   */
4546 -static void megasas_detach_one(struct pci_dev *pdev)
4547 +static void __devexit megasas_detach_one(struct pci_dev *pdev)
4548  {
4549         int i;
4550         struct Scsi_Host *host;
4551         struct megasas_instance *instance;
4552  
4553         instance = pci_get_drvdata(pdev);
4554 +       instance->unload = 1;
4555         host = instance->host;
4556  
4557 +       if (poll_mode_io)
4558 +               del_timer_sync(&instance->io_completion_timer);
4559 +
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);
4564 +
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;
4572 +       }
4573 +
4574         tasklet_kill(&instance->isr_tasklet);
4575  
4576         /*
4577 @@ -2666,7 +5618,9 @@ static void megasas_detach_one(struct pc
4578  static void megasas_shutdown(struct pci_dev *pdev)
4579  {
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);
4584  }
4585  
4586  /**
4587 @@ -2722,6 +5676,23 @@ static int megasas_mgmt_fasync(int fd, s
4588  }
4589  
4590  /**
4591 + * megasas_mgmt_poll -  char node "poll" entry point
4592 + * */
4593 +static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
4594 +{
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);
4601 +       else
4602 +               mask = 0;
4603 +       spin_unlock_irqrestore(&poll_aen_lock, flags);
4604 +       return mask;
4605 +}
4606 +
4607 +/**
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
4612         int error = 0, i;
4613         void *sense = NULL;
4614         dma_addr_t sense_handle;
4615 -       u32 *sense_ptr;
4616 +       unsigned long *sense_ptr;
4617  
4618         memset(kbuff_arr, 0, sizeof(kbuff_arr));
4619  
4620 @@ -2762,6 +5733,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4621          */
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;
4625  
4626         /*
4627          * The management interface between applications and the fw uses
4628 @@ -2815,7 +5787,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4629                 }
4630  
4631                 sense_ptr =
4632 -                   (u32 *) ((unsigned long)cmd->frame + ioc->sense_off);
4633 +               (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
4634                 *sense_ptr = sense_handle;
4635         }
4636  
4637 @@ -2843,14 +5815,16 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4638          */
4639         if (ioc->sense_len) {
4640                 /*
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
4644                  */
4645 -               sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
4646 -                                    ioc->sense_off);
4647 +               sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
4648 +                               ioc->sense_off);
4649  
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 "
4653 +                                       "sense data\n");
4654                         error = -EFAULT;
4655                         goto out;
4656                 }
4657 @@ -2881,20 +5855,6 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4658         return error;
4659  }
4660  
4661 -static struct megasas_instance *megasas_lookup_instance(u16 host_no)
4662 -{
4663 -       int i;
4664 -
4665 -       for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4666 -
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];
4670 -       }
4671 -
4672 -       return NULL;
4673 -}
4674 -
4675  static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
4676  {
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;
4681         int error;
4682 +       int i;
4683 +       unsigned long flags;
4684 +       u32 wait_time = MEGASAS_RESET_WAIT_TIME;
4685  
4686         ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
4687         if (!ioc)
4688 @@ -2918,6 +5881,17 @@ static int megasas_mgmt_ioctl_fw(struct 
4689                 goto out_kfree_ioc;
4690         }
4691  
4692 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
4693 +               printk("Controller in crit error\n");
4694 +               error = -ENODEV;
4695 +               goto out_kfree_ioc;
4696 +       }
4697 +
4698 +       if (instance->unload == 1) {
4699 +               error = -ENODEV;
4700 +               goto out_kfree_ioc;
4701 +       }
4702 +
4703         /*
4704          * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
4705          */
4706 @@ -2925,6 +5899,35 @@ static int megasas_mgmt_ioctl_fw(struct 
4707                 error = -ERESTARTSYS;
4708                 goto out_kfree_ioc;
4709         }
4710 +       
4711 +       // If HBA is undergoing a reset recovery, wait for that to complete
4712 +       // before issuing this command
4713 +
4714 +       for (i = 0; i < wait_time; i++) {
4715 +
4716 +               spin_lock_irqsave(&instance->hba_lock, flags);
4717 +               if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
4718 +                       spin_unlock_irqrestore(&instance->hba_lock, flags);
4719 +                       break;
4720 +               }
4721 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
4722 +
4723 +               if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
4724 +                       printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
4725 +               }
4726 +
4727 +               msleep(1000);
4728 +       }
4729 +
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__);
4734 +               error = -ENODEV;
4735 +               goto out_kfree_ioc;
4736 +       }
4737 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
4738 +
4739         error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
4740         up(&instance->ioctl_sem);
4741  
4742 @@ -2938,6 +5941,9 @@ static int megasas_mgmt_ioctl_aen(struct
4743         struct megasas_instance *instance;
4744         struct megasas_aen aen;
4745         int error;
4746 +       int i;
4747 +       unsigned long flags;
4748 +       u32 wait_time = MEGASAS_RESET_WAIT_TIME;
4749  
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
4753         if (!instance)
4754                 return -ENODEV;
4755  
4756 -       down(&instance->aen_mutex);
4757 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
4758 +               return -ENODEV;
4759 +       }
4760 +
4761 +       if (instance->unload == 1) {
4762 +               return -ENODEV;
4763 +       }
4764 +       for (i = 0; i < wait_time; i++) {
4765 +
4766 +               spin_lock_irqsave(&instance->hba_lock, flags);
4767 +               if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
4768 +                       spin_unlock_irqrestore(&instance->hba_lock, flags);
4769 +                       break;
4770 +               }
4771 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
4772 +
4773 +               if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
4774 +                       printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
4775 +               }
4776 +
4777 +               msleep(1000);
4778 +       }
4779 +
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__);
4784 +               return -ENODEV;
4785 +       }
4786 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
4787 +
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);
4793         return error;
4794  }
4795  
4796 @@ -2986,6 +6023,8 @@ static int megasas_mgmt_compat_ioctl_fw(
4797             compat_alloc_user_space(sizeof(struct megasas_iocpacket));
4798         int i;
4799         int error = 0;
4800 +       compat_uptr_t ptr;
4801 +       u8 *raw_ptr;
4802  
4803         if (clear_user(ioc, sizeof(*ioc)))
4804                 return -EFAULT;
4805 @@ -2998,9 +6037,14 @@ static int megasas_mgmt_compat_ioctl_fw(
4806             copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
4807                 return -EFAULT;
4808  
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))
4815 +                       return -EFAULT;
4816 +       }
4817  
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,
4829  #endif
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,
4837  };
4838  
4839 @@ -3081,9 +6128,27 @@ static DRIVER_ATTR(release_date, S_IRUGO
4840                    NULL);
4841  
4842  static ssize_t
4843 +megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
4844 +{
4845 +       return sprintf(buf, "%u\n", support_poll_for_event);
4846 +}
4847 +
4848 +static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
4849 +                       megasas_sysfs_show_support_poll_for_event, NULL);
4850 +
4851 +static ssize_t
4852 +megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf)
4853 +{
4854 +       return sprintf(buf, "%u\n", support_device_change);
4855 +}
4856 +
4857 +static DRIVER_ATTR(support_device_change, S_IRUGO,
4858 +                       megasas_sysfs_show_support_device_change, NULL);
4859 +
4860 +static ssize_t
4861  megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
4862  {
4863 -       return sprintf(buf,"%u",megasas_dbg_lvl);
4864 +       return sprintf(buf, "%u\n", megasas_dbg_lvl);
4865  }
4866  
4867  static ssize_t
4868 @@ -3097,8 +6162,262 @@ megasas_sysfs_set_dbg_lvl(struct device_
4869         return retval;
4870  }
4871  
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);
4876 +
4877 +static ssize_t
4878 +megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
4879 +{
4880 +       return sprintf(buf, "%u\n", poll_mode_io);
4881 +}
4882 +
4883 +static ssize_t
4884 +megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
4885 +                               const char *buf, size_t count)
4886 +{
4887 +       int retval = count;
4888 +       int tmp = poll_mode_io;
4889 +       int i;
4890 +       struct megasas_instance *instance;
4891 +
4892 +       if (sscanf(buf, "%u", &poll_mode_io) < 1) {
4893 +               printk(KERN_ERR "megasas: could not set poll_mode_io\n");
4894 +               retval = -EINVAL;
4895 +       }
4896 +
4897 +       /*
4898 +        * Check if poll_mode_io is already set or is same as previous value
4899 +        */
4900 +       if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
4901 +               goto out;
4902 +
4903 +       if (poll_mode_io) {
4904 +               /*
4905 +                * Start timers for all adapters
4906 +                */
4907 +               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4908 +                       instance = megasas_mgmt_info.instance[i];
4909 +                       if (instance) {
4910 +                               megasas_start_timer(instance,
4911 +                                       &instance->io_completion_timer,
4912 +                                       megasas_io_completion_timer,
4913 +                                       MEGASAS_COMPLETION_TIMER_INTERVAL);
4914 +                       }
4915 +               }
4916 +       } else {
4917 +               /*
4918 +                * Delete timers for all adapters
4919 +                */
4920 +               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4921 +                       instance = megasas_mgmt_info.instance[i];
4922 +                       if (instance)
4923 +                               del_timer_sync(&instance->io_completion_timer);
4924 +               }
4925 +       }
4926 +
4927 +out:
4928 +       return retval;
4929 +}
4930 +
4931 +static void
4932 +megasas_aen_polling(struct work_struct *work)
4933 +{
4934 +       struct  Scsi_Host *host;
4935 +       struct  scsi_device *sdev1;
4936 +       u16     pd_index = 0;
4937 +       u16     ld_index = 0;
4938 +
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;
4944 +       u32 seq_num;
4945 +       int error;
4946 +
4947 +       if (!instance) {
4948 +               printk(KERN_ERR "invalid instance!\n");
4949 +               kfree(ev);
4950 +               return;
4951 +       }
4952 +       instance->ev = NULL;
4953 +       host = instance->host;
4954 +       if (instance->evt_detail) {
4955 +
4956 +               switch (instance->evt_detail->code) {
4957 +               case MR_EVT_PD_INSERTED:
4958 +                       if(megasas_get_pd_list(instance) == 0) {
4959 +                       
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) {
4965 +                                               if (!sdev1) {
4966 +                                                       scsi_add_device(host, i, j, 0);
4967 +                                               }
4968 +                                       } 
4969 +                                       if (sdev1) {
4970 +                                               scsi_device_put(sdev1);
4971 +                                       }
4972 +                                       
4973 +                               }
4974 +                       }
4975 +                       }
4976 +                       doscan = 0;
4977 +                       break;
4978 +               
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) {
4987 +                                               if (sdev1) {
4988 +                                                       scsi_device_put(sdev1);
4989 +                                               }
4990 +                                       } else {
4991 +                                               if (sdev1) {
4992 +                                                       scsi_remove_device(sdev1);
4993 +                                                       scsi_device_put(sdev1);
4994 +                                               }
4995 +                                       }
4996 +                               }
4997 +                       
4998 +                       }
4999 +                       }
5000 +                       doscan = 0;
5001 +                       break;
5002 +
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) {
5012 +                                               if (sdev1) {
5013 +                                                       scsi_device_put(sdev1);
5014 +                                               }
5015 +                                               
5016 +                                       } else {
5017 +                                               if (sdev1) {
5018 +                                                       scsi_remove_device(sdev1);
5019 +                                                       scsi_device_put(sdev1);
5020 +                                               }
5021 +                                       }
5022 +                               }
5023 +                       }
5024 +                       doscan = 0;
5025 +                       break;          
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) {
5033 +                                               if (!sdev1) {
5034 +                                                       scsi_add_device(host, i+2, j, 0);
5035 +                                               }
5036 +                                       } 
5037 +                                       if (sdev1) {
5038 +                                               scsi_device_put(sdev1);
5039 +                                       }
5040 +                               }
5041 +                       }               
5042 +                       doscan = 0;
5043 +                       break;
5044 +               case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
5045 +               case MR_EVT_FOREIGN_CFG_IMPORTED: 
5046 +               case MR_EVT_LD_STATE_CHANGE:
5047 +                       doscan = 1;
5048 +                       break;
5049 +               default:
5050 +                       doscan = 0;
5051 +                       break;
5052 +               }
5053 +       } else {
5054 +               printk(KERN_ERR "invalid evt_detail!\n");
5055 +               kfree(ev);
5056 +               return;
5057 +       }
5058 +
5059 +       if (doscan) {
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) {
5068 +                                       if (!sdev1) {
5069 +                                               scsi_add_device(host, i, j, 0);
5070 +                                       } else {
5071 +                                               scsi_device_put(sdev1);
5072 +                                       }
5073 +                               } else {
5074 +                                       if (sdev1) {
5075 +                                               scsi_remove_device(sdev1);
5076 +                                               scsi_device_put(sdev1);
5077 +                                       }
5078 +                               }
5079 +                       }
5080 +               }
5081 +
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) {
5088 +                                       if (!sdev1) {
5089 +                                               scsi_add_device(host, i+2, j, 0);
5090 +                                       } else {
5091 +                                               scsi_device_put(sdev1);
5092 +                                       }
5093 +                               } else {
5094 +                                       if (sdev1) {
5095 +                                               scsi_remove_device(sdev1);
5096 +                                               scsi_device_put(sdev1);
5097 +                                       }
5098 +                               }
5099 +                       }
5100 +               }               
5101 +       }
5102 +
5103 +       seq_num = instance->evt_detail->seq_num + 1;
5104 +
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;
5109 +       
5110 +       if ( instance->aen_cmd != NULL ) {
5111 +               kfree(ev);
5112 +               return ; 
5113 +       }
5114 +
5115 +       mutex_lock(&instance->aen_mutex);
5116 +       error = megasas_register_aen(instance, seq_num,
5117 +                                       class_locale.word);
5118 +       mutex_unlock(&instance->aen_mutex);
5119 +
5120 +       if (error)
5121 +               printk(KERN_ERR "register aen failed error %x\n", error);
5122 +
5123 +       kfree(ev);
5124 +}
5125 +
5126 +
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);
5130  
5131  /**
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);
5136  
5137 +       support_poll_for_event = 2;
5138 +       support_device_change = 1;
5139 +
5140         memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
5141  
5142         /*
5143 @@ -3145,15 +6467,41 @@ static int __init megasas_init(void)
5144                                   &driver_attr_release_date);
5145         if (rval)
5146                 goto err_dcf_rel_date;
5147 +
5148 +       rval = driver_create_file(&megasas_pci_driver.driver,
5149 +                               &driver_attr_support_poll_for_event);
5150 +       if (rval)
5151 +               goto err_dcf_support_poll_for_event;
5152 +
5153         rval = driver_create_file(&megasas_pci_driver.driver,
5154                                   &driver_attr_dbg_lvl);
5155         if (rval)
5156                 goto err_dcf_dbg_lvl;
5157 +       rval = driver_create_file(&megasas_pci_driver.driver,
5158 +                                 &driver_attr_poll_mode_io);
5159 +       if (rval)
5160 +               goto err_dcf_poll_mode_io;
5161 +       rval = driver_create_file(&megasas_pci_driver.driver,
5162 +                               &driver_attr_support_device_change);
5163 +       if (rval)
5164 +               goto err_dcf_support_device_change;
5165  
5166         return rval;
5167 +err_dcf_support_device_change:
5168 +       driver_remove_file(&megasas_pci_driver.driver,
5169 +                         &driver_attr_poll_mode_io);
5170 +
5171 +err_dcf_poll_mode_io:
5172 +       driver_remove_file(&megasas_pci_driver.driver,
5173 +                          &driver_attr_dbg_lvl);
5174  err_dcf_dbg_lvl:
5175         driver_remove_file(&megasas_pci_driver.driver,
5176 +                       &driver_attr_support_poll_for_event);
5177 +
5178 +err_dcf_support_poll_for_event:
5179 +       driver_remove_file(&megasas_pci_driver.driver,
5180                            &driver_attr_release_date);
5181 +
5182  err_dcf_rel_date:
5183         driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
5184  err_dcf_attr_ver:
5185 @@ -3169,8 +6517,14 @@ err_pcidrv:
5186  static void __exit megasas_exit(void)
5187  {
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);
5199  
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
5203 @@ -18,15 +18,21 @@
5204  /*
5205   * MegaRAID SAS Driver meta data
5206   */
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"
5213 +
5214  
5215  /*
5216   * Device IDs
5217   */
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
5225  
5226  /*
5227   * =====================================
5228 @@ -55,6 +61,7 @@
5229  #define MFI_STATE_READY                                0xB0000000
5230  #define MFI_STATE_OPERATIONAL                  0xC0000000
5231  #define MFI_STATE_FAULT                                0xF0000000
5232 +#define  MFI_RESET_REQUIRED                    0x00000001
5233  
5234  #define MEGAMFI_FRAME_SIZE                     64
5235  
5236 @@ -68,6 +75,13 @@
5237   * HOTPLUG     : Resume from Hotplug
5238   * MFI_STOP_ADP        : Send signal to FW to stop processing
5239   */
5240 +
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)
5245 +
5246 +#define MFI_ADP_RESET                          0x00000040
5247  #define MFI_INIT_ABORT                         0x00000001
5248  #define MFI_INIT_READY                         0x00000002
5249  #define MFI_INIT_MFIMODE                       0x00000004
5250 @@ -91,6 +105,7 @@
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
5255  
5256  /*
5257   * Definition for cmd_status
5258 @@ -111,12 +126,14 @@
5259  #define MFI_CMD_STP                            0x08
5260  
5261  #define MR_DCMD_CTRL_GET_INFO                  0x01010000
5262 +#define MR_DCMD_LD_GET_LIST                    0x03010000
5263  
5264  #define MR_DCMD_CTRL_CACHE_FLUSH               0x01101000
5265  #define MR_FLUSH_CTRL_CACHE                    0x01
5266  #define MR_FLUSH_DISK_CACHE                    0x02
5267  
5268  #define MR_DCMD_CTRL_SHUTDOWN                  0x01050000
5269 +#define MR_DCMD_HIBERNATE_SHUTDOWN             0x01060000
5270  #define MR_ENABLE_DRIVE_SPINDOWN               0x01
5271  
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
5278 +
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
5287 +
5288 +#define MR_EVT_CFG_CLEARED                     0x0004
5289 +
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
5299 +
5300  
5301  /*
5302   * MFI command completion codes
5303 @@ -247,8 +287,128 @@ enum MR_EVT_ARGS {
5304         MR_EVT_ARGS_STR,
5305         MR_EVT_ARGS_TIME,
5306         MR_EVT_ARGS_ECC,
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,
5323 +
5324 +};
5325  
5326 +/*
5327 + * define constants for device list query options
5328 + */
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));
5337 +
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
5347 +
5348 +enum MR_PD_STATE {                 
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,
5358  };
5359
5360 + /*
5361 + * defines the physical drive address structure
5362 + */
5363 +struct MR_PD_ADDRESS {
5364 +    u16     deviceId;
5365 +    u16     enclDeviceId;
5366 +                         
5367 +    union {
5368 +        struct {         
5369 +                         
5370 +            u8  enclIndex;
5371 +            u8  slotNumber;
5372 +        } mrPdAddress;
5373 +        struct {
5374 +            u8  enclPosition;
5375 +            u8  enclConnectorIndex;
5376 +        } mrEnclAddress;
5377 +    };
5378 +    u8      scsiDevType;
5379 +    union {
5380 +        u8      connectedPortBitmap;
5381 +        u8      connectedPortNumbers;
5382 +                    
5383 +    };
5384 +    u64     sasAddr[2];
5385 +} __attribute__ ((packed));
5386 +
5387 +/*
5388 + * defines the physical drive list structure
5389 + */
5390 +struct MR_PD_LIST {
5391 +    u32             size;
5392 +    u32             count;
5393 +    struct MR_PD_ADDRESS   addr[1];
5394 +} __attribute__ ((packed));
5395 +
5396 +
5397 +struct megasas_pd_list {
5398 +    u16             tid;
5399 +    u8             driveType;
5400 +    u8             driveState;
5401 +} __attribute__ ((packed));
5402 +
5403 + /*
5404 + * defines the logical drive reference structure
5405 + */
5406 +typedef union  _MR_LD_REF {        // LD reference structure
5407 +    struct {
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
5411 +    };
5412 +    u32     ref;                    // shorthand reference to full 32-bits
5413 +} MR_LD_REF;                        // 4 bytes
5414 +
5415 +
5416 +/*
5417 + * defines the logical drive list structure
5418 + */
5419 +struct MR_LD_LIST {
5420 +    u32     ldCount;                // number of LDs
5421 +    u32     reserved;               // pad to 8-byte boundary
5422 +    struct {
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));
5429  
5430  /*
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;
5436 -       u8 reserved[38];
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
5447 +
5448 +    /*
5449 +     * Add properties that can be controlled by a bit in the following structure.
5450 +     */
5451 +    struct {
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;
5466 +        u32     reserved                    :18;
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
5472 +        
5473 +    u16     spinDownTime;                   // # of idle minutes before device is spun down (0=use FW defaults)
5474 +
5475 +    u8      reserved[24];
5476  
5477  } __attribute__ ((packed));
5478  
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)
5488  
5489 -#define MEGASAS_DBG_LVL                                1
5490  
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
5495 +/* Frame Type */
5496 +#define IO_FRAME                               0
5497 +#define PTHRU_FRAME                            1
5498  
5499  /*
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
5505 +
5506  #define MEGASAS_IOCTL_CMD                      0
5507  #define MEGASAS_DEFAULT_CMD_TIMEOUT            90
5508  
5509 @@ -562,6 +771,7 @@ struct megasas_ctrl_info {
5510   * is shown below
5511   */
5512  #define MEGASAS_INT_CMDS                       32
5513 +#define MEGASAS_SKINNY_INT_CMDS                        5       
5514  
5515  /*
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 {
5518   */
5519  #define IS_DMA64                               (sizeof(dma_addr_t) == 8)
5520  
5521 +#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT            0x00000001  /* MFI state change interrupt */
5522 +
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 */
5526 +
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)
5531  
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
5540 +
5541  
5542  /*
5543  * register set for both 1068 and 1078 controllers
5544 @@ -580,7 +805,11 @@ struct megasas_ctrl_info {
5545  */
5546   
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*/
5553 +
5554  
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*/
5559  
5560         u32     reserved_5;                     /*00C8h*/
5561 -       u32     index_registers[820];           /*00CCh*/
5562 +       u32             res_6[11];                      /*CCh*/
5563 +       u32             host_diag;
5564 +       u32             seq_offset;
5565 +       u32     index_registers[807];           /*00CCh*/
5566  
5567  } __attribute__ ((packed));
5568  
5569 @@ -632,11 +864,20 @@ struct megasas_sge64 {
5570         u32 length;
5571  
5572  } __attribute__ ((packed));
5573
5574 +struct megasas_sge_skinny {
5575 +
5576 +       u64 phys_addr;
5577 +       u32 length;
5578 +       u32 flag;
5579 +
5580 +} __attribute__ ((packed));
5581  
5582  union megasas_sgl {
5583  
5584         struct megasas_sge32 sge32[1];
5585         struct megasas_sge64 sge64[1];
5586 +       struct megasas_sge_skinny sge_skinny[1];
5587  
5588  } __attribute__ ((packed));
5589  
5590 @@ -1050,16 +1291,177 @@ struct megasas_evt_detail {
5591  
5592  } __attribute__ ((packed));
5593  
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);
5599 +/*
5600 + * enumerates type of descriptor
5601 + */
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;
5606  
5607 -       void (*enable_intr)(struct megasas_register_set __iomem *) ;
5608 -       void (*disable_intr)(struct megasas_register_set __iomem *);
5609 +/*
5610 + * status information of copy or xor operation
5611 + */
5612 +typedef enum _MR_CPX_STATUS {
5613 +       MR_CPX_STATUS_SUCCESS      = 0,
5614 +       MR_CPX_STATUS_INCONSISTENT = 1,
5615 +       MR_CPX_STATUS_FAILURE      = 2,
5616 +} MR_CPX_STATUS;     
5617  
5618 -       int (*clear_intr)(struct megasas_register_set __iomem *);
5619 +/*
5620 + * define the XOR opcodes
5621 + */
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)
5629 +} MR_CPX_XOR_OP;
5630 +
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
5636  
5637 -       u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
5638 - };
5639 +
5640 +/*
5641 + * this data is passed to driver during driver init.
5642 + */
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
5647 +
5648 +} __attribute__ ((packed));
5649 +
5650 +/*
5651 + * header passed with each descriptor
5652 + */
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
5656 +       u32        resvd    :  4;
5657 +} __attribute__ ((packed));
5658 +
5659 +/*
5660 + * xor descriptor data
5661 + */
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)
5669 +       u8              pad[2];             
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));
5673 +
5674 +
5675 +/*
5676 + * copy buffer for each transfer. each such tranfer between
5677 + * user spare host address and firmware allocated cache data.
5678 + */
5679 +struct mr_cpx_copy_mr_buffer {
5680 +       u32     buf;                       // buffer address/offset 
5681 +       u32     size;                      // size of copy 
5682 +} __attribute__ ((packed));
5683 +
5684 +/*
5685 + * copy descriptor data
5686 + */
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 
5693 +       u8                      pad[3];
5694 +       struct mr_cpx_copy_mr_buffer      copy_buf[MAX_MR_ROW_SIZE];
5695 +} __attribute__ ((packed)) ;
5696 +
5697 +/*
5698 + * users of this interface must allocate memory for the size of
5699 + * this structure while allocating memory for descriptors
5700 + */
5701 +union mr_cpx_descriptor {
5702 +       struct mr_cpx_xor_descriptor       cpx_xor_desc;
5703 +       struct mr_cpx_copy_descriptor     cpx_copy_desc;
5704 +       u8                      pad[512];
5705 +} __attribute__ ((packed));
5706 +
5707 +
5708 +/*
5709 + * request queue.
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.
5713 + */
5714 +struct mr_cpx_request_queue {
5715 +       u32             consumer_idx;
5716 +       u32             producer_idx;
5717 +       union mr_cpx_descriptor   cpxdescriptor[1]; // use max host commands 
5718 +} __attribute__ ((packed));
5719 +
5720 +
5721 +/*
5722 + * response data. this data will be posted by driver after copy/xor
5723 + * operation is compete.
5724 + */
5725 +union mr_cpx_response_data {
5726 +       struct {
5727 +               u32         context     : 24;                // context  
5728 +               u32         status      :  4;                // status in the form of cpx_status
5729 +               u32         type        :  4;
5730 +       } r;
5731 +       u32         w;
5732 +} __attribute__ ((packed));
5733 +
5734 +
5735 +/*
5736 + * response queue.
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.
5740 + */
5741 +struct  mr_cpx_response_queue {
5742 +       u32                 consumer_idx;
5743 +       u32                 producer_idx;
5744 +       union mr_cpx_response_data   cpx_resp_data[1]; // use max host commands 
5745 +} __attribute__ ((packed));
5746 +
5747 +
5748 +/*
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
5752 + */
5753 +struct  mr_cpx_queues {
5754 +       struct mr_cpx_request_queue     requestqueue;
5755 +       struct mr_cpx_response_queue    responsequeue;
5756 +} __attribute__ ((packed));
5757 +
5758 +/*
5759 + * driver sends this queue data during mfi init. firmware
5760 + * will not use the interface if the versions do not match.
5761 + */
5762 +struct mr_cpx_queue_data {
5763 +       u32         version;
5764 +       u32         count_queue_entries;
5765 +       u64         phys_addr_cpx_queues;
5766 +} __attribute__ ((packed));
5767 +
5768 +struct megasas_aen_event {
5769 +       struct work_struct hotplug_work;
5770 +       struct megasas_instance *instance;
5771 +};
5772  
5773  struct megasas_instance {
5774  
5775 @@ -1074,22 +1476,30 @@ struct megasas_instance {
5776         unsigned long base_addr;
5777         struct megasas_register_set __iomem *reg_set;
5778  
5779 +       struct megasas_pd_list          pd_list[MEGASAS_MAX_PD];
5780 +       u8     ld_ids[MEGASAS_MAX_LD_IDS];
5781 +
5782         s8 init_id;
5783  
5784         u16 max_num_sge;
5785         u16 max_fw_cmds;
5786         u32 max_sectors_per_req;
5787 +       u32 cmd_per_lun;
5788  
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;
5798  
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;
5805  
5806         struct Scsi_Host *host;
5807 @@ -1099,17 +1509,62 @@ struct megasas_instance {
5808  
5809         struct pci_dev *pdev;
5810         u32 unique_id;
5811 +       u32 fw_support_ieee;
5812  
5813         atomic_t fw_outstanding;
5814 -       u32 hw_crit_error;
5815 +       atomic_t fw_reset_no_pci_access;
5816  
5817         struct megasas_instance_template *instancet;
5818         struct tasklet_struct isr_tasklet;
5819 +       struct work_struct work_init;
5820  
5821         u8 flag;
5822 +       u8 unload;
5823 +       u8 flag_ieee;
5824 +       u8 issuepend_done;
5825 +       u8 disableOnlineCtrlReset;
5826 +       u8 adprecovery;
5827         unsigned long last_time;
5828 +       u32 mfiStatus;
5829 +       u32 last_seq_num;
5830 +
5831 +       struct timer_list io_completion_timer;
5832 +       struct list_head internal_reset_pending_q;
5833 +       
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;
5840 +       u32 host_mem_len;
5841 +       u8 *host_mem_virt;
5842 +
5843 +};
5844 +
5845 +enum {
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,
5852  };
5853  
5854 +
5855 + struct megasas_instance_template {
5856 +       void (*fire_cmd)(struct megasas_instance *, dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
5857 +
5858 +       void (*enable_intr)(struct megasas_register_set __iomem *) ;
5859 +       void (*disable_intr)(struct megasas_register_set __iomem *);
5860 +
5861 +       int (*clear_intr)(struct megasas_register_set __iomem *);
5862 +
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 *);
5866 + };
5867 +
5868  #define MEGASAS_IS_LOGICAL(scp)                                                \
5869         (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1
5870  
5871 @@ -1127,7 +1582,9 @@ struct megasas_cmd {
5872         u32 index;
5873         u8 sync_cmd;
5874         u8 cmd_status;
5875 -       u16 abort_aen;
5876 +       u8 abort_aen;
5877 +        u8 retry_for_fw_reset;
5878 +
5879  
5880         struct list_head list;
5881         struct scsi_cmnd *scmd;