diff options
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 738 |
1 files changed, 671 insertions, 67 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index a39addc3a596..134c63ef6d38 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * FILE : megaraid_sas.c | 12 | * FILE : megaraid_sas.c |
13 | * Version : v00.00.04.01-rc1 | 13 | * Version : v00.00.04.12-rc1 |
14 | * | 14 | * |
15 | * Authors: | 15 | * Authors: |
16 | * (email-id : megaraidlinux@lsi.com) | 16 | * (email-id : megaraidlinux@lsi.com) |
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/compat.h> | 40 | #include <linux/compat.h> |
41 | #include <linux/blkdev.h> | 41 | #include <linux/blkdev.h> |
42 | #include <linux/mutex.h> | 42 | #include <linux/mutex.h> |
43 | #include <linux/poll.h> | ||
43 | 44 | ||
44 | #include <scsi/scsi.h> | 45 | #include <scsi/scsi.h> |
45 | #include <scsi/scsi_cmnd.h> | 46 | #include <scsi/scsi_cmnd.h> |
@@ -75,6 +76,10 @@ static struct pci_device_id megasas_pci_table[] = { | |||
75 | /* gen2*/ | 76 | /* gen2*/ |
76 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, | 77 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, |
77 | /* gen2*/ | 78 | /* gen2*/ |
79 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)}, | ||
80 | /* skinny*/ | ||
81 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)}, | ||
82 | /* skinny*/ | ||
78 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, | 83 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, |
79 | /* xscale IOP, vega */ | 84 | /* xscale IOP, vega */ |
80 | {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, | 85 | {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, |
@@ -89,8 +94,14 @@ static struct megasas_mgmt_info megasas_mgmt_info; | |||
89 | static struct fasync_struct *megasas_async_queue; | 94 | static struct fasync_struct *megasas_async_queue; |
90 | static DEFINE_MUTEX(megasas_async_queue_mutex); | 95 | static DEFINE_MUTEX(megasas_async_queue_mutex); |
91 | 96 | ||
97 | static int megasas_poll_wait_aen; | ||
98 | static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); | ||
99 | static u32 support_poll_for_event; | ||
92 | static u32 megasas_dbg_lvl; | 100 | static u32 megasas_dbg_lvl; |
93 | 101 | ||
102 | /* define lock for aen poll */ | ||
103 | spinlock_t poll_aen_lock; | ||
104 | |||
94 | static void | 105 | static void |
95 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | 106 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, |
96 | u8 alt_status); | 107 | u8 alt_status); |
@@ -215,7 +226,10 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) | |||
215 | * @regs : MFI register set | 226 | * @regs : MFI register set |
216 | */ | 227 | */ |
217 | static inline void | 228 | static inline void |
218 | megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs) | 229 | megasas_fire_cmd_xscale(struct megasas_instance *instance, |
230 | dma_addr_t frame_phys_addr, | ||
231 | u32 frame_count, | ||
232 | struct megasas_register_set __iomem *regs) | ||
219 | { | 233 | { |
220 | writel((frame_phys_addr >> 3)|(frame_count), | 234 | writel((frame_phys_addr >> 3)|(frame_count), |
221 | &(regs)->inbound_queue_port); | 235 | &(regs)->inbound_queue_port); |
@@ -312,7 +326,10 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) | |||
312 | * @regs : MFI register set | 326 | * @regs : MFI register set |
313 | */ | 327 | */ |
314 | static inline void | 328 | static inline void |
315 | megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs) | 329 | megasas_fire_cmd_ppc(struct megasas_instance *instance, |
330 | dma_addr_t frame_phys_addr, | ||
331 | u32 frame_count, | ||
332 | struct megasas_register_set __iomem *regs) | ||
316 | { | 333 | { |
317 | writel((frame_phys_addr | (frame_count<<1))|1, | 334 | writel((frame_phys_addr | (frame_count<<1))|1, |
318 | &(regs)->inbound_queue_port); | 335 | &(regs)->inbound_queue_port); |
@@ -328,6 +345,104 @@ static struct megasas_instance_template megasas_instance_template_ppc = { | |||
328 | }; | 345 | }; |
329 | 346 | ||
330 | /** | 347 | /** |
348 | * megasas_enable_intr_skinny - Enables interrupts | ||
349 | * @regs: MFI register set | ||
350 | */ | ||
351 | static inline void | ||
352 | megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) | ||
353 | { | ||
354 | writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); | ||
355 | |||
356 | writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); | ||
357 | |||
358 | /* Dummy readl to force pci flush */ | ||
359 | readl(®s->outbound_intr_mask); | ||
360 | } | ||
361 | |||
362 | /** | ||
363 | * megasas_disable_intr_skinny - Disables interrupt | ||
364 | * @regs: MFI register set | ||
365 | */ | ||
366 | static inline void | ||
367 | megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs) | ||
368 | { | ||
369 | u32 mask = 0xFFFFFFFF; | ||
370 | writel(mask, ®s->outbound_intr_mask); | ||
371 | /* Dummy readl to force pci flush */ | ||
372 | readl(®s->outbound_intr_mask); | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * megasas_read_fw_status_reg_skinny - returns the current FW status value | ||
377 | * @regs: MFI register set | ||
378 | */ | ||
379 | static u32 | ||
380 | megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs) | ||
381 | { | ||
382 | return readl(&(regs)->outbound_scratch_pad); | ||
383 | } | ||
384 | |||
385 | /** | ||
386 | * megasas_clear_interrupt_skinny - Check & clear interrupt | ||
387 | * @regs: MFI register set | ||
388 | */ | ||
389 | static int | ||
390 | megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs) | ||
391 | { | ||
392 | u32 status; | ||
393 | /* | ||
394 | * Check if it is our interrupt | ||
395 | */ | ||
396 | status = readl(®s->outbound_intr_status); | ||
397 | |||
398 | if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) { | ||
399 | return 1; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * Clear the interrupt by writing back the same value | ||
404 | */ | ||
405 | writel(status, ®s->outbound_intr_status); | ||
406 | |||
407 | /* | ||
408 | * dummy read to flush PCI | ||
409 | */ | ||
410 | readl(®s->outbound_intr_status); | ||
411 | |||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * megasas_fire_cmd_skinny - Sends command to the FW | ||
417 | * @frame_phys_addr : Physical address of cmd | ||
418 | * @frame_count : Number of frames for the command | ||
419 | * @regs : MFI register set | ||
420 | */ | ||
421 | static inline void | ||
422 | megasas_fire_cmd_skinny(struct megasas_instance *instance, | ||
423 | dma_addr_t frame_phys_addr, | ||
424 | u32 frame_count, | ||
425 | struct megasas_register_set __iomem *regs) | ||
426 | { | ||
427 | unsigned long flags; | ||
428 | spin_lock_irqsave(&instance->fire_lock, flags); | ||
429 | writel(0, &(regs)->inbound_high_queue_port); | ||
430 | writel((frame_phys_addr | (frame_count<<1))|1, | ||
431 | &(regs)->inbound_low_queue_port); | ||
432 | spin_unlock_irqrestore(&instance->fire_lock, flags); | ||
433 | } | ||
434 | |||
435 | static struct megasas_instance_template megasas_instance_template_skinny = { | ||
436 | |||
437 | .fire_cmd = megasas_fire_cmd_skinny, | ||
438 | .enable_intr = megasas_enable_intr_skinny, | ||
439 | .disable_intr = megasas_disable_intr_skinny, | ||
440 | .clear_intr = megasas_clear_intr_skinny, | ||
441 | .read_fw_status_reg = megasas_read_fw_status_reg_skinny, | ||
442 | }; | ||
443 | |||
444 | |||
445 | /** | ||
331 | * The following functions are defined for gen2 (deviceid : 0x78 0x79) | 446 | * The following functions are defined for gen2 (deviceid : 0x78 0x79) |
332 | * controllers | 447 | * controllers |
333 | */ | 448 | */ |
@@ -404,7 +519,9 @@ megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs) | |||
404 | * @regs : MFI register set | 519 | * @regs : MFI register set |
405 | */ | 520 | */ |
406 | static inline void | 521 | static inline void |
407 | megasas_fire_cmd_gen2(dma_addr_t frame_phys_addr, u32 frame_count, | 522 | megasas_fire_cmd_gen2(struct megasas_instance *instance, |
523 | dma_addr_t frame_phys_addr, | ||
524 | u32 frame_count, | ||
408 | struct megasas_register_set __iomem *regs) | 525 | struct megasas_register_set __iomem *regs) |
409 | { | 526 | { |
410 | writel((frame_phys_addr | (frame_count<<1))|1, | 527 | writel((frame_phys_addr | (frame_count<<1))|1, |
@@ -446,7 +563,8 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
446 | /* | 563 | /* |
447 | * Issue the frame using inbound queue port | 564 | * Issue the frame using inbound queue port |
448 | */ | 565 | */ |
449 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 566 | instance->instancet->fire_cmd(instance, |
567 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
450 | 568 | ||
451 | /* | 569 | /* |
452 | * Wait for cmd_status to change | 570 | * Wait for cmd_status to change |
@@ -477,7 +595,8 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, | |||
477 | { | 595 | { |
478 | cmd->cmd_status = ENODATA; | 596 | cmd->cmd_status = ENODATA; |
479 | 597 | ||
480 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 598 | instance->instancet->fire_cmd(instance, |
599 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
481 | 600 | ||
482 | wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA), | 601 | wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA), |
483 | MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); | 602 | MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); |
@@ -522,7 +641,8 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, | |||
522 | cmd->sync_cmd = 1; | 641 | cmd->sync_cmd = 1; |
523 | cmd->cmd_status = 0xFF; | 642 | cmd->cmd_status = 0xFF; |
524 | 643 | ||
525 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 644 | instance->instancet->fire_cmd(instance, |
645 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
526 | 646 | ||
527 | /* | 647 | /* |
528 | * Wait for this cmd to complete | 648 | * Wait for this cmd to complete |
@@ -592,6 +712,35 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
592 | return sge_count; | 712 | return sge_count; |
593 | } | 713 | } |
594 | 714 | ||
715 | /** | ||
716 | * megasas_make_sgl_skinny - Prepares IEEE SGL | ||
717 | * @instance: Adapter soft state | ||
718 | * @scp: SCSI command from the mid-layer | ||
719 | * @mfi_sgl: SGL to be filled in | ||
720 | * | ||
721 | * If successful, this function returns the number of SG elements. Otherwise, | ||
722 | * it returnes -1. | ||
723 | */ | ||
724 | static int | ||
725 | megasas_make_sgl_skinny(struct megasas_instance *instance, | ||
726 | struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) | ||
727 | { | ||
728 | int i; | ||
729 | int sge_count; | ||
730 | struct scatterlist *os_sgl; | ||
731 | |||
732 | sge_count = scsi_dma_map(scp); | ||
733 | |||
734 | if (sge_count) { | ||
735 | scsi_for_each_sg(scp, os_sgl, sge_count, i) { | ||
736 | mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl); | ||
737 | mfi_sgl->sge_skinny[i].phys_addr = | ||
738 | sg_dma_address(os_sgl); | ||
739 | } | ||
740 | } | ||
741 | return sge_count; | ||
742 | } | ||
743 | |||
595 | /** | 744 | /** |
596 | * megasas_get_frame_count - Computes the number of frames | 745 | * megasas_get_frame_count - Computes the number of frames |
597 | * @frame_type : type of frame- io or pthru frame | 746 | * @frame_type : type of frame- io or pthru frame |
@@ -600,7 +749,8 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
600 | * Returns the number of frames required for numnber of sge's (sge_count) | 749 | * Returns the number of frames required for numnber of sge's (sge_count) |
601 | */ | 750 | */ |
602 | 751 | ||
603 | static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | 752 | static u32 megasas_get_frame_count(struct megasas_instance *instance, |
753 | u8 sge_count, u8 frame_type) | ||
604 | { | 754 | { |
605 | int num_cnt; | 755 | int num_cnt; |
606 | int sge_bytes; | 756 | int sge_bytes; |
@@ -610,6 +760,10 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | |||
610 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | 760 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : |
611 | sizeof(struct megasas_sge32); | 761 | sizeof(struct megasas_sge32); |
612 | 762 | ||
763 | if (instance->flag_ieee) { | ||
764 | sge_sz = sizeof(struct megasas_sge_skinny); | ||
765 | } | ||
766 | |||
613 | /* | 767 | /* |
614 | * Main frame can contain 2 SGEs for 64-bit SGLs and | 768 | * Main frame can contain 2 SGEs for 64-bit SGLs and |
615 | * 3 SGEs for 32-bit SGLs for ldio & | 769 | * 3 SGEs for 32-bit SGLs for ldio & |
@@ -617,12 +771,16 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | |||
617 | * 2 SGEs for 32-bit SGLs for pthru frame | 771 | * 2 SGEs for 32-bit SGLs for pthru frame |
618 | */ | 772 | */ |
619 | if (unlikely(frame_type == PTHRU_FRAME)) { | 773 | if (unlikely(frame_type == PTHRU_FRAME)) { |
620 | if (IS_DMA64) | 774 | if (instance->flag_ieee == 1) { |
775 | num_cnt = sge_count - 1; | ||
776 | } else if (IS_DMA64) | ||
621 | num_cnt = sge_count - 1; | 777 | num_cnt = sge_count - 1; |
622 | else | 778 | else |
623 | num_cnt = sge_count - 2; | 779 | num_cnt = sge_count - 2; |
624 | } else { | 780 | } else { |
625 | if (IS_DMA64) | 781 | if (instance->flag_ieee == 1) { |
782 | num_cnt = sge_count - 1; | ||
783 | } else if (IS_DMA64) | ||
626 | num_cnt = sge_count - 2; | 784 | num_cnt = sge_count - 2; |
627 | else | 785 | else |
628 | num_cnt = sge_count - 3; | 786 | num_cnt = sge_count - 3; |
@@ -671,6 +829,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
671 | else if (scp->sc_data_direction == PCI_DMA_NONE) | 829 | else if (scp->sc_data_direction == PCI_DMA_NONE) |
672 | flags = MFI_FRAME_DIR_NONE; | 830 | flags = MFI_FRAME_DIR_NONE; |
673 | 831 | ||
832 | if (instance->flag_ieee == 1) { | ||
833 | flags |= MFI_FRAME_IEEE; | ||
834 | } | ||
835 | |||
674 | /* | 836 | /* |
675 | * Prepare the DCDB frame | 837 | * Prepare the DCDB frame |
676 | */ | 838 | */ |
@@ -687,9 +849,24 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
687 | memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); | 849 | memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); |
688 | 850 | ||
689 | /* | 851 | /* |
852 | * If the command is for the tape device, set the | ||
853 | * pthru timeout to the os layer timeout value. | ||
854 | */ | ||
855 | if (scp->device->type == TYPE_TAPE) { | ||
856 | if ((scp->request->timeout / HZ) > 0xFFFF) | ||
857 | pthru->timeout = 0xFFFF; | ||
858 | else | ||
859 | pthru->timeout = scp->request->timeout / HZ; | ||
860 | } | ||
861 | |||
862 | /* | ||
690 | * Construct SGL | 863 | * Construct SGL |
691 | */ | 864 | */ |
692 | if (IS_DMA64) { | 865 | if (instance->flag_ieee == 1) { |
866 | pthru->flags |= MFI_FRAME_SGL64; | ||
867 | pthru->sge_count = megasas_make_sgl_skinny(instance, scp, | ||
868 | &pthru->sgl); | ||
869 | } else if (IS_DMA64) { | ||
693 | pthru->flags |= MFI_FRAME_SGL64; | 870 | pthru->flags |= MFI_FRAME_SGL64; |
694 | pthru->sge_count = megasas_make_sgl64(instance, scp, | 871 | pthru->sge_count = megasas_make_sgl64(instance, scp, |
695 | &pthru->sgl); | 872 | &pthru->sgl); |
@@ -708,7 +885,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
708 | * Compute the total number of frames this command consumes. FW uses | 885 | * Compute the total number of frames this command consumes. FW uses |
709 | * this number to pull sufficient number of frames from host memory. | 886 | * this number to pull sufficient number of frames from host memory. |
710 | */ | 887 | */ |
711 | cmd->frame_count = megasas_get_frame_count(pthru->sge_count, | 888 | cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count, |
712 | PTHRU_FRAME); | 889 | PTHRU_FRAME); |
713 | 890 | ||
714 | return cmd->frame_count; | 891 | return cmd->frame_count; |
@@ -739,6 +916,10 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
739 | else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) | 916 | else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) |
740 | flags = MFI_FRAME_DIR_READ; | 917 | flags = MFI_FRAME_DIR_READ; |
741 | 918 | ||
919 | if (instance->flag_ieee == 1) { | ||
920 | flags |= MFI_FRAME_IEEE; | ||
921 | } | ||
922 | |||
742 | /* | 923 | /* |
743 | * Prepare the Logical IO frame: 2nd bit is zero for all read cmds | 924 | * Prepare the Logical IO frame: 2nd bit is zero for all read cmds |
744 | */ | 925 | */ |
@@ -809,7 +990,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
809 | /* | 990 | /* |
810 | * Construct SGL | 991 | * Construct SGL |
811 | */ | 992 | */ |
812 | if (IS_DMA64) { | 993 | if (instance->flag_ieee) { |
994 | ldio->flags |= MFI_FRAME_SGL64; | ||
995 | ldio->sge_count = megasas_make_sgl_skinny(instance, scp, | ||
996 | &ldio->sgl); | ||
997 | } else if (IS_DMA64) { | ||
813 | ldio->flags |= MFI_FRAME_SGL64; | 998 | ldio->flags |= MFI_FRAME_SGL64; |
814 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); | 999 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); |
815 | } else | 1000 | } else |
@@ -826,7 +1011,8 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
826 | * Compute the total number of frames this command consumes. FW uses | 1011 | * Compute the total number of frames this command consumes. FW uses |
827 | * this number to pull sufficient number of frames from host memory. | 1012 | * this number to pull sufficient number of frames from host memory. |
828 | */ | 1013 | */ |
829 | cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME); | 1014 | cmd->frame_count = megasas_get_frame_count(instance, |
1015 | ldio->sge_count, IO_FRAME); | ||
830 | 1016 | ||
831 | return cmd->frame_count; | 1017 | return cmd->frame_count; |
832 | } | 1018 | } |
@@ -983,7 +1169,8 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
983 | */ | 1169 | */ |
984 | atomic_inc(&instance->fw_outstanding); | 1170 | atomic_inc(&instance->fw_outstanding); |
985 | 1171 | ||
986 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set); | 1172 | instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, |
1173 | cmd->frame_count-1, instance->reg_set); | ||
987 | /* | 1174 | /* |
988 | * Check if we have pend cmds to be completed | 1175 | * Check if we have pend cmds to be completed |
989 | */ | 1176 | */ |
@@ -1000,24 +1187,76 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
1000 | return 0; | 1187 | return 0; |
1001 | } | 1188 | } |
1002 | 1189 | ||
1190 | static struct megasas_instance *megasas_lookup_instance(u16 host_no) | ||
1191 | { | ||
1192 | int i; | ||
1193 | |||
1194 | for (i = 0; i < megasas_mgmt_info.max_index; i++) { | ||
1195 | |||
1196 | if ((megasas_mgmt_info.instance[i]) && | ||
1197 | (megasas_mgmt_info.instance[i]->host->host_no == host_no)) | ||
1198 | return megasas_mgmt_info.instance[i]; | ||
1199 | } | ||
1200 | |||
1201 | return NULL; | ||
1202 | } | ||
1203 | |||
1003 | static int megasas_slave_configure(struct scsi_device *sdev) | 1204 | static int megasas_slave_configure(struct scsi_device *sdev) |
1004 | { | 1205 | { |
1206 | u16 pd_index = 0; | ||
1207 | struct megasas_instance *instance ; | ||
1208 | |||
1209 | instance = megasas_lookup_instance(sdev->host->host_no); | ||
1210 | |||
1005 | /* | 1211 | /* |
1006 | * Don't export physical disk devices to the disk driver. | 1212 | * Don't export physical disk devices to the disk driver. |
1007 | * | 1213 | * |
1008 | * FIXME: Currently we don't export them to the midlayer at all. | 1214 | * FIXME: Currently we don't export them to the midlayer at all. |
1009 | * That will be fixed once LSI engineers have audited the | 1215 | * That will be fixed once LSI engineers have audited the |
1010 | * firmware for possible issues. | 1216 | * firmware for possible issues. |
1011 | */ | 1217 | */ |
1012 | if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK) | 1218 | if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && |
1219 | sdev->type == TYPE_DISK) { | ||
1220 | pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | ||
1221 | sdev->id; | ||
1222 | if (instance->pd_list[pd_index].driveState == | ||
1223 | MR_PD_STATE_SYSTEM) { | ||
1224 | blk_queue_rq_timeout(sdev->request_queue, | ||
1225 | MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); | ||
1226 | return 0; | ||
1227 | } | ||
1013 | return -ENXIO; | 1228 | return -ENXIO; |
1229 | } | ||
1014 | 1230 | ||
1015 | /* | 1231 | /* |
1016 | * The RAID firmware may require extended timeouts. | 1232 | * The RAID firmware may require extended timeouts. |
1017 | */ | 1233 | */ |
1018 | if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) | 1234 | blk_queue_rq_timeout(sdev->request_queue, |
1019 | blk_queue_rq_timeout(sdev->request_queue, | 1235 | MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); |
1020 | MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); | 1236 | return 0; |
1237 | } | ||
1238 | |||
1239 | static int megasas_slave_alloc(struct scsi_device *sdev) | ||
1240 | { | ||
1241 | u16 pd_index = 0; | ||
1242 | struct megasas_instance *instance ; | ||
1243 | instance = megasas_lookup_instance(sdev->host->host_no); | ||
1244 | if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) && | ||
1245 | (sdev->type == TYPE_DISK)) { | ||
1246 | /* | ||
1247 | * Open the OS scan to the SYSTEM PD | ||
1248 | */ | ||
1249 | pd_index = | ||
1250 | (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | ||
1251 | sdev->id; | ||
1252 | if ((instance->pd_list[pd_index].driveState == | ||
1253 | MR_PD_STATE_SYSTEM) && | ||
1254 | (instance->pd_list[pd_index].driveType == | ||
1255 | TYPE_DISK)) { | ||
1256 | return 0; | ||
1257 | } | ||
1258 | return -ENXIO; | ||
1259 | } | ||
1021 | return 0; | 1260 | return 0; |
1022 | } | 1261 | } |
1023 | 1262 | ||
@@ -1072,7 +1311,14 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr) | |||
1072 | 1311 | ||
1073 | spin_lock_irqsave(instance->host->host_lock, flags); | 1312 | spin_lock_irqsave(instance->host->host_lock, flags); |
1074 | instance->flag &= ~MEGASAS_FW_BUSY; | 1313 | instance->flag &= ~MEGASAS_FW_BUSY; |
1075 | instance->host->can_queue = | 1314 | if ((instance->pdev->device == |
1315 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
1316 | (instance->pdev->device == | ||
1317 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1318 | instance->host->can_queue = | ||
1319 | instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; | ||
1320 | } else | ||
1321 | instance->host->can_queue = | ||
1076 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | 1322 | instance->max_fw_cmds - MEGASAS_INT_CMDS; |
1077 | 1323 | ||
1078 | spin_unlock_irqrestore(instance->host->host_lock, flags); | 1324 | spin_unlock_irqrestore(instance->host->host_lock, flags); |
@@ -1117,8 +1363,16 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) | |||
1117 | * Send signal to FW to stop processing any pending cmds. | 1363 | * Send signal to FW to stop processing any pending cmds. |
1118 | * The controller will be taken offline by the OS now. | 1364 | * The controller will be taken offline by the OS now. |
1119 | */ | 1365 | */ |
1120 | writel(MFI_STOP_ADP, | 1366 | if ((instance->pdev->device == |
1367 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
1368 | (instance->pdev->device == | ||
1369 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1370 | writel(MFI_STOP_ADP, | ||
1371 | &instance->reg_set->reserved_0[0]); | ||
1372 | } else { | ||
1373 | writel(MFI_STOP_ADP, | ||
1121 | &instance->reg_set->inbound_doorbell); | 1374 | &instance->reg_set->inbound_doorbell); |
1375 | } | ||
1122 | megasas_dump_pending_frames(instance); | 1376 | megasas_dump_pending_frames(instance); |
1123 | instance->hw_crit_error = 1; | 1377 | instance->hw_crit_error = 1; |
1124 | return FAILED; | 1378 | return FAILED; |
@@ -1266,6 +1520,8 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, | |||
1266 | return 0; | 1520 | return 0; |
1267 | } | 1521 | } |
1268 | 1522 | ||
1523 | static void megasas_aen_polling(struct work_struct *work); | ||
1524 | |||
1269 | /** | 1525 | /** |
1270 | * megasas_service_aen - Processes an event notification | 1526 | * megasas_service_aen - Processes an event notification |
1271 | * @instance: Adapter soft state | 1527 | * @instance: Adapter soft state |
@@ -1281,16 +1537,36 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, | |||
1281 | static void | 1537 | static void |
1282 | megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) | 1538 | megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) |
1283 | { | 1539 | { |
1540 | unsigned long flags; | ||
1284 | /* | 1541 | /* |
1285 | * Don't signal app if it is just an aborted previously registered aen | 1542 | * Don't signal app if it is just an aborted previously registered aen |
1286 | */ | 1543 | */ |
1287 | if (!cmd->abort_aen) | 1544 | if ((!cmd->abort_aen) && (instance->unload == 0)) { |
1545 | spin_lock_irqsave(&poll_aen_lock, flags); | ||
1546 | megasas_poll_wait_aen = 1; | ||
1547 | spin_unlock_irqrestore(&poll_aen_lock, flags); | ||
1548 | wake_up(&megasas_poll_wait); | ||
1288 | kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); | 1549 | kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); |
1550 | } | ||
1289 | else | 1551 | else |
1290 | cmd->abort_aen = 0; | 1552 | cmd->abort_aen = 0; |
1291 | 1553 | ||
1292 | instance->aen_cmd = NULL; | 1554 | instance->aen_cmd = NULL; |
1293 | megasas_return_cmd(instance, cmd); | 1555 | megasas_return_cmd(instance, cmd); |
1556 | |||
1557 | if (instance->unload == 0) { | ||
1558 | struct megasas_aen_event *ev; | ||
1559 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
1560 | if (!ev) { | ||
1561 | printk(KERN_ERR "megasas_service_aen: out of memory\n"); | ||
1562 | } else { | ||
1563 | ev->instance = instance; | ||
1564 | instance->ev = ev; | ||
1565 | INIT_WORK(&ev->hotplug_work, megasas_aen_polling); | ||
1566 | schedule_delayed_work( | ||
1567 | (struct delayed_work *)&ev->hotplug_work, 0); | ||
1568 | } | ||
1569 | } | ||
1294 | } | 1570 | } |
1295 | 1571 | ||
1296 | /* | 1572 | /* |
@@ -1302,6 +1578,7 @@ static struct scsi_host_template megasas_template = { | |||
1302 | .name = "LSI SAS based MegaRAID driver", | 1578 | .name = "LSI SAS based MegaRAID driver", |
1303 | .proc_name = "megaraid_sas", | 1579 | .proc_name = "megaraid_sas", |
1304 | .slave_configure = megasas_slave_configure, | 1580 | .slave_configure = megasas_slave_configure, |
1581 | .slave_alloc = megasas_slave_alloc, | ||
1305 | .queuecommand = megasas_queue_command, | 1582 | .queuecommand = megasas_queue_command, |
1306 | .eh_device_reset_handler = megasas_reset_device, | 1583 | .eh_device_reset_handler = megasas_reset_device, |
1307 | .eh_bus_reset_handler = megasas_reset_bus_host, | 1584 | .eh_bus_reset_handler = megasas_reset_bus_host, |
@@ -1370,6 +1647,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
1370 | { | 1647 | { |
1371 | int exception = 0; | 1648 | int exception = 0; |
1372 | struct megasas_header *hdr = &cmd->frame->hdr; | 1649 | struct megasas_header *hdr = &cmd->frame->hdr; |
1650 | unsigned long flags; | ||
1373 | 1651 | ||
1374 | if (cmd->scmd) | 1652 | if (cmd->scmd) |
1375 | cmd->scmd->SCp.ptr = NULL; | 1653 | cmd->scmd->SCp.ptr = NULL; |
@@ -1459,6 +1737,12 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
1459 | case MFI_CMD_SMP: | 1737 | case MFI_CMD_SMP: |
1460 | case MFI_CMD_STP: | 1738 | case MFI_CMD_STP: |
1461 | case MFI_CMD_DCMD: | 1739 | case MFI_CMD_DCMD: |
1740 | if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || | ||
1741 | cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { | ||
1742 | spin_lock_irqsave(&poll_aen_lock, flags); | ||
1743 | megasas_poll_wait_aen = 0; | ||
1744 | spin_unlock_irqrestore(&poll_aen_lock, flags); | ||
1745 | } | ||
1462 | 1746 | ||
1463 | /* | 1747 | /* |
1464 | * See if got an event notification | 1748 | * See if got an event notification |
@@ -1536,6 +1820,7 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1536 | u8 max_wait; | 1820 | u8 max_wait; |
1537 | u32 fw_state; | 1821 | u32 fw_state; |
1538 | u32 cur_state; | 1822 | u32 cur_state; |
1823 | u32 abs_state, curr_abs_state; | ||
1539 | 1824 | ||
1540 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; | 1825 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; |
1541 | 1826 | ||
@@ -1545,6 +1830,9 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1545 | 1830 | ||
1546 | while (fw_state != MFI_STATE_READY) { | 1831 | while (fw_state != MFI_STATE_READY) { |
1547 | 1832 | ||
1833 | abs_state = | ||
1834 | instance->instancet->read_fw_status_reg(instance->reg_set); | ||
1835 | |||
1548 | switch (fw_state) { | 1836 | switch (fw_state) { |
1549 | 1837 | ||
1550 | case MFI_STATE_FAULT: | 1838 | case MFI_STATE_FAULT: |
@@ -1556,18 +1844,36 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1556 | /* | 1844 | /* |
1557 | * Set the CLR bit in inbound doorbell | 1845 | * Set the CLR bit in inbound doorbell |
1558 | */ | 1846 | */ |
1559 | writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | 1847 | if ((instance->pdev->device == |
1560 | &instance->reg_set->inbound_doorbell); | 1848 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
1849 | (instance->pdev->device == | ||
1850 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1851 | |||
1852 | writel( | ||
1853 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | ||
1854 | &instance->reg_set->reserved_0[0]); | ||
1855 | } else { | ||
1856 | writel( | ||
1857 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | ||
1858 | &instance->reg_set->inbound_doorbell); | ||
1859 | } | ||
1561 | 1860 | ||
1562 | max_wait = 2; | 1861 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1563 | cur_state = MFI_STATE_WAIT_HANDSHAKE; | 1862 | cur_state = MFI_STATE_WAIT_HANDSHAKE; |
1564 | break; | 1863 | break; |
1565 | 1864 | ||
1566 | case MFI_STATE_BOOT_MESSAGE_PENDING: | 1865 | case MFI_STATE_BOOT_MESSAGE_PENDING: |
1567 | writel(MFI_INIT_HOTPLUG, | 1866 | if ((instance->pdev->device == |
1568 | &instance->reg_set->inbound_doorbell); | 1867 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
1868 | (instance->pdev->device == | ||
1869 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1870 | writel(MFI_INIT_HOTPLUG, | ||
1871 | &instance->reg_set->reserved_0[0]); | ||
1872 | } else | ||
1873 | writel(MFI_INIT_HOTPLUG, | ||
1874 | &instance->reg_set->inbound_doorbell); | ||
1569 | 1875 | ||
1570 | max_wait = 10; | 1876 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1571 | cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; | 1877 | cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; |
1572 | break; | 1878 | break; |
1573 | 1879 | ||
@@ -1576,9 +1882,17 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1576 | * Bring it to READY state; assuming max wait 10 secs | 1882 | * Bring it to READY state; assuming max wait 10 secs |
1577 | */ | 1883 | */ |
1578 | instance->instancet->disable_intr(instance->reg_set); | 1884 | instance->instancet->disable_intr(instance->reg_set); |
1579 | writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell); | 1885 | if ((instance->pdev->device == |
1886 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
1887 | (instance->pdev->device == | ||
1888 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1889 | writel(MFI_RESET_FLAGS, | ||
1890 | &instance->reg_set->reserved_0[0]); | ||
1891 | } else | ||
1892 | writel(MFI_RESET_FLAGS, | ||
1893 | &instance->reg_set->inbound_doorbell); | ||
1580 | 1894 | ||
1581 | max_wait = 60; | 1895 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1582 | cur_state = MFI_STATE_OPERATIONAL; | 1896 | cur_state = MFI_STATE_OPERATIONAL; |
1583 | break; | 1897 | break; |
1584 | 1898 | ||
@@ -1586,32 +1900,32 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1586 | /* | 1900 | /* |
1587 | * This state should not last for more than 2 seconds | 1901 | * This state should not last for more than 2 seconds |
1588 | */ | 1902 | */ |
1589 | max_wait = 2; | 1903 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1590 | cur_state = MFI_STATE_UNDEFINED; | 1904 | cur_state = MFI_STATE_UNDEFINED; |
1591 | break; | 1905 | break; |
1592 | 1906 | ||
1593 | case MFI_STATE_BB_INIT: | 1907 | case MFI_STATE_BB_INIT: |
1594 | max_wait = 2; | 1908 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1595 | cur_state = MFI_STATE_BB_INIT; | 1909 | cur_state = MFI_STATE_BB_INIT; |
1596 | break; | 1910 | break; |
1597 | 1911 | ||
1598 | case MFI_STATE_FW_INIT: | 1912 | case MFI_STATE_FW_INIT: |
1599 | max_wait = 20; | 1913 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1600 | cur_state = MFI_STATE_FW_INIT; | 1914 | cur_state = MFI_STATE_FW_INIT; |
1601 | break; | 1915 | break; |
1602 | 1916 | ||
1603 | case MFI_STATE_FW_INIT_2: | 1917 | case MFI_STATE_FW_INIT_2: |
1604 | max_wait = 20; | 1918 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1605 | cur_state = MFI_STATE_FW_INIT_2; | 1919 | cur_state = MFI_STATE_FW_INIT_2; |
1606 | break; | 1920 | break; |
1607 | 1921 | ||
1608 | case MFI_STATE_DEVICE_SCAN: | 1922 | case MFI_STATE_DEVICE_SCAN: |
1609 | max_wait = 20; | 1923 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1610 | cur_state = MFI_STATE_DEVICE_SCAN; | 1924 | cur_state = MFI_STATE_DEVICE_SCAN; |
1611 | break; | 1925 | break; |
1612 | 1926 | ||
1613 | case MFI_STATE_FLUSH_CACHE: | 1927 | case MFI_STATE_FLUSH_CACHE: |
1614 | max_wait = 20; | 1928 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1615 | cur_state = MFI_STATE_FLUSH_CACHE; | 1929 | cur_state = MFI_STATE_FLUSH_CACHE; |
1616 | break; | 1930 | break; |
1617 | 1931 | ||
@@ -1627,8 +1941,10 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1627 | for (i = 0; i < (max_wait * 1000); i++) { | 1941 | for (i = 0; i < (max_wait * 1000); i++) { |
1628 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & | 1942 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & |
1629 | MFI_STATE_MASK ; | 1943 | MFI_STATE_MASK ; |
1944 | curr_abs_state = | ||
1945 | instance->instancet->read_fw_status_reg(instance->reg_set); | ||
1630 | 1946 | ||
1631 | if (fw_state == cur_state) { | 1947 | if (abs_state == curr_abs_state) { |
1632 | msleep(1); | 1948 | msleep(1); |
1633 | } else | 1949 | } else |
1634 | break; | 1950 | break; |
@@ -1637,7 +1953,7 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1637 | /* | 1953 | /* |
1638 | * Return error if fw_state hasn't changed after max_wait | 1954 | * Return error if fw_state hasn't changed after max_wait |
1639 | */ | 1955 | */ |
1640 | if (fw_state == cur_state) { | 1956 | if (curr_abs_state == abs_state) { |
1641 | printk(KERN_DEBUG "FW state [%d] hasn't changed " | 1957 | printk(KERN_DEBUG "FW state [%d] hasn't changed " |
1642 | "in %d secs\n", fw_state, max_wait); | 1958 | "in %d secs\n", fw_state, max_wait); |
1643 | return -ENODEV; | 1959 | return -ENODEV; |
@@ -1715,6 +2031,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) | |||
1715 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | 2031 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : |
1716 | sizeof(struct megasas_sge32); | 2032 | sizeof(struct megasas_sge32); |
1717 | 2033 | ||
2034 | if (instance->flag_ieee) { | ||
2035 | sge_sz = sizeof(struct megasas_sge_skinny); | ||
2036 | } | ||
2037 | |||
1718 | /* | 2038 | /* |
1719 | * Calculated the number of 64byte frames required for SGL | 2039 | * Calculated the number of 64byte frames required for SGL |
1720 | */ | 2040 | */ |
@@ -1777,6 +2097,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) | |||
1777 | } | 2097 | } |
1778 | 2098 | ||
1779 | cmd->frame->io.context = cmd->index; | 2099 | cmd->frame->io.context = cmd->index; |
2100 | cmd->frame->io.pad_0 = 0; | ||
1780 | } | 2101 | } |
1781 | 2102 | ||
1782 | return 0; | 2103 | return 0; |
@@ -1882,6 +2203,97 @@ static int megasas_alloc_cmds(struct megasas_instance *instance) | |||
1882 | return 0; | 2203 | return 0; |
1883 | } | 2204 | } |
1884 | 2205 | ||
2206 | /* | ||
2207 | * megasas_get_pd_list_info - Returns FW's pd_list structure | ||
2208 | * @instance: Adapter soft state | ||
2209 | * @pd_list: pd_list structure | ||
2210 | * | ||
2211 | * Issues an internal command (DCMD) to get the FW's controller PD | ||
2212 | * list structure. This information is mainly used to find out SYSTEM | ||
2213 | * supported by the FW. | ||
2214 | */ | ||
2215 | static int | ||
2216 | megasas_get_pd_list(struct megasas_instance *instance) | ||
2217 | { | ||
2218 | int ret = 0, pd_index = 0; | ||
2219 | struct megasas_cmd *cmd; | ||
2220 | struct megasas_dcmd_frame *dcmd; | ||
2221 | struct MR_PD_LIST *ci; | ||
2222 | struct MR_PD_ADDRESS *pd_addr; | ||
2223 | dma_addr_t ci_h = 0; | ||
2224 | |||
2225 | cmd = megasas_get_cmd(instance); | ||
2226 | |||
2227 | if (!cmd) { | ||
2228 | printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n"); | ||
2229 | return -ENOMEM; | ||
2230 | } | ||
2231 | |||
2232 | dcmd = &cmd->frame->dcmd; | ||
2233 | |||
2234 | ci = pci_alloc_consistent(instance->pdev, | ||
2235 | MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h); | ||
2236 | |||
2237 | if (!ci) { | ||
2238 | printk(KERN_DEBUG "Failed to alloc mem for pd_list\n"); | ||
2239 | megasas_return_cmd(instance, cmd); | ||
2240 | return -ENOMEM; | ||
2241 | } | ||
2242 | |||
2243 | memset(ci, 0, sizeof(*ci)); | ||
2244 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
2245 | |||
2246 | dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST; | ||
2247 | dcmd->mbox.b[1] = 0; | ||
2248 | dcmd->cmd = MFI_CMD_DCMD; | ||
2249 | dcmd->cmd_status = 0xFF; | ||
2250 | dcmd->sge_count = 1; | ||
2251 | dcmd->flags = MFI_FRAME_DIR_READ; | ||
2252 | dcmd->timeout = 0; | ||
2253 | dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); | ||
2254 | dcmd->opcode = MR_DCMD_PD_LIST_QUERY; | ||
2255 | dcmd->sgl.sge32[0].phys_addr = ci_h; | ||
2256 | dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); | ||
2257 | |||
2258 | if (!megasas_issue_polled(instance, cmd)) { | ||
2259 | ret = 0; | ||
2260 | } else { | ||
2261 | ret = -1; | ||
2262 | } | ||
2263 | |||
2264 | /* | ||
2265 | * the following function will get the instance PD LIST. | ||
2266 | */ | ||
2267 | |||
2268 | pd_addr = ci->addr; | ||
2269 | |||
2270 | if ( ret == 0 && | ||
2271 | (ci->count < | ||
2272 | (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { | ||
2273 | |||
2274 | memset(instance->pd_list, 0, | ||
2275 | MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); | ||
2276 | |||
2277 | for (pd_index = 0; pd_index < ci->count; pd_index++) { | ||
2278 | |||
2279 | instance->pd_list[pd_addr->deviceId].tid = | ||
2280 | pd_addr->deviceId; | ||
2281 | instance->pd_list[pd_addr->deviceId].driveType = | ||
2282 | pd_addr->scsiDevType; | ||
2283 | instance->pd_list[pd_addr->deviceId].driveState = | ||
2284 | MR_PD_STATE_SYSTEM; | ||
2285 | pd_addr++; | ||
2286 | } | ||
2287 | } | ||
2288 | |||
2289 | pci_free_consistent(instance->pdev, | ||
2290 | MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), | ||
2291 | ci, ci_h); | ||
2292 | megasas_return_cmd(instance, cmd); | ||
2293 | |||
2294 | return ret; | ||
2295 | } | ||
2296 | |||
1885 | /** | 2297 | /** |
1886 | * megasas_get_controller_info - Returns FW's controller structure | 2298 | * megasas_get_controller_info - Returns FW's controller structure |
1887 | * @instance: Adapter soft state | 2299 | * @instance: Adapter soft state |
@@ -2081,6 +2493,8 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2081 | * Map the message registers | 2493 | * Map the message registers |
2082 | */ | 2494 | */ |
2083 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || | 2495 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || |
2496 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || | ||
2497 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
2084 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { | 2498 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { |
2085 | instance->base_addr = pci_resource_start(instance->pdev, 1); | 2499 | instance->base_addr = pci_resource_start(instance->pdev, 1); |
2086 | } else { | 2500 | } else { |
@@ -2111,6 +2525,10 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2111 | case PCI_DEVICE_ID_LSI_SAS0079GEN2: | 2525 | case PCI_DEVICE_ID_LSI_SAS0079GEN2: |
2112 | instance->instancet = &megasas_instance_template_gen2; | 2526 | instance->instancet = &megasas_instance_template_gen2; |
2113 | break; | 2527 | break; |
2528 | case PCI_DEVICE_ID_LSI_SAS0073SKINNY: | ||
2529 | case PCI_DEVICE_ID_LSI_SAS0071SKINNY: | ||
2530 | instance->instancet = &megasas_instance_template_skinny; | ||
2531 | break; | ||
2114 | case PCI_DEVICE_ID_LSI_SAS1064R: | 2532 | case PCI_DEVICE_ID_LSI_SAS1064R: |
2115 | case PCI_DEVICE_ID_DELL_PERC5: | 2533 | case PCI_DEVICE_ID_DELL_PERC5: |
2116 | default: | 2534 | default: |
@@ -2166,6 +2584,10 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2166 | if (megasas_issue_init_mfi(instance)) | 2584 | if (megasas_issue_init_mfi(instance)) |
2167 | goto fail_fw_init; | 2585 | goto fail_fw_init; |
2168 | 2586 | ||
2587 | memset(instance->pd_list, 0 , | ||
2588 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); | ||
2589 | megasas_get_pd_list(instance); | ||
2590 | |||
2169 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); | 2591 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); |
2170 | 2592 | ||
2171 | /* | 2593 | /* |
@@ -2409,6 +2831,11 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
2409 | dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; | 2831 | dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; |
2410 | dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); | 2832 | dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); |
2411 | 2833 | ||
2834 | if (instance->aen_cmd != NULL) { | ||
2835 | megasas_return_cmd(instance, cmd); | ||
2836 | return 0; | ||
2837 | } | ||
2838 | |||
2412 | /* | 2839 | /* |
2413 | * Store reference to the cmd used to register for AEN. When an | 2840 | * Store reference to the cmd used to register for AEN. When an |
2414 | * application wants us to register for AEN, we have to abort this | 2841 | * application wants us to register for AEN, we have to abort this |
@@ -2419,7 +2846,8 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
2419 | /* | 2846 | /* |
2420 | * Issue the aen registration frame | 2847 | * Issue the aen registration frame |
2421 | */ | 2848 | */ |
2422 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 2849 | instance->instancet->fire_cmd(instance, |
2850 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
2423 | 2851 | ||
2424 | return 0; | 2852 | return 0; |
2425 | } | 2853 | } |
@@ -2465,7 +2893,13 @@ static int megasas_io_attach(struct megasas_instance *instance) | |||
2465 | */ | 2893 | */ |
2466 | host->irq = instance->pdev->irq; | 2894 | host->irq = instance->pdev->irq; |
2467 | host->unique_id = instance->unique_id; | 2895 | host->unique_id = instance->unique_id; |
2468 | host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS; | 2896 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
2897 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
2898 | host->can_queue = | ||
2899 | instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; | ||
2900 | } else | ||
2901 | host->can_queue = | ||
2902 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | ||
2469 | host->this_id = instance->init_id; | 2903 | host->this_id = instance->init_id; |
2470 | host->sg_tablesize = instance->max_num_sge; | 2904 | host->sg_tablesize = instance->max_num_sge; |
2471 | host->max_sectors = instance->max_sectors_per_req; | 2905 | host->max_sectors = instance->max_sectors_per_req; |
@@ -2572,6 +3006,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2572 | 3006 | ||
2573 | *instance->producer = 0; | 3007 | *instance->producer = 0; |
2574 | *instance->consumer = 0; | 3008 | *instance->consumer = 0; |
3009 | megasas_poll_wait_aen = 0; | ||
3010 | instance->flag_ieee = 0; | ||
3011 | instance->ev = NULL; | ||
2575 | 3012 | ||
2576 | instance->evt_detail = pci_alloc_consistent(pdev, | 3013 | instance->evt_detail = pci_alloc_consistent(pdev, |
2577 | sizeof(struct | 3014 | sizeof(struct |
@@ -2595,10 +3032,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2595 | init_waitqueue_head(&instance->abort_cmd_wait_q); | 3032 | init_waitqueue_head(&instance->abort_cmd_wait_q); |
2596 | 3033 | ||
2597 | spin_lock_init(&instance->cmd_pool_lock); | 3034 | spin_lock_init(&instance->cmd_pool_lock); |
3035 | spin_lock_init(&instance->fire_lock); | ||
2598 | spin_lock_init(&instance->completion_lock); | 3036 | spin_lock_init(&instance->completion_lock); |
3037 | spin_lock_init(&poll_aen_lock); | ||
2599 | 3038 | ||
2600 | mutex_init(&instance->aen_mutex); | 3039 | mutex_init(&instance->aen_mutex); |
2601 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); | ||
2602 | 3040 | ||
2603 | /* | 3041 | /* |
2604 | * Initialize PCI related and misc parameters | 3042 | * Initialize PCI related and misc parameters |
@@ -2608,8 +3046,16 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2608 | instance->unique_id = pdev->bus->number << 8 | pdev->devfn; | 3046 | instance->unique_id = pdev->bus->number << 8 | pdev->devfn; |
2609 | instance->init_id = MEGASAS_DEFAULT_INIT_ID; | 3047 | instance->init_id = MEGASAS_DEFAULT_INIT_ID; |
2610 | 3048 | ||
3049 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
3050 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
3051 | instance->flag_ieee = 1; | ||
3052 | sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS); | ||
3053 | } else | ||
3054 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); | ||
3055 | |||
2611 | megasas_dbg_lvl = 0; | 3056 | megasas_dbg_lvl = 0; |
2612 | instance->flag = 0; | 3057 | instance->flag = 0; |
3058 | instance->unload = 1; | ||
2613 | instance->last_time = 0; | 3059 | instance->last_time = 0; |
2614 | 3060 | ||
2615 | /* | 3061 | /* |
@@ -2655,6 +3101,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2655 | if (megasas_io_attach(instance)) | 3101 | if (megasas_io_attach(instance)) |
2656 | goto fail_io_attach; | 3102 | goto fail_io_attach; |
2657 | 3103 | ||
3104 | instance->unload = 0; | ||
2658 | return 0; | 3105 | return 0; |
2659 | 3106 | ||
2660 | fail_start_aen: | 3107 | fail_start_aen: |
@@ -2778,12 +3225,23 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2778 | 3225 | ||
2779 | instance = pci_get_drvdata(pdev); | 3226 | instance = pci_get_drvdata(pdev); |
2780 | host = instance->host; | 3227 | host = instance->host; |
3228 | instance->unload = 1; | ||
2781 | 3229 | ||
2782 | if (poll_mode_io) | 3230 | if (poll_mode_io) |
2783 | del_timer_sync(&instance->io_completion_timer); | 3231 | del_timer_sync(&instance->io_completion_timer); |
2784 | 3232 | ||
2785 | megasas_flush_cache(instance); | 3233 | megasas_flush_cache(instance); |
2786 | megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); | 3234 | megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); |
3235 | |||
3236 | /* cancel the delayed work if this work still in queue */ | ||
3237 | if (instance->ev != NULL) { | ||
3238 | struct megasas_aen_event *ev = instance->ev; | ||
3239 | cancel_delayed_work( | ||
3240 | (struct delayed_work *)&ev->hotplug_work); | ||
3241 | flush_scheduled_work(); | ||
3242 | instance->ev = NULL; | ||
3243 | } | ||
3244 | |||
2787 | tasklet_kill(&instance->isr_tasklet); | 3245 | tasklet_kill(&instance->isr_tasklet); |
2788 | 3246 | ||
2789 | pci_set_drvdata(instance->pdev, instance); | 3247 | pci_set_drvdata(instance->pdev, instance); |
@@ -2873,6 +3331,8 @@ megasas_resume(struct pci_dev *pdev) | |||
2873 | megasas_start_timer(instance, &instance->io_completion_timer, | 3331 | megasas_start_timer(instance, &instance->io_completion_timer, |
2874 | megasas_io_completion_timer, | 3332 | megasas_io_completion_timer, |
2875 | MEGASAS_COMPLETION_TIMER_INTERVAL); | 3333 | MEGASAS_COMPLETION_TIMER_INTERVAL); |
3334 | instance->unload = 0; | ||
3335 | |||
2876 | return 0; | 3336 | return 0; |
2877 | 3337 | ||
2878 | fail_irq: | 3338 | fail_irq: |
@@ -2913,6 +3373,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
2913 | struct megasas_instance *instance; | 3373 | struct megasas_instance *instance; |
2914 | 3374 | ||
2915 | instance = pci_get_drvdata(pdev); | 3375 | instance = pci_get_drvdata(pdev); |
3376 | instance->unload = 1; | ||
2916 | host = instance->host; | 3377 | host = instance->host; |
2917 | 3378 | ||
2918 | if (poll_mode_io) | 3379 | if (poll_mode_io) |
@@ -2921,6 +3382,16 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
2921 | scsi_remove_host(instance->host); | 3382 | scsi_remove_host(instance->host); |
2922 | megasas_flush_cache(instance); | 3383 | megasas_flush_cache(instance); |
2923 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 3384 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
3385 | |||
3386 | /* cancel the delayed work if this work still in queue*/ | ||
3387 | if (instance->ev != NULL) { | ||
3388 | struct megasas_aen_event *ev = instance->ev; | ||
3389 | cancel_delayed_work( | ||
3390 | (struct delayed_work *)&ev->hotplug_work); | ||
3391 | flush_scheduled_work(); | ||
3392 | instance->ev = NULL; | ||
3393 | } | ||
3394 | |||
2924 | tasklet_kill(&instance->isr_tasklet); | 3395 | tasklet_kill(&instance->isr_tasklet); |
2925 | 3396 | ||
2926 | /* | 3397 | /* |
@@ -2969,6 +3440,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
2969 | static void megasas_shutdown(struct pci_dev *pdev) | 3440 | static void megasas_shutdown(struct pci_dev *pdev) |
2970 | { | 3441 | { |
2971 | struct megasas_instance *instance = pci_get_drvdata(pdev); | 3442 | struct megasas_instance *instance = pci_get_drvdata(pdev); |
3443 | instance->unload = 1; | ||
2972 | megasas_flush_cache(instance); | 3444 | megasas_flush_cache(instance); |
2973 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 3445 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
2974 | } | 3446 | } |
@@ -3016,6 +3488,23 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) | |||
3016 | } | 3488 | } |
3017 | 3489 | ||
3018 | /** | 3490 | /** |
3491 | * megasas_mgmt_poll - char node "poll" entry point | ||
3492 | * */ | ||
3493 | static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) | ||
3494 | { | ||
3495 | unsigned int mask; | ||
3496 | unsigned long flags; | ||
3497 | poll_wait(file, &megasas_poll_wait, wait); | ||
3498 | spin_lock_irqsave(&poll_aen_lock, flags); | ||
3499 | if (megasas_poll_wait_aen) | ||
3500 | mask = (POLLIN | POLLRDNORM); | ||
3501 | else | ||
3502 | mask = 0; | ||
3503 | spin_unlock_irqrestore(&poll_aen_lock, flags); | ||
3504 | return mask; | ||
3505 | } | ||
3506 | |||
3507 | /** | ||
3019 | * megasas_mgmt_fw_ioctl - Issues management ioctls to FW | 3508 | * megasas_mgmt_fw_ioctl - Issues management ioctls to FW |
3020 | * @instance: Adapter soft state | 3509 | * @instance: Adapter soft state |
3021 | * @argp: User's ioctl packet | 3510 | * @argp: User's ioctl packet |
@@ -3032,7 +3521,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3032 | int error = 0, i; | 3521 | int error = 0, i; |
3033 | void *sense = NULL; | 3522 | void *sense = NULL; |
3034 | dma_addr_t sense_handle; | 3523 | dma_addr_t sense_handle; |
3035 | u32 *sense_ptr; | 3524 | unsigned long *sense_ptr; |
3036 | 3525 | ||
3037 | memset(kbuff_arr, 0, sizeof(kbuff_arr)); | 3526 | memset(kbuff_arr, 0, sizeof(kbuff_arr)); |
3038 | 3527 | ||
@@ -3056,6 +3545,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3056 | */ | 3545 | */ |
3057 | memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); | 3546 | memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); |
3058 | cmd->frame->hdr.context = cmd->index; | 3547 | cmd->frame->hdr.context = cmd->index; |
3548 | cmd->frame->hdr.pad_0 = 0; | ||
3059 | 3549 | ||
3060 | /* | 3550 | /* |
3061 | * The management interface between applications and the fw uses | 3551 | * The management interface between applications and the fw uses |
@@ -3109,7 +3599,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3109 | } | 3599 | } |
3110 | 3600 | ||
3111 | sense_ptr = | 3601 | sense_ptr = |
3112 | (u32 *) ((unsigned long)cmd->frame + ioc->sense_off); | 3602 | (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); |
3113 | *sense_ptr = sense_handle; | 3603 | *sense_ptr = sense_handle; |
3114 | } | 3604 | } |
3115 | 3605 | ||
@@ -3140,8 +3630,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3140 | * sense_ptr points to the location that has the user | 3630 | * sense_ptr points to the location that has the user |
3141 | * sense buffer address | 3631 | * sense buffer address |
3142 | */ | 3632 | */ |
3143 | sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw + | 3633 | sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + |
3144 | ioc->sense_off); | 3634 | ioc->sense_off); |
3145 | 3635 | ||
3146 | if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), | 3636 | if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), |
3147 | sense, ioc->sense_len)) { | 3637 | sense, ioc->sense_len)) { |
@@ -3177,20 +3667,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3177 | return error; | 3667 | return error; |
3178 | } | 3668 | } |
3179 | 3669 | ||
3180 | static struct megasas_instance *megasas_lookup_instance(u16 host_no) | ||
3181 | { | ||
3182 | int i; | ||
3183 | |||
3184 | for (i = 0; i < megasas_mgmt_info.max_index; i++) { | ||
3185 | |||
3186 | if ((megasas_mgmt_info.instance[i]) && | ||
3187 | (megasas_mgmt_info.instance[i]->host->host_no == host_no)) | ||
3188 | return megasas_mgmt_info.instance[i]; | ||
3189 | } | ||
3190 | |||
3191 | return NULL; | ||
3192 | } | ||
3193 | |||
3194 | static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) | 3670 | static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) |
3195 | { | 3671 | { |
3196 | struct megasas_iocpacket __user *user_ioc = | 3672 | struct megasas_iocpacket __user *user_ioc = |
@@ -3214,6 +3690,17 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) | |||
3214 | goto out_kfree_ioc; | 3690 | goto out_kfree_ioc; |
3215 | } | 3691 | } |
3216 | 3692 | ||
3693 | if (instance->hw_crit_error == 1) { | ||
3694 | printk(KERN_DEBUG "Controller in Crit ERROR\n"); | ||
3695 | error = -ENODEV; | ||
3696 | goto out_kfree_ioc; | ||
3697 | } | ||
3698 | |||
3699 | if (instance->unload == 1) { | ||
3700 | error = -ENODEV; | ||
3701 | goto out_kfree_ioc; | ||
3702 | } | ||
3703 | |||
3217 | /* | 3704 | /* |
3218 | * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds | 3705 | * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds |
3219 | */ | 3706 | */ |
@@ -3249,6 +3736,14 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) | |||
3249 | if (!instance) | 3736 | if (!instance) |
3250 | return -ENODEV; | 3737 | return -ENODEV; |
3251 | 3738 | ||
3739 | if (instance->hw_crit_error == 1) { | ||
3740 | error = -ENODEV; | ||
3741 | } | ||
3742 | |||
3743 | if (instance->unload == 1) { | ||
3744 | return -ENODEV; | ||
3745 | } | ||
3746 | |||
3252 | mutex_lock(&instance->aen_mutex); | 3747 | mutex_lock(&instance->aen_mutex); |
3253 | error = megasas_register_aen(instance, aen.seq_num, | 3748 | error = megasas_register_aen(instance, aen.seq_num, |
3254 | aen.class_locale_word); | 3749 | aen.class_locale_word); |
@@ -3337,6 +3832,7 @@ static const struct file_operations megasas_mgmt_fops = { | |||
3337 | .open = megasas_mgmt_open, | 3832 | .open = megasas_mgmt_open, |
3338 | .fasync = megasas_mgmt_fasync, | 3833 | .fasync = megasas_mgmt_fasync, |
3339 | .unlocked_ioctl = megasas_mgmt_ioctl, | 3834 | .unlocked_ioctl = megasas_mgmt_ioctl, |
3835 | .poll = megasas_mgmt_poll, | ||
3340 | #ifdef CONFIG_COMPAT | 3836 | #ifdef CONFIG_COMPAT |
3341 | .compat_ioctl = megasas_mgmt_compat_ioctl, | 3837 | .compat_ioctl = megasas_mgmt_compat_ioctl, |
3342 | #endif | 3838 | #endif |
@@ -3378,6 +3874,15 @@ static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, | |||
3378 | NULL); | 3874 | NULL); |
3379 | 3875 | ||
3380 | static ssize_t | 3876 | static ssize_t |
3877 | megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf) | ||
3878 | { | ||
3879 | return sprintf(buf, "%u\n", support_poll_for_event); | ||
3880 | } | ||
3881 | |||
3882 | static DRIVER_ATTR(support_poll_for_event, S_IRUGO, | ||
3883 | megasas_sysfs_show_support_poll_for_event, NULL); | ||
3884 | |||
3885 | static ssize_t | ||
3381 | megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) | 3886 | megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) |
3382 | { | 3887 | { |
3383 | return sprintf(buf, "%u\n", megasas_dbg_lvl); | 3888 | return sprintf(buf, "%u\n", megasas_dbg_lvl); |
@@ -3451,6 +3956,92 @@ out: | |||
3451 | return retval; | 3956 | return retval; |
3452 | } | 3957 | } |
3453 | 3958 | ||
3959 | static void | ||
3960 | megasas_aen_polling(struct work_struct *work) | ||
3961 | { | ||
3962 | struct megasas_aen_event *ev = | ||
3963 | container_of(work, struct megasas_aen_event, hotplug_work); | ||
3964 | struct megasas_instance *instance = ev->instance; | ||
3965 | union megasas_evt_class_locale class_locale; | ||
3966 | struct Scsi_Host *host; | ||
3967 | struct scsi_device *sdev1; | ||
3968 | u16 pd_index = 0; | ||
3969 | int i, j, doscan = 0; | ||
3970 | u32 seq_num; | ||
3971 | int error; | ||
3972 | |||
3973 | if (!instance) { | ||
3974 | printk(KERN_ERR "invalid instance!\n"); | ||
3975 | kfree(ev); | ||
3976 | return; | ||
3977 | } | ||
3978 | instance->ev = NULL; | ||
3979 | host = instance->host; | ||
3980 | if (instance->evt_detail) { | ||
3981 | |||
3982 | switch (instance->evt_detail->code) { | ||
3983 | case MR_EVT_PD_INSERTED: | ||
3984 | case MR_EVT_PD_REMOVED: | ||
3985 | case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: | ||
3986 | doscan = 1; | ||
3987 | break; | ||
3988 | default: | ||
3989 | doscan = 0; | ||
3990 | break; | ||
3991 | } | ||
3992 | } else { | ||
3993 | printk(KERN_ERR "invalid evt_detail!\n"); | ||
3994 | kfree(ev); | ||
3995 | return; | ||
3996 | } | ||
3997 | |||
3998 | if (doscan) { | ||
3999 | printk(KERN_INFO "scanning ...\n"); | ||
4000 | megasas_get_pd_list(instance); | ||
4001 | for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { | ||
4002 | for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { | ||
4003 | pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; | ||
4004 | sdev1 = scsi_device_lookup(host, i, j, 0); | ||
4005 | if (instance->pd_list[pd_index].driveState == | ||
4006 | MR_PD_STATE_SYSTEM) { | ||
4007 | if (!sdev1) { | ||
4008 | scsi_add_device(host, i, j, 0); | ||
4009 | } | ||
4010 | if (sdev1) | ||
4011 | scsi_device_put(sdev1); | ||
4012 | } else { | ||
4013 | if (sdev1) { | ||
4014 | scsi_remove_device(sdev1); | ||
4015 | scsi_device_put(sdev1); | ||
4016 | } | ||
4017 | } | ||
4018 | } | ||
4019 | } | ||
4020 | } | ||
4021 | |||
4022 | if ( instance->aen_cmd != NULL ) { | ||
4023 | kfree(ev); | ||
4024 | return ; | ||
4025 | } | ||
4026 | |||
4027 | seq_num = instance->evt_detail->seq_num + 1; | ||
4028 | |||
4029 | /* Register AEN with FW for latest sequence number plus 1 */ | ||
4030 | class_locale.members.reserved = 0; | ||
4031 | class_locale.members.locale = MR_EVT_LOCALE_ALL; | ||
4032 | class_locale.members.class = MR_EVT_CLASS_DEBUG; | ||
4033 | mutex_lock(&instance->aen_mutex); | ||
4034 | error = megasas_register_aen(instance, seq_num, | ||
4035 | class_locale.word); | ||
4036 | mutex_unlock(&instance->aen_mutex); | ||
4037 | |||
4038 | if (error) | ||
4039 | printk(KERN_ERR "register aen failed error %x\n", error); | ||
4040 | |||
4041 | kfree(ev); | ||
4042 | } | ||
4043 | |||
4044 | |||
3454 | static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, | 4045 | static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, |
3455 | megasas_sysfs_show_poll_mode_io, | 4046 | megasas_sysfs_show_poll_mode_io, |
3456 | megasas_sysfs_set_poll_mode_io); | 4047 | megasas_sysfs_set_poll_mode_io); |
@@ -3468,6 +4059,8 @@ static int __init megasas_init(void) | |||
3468 | printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, | 4059 | printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, |
3469 | MEGASAS_EXT_VERSION); | 4060 | MEGASAS_EXT_VERSION); |
3470 | 4061 | ||
4062 | support_poll_for_event = 2; | ||
4063 | |||
3471 | memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); | 4064 | memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); |
3472 | 4065 | ||
3473 | /* | 4066 | /* |
@@ -3500,6 +4093,12 @@ static int __init megasas_init(void) | |||
3500 | &driver_attr_release_date); | 4093 | &driver_attr_release_date); |
3501 | if (rval) | 4094 | if (rval) |
3502 | goto err_dcf_rel_date; | 4095 | goto err_dcf_rel_date; |
4096 | |||
4097 | rval = driver_create_file(&megasas_pci_driver.driver, | ||
4098 | &driver_attr_support_poll_for_event); | ||
4099 | if (rval) | ||
4100 | goto err_dcf_support_poll_for_event; | ||
4101 | |||
3503 | rval = driver_create_file(&megasas_pci_driver.driver, | 4102 | rval = driver_create_file(&megasas_pci_driver.driver, |
3504 | &driver_attr_dbg_lvl); | 4103 | &driver_attr_dbg_lvl); |
3505 | if (rval) | 4104 | if (rval) |
@@ -3516,7 +4115,12 @@ err_dcf_poll_mode_io: | |||
3516 | &driver_attr_dbg_lvl); | 4115 | &driver_attr_dbg_lvl); |
3517 | err_dcf_dbg_lvl: | 4116 | err_dcf_dbg_lvl: |
3518 | driver_remove_file(&megasas_pci_driver.driver, | 4117 | driver_remove_file(&megasas_pci_driver.driver, |
4118 | &driver_attr_support_poll_for_event); | ||
4119 | |||
4120 | err_dcf_support_poll_for_event: | ||
4121 | driver_remove_file(&megasas_pci_driver.driver, | ||
3519 | &driver_attr_release_date); | 4122 | &driver_attr_release_date); |
4123 | |||
3520 | err_dcf_rel_date: | 4124 | err_dcf_rel_date: |
3521 | driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); | 4125 | driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); |
3522 | err_dcf_attr_ver: | 4126 | err_dcf_attr_ver: |