MegaRAID SAS controllers.
[linux-2.6.git] / linux-2.6-820-megaraid.patch
1 diff -Nurp linux-2.6.22-950/drivers/scsi/megaraid/megaraid_sas.c linux-2.6.22-960/drivers/scsi/megaraid/megaraid_sas.c
2 --- linux-2.6.22-950/drivers/scsi/megaraid/megaraid_sas.c       2007-07-08 19:32:17.000000000 -0400
3 +++ linux-2.6.22-960/drivers/scsi/megaraid/megaraid_sas.c       2010-07-20 16:47:48.000000000 -0400
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 @@ -433,34 +897,15 @@ megasas_make_sgl32(struct megasas_instan
704         int sge_count;
705         struct scatterlist *os_sgl;
706  
707 -       /*
708 -        * Return 0 if there is no data transfer
709 -        */
710 -       if (!scp->request_buffer || !scp->request_bufflen)
711 -               return 0;
712 -
713 -       if (!scp->use_sg) {
714 -               mfi_sgl->sge32[0].phys_addr = pci_map_single(instance->pdev,
715 -                                                            scp->
716 -                                                            request_buffer,
717 -                                                            scp->
718 -                                                            request_bufflen,
719 -                                                            scp->
720 -                                                            sc_data_direction);
721 -               mfi_sgl->sge32[0].length = scp->request_bufflen;
722 +       sge_count = scsi_dma_map(scp);
723 +       BUG_ON(sge_count < 0);
724  
725 -               return 1;
726 -       }
727 -
728 -       os_sgl = (struct scatterlist *)scp->request_buffer;
729 -       sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
730 -                              scp->sc_data_direction);
731 -
732 -       for (i = 0; i < sge_count; i++, os_sgl++) {
733 -               mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
734 -               mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
735 +       if (sge_count) {
736 +               scsi_for_each_sg(scp, os_sgl, sge_count, i) {
737 +                       mfi_sgl->sge32[i].length = sg_dma_len(os_sgl);
738 +                       mfi_sgl->sge32[i].phys_addr = sg_dma_address(os_sgl);
739 +               }
740         }
741 -
742         return sge_count;
743  }
744  
745 @@ -481,46 +926,58 @@ megasas_make_sgl64(struct megasas_instan
746         int sge_count;
747         struct scatterlist *os_sgl;
748  
749 -       /*
750 -        * Return 0 if there is no data transfer
751 -        */
752 -       if (!scp->request_buffer || !scp->request_bufflen)
753 -               return 0;
754 +       sge_count = scsi_dma_map(scp);
755 +       BUG_ON(sge_count < 0);
756  
757 -       if (!scp->use_sg) {
758 -               mfi_sgl->sge64[0].phys_addr = pci_map_single(instance->pdev,
759 -                                                            scp->
760 -                                                            request_buffer,
761 -                                                            scp->
762 -                                                            request_bufflen,
763 -                                                            scp->
764 -                                                            sc_data_direction);
765 +       if (sge_count) {
766 +               scsi_for_each_sg(scp, os_sgl, sge_count, i) {
767 +                       mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
768 +                       mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
769 +               }
770 +       }
771 +       return sge_count;
772 +}
773  
774 -               mfi_sgl->sge64[0].length = scp->request_bufflen;
775 +/**
776 + * megasas_make_sgl_skinny - Prepares IEEE SGL
777 + * @instance:           Adapter soft state
778 + * @scp:                SCSI command from the mid-layer
779 + * @mfi_sgl:            SGL to be filled in
780 + *
781 + * If successful, this function returns the number of SG elements. Otherwise,
782 + * it returnes -1.
783 + */
784 +static int
785 +megasas_make_sgl_skinny(struct megasas_instance *instance,
786 +               struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl)
787 +{
788 +       int i;
789 +       int sge_count;
790 +       struct scatterlist *os_sgl;
791  
792 -               return 1;
793 -       }
794 +       sge_count = scsi_dma_map(scp);
795  
796 -       os_sgl = (struct scatterlist *)scp->request_buffer;
797 -       sge_count = pci_map_sg(instance->pdev, os_sgl, scp->use_sg,
798 -                              scp->sc_data_direction);
799 -
800 -       for (i = 0; i < sge_count; i++, os_sgl++) {
801 -               mfi_sgl->sge64[i].length = sg_dma_len(os_sgl);
802 -               mfi_sgl->sge64[i].phys_addr = sg_dma_address(os_sgl);
803 +       if (sge_count) {
804 +               scsi_for_each_sg(scp, os_sgl, sge_count, i) {
805 +                       mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl);
806 +                       mfi_sgl->sge_skinny[i].phys_addr =
807 +                                               sg_dma_address(os_sgl);
808 +                       mfi_sgl->sge_skinny[i].flag = 0;
809 +               }
810         }
811 -
812         return sge_count;
813  }
814  
815   /**
816   * megasas_get_frame_count - Computes the number of frames
817 + * @frame_type         : type of frame- io or pthru frame
818   * @sge_count          : number of sg elements
819   *
820   * Returns the number of frames required for numnber of sge's (sge_count)
821   */
822  
823 -static u32 megasas_get_frame_count(u8 sge_count)
824 +static u32 megasas_get_frame_count(struct megasas_instance *instance,
825 +                       u8 sge_count, u8 frame_type)
826  {
827         int num_cnt;
828         int sge_bytes;
829 @@ -530,14 +987,31 @@ static u32 megasas_get_frame_count(u8 sg
830         sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
831             sizeof(struct megasas_sge32);
832  
833 +       if (instance->flag_ieee) {
834 +               sge_sz = sizeof(struct megasas_sge_skinny);
835 +       }
836 +
837         /*
838 -       * Main frame can contain 2 SGEs for 64-bit SGLs and
839 -       * 3 SGEs for 32-bit SGLs
840 -       */
841 -       if (IS_DMA64)
842 -               num_cnt = sge_count - 2;
843 -       else
844 -               num_cnt = sge_count - 3;
845 +        * Main frame can contain 2 SGEs for 64-bit SGLs and
846 +        * 3 SGEs for 32-bit SGLs for ldio &
847 +        * 1 SGEs for 64-bit SGLs and
848 +        * 2 SGEs for 32-bit SGLs for pthru frame
849 +        */
850 +       if (unlikely(frame_type == PTHRU_FRAME)) {
851 +               if (instance->flag_ieee == 1) {
852 +                       num_cnt = sge_count - 1;
853 +               } else if (IS_DMA64)
854 +                       num_cnt = sge_count - 1;
855 +               else
856 +                       num_cnt = sge_count - 2;
857 +       } else {
858 +               if (instance->flag_ieee == 1) {
859 +                       num_cnt = sge_count - 1;
860 +               } else if (IS_DMA64)
861 +                       num_cnt = sge_count - 2;
862 +               else
863 +                       num_cnt = sge_count - 3;
864 +       }
865  
866         if(num_cnt>0){
867                 sge_bytes = sge_sz * num_cnt;
868 @@ -582,6 +1056,10 @@ megasas_build_dcdb(struct megasas_instan
869         else if (scp->sc_data_direction == PCI_DMA_NONE)
870                 flags = MFI_FRAME_DIR_NONE;
871  
872 +       if (instance->flag_ieee == 1) {
873 +               flags |= MFI_FRAME_IEEE;
874 +       }
875 +
876         /*
877          * Prepare the DCDB frame
878          */
879 @@ -592,15 +1070,31 @@ megasas_build_dcdb(struct megasas_instan
880         pthru->lun = scp->device->lun;
881         pthru->cdb_len = scp->cmd_len;
882         pthru->timeout = 0;
883 +       pthru->pad_0 = 0;
884         pthru->flags = flags;
885 -       pthru->data_xfer_len = scp->request_bufflen;
886 +       pthru->data_xfer_len = scsi_bufflen(scp);
887  
888         memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);
889  
890         /*
891 +       * If the command is for the tape device, set the
892 +       * pthru timeout to the os layer timeout value.
893 +       */
894 +       if (scp->device->type == TYPE_TAPE) {
895 +               if ((scp->request->timeout / HZ) > 0xFFFF)
896 +                       pthru->timeout = 0xFFFF;
897 +               else
898 +                       pthru->timeout = scp->request->timeout / HZ;
899 +       }
900 +
901 +       /*
902          * Construct SGL
903          */
904 -       if (IS_DMA64) {
905 +       if (instance->flag_ieee == 1) {
906 +               pthru->flags |= MFI_FRAME_SGL64;
907 +               pthru->sge_count = megasas_make_sgl_skinny(instance, scp,
908 +                                                     &pthru->sgl);
909 +       } else if (IS_DMA64) {
910                 pthru->flags |= MFI_FRAME_SGL64;
911                 pthru->sge_count = megasas_make_sgl64(instance, scp,
912                                                       &pthru->sgl);
913 @@ -608,6 +1102,10 @@ megasas_build_dcdb(struct megasas_instan
914                 pthru->sge_count = megasas_make_sgl32(instance, scp,
915                                                       &pthru->sgl);
916  
917 +       if (pthru->sge_count > instance->max_num_sge) {
918 +               printk("megasas: build_dcdb error, two many SGE\n");
919 +               return 0;
920 +       }
921         /*
922          * Sense info specific
923          */
924 @@ -619,7 +1117,8 @@ megasas_build_dcdb(struct megasas_instan
925          * Compute the total number of frames this command consumes. FW uses
926          * this number to pull sufficient number of frames from host memory.
927          */
928 -       cmd->frame_count = megasas_get_frame_count(pthru->sge_count);
929 +       cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count,
930 +                                                       PTHRU_FRAME);
931  
932         return cmd->frame_count;
933  }
934 @@ -628,7 +1127,7 @@ megasas_build_dcdb(struct megasas_instan
935   * megasas_build_ldio -        Prepares IOs to logical devices
936   * @instance:          Adapter soft state
937   * @scp:               SCSI command
938 - * @cmd:               Command to to be prepared
939 + * @cmd:               Command to be prepared
940   *
941   * Frames (and accompanying SGLs) for regular SCSI IOs use this function.
942   */
943 @@ -649,6 +1148,10 @@ megasas_build_ldio(struct megasas_instan
944         else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE)
945                 flags = MFI_FRAME_DIR_READ;
946  
947 +       if (instance->flag_ieee == 1) {
948 +               flags |= MFI_FRAME_IEEE;
949 +       }
950 +
951         /*
952          * Prepare the Logical IO frame: 2nd bit is zero for all read cmds
953          */
954 @@ -719,12 +1222,20 @@ megasas_build_ldio(struct megasas_instan
955         /*
956          * Construct SGL
957          */
958 -       if (IS_DMA64) {
959 +       if (instance->flag_ieee) {
960 +               ldio->flags |= MFI_FRAME_SGL64;
961 +               ldio->sge_count = megasas_make_sgl_skinny(instance, scp,
962 +                                             &ldio->sgl);
963 +       } else if (IS_DMA64) {
964                 ldio->flags |= MFI_FRAME_SGL64;
965                 ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl);
966         } else
967                 ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl);
968  
969 +        if (ldio->sge_count > instance->max_num_sge) {
970 +               printk("megasas: build_ld_io  error, sge_count = %x\n", ldio->sge_count);
971 +               return 0;
972 +       }
973         /*
974          * Sense info specific
975          */
976 @@ -736,7 +1247,8 @@ megasas_build_ldio(struct megasas_instan
977          * Compute the total number of frames this command consumes. FW uses
978          * this number to pull sufficient number of frames from host memory.
979          */
980 -       cmd->frame_count = megasas_get_frame_count(ldio->sge_count);
981 +       cmd->frame_count = megasas_get_frame_count(instance,
982 +                       ldio->sge_count, IO_FRAME);
983  
984         return cmd->frame_count;
985  }
986 @@ -821,109 +1333,1311 @@ megasas_dump_pending_frames(struct megas
987         printk(KERN_ERR "\nmegasas[%d]: Pending Internal cmds in FW : \n",instance->host->host_no);
988         for (i = 0; i < max_cmd; i++) {
989  
990 -               cmd = instance->cmd_list[i];
991 +               cmd = instance->cmd_list[i];
992 +
993 +               if(cmd->sync_cmd == 1){
994 +                       printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr);
995 +               }
996 +       }
997 +       printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
998 +}
999 +
1000 +/**
1001 + * megasas_queue_command -     Queue entry point
1002 + * @scmd:                      SCSI command to be queued
1003 + * @done:                      Callback entry point
1004 + */
1005 +static int
1006 +megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
1007 +{
1008 +       u32 frame_count;
1009 +       struct megasas_cmd *cmd;
1010 +       struct megasas_instance *instance;
1011 +       unsigned long flags;
1012 +
1013 +       instance = (struct megasas_instance *)
1014 +           scmd->device->host->hostdata;
1015 +
1016 +        if (instance->issuepend_done == 0)
1017 +               return SCSI_MLQUEUE_HOST_BUSY;
1018 +
1019 +       spin_lock_irqsave(&instance->hba_lock, flags);
1020 +       //Don't process if we have already declared adapter dead
1021 +       // If we are in middle of bringing up the HBA, send the busy status to mid-layer
1022 +       // till the process is complete
1023 +       if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
1024 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
1025 +               return SCSI_MLQUEUE_HOST_BUSY;
1026 +       }
1027 +
1028 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
1029 +
1030 +       scmd->scsi_done = done;
1031 +       scmd->result = 0;
1032 +
1033 +       if (MEGASAS_IS_LOGICAL(scmd) &&
1034 +           (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
1035 +               scmd->result = DID_BAD_TARGET << 16;
1036 +               goto out_done;
1037 +       }
1038 +
1039 +       switch (scmd->cmnd[0]) {
1040 +       case SYNCHRONIZE_CACHE:
1041 +               /*
1042 +                * FW takes care of flush cache on its own
1043 +                * No need to send it down
1044 +                */
1045 +               scmd->result = DID_OK << 16;
1046 +               goto out_done;
1047 +       default:
1048 +               break;
1049 +       }
1050 +
1051 +       cmd = megasas_get_cmd(instance);
1052 +       if (!cmd)
1053 +               return SCSI_MLQUEUE_HOST_BUSY;
1054 +
1055 +       /*
1056 +        * Logical drive command
1057 +        */
1058 +       if (megasas_is_ldio(scmd))
1059 +               frame_count = megasas_build_ldio(instance, scmd, cmd);
1060 +       else
1061 +               frame_count = megasas_build_dcdb(instance, scmd, cmd);
1062 +
1063 +       if (!frame_count)
1064 +               goto out_return_cmd;
1065 +
1066 +       cmd->scmd = scmd;
1067 +       scmd->SCp.ptr = (char *)cmd;
1068 +
1069 +       /*
1070 +        * Issue the command to the FW
1071 +        */
1072 +       atomic_inc(&instance->fw_outstanding);
1073 +
1074 +       instance->instancet->fire_cmd(instance, cmd->frame_phys_addr,
1075 +                               cmd->frame_count-1, instance->reg_set);
1076 +       /*
1077 +        * Check if we have pend cmds to be completed
1078 +        */
1079 +       if (poll_mode_io && atomic_read(&instance->fw_outstanding))
1080 +               tasklet_schedule(&instance->isr_tasklet);
1081 +
1082 +
1083 +       return 0;
1084 +
1085 + out_return_cmd:
1086 +       megasas_return_cmd(instance, cmd);
1087 + out_done:
1088 +       done(scmd);
1089 +       return 0;
1090 +}
1091 +
1092 +static struct megasas_instance *megasas_lookup_instance(u16 host_no)
1093 +{
1094 +       int i;
1095 +
1096 +       for (i = 0; i < megasas_mgmt_info.max_index; i++) {
1097 +
1098 +               if ((megasas_mgmt_info.instance[i]) &&
1099 +                   (megasas_mgmt_info.instance[i]->host->host_no == host_no))
1100 +                       return megasas_mgmt_info.instance[i];
1101 +       }
1102 +
1103 +       return NULL;
1104 +}
1105 +
1106 +static int megasas_slave_configure(struct scsi_device *sdev)
1107 +{
1108 +       u16             pd_index = 0;
1109 +       struct  megasas_instance *instance ;
1110 +
1111 +       instance = megasas_lookup_instance(sdev->host->host_no);
1112 +
1113 +       /*
1114 +       * Don't export physical disk devices to the disk driver.
1115 +       *
1116 +       * FIXME: Currently we don't export them to the midlayer at all.
1117 +       *        That will be fixed once LSI engineers have audited the
1118 +       *        firmware for possible issues.
1119 +       */
1120 +       if (sdev->channel < MEGASAS_MAX_PD_CHANNELS) {
1121 +               if (sdev->type == TYPE_TAPE) {
1122 +                       blk_queue_rq_timeout(sdev->request_queue,
1123 +                                    MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
1124 +                       return 0;
1125 +               } else if (sdev->type == TYPE_DISK) {
1126 +               
1127 +                       pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
1128 +               
1129 +                       if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
1130 +                               (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
1131 +                               blk_queue_rq_timeout(sdev->request_queue,
1132 +                                    MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
1133 +                               return 0;
1134 +                       }
1135 +               }
1136 +               return -ENXIO;
1137 +       }
1138 +
1139 +       /*
1140 +       * The RAID firmware may require extended timeouts.
1141 +       */
1142 +       blk_queue_rq_timeout(sdev->request_queue,
1143 +               MEGASAS_DEFAULT_CMD_TIMEOUT * HZ);
1144 +       return 0;
1145 +}
1146 +
1147 +static void megaraid_sas_kill_hba(struct megasas_instance *instance)
1148 +{
1149 +       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
1150 +               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY))
1151 +       {
1152 +               writel(MFI_STOP_ADP,
1153 +                       &instance->reg_set->reserved_0);
1154 +       } else {
1155 +               writel(MFI_STOP_ADP,
1156 +                       &instance->reg_set->inbound_doorbell);
1157 +       }
1158 +}
1159 +
1160 +
1161 +
1162 +
1163 +void xor_gen_15x1(u32 *buff_ptrs[16], u32 bytes)
1164 +{
1165 +    u32    off, words;
1166 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14, *s15;
1167 +
1168 +    d   = buff_ptrs[0];
1169 +    s1  = buff_ptrs[1];
1170 +    s2  = buff_ptrs[2];
1171 +    s3  = buff_ptrs[3];
1172 +    s4  = buff_ptrs[4];
1173 +    s5  = buff_ptrs[5];
1174 +    s6  = buff_ptrs[6];
1175 +    s7  = buff_ptrs[7];
1176 +    s8  = buff_ptrs[8];
1177 +    s9  = buff_ptrs[9];
1178 +    s10 = buff_ptrs[10];
1179 +    s11 = buff_ptrs[11];
1180 +    s12 = buff_ptrs[12];
1181 +    s13 = buff_ptrs[13];
1182 +    s14 = buff_ptrs[14];
1183 +    s15 = buff_ptrs[15];
1184 +
1185 +    for (words = bytes/4, off=0; words>0; words--, off++)
1186 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1187 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off] ^ s15[off];
1188 +
1189 +}
1190 +
1191 +
1192 +void xor_gen_14x1(u32 *buff_ptrs[15], u32 bytes)
1193 +{
1194 +    u32    off, words;
1195 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14;
1196 +
1197 +    d   = buff_ptrs[0];
1198 +    s1  = buff_ptrs[1];
1199 +    s2  = buff_ptrs[2];
1200 +    s3  = buff_ptrs[3];
1201 +    s4  = buff_ptrs[4];
1202 +    s5  = buff_ptrs[5];
1203 +    s6  = buff_ptrs[6];
1204 +    s7  = buff_ptrs[7];
1205 +    s8  = buff_ptrs[8];
1206 +    s9  = buff_ptrs[9];
1207 +    s10 = buff_ptrs[10];
1208 +    s11 = buff_ptrs[11];
1209 +    s12 = buff_ptrs[12];
1210 +    s13 = buff_ptrs[13];
1211 +    s14 = buff_ptrs[14];
1212 +
1213 +    for (words = bytes/4, off=0; words>0; words--, off++)
1214 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1215 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off];
1216 +
1217 +}
1218 +
1219 +
1220 +void xor_gen_13x1(u32 *buff_ptrs[14], u32 bytes)
1221 +{
1222 +    u32    off, words;
1223 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13;
1224 +
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 +    s13 = buff_ptrs[13];
1239 +
1240 +    for (words = bytes/4, off=0; words>0; words--, off++)
1241 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1242 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off];
1243 +
1244 +}
1245 +
1246 +
1247 +void xor_gen_12x1(u32 *buff_ptrs[13], u32 bytes)
1248 +{
1249 +    u32    off, words;
1250 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12;
1251 +
1252 +    d   = buff_ptrs[0];
1253 +    s1  = buff_ptrs[1];
1254 +    s2  = buff_ptrs[2];
1255 +    s3  = buff_ptrs[3];
1256 +    s4  = buff_ptrs[4];
1257 +    s5  = buff_ptrs[5];
1258 +    s6  = buff_ptrs[6];
1259 +    s7  = buff_ptrs[7];
1260 +    s8  = buff_ptrs[8];
1261 +    s9  = buff_ptrs[9];
1262 +    s10 = buff_ptrs[10];
1263 +    s11 = buff_ptrs[11];
1264 +    s12 = buff_ptrs[12];
1265 +
1266 +    for (words = bytes/4, off=0; words>0; words--, off++)
1267 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1268 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off];
1269 +
1270 +}
1271 +
1272 +
1273 +void xor_gen_11x1(u32 *buff_ptrs[12], u32 bytes)
1274 +{
1275 +    u32    off, words;
1276 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11;
1277 +
1278 +    d   = buff_ptrs[0];
1279 +    s1  = buff_ptrs[1];
1280 +    s2  = buff_ptrs[2];
1281 +    s3  = buff_ptrs[3];
1282 +    s4  = buff_ptrs[4];
1283 +    s5  = buff_ptrs[5];
1284 +    s6  = buff_ptrs[6];
1285 +    s7  = buff_ptrs[7];
1286 +    s8  = buff_ptrs[8];
1287 +    s9  = buff_ptrs[9];
1288 +    s10 = buff_ptrs[10];
1289 +    s11 = buff_ptrs[11];
1290 +
1291 +    for (words = bytes/4, off=0; words>0; words--, off++)
1292 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1293 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off];
1294 +
1295 +}
1296 +
1297 +
1298 +void xor_gen_10x1(u32 *buff_ptrs[11], u32 bytes)
1299 +{
1300 +    u32    off, words;
1301 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10;
1302 +
1303 +    d   = buff_ptrs[0];
1304 +    s1  = buff_ptrs[1];
1305 +    s2  = buff_ptrs[2];
1306 +    s3  = buff_ptrs[3];
1307 +    s4  = buff_ptrs[4];
1308 +    s5  = buff_ptrs[5];
1309 +    s6  = buff_ptrs[6];
1310 +    s7  = buff_ptrs[7];
1311 +    s8  = buff_ptrs[8];
1312 +    s9  = buff_ptrs[9];
1313 +    s10 = buff_ptrs[10];
1314 +
1315 +    for (words = bytes/4, off=0; words>0; words--, off++)
1316 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1317 +            s8[off] ^ s9[off] ^ s10[off];
1318 +
1319 +}
1320 +
1321 +
1322 +void xor_gen_9x1(u32 *buff_ptrs[10], u32 bytes)
1323 +{
1324 +    u32    off, words;
1325 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1326 +
1327 +    d   = buff_ptrs[0];
1328 +    s1  = buff_ptrs[1];
1329 +    s2  = buff_ptrs[2];
1330 +    s3  = buff_ptrs[3];
1331 +    s4  = buff_ptrs[4];
1332 +    s5  = buff_ptrs[5];
1333 +    s6  = buff_ptrs[6];
1334 +    s7  = buff_ptrs[7];
1335 +    s8  = buff_ptrs[8];
1336 +    s9  = buff_ptrs[9];
1337 +
1338 +    for (words = bytes/4, off=0; words>0; words--, off++)
1339 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1340 +            s8[off] ^ s9[off];
1341 +
1342 +}
1343 +
1344 +
1345 +void xor_gen_8x1(u32 *buff_ptrs[9], u32 bytes)
1346 +{
1347 +    u32    off, words;
1348 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8;
1349 +
1350 +    d   = buff_ptrs[0];
1351 +    s1  = buff_ptrs[1];
1352 +    s2  = buff_ptrs[2];
1353 +    s3  = buff_ptrs[3];
1354 +    s4  = buff_ptrs[4];
1355 +    s5  = buff_ptrs[5];
1356 +    s6  = buff_ptrs[6];
1357 +    s7  = buff_ptrs[7];
1358 +    s8  = buff_ptrs[8];
1359 +
1360 +    for (words = bytes/4, off=0; words>0; words--, off++)
1361 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^ s8[off];
1362 +
1363 +}
1364 +
1365 +
1366 +void xor_gen_7x1(u32 *buff_ptrs[8], u32 bytes)
1367 +{
1368 +    u32    off, words;
1369 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7;
1370 +
1371 +    d   = buff_ptrs[0];
1372 +    s1  = buff_ptrs[1];
1373 +    s2  = buff_ptrs[2];
1374 +    s3  = buff_ptrs[3];
1375 +    s4  = buff_ptrs[4];
1376 +    s5  = buff_ptrs[5];
1377 +    s6  = buff_ptrs[6];
1378 +    s7  = buff_ptrs[7];
1379 +
1380 +    for (words = bytes/4, off=0; words>0; words--, off++)
1381 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off];
1382 +
1383 +}
1384 +
1385 +
1386 +void xor_gen_6x1(u32 *buff_ptrs[7], u32 bytes)
1387 +{
1388 +    u32    off, words;
1389 +    u32    *d, *s1, *s2, *s3, *s4, *s5, *s6;
1390 +
1391 +    d   = buff_ptrs[0];
1392 +    s1  = buff_ptrs[1];
1393 +    s2  = buff_ptrs[2];
1394 +    s3  = buff_ptrs[3];
1395 +    s4  = buff_ptrs[4];
1396 +    s5  = buff_ptrs[5];
1397 +    s6  = buff_ptrs[6];
1398 +
1399 +    for (words = bytes/4, off=0; words>0; words--, off++)
1400 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off];
1401 +
1402 +}
1403 +
1404 +
1405 +void xor_gen_5x1(u32 *buff_ptrs[6], u32 bytes)
1406 +{
1407 +    u32    off, words;
1408 +    u32    *d, *s1, *s2, *s3, *s4, *s5;
1409 +
1410 +    d   = buff_ptrs[0];
1411 +    s1  = buff_ptrs[1];
1412 +    s2  = buff_ptrs[2];
1413 +    s3  = buff_ptrs[3];
1414 +    s4  = buff_ptrs[4];
1415 +    s5  = buff_ptrs[5];
1416 +
1417 +    for (words = bytes/4, off=0; words>0; words--, off++)
1418 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off];
1419 +
1420 +}
1421 +
1422 +
1423 +void xor_gen_4x1(u32 *buff_ptrs[5], u32 bytes)
1424 +{
1425 +    u32    off, words;
1426 +    u32    *d, *s1, *s2, *s3, *s4;
1427 +
1428 +    d   = buff_ptrs[0];
1429 +    s1  = buff_ptrs[1];
1430 +    s2  = buff_ptrs[2];
1431 +    s3  = buff_ptrs[3];
1432 +    s4  = buff_ptrs[4];
1433 +
1434 +    for (words = bytes/4, off=0; words>0; words--, off++)
1435 +        d[off] = s1[off] ^ s2[off] ^ s3[off] ^ s4[off];
1436 +
1437 +}
1438 +
1439 +
1440 +void xor_gen_3x1(u32 *buff_ptrs[4], u32 bytes)
1441 +{
1442 +    u32    off, words;
1443 +    u32    *d, *s1, *s2, *s3;
1444 +
1445 +    d   = buff_ptrs[0];
1446 +    s1  = buff_ptrs[1];
1447 +    s2  = buff_ptrs[2];
1448 +    s3  = buff_ptrs[3];
1449 +
1450 +    for (words = bytes/4, off=0; words>0; words--, off++)
1451 +        d[off] = s1[off] ^ s2[off] ^ s3[off];
1452 +
1453 +}
1454 +
1455 +
1456 +void xor_gen_2x1(u32 *buff_ptrs[3], u32 bytes)
1457 +{
1458 +    u32    off, words;
1459 +    u32    *d, *s1, *s2;
1460 +
1461 +    d   = buff_ptrs[0];
1462 +    s1  = buff_ptrs[1];
1463 +    s2  = buff_ptrs[2];
1464 +
1465 +    for (words = bytes/4, off=0; words>0; words--, off++)
1466 +        d[off] = s1[off] ^ s2[off];
1467 +    
1468 +}
1469 +
1470 +
1471 +void xor_gen_1x1(u32 *buff_ptrs[2], u32 bytes)
1472 +{
1473 +    u32    off, words;
1474 +    u32    *d, *s1;
1475 +
1476 +    d   = buff_ptrs[0];
1477 +    s1  = buff_ptrs[1];
1478 +
1479 +    for (words = bytes/4, off=0; words>0; words--, off++)
1480 +        d[off] = s1[off];
1481 +
1482 +}
1483 +
1484 +
1485 +u8 xor_chk_15x1(u32 *buff_ptrs[16], u32 bytes)
1486 +{
1487 +    u32    off, words;
1488 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13, *s14, *s15;
1489 +    u8     xor_result = MR_CPX_STATUS_SUCCESS;
1490 +
1491 +    d   = buff_ptrs[0];
1492 +    s1  = buff_ptrs[1];
1493 +    s2  = buff_ptrs[2];
1494 +    s3  = buff_ptrs[3];
1495 +    s4  = buff_ptrs[4];
1496 +    s5  = buff_ptrs[5];
1497 +    s6  = buff_ptrs[6];
1498 +    s7  = buff_ptrs[7];
1499 +    s8  = buff_ptrs[8];
1500 +    s9  = buff_ptrs[9];
1501 +    s10 = buff_ptrs[10];
1502 +    s11 = buff_ptrs[11];
1503 +    s12 = buff_ptrs[12];
1504 +    s13 = buff_ptrs[13];
1505 +    s14 = buff_ptrs[14];
1506 +    s15 = buff_ptrs[15];
1507 +
1508 +
1509 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1510 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1511 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off] ^ s15[off];
1512 +        if (r) {
1513 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1514 +            d[off] ^= r;
1515 +        }
1516 +    }
1517 +    return xor_result;
1518 +}
1519 +
1520 +
1521 +u8 xor_chk_14x1(u32 *buff_ptrs[15], 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;
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 +
1543 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1544 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1545 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off] ^ s14[off];
1546 +        if (r) {
1547 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1548 +            d[off] ^= r;
1549 +        }
1550 +    }
1551 +    return xor_result;
1552 +
1553 +}
1554 +
1555 +
1556 +u8 xor_chk_13x1(u32 *buff_ptrs[14], u32 bytes)
1557 +{
1558 +    u32    off, words;
1559 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12, *s13;
1560 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1561 +
1562 +    d   = buff_ptrs[0];
1563 +    s1  = buff_ptrs[1];
1564 +    s2  = buff_ptrs[2];
1565 +    s3  = buff_ptrs[3];
1566 +    s4  = buff_ptrs[4];
1567 +    s5  = buff_ptrs[5];
1568 +    s6  = buff_ptrs[6];
1569 +    s7  = buff_ptrs[7];
1570 +    s8  = buff_ptrs[8];
1571 +    s9  = buff_ptrs[9];
1572 +    s10 = buff_ptrs[10];
1573 +    s11 = buff_ptrs[11];
1574 +    s12 = buff_ptrs[12];
1575 +    s13 = buff_ptrs[13];
1576 +
1577 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1578 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1579 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off] ^ s13[off];
1580 +        if (r) {
1581 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1582 +            d[off] ^= r;
1583 +        }
1584 +    }
1585 +    return xor_result;
1586 +
1587 +}
1588 +
1589 +
1590 +u8 xor_chk_12x1(u32 *buff_ptrs[13], u32 bytes)
1591 +{
1592 +    u32    off, words;
1593 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12;
1594 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1595 +
1596 +    d   = buff_ptrs[0];
1597 +    s1  = buff_ptrs[1];
1598 +    s2  = buff_ptrs[2];
1599 +    s3  = buff_ptrs[3];
1600 +    s4  = buff_ptrs[4];
1601 +    s5  = buff_ptrs[5];
1602 +    s6  = buff_ptrs[6];
1603 +    s7  = buff_ptrs[7];
1604 +    s8  = buff_ptrs[8];
1605 +    s9  = buff_ptrs[9];
1606 +    s10 = buff_ptrs[10];
1607 +    s11 = buff_ptrs[11];
1608 +    s12 = buff_ptrs[12];
1609 +
1610 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1611 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1612 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off] ^ s12[off];
1613 +        if (r) {
1614 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1615 +            d[off] ^= r;
1616 +        }
1617 +    }
1618 +    return xor_result;
1619 +
1620 +}
1621 +
1622 +
1623 +u8 xor_chk_11x1(u32 *buff_ptrs[12], u32 bytes)
1624 +{
1625 +    u32    off, words;
1626 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11;
1627 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1628 +
1629 +    d   = buff_ptrs[0];
1630 +    s1  = buff_ptrs[1];
1631 +    s2  = buff_ptrs[2];
1632 +    s3  = buff_ptrs[3];
1633 +    s4  = buff_ptrs[4];
1634 +    s5  = buff_ptrs[5];
1635 +    s6  = buff_ptrs[6];
1636 +    s7  = buff_ptrs[7];
1637 +    s8  = buff_ptrs[8];
1638 +    s9  = buff_ptrs[9];
1639 +    s10 = buff_ptrs[10];
1640 +    s11 = buff_ptrs[11];
1641 +
1642 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1643 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1644 +            s8[off] ^ s9[off] ^ s10[off] ^ s11[off];
1645 +        if (r) {
1646 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1647 +            d[off] ^= r;
1648 +        }
1649 +    }
1650 +    return xor_result;
1651 +
1652 +}
1653 +
1654 +
1655 +u8 xor_chk_10x1(u32 *buff_ptrs[11], u32 bytes)
1656 +{
1657 +    u32    off, words;
1658 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10;
1659 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1660 +
1661 +    d   = buff_ptrs[0];
1662 +    s1  = buff_ptrs[1];
1663 +    s2  = buff_ptrs[2];
1664 +    s3  = buff_ptrs[3];
1665 +    s4  = buff_ptrs[4];
1666 +    s5  = buff_ptrs[5];
1667 +    s6  = buff_ptrs[6];
1668 +    s7  = buff_ptrs[7];
1669 +    s8  = buff_ptrs[8];
1670 +    s9  = buff_ptrs[9];
1671 +    s10 = buff_ptrs[10];
1672 +
1673 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1674 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1675 +            s8[off] ^ s9[off] ^ s10[off];
1676 +        if (r) {
1677 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1678 +            d[off] ^= r;
1679 +        }
1680 +    }
1681 +    return xor_result;
1682 +}
1683 +
1684 +
1685 +u8 xor_chk_9x1(u32 *buff_ptrs[10], u32 bytes)
1686 +{
1687 +    u32    off, words;
1688 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9;
1689 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1690 +
1691 +    d   = buff_ptrs[0];
1692 +    s1  = buff_ptrs[1];
1693 +    s2  = buff_ptrs[2];
1694 +    s3  = buff_ptrs[3];
1695 +    s4  = buff_ptrs[4];
1696 +    s5  = buff_ptrs[5];
1697 +    s6  = buff_ptrs[6];
1698 +    s7  = buff_ptrs[7];
1699 +    s8  = buff_ptrs[8];
1700 +    s9  = buff_ptrs[9];
1701 +
1702 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1703 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^\
1704 +            s8[off] ^ s9[off];
1705 +        if (r) {
1706 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1707 +            d[off] ^= r;
1708 +        }
1709 +    }
1710 +    return xor_result;
1711 +}
1712 +
1713 +
1714 +u8 xor_chk_8x1(u32 *buff_ptrs[9], u32 bytes)
1715 +{
1716 +    u32    off, words;
1717 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8;
1718 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1719 +
1720 +    d   = buff_ptrs[0];
1721 +    s1  = buff_ptrs[1];
1722 +    s2  = buff_ptrs[2];
1723 +    s3  = buff_ptrs[3];
1724 +    s4  = buff_ptrs[4];
1725 +    s5  = buff_ptrs[5];
1726 +    s6  = buff_ptrs[6];
1727 +    s7  = buff_ptrs[7];
1728 +    s8  = buff_ptrs[8];
1729 +
1730 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1731 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off] ^ s8[off];
1732 +        if (r) {
1733 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1734 +            d[off] ^= r;
1735 +        }
1736 +    }
1737 +    return xor_result;
1738 +}
1739 +
1740 +
1741 +u8 xor_chk_7x1(u32 *buff_ptrs[8], u32 bytes)
1742 +{
1743 +    u32    off, words;
1744 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6, *s7;
1745 +    u8    xor_result = MR_CPX_STATUS_SUCCESS;
1746 +
1747 +    d   = buff_ptrs[0];
1748 +    s1  = buff_ptrs[1];
1749 +    s2  = buff_ptrs[2];
1750 +    s3  = buff_ptrs[3];
1751 +    s4  = buff_ptrs[4];
1752 +    s5  = buff_ptrs[5];
1753 +    s6  = buff_ptrs[6];
1754 +    s7  = buff_ptrs[7];
1755 +
1756 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1757 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off] ^ s7[off];
1758 +        if (r) {
1759 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1760 +            d[off] ^= r;
1761 +        }
1762 +    }
1763 +    return xor_result;
1764 +
1765 +}
1766 +
1767 +
1768 +u8 xor_chk_6x1(u32 *buff_ptrs[7], u32 bytes)
1769 +{
1770 +    u32    off, words;
1771 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5, *s6;
1772 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1773 +
1774 +    d   = buff_ptrs[0];
1775 +    s1  = buff_ptrs[1];
1776 +    s2  = buff_ptrs[2];
1777 +    s3  = buff_ptrs[3];
1778 +    s4  = buff_ptrs[4];
1779 +    s5  = buff_ptrs[5];
1780 +    s6  = buff_ptrs[6];
1781 +
1782 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1783 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off] ^ s6[off];
1784 +        if (r) {
1785 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1786 +            d[off] ^= r;
1787 +        }
1788 +    }
1789 +    return xor_result;
1790 +}
1791 +
1792 +
1793 +u8 xor_chk_5x1(u32 *buff_ptrs[6], u32 bytes)
1794 +{
1795 +    u32    off, words;
1796 +    u32    r, *d, *s1, *s2, *s3, *s4, *s5;
1797 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1798 +
1799 +    d   = buff_ptrs[0];
1800 +    s1  = buff_ptrs[1];
1801 +    s2  = buff_ptrs[2];
1802 +    s3  = buff_ptrs[3];
1803 +    s4  = buff_ptrs[4];
1804 +    s5  = buff_ptrs[5];
1805 +
1806 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1807 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off] ^ s5[off];
1808 +        if (r) {
1809 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1810 +            d[off] ^= r;
1811 +        }
1812 +    }
1813 +    return xor_result;
1814 +}
1815 +
1816 +
1817 +u8 xor_chk_4x1(u32 *buff_ptrs[5], u32 bytes)
1818 +{
1819 +    u32    off, words;
1820 +    u32    r, *d, *s1, *s2, *s3, *s4;
1821 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1822 +
1823 +    d   = buff_ptrs[0];
1824 +    s1  = buff_ptrs[1];
1825 +    s2  = buff_ptrs[2];
1826 +    s3  = buff_ptrs[3];
1827 +    s4  = buff_ptrs[4];
1828 +
1829 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1830 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off] ^ s4[off];
1831 +        if (r) {
1832 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1833 +            d[off] ^= r;
1834 +        }
1835 +    }
1836 +    return xor_result;
1837 +}
1838 +
1839 +
1840 +u8 xor_chk_3x1(u32 *buff_ptrs[4], u32 bytes)
1841 +{
1842 +    u32    off, words;
1843 +    u32    r, *d, *s1, *s2, *s3;
1844 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1845 +
1846 +    d   = buff_ptrs[0];
1847 +    s1  = buff_ptrs[1];
1848 +    s2  = buff_ptrs[2];
1849 +    s3  = buff_ptrs[3];
1850 +
1851 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1852 +        r = d[off] ^ s1[off] ^ s2[off] ^ s3[off];
1853 +        if (r) {
1854 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1855 +            d[off] ^= r;
1856 +        }
1857 +    }
1858 +    return xor_result;
1859 +}
1860 +
1861 +
1862 +u8 xor_chk_2x1(u32 *buff_ptrs[3], u32 bytes)
1863 +{
1864 +    u32    off, words;
1865 +    u32    r, *d, *s1, *s2;
1866 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1867 +
1868 +    d   = buff_ptrs[0];
1869 +    s1  = buff_ptrs[1];
1870 +    s2  = buff_ptrs[2];
1871 +
1872 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1873 +        r = d[off] ^ s1[off] ^ s2[off];
1874 +        if (r) {
1875 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1876 +            d[off] ^= r;
1877 +        }
1878 +    }
1879 +    return xor_result;
1880 +}
1881 +
1882 +
1883 +u8 xor_chk_1x1(u32 *buff_ptrs[2], u32 bytes)
1884 +{
1885 +    u32    off, words;
1886 +    u32    *d, *s1;
1887 +    u8   xor_result = MR_CPX_STATUS_SUCCESS;
1888 +
1889 +    d   = buff_ptrs[0];
1890 +    s1  = buff_ptrs[1];
1891 +
1892 +    for (words = bytes/4, off=0; words>0; words--, off++) {
1893 +        if (d[off] != s1[off]) {
1894 +            xor_result = MR_CPX_STATUS_INCONSISTENT;
1895 +            d[off] = s1[off];
1896 +        }
1897 +    }
1898 +    return xor_result;
1899 +}
1900 +
1901 +
1902 +XOR_LOW_LEVEL_GEN_FUNC  xor_gen_funcs[MAX_MR_ROW_SIZE] = {
1903 +    xor_gen_1x1,
1904 +    xor_gen_2x1,
1905 +    xor_gen_3x1,
1906 +    xor_gen_4x1,
1907 +    xor_gen_5x1,
1908 +    xor_gen_6x1,
1909 +    xor_gen_7x1,
1910 +    xor_gen_8x1,
1911 +    xor_gen_9x1,
1912 +    xor_gen_10x1,
1913 +    xor_gen_11x1,
1914 +    xor_gen_12x1,
1915 +    xor_gen_13x1,
1916 +    xor_gen_14x1,
1917 +    xor_gen_15x1,
1918 + };
1919 +
1920 +XOR_LOW_LEVEL_CHECK_FUNC  xor_check_funcs[MAX_MR_ROW_SIZE] = {
1921 +    xor_chk_1x1,
1922 +    xor_chk_2x1,
1923 +    xor_chk_3x1,
1924 +    xor_chk_4x1,
1925 +    xor_chk_5x1,
1926 +    xor_chk_6x1,
1927 +    xor_chk_7x1,
1928 +    xor_chk_8x1,
1929 +    xor_chk_9x1,
1930 +    xor_chk_10x1,
1931 +    xor_chk_11x1,
1932 +    xor_chk_12x1,
1933 +    xor_chk_13x1,
1934 +    xor_chk_14x1,
1935 +    xor_chk_15x1,
1936 +};
1937 +
1938 +inline static u8 megasas_scan_set_bit(u32 bitmap)
1939 +{
1940 +    u8  bit = 0;
1941 +
1942 +    while (bitmap) {
1943 +        if (bitmap & 1)
1944 +            return bit;
1945 +
1946 +        bitmap >>= 1;
1947 +        bit++;
1948 +    }
1949 +    return ~0;
1950 +}
1951 +
1952 +
1953 +/**
1954 + * megasas_do_cpx_xor - completes the xor operation 
1955 + * @xor_des            : soruce and dest buffers details.
1956 + * @host_mem           : previously mapped memory for fw
1957 + * @host_mem_len       : mapped memory length in bytes.        
1958 + *     
1959 + * @return 0 on success != 0 on failure
1960 + * 
1961 + */
1962 +static u8 megasas_do_cpx_xor( struct mr_cpx_xor_descriptor *xor_des, const u8 *host_mem, const  u32 host_mem_len)
1963 +{
1964 +
1965 +       u32 buff_valid_bit_map = xor_des->buff_valid_bitmap;
1966 +       u32 *buf_ptr_list[MAX_MR_ROW_SIZE];
1967 +       u32 tx_count = xor_des->size;
1968 +       u8 dest_idx, buf_idx, bit;
1969 +       u8          is_op_gen;    // means is XOR generation (TRUE) or check (FALSE)
1970 +       u8  status = MR_CPX_STATUS_SUCCESS;
1971 +       
1972 +
1973 +       //make the first buffer ptr as the destination.
1974 +       if( xor_des->op ==  MR_CPX_XOR_OP_GEN_P || xor_des->op == MR_CPX_XOR_OP_CHECK_P )
1975 +               dest_idx = xor_des->p_idx;
1976 +       else 
1977 +               dest_idx = xor_des->q_idx;
1978 +
1979 +       buf_ptr_list[0] = (u32 *)(host_mem + xor_des->buff_list[dest_idx]);
1980 +       
1981 +       is_op_gen = MR_CPX_XOR_OP_IS_GEN(xor_des->op);
1982 +
1983 +       if ( xor_des->buff_list[dest_idx]+tx_count > host_mem_len){
1984 +               printk("Error: 1st host memory over flow detected.\n");
1985 +               return MR_CPX_STATUS_FAILURE;
1986 +       }
1987 +
1988 +       /*
1989 +        * For XOR_OP_CHECK_P, our check routine expects bufPtrs[0] to be both parity
1990 +        * source and parity destination; clear out the P-index from our working bitmap
1991 +        * so that the source-buffer scan loop below doesn't include P as one of the
1992 +        * explicit source buffers in bufPtrs[].
1993 +        */
1994 +       if ( !is_op_gen)
1995 +               buff_valid_bit_map &= ~(1<<xor_des->p_idx);
1996 +       
1997 +       //populate buf_ptr_list with valid buffer pointers.
1998 +       for ( buf_idx =1 ; buff_valid_bit_map != 0 ; buf_idx++ ){
1999 +               bit = megasas_scan_set_bit( buff_valid_bit_map);
2000 +               buf_ptr_list[buf_idx] = (u32 *)(host_mem + (u32)xor_des->buff_list[bit]);
2001 +               if ( xor_des->buff_list[bit]+tx_count > host_mem_len) {
2002 +                       printk("Error: host memory over flow detected.\n");
2003 +                       return MR_CPX_STATUS_FAILURE;;
2004 +               }
2005 +               buff_valid_bit_map &= ~(1 <<bit);
2006 +       }
2007 +       //call the xor gen fuctions.
2008 +       if ( is_op_gen )
2009 +       (*xor_gen_funcs[buf_idx-2])(buf_ptr_list, tx_count);
2010 +       else
2011 +               status = (*xor_check_funcs[buf_idx-2])(buf_ptr_list, tx_count);
2012 +       
2013 +       return status;
2014 +}
2015 +
2016 +static u8 megasas_copy( struct page *page, u32 page_offset, u32 sge_offset, u8 *host_ptr, u32 len, u8 dir)
2017 +{
2018 +       u8 *page_addr;
2019 +       u32 off;
2020 +       u32 bytes_copied;
2021 +       u32 remaining;
2022 +
2023 +       remaining = len;
2024 +       off = page_offset+sge_offset;
2025 +
2026 +       //kmap_atomic maps single page size but os sg element can have size 
2027 +       //more than page size, handle it.
2028 +       while( remaining > 0 ){
2029 +
2030 +               bytes_copied = min((size_t)remaining, (size_t)(PAGE_SIZE - (off & ~PAGE_MASK)));
2031 +
2032 +               page_addr = kmap_atomic(page+ (off >> PAGE_SHIFT), KM_SOFTIRQ0);
2033 +               if ( page_addr == NULL ){
2034 +                       printk("kmap_atomic is failed.\n");
2035 +                       return MR_CPX_STATUS_FAILURE;;
2036 +               }
2037 +               if ( dir == MR_CPX_DIR_WRITE )
2038 +                       memcpy( host_ptr, page_addr+(off & ~PAGE_MASK), bytes_copied );
2039 +               else 
2040 +                       memcpy( page_addr+(off & ~PAGE_MASK), host_ptr, bytes_copied );
2041 +       
2042 +               kunmap_atomic ( page_addr, KM_SOFTIRQ0 );
2043 +
2044 +               host_ptr += bytes_copied;
2045 +               remaining -= bytes_copied;
2046 +               off += bytes_copied;
2047 +       }
2048 +       
2049 +       return MR_CPX_STATUS_SUCCESS;
2050 +}
2051 +/**
2052 + * megasas_do_cpx_copy - Completes the copy opreation 
2053 + * @instance           : Driver soft state.
2054 + * @cpy_des            : input for copying the data.
2055 + *     
2056 + * @return 0 on success != 0 on failure
2057 + * 
2058 + */
2059 +static u8 megasas_do_cpx_copy( struct megasas_instance *instance, struct mr_cpx_copy_descriptor *cpy_des)
2060 +{
2061 +       u8                      status = MR_CPX_STATUS_SUCCESS ;
2062 +       u32                     total_remaining_len = cpy_des->total_byte_count;
2063 +       u32                     row_remaining_length;
2064 +       u32                     os_sge_sz = 0, os_sge_offset = 0, os_sge_idx =0, os_sge_len;
2065 +       u8                      sge_cnt, row_idx, *fw_ptr,host_skip_count_handled;
2066 +       struct scsi_cmnd        *os_cmd;
2067 +       struct scatterlist      *os_sgl;
2068 +       struct megasas_cmd      *mega_cmd;
2069 +       struct megasas_io_frame *ldio;
2070 +       
2071 +       if ( cpy_des->mfi_cmd_cxt  >= instance->max_fw_cmds ){
2072 +               printk("megasas: invalid context - 0x%x shoul be < 0x%x \n", cpy_des->mfi_cmd_cxt ,instance->max_fw_cmds );
2073 +                return MR_CPX_STATUS_FAILURE;
2074 +       }
2075 +       
2076 +       mega_cmd = ( struct megasas_cmd *)  instance->cmd_list[cpy_des->mfi_cmd_cxt];
2077 +       os_cmd = mega_cmd->scmd;
2078 +       ldio = (struct megasas_io_frame *)mega_cmd->frame;
2079 +       sge_cnt = ldio->sge_count;
2080 +       
2081 +       host_skip_count_handled = 0;
2082 +       row_idx = 0;
2083 +       row_remaining_length =0;
2084 +       
2085 +       scsi_for_each_sg(os_cmd, os_sgl, sge_cnt, os_sge_idx){
2086 +               
2087 +               os_sge_len = sg_dma_len(os_sgl);
2088 +
2089 +               if ( !host_skip_count_handled  && cpy_des->host_skip_count < ( os_sge_sz += os_sge_len )  ){
2090 +                       os_sge_offset = cpy_des->host_skip_count - ( os_sge_sz -os_sge_len );
2091 +                       os_sge_len -= os_sge_offset;
2092 +                       host_skip_count_handled = 1;
2093 +               } else if ( !host_skip_count_handled && cpy_des->host_skip_count == os_sge_sz ){
2094 +                       os_sge_offset = 0;
2095 +                       host_skip_count_handled = 1;
2096 +                       continue;
2097 +               }
2098 +               
2099 +               if ( !host_skip_count_handled )
2100 +                       continue;
2101 +               
2102 +               for( ;total_remaining_len &&  row_idx < MAX_MR_ROW_SIZE ; row_idx++ ){
2103 +
2104 +                       if ( ! row_remaining_length ){
2105 +                               fw_ptr = (u8 *)(instance->host_mem_virt+cpy_des->copy_buf[row_idx].buf);
2106 +                               row_remaining_length = cpy_des->copy_buf[row_idx].size;
2107 +                       }
2108 +
2109 +                       if ( (status = megasas_copy( sg_page(os_sgl), os_sgl->offset, os_sge_offset, fw_ptr,
2110 +                                                    MIN(os_sge_len, row_remaining_length), cpy_des->dir) ) )
2111 +                            break;
2112 +                       
2113 +                       total_remaining_len -= MIN(os_sge_len, row_remaining_length);
2114 +                       
2115 +                       if ( os_sge_len <= row_remaining_length ){
2116 +                               fw_ptr += os_sge_len;
2117 +                               if ( !(row_remaining_length -= os_sge_len) ) row_idx++;
2118 +                               os_sge_offset = 0;
2119 +                               break;
2120 +                       }else{
2121 +                               os_sge_len -= row_remaining_length;
2122 +                               os_sge_offset += row_remaining_length;
2123 +                               row_remaining_length =0;
2124 +                       }
2125 +
2126 +               }
2127 +               if ( row_idx >= MAX_MR_ROW_SIZE && total_remaining_len )
2128 +                       printk("megasas: Reached end of fw sglist while pending data transfer,row_idx = 0x%x, total_remaining_len = 0x%x \n",
2129 +                              row_idx, total_remaining_len);
2130 +               
2131 +               if( total_remaining_len == 0 || status == MR_CPX_STATUS_FAILURE )
2132 +                       break;
2133 +       }
2134 +
2135 +       if ( os_sge_idx >= sge_cnt && total_remaining_len )
2136 +               printk("megasas: Reached end of os sglist while pending data transfer, os_sge_idx = 0x%x, total_remaining_len = 0x%x \n",
2137 +                              os_sge_idx, total_remaining_len);
2138 +               
2139 +       return status;
2140 +       
2141 +}
2142 +/**
2143 + * megasas_handle_cpx_requests - Manages the fw queues 
2144 + * @instance           : Driver soft state.
2145 + *     
2146 + * @return 0 on success != 0 on failure
2147 + * 
2148 + */
2149 +static int megasas_handle_cpx_requests( struct megasas_instance *instance)
2150 +{
2151 +       struct mr_cpx_request_queue *req_q = instance->cpx_request_queue;
2152 +       u32 producer_idx, consumer_idx;
2153 +       u8 retval = 0;
2154 +       unsigned long flags;
2155  
2156 -               if(cmd->sync_cmd == 1){
2157 -                       printk(KERN_ERR "0x%08lx : ", (unsigned long)cmd->frame_phys_addr);
2158 +       producer_idx = req_q->producer_idx;
2159 +       consumer_idx = req_q->consumer_idx;
2160 +       
2161 +       while (producer_idx != consumer_idx ){
2162 +               union  mr_cpx_descriptor *cpx_des = &instance->cpx_dscrptr[consumer_idx];
2163 +               union  mr_cpx_response_data rsp_data;
2164 +
2165 +               if ( cpx_des->cpx_copy_desc.hdr.type == MR_CPX_DESCRIPTOR_TYPE_COPY )
2166 +                       retval = megasas_do_cpx_copy( instance, ( struct mr_cpx_copy_descriptor *)cpx_des );
2167 +               
2168 +               else if (cpx_des->cpx_copy_desc.hdr.type == MR_CPX_DESCRIPTOR_TYPE_XOR )
2169 +                       retval = megasas_do_cpx_xor( ( struct mr_cpx_xor_descriptor *)cpx_des,
2170 +                                                    (u8 *)instance->host_mem_virt, instance->host_mem_len );
2171 +               else{
2172 +                       printk("Fatal Error : Got invalid descriptor type...\n");
2173 +                       retval = MR_CPX_STATUS_FAILURE;
2174 +                       break;
2175                 }
2176 +
2177 +               rsp_data.r.status = retval;
2178 +               rsp_data.r.context = cpx_des->cpx_copy_desc.hdr.context;
2179 +               rsp_data.r.type = cpx_des->cpx_copy_desc.hdr.type;
2180 +
2181 +               //notify fw.
2182 +               spin_lock_irqsave(&instance->hba_lock, flags);
2183 +               writel( ~0, &instance->reg_set->inbound_high_queue_port);
2184 +               writel( rsp_data.w, &instance->reg_set->inbound_low_queue_port);
2185 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
2186 +
2187 +               //take care of wrap around case.
2188 +               consumer_idx++;
2189 +               if ( consumer_idx == instance->cpx_dscrptr_cnt )
2190 +                       consumer_idx = 0;
2191 +               
2192         }
2193 -       printk(KERN_ERR "megasas[%d]: Dumping Done.\n\n",instance->host->host_no);
2194 +               req_q->consumer_idx = producer_idx;
2195 +       
2196 +       return 0;
2197  }
2198  
2199  /**
2200 - * megasas_queue_command -     Queue entry point
2201 - * @scmd:                      SCSI command to be queued
2202 - * @done:                      Callback entry point
2203 + * megasas_complete_cmd_dpc     -      Returns FW's controller structure
2204 + * @instance_addr:                     Address of adapter soft state
2205 + *
2206 + * Tasklet to complete cmds
2207   */
2208 -static int
2209 -megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *))
2210 +static void megasas_complete_cmd_dpc(unsigned long instance_addr)
2211  {
2212 -       u32 frame_count;
2213 +       u32 producer;
2214 +       u32 consumer;
2215 +       u32 context;
2216         struct megasas_cmd *cmd;
2217 -       struct megasas_instance *instance;
2218 +       struct megasas_instance *instance =
2219 +                               (struct megasas_instance *)instance_addr;
2220 +       unsigned long flags;
2221  
2222 -       instance = (struct megasas_instance *)
2223 -           scmd->device->host->hostdata;
2224 +       /* If we have already declared adapter dead, donot complete cmds */
2225 +       spin_lock_irqsave(&instance->hba_lock, flags);
2226 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR ) { 
2227 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
2228 +               return;
2229 +       }
2230 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
2231  
2232 -       /* Don't process if we have already declared adapter dead */
2233 -       if (instance->hw_crit_error)
2234 -               return SCSI_MLQUEUE_HOST_BUSY;
2235 +       spin_lock_irqsave(&instance->completion_lock, flags);
2236  
2237 -       scmd->scsi_done = done;
2238 -       scmd->result = 0;
2239 +       producer = *instance->producer;
2240 +       consumer = *instance->consumer;
2241  
2242 -       if (MEGASAS_IS_LOGICAL(scmd) &&
2243 -           (scmd->device->id >= MEGASAS_MAX_LD || scmd->device->lun)) {
2244 -               scmd->result = DID_BAD_TARGET << 16;
2245 -               goto out_done;
2246 -       }
2247 +       while (consumer != producer) {
2248 +               context = instance->reply_queue[consumer];
2249 +               if (context >= instance->max_fw_cmds) {
2250 +                       printk("ERROR ERROR: unexpected context value %x\n", context);
2251 +                       BUG();
2252 +               }
2253  
2254 -       switch (scmd->cmnd[0]) {
2255 -       case SYNCHRONIZE_CACHE:
2256 -               /*
2257 -                * FW takes care of flush cache on its own
2258 -                * No need to send it down
2259 -                */
2260 -               scmd->result = DID_OK << 16;
2261 -               goto out_done;
2262 -       default:
2263 -               break;
2264 +               cmd = instance->cmd_list[context];
2265 +
2266 +               megasas_complete_cmd(instance, cmd, DID_OK);
2267 +
2268 +               consumer++;
2269 +               if (consumer == (instance->max_fw_cmds + 1)) {
2270 +                       consumer = 0;
2271 +               }
2272         }
2273  
2274 -       cmd = megasas_get_cmd(instance);
2275 -       if (!cmd)
2276 -               return SCSI_MLQUEUE_HOST_BUSY;
2277 +       *instance->consumer = producer;
2278  
2279 -       /*
2280 -        * Logical drive command
2281 -        */
2282 -       if (megasas_is_ldio(scmd))
2283 -               frame_count = megasas_build_ldio(instance, scmd, cmd);
2284 -       else
2285 -               frame_count = megasas_build_dcdb(instance, scmd, cmd);
2286 +       spin_unlock_irqrestore(&instance->completion_lock, flags);
2287 +       
2288  
2289 -       if (!frame_count)
2290 -               goto out_return_cmd;
2291  
2292 -       cmd->scmd = scmd;
2293 -       scmd->SCp.ptr = (char *)cmd;
2294 +       if ( instance->cpx_supported )
2295 +               megasas_handle_cpx_requests( instance);
2296  
2297         /*
2298 -        * Issue the command to the FW
2299 +        * Check if we can restore can_queue
2300          */
2301 -       atomic_inc(&instance->fw_outstanding);
2302 -
2303 -       instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
2304 +       if (instance->flag & MEGASAS_FW_BUSY
2305 +               && time_after(jiffies, instance->last_time + 5 * HZ)
2306 +               && atomic_read(&instance->fw_outstanding) < 17) {
2307  
2308 -       return 0;
2309 +               spin_lock_irqsave(instance->host->host_lock, flags);
2310 +               instance->flag &= ~MEGASAS_FW_BUSY;
2311 +               if ((instance->pdev->device ==
2312 +                       PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
2313 +                       (instance->pdev->device ==
2314 +                       PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
2315 +                       instance->host->can_queue =
2316 +                               instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
2317 +               } else
2318 +                       instance->host->can_queue =
2319 +                               instance->max_fw_cmds - MEGASAS_INT_CMDS;
2320  
2321 - out_return_cmd:
2322 -       megasas_return_cmd(instance, cmd);
2323 - out_done:
2324 -       done(scmd);
2325 -       return 0;
2326 +               spin_unlock_irqrestore(instance->host->host_lock, flags);
2327 +       }
2328  }
2329  
2330 -static int megasas_slave_configure(struct scsi_device *sdev)
2331 -{
2332 -       /*
2333 -        * Don't export physical disk devices to the disk driver.
2334 -        *
2335 -        * FIXME: Currently we don't export them to the midlayer at all.
2336 -        *        That will be fixed once LSI engineers have audited the
2337 -        *        firmware for possible issues.
2338 -        */
2339 -       if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK)
2340 -               return -ENXIO;
2341 +static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance);
2342 +static void process_fw_state_change_wq(struct work_struct *work); 
2343  
2344 -       /*
2345 -        * The RAID firmware may require extended timeouts.
2346 -        */
2347 -       if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS)
2348 -               sdev->timeout = MEGASAS_DEFAULT_CMD_TIMEOUT * HZ;
2349 -       return 0;
2350 +void megasas_do_ocr(struct megasas_instance *instance)
2351 +{
2352 +       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
2353 +               (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
2354 +               (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
2355 +       {
2356 +               *instance->consumer     = MEGASAS_ADPRESET_INPROG_SIGN;
2357 +       }
2358 +
2359 +       instance->instancet->disable_intr(instance->reg_set);
2360 +       instance->adprecovery   = MEGASAS_ADPRESET_SM_INFAULT;
2361 +       instance->issuepend_done = 0;
2362 +
2363 +       atomic_set(&instance->fw_outstanding, 0);
2364 +       megasas_internal_reset_defer_cmds(instance);
2365 +       process_fw_state_change_wq(&instance->work_init); 
2366  }
2367  
2368 +
2369  /**
2370   * megasas_wait_for_outstanding -      Wait for all outstanding cmds
2371   * @instance:                          Adapter soft state
2372 @@ -934,11 +2648,86 @@ static int megasas_slave_configure(struc
2373   */
2374  static int megasas_wait_for_outstanding(struct megasas_instance *instance)
2375  {
2376 -       int i;
2377 +       int i, sl;
2378 +       u32 reset_index;
2379         u32 wait_time = MEGASAS_RESET_WAIT_TIME;
2380 +       u8 adprecovery;
2381 +       unsigned long flags;
2382 +       struct list_head clist_local;
2383 +       struct megasas_cmd *reset_cmd;
2384 +       u32 fw_state;
2385 +       u8 kill_adapter_flag;
2386  
2387 -       for (i = 0; i < wait_time; i++) {
2388  
2389 +       // If we are in-process if internal reset, we should wait for that process to
2390 +       // complete
2391 +       spin_lock_irqsave(&instance->hba_lock, flags);
2392 +       adprecovery = instance->adprecovery;
2393 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
2394 +
2395 +       if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
2396 +
2397 +               // We take the ownership of all the pending commands. These would be failed to the OS
2398 +               // after a successful recovery from adapter internal reset condition.
2399 +               INIT_LIST_HEAD(&clist_local);
2400 +               spin_lock_irqsave(&instance->hba_lock, flags);
2401 +               list_splice_init(&instance->internal_reset_pending_q, &clist_local);
2402 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
2403 +
2404 +               printk("megasas: HBA reset handler invoked while adapter internal reset in progress, wait till that's over...\n");
2405 +               for (i = 0; i < wait_time; i++) {
2406 +                       msleep(1000);
2407 +                       // Are we there yet?
2408 +                       spin_lock_irqsave(&instance->hba_lock, flags);
2409 +                       adprecovery = instance->adprecovery;
2410 +                       spin_unlock_irqrestore(&instance->hba_lock, flags);
2411 +                       if (adprecovery == MEGASAS_HBA_OPERATIONAL)
2412 +                               break;
2413 +               }
2414 +
2415 +               // Are we out of reset yet? If not, HBA is toasted :-(
2416 +               if (adprecovery != MEGASAS_HBA_OPERATIONAL) {
2417 +                       printk("megasas: HBA reset handler timedout for internal reset. Stopping the HBA.\n");
2418 +                       spin_lock_irqsave(&instance->hba_lock, flags);
2419 +                       instance->adprecovery   = MEGASAS_HW_CRITICAL_ERROR;
2420 +                       spin_unlock_irqrestore(&instance->hba_lock, flags);
2421 +                       return FAILED;
2422 +               }
2423 +
2424 +               printk("megasas: HBA internal reset condition discovered to be cleared.\n");
2425 +
2426 +               // Send the pending commands back to the OS with reset condition
2427 +               reset_index     = 0;
2428 +               while (!list_empty(&clist_local)) {
2429 +                       reset_cmd       = list_entry((&clist_local)->next, struct megasas_cmd, list);
2430 +                       list_del_init(&reset_cmd->list);
2431 +                       if (reset_cmd->scmd) {
2432 +                               reset_cmd->scmd->result = DID_RESET << 16;
2433 +                               printk("megasas: %d:%p reset scsi command [%02x], %#lx\n",
2434 +                                       reset_index, reset_cmd, reset_cmd->scmd->cmnd[0], reset_cmd->scmd->serial_number);
2435 +                               reset_cmd->scmd->scsi_done(reset_cmd->scmd);
2436 +                               megasas_return_cmd(instance, reset_cmd);
2437 +                       }
2438 +                       else if (reset_cmd->sync_cmd) {
2439 +                               // Such commands have no timeout, we re-issue this guy again.
2440 +                               printk("megasas: %p synchronous command detected on the internal reset queue, re-issuing it.\n", reset_cmd);
2441 +                               reset_cmd->cmd_status = ENODATA;
2442 +                               instance->instancet->fire_cmd(instance, reset_cmd->frame_phys_addr ,0,instance->reg_set);
2443 +                       }
2444 +                       else {
2445 +                               printk("megasas: %p unexpected command on the internal reset defer list.\n", reset_cmd);
2446 +                       }
2447 +                       reset_index++;
2448 +               }
2449 +
2450 +               printk("megaraid_sas: All pending commands have been cleared for reset condition.\n");
2451 +
2452 +               return SUCCESS;
2453 +       }
2454 +
2455 +       // Kernel reset without internal reset in progress.
2456 +       printk("megaraid_sas: HBA reset handler invoked without an internal reset condition.\n");
2457 +       for (i = 0; i < wait_time; i++) {
2458                 int outstanding = atomic_read(&instance->fw_outstanding);
2459  
2460                 if (!outstanding)
2461 @@ -947,23 +2736,79 @@ static int megasas_wait_for_outstanding(
2462                 if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
2463                         printk(KERN_NOTICE "megasas: [%2d]waiting for %d "
2464                                "commands to complete\n",i,outstanding);
2465 +                       /*
2466 +                        * Call cmd completion routine. Cmd to be
2467 +                        * be completed directly without depending on isr.
2468 +                        */
2469 +                       megasas_complete_cmd_dpc((unsigned long)instance);
2470                 }
2471  
2472                 msleep(1000);
2473         }
2474  
2475 -       if (atomic_read(&instance->fw_outstanding)) {
2476 +       i = 0;
2477 +       kill_adapter_flag = 0;
2478 +       do {
2479 +                fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
2480 +                if ((fw_state == MFI_STATE_FAULT) && (instance->disableOnlineCtrlReset == 0)) {
2481 +                        printk("megasas: waiting_for_outstanding: before issue OCR. FW state = %x\n", fw_state);
2482 +                       if (i == 3) {
2483 +                               kill_adapter_flag = 2;
2484 +                               break;
2485 +                       } 
2486 +                        megasas_do_ocr(instance);
2487 +                       kill_adapter_flag = 1;
2488 +                        printk("megasas: waiting_for_outstanding: after issue OCR. \n");
2489 +
2490 +                        /* wait for 5 secs to let the FW finish all the pending cmds*/
2491 +                        for (sl=0; sl<10; sl++)
2492 +                                msleep(500);
2493 +               }
2494 +               i++;
2495 +       } while (i <= 3);
2496 +
2497 +       if (atomic_read(&instance->fw_outstanding) && !kill_adapter_flag) {
2498 +               if (instance->disableOnlineCtrlReset == 0) {
2499 +                        printk("megasas: waiting_for_outstanding: before issue OCR. FW state = %x\n", fw_state);
2500 +                        megasas_do_ocr(instance);
2501 +                        printk("megasas: waiting_for_outstanding: after issue OCR. \n");
2502 +
2503 +                        /* wait for 5 secs to let the FW finish all the pending cmds*/
2504 +                       for (i = 0; i < wait_time; i++) {
2505 +                               int outstanding = atomic_read(&instance->fw_outstanding);
2506 +
2507 +                               if (!outstanding)
2508 +                                       return SUCCESS;
2509 +                                msleep(1000);
2510 +                       }
2511 +               } 
2512 +       }
2513 +
2514 +       if (atomic_read(&instance->fw_outstanding) || (kill_adapter_flag == 2)) {
2515 +               printk("megaraid_sas: pending commands remain even after reset handling.\n");
2516                 /*
2517                 * Send signal to FW to stop processing any pending cmds.
2518                 * The controller will be taken offline by the OS now.
2519                 */
2520 -               writel(MFI_STOP_ADP,
2521 +               if ((instance->pdev->device ==
2522 +                       PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
2523 +                       (instance->pdev->device ==
2524 +                       PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
2525 +                       writel(MFI_STOP_ADP,
2526 +                               &instance->reg_set->reserved_0);
2527 +               } else {
2528 +                       writel(MFI_STOP_ADP,
2529                                 &instance->reg_set->inbound_doorbell);
2530 +               }
2531                 megasas_dump_pending_frames(instance);
2532 -               instance->hw_crit_error = 1;
2533 +               spin_lock_irqsave(&instance->hba_lock, flags);
2534 +               instance->adprecovery   = MEGASAS_HW_CRITICAL_ERROR;
2535 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
2536                 return FAILED;
2537         }
2538  
2539 +       printk("megaraid_sas: no more pending commands remain after reset handling.\n");
2540 +
2541         return SUCCESS;
2542  }
2543  
2544 @@ -985,7 +2830,7 @@ static int megasas_generic_reset(struct 
2545         scmd_printk(KERN_NOTICE, scmd, "megasas: RESET -%ld cmd=%x retries=%x\n",
2546                  scmd->serial_number, scmd->cmnd[0], scmd->retries);
2547  
2548 -       if (instance->hw_crit_error) {
2549 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
2550                 printk(KERN_ERR "megasas: cannot recover from previous reset "
2551                        "failures\n");
2552                 return FAILED;
2553 @@ -1008,7 +2853,7 @@ static int megasas_generic_reset(struct 
2554   * cmd has not been completed within the timeout period.
2555   */
2556  static enum
2557 -scsi_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
2558 +blk_eh_timer_return megasas_reset_timer(struct scsi_cmnd *scmd)
2559  {
2560         struct megasas_cmd *cmd = (struct megasas_cmd *)scmd->SCp.ptr;
2561         struct megasas_instance *instance;
2562 @@ -1016,7 +2861,7 @@ scsi_eh_timer_return megasas_reset_timer
2563  
2564         if (time_after(jiffies, scmd->jiffies_at_alloc +
2565                                 (MEGASAS_DEFAULT_CMD_TIMEOUT * 2) * HZ)) {
2566 -               return EH_NOT_HANDLED;
2567 +               return BLK_EH_NOT_HANDLED;
2568         }
2569  
2570         instance = cmd->instance;
2571 @@ -1030,7 +2875,7 @@ scsi_eh_timer_return megasas_reset_timer
2572  
2573                 spin_unlock_irqrestore(instance->host->host_lock, flags);
2574         }
2575 -       return EH_RESET_TIMER;
2576 +       return BLK_EH_RESET_TIMER;
2577  }
2578  
2579  /**
2580 @@ -1106,6 +2951,8 @@ megasas_bios_param(struct scsi_device *s
2581         return 0;
2582  }
2583  
2584 +static void megasas_aen_polling(struct work_struct *work);
2585 +
2586  /**
2587   * megasas_service_aen -       Processes an event notification
2588   * @instance:                  Adapter soft state
2589 @@ -1121,27 +2968,74 @@ megasas_bios_param(struct scsi_device *s
2590  static void
2591  megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd)
2592  {
2593 +       unsigned long flags;
2594         /*
2595          * Don't signal app if it is just an aborted previously registered aen
2596          */
2597 -       if (!cmd->abort_aen)
2598 +       if ((!cmd->abort_aen) && (instance->unload == 0)) {
2599 +               spin_lock_irqsave(&poll_aen_lock, flags);
2600 +               megasas_poll_wait_aen = 1;
2601 +               spin_unlock_irqrestore(&poll_aen_lock, flags);
2602 +               wake_up(&megasas_poll_wait);
2603                 kill_fasync(&megasas_async_queue, SIGIO, POLL_IN);
2604 +       }
2605         else
2606                 cmd->abort_aen = 0;
2607  
2608         instance->aen_cmd = NULL;
2609         megasas_return_cmd(instance, cmd);
2610 +
2611 +       if ((instance->unload == 0) && ((instance->issuepend_done == 1))) {
2612 +               struct megasas_aen_event *ev;
2613 +               ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2614 +               if (!ev) {
2615 +                       printk(KERN_ERR "megasas_service_aen: out of memory\n");
2616 +               } else {
2617 +                       ev->instance = instance;
2618 +                       instance->ev = ev;
2619 +                       INIT_WORK(&ev->hotplug_work, megasas_aen_polling);
2620 +                       schedule_delayed_work(
2621 +                               (struct delayed_work *)&ev->hotplug_work, 0);
2622 +               }
2623 +       }
2624 +}
2625 +
2626 +static int megasas_slave_alloc(struct scsi_device *sdev)
2627 +{
2628 +       u16             pd_index = 0;
2629 +       struct megasas_instance *instance ;
2630 +       instance = megasas_lookup_instance(sdev->host->host_no);
2631 +
2632 +       if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) &&
2633 +               (sdev->type == TYPE_DISK)) {
2634 +               /*
2635 +                * Open the OS scan to the SYSTEM PD
2636 +                */
2637 +               pd_index =
2638 +                   (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id;
2639 +               if ((instance->pd_list[pd_index].driveState ==
2640 +                       MR_PD_STATE_SYSTEM) &&
2641 +                       (instance->pd_list[pd_index].driveType ==
2642 +                       TYPE_DISK)) {
2643 +                       return 0;
2644 +               }
2645 +
2646 +               return -ENXIO;
2647 +       }
2648 +       return 0;
2649  }
2650  
2651 +
2652  /*
2653   * Scsi host template for megaraid_sas driver
2654   */
2655  static struct scsi_host_template megasas_template = {
2656  
2657         .module = THIS_MODULE,
2658 -       .name = "LSI Logic SAS based MegaRAID driver",
2659 +       .name = "LSI SAS based MegaRAID driver",
2660         .proc_name = "megaraid_sas",
2661         .slave_configure = megasas_slave_configure,
2662 +       .slave_alloc = megasas_slave_alloc,
2663         .queuecommand = megasas_queue_command,
2664         .eh_device_reset_handler = megasas_reset_device,
2665         .eh_bus_reset_handler = megasas_reset_bus_host,
2666 @@ -1195,45 +3089,6 @@ megasas_complete_abort(struct megasas_in
2667  }
2668  
2669  /**
2670 - * megasas_unmap_sgbuf -       Unmap SG buffers
2671 - * @instance:                  Adapter soft state
2672 - * @cmd:                       Completed command
2673 - */
2674 -static void
2675 -megasas_unmap_sgbuf(struct megasas_instance *instance, struct megasas_cmd *cmd)
2676 -{
2677 -       dma_addr_t buf_h;
2678 -       u8 opcode;
2679 -
2680 -       if (cmd->scmd->use_sg) {
2681 -               pci_unmap_sg(instance->pdev, cmd->scmd->request_buffer,
2682 -                            cmd->scmd->use_sg, cmd->scmd->sc_data_direction);
2683 -               return;
2684 -       }
2685 -
2686 -       if (!cmd->scmd->request_bufflen)
2687 -               return;
2688 -
2689 -       opcode = cmd->frame->hdr.cmd;
2690 -
2691 -       if ((opcode == MFI_CMD_LD_READ) || (opcode == MFI_CMD_LD_WRITE)) {
2692 -               if (IS_DMA64)
2693 -                       buf_h = cmd->frame->io.sgl.sge64[0].phys_addr;
2694 -               else
2695 -                       buf_h = cmd->frame->io.sgl.sge32[0].phys_addr;
2696 -       } else {
2697 -               if (IS_DMA64)
2698 -                       buf_h = cmd->frame->pthru.sgl.sge64[0].phys_addr;
2699 -               else
2700 -                       buf_h = cmd->frame->pthru.sgl.sge32[0].phys_addr;
2701 -       }
2702 -
2703 -       pci_unmap_single(instance->pdev, buf_h, cmd->scmd->request_bufflen,
2704 -                        cmd->scmd->sc_data_direction);
2705 -       return;
2706 -}
2707 -
2708 -/**
2709   * megasas_complete_cmd -      Completes a command
2710   * @instance:                  Adapter soft state
2711   * @cmd:                       Command to be completed
2712 @@ -1247,9 +3102,14 @@ static void
2713  megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
2714                      u8 alt_status)
2715  {
2716 +       unsigned long flags;
2717         int exception = 0;
2718         struct megasas_header *hdr = &cmd->frame->hdr;
2719  
2720 +       // If the commands complete successfully, the retry counter should also be reset
2721 +        // for future re-tries.
2722 +        cmd->retry_for_fw_reset = 0;
2723 +
2724         if (cmd->scmd)
2725                 cmd->scmd->SCp.ptr = NULL;
2726  
2727 @@ -1281,7 +3141,7 @@ megasas_complete_cmd(struct megasas_inst
2728  
2729                         atomic_dec(&instance->fw_outstanding);
2730  
2731 -                       megasas_unmap_sgbuf(instance, cmd);
2732 +                       scsi_dma_unmap(cmd->scmd);
2733                         cmd->scmd->scsi_done(cmd->scmd);
2734                         megasas_return_cmd(instance, cmd);
2735  
2736 @@ -1329,7 +3189,7 @@ megasas_complete_cmd(struct megasas_inst
2737  
2738                 atomic_dec(&instance->fw_outstanding);
2739  
2740 -               megasas_unmap_sgbuf(instance, cmd);
2741 +               scsi_dma_unmap(cmd->scmd);
2742                 cmd->scmd->scsi_done(cmd->scmd);
2743                 megasas_return_cmd(instance, cmd);
2744  
2745 @@ -1338,6 +3198,12 @@ megasas_complete_cmd(struct megasas_inst
2746         case MFI_CMD_SMP:
2747         case MFI_CMD_STP:
2748         case MFI_CMD_DCMD:
2749 +               if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
2750 +                       cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) {
2751 +                       spin_lock_irqsave(&poll_aen_lock, flags);
2752 +                       megasas_poll_wait_aen = 0;
2753 +                       spin_unlock_irqrestore(&poll_aen_lock, flags);
2754 +               }
2755  
2756                 /*
2757                  * See if got an event notification
2758 @@ -1364,39 +3230,286 @@ megasas_complete_cmd(struct megasas_inst
2759  }
2760  
2761  /**
2762 + * megasas_issue_pending_cmds_again -  issue all pending cmds
2763 + *                                     in FW again because of the fw reset
2764 + * @instance:                          Adapter soft state
2765 + */
2766 +static inline void
2767 +megasas_issue_pending_cmds_again(struct megasas_instance *instance)
2768 +{
2769 +       struct megasas_cmd *cmd;
2770 +       struct list_head clist_local;
2771 +       union megasas_evt_class_locale class_locale;
2772 +       unsigned long flags;
2773 +       u32 seq_num;
2774 +
2775 +       INIT_LIST_HEAD(&clist_local);
2776 +       spin_lock_irqsave(&instance->hba_lock, flags);
2777 +       list_splice_init(&instance->internal_reset_pending_q, &clist_local);
2778 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
2779 +
2780 +       while (!list_empty(&clist_local)) {
2781 +               cmd     = list_entry((&clist_local)->next, struct megasas_cmd, list);
2782 +               list_del_init(&cmd->list);
2783 +
2784 +               if (cmd->sync_cmd || cmd->scmd) {
2785 +                       printk("megaraid_sas: command %p, %p:%d detected to be pending while HBA reset.\n", cmd, cmd->scmd, cmd->sync_cmd);
2786 +
2787 +                       cmd->retry_for_fw_reset++;
2788 +
2789 +                       // If a command has continuously been tried multiple times and causing
2790 +                       // a FW reset condition, no further recoveries should be performed on
2791 +                       // the controller
2792 +                       if (cmd->retry_for_fw_reset == 3) {
2793 +                               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);
2794 +                               megaraid_sas_kill_hba(instance);
2795 +
2796 +                               instance->adprecovery   = MEGASAS_HW_CRITICAL_ERROR;
2797 +                              return;
2798 +                       }
2799 +               }
2800 +
2801 +               if (cmd->sync_cmd == 1) {
2802 +                       if (cmd->scmd) {
2803 +                               printk("megaraid_sas: unexpected SCSI command attached to internal command!\n");
2804 +                       }
2805 +                       printk("megasas: %p synchronous command detected on the internal reset queue, issue it again.\n", cmd);
2806 +                       cmd->cmd_status = ENODATA;
2807 +                       instance->instancet->fire_cmd(instance,cmd->frame_phys_addr ,0,instance->reg_set);
2808 +               } else if (cmd->scmd) {
2809 +                       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);
2810 +                       atomic_inc(&instance->fw_outstanding);
2811 +                       instance->instancet->fire_cmd(instance, cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set);
2812 +               }
2813 +               else {
2814 +                       printk("megasas: %p unexpected command on the internal reset defer list while re-issue!!\n", cmd);
2815 +               }
2816 +       }
2817 +
2818 +       // Re-register AEN
2819 +       if (instance->aen_cmd) {
2820 +               printk("megaraid_sas: existing aen_cmd discovered in deferred processing, freeing...\n");
2821 +               megasas_return_cmd(instance, instance->aen_cmd);
2822 +               instance->aen_cmd       = NULL;
2823 +       }
2824 +
2825 +       /*
2826 +       * Initiate AEN (Asynchronous Event Notification)
2827 +       */
2828 +       seq_num = instance->last_seq_num;
2829 +       class_locale.members.reserved = 0;
2830 +       class_locale.members.locale = MR_EVT_LOCALE_ALL;
2831 +       class_locale.members.class = MR_EVT_CLASS_DEBUG;
2832 +
2833 +       megasas_register_aen(instance, seq_num, class_locale.word);
2834 +
2835 +
2836 +}
2837 +
2838 +/**
2839 + * Move the internal reset pending commands to a deferred queue.
2840 + *
2841 + * We move the commands pending at internal reset time to a pending queue. This queue would
2842 + * be flushed after successful completion of the internal reset sequence.
2843 + * if the internal reset did not complete in time, the kernel reset handler would flush these
2844 + * commands.
2845 + **/
2846 +static void megasas_internal_reset_defer_cmds(struct megasas_instance *instance)
2847 +{
2848 +        struct megasas_cmd *cmd;
2849 +        int i;
2850 +        u32 max_cmd = instance->max_fw_cmds;
2851 +        u32 defer_index;
2852 +        unsigned long flags;
2853 +
2854 +        defer_index     = 0;
2855 +        spin_lock_irqsave(&instance->cmd_pool_lock, flags);
2856 +        for (i = 0; i < max_cmd; i++) {
2857 +                cmd = instance->cmd_list[i];
2858 +                if (cmd->sync_cmd == 1 || cmd->scmd) {
2859 +                        printk("megasas: moving cmd[%d]:%p:%d:%p on the defer queue as internal reset in progress.\n",
2860 +                                defer_index, cmd, cmd->sync_cmd, cmd->scmd);
2861 +                        if (!list_empty(&cmd->list)) {
2862 +                                printk("megaraid_sas: ERROR while moving this cmd:%p, %d %p, it was discovered on some list?\n", cmd, cmd->sync_cmd, cmd->scmd);
2863 +                                list_del_init(&cmd->list);
2864 +                        }
2865 +                        defer_index++;
2866 +                        list_add_tail(&cmd->list, &instance->internal_reset_pending_q);
2867 +                }
2868 +        }
2869 +        spin_unlock_irqrestore(&instance->cmd_pool_lock, flags);
2870 +}
2871 +
2872 +
2873 +static void 
2874 +process_fw_state_change_wq(struct work_struct *work) 
2875 +{
2876 +       struct megasas_instance *instance =
2877 +               container_of(work, struct megasas_instance, work_init);
2878 +        u32 wait;
2879 +        unsigned long flags;
2880 +
2881 +        if (instance->adprecovery != MEGASAS_ADPRESET_SM_INFAULT) {
2882 +                printk("megaraid_sas: error, unexpected adapter recovery state %x in %s\n", instance->adprecovery, __FUNCTION__);
2883 +                return ;
2884 +        }
2885 +
2886 +       if (instance->adprecovery == MEGASAS_ADPRESET_SM_INFAULT) {
2887 +               printk("megaraid_sas: FW detected to be in fault state, restarting it...\n");
2888 +
2889 +               instance->instancet->disable_intr(instance->reg_set);
2890 +                atomic_set(&instance->fw_outstanding, 0);
2891 +
2892 +                atomic_set(&instance->fw_reset_no_pci_access, 1);
2893 +                instance->instancet->adp_reset(instance, instance->reg_set);
2894 +                atomic_set(&instance->fw_reset_no_pci_access, 0 );
2895 +
2896 +               printk("megaraid_sas: FW was restarted successfully, initiating next stage...\n");
2897 +
2898 +               printk("megaraid_sas: HBA recovery state machine, state 2 starting...\n");
2899 +
2900 +                /*waitting for about 20 second before start the second init*/
2901 +                for(wait = 0; wait < 30; wait++)
2902 +                        msleep(1000);
2903 +
2904 +                if (megasas_transition_to_ready(instance))
2905 +                {
2906 +                        printk("megaraid_sas: out: controller is not in ready state\n");
2907 +
2908 +                        megaraid_sas_kill_hba(instance);
2909 +                       instance->adprecovery   = MEGASAS_HW_CRITICAL_ERROR;
2910 +                        return ;
2911 +                }
2912 +
2913 +                if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
2914 +                        (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
2915 +                        (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
2916 +                {
2917 +                        *instance->consumer = *instance->producer;
2918 +                } else {
2919 +                        *instance->consumer = 0;
2920 +                        *instance->producer = 0;
2921 +                }
2922 +
2923 +               if ( megasas_check_cpx_support( instance ) == 0  ){
2924 +                       if ( megasas_send_cpx_queue_data( instance ) ){
2925 +                               printk("megasas: Sending cpx queue data to FW failed.\n");
2926 +                               megasas_remove_cpx(instance);
2927 +                       }
2928 +               }
2929 +
2930 +               // Transition the FW to operational state
2931 +               megasas_issue_init_mfi(instance);
2932 +
2933 +               // Setting the adapter to OPERATIONAL at this point is very important. This would
2934 +               // prevent other subsystems (reset, aen, and ioctls) to block till the recovery
2935 +               // logic has run it's course.
2936 +               spin_lock_irqsave(&instance->hba_lock, flags);
2937 +               instance->adprecovery   = MEGASAS_HBA_OPERATIONAL;
2938 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
2939 +               instance->instancet->enable_intr(instance->reg_set);
2940 +
2941 +               printk("megaraid_sas: second stage of reset complete, FW is ready now.\n");
2942 +
2943 +               megasas_issue_pending_cmds_again(instance);
2944 +               instance->issuepend_done = 1;
2945 +
2946 +
2947 +       }
2948 +       return ;
2949 +}
2950 +
2951 +/**
2952   * megasas_deplete_reply_queue -       Processes all completed commands
2953   * @instance:                          Adapter soft state
2954   * @alt_status:                                Alternate status to be returned to
2955   *                                     SCSI mid-layer instead of the status
2956   *                                     returned by the FW
2957 + * Note: this must be called with hba lock held
2958   */
2959  static int
2960  megasas_deplete_reply_queue(struct megasas_instance *instance, u8 alt_status)
2961  {
2962 -       /*
2963 -        * Check if it is our interrupt
2964 -        * Clear the interrupt 
2965 -        */
2966 -       if(instance->instancet->clear_intr(instance->reg_set))
2967 +       u32 mfiStatus;
2968 +       u32 fw_state;
2969 +
2970 +       // If the adapter is under a reset recovery, all interrupts coming from it must be acknowledged
2971 +       // if the consumer pointer value indicates so.
2972 +        if((mfiStatus = instance->instancet->check_reset(instance, instance->reg_set)) == 1) {
2973 +                return IRQ_HANDLED;
2974 +        }
2975 +
2976 +       // Clear the interrupt on the HBA
2977 +       if((mfiStatus = instance->instancet->clear_intr(instance->reg_set)) == 0) {
2978                 return IRQ_NONE;
2979 +       }
2980  
2981 -       if (instance->hw_crit_error)
2982 -               goto out_done;
2983 -        /*
2984 -        * Schedule the tasklet for cmd completion
2985 -        */
2986 +       instance->mfiStatus = mfiStatus;
2987 +
2988 +       // If the current soft state indicates an OPERATIONAL state _and_ now we have
2989 +       // detected state change, this should be FW FAULT case.
2990 +       if ((mfiStatus & MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE)) {
2991 +               fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
2992 +
2993 +                if (fw_state != MFI_STATE_FAULT) {
2994 +                        printk("megaraid_sas: fw state while internal state change operational, state:%x\n", fw_state);
2995 +                }
2996 +
2997 +                       if ((fw_state == MFI_STATE_FAULT) && (instance->disableOnlineCtrlReset == 0)){
2998 +                       printk("megaraid_sas: adapter reset condition is detected, waiting for it to restart...\n");
2999 +
3000 +                               if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1064R) ||
3001 +                                       (instance->pdev->device == PCI_DEVICE_ID_DELL_PERC5) ||
3002 +                                       (instance->pdev->device == PCI_DEVICE_ID_LSI_VERDE_ZCR))
3003 +                                       {
3004 +                                       *instance->consumer     = MEGASAS_ADPRESET_INPROG_SIGN;
3005 +                               }
3006 +
3007 +
3008 +                       instance->instancet->disable_intr(instance->reg_set);
3009 +                       instance->adprecovery   = MEGASAS_ADPRESET_SM_INFAULT;    // indicates adapter restart stage 1 is in progress
3010 +                       instance->issuepend_done = 0;
3011 +
3012 +                       // The pending commands are moved to a deferred list. We would pick commands up and
3013 +                       // re-issue once the reset processing is over.
3014 +                       atomic_set(&instance->fw_outstanding, 0);
3015 +                       megasas_internal_reset_defer_cmds(instance);
3016 +
3017 +                       // Schedule a low-priorty thread to perform the function for current stage of
3018 +                       // adapter reset state machine.
3019 +                               printk("megaraid_sas: FW state detected, current:%x, reset stage:%d\n", fw_state, instance->adprecovery);
3020 +                       schedule_work(&instance->work_init);
3021 +                       return IRQ_HANDLED;
3022 +               }
3023 +               else {
3024 +                       printk("megaraid_sas: fw state while internal state changes, state:%x, disableOCR=%x\n",
3025 +                               fw_state, instance->disableOnlineCtrlReset);
3026 +               }
3027 +       }
3028 +
3029 +       // Schedule the tasklet for cmd completion
3030         tasklet_schedule(&instance->isr_tasklet);
3031 -out_done:
3032         return IRQ_HANDLED;
3033  }
3034 -
3035  /**
3036   * megasas_isr - isr entry point
3037   */
3038  static irqreturn_t megasas_isr(int irq, void *devp)
3039  {
3040 -       return megasas_deplete_reply_queue((struct megasas_instance *)devp,
3041 -                                          DID_OK);
3042 +       struct megasas_instance *instance;
3043 +       unsigned long flags;
3044 +       irqreturn_t     rc;
3045 +      
3046 +       if ( atomic_read( &(( (struct megasas_instance *)devp)->fw_reset_no_pci_access )) )
3047 +                return IRQ_HANDLED;
3048 +
3049 +       instance = (struct megasas_instance *)devp;
3050 +
3051 +       spin_lock_irqsave(&instance->hba_lock, flags);
3052 +       rc =  megasas_deplete_reply_queue(instance, DID_OK);
3053 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
3054 +
3055 +       return rc;
3056  }
3057  
3058  /**
3059 @@ -1415,6 +3528,7 @@ megasas_transition_to_ready(struct megas
3060         u8 max_wait;
3061         u32 fw_state;
3062         u32 cur_state;
3063 +       u32 abs_state, curr_abs_state;
3064  
3065         fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK;
3066  
3067 @@ -1424,6 +3538,8 @@ megasas_transition_to_ready(struct megas
3068  
3069         while (fw_state != MFI_STATE_READY) {
3070  
3071 +               abs_state = instance->instancet->read_fw_status_reg(instance->reg_set);
3072 +
3073                 switch (fw_state) {
3074  
3075                 case MFI_STATE_FAULT:
3076 @@ -1435,18 +3551,36 @@ megasas_transition_to_ready(struct megas
3077                         /*
3078                          * Set the CLR bit in inbound doorbell
3079                          */
3080 -                       writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3081 -                               &instance->reg_set->inbound_doorbell);
3082 +                       if ((instance->pdev->device ==
3083 +                               PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3084 +                               (instance->pdev->device ==
3085 +                               PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
3086 +
3087 +                               writel(
3088 +                                 MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3089 +                                       &instance->reg_set->reserved_0);
3090 +                       } else {
3091 +                               writel(
3092 +                                   MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG,
3093 +                                       &instance->reg_set->inbound_doorbell);
3094 +                       }
3095  
3096 -                       max_wait = 2;
3097 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3098                         cur_state = MFI_STATE_WAIT_HANDSHAKE;
3099                         break;
3100  
3101                 case MFI_STATE_BOOT_MESSAGE_PENDING:
3102 -                       writel(MFI_INIT_HOTPLUG,
3103 -                               &instance->reg_set->inbound_doorbell);
3104 +                       if ((instance->pdev->device ==
3105 +                               PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3106 +                       (instance->pdev->device ==
3107 +                               PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
3108 +                               writel(MFI_INIT_HOTPLUG,
3109 +                                       &instance->reg_set->reserved_0);
3110 +                       } else 
3111 +                               writel(MFI_INIT_HOTPLUG,
3112 +                                       &instance->reg_set->inbound_doorbell);
3113  
3114 -                       max_wait = 10;
3115 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3116                         cur_state = MFI_STATE_BOOT_MESSAGE_PENDING;
3117                         break;
3118  
3119 @@ -1455,9 +3589,17 @@ megasas_transition_to_ready(struct megas
3120                          * Bring it to READY state; assuming max wait 10 secs
3121                          */
3122                         instance->instancet->disable_intr(instance->reg_set);
3123 -                       writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell);
3124 +                       if ((instance->pdev->device ==
3125 +                               PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3126 +                               (instance->pdev->device ==
3127 +                               PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
3128 +                               writel(MFI_RESET_FLAGS,
3129 +                                       &instance->reg_set->reserved_0);
3130 +                       } else 
3131 +                               writel(MFI_RESET_FLAGS,
3132 +                                       &instance->reg_set->inbound_doorbell);
3133  
3134 -                       max_wait = 10;
3135 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3136                         cur_state = MFI_STATE_OPERATIONAL;
3137                         break;
3138  
3139 @@ -1465,32 +3607,32 @@ megasas_transition_to_ready(struct megas
3140                         /*
3141                          * This state should not last for more than 2 seconds
3142                          */
3143 -                       max_wait = 2;
3144 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3145                         cur_state = MFI_STATE_UNDEFINED;
3146                         break;
3147  
3148                 case MFI_STATE_BB_INIT:
3149 -                       max_wait = 2;
3150 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3151                         cur_state = MFI_STATE_BB_INIT;
3152                         break;
3153  
3154                 case MFI_STATE_FW_INIT:
3155 -                       max_wait = 20;
3156 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3157                         cur_state = MFI_STATE_FW_INIT;
3158                         break;
3159  
3160                 case MFI_STATE_FW_INIT_2:
3161 -                       max_wait = 20;
3162 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3163                         cur_state = MFI_STATE_FW_INIT_2;
3164                         break;
3165  
3166                 case MFI_STATE_DEVICE_SCAN:
3167 -                       max_wait = 20;
3168 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3169                         cur_state = MFI_STATE_DEVICE_SCAN;
3170                         break;
3171  
3172                 case MFI_STATE_FLUSH_CACHE:
3173 -                       max_wait = 20;
3174 +                       max_wait = MEGASAS_RESET_WAIT_TIME;
3175                         cur_state = MFI_STATE_FLUSH_CACHE;
3176                         break;
3177  
3178 @@ -1506,8 +3648,10 @@ megasas_transition_to_ready(struct megas
3179                 for (i = 0; i < (max_wait * 1000); i++) {
3180                         fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) &  
3181                                         MFI_STATE_MASK ;
3182 +               curr_abs_state =
3183 +               instance->instancet->read_fw_status_reg(instance->reg_set);
3184  
3185 -                       if (fw_state == cur_state) {
3186 +                       if (abs_state == curr_abs_state) {
3187                                 msleep(1);
3188                         } else
3189                                 break;
3190 @@ -1516,12 +3660,12 @@ megasas_transition_to_ready(struct megas
3191                 /*
3192                  * Return error if fw_state hasn't changed after max_wait
3193                  */
3194 -               if (fw_state == cur_state) {
3195 +               if (curr_abs_state == abs_state) {
3196                         printk(KERN_DEBUG "FW state [%d] hasn't changed "
3197                                "in %d secs\n", fw_state, max_wait);
3198                         return -ENODEV;
3199                 }
3200 -       };
3201 +       }
3202         printk(KERN_INFO "megasas: FW now in Ready state\n");
3203  
3204         return 0;
3205 @@ -1594,11 +3738,16 @@ static int megasas_create_frame_pool(str
3206         sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) :
3207             sizeof(struct megasas_sge32);
3208  
3209 +       if (instance->flag_ieee) {
3210 +               sge_sz = sizeof(struct megasas_sge_skinny);
3211 +       }
3212 +
3213         /*
3214          * Calculated the number of 64byte frames required for SGL
3215          */
3216         sgl_sz = sge_sz * instance->max_num_sge;
3217         frame_count = (sgl_sz + MEGAMFI_FRAME_SIZE - 1) / MEGAMFI_FRAME_SIZE;
3218 +       frame_count = 15;
3219  
3220         /*
3221          * We need one extra frame for the MFI command
3222 @@ -1655,7 +3804,15 @@ static int megasas_create_frame_pool(str
3223                         return -ENOMEM;
3224                 }
3225  
3226 +               memset(cmd->frame, 0, total_sz);
3227 +
3228                 cmd->frame->io.context = cmd->index;
3229 +
3230 +               /*
3231 +                * Initialize pad_0 to 0, otherwise it could corrupt
3232 +                * the value of context and cause FW crash
3233 +                */
3234 +               cmd->frame->io.pad_0 = 0;
3235         }
3236  
3237         return 0;
3238 @@ -1714,8 +3871,7 @@ static int megasas_alloc_cmds(struct meg
3239          * Allocate the dynamic array first and then allocate individual
3240          * commands.
3241          */
3242 -       instance->cmd_list = kmalloc(sizeof(struct megasas_cmd *) * max_cmd,
3243 -                                    GFP_KERNEL);
3244 +       instance->cmd_list = kcalloc(max_cmd, sizeof(struct megasas_cmd*), GFP_KERNEL);
3245  
3246         if (!instance->cmd_list) {
3247                 printk(KERN_DEBUG "megasas: out of memory\n");
3248 @@ -1747,6 +3903,7 @@ static int megasas_alloc_cmds(struct meg
3249                 cmd = instance->cmd_list[i];
3250                 memset(cmd, 0, sizeof(struct megasas_cmd));
3251                 cmd->index = i;
3252 +               cmd->scmd = NULL;
3253                 cmd->instance = instance;
3254  
3255                 list_add_tail(&cmd->list, &instance->cmd_pool);
3256 @@ -1763,6 +3920,181 @@ static int megasas_alloc_cmds(struct meg
3257         return 0;
3258  }
3259  
3260 +/*
3261 + * megasas_get_pd_list_info -  Returns FW's pd_list structure
3262 + * @instance:                          Adapter soft state
3263 + * @pd_list:                           pd_list structure
3264 + *
3265 + * Issues an internal command (DCMD) to get the FW's controller PD
3266 + * list structure.  This information is mainly used to find out SYSTEM
3267 + * supported by the FW.
3268 + */
3269 +static int
3270 +megasas_get_pd_list(struct megasas_instance *instance)
3271 +{
3272 +       int ret = 0, pd_index = 0;
3273 +       struct megasas_cmd *cmd;
3274 +       struct megasas_dcmd_frame *dcmd;
3275 +       struct MR_PD_LIST *ci;
3276 +       struct MR_PD_ADDRESS *pd_addr;
3277 +       dma_addr_t ci_h = 0;
3278 +
3279 +       cmd = megasas_get_cmd(instance);
3280 +
3281 +       if (!cmd) {
3282 +               printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n");
3283 +               return -ENOMEM;
3284 +       }
3285 +
3286 +       dcmd = &cmd->frame->dcmd;
3287 +
3288 +       ci = pci_alloc_consistent(instance->pdev,
3289 +                 MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h);
3290 +
3291 +       if (!ci) {
3292 +               printk(KERN_DEBUG "Failed to alloc mem for pd_list\n");
3293 +               megasas_return_cmd(instance, cmd);
3294 +               return -ENOMEM;
3295 +       }
3296 +
3297 +       memset(ci, 0, sizeof(*ci));
3298 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3299 +
3300 +       dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST;
3301 +       dcmd->mbox.b[1] = 0;
3302 +       dcmd->cmd = MFI_CMD_DCMD;
3303 +       dcmd->cmd_status = 0xFF;
3304 +       dcmd->sge_count = 1;
3305 +       dcmd->flags = MFI_FRAME_DIR_READ;
3306 +       dcmd->timeout = 0;
3307 +       dcmd->pad_0 = 0;
3308 +       dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
3309 +       dcmd->opcode = MR_DCMD_PD_LIST_QUERY;
3310 +       dcmd->sgl.sge32[0].phys_addr = ci_h;
3311 +       dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST);
3312 +
3313 +       if (!megasas_issue_polled(instance, cmd)) {
3314 +               ret = 0;
3315 +       } else {
3316 +               ret = -1;
3317 +       }
3318 +
3319 +       /*
3320 +       * the following function will get the instance PD LIST.
3321 +       */
3322 +
3323 +       pd_addr = ci->addr;
3324 +
3325 +       if ( ret == 0 &&
3326 +               (ci->count <
3327 +                 (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) {
3328 +
3329 +               memset(instance->pd_list, 0,
3330 +                       MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
3331 +
3332 +               for (pd_index = 0; pd_index < ci->count; pd_index++) {
3333 +
3334 +                       instance->pd_list[pd_addr->deviceId].tid        =
3335 +                                                       pd_addr->deviceId;
3336 +                       instance->pd_list[pd_addr->deviceId].driveType  =
3337 +                                                       pd_addr->scsiDevType;
3338 +                       instance->pd_list[pd_addr->deviceId].driveState =
3339 +                                                       MR_PD_STATE_SYSTEM;
3340 +                       pd_addr++;
3341 +               }
3342 +       }
3343 +
3344 +       pci_free_consistent(instance->pdev,
3345 +                               MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST),
3346 +                               ci, ci_h);
3347 +               
3348 +
3349 +       megasas_return_cmd(instance, cmd);
3350 +       
3351 +       return ret;
3352 +}
3353 +/**
3354 + * megasas_get_ld_list_info -  Returns FW's ld_list structure
3355 + * @instance:                          Adapter soft state
3356 + * @ld_list:                           ld_list structure
3357 + *
3358 + * Issues an internal command (DCMD) to get the FW's controller PD
3359 + * list structure.  This information is mainly used to find out SYSTEM
3360 + * supported by the FW.
3361 + */
3362 +static int
3363 +megasas_get_ld_list(struct megasas_instance *instance)
3364 +{
3365 +       int ret = 0, ld_index = 0, ids = 0;
3366 +       struct megasas_cmd *cmd;
3367 +       struct megasas_dcmd_frame *dcmd;
3368 +       struct MR_LD_LIST *ci;
3369 +       dma_addr_t ci_h = 0;
3370 +
3371 +       cmd = megasas_get_cmd(instance);
3372 +
3373 +       if (!cmd) {
3374 +               printk(KERN_DEBUG "megasas (megasas_get_ld_list): Failed to get cmd\n");
3375 +               return -ENOMEM;
3376 +       }
3377 +
3378 +       dcmd = &cmd->frame->dcmd;
3379 +
3380 +       ci = pci_alloc_consistent(instance->pdev, sizeof(struct MR_LD_LIST), &ci_h);
3381 +
3382 +       if (!ci) {
3383 +               printk(KERN_DEBUG "Failed to alloc mem for megasas_get_ld_list\n");
3384 +               megasas_return_cmd(instance, cmd);
3385 +               return -ENOMEM;
3386 +       }
3387 +
3388 +       memset(ci, 0, sizeof(*ci));
3389 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
3390 +
3391 +       dcmd->cmd = MFI_CMD_DCMD;
3392 +       dcmd->cmd_status = 0xFF;
3393 +       dcmd->sge_count = 1;
3394 +       dcmd->flags = MFI_FRAME_DIR_READ;
3395 +       dcmd->timeout = 0;
3396 +       dcmd->data_xfer_len = sizeof(struct MR_LD_LIST);
3397 +       dcmd->opcode = MR_DCMD_LD_GET_LIST;
3398 +       dcmd->sgl.sge32[0].phys_addr = ci_h;
3399 +       dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST);
3400 +       dcmd->pad_0  = 0;
3401 +
3402 +       if (!megasas_issue_polled(instance, cmd)) {
3403 +               ret = 0;
3404 +
3405 +       } else {
3406 +               ret = -1;
3407 +       }
3408 +
3409 +       /*
3410 +       * the following function will get the instance PD LIST.
3411 +       */
3412 +
3413 +       if ( (ret == 0) && (ci->ldCount <= (MAX_LOGICAL_DRIVES))){
3414 +               
3415 +               memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3416 +
3417 +               for (ld_index = 0; ld_index < ci->ldCount; ld_index++) {
3418 +                       if (ci->ldList[ld_index].state != 0) {
3419 +                               ids = ci->ldList[ld_index].ref.targetId;
3420 +                               instance->ld_ids[ids] = ci->ldList[ld_index].ref.targetId;
3421 +                       }
3422 +                                                               
3423 +               }
3424 +
3425 +       }
3426 +
3427 +       pci_free_consistent(instance->pdev, sizeof(struct MR_LD_LIST), ci, ci_h); 
3428 +               
3429 +
3430 +       megasas_return_cmd(instance, cmd);
3431 +
3432 +       return ret;
3433 +}
3434 +
3435  /**
3436   * megasas_get_controller_info -       Returns FW's controller structure
3437   * @instance:                          Adapter soft state
3438 @@ -1808,6 +4140,7 @@ megasas_get_ctrl_info(struct megasas_ins
3439         dcmd->sge_count = 1;
3440         dcmd->flags = MFI_FRAME_DIR_READ;
3441         dcmd->timeout = 0;
3442 +       dcmd->pad_0 = 0;
3443         dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info);
3444         dcmd->opcode = MR_DCMD_CTRL_GET_INFO;
3445         dcmd->sgl.sge32[0].phys_addr = ci_h;
3446 @@ -1827,58 +4160,276 @@ megasas_get_ctrl_info(struct megasas_ins
3447         return ret;
3448  }
3449  
3450 +
3451  /**
3452 - * megasas_complete_cmd_dpc     -      Returns FW's controller structure
3453 - * @instance_addr:                     Address of adapter soft state
3454 + * megasas_check_cpx_support : Tries to get the host memory address if fails then cpx
3455 +                               not supported else cpx supported.
3456 + * @instance:          Adapter soft state
3457   *
3458 - * Tasklet to complete cmds
3459 + * @return 0 on success non-zero on failure.
3460   */
3461 -static void megasas_complete_cmd_dpc(unsigned long instance_addr)
3462 +static int megasas_check_cpx_support( struct megasas_instance *instance)
3463 +{
3464 +       struct megasas_cmd *cmd;
3465 +       struct megasas_dcmd_frame *dcmd;
3466 +       struct mr_cpx_init_data *cpx_init_data;
3467 +       dma_addr_t cpx_init_data_h;
3468 +       int retval = 0;
3469 +               
3470 +       cmd = megasas_get_cmd(instance);
3471 +       if (!cmd) {
3472 +               printk(KERN_DEBUG "megasas (get_host_mem_addr): Failed to get cmd\n");
3473 +               return -ENOMEM;
3474 +       }
3475 +
3476 +       cpx_init_data = pci_alloc_consistent(instance->pdev, sizeof( struct mr_cpx_init_data), &cpx_init_data_h);
3477 +       if (cpx_init_data == NULL) {
3478 +               printk(KERN_DEBUG "Failed to alloc mem for cpx_init_data. \n");
3479 +               megasas_return_cmd(instance, cmd);
3480 +               return -ENOMEM;
3481 +       }
3482 +
3483 +       dcmd = &cmd->frame->dcmd;
3484 +       dcmd->flags = 0;
3485 +       dcmd->opcode = MR_DCMD_CTRL_MISC_CPX_INIT_DATA_GET;
3486 +       dcmd->data_xfer_len  = sizeof(struct mr_cpx_init_data );
3487 +       dcmd->cmd = MFI_CMD_DCMD;
3488 +       dcmd->cmd_status  = 0xff;
3489 +       dcmd->sge_count = 1;
3490 +       dcmd->sgl.sge32[0].phys_addr = cpx_init_data_h;
3491 +       dcmd->sgl.sge32[0].length = sizeof(struct mr_cpx_init_data);
3492 +
3493 +       retval = megasas_issue_polled ( instance, cmd );
3494 +       
3495 +       if ( retval == 0 && cmd->frame->hdr.cmd_status == 0  ){
3496 +               instance->host_mem_phys = cpx_init_data->phys_addr_cache_buf;
3497 +               instance->host_mem_len  = cpx_init_data->size;
3498 +               instance->cpx_dscrptr_cnt = cpx_init_data->cpx_desc_count;
3499 +               if ( instance->host_mem_len == 0 || instance->host_mem_phys == 0 || ! instance->cpx_dscrptr_cnt ){
3500 +                       printk("Got host_mem_len = 0 OR host_mem_phys as NULL OR cpx_descriptor count = 0 \n");
3501 +                       retval = 1;
3502 +               }
3503 +       } else {
3504 +               printk("megasas: cpx is not supported.\n");
3505 +               retval = 1;
3506 +       }
3507 +       
3508 +       
3509 +       pci_free_consistent(instance->pdev, sizeof(struct mr_cpx_init_data), cpx_init_data, cpx_init_data_h);
3510 +       megasas_return_cmd(instance, cmd);
3511 +       
3512 +       return retval;
3513 +}
3514 +
3515 +/**
3516 + * megasas_send_cpx_queue_data : Sends the queue setup info to fw.
3517 + * @instance:          Adapter soft state
3518 + *
3519 + * @return 0 on success non-zero on failure.
3520 + */
3521 +
3522 +static int megasas_send_cpx_queue_data( struct megasas_instance *instance )
3523 +{
3524 +
3525 +       struct megasas_cmd *cmd;
3526 +       struct megasas_dcmd_frame *dcmd;
3527 +       int retval = 0;
3528 +       
3529 +       cmd = megasas_get_cmd(instance);
3530 +       if (!cmd) {
3531 +               printk(KERN_DEBUG "megasas (get_host_mem_addr): Failed to get cmd\n");
3532 +               return -ENOMEM;
3533 +       }
3534 +
3535 +       //initialize dcmd data
3536 +       dcmd = &cmd->frame->dcmd;
3537 +       dcmd->flags = 0;
3538 +       dcmd->opcode = MR_DCMD_CTRL_MISC_CPX_QUEUE_DATA;
3539 +       dcmd->data_xfer_len  = sizeof( struct mr_cpx_queue_data );
3540 +       dcmd->cmd = MFI_CMD_DCMD;
3541 +       dcmd->cmd_status  = 0xff;
3542 +       dcmd->sge_count = 1;
3543 +       dcmd->mbox.w[0] = instance->cpx_request_queue_h;
3544 +       dcmd->mbox.w[1] = 0;
3545 +       dcmd->mbox.w[2] = instance->cpx_dscrptr_cnt;
3546 +
3547 +       retval = megasas_issue_polled ( instance, cmd );
3548 +       
3549 +       megasas_return_cmd( instance, cmd);
3550 +       
3551 +       if ( retval == 0 ){
3552 +               instance->cpx_request_queue->consumer_idx = instance->cpx_request_queue->producer_idx = 0;
3553 +               instance->cpx_supported = 1;
3554 +       }
3555 +       
3556 +       return retval;
3557 +}
3558 +
3559 +static u32 megasas_get_cpx_mem_len( u16 max_fw_cmds )
3560 +{
3561 +       return (sizeof( struct mr_cpx_request_queue ) + sizeof( union mr_cpx_descriptor ) * ( max_fw_cmds) );
3562 +}
3563 +
3564 +static u32 megasas_remove_cpx( struct megasas_instance *instance)
3565 +{
3566 +               if ( instance->host_mem_virt )
3567 +                       iounmap(instance->host_mem_virt);
3568 +               if ( instance->cpx_request_queue )
3569 +                       pci_free_consistent(instance->pdev, megasas_get_cpx_mem_len( instance->cpx_dscrptr_cnt),
3570 +                                           instance->cpx_request_queue,instance->cpx_request_queue_h );
3571 +               instance->cpx_supported = 0;
3572 +       
3573 +       return 0;
3574 +}
3575 +
3576 +/* should have host_mem_phys intialized before calling this function.*/        
3577 +static int megasas_init_cpx( struct megasas_instance *instance)
3578 +{
3579 +
3580 +       //map address
3581 +       instance->host_mem_virt = ioremap(instance->host_mem_phys, instance->host_mem_len);
3582 +       if ( instance->host_mem_virt == NULL ){
3583 +               printk("megasas: Failed to ioremap host memory.\n");
3584 +               goto error_unload;
3585 +       }
3586 +               
3587 +       //allocate memory for indices and descriptors for reply and response array's
3588 +       instance->cpx_request_queue = pci_alloc_consistent( instance->pdev, megasas_get_cpx_mem_len (instance->cpx_dscrptr_cnt), &instance->cpx_request_queue_h );
3589 +       if ( instance->cpx_request_queue == NULL ){
3590 +               printk(KERN_ERR "megasas: Out of DMA memory for cpx operations.\n");
3591 +               goto error_unload;
3592 +       }
3593 +               
3594 +       //initialize queues
3595 +       instance->cpx_dscrptr = (union mr_cpx_descriptor *)((u8*)instance->cpx_request_queue + (  sizeof(instance->cpx_request_queue->consumer_idx)*2  ));
3596 +
3597 +       //send data to fw.
3598 +       if ( megasas_send_cpx_queue_data( instance ) ){
3599 +               printk("megasas: Sending cpx queue data to FW failed.\n");
3600 +               goto error_unload;
3601 +       }
3602 +                       
3603 +       return 0;
3604 +
3605 +error_unload:
3606 +       megasas_remove_cpx( instance );
3607 +       return -1;
3608 +}
3609 +
3610 +/**
3611 + * megasas_issue_init_mfi -    Initializes the FW
3612 + * @instance:          Adapter soft state
3613 + *
3614 + * Issues the INIT MFI cmd
3615 + */
3616 +static int
3617 +megasas_issue_init_mfi(struct megasas_instance *instance)
3618  {
3619 -       u32 producer;
3620 -       u32 consumer;
3621         u32 context;
3622 +
3623         struct megasas_cmd *cmd;
3624 -       struct megasas_instance *instance = (struct megasas_instance *)instance_addr;
3625 -       unsigned long flags;
3626  
3627 -       /* If we have already declared adapter dead, donot complete cmds */
3628 -       if (instance->hw_crit_error)
3629 -               return;
3630 +       struct megasas_init_frame *init_frame;
3631 +       struct megasas_init_queue_info *initq_info;
3632 +       dma_addr_t init_frame_h;
3633 +       dma_addr_t initq_info_h;
3634  
3635 -       producer = *instance->producer;
3636 -       consumer = *instance->consumer;
3637 +       /*
3638 +        * Prepare a init frame. Note the init frame points to queue info
3639 +        * structure. Each frame has SGL allocated after first 64 bytes. For
3640 +        * this frame - since we don't need any SGL - we use SGL's space as
3641 +        * queue info structure
3642 +        *
3643 +        * We will not get a NULL command below. We just created the pool.
3644 +        */
3645 +       cmd = megasas_get_cmd(instance);
3646  
3647 -       while (consumer != producer) {
3648 -               context = instance->reply_queue[consumer];
3649 +       init_frame = (struct megasas_init_frame *)cmd->frame;
3650 +       initq_info = (struct megasas_init_queue_info *)
3651 +               ((unsigned long)init_frame + 64);
3652  
3653 -               cmd = instance->cmd_list[context];
3654 +       init_frame_h = cmd->frame_phys_addr;
3655 +       initq_info_h = init_frame_h + 64;
3656 +
3657 +       context = init_frame->context;
3658 +       memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
3659 +       memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
3660 +       init_frame->context = context;
3661 +
3662 +       initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
3663 +       initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
3664 +
3665 +       initq_info->producer_index_phys_addr_lo = instance->producer_h;
3666 +       initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
3667 +
3668 +       init_frame->cmd = MFI_CMD_INIT;
3669 +       init_frame->cmd_status = 0xFF;
3670 +       init_frame->queue_info_new_phys_addr_lo = initq_info_h;
3671 +
3672 +       init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
3673 +
3674 +       /*
3675 +        * disable the intr before firing the init frame to FW
3676 +        */
3677 +       instance->instancet->disable_intr(instance->reg_set);
3678 +
3679 +       /*
3680 +        * Issue the init frame in polled mode
3681 +        */
3682 +
3683 +       if (megasas_issue_polled(instance, cmd)) {
3684 +               printk(KERN_ERR "megasas: Failed to init firmware\n");
3685 +               megasas_return_cmd(instance, cmd);
3686 +               goto fail_fw_init;
3687 +       }
3688  
3689 -               megasas_complete_cmd(instance, cmd, DID_OK);
3690 +       megasas_return_cmd(instance, cmd);
3691  
3692 -               consumer++;
3693 -               if (consumer == (instance->max_fw_cmds + 1)) {
3694 -                       consumer = 0;
3695 -               }
3696 -       }
3697 +       return 0;
3698  
3699 -       *instance->consumer = producer;
3700 +fail_fw_init:
3701 +       return -EINVAL;
3702 +}
3703  
3704 -       /*
3705 -        * Check if we can restore can_queue
3706 -        */
3707 -       if (instance->flag & MEGASAS_FW_BUSY
3708 -               && time_after(jiffies, instance->last_time + 5 * HZ)
3709 -               && atomic_read(&instance->fw_outstanding) < 17) {
3710 +/**
3711 + * megasas_start_timer - Initializes a timer object
3712 + * @instance:          Adapter soft state
3713 + * @timer:             timer object to be initialized
3714 + * @fn:                        timer function
3715 + * @interval:          time interval between timer function call
3716 + */
3717 +static inline void
3718 +megasas_start_timer(struct megasas_instance *instance,
3719 +                       struct timer_list *timer,
3720 +                       void *fn, unsigned long interval)
3721 +{
3722 +       init_timer(timer);
3723 +       timer->expires = jiffies + interval;
3724 +       timer->data = (unsigned long)instance;
3725 +       timer->function = fn;
3726 +       add_timer(timer);
3727 +}
3728  
3729 -               spin_lock_irqsave(instance->host->host_lock, flags);
3730 -               instance->flag &= ~MEGASAS_FW_BUSY;
3731 -               instance->host->can_queue =
3732 -                               instance->max_fw_cmds - MEGASAS_INT_CMDS;
3733 +/**
3734 + * megasas_io_completion_timer - Timer fn
3735 + * @instance_addr:     Address of adapter soft state
3736 + *
3737 + * Schedules tasklet for cmd completion
3738 + * if poll_mode_io is set
3739 + */
3740 +static void
3741 +megasas_io_completion_timer(unsigned long instance_addr)
3742 +{
3743 +       struct megasas_instance *instance =
3744 +                       (struct megasas_instance *)instance_addr;
3745  
3746 -               spin_unlock_irqrestore(instance->host->host_lock, flags);
3747 -       }
3748 +       if (atomic_read(&instance->fw_outstanding))
3749 +               tasklet_schedule(&instance->isr_tasklet);
3750  
3751 +       /* Restart timer */
3752 +       if (poll_mode_io)
3753 +               mod_timer(&instance->io_completion_timer,
3754 +                       jiffies + MEGASAS_COMPLETION_TIMER_INTERVAL);
3755  }
3756  
3757  /**
3758 @@ -1893,22 +4444,24 @@ static int megasas_init_mfi(struct megas
3759         u32 reply_q_sz;
3760         u32 max_sectors_1;
3761         u32 max_sectors_2;
3762 +       u32 tmp_sectors;
3763         struct megasas_register_set __iomem *reg_set;
3764 -
3765 -       struct megasas_cmd *cmd;
3766         struct megasas_ctrl_info *ctrl_info;
3767 -
3768 -       struct megasas_init_frame *init_frame;
3769 -       struct megasas_init_queue_info *initq_info;
3770 -       dma_addr_t init_frame_h;
3771 -       dma_addr_t initq_info_h;
3772 -
3773         /*
3774          * Map the message registers
3775          */
3776 -       instance->base_addr = pci_resource_start(instance->pdev, 0);
3777 +       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
3778 +               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) ||
3779 +               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
3780 +               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
3781 +               instance->base_addr = pci_resource_start(instance->pdev, 1);
3782 +       } else {
3783 +               instance->base_addr = pci_resource_start(instance->pdev, 0);
3784 +       }
3785  
3786 -       if (pci_request_regions(instance->pdev, "megasas: LSI Logic")) {
3787 +       if (pci_request_selected_regions(instance->pdev,
3788 +                                        pci_select_bars(instance->pdev, IORESOURCE_MEM),
3789 +                                        "megasas: LSI")) {
3790                 printk(KERN_DEBUG "megasas: IO memory region busy!\n");
3791                 return -EBUSY;
3792         }
3793 @@ -1924,9 +4477,18 @@ static int megasas_init_mfi(struct megas
3794  
3795         switch(instance->pdev->device)
3796         {
3797 -               case PCI_DEVICE_ID_LSI_SAS1078R:        
3798 +               case PCI_DEVICE_ID_LSI_SAS1078R:
3799 +               case PCI_DEVICE_ID_LSI_SAS1078DE:
3800                         instance->instancet = &megasas_instance_template_ppc;
3801                         break;
3802 +               case PCI_DEVICE_ID_LSI_SAS1078GEN2:
3803 +               case PCI_DEVICE_ID_LSI_SAS0079GEN2:
3804 +                       instance->instancet = &megasas_instance_template_gen2;
3805 +                       break;
3806 +               case PCI_DEVICE_ID_LSI_SAS0073SKINNY:
3807 +               case PCI_DEVICE_ID_LSI_SAS0071SKINNY:
3808 +                       instance->instancet = &megasas_instance_template_skinny;
3809 +                       break;
3810                 case PCI_DEVICE_ID_LSI_SAS1064R:
3811                 case PCI_DEVICE_ID_DELL_PERC5:
3812                 default:
3813 @@ -1979,52 +4541,29 @@ static int megasas_init_mfi(struct megas
3814                 goto fail_reply_queue;
3815         }
3816  
3817 -       /*
3818 -        * Prepare a init frame. Note the init frame points to queue info
3819 -        * structure. Each frame has SGL allocated after first 64 bytes. For
3820 -        * this frame - since we don't need any SGL - we use SGL's space as
3821 -        * queue info structure
3822 -        *
3823 -        * We will not get a NULL command below. We just created the pool.
3824 -        */
3825 -       cmd = megasas_get_cmd(instance);
3826 -
3827 -       init_frame = (struct megasas_init_frame *)cmd->frame;
3828 -       initq_info = (struct megasas_init_queue_info *)
3829 -           ((unsigned long)init_frame + 64);
3830 -
3831 -       init_frame_h = cmd->frame_phys_addr;
3832 -       initq_info_h = init_frame_h + 64;
3833 -
3834 -       memset(init_frame, 0, MEGAMFI_FRAME_SIZE);
3835 -       memset(initq_info, 0, sizeof(struct megasas_init_queue_info));
3836 -
3837 -       initq_info->reply_queue_entries = instance->max_fw_cmds + 1;
3838 -       initq_info->reply_queue_start_phys_addr_lo = instance->reply_queue_h;
3839 -
3840 -       initq_info->producer_index_phys_addr_lo = instance->producer_h;
3841 -       initq_info->consumer_index_phys_addr_lo = instance->consumer_h;
3842 +       if ( megasas_check_cpx_support( instance ) == 0  )
3843 +               if ( megasas_init_cpx( instance ) )
3844 +                       printk("Error in initilizing cpx.\n");
3845  
3846 -       init_frame->cmd = MFI_CMD_INIT;
3847 -       init_frame->cmd_status = 0xFF;
3848 -       init_frame->queue_info_new_phys_addr_lo = initq_info_h;
3849 +       if (megasas_issue_init_mfi(instance))
3850 +               goto fail_fw_init;
3851  
3852 -       init_frame->data_xfer_len = sizeof(struct megasas_init_queue_info);
3853 +       instance->fw_support_ieee = 0; 
3854 +       instance->fw_support_ieee = (instance->instancet->read_fw_status_reg(reg_set) & 0x04000000); 
3855  
3856 -       /*
3857 -        * disable the intr before firing the init frame to FW
3858 -        */
3859 -       instance->instancet->disable_intr(instance->reg_set);
3860 +       printk("megasas_init_mfi: fw_support_ieee=%d", instance->fw_support_ieee);
3861 +       if (instance->fw_support_ieee)
3862 +               instance->flag_ieee = 1;
3863 +       
3864 +       /** for passthrough
3865 +       * the following function will get the PD LIST.
3866 +       */
3867  
3868 -       /*
3869 -        * Issue the init frame in polled mode
3870 -        */
3871 -       if (megasas_issue_polled(instance, cmd)) {
3872 -               printk(KERN_DEBUG "megasas: Failed to init firmware\n");
3873 -               goto fail_fw_init;
3874 -       }
3875 +       memset(instance->pd_list, 0, MEGASAS_MAX_PD * sizeof(struct megasas_pd_list));
3876 +       megasas_get_pd_list(instance);
3877  
3878 -       megasas_return_cmd(instance, cmd);
3879 +       memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
3880 +       megasas_get_ld_list(instance);
3881  
3882         ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);
3883  
3884 @@ -2037,17 +4576,21 @@ static int megasas_init_mfi(struct megas
3885          * Note that older firmwares ( < FW ver 30) didn't report information
3886          * to calculate max_sectors_1. So the number ended up as zero always.
3887          */
3888 +       tmp_sectors = 0;
3889         if (ctrl_info && !megasas_get_ctrl_info(instance, ctrl_info)) {
3890  
3891                 max_sectors_1 = (1 << ctrl_info->stripe_sz_ops.min) *
3892                     ctrl_info->max_strips_per_io;
3893                 max_sectors_2 = ctrl_info->max_request_size;
3894  
3895 -               instance->max_sectors_per_req = (max_sectors_1 < max_sectors_2)
3896 -                   ? max_sectors_1 : max_sectors_2;
3897 -       } else
3898 -               instance->max_sectors_per_req = instance->max_num_sge *
3899 -                   PAGE_SIZE / 512;
3900 +               tmp_sectors = min_t(u32, max_sectors_1 , max_sectors_2);
3901 +                instance->disableOnlineCtrlReset = ctrl_info->properties.OnOffProperties.disableOnlineCtrlReset;
3902 +       }
3903 +
3904 +       instance->max_sectors_per_req = instance->max_num_sge *
3905 +                                               PAGE_SIZE / 512;
3906 +       if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
3907 +               instance->max_sectors_per_req = tmp_sectors;
3908  
3909         kfree(ctrl_info);
3910  
3911 @@ -2055,12 +4598,17 @@ static int megasas_init_mfi(struct megas
3912         * Setup tasklet for cmd completion
3913         */
3914  
3915 -        tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
3916 -                        (unsigned long)instance);
3917 +       tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
3918 +               (unsigned long)instance);
3919 +
3920 +       /* Initialize the cmd completion timer */
3921 +       if (poll_mode_io)
3922 +               megasas_start_timer(instance, &instance->io_completion_timer,
3923 +                               megasas_io_completion_timer,
3924 +                               MEGASAS_COMPLETION_TIMER_INTERVAL);
3925         return 0;
3926  
3927        fail_fw_init:
3928 -       megasas_return_cmd(instance, cmd);
3929  
3930         pci_free_consistent(instance->pdev, reply_q_sz,
3931                             instance->reply_queue, instance->reply_queue_h);
3932 @@ -2072,7 +4620,8 @@ static int megasas_init_mfi(struct megas
3933         iounmap(instance->reg_set);
3934  
3935        fail_ioremap:
3936 -       pci_release_regions(instance->pdev);
3937 +       pci_release_selected_regions(instance->pdev,
3938 +                                    pci_select_bars(instance->pdev, IORESOURCE_MEM));
3939  
3940         return -EINVAL;
3941  }
3942 @@ -2092,7 +4641,10 @@ static void megasas_release_mfi(struct m
3943  
3944         iounmap(instance->reg_set);
3945  
3946 -       pci_release_regions(instance->pdev);
3947 +       megasas_remove_cpx( instance );
3948 +
3949 +       pci_release_selected_regions(instance->pdev,
3950 +                                    pci_select_bars(instance->pdev, IORESOURCE_MEM));
3951  }
3952  
3953  /**
3954 @@ -2140,6 +4692,7 @@ megasas_get_seq_num(struct megasas_insta
3955         dcmd->sge_count = 1;
3956         dcmd->flags = MFI_FRAME_DIR_READ;
3957         dcmd->timeout = 0;
3958 +       dcmd->pad_0 = 0;
3959         dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info);
3960         dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO;
3961         dcmd->sgl.sge32[0].phys_addr = el_info_h;
3962 @@ -2215,6 +4768,8 @@ megasas_register_aen(struct megasas_inst
3963                          * Previously issued event registration includes
3964                          * current request. Nothing to do.
3965                          */
3966 +                       printk(KERN_INFO "%s[%d]: already registered\n",
3967 +                               __FUNCTION__, instance->host->host_no);
3968                         return 0;
3969                 } else {
3970                         curr_aen.members.locale |= prev_aen.members.locale;
3971 @@ -2254,13 +4809,20 @@ megasas_register_aen(struct megasas_inst
3972         dcmd->sge_count = 1;
3973         dcmd->flags = MFI_FRAME_DIR_READ;
3974         dcmd->timeout = 0;
3975 +       dcmd->pad_0 = 0;
3976         dcmd->data_xfer_len = sizeof(struct megasas_evt_detail);
3977         dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
3978         dcmd->mbox.w[0] = seq_num;
3979 +        instance->last_seq_num = seq_num;
3980         dcmd->mbox.w[1] = curr_aen.word;
3981         dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h;
3982         dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail);
3983  
3984 +       if (instance->aen_cmd != NULL) {
3985 +               megasas_return_cmd(instance, cmd);
3986 +               return 0;
3987 +       }
3988 +
3989         /*
3990          * Store reference to the cmd used to register for AEN. When an
3991          * application wants us to register for AEN, we have to abort this
3992 @@ -2271,7 +4833,8 @@ megasas_register_aen(struct megasas_inst
3993         /*
3994          * Issue the aen registration frame
3995          */
3996 -       instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set);
3997 +       instance->instancet->fire_cmd(instance,
3998 +                       cmd->frame_phys_addr, 0, instance->reg_set);
3999  
4000         return 0;
4001  }
4002 @@ -2304,6 +4867,32 @@ static int megasas_start_aen(struct mega
4003                                     class_locale.word);
4004  }
4005  
4006 +static ssize_t
4007 +sysfs_max_sectors_read(struct kobject *kobj, struct bin_attribute *bin_attr,
4008 +                       char *buf, loff_t off, size_t count)
4009 +{
4010 +       struct device *dev = container_of(kobj, struct device, kobj);
4011 +
4012 +       struct Scsi_Host *host = class_to_shost(dev);
4013 +
4014 +       struct megasas_instance *instance =
4015 +                               (struct megasas_instance *)host->hostdata;
4016 +
4017 +       count = sprintf(buf,"%u\n", instance->max_sectors_per_req);
4018 +
4019 +       return count+1;
4020 +}
4021 +
4022 +static struct bin_attribute sysfs_max_sectors_attr = {
4023 +       .attr = {
4024 +               .name = "max_sectors",
4025 +               .mode = S_IRUSR|S_IRGRP|S_IROTH,
4026 +               .owner = THIS_MODULE,
4027 +       },
4028 +       .size = 7,
4029 +       .read = sysfs_max_sectors_read,
4030 +};
4031 +
4032  /**
4033   * megasas_io_attach - Attaches this driver to SCSI mid-layer
4034   * @instance:          Adapter soft state
4035 @@ -2311,17 +4900,48 @@ static int megasas_start_aen(struct mega
4036  static int megasas_io_attach(struct megasas_instance *instance)
4037  {
4038         struct Scsi_Host *host = instance->host;
4039 +       u32             error;
4040  
4041         /*
4042          * Export parameters required by SCSI mid-layer
4043          */
4044         host->irq = instance->pdev->irq;
4045         host->unique_id = instance->unique_id;
4046 -       host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS;
4047 +       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
4048 +               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
4049 +               host->can_queue =
4050 +                       instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS;
4051 +       } else
4052 +               host->can_queue =
4053 +                       instance->max_fw_cmds - MEGASAS_INT_CMDS;
4054         host->this_id = instance->init_id;
4055         host->sg_tablesize = instance->max_num_sge;
4056 +       
4057 +       if (instance->fw_support_ieee)
4058 +               instance->max_sectors_per_req = MEGASAS_MAX_SECTORS_IEEE;
4059 +       /*
4060 +        * Check if the module parameter value for max_sectors can be used
4061 +        */
4062 +       if (max_sectors && max_sectors < instance->max_sectors_per_req)
4063 +               instance->max_sectors_per_req = max_sectors;
4064 +       else {
4065 +               if (max_sectors) {
4066 +                       if (((instance->pdev->device ==
4067 +                               PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
4068 +                               (instance->pdev->device ==
4069 +                               PCI_DEVICE_ID_LSI_SAS0079GEN2)) &&
4070 +                               (max_sectors <= MEGASAS_MAX_SECTORS)) {
4071 +                                       instance->max_sectors_per_req = max_sectors;
4072 +                       } else {
4073 +                               printk(KERN_INFO "megasas: max_sectors should be > 0 and"
4074 +                                       "<= %d (or < 1MB for GEN2 controller)\n",
4075 +                                       instance->max_sectors_per_req);
4076 +                       }
4077 +               }
4078 +       }
4079 +
4080         host->max_sectors = instance->max_sectors_per_req;
4081 -       host->cmd_per_lun = 128;
4082 +       host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN;
4083         host->max_channel = MEGASAS_MAX_CHANNELS - 1;
4084         host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL;
4085         host->max_lun = MEGASAS_MAX_LUN;
4086 @@ -2335,11 +4955,50 @@ static int megasas_io_attach(struct mega
4087                 return -ENODEV;
4088         }
4089  
4090 +        /*
4091 +        * Create sysfs entries for module paramaters
4092 +        */
4093 +       error = sysfs_create_bin_file(&instance->host->shost_dev.kobj,
4094 +                       &sysfs_max_sectors_attr);
4095 +
4096 +       if (error) {
4097 +               printk(KERN_INFO "megasas: Error in creating the sysfs entry"
4098 +                               " max_sectors.\n");
4099 +               goto out_remove_host;
4100 +       }
4101 +
4102         /*
4103          * Trigger SCSI to scan our drives
4104          */
4105         scsi_scan_host(host);
4106         return 0;
4107 +
4108 +out_remove_host:
4109 +        scsi_remove_host(host);
4110 +        return error;
4111 +
4112 +}
4113 +
4114 +static int
4115 +megasas_set_dma_mask(struct pci_dev *pdev)
4116 +{
4117 +       /*
4118 +        * All our contollers are capable of performing 64-bit DMA
4119 +        */
4120 +       if (IS_DMA64) {
4121 +               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
4122 +
4123 +                       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
4124 +                               goto fail_set_dma_mask;
4125 +               }
4126 +       } else {
4127 +               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
4128 +                       goto fail_set_dma_mask;
4129 +       }
4130 +       return 0;
4131 +
4132 +fail_set_dma_mask:
4133 +       return 1;
4134  }
4135  
4136  /**
4137 @@ -2375,19 +5034,8 @@ megasas_probe_one(struct pci_dev *pdev, 
4138  
4139         pci_set_master(pdev);
4140  
4141 -       /*
4142 -        * All our contollers are capable of performing 64-bit DMA
4143 -        */
4144 -       if (IS_DMA64) {
4145 -               if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
4146 -
4147 -                       if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4148 -                               goto fail_set_dma_mask;
4149 -               }
4150 -       } else {
4151 -               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0)
4152 -                       goto fail_set_dma_mask;
4153 -       }
4154 +       if (megasas_set_dma_mask(pdev))
4155 +               goto fail_set_dma_mask;
4156  
4157         host = scsi_host_alloc(&megasas_template,
4158                                sizeof(struct megasas_instance));
4159 @@ -2399,6 +5047,7 @@ megasas_probe_one(struct pci_dev *pdev, 
4160  
4161         instance = (struct megasas_instance *)host->hostdata;
4162         memset(instance, 0, sizeof(*instance));
4163 +       atomic_set( &instance->fw_reset_no_pci_access, 0 );
4164  
4165         instance->producer = pci_alloc_consistent(pdev, sizeof(u32),
4166                                                   &instance->producer_h);
4167 @@ -2413,6 +5062,11 @@ megasas_probe_one(struct pci_dev *pdev, 
4168  
4169         *instance->producer = 0;
4170         *instance->consumer = 0;
4171 +       instance->flag_ieee = 0;
4172 +       instance->ev = NULL;
4173 +       instance->issuepend_done = 1;
4174 +       instance->adprecovery = MEGASAS_HBA_OPERATIONAL;
4175 +       megasas_poll_wait_aen = 0;      
4176  
4177         instance->evt_detail = pci_alloc_consistent(pdev,
4178                                                     sizeof(struct
4179 @@ -2429,6 +5083,7 @@ megasas_probe_one(struct pci_dev *pdev, 
4180          * Initialize locks and queues
4181          */
4182         INIT_LIST_HEAD(&instance->cmd_pool);
4183 +       INIT_LIST_HEAD(&instance->internal_reset_pending_q);
4184  
4185         atomic_set(&instance->fw_outstanding,0);
4186  
4187 @@ -2436,9 +5091,12 @@ megasas_probe_one(struct pci_dev *pdev, 
4188         init_waitqueue_head(&instance->abort_cmd_wait_q);
4189  
4190         spin_lock_init(&instance->cmd_pool_lock);
4191 +       spin_lock_init(&instance->hba_lock);
4192 +
4193 +       spin_lock_init(&instance->completion_lock);
4194 +       spin_lock_init(&poll_aen_lock);
4195  
4196 -       sema_init(&instance->aen_mutex, 1);
4197 -       sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
4198 +       mutex_init(&instance->aen_mutex);
4199  
4200         /*
4201          * Initialize PCI related and misc parameters
4202 @@ -2448,9 +5106,20 @@ megasas_probe_one(struct pci_dev *pdev, 
4203         instance->unique_id = pdev->bus->number << 8 | pdev->devfn;
4204         instance->init_id = MEGASAS_DEFAULT_INIT_ID;
4205  
4206 +       if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) ||
4207 +               (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) {
4208 +               instance->flag_ieee = 1;
4209 +               sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS);
4210 +       } else
4211 +               sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS);
4212 +
4213         megasas_dbg_lvl = 0;
4214         instance->flag = 0;
4215 +       instance->unload = 1;
4216         instance->last_time = 0;
4217 +       instance->disableOnlineCtrlReset = 1;
4218 +
4219 +       INIT_WORK(&instance->work_init, process_fw_state_change_wq);
4220  
4221         /*
4222          * Initialize MFI Firmware
4223 @@ -2495,6 +5164,7 @@ megasas_probe_one(struct pci_dev *pdev, 
4224         if (megasas_io_attach(instance))
4225                 goto fail_io_attach;
4226  
4227 +       instance->unload = 0;
4228         return 0;
4229  
4230        fail_start_aen:
4231 @@ -2541,83 +5211,266 @@ static void megasas_flush_cache(struct m
4232         struct megasas_cmd *cmd;
4233         struct megasas_dcmd_frame *dcmd;
4234  
4235 -       cmd = megasas_get_cmd(instance);
4236 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
4237 +               return;
4238 +
4239 +       cmd = megasas_get_cmd(instance);
4240 +
4241 +       if (!cmd)
4242 +               return;
4243 +
4244 +       dcmd = &cmd->frame->dcmd;
4245 +
4246 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4247 +
4248 +       dcmd->cmd = MFI_CMD_DCMD;
4249 +       dcmd->cmd_status = 0x0;
4250 +       dcmd->sge_count = 0;
4251 +       dcmd->flags = MFI_FRAME_DIR_NONE;
4252 +       dcmd->timeout = 0;
4253 +       dcmd->pad_0 = 0;
4254 +       dcmd->data_xfer_len = 0;
4255 +       dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
4256 +       dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
4257 +
4258 +       megasas_issue_blocked_cmd(instance, cmd);
4259 +
4260 +       megasas_return_cmd(instance, cmd);
4261 +
4262 +       return;
4263 +}
4264 +
4265 +/**
4266 + * megasas_shutdown_controller -       Instructs FW to shutdown the controller
4267 + * @instance:                          Adapter soft state
4268 + * @opcode:                            Shutdown/Hibernate
4269 + */
4270 +static void megasas_shutdown_controller(struct megasas_instance *instance,
4271 +                                       u32 opcode)
4272 +{
4273 +       struct megasas_cmd *cmd;
4274 +       struct megasas_dcmd_frame *dcmd;
4275 +
4276 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR)
4277 +               return;
4278 +
4279 +       cmd = megasas_get_cmd(instance);
4280 +
4281 +       if (!cmd)
4282 +               return;
4283 +
4284 +       if (instance->aen_cmd)
4285 +               megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
4286 +
4287 +       dcmd = &cmd->frame->dcmd;
4288 +
4289 +       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4290 +
4291 +       dcmd->cmd = MFI_CMD_DCMD;
4292 +       dcmd->cmd_status = 0x0;
4293 +       dcmd->sge_count = 0;
4294 +       dcmd->flags = MFI_FRAME_DIR_NONE;
4295 +       dcmd->timeout = 0;
4296 +       dcmd->pad_0 = 0;
4297 +       dcmd->data_xfer_len = 0;
4298 +       dcmd->opcode = opcode;
4299 +
4300 +       megasas_issue_blocked_cmd(instance, cmd);
4301 +
4302 +       megasas_return_cmd(instance, cmd);
4303 +
4304 +       return;
4305 +}
4306 +
4307 +#ifdef CONFIG_PM
4308 +/**
4309 + * megasas_suspend -   driver suspend entry point
4310 + * @pdev:              PCI device structure
4311 + * @state:             PCI power state to suspend routine
4312 + */
4313 +static int
4314 +megasas_suspend(struct pci_dev *pdev, pm_message_t state)
4315 +{
4316 +       struct Scsi_Host *host;
4317 +       struct megasas_instance *instance;
4318 +
4319 +       instance = pci_get_drvdata(pdev);
4320 +       host = instance->host;
4321 +       instance->unload = 1;
4322 +
4323 +       if (poll_mode_io)
4324 +               del_timer_sync(&instance->io_completion_timer);
4325 +
4326 +       megasas_flush_cache(instance);
4327 +       megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN);
4328 +
4329 +       /* cancel the delayed work if this work still in queue */
4330 +       if (instance->ev != NULL) {
4331 +               struct megasas_aen_event *ev = instance->ev;
4332 +               cancel_delayed_work(
4333 +                       (struct delayed_work *)&ev->hotplug_work);
4334 +               flush_scheduled_work();
4335 +               instance->ev = NULL;
4336 +       }
4337 +
4338 +       tasklet_kill(&instance->isr_tasklet);
4339 +
4340 +       pci_set_drvdata(instance->pdev, instance);
4341 +       instance->instancet->disable_intr(instance->reg_set);
4342 +       free_irq(instance->pdev->irq, instance);
4343 +
4344 +       pci_save_state(pdev);
4345 +       pci_disable_device(pdev);
4346 +
4347 +       pci_set_power_state(pdev, pci_choose_state(pdev, state));
4348 +
4349 +       return 0;
4350 +}
4351 +
4352 +/**
4353 + * megasas_resume-      driver resume entry point
4354 + * @pdev:               PCI device structure
4355 + */
4356 +static int
4357 +megasas_resume(struct pci_dev *pdev)
4358 +{
4359 +       int rval;
4360 +       struct Scsi_Host *host;
4361 +       struct megasas_instance *instance;
4362 +
4363 +       instance = pci_get_drvdata(pdev);
4364 +       host = instance->host;
4365 +       pci_set_power_state(pdev, PCI_D0);
4366 +       pci_enable_wake(pdev, PCI_D0, 0);
4367 +       pci_restore_state(pdev);
4368 +
4369 +       /*
4370 +        * PCI prepping: enable device set bus mastering and dma mask
4371 +        */
4372 +       rval = pci_enable_device(pdev);
4373 +
4374 +       if (rval) {
4375 +               printk(KERN_ERR "megasas: Enable device failed\n");
4376 +               return rval;
4377 +       }
4378 +
4379 +       pci_set_master(pdev);
4380 +
4381 +       if (megasas_set_dma_mask(pdev))
4382 +               goto fail_set_dma_mask;
4383  
4384 -       if (!cmd)
4385 -               return;
4386 +       /*
4387 +        * Initialize MFI Firmware
4388 +        */
4389  
4390 -       dcmd = &cmd->frame->dcmd;
4391 +       *instance->producer = 0;
4392 +       *instance->consumer = 0;
4393  
4394 -       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4395 +       atomic_set(&instance->fw_outstanding, 0);
4396  
4397 -       dcmd->cmd = MFI_CMD_DCMD;
4398 -       dcmd->cmd_status = 0x0;
4399 -       dcmd->sge_count = 0;
4400 -       dcmd->flags = MFI_FRAME_DIR_NONE;
4401 -       dcmd->timeout = 0;
4402 -       dcmd->data_xfer_len = 0;
4403 -       dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH;
4404 -       dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
4405 +       /*
4406 +        * We expect the FW state to be READY
4407 +        */
4408 +       if (megasas_transition_to_ready(instance))
4409 +               goto fail_ready_state;
4410  
4411 -       megasas_issue_blocked_cmd(instance, cmd);
4412 +       if ( megasas_check_cpx_support( instance ) == 0  ){
4413 +               if ( megasas_send_cpx_queue_data( instance ) ){
4414 +                       printk("megasas: Sending cpx queue data to FW failed.\n");
4415 +                       megasas_remove_cpx(instance);
4416 +               }else
4417 +                       instance->cpx_request_queue->consumer_idx = instance->cpx_request_queue->producer_idx = 0;
4418 +       }
4419  
4420 -       megasas_return_cmd(instance, cmd);
4421 +       if (megasas_issue_init_mfi(instance))
4422 +               goto fail_init_mfi;
4423  
4424 -       return;
4425 -}
4426 +       tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
4427 +                       (unsigned long)instance);
4428  
4429 -/**
4430 - * megasas_shutdown_controller -       Instructs FW to shutdown the controller
4431 - * @instance:                          Adapter soft state
4432 - */
4433 -static void megasas_shutdown_controller(struct megasas_instance *instance)
4434 -{
4435 -       struct megasas_cmd *cmd;
4436 -       struct megasas_dcmd_frame *dcmd;
4437 +       /*
4438 +        * Register IRQ
4439 +        */
4440 +       if (request_irq(pdev->irq, megasas_isr, IRQF_SHARED,
4441 +               "megasas", instance)) {
4442 +               printk(KERN_ERR "megasas: Failed to register IRQ\n");
4443 +               goto fail_irq;
4444 +       }
4445  
4446 -       cmd = megasas_get_cmd(instance);
4447 +       instance->instancet->enable_intr(instance->reg_set);
4448  
4449 -       if (!cmd)
4450 -               return;
4451 +       /*
4452 +        * Initiate AEN (Asynchronous Event Notification)
4453 +        */
4454 +       if (megasas_start_aen(instance))
4455 +               printk(KERN_ERR "megasas: Start AEN failed\n");
4456  
4457 -       if (instance->aen_cmd)
4458 -               megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd);
4459 +       /* Initialize the cmd completion timer */
4460 +       if (poll_mode_io)
4461 +               megasas_start_timer(instance, &instance->io_completion_timer,
4462 +                               megasas_io_completion_timer,
4463 +                               MEGASAS_COMPLETION_TIMER_INTERVAL);
4464 +       instance->unload = 0;
4465  
4466 -       dcmd = &cmd->frame->dcmd;
4467 +       return 0;
4468  
4469 -       memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
4470 +fail_irq:
4471 +fail_init_mfi:
4472 +       if (instance->evt_detail)
4473 +               pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
4474 +                               instance->evt_detail,
4475 +                               instance->evt_detail_h);
4476  
4477 -       dcmd->cmd = MFI_CMD_DCMD;
4478 -       dcmd->cmd_status = 0x0;
4479 -       dcmd->sge_count = 0;
4480 -       dcmd->flags = MFI_FRAME_DIR_NONE;
4481 -       dcmd->timeout = 0;
4482 -       dcmd->data_xfer_len = 0;
4483 -       dcmd->opcode = MR_DCMD_CTRL_SHUTDOWN;
4484 +       if (instance->producer)
4485 +               pci_free_consistent(pdev, sizeof(u32), instance->producer,
4486 +                               instance->producer_h);
4487 +       if (instance->consumer)
4488 +               pci_free_consistent(pdev, sizeof(u32), instance->consumer,
4489 +                               instance->consumer_h);
4490 +       scsi_host_put(host);
4491  
4492 -       megasas_issue_blocked_cmd(instance, cmd);
4493 +fail_set_dma_mask:
4494 +fail_ready_state:
4495  
4496 -       megasas_return_cmd(instance, cmd);
4497 +       pci_disable_device(pdev);
4498  
4499 -       return;
4500 +       return -ENODEV;
4501  }
4502 +#else
4503 +#define megasas_suspend        NULL
4504 +#define megasas_resume NULL
4505 +#endif
4506  
4507  /**
4508   * megasas_detach_one -        PCI hot"un"plug entry point
4509   * @pdev:              PCI device structure
4510   */
4511 -static void megasas_detach_one(struct pci_dev *pdev)
4512 +static void __devexit megasas_detach_one(struct pci_dev *pdev)
4513  {
4514         int i;
4515         struct Scsi_Host *host;
4516         struct megasas_instance *instance;
4517  
4518         instance = pci_get_drvdata(pdev);
4519 +       instance->unload = 1;
4520         host = instance->host;
4521  
4522 +       if (poll_mode_io)
4523 +               del_timer_sync(&instance->io_completion_timer);
4524 +
4525         scsi_remove_host(instance->host);
4526         megasas_flush_cache(instance);
4527 -       megasas_shutdown_controller(instance);
4528 +       megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
4529 +
4530 +       /* cancel the delayed work if this work still in queue*/
4531 +       if (instance->ev != NULL) {
4532 +               struct megasas_aen_event *ev = instance->ev;
4533 +               cancel_delayed_work(
4534 +                       (struct delayed_work *)&ev->hotplug_work);
4535 +               flush_scheduled_work();
4536 +               instance->ev = NULL;
4537 +       }
4538 +
4539         tasklet_kill(&instance->isr_tasklet);
4540  
4541         /*
4542 @@ -2666,7 +5519,9 @@ static void megasas_detach_one(struct pc
4543  static void megasas_shutdown(struct pci_dev *pdev)
4544  {
4545         struct megasas_instance *instance = pci_get_drvdata(pdev);
4546 +       instance->unload = 1;
4547         megasas_flush_cache(instance);
4548 +       megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
4549  }
4550  
4551  /**
4552 @@ -2674,6 +5529,7 @@ static void megasas_shutdown(struct pci_
4553   */
4554  static int megasas_mgmt_open(struct inode *inode, struct file *filep)
4555  {
4556 +       cycle_kernel_lock();
4557         /*
4558          * Allow only those users with admin rights
4559          */
4560 @@ -2722,6 +5578,23 @@ static int megasas_mgmt_fasync(int fd, s
4561  }
4562  
4563  /**
4564 + * megasas_mgmt_poll -  char node "poll" entry point
4565 + * */
4566 +static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait)
4567 +{
4568 +       unsigned int mask;
4569 +       unsigned long flags;
4570 +       poll_wait(file, &megasas_poll_wait, wait);
4571 +       spin_lock_irqsave(&poll_aen_lock, flags);
4572 +       if (megasas_poll_wait_aen)
4573 +               mask =   (POLLIN | POLLRDNORM);
4574 +       else
4575 +               mask = 0;
4576 +       spin_unlock_irqrestore(&poll_aen_lock, flags);
4577 +       return mask;
4578 +}
4579 +
4580 +/**
4581   * megasas_mgmt_fw_ioctl -     Issues management ioctls to FW
4582   * @instance:                  Adapter soft state
4583   * @argp:                      User's ioctl packet
4584 @@ -2738,7 +5611,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4585         int error = 0, i;
4586         void *sense = NULL;
4587         dma_addr_t sense_handle;
4588 -       u32 *sense_ptr;
4589 +       unsigned long *sense_ptr;
4590  
4591         memset(kbuff_arr, 0, sizeof(kbuff_arr));
4592  
4593 @@ -2762,6 +5635,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4594          */
4595         memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE);
4596         cmd->frame->hdr.context = cmd->index;
4597 +       cmd->frame->hdr.pad_0 = 0;
4598  
4599         /*
4600          * The management interface between applications and the fw uses
4601 @@ -2815,7 +5689,7 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4602                 }
4603  
4604                 sense_ptr =
4605 -                   (u32 *) ((unsigned long)cmd->frame + ioc->sense_off);
4606 +               (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off);
4607                 *sense_ptr = sense_handle;
4608         }
4609  
4610 @@ -2843,14 +5717,16 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4611          */
4612         if (ioc->sense_len) {
4613                 /*
4614 -                * sense_ptr points to the location that has the user
4615 +                * sense_buff points to the location that has the user
4616                  * sense buffer address
4617                  */
4618 -               sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw +
4619 -                                    ioc->sense_off);
4620 +               sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw +
4621 +                               ioc->sense_off);
4622  
4623                 if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)),
4624                                  sense, ioc->sense_len)) {
4625 +                       printk(KERN_ERR "megasas: Failed to copy out to user "
4626 +                                       "sense data\n");
4627                         error = -EFAULT;
4628                         goto out;
4629                 }
4630 @@ -2881,20 +5757,6 @@ megasas_mgmt_fw_ioctl(struct megasas_ins
4631         return error;
4632  }
4633  
4634 -static struct megasas_instance *megasas_lookup_instance(u16 host_no)
4635 -{
4636 -       int i;
4637 -
4638 -       for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4639 -
4640 -               if ((megasas_mgmt_info.instance[i]) &&
4641 -                   (megasas_mgmt_info.instance[i]->host->host_no == host_no))
4642 -                       return megasas_mgmt_info.instance[i];
4643 -       }
4644 -
4645 -       return NULL;
4646 -}
4647 -
4648  static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg)
4649  {
4650         struct megasas_iocpacket __user *user_ioc =
4651 @@ -2902,6 +5764,9 @@ static int megasas_mgmt_ioctl_fw(struct 
4652         struct megasas_iocpacket *ioc;
4653         struct megasas_instance *instance;
4654         int error;
4655 +       int i;
4656 +       unsigned long flags;
4657 +       u32 wait_time = MEGASAS_RESET_WAIT_TIME;
4658  
4659         ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
4660         if (!ioc)
4661 @@ -2918,6 +5783,17 @@ static int megasas_mgmt_ioctl_fw(struct 
4662                 goto out_kfree_ioc;
4663         }
4664  
4665 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
4666 +               printk("Controller in crit error\n");
4667 +               error = -ENODEV;
4668 +               goto out_kfree_ioc;
4669 +       }
4670 +
4671 +       if (instance->unload == 1) {
4672 +               error = -ENODEV;
4673 +               goto out_kfree_ioc;
4674 +       }
4675 +
4676         /*
4677          * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds
4678          */
4679 @@ -2925,6 +5801,35 @@ static int megasas_mgmt_ioctl_fw(struct 
4680                 error = -ERESTARTSYS;
4681                 goto out_kfree_ioc;
4682         }
4683 +       
4684 +       // If HBA is undergoing a reset recovery, wait for that to complete
4685 +       // before issuing this command
4686 +
4687 +       for (i = 0; i < wait_time; i++) {
4688 +
4689 +               spin_lock_irqsave(&instance->hba_lock, flags);
4690 +               if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
4691 +                       spin_unlock_irqrestore(&instance->hba_lock, flags);
4692 +                       break;
4693 +               }
4694 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
4695 +
4696 +               if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
4697 +                       printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
4698 +               }
4699 +
4700 +               msleep(1000);
4701 +       }
4702 +
4703 +       spin_lock_irqsave(&instance->hba_lock, flags);
4704 +       if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
4705 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
4706 +               printk("megaraid_sas: %s timed out while waiting for HBA to recover.\n", __FUNCTION__);
4707 +               error = -ENODEV;
4708 +               goto out_kfree_ioc;
4709 +       }
4710 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
4711 +
4712         error = megasas_mgmt_fw_ioctl(instance, user_ioc, ioc);
4713         up(&instance->ioctl_sem);
4714  
4715 @@ -2938,6 +5843,9 @@ static int megasas_mgmt_ioctl_aen(struct
4716         struct megasas_instance *instance;
4717         struct megasas_aen aen;
4718         int error;
4719 +       int i;
4720 +       unsigned long flags;
4721 +       u32 wait_time = MEGASAS_RESET_WAIT_TIME;
4722  
4723         if (file->private_data != file) {
4724                 printk(KERN_DEBUG "megasas: fasync_helper was not "
4725 @@ -2953,10 +5861,41 @@ static int megasas_mgmt_ioctl_aen(struct
4726         if (!instance)
4727                 return -ENODEV;
4728  
4729 -       down(&instance->aen_mutex);
4730 +       if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) {
4731 +               return -ENODEV;
4732 +       }
4733 +
4734 +       if (instance->unload == 1) {
4735 +               return -ENODEV;
4736 +       }
4737 +       for (i = 0; i < wait_time; i++) {
4738 +
4739 +               spin_lock_irqsave(&instance->hba_lock, flags);
4740 +               if (instance->adprecovery == MEGASAS_HBA_OPERATIONAL) {
4741 +                       spin_unlock_irqrestore(&instance->hba_lock, flags);
4742 +                       break;
4743 +               }
4744 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
4745 +
4746 +               if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) {
4747 +                       printk(KERN_NOTICE "megasas: waiting for controller reset to finish\n");
4748 +               }
4749 +
4750 +               msleep(1000);
4751 +       }
4752 +
4753 +       spin_lock_irqsave(&instance->hba_lock, flags);
4754 +       if (instance->adprecovery != MEGASAS_HBA_OPERATIONAL) {
4755 +               spin_unlock_irqrestore(&instance->hba_lock, flags);
4756 +               printk("megaraid_sas: %s timed out while waiting for HBA to recover.\n", __FUNCTION__);
4757 +               return -ENODEV;
4758 +       }
4759 +       spin_unlock_irqrestore(&instance->hba_lock, flags);
4760 +
4761 +       mutex_lock(&instance->aen_mutex);
4762         error = megasas_register_aen(instance, aen.seq_num,
4763                                      aen.class_locale_word);
4764 -       up(&instance->aen_mutex);
4765 +       mutex_unlock(&instance->aen_mutex);
4766         return error;
4767  }
4768  
4769 @@ -2986,6 +5925,8 @@ static int megasas_mgmt_compat_ioctl_fw(
4770             compat_alloc_user_space(sizeof(struct megasas_iocpacket));
4771         int i;
4772         int error = 0;
4773 +       compat_uptr_t ptr;
4774 +       u8 *raw_ptr;
4775  
4776         if (clear_user(ioc, sizeof(*ioc)))
4777                 return -EFAULT;
4778 @@ -2998,9 +5939,14 @@ static int megasas_mgmt_compat_ioctl_fw(
4779             copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32)))
4780                 return -EFAULT;
4781  
4782 -       for (i = 0; i < MAX_IOCTL_SGE; i++) {
4783 -               compat_uptr_t ptr;
4784 +       if (ioc->sense_len) {
4785 +               raw_ptr = ioc->frame.raw + ioc->sense_off;
4786 +               if (get_user(ptr, (compat_uptr_t *)raw_ptr) ||
4787 +                   put_user(ptr, (unsigned long *)raw_ptr))
4788 +                       return -EFAULT;
4789 +       }
4790  
4791 +       for (i = 0; i < MAX_IOCTL_SGE; i++) {
4792                 if (get_user(ptr, &cioc->sgl[i].iov_base) ||
4793                     put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) ||
4794                     copy_in_user(&ioc->sgl[i].iov_len,
4795 @@ -3042,6 +5988,7 @@ static const struct file_operations mega
4796         .release = megasas_mgmt_release,
4797         .fasync = megasas_mgmt_fasync,
4798         .unlocked_ioctl = megasas_mgmt_ioctl,
4799 +       .poll = megasas_mgmt_poll,
4800  #ifdef CONFIG_COMPAT
4801         .compat_ioctl = megasas_mgmt_compat_ioctl,
4802  #endif
4803 @@ -3056,6 +6003,8 @@ static struct pci_driver megasas_pci_dri
4804         .id_table = megasas_pci_table,
4805         .probe = megasas_probe_one,
4806         .remove = __devexit_p(megasas_detach_one),
4807 +       .suspend = megasas_suspend,
4808 +       .resume = megasas_resume,
4809         .shutdown = megasas_shutdown,
4810  };
4811  
4812 @@ -3081,9 +6030,27 @@ static DRIVER_ATTR(release_date, S_IRUGO
4813                    NULL);
4814  
4815  static ssize_t
4816 +megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf)
4817 +{
4818 +       return sprintf(buf, "%u\n", support_poll_for_event);
4819 +}
4820 +
4821 +static DRIVER_ATTR(support_poll_for_event, S_IRUGO,
4822 +                       megasas_sysfs_show_support_poll_for_event, NULL);
4823 +
4824 +static ssize_t
4825 +megasas_sysfs_show_support_device_change(struct device_driver *dd, char *buf)
4826 +{
4827 +       return sprintf(buf, "%u\n", support_device_change);
4828 +}
4829 +
4830 +static DRIVER_ATTR(support_device_change, S_IRUGO,
4831 +                       megasas_sysfs_show_support_device_change, NULL);
4832 +
4833 +static ssize_t
4834  megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf)
4835  {
4836 -       return sprintf(buf,"%u",megasas_dbg_lvl);
4837 +       return sprintf(buf, "%u\n", megasas_dbg_lvl);
4838  }
4839  
4840  static ssize_t
4841 @@ -3097,8 +6064,262 @@ megasas_sysfs_set_dbg_lvl(struct device_
4842         return retval;
4843  }
4844  
4845 -static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl,
4846 -                  megasas_sysfs_set_dbg_lvl);
4847 +static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
4848 +               megasas_sysfs_set_dbg_lvl);
4849 +
4850 +static ssize_t
4851 +megasas_sysfs_show_poll_mode_io(struct device_driver *dd, char *buf)
4852 +{
4853 +       return sprintf(buf, "%u\n", poll_mode_io);
4854 +}
4855 +
4856 +static ssize_t
4857 +megasas_sysfs_set_poll_mode_io(struct device_driver *dd,
4858 +                               const char *buf, size_t count)
4859 +{
4860 +       int retval = count;
4861 +       int tmp = poll_mode_io;
4862 +       int i;
4863 +       struct megasas_instance *instance;
4864 +
4865 +       if (sscanf(buf, "%u", &poll_mode_io) < 1) {
4866 +               printk(KERN_ERR "megasas: could not set poll_mode_io\n");
4867 +               retval = -EINVAL;
4868 +       }
4869 +
4870 +       /*
4871 +        * Check if poll_mode_io is already set or is same as previous value
4872 +        */
4873 +       if ((tmp && poll_mode_io) || (tmp == poll_mode_io))
4874 +               goto out;
4875 +
4876 +       if (poll_mode_io) {
4877 +               /*
4878 +                * Start timers for all adapters
4879 +                */
4880 +               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4881 +                       instance = megasas_mgmt_info.instance[i];
4882 +                       if (instance) {
4883 +                               megasas_start_timer(instance,
4884 +                                       &instance->io_completion_timer,
4885 +                                       megasas_io_completion_timer,
4886 +                                       MEGASAS_COMPLETION_TIMER_INTERVAL);
4887 +                       }
4888 +               }
4889 +       } else {
4890 +               /*
4891 +                * Delete timers for all adapters
4892 +                */
4893 +               for (i = 0; i < megasas_mgmt_info.max_index; i++) {
4894 +                       instance = megasas_mgmt_info.instance[i];
4895 +                       if (instance)
4896 +                               del_timer_sync(&instance->io_completion_timer);
4897 +               }
4898 +       }
4899 +
4900 +out:
4901 +       return retval;
4902 +}
4903 +
4904 +static void
4905 +megasas_aen_polling(struct work_struct *work)
4906 +{
4907 +       struct  Scsi_Host *host;
4908 +       struct  scsi_device *sdev1;
4909 +       u16     pd_index = 0;
4910 +       u16     ld_index = 0;
4911 +
4912 +       struct megasas_aen_event *ev =
4913 +               container_of(work, struct megasas_aen_event, hotplug_work);
4914 +       struct megasas_instance *instance = ev->instance;
4915 +       union megasas_evt_class_locale class_locale;
4916 +       int     i, j, doscan = 0;
4917 +       u32 seq_num;
4918 +       int error;
4919 +
4920 +       if (!instance) {
4921 +               printk(KERN_ERR "invalid instance!\n");
4922 +               kfree(ev);
4923 +               return;
4924 +       }
4925 +       instance->ev = NULL;
4926 +       host = instance->host;
4927 +       if (instance->evt_detail) {
4928 +
4929 +               switch (instance->evt_detail->code) {
4930 +               case MR_EVT_PD_INSERTED:
4931 +                       if(megasas_get_pd_list(instance) == 0) {
4932 +                       
4933 +                       for (i=0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
4934 +                               for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
4935 +                                       pd_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4936 +                                       sdev1 = scsi_device_lookup(host, i, j, 0);
4937 +                                       if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
4938 +                                               if (!sdev1) {
4939 +                                                       scsi_add_device(host, i, j, 0);
4940 +                                               }
4941 +                                       } 
4942 +                                       if (sdev1) {
4943 +                                               scsi_device_put(sdev1);
4944 +                                       }
4945 +                                       
4946 +                               }
4947 +                       }
4948 +                       }
4949 +                       doscan = 0;
4950 +                       break;
4951 +               
4952 +               case MR_EVT_PD_REMOVED:
4953 +                       if(megasas_get_pd_list(instance) == 0) {
4954 +                       megasas_get_pd_list(instance);
4955 +                       for (i=0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
4956 +                               for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
4957 +                                       pd_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4958 +                                       sdev1 = scsi_device_lookup(host, i, j, 0);
4959 +                                       if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
4960 +                                               if (sdev1) {
4961 +                                                       scsi_device_put(sdev1);
4962 +                                               }
4963 +                                       } else {
4964 +                                               if (sdev1) {
4965 +                                                       scsi_remove_device(sdev1);
4966 +                                                       scsi_device_put(sdev1);
4967 +                                               }
4968 +                                       }
4969 +                               }
4970 +                       
4971 +                       }
4972 +                       }
4973 +                       doscan = 0;
4974 +                       break;
4975 +
4976 +               case MR_EVT_LD_OFFLINE:
4977 +               case MR_EVT_CFG_CLEARED:
4978 +               case MR_EVT_LD_DELETED:
4979 +                       megasas_get_ld_list(instance);
4980 +                       for (i=0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
4981 +                               for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
4982 +                                       ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
4983 +                                       sdev1 = scsi_device_lookup(host, i+MEGASAS_MAX_LD_CHANNELS, j, 0);
4984 +                                       if (instance->ld_ids[ld_index] != 0xff) {
4985 +                                               if (sdev1) {
4986 +                                                       scsi_device_put(sdev1);
4987 +                                               }
4988 +                                               
4989 +                                       } else {
4990 +                                               if (sdev1) {
4991 +                                                       scsi_remove_device(sdev1);
4992 +                                                       scsi_device_put(sdev1);
4993 +                                               }
4994 +                                       }
4995 +                               }
4996 +                       }
4997 +                       doscan = 0;
4998 +                       break;          
4999 +               case MR_EVT_LD_CREATED:
5000 +                       megasas_get_ld_list(instance);
5001 +                       for (i=0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5002 +                               for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5003 +                                       ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5004 +                                       sdev1 = scsi_device_lookup(host, i+MEGASAS_MAX_LD_CHANNELS, j, 0);
5005 +                                       if (instance->ld_ids[ld_index] != 0xff) {
5006 +                                               if (!sdev1) {
5007 +                                                       scsi_add_device(host, i+2, j, 0);
5008 +                                               }
5009 +                                       } 
5010 +                                       if (sdev1) {
5011 +                                               scsi_device_put(sdev1);
5012 +                                       }
5013 +                               }
5014 +                       }               
5015 +                       doscan = 0;
5016 +                       break;
5017 +               case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
5018 +               case MR_EVT_FOREIGN_CFG_IMPORTED: 
5019 +               case MR_EVT_LD_STATE_CHANGE:
5020 +                       doscan = 1;
5021 +                       break;
5022 +               default:
5023 +                       doscan = 0;
5024 +                       break;
5025 +               }
5026 +       } else {
5027 +               printk(KERN_ERR "invalid evt_detail!\n");
5028 +               kfree(ev);
5029 +               return;
5030 +       }
5031 +
5032 +       if (doscan) {
5033 +               printk(KERN_INFO "scanning ...\n");
5034 +               megasas_get_pd_list(instance);
5035 +               for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) {
5036 +                       for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5037 +                               pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j;
5038 +                               sdev1 = scsi_device_lookup(host, i, j, 0);
5039 +                               if (instance->pd_list[pd_index].driveState ==
5040 +                                                       MR_PD_STATE_SYSTEM) {
5041 +                                       if (!sdev1) {
5042 +                                               scsi_add_device(host, i, j, 0);
5043 +                                       } else {
5044 +                                               scsi_device_put(sdev1);
5045 +                                       }
5046 +                               } else {
5047 +                                       if (sdev1) {
5048 +                                               scsi_remove_device(sdev1);
5049 +                                               scsi_device_put(sdev1);
5050 +                                       }
5051 +                               }
5052 +                       }
5053 +               }
5054 +
5055 +               megasas_get_ld_list(instance);
5056 +               for (i=0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
5057 +                       for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
5058 +                               ld_index = (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;
5059 +                               sdev1 = scsi_device_lookup(host, i+MEGASAS_MAX_LD_CHANNELS, j, 0);
5060 +                               if (instance->ld_ids[ld_index] != 0xff) {
5061 +                                       if (!sdev1) {
5062 +                                               scsi_add_device(host, i+2, j, 0);
5063 +                                       } else {
5064 +                                               scsi_device_put(sdev1);
5065 +                                       }
5066 +                               } else {
5067 +                                       if (sdev1) {
5068 +                                               scsi_remove_device(sdev1);
5069 +                                               scsi_device_put(sdev1);
5070 +                                       }
5071 +                               }
5072 +                       }
5073 +               }               
5074 +       }
5075 +
5076 +       seq_num = instance->evt_detail->seq_num + 1;
5077 +
5078 +       /* Register AEN with FW for latest sequence number plus 1 */
5079 +       class_locale.members.reserved = 0;
5080 +       class_locale.members.locale = MR_EVT_LOCALE_ALL;
5081 +       class_locale.members.class = MR_EVT_CLASS_DEBUG;
5082 +       
5083 +       if ( instance->aen_cmd != NULL ) {
5084 +               kfree(ev);
5085 +               return ; 
5086 +       }
5087 +
5088 +       mutex_lock(&instance->aen_mutex);
5089 +       error = megasas_register_aen(instance, seq_num,
5090 +                                       class_locale.word);
5091 +       mutex_unlock(&instance->aen_mutex);
5092 +
5093 +       if (error)
5094 +               printk(KERN_ERR "register aen failed error %x\n", error);
5095 +
5096 +       kfree(ev);
5097 +}
5098 +
5099 +
5100 +static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR,
5101 +               megasas_sysfs_show_poll_mode_io,
5102 +               megasas_sysfs_set_poll_mode_io);
5103  
5104  /**
5105   * megasas_init - Driver load entry point
5106 @@ -3113,6 +6334,9 @@ static int __init megasas_init(void)
5107         printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
5108                MEGASAS_EXT_VERSION);
5109  
5110 +       support_poll_for_event = 2;
5111 +       support_device_change = 1;
5112 +
5113         memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info));
5114  
5115         /*
5116 @@ -3145,15 +6369,41 @@ static int __init megasas_init(void)
5117                                   &driver_attr_release_date);
5118         if (rval)
5119                 goto err_dcf_rel_date;
5120 +
5121 +       rval = driver_create_file(&megasas_pci_driver.driver,
5122 +                               &driver_attr_support_poll_for_event);
5123 +       if (rval)
5124 +               goto err_dcf_support_poll_for_event;
5125 +
5126         rval = driver_create_file(&megasas_pci_driver.driver,
5127                                   &driver_attr_dbg_lvl);
5128         if (rval)
5129                 goto err_dcf_dbg_lvl;
5130 +       rval = driver_create_file(&megasas_pci_driver.driver,
5131 +                                 &driver_attr_poll_mode_io);
5132 +       if (rval)
5133 +               goto err_dcf_poll_mode_io;
5134 +       rval = driver_create_file(&megasas_pci_driver.driver,
5135 +                               &driver_attr_support_device_change);
5136 +       if (rval)
5137 +               goto err_dcf_support_device_change;
5138  
5139         return rval;
5140 +err_dcf_support_device_change:
5141 +       driver_remove_file(&megasas_pci_driver.driver,
5142 +                         &driver_attr_poll_mode_io);
5143 +
5144 +err_dcf_poll_mode_io:
5145 +       driver_remove_file(&megasas_pci_driver.driver,
5146 +                          &driver_attr_dbg_lvl);
5147  err_dcf_dbg_lvl:
5148         driver_remove_file(&megasas_pci_driver.driver,
5149 +                       &driver_attr_support_poll_for_event);
5150 +
5151 +err_dcf_support_poll_for_event:
5152 +       driver_remove_file(&megasas_pci_driver.driver,
5153                            &driver_attr_release_date);
5154 +
5155  err_dcf_rel_date:
5156         driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
5157  err_dcf_attr_ver:
5158 @@ -3169,8 +6419,14 @@ err_pcidrv:
5159  static void __exit megasas_exit(void)
5160  {
5161         driver_remove_file(&megasas_pci_driver.driver,
5162 +                          &driver_attr_poll_mode_io);
5163 +       driver_remove_file(&megasas_pci_driver.driver,
5164                            &driver_attr_dbg_lvl);
5165         driver_remove_file(&megasas_pci_driver.driver,
5166 +                       &driver_attr_support_poll_for_event);
5167 +       driver_remove_file(&megasas_pci_driver.driver,
5168 +                       &driver_attr_support_device_change);
5169 +       driver_remove_file(&megasas_pci_driver.driver,
5170                            &driver_attr_release_date);
5171         driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version);
5172  
5173 diff -Nurp linux-2.6.22-950/drivers/scsi/megaraid/megaraid_sas.h linux-2.6.22-960/drivers/scsi/megaraid/megaraid_sas.h
5174 --- linux-2.6.22-950/drivers/scsi/megaraid/megaraid_sas.h       2007-07-08 19:32:17.000000000 -0400
5175 +++ linux-2.6.22-960/drivers/scsi/megaraid/megaraid_sas.h       2010-07-20 16:47:48.000000000 -0400
5176 @@ -18,15 +18,21 @@
5177  /*
5178   * MegaRAID SAS Driver meta data
5179   */
5180 -#define MEGASAS_VERSION                                "00.00.03.10-rc5"
5181 -#define MEGASAS_RELDATE                                "May 17, 2007"
5182 -#define MEGASAS_EXT_VERSION                    "Thu May 17 10:09:32 PDT 2007"
5183 +#define MEGASAS_VERSION                                "00.00.04.33"
5184 +#define MEGASAS_RELDATE                                "July 20, 2010"
5185 +#define MEGASAS_EXT_VERSION                    "Tue Jul 20 12:24:32 EDT 2010"
5186 +
5187  
5188  /*
5189   * Device IDs
5190   */
5191  #define        PCI_DEVICE_ID_LSI_SAS1078R              0x0060
5192 +#define        PCI_DEVICE_ID_LSI_SAS1078DE             0x007C
5193  #define        PCI_DEVICE_ID_LSI_VERDE_ZCR             0x0413
5194 +#define        PCI_DEVICE_ID_LSI_SAS1078GEN2           0x0078
5195 +#define        PCI_DEVICE_ID_LSI_SAS0079GEN2           0x0079
5196 +#define        PCI_DEVICE_ID_LSI_SAS0073SKINNY         0x0073
5197 +#define        PCI_DEVICE_ID_LSI_SAS0071SKINNY         0x0071
5198  
5199  /*
5200   * =====================================
5201 @@ -55,6 +61,7 @@
5202  #define MFI_STATE_READY                                0xB0000000
5203  #define MFI_STATE_OPERATIONAL                  0xC0000000
5204  #define MFI_STATE_FAULT                                0xF0000000
5205 +#define  MFI_RESET_REQUIRED                    0x00000001
5206  
5207  #define MEGAMFI_FRAME_SIZE                     64
5208  
5209 @@ -68,6 +75,13 @@
5210   * HOTPLUG     : Resume from Hotplug
5211   * MFI_STOP_ADP        : Send signal to FW to stop processing
5212   */
5213 +
5214 +#define WRITE_SEQUENCE_OFFSET          (0x0000000FC) // I20
5215 +#define HOST_DIAGNOSTIC_OFFSET         (0x000000F8)  // I20
5216 +#define DIAG_WRITE_ENABLE                      (0x00000080)
5217 +#define DIAG_RESET_ADAPTER                     (0x00000004)
5218 +
5219 +#define MFI_ADP_RESET                          0x00000040
5220  #define MFI_INIT_ABORT                         0x00000001
5221  #define MFI_INIT_READY                         0x00000002
5222  #define MFI_INIT_MFIMODE                       0x00000004
5223 @@ -91,6 +105,7 @@
5224  #define MFI_FRAME_DIR_WRITE                    0x0008
5225  #define MFI_FRAME_DIR_READ                     0x0010
5226  #define MFI_FRAME_DIR_BOTH                     0x0018
5227 +#define MFI_FRAME_IEEE                         0x0020
5228  
5229  /*
5230   * Definition for cmd_status
5231 @@ -111,12 +126,14 @@
5232  #define MFI_CMD_STP                            0x08
5233  
5234  #define MR_DCMD_CTRL_GET_INFO                  0x01010000
5235 +#define MR_DCMD_LD_GET_LIST                    0x03010000
5236  
5237  #define MR_DCMD_CTRL_CACHE_FLUSH               0x01101000
5238  #define MR_FLUSH_CTRL_CACHE                    0x01
5239  #define MR_FLUSH_DISK_CACHE                    0x02
5240  
5241  #define MR_DCMD_CTRL_SHUTDOWN                  0x01050000
5242 +#define MR_DCMD_HIBERNATE_SHUTDOWN             0x01060000
5243  #define MR_ENABLE_DRIVE_SPINDOWN               0x01
5244  
5245  #define MR_DCMD_CTRL_EVENT_GET_INFO            0x01040100
5246 @@ -127,6 +144,29 @@
5247  #define MR_DCMD_CLUSTER                                0x08000000
5248  #define MR_DCMD_CLUSTER_RESET_ALL              0x08010100
5249  #define MR_DCMD_CLUSTER_RESET_LD               0x08010200
5250 +#define MR_DCMD_PD_LIST_QUERY                  0x02010100
5251 +
5252 +#define MR_DCMD_CTRL_MISC_CPX                  0x0100e200
5253 +#define MR_DCMD_CTRL_MISC_CPX_INIT_DATA_GET    0x0100e201
5254 +#define MR_DCMD_CTRL_MISC_CPX_QUEUE_DATA       0x0100e202
5255 +#define MR_DCMD_CTRL_MISC_CPX_UNREGISTER       0x0100e203
5256 +#define MAX_MR_ROW_SIZE                                32
5257 +#define MR_CPX_DIR_WRITE                       1
5258 +#define MR_CPX_DIR_READ                                0
5259 +#define MR_CPX_VERSION                         1
5260 +
5261 +#define MR_EVT_CFG_CLEARED                     0x0004
5262 +
5263 +#define MR_EVT_LD_STATE_CHANGE                 0x0051
5264 +#define MR_EVT_PD_INSERTED                     0x005b
5265 +#define MR_EVT_PD_REMOVED                      0x0070
5266 +#define MR_EVT_LD_CREATED                      0x008a
5267 +#define MR_EVT_LD_DELETED                      0x008b
5268 +#define MR_EVT_FOREIGN_CFG_IMPORTED            0x00db
5269 +#define MR_EVT_LD_OFFLINE                      0x00fc
5270 +#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED    0x0152
5271 +#define MAX_LOGICAL_DRIVES                      64
5272 +
5273  
5274  /*
5275   * MFI command completion codes
5276 @@ -247,8 +287,128 @@ enum MR_EVT_ARGS {
5277         MR_EVT_ARGS_STR,
5278         MR_EVT_ARGS_TIME,
5279         MR_EVT_ARGS_ECC,
5280 +       MR_EVT_ARGS_LD_PROP,
5281 +       MR_EVT_ARGS_PD_SPARE,
5282 +       MR_EVT_ARGS_PD_INDEX,
5283 +       MR_EVT_ARGS_DIAG_PASS,
5284 +       MR_EVT_ARGS_DIAG_FAIL,
5285 +       MR_EVT_ARGS_PD_LBA_LBA,
5286 +       MR_EVT_ARGS_PORT_PHY,
5287 +       MR_EVT_ARGS_PD_MISSING,
5288 +       MR_EVT_ARGS_PD_ADDRESS,
5289 +       MR_EVT_ARGS_BITMAP,
5290 +       MR_EVT_ARGS_CONNECTOR,
5291 +       MR_EVT_ARGS_PD_PD,
5292 +       MR_EVT_ARGS_PD_FRU,
5293 +       MR_EVT_ARGS_PD_PATHINFO,
5294 +       MR_EVT_ARGS_PD_POWER_STATE,
5295 +       MR_EVT_ARGS_GENERIC,
5296 +
5297 +};
5298  
5299 +/*
5300 + * define constants for device list query options
5301 + */
5302 +enum MR_PD_QUERY_TYPE {
5303 +    MR_PD_QUERY_TYPE_ALL                = 0,
5304 +    MR_PD_QUERY_TYPE_STATE              = 1,
5305 +    MR_PD_QUERY_TYPE_POWER_STATE        = 2,
5306 +    MR_PD_QUERY_TYPE_MEDIA_TYPE         = 3,
5307 +    MR_PD_QUERY_TYPE_SPEED              = 4,
5308 +    MR_PD_QUERY_TYPE_EXPOSED_TO_HOST    = 5,
5309 +} __attribute__ ((packed));
5310 +
5311 +#define MR_EVT_CFG_CLEARED                             0x0004
5312 +#define MR_EVT_LD_STATE_CHANGE                         0x0051
5313 +#define MR_EVT_PD_INSERTED                             0x005b
5314 +#define MR_EVT_PD_REMOVED                              0x0070
5315 +#define MR_EVT_LD_CREATED                              0x008a
5316 +#define MR_EVT_LD_DELETED                              0x008b
5317 +#define MR_EVT_FOREIGN_CFG_IMPORTED                    0x00db
5318 +#define MR_EVT_LD_OFFLINE                              0x00fc
5319 +#define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED            0x0152
5320 +
5321 +enum MR_PD_STATE {                 
5322 +    MR_PD_STATE_UNCONFIGURED_GOOD   = 0x00,
5323 +    MR_PD_STATE_UNCONFIGURED_BAD    = 0x01,
5324 +    MR_PD_STATE_HOT_SPARE           = 0x02,
5325 +    MR_PD_STATE_OFFLINE             = 0x10,
5326 +    MR_PD_STATE_FAILED              = 0x11,
5327 +    MR_PD_STATE_REBUILD             = 0x14,
5328 +    MR_PD_STATE_ONLINE              = 0x18,
5329 +    MR_PD_STATE_COPYBACK            = 0x20,
5330 +    MR_PD_STATE_SYSTEM              = 0x40,
5331  };
5332
5333 + /*
5334 + * defines the physical drive address structure
5335 + */
5336 +struct MR_PD_ADDRESS {
5337 +    u16     deviceId;
5338 +    u16     enclDeviceId;
5339 +                         
5340 +    union {
5341 +        struct {         
5342 +                         
5343 +            u8  enclIndex;
5344 +            u8  slotNumber;
5345 +        } mrPdAddress;
5346 +        struct {
5347 +            u8  enclPosition;
5348 +            u8  enclConnectorIndex;
5349 +        } mrEnclAddress;
5350 +    };
5351 +    u8      scsiDevType;
5352 +    union {
5353 +        u8      connectedPortBitmap;
5354 +        u8      connectedPortNumbers;
5355 +                    
5356 +    };
5357 +    u64     sasAddr[2];
5358 +} __attribute__ ((packed));
5359 +
5360 +/*
5361 + * defines the physical drive list structure
5362 + */
5363 +struct MR_PD_LIST {
5364 +    u32             size;
5365 +    u32             count;
5366 +    struct MR_PD_ADDRESS   addr[1];
5367 +} __attribute__ ((packed));
5368 +
5369 +
5370 +struct megasas_pd_list {
5371 +    u16             tid;
5372 +    u8             driveType;
5373 +    u8             driveState;
5374 +} __attribute__ ((packed));
5375 +
5376 + /*
5377 + * defines the logical drive reference structure
5378 + */
5379 +typedef union  _MR_LD_REF {        // LD reference structure
5380 +    struct {
5381 +        u8      targetId;           // LD target id (0 to MAX_TARGET_ID)
5382 +        u8      reserved;           // reserved to make in line with MR_PD_REF
5383 +        u16     seqNum;             // Sequence Number
5384 +    };
5385 +    u32     ref;                    // shorthand reference to full 32-bits
5386 +} MR_LD_REF;                        // 4 bytes
5387 +
5388 +
5389 +/*
5390 + * defines the logical drive list structure
5391 + */
5392 +struct MR_LD_LIST {
5393 +    u32     ldCount;                // number of LDs
5394 +    u32     reserved;               // pad to 8-byte boundary
5395 +    struct {
5396 +        MR_LD_REF   ref;            // LD reference
5397 +        u8          state;          // current LD state (MR_LD_STATE)
5398 +        u8          reserved[3];    // pad to 8-byte boundary
5399 +        u64         size;           // LD size
5400 +    } ldList[MAX_LOGICAL_DRIVES];
5401 +} __attribute__ ((packed));
5402  
5403  /*
5404   * SAS controller properties
5405 @@ -276,7 +436,45 @@ struct megasas_ctrl_prop {
5406         u16 ecc_bucket_leak_rate;
5407         u8 restore_hotspare_on_insertion;
5408         u8 expose_encl_devices;
5409 -       u8 reserved[38];
5410 +        u8      maintainPdFailHistory;
5411 +    u8      disallowHostRequestReordering;
5412 +    u8      abortCCOnError;                 // set TRUE to abort CC on detecting an inconsistency
5413 +    u8      loadBalanceMode;                // load balance mode (MR_LOAD_BALANCE_MODE)
5414 +    u8      disableAutoDetectBackplane;     // 0 - use auto detect logic of backplanes like SGPIO, i2c SEP using h/w mechansim like GPIO pins
5415 +                                            // 1 - disable auto detect SGPIO,
5416 +                                            // 2 - disable i2c SEP auto detect
5417 +                                            // 3 - disable both auto detect
5418 +    u8      snapVDSpace;                    // % of source LD to be reserved for a VDs snapshot in snapshot repository, for metadata and user data
5419 +                                            // 1=5%, 2=10%, 3=15% and so on
5420 +
5421 +    /*
5422 +     * Add properties that can be controlled by a bit in the following structure.
5423 +     */
5424 +    struct {
5425 +        u32     copyBackDisabled            : 1;     // set TRUE to disable copyBack (0=copback enabled)
5426 +        u32     SMARTerEnabled              : 1;
5427 +        u32     prCorrectUnconfiguredAreas  : 1;
5428 +        u32     useFdeOnly                  : 1;
5429 +        u32     disableNCQ                  : 1;
5430 +       u32     SSDSMARTerEnabled           : 1;
5431 +        u32     SSDPatrolReadEnabled        : 1;
5432 +        u32     enableSpinDownUnconfigured  : 1;
5433 +        u32     autoEnhancedImport          : 1;
5434 +        u32     enableSecretKeyControl      : 1;
5435 +        u32     disableOnlineCtrlReset      : 1;
5436 +        u32     allowBootWithPinnedCache    : 1;
5437 +        u32     disableSpinDownHS           : 1;
5438 +        u32     enableJBOD                  : 1;
5439 +        u32     reserved                    :18;
5440 +    } OnOffProperties;
5441 +    u8      autoSnapVDSpace;                // % of source LD to be reserved for auto snapshot in snapshot repository, for metadata and user data
5442 +                                            // 1=5%, 2=10%, 3=15% and so on
5443 +    u8      viewSpace;                      // snapshot writeable VIEWs capacity as a % of source LD capacity. 0=READ only
5444 +                                            // 1=5%, 2=10%, 3=15% and so on
5445 +        
5446 +    u16     spinDownTime;                   // # of idle minutes before device is spun down (0=use FW defaults)
5447 +
5448 +    u8      reserved[24];
5449  
5450  } __attribute__ ((packed));
5451  
5452 @@ -536,10 +734,20 @@ struct megasas_ctrl_info {
5453  #define MEGASAS_DEFAULT_INIT_ID                        -1
5454  #define MEGASAS_MAX_LUN                                8
5455  #define MEGASAS_MAX_LD                         64
5456 +#define MEGASAS_DEFAULT_CMD_PER_LUN            128
5457 +#define MEGASAS_MAX_PD                         (MEGASAS_MAX_PD_CHANNELS * \
5458 +                                                       MEGASAS_MAX_DEV_PER_CHANNEL)
5459 +#define MEGASAS_MAX_LD_IDS                     (MEGASAS_MAX_LD_CHANNELS * \
5460 +                                                       MEGASAS_MAX_DEV_PER_CHANNEL)
5461  
5462 -#define MEGASAS_DBG_LVL                                1
5463  
5464 +#define MEGASAS_MAX_SECTORS                    (2*1024)
5465 +#define MEGASAS_MAX_SECTORS_IEEE               (2*128)
5466 +#define MEGASAS_DBG_LVL                                1
5467  #define MEGASAS_FW_BUSY                                1
5468 +/* Frame Type */
5469 +#define IO_FRAME                               0
5470 +#define PTHRU_FRAME                            1
5471  
5472  /*
5473   * When SCSI mid-layer calls driver's reset routine, driver waits for
5474 @@ -551,6 +759,7 @@ struct megasas_ctrl_info {
5475  #define MEGASAS_RESET_WAIT_TIME                        180
5476  #define MEGASAS_INTERNAL_CMD_WAIT_TIME         180
5477  #define        MEGASAS_RESET_NOTICE_INTERVAL           5
5478 +
5479  #define MEGASAS_IOCTL_CMD                      0
5480  #define MEGASAS_DEFAULT_CMD_TIMEOUT            90
5481  
5482 @@ -562,6 +771,7 @@ struct megasas_ctrl_info {
5483   * is shown below
5484   */
5485  #define MEGASAS_INT_CMDS                       32
5486 +#define MEGASAS_SKINNY_INT_CMDS                        5       
5487  
5488  /*
5489   * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit
5490 @@ -569,10 +779,25 @@ struct megasas_ctrl_info {
5491   */
5492  #define IS_DMA64                               (sizeof(dma_addr_t) == 8)
5493  
5494 +#define MFI_XSCALE_OMR0_CHANGE_INTERRUPT            0x00000001  /* MFI state change interrupt */
5495 +
5496 +#define MFI_INTR_FLAG_REPLY_MESSAGE                 0x00000001
5497 +#define MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE         0x00000002
5498 +#define MFI_G2_OUTBOUND_DOORBELL_CHANGE_INTERRUPT 0x00000004  /* MFI state change interrrupt */
5499 +
5500  #define MFI_OB_INTR_STATUS_MASK                        0x00000002
5501 -#define MFI_POLL_TIMEOUT_SECS                  10
5502 +#define MFI_POLL_TIMEOUT_SECS                  60
5503 +#define MEGASAS_COMPLETION_TIMER_INTERVAL      (HZ/10)
5504  
5505  #define MFI_REPLY_1078_MESSAGE_INTERRUPT       0x80000000
5506 +#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT       0x00000001
5507 +#define MFI_GEN2_ENABLE_INTERRUPT_MASK         0x00000001 
5508 +#define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT     0x40000000
5509 +#define MFI_SKINNY_ENABLE_INTERRUPT_MASK       (0x00000001)
5510 +#define MFI_1068_PCSR_OFFSET                   0x84
5511 +#define MFI_1068_FW_HANDSHAKE_OFFSET           0x64
5512 +#define MFI_1068_FW_READY                      0xDDDD0000
5513 +
5514  
5515  /*
5516  * register set for both 1068 and 1078 controllers
5517 @@ -580,7 +805,11 @@ struct megasas_ctrl_info {
5518  */
5519   
5520  struct megasas_register_set {
5521 -       u32     reserved_0[4];                  /*0000h*/
5522 +       u32     reserved_0;                     /*0000h*/
5523 +       u32     fusion_seq_offset;              /*0008h*/
5524 +       u32     fusion_host_diag;               /*0004h*/
5525 +       u32     reserved_01;                    /*000Ch*/
5526 +
5527  
5528         u32     inbound_msg_0;                  /*0010h*/
5529         u32     inbound_msg_1;                  /*0014h*/
5530 @@ -615,7 +844,10 @@ struct megasas_register_set {
5531         u32     inbound_high_queue_port ;       /*00C4h*/
5532  
5533         u32     reserved_5;                     /*00C8h*/
5534 -       u32     index_registers[820];           /*00CCh*/
5535 +       u32             res_6[11];                      /*CCh*/
5536 +       u32             host_diag;
5537 +       u32             seq_offset;
5538 +       u32     index_registers[807];           /*00CCh*/
5539  
5540  } __attribute__ ((packed));
5541  
5542 @@ -632,11 +864,20 @@ struct megasas_sge64 {
5543         u32 length;
5544  
5545  } __attribute__ ((packed));
5546
5547 +struct megasas_sge_skinny {
5548 +
5549 +       u64 phys_addr;
5550 +       u32 length;
5551 +       u32 flag;
5552 +
5553 +} __attribute__ ((packed));
5554  
5555  union megasas_sgl {
5556  
5557         struct megasas_sge32 sge32[1];
5558         struct megasas_sge64 sge64[1];
5559 +       struct megasas_sge_skinny sge_skinny[1];
5560  
5561  } __attribute__ ((packed));
5562  
5563 @@ -1050,16 +1291,177 @@ struct megasas_evt_detail {
5564  
5565  } __attribute__ ((packed));
5566  
5567 - struct megasas_instance_template {
5568 -       void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
5569 +#define MIN(a,b) ((a)<(b) ? (a):(b))
5570 +typedef void (*XOR_LOW_LEVEL_GEN_FUNC)(u32 **, u32);
5571 +typedef u8 (*XOR_LOW_LEVEL_CHECK_FUNC)(u32 **, u32);
5572 +/*
5573 + * enumerates type of descriptor
5574 + */
5575 +typedef  enum _MR_CPX_DESCRIPTOR_TYPE {
5576 +       MR_CPX_DESCRIPTOR_TYPE_COPY   = 1,
5577 +       MR_CPX_DESCRIPTOR_TYPE_XOR    = 2
5578 +} MR_CPX_DESCRIPTOR_TYPE;
5579  
5580 -       void (*enable_intr)(struct megasas_register_set __iomem *) ;
5581 -       void (*disable_intr)(struct megasas_register_set __iomem *);
5582 +/*
5583 + * status information of copy or xor operation
5584 + */
5585 +typedef enum _MR_CPX_STATUS {
5586 +       MR_CPX_STATUS_SUCCESS      = 0,
5587 +       MR_CPX_STATUS_INCONSISTENT = 1,
5588 +       MR_CPX_STATUS_FAILURE      = 2,
5589 +} MR_CPX_STATUS;     
5590  
5591 -       int (*clear_intr)(struct megasas_register_set __iomem *);
5592 +/*
5593 + * define the XOR opcodes
5594 + */
5595 +typedef enum _mr_cpx_xor_op {
5596 +       MR_CPX_XOR_OP_GEN_P    = 0x01,                  // generate P buffer
5597 +       MR_CPX_XOR_OP_GEN_Q    = 0x02,                  // generate Q buffer
5598 +       MR_CPX_XOR_OP_GEN_PQ   = 0x03,                  // generate P+Q buffers
5599 +       MR_CPX_XOR_OP_CHECK_P  = 0x11,                  // check P buffer (and generate if bad)
5600 +       MR_CPX_XOR_OP_CHECK_Q  = 0x12,                  // check Q buffer (and generate if bad)
5601 +       MR_CPX_XOR_OP_CHECK_PQ = 0x13,                  // check P+Q buffers (and generate if bad)
5602 +} MR_CPX_XOR_OP;
5603 +
5604 +#define MR_CPX_XOR_OP_IS_CHECK(xorOp)  ((xorOp & 0x10)!=0)              // TRUE if operation is a CHECK operation
5605 +#define MR_CPX_XOR_OP_IS_GEN(xorOp)    (!MR_CPX_XOR_OP_IS_CHECK(xorOp)) // TRUE if operation is a GEN operation
5606 +#define MR_CPX_XOR_OP_IS_P(xorOp)      ((xorOp & 0x01)!=0)              // TRUE if operation is for P or P/Q
5607 +#define MR_CPX_XOR_OP_IS_Q(xorOp)      ((xorOp & 0x02)!=0)              // TRUE if operation is for Q or P/Q
5608 +#define MR_CPX_XOR_OP_IS_PQ(xorOp)     ((xorOp & 0x03)==3)              // TRUE if operation is for P/Q
5609  
5610 -       u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
5611 - };
5612 +
5613 +/*
5614 + * this data is passed to driver during driver init.
5615 + */
5616 +struct mr_cpx_init_data {
5617 +       u32     cpx_desc_count;         // Number of cpx desc required by fw.
5618 +       u32     size;                   // size of the buffer
5619 +       u64     phys_addr_cache_buf;       // physical address of cache buffer allocated by pre-boot
5620 +
5621 +} __attribute__ ((packed));
5622 +
5623 +/*
5624 + * header passed with each descriptor
5625 + */
5626 +struct mr_cpx_header {
5627 +       u32        context   : 24;       // context information passed by firmware, to be passed back in response data
5628 +       u32        type     :  4;       // type of descriptor
5629 +       u32        resvd    :  4;
5630 +} __attribute__ ((packed));
5631 +
5632 +/*
5633 + * xor descriptor data
5634 + */
5635 +struct mr_cpx_xor_descriptor {
5636 +       struct mr_cpx_header      hdr;
5637 +       MR_CPX_XOR_OP      op;                           // xor operation for gen/check of p/q/p+q
5638 +       u32             size;                         // number of bytes to gen/check for this operation
5639 +       u32             buff_valid_bitmap;              // bitmap of valid buffers for input
5640 +       u8              p_idx;                       // index of p buffer within list (for p/pq gen/check functions)
5641 +       u8              q_idx;                       // index of q buffer within list (for q/pq gen/check functions)
5642 +       u8              pad[2];             
5643 +       u32             buff_list[MAX_MR_ROW_SIZE];    // list of buffers for this xor operation (32 bit offset)
5644 +       u32             mult_list[MAX_MR_ROW_SIZE];    // list of coefficient multipliers for q operations
5645 +} __attribute__ ((packed));
5646 +
5647 +
5648 +/*
5649 + * copy buffer for each transfer. each such tranfer between
5650 + * user spare host address and firmware allocated cache data.
5651 + */
5652 +struct mr_cpx_copy_mr_buffer {
5653 +       u32     buf;                       // buffer address/offset 
5654 +       u32     size;                      // size of copy 
5655 +} __attribute__ ((packed));
5656 +
5657 +/*
5658 + * copy descriptor data
5659 + */
5660 +struct mr_cpx_copy_descriptor {
5661 +       struct mr_cpx_header              hdr;
5662 +       u32                     mfi_cmd_cxt;          // mfi context
5663 +       u32                     total_byte_count;         // total byte count for this transfer 
5664 +       u32                     host_skip_count;          // skip count from starting address of host buffer 
5665 +       u8                      dir;                    // direction of transfer 
5666 +       u8                      pad[3];
5667 +       struct mr_cpx_copy_mr_buffer      copy_buf[MAX_MR_ROW_SIZE];
5668 +} __attribute__ ((packed)) ;
5669 +
5670 +/*
5671 + * users of this interface must allocate memory for the size of
5672 + * this structure while allocating memory for descriptors
5673 + */
5674 +union mr_cpx_descriptor {
5675 +       struct mr_cpx_xor_descriptor       cpx_xor_desc;
5676 +       struct mr_cpx_copy_descriptor     cpx_copy_desc;
5677 +       u8                      pad[512];
5678 +} __attribute__ ((packed));
5679 +
5680 +
5681 +/*
5682 + * request queue.
5683 + * firmware manages producerindex, driver manages consumerindex.
5684 + * number of decriptors is kept as variable. driver must use
5685 + * max host commands supported for allocation.
5686 + */
5687 +struct mr_cpx_request_queue {
5688 +       u32             consumer_idx;
5689 +       u32             producer_idx;
5690 +       union mr_cpx_descriptor   cpxdescriptor[1]; // use max host commands 
5691 +} __attribute__ ((packed));
5692 +
5693 +
5694 +/*
5695 + * response data. this data will be posted by driver after copy/xor
5696 + * operation is compete.
5697 + */
5698 +union mr_cpx_response_data {
5699 +       struct {
5700 +               u32         context     : 24;                // context  
5701 +               u32         status      :  4;                // status in the form of cpx_status
5702 +               u32         type        :  4;
5703 +       } r;
5704 +       u32         w;
5705 +} __attribute__ ((packed));
5706 +
5707 +
5708 +/*
5709 + * response queue.
5710 + * driver manages producerindex, firmware 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_response_queue {
5715 +       u32                 consumer_idx;
5716 +       u32                 producer_idx;
5717 +       union mr_cpx_response_data   cpx_resp_data[1]; // use max host commands 
5718 +} __attribute__ ((packed));
5719 +
5720 +
5721 +/*
5722 + * the size of each of the structure within this is determined at run time.
5723 + * this structure is for document purpose and shows that the structures
5724 + * lay as shown below in memory
5725 + */
5726 +struct  mr_cpx_queues {
5727 +       struct mr_cpx_request_queue     requestqueue;
5728 +       struct mr_cpx_response_queue    responsequeue;
5729 +} __attribute__ ((packed));
5730 +
5731 +/*
5732 + * driver sends this queue data during mfi init. firmware
5733 + * will not use the interface if the versions do not match.
5734 + */
5735 +struct mr_cpx_queue_data {
5736 +       u32         version;
5737 +       u32         count_queue_entries;
5738 +       u64         phys_addr_cpx_queues;
5739 +} __attribute__ ((packed));
5740 +
5741 +struct megasas_aen_event {
5742 +       struct work_struct hotplug_work;
5743 +       struct megasas_instance *instance;
5744 +};
5745  
5746  struct megasas_instance {
5747  
5748 @@ -1074,22 +1476,30 @@ struct megasas_instance {
5749         unsigned long base_addr;
5750         struct megasas_register_set __iomem *reg_set;
5751  
5752 +       struct megasas_pd_list          pd_list[MEGASAS_MAX_PD];
5753 +       u8     ld_ids[MEGASAS_MAX_LD_IDS];
5754 +
5755         s8 init_id;
5756  
5757         u16 max_num_sge;
5758         u16 max_fw_cmds;
5759         u32 max_sectors_per_req;
5760 +       u32 cmd_per_lun;
5761  
5762         struct megasas_cmd **cmd_list;
5763         struct list_head cmd_pool;
5764         spinlock_t cmd_pool_lock;
5765 +       struct megasas_aen_event *ev;
5766 +       spinlock_t hba_lock;
5767 +       /* used to synch producer, consumer ptrs in dpc */
5768 +       spinlock_t completion_lock;
5769         struct dma_pool *frame_dma_pool;
5770         struct dma_pool *sense_dma_pool;
5771  
5772         struct megasas_evt_detail *evt_detail;
5773         dma_addr_t evt_detail_h;
5774         struct megasas_cmd *aen_cmd;
5775 -       struct semaphore aen_mutex;
5776 +       struct mutex aen_mutex;
5777         struct semaphore ioctl_sem;
5778  
5779         struct Scsi_Host *host;
5780 @@ -1099,17 +1509,62 @@ struct megasas_instance {
5781  
5782         struct pci_dev *pdev;
5783         u32 unique_id;
5784 +       u32 fw_support_ieee;
5785  
5786         atomic_t fw_outstanding;
5787 -       u32 hw_crit_error;
5788 +       atomic_t fw_reset_no_pci_access;
5789  
5790         struct megasas_instance_template *instancet;
5791         struct tasklet_struct isr_tasklet;
5792 +       struct work_struct work_init;
5793  
5794         u8 flag;
5795 +       u8 unload;
5796 +       u8 flag_ieee;
5797 +       u8 issuepend_done;
5798 +       u8 disableOnlineCtrlReset;
5799 +       u8 adprecovery;
5800         unsigned long last_time;
5801 +       u32 mfiStatus;
5802 +       u32 last_seq_num;
5803 +
5804 +       struct timer_list io_completion_timer;
5805 +       struct list_head internal_reset_pending_q;
5806 +       
5807 +       u32 cpx_supported;
5808 +       struct mr_cpx_request_queue *cpx_request_queue;
5809 +       dma_addr_t cpx_request_queue_h;
5810 +       union mr_cpx_descriptor *cpx_dscrptr;
5811 +       u32 cpx_dscrptr_cnt;    
5812 +       u64 host_mem_phys;
5813 +       u32 host_mem_len;
5814 +       u8 *host_mem_virt;
5815 +
5816 +};
5817 +
5818 +enum {
5819 +       MEGASAS_HBA_OPERATIONAL                 = 0,
5820 +       MEGASAS_ADPRESET_SM_INFAULT             = 1,
5821 +       MEGASAS_ADPRESET_SM_FW_RESET_SUCCESS    = 2,
5822 +       MEGASAS_ADPRESET_SM_OPERATIONAL         = 3,
5823 +       MEGASAS_HW_CRITICAL_ERROR               = 4,
5824 +       MEGASAS_ADPRESET_INPROG_SIGN            = 0xDEADDEAD,
5825  };
5826  
5827 +
5828 + struct megasas_instance_template {
5829 +       void (*fire_cmd)(struct megasas_instance *, dma_addr_t ,u32 ,struct megasas_register_set __iomem *);
5830 +
5831 +       void (*enable_intr)(struct megasas_register_set __iomem *) ;
5832 +       void (*disable_intr)(struct megasas_register_set __iomem *);
5833 +
5834 +       int (*clear_intr)(struct megasas_register_set __iomem *);
5835 +
5836 +       u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *);
5837 +       int (*adp_reset)(struct megasas_instance *, struct megasas_register_set __iomem *);
5838 +       int (*check_reset)(struct megasas_instance *, struct megasas_register_set __iomem *);
5839 + };
5840 +
5841  #define MEGASAS_IS_LOGICAL(scp)                                                \
5842         (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1
5843  
5844 @@ -1127,7 +1582,9 @@ struct megasas_cmd {
5845         u32 index;
5846         u8 sync_cmd;
5847         u8 cmd_status;
5848 -       u16 abort_aen;
5849 +       u8 abort_aen;
5850 +        u8 retry_for_fw_reset;
5851 +
5852  
5853         struct list_head list;
5854         struct scsi_cmnd *scmd;