diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_init.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_init.c | 104 |
1 files changed, 90 insertions, 14 deletions
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index aef093db597e..880de6f380e9 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -770,29 +770,104 @@ qla24xx_chip_diag(scsi_qla_host_t *ha) | |||
770 | return rval; | 770 | return rval; |
771 | } | 771 | } |
772 | 772 | ||
773 | static void | 773 | void |
774 | qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) | 774 | qla2x00_alloc_fw_dump(scsi_qla_host_t *ha) |
775 | { | 775 | { |
776 | uint32_t dump_size = 0; | 776 | int rval; |
777 | uint32_t dump_size, fixed_size, mem_size, req_q_size, rsp_q_size, | ||
778 | eft_size; | ||
779 | dma_addr_t eft_dma; | ||
780 | void *eft; | ||
781 | |||
782 | if (ha->fw_dump) { | ||
783 | qla_printk(KERN_WARNING, ha, | ||
784 | "Firmware dump previously allocated.\n"); | ||
785 | return; | ||
786 | } | ||
777 | 787 | ||
778 | ha->fw_dumped = 0; | 788 | ha->fw_dumped = 0; |
789 | fixed_size = mem_size = eft_size = 0; | ||
779 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { | 790 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) { |
780 | dump_size = sizeof(struct qla2100_fw_dump); | 791 | fixed_size = sizeof(struct qla2100_fw_dump); |
781 | } else if (IS_QLA23XX(ha)) { | 792 | } else if (IS_QLA23XX(ha)) { |
782 | dump_size = sizeof(struct qla2300_fw_dump); | 793 | fixed_size = offsetof(struct qla2300_fw_dump, data_ram); |
783 | dump_size += (ha->fw_memory_size - 0x11000) * sizeof(uint16_t); | 794 | mem_size = (ha->fw_memory_size - 0x11000 + 1) * |
784 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { | 795 | sizeof(uint16_t); |
785 | dump_size = sizeof(struct qla24xx_fw_dump); | 796 | } else if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { |
786 | dump_size += (ha->fw_memory_size - 0x100000) * sizeof(uint32_t); | 797 | fixed_size = offsetof(struct qla24xx_fw_dump, ext_mem); |
798 | mem_size = (ha->fw_memory_size - 0x100000 + 1) * | ||
799 | sizeof(uint32_t); | ||
800 | |||
801 | /* Allocate memory for Extended Trace Buffer. */ | ||
802 | eft = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &eft_dma, | ||
803 | GFP_KERNEL); | ||
804 | if (!eft) { | ||
805 | qla_printk(KERN_WARNING, ha, "Unable to allocate " | ||
806 | "(%d KB) for EFT.\n", EFT_SIZE / 1024); | ||
807 | goto cont_alloc; | ||
808 | } | ||
809 | |||
810 | rval = qla2x00_trace_control(ha, TC_ENABLE, eft_dma, | ||
811 | EFT_NUM_BUFFERS); | ||
812 | if (rval) { | ||
813 | qla_printk(KERN_WARNING, ha, "Unable to initialize " | ||
814 | "EFT (%d).\n", rval); | ||
815 | dma_free_coherent(&ha->pdev->dev, EFT_SIZE, eft, | ||
816 | eft_dma); | ||
817 | goto cont_alloc; | ||
818 | } | ||
819 | |||
820 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for EFT...\n", | ||
821 | EFT_SIZE / 1024); | ||
822 | |||
823 | eft_size = EFT_SIZE; | ||
824 | memset(eft, 0, eft_size); | ||
825 | ha->eft_dma = eft_dma; | ||
826 | ha->eft = eft; | ||
787 | } | 827 | } |
828 | cont_alloc: | ||
829 | req_q_size = ha->request_q_length * sizeof(request_t); | ||
830 | rsp_q_size = ha->response_q_length * sizeof(response_t); | ||
831 | |||
832 | dump_size = offsetof(struct qla2xxx_fw_dump, isp); | ||
833 | dump_size += fixed_size + mem_size + req_q_size + rsp_q_size + | ||
834 | eft_size; | ||
788 | 835 | ||
789 | ha->fw_dump = vmalloc(dump_size); | 836 | ha->fw_dump = vmalloc(dump_size); |
790 | if (ha->fw_dump) | 837 | if (!ha->fw_dump) { |
791 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware " | ||
792 | "dump...\n", dump_size / 1024); | ||
793 | else | ||
794 | qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " | 838 | qla_printk(KERN_WARNING, ha, "Unable to allocate (%d KB) for " |
795 | "firmware dump!!!\n", dump_size / 1024); | 839 | "firmware dump!!!\n", dump_size / 1024); |
840 | |||
841 | if (ha->eft) { | ||
842 | dma_free_coherent(&ha->pdev->dev, eft_size, ha->eft, | ||
843 | ha->eft_dma); | ||
844 | ha->eft = NULL; | ||
845 | ha->eft_dma = 0; | ||
846 | } | ||
847 | return; | ||
848 | } | ||
849 | |||
850 | qla_printk(KERN_INFO, ha, "Allocated (%d KB) for firmware dump...\n", | ||
851 | dump_size / 1024); | ||
852 | |||
853 | ha->fw_dump_len = dump_size; | ||
854 | ha->fw_dump->signature[0] = 'Q'; | ||
855 | ha->fw_dump->signature[1] = 'L'; | ||
856 | ha->fw_dump->signature[2] = 'G'; | ||
857 | ha->fw_dump->signature[3] = 'C'; | ||
858 | ha->fw_dump->version = __constant_htonl(1); | ||
859 | |||
860 | ha->fw_dump->fixed_size = htonl(fixed_size); | ||
861 | ha->fw_dump->mem_size = htonl(mem_size); | ||
862 | ha->fw_dump->req_q_size = htonl(req_q_size); | ||
863 | ha->fw_dump->rsp_q_size = htonl(rsp_q_size); | ||
864 | |||
865 | ha->fw_dump->eft_size = htonl(eft_size); | ||
866 | ha->fw_dump->eft_addr_l = htonl(LSD(ha->eft_dma)); | ||
867 | ha->fw_dump->eft_addr_h = htonl(MSD(ha->eft_dma)); | ||
868 | |||
869 | ha->fw_dump->header_size = | ||
870 | htonl(offsetof(struct qla2xxx_fw_dump, isp)); | ||
796 | } | 871 | } |
797 | 872 | ||
798 | /** | 873 | /** |
@@ -810,8 +885,6 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) | |||
810 | dma_addr_t request_dma; | 885 | dma_addr_t request_dma; |
811 | request_t *request_ring; | 886 | request_t *request_ring; |
812 | 887 | ||
813 | qla2x00_alloc_fw_dump(ha); | ||
814 | |||
815 | /* Valid only on recent ISPs. */ | 888 | /* Valid only on recent ISPs. */ |
816 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) | 889 | if (IS_QLA2100(ha) || IS_QLA2200(ha)) |
817 | return; | 890 | return; |
@@ -883,6 +956,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) | |||
883 | &ha->fw_subminor_version, | 956 | &ha->fw_subminor_version, |
884 | &ha->fw_attributes, &ha->fw_memory_size); | 957 | &ha->fw_attributes, &ha->fw_memory_size); |
885 | qla2x00_resize_request_q(ha); | 958 | qla2x00_resize_request_q(ha); |
959 | |||
960 | if (ql2xallocfwdump) | ||
961 | qla2x00_alloc_fw_dump(ha); | ||
886 | } | 962 | } |
887 | } else { | 963 | } else { |
888 | DEBUG2(printk(KERN_INFO | 964 | DEBUG2(printk(KERN_INFO |