diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-04-28 11:29:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-04-29 01:44:31 -0400 |
commit | f7185c71234434d48b96f9a0387737df1759a4af (patch) | |
tree | 1974fad5606305f11a750e66ec1e45f0f89a65ac /drivers/net/netxen/netxen_nic_init.c | |
parent | 4ea528a151549df795c984649d75860ea40390bd (diff) |
netxen: fix firmware download
o hold the firmware in memory across suspend, since filesystem
may not be up after resuming.
o reset the chip after requesting firmware, to minimize downtime
for NC-SI.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/netxen/netxen_nic_init.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 363ef701e71e..d18216779a09 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -683,6 +683,202 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) | |||
683 | return 0; | 683 | return 0; |
684 | } | 684 | } |
685 | 685 | ||
686 | int | ||
687 | netxen_load_firmware(struct netxen_adapter *adapter) | ||
688 | { | ||
689 | u64 *ptr64; | ||
690 | u32 i, flashaddr, size; | ||
691 | const struct firmware *fw = adapter->fw; | ||
692 | |||
693 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
694 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); | ||
695 | |||
696 | if (fw) { | ||
697 | __le64 data; | ||
698 | |||
699 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; | ||
700 | |||
701 | ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; | ||
702 | flashaddr = NETXEN_BOOTLD_START; | ||
703 | |||
704 | for (i = 0; i < size; i++) { | ||
705 | data = cpu_to_le64(ptr64[i]); | ||
706 | adapter->pci_mem_write(adapter, flashaddr, &data, 8); | ||
707 | flashaddr += 8; | ||
708 | } | ||
709 | |||
710 | size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; | ||
711 | size = (__force u32)cpu_to_le32(size) / 8; | ||
712 | |||
713 | ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; | ||
714 | flashaddr = NETXEN_IMAGE_START; | ||
715 | |||
716 | for (i = 0; i < size; i++) { | ||
717 | data = cpu_to_le64(ptr64[i]); | ||
718 | |||
719 | if (adapter->pci_mem_write(adapter, | ||
720 | flashaddr, &data, 8)) | ||
721 | return -EIO; | ||
722 | |||
723 | flashaddr += 8; | ||
724 | } | ||
725 | } else { | ||
726 | u32 data; | ||
727 | |||
728 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; | ||
729 | flashaddr = NETXEN_BOOTLD_START; | ||
730 | |||
731 | for (i = 0; i < size; i++) { | ||
732 | if (netxen_rom_fast_read(adapter, | ||
733 | flashaddr, (int *)&data) != 0) | ||
734 | return -EIO; | ||
735 | |||
736 | if (adapter->pci_mem_write(adapter, | ||
737 | flashaddr, &data, 4)) | ||
738 | return -EIO; | ||
739 | |||
740 | flashaddr += 4; | ||
741 | } | ||
742 | } | ||
743 | msleep(1); | ||
744 | |||
745 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
746 | NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); | ||
747 | else { | ||
748 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); | ||
749 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0); | ||
750 | } | ||
751 | |||
752 | return 0; | ||
753 | } | ||
754 | |||
755 | static int | ||
756 | netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname) | ||
757 | { | ||
758 | __le32 val; | ||
759 | u32 major, minor, build, ver, min_ver, bios; | ||
760 | struct pci_dev *pdev = adapter->pdev; | ||
761 | const struct firmware *fw = adapter->fw; | ||
762 | |||
763 | if (fw->size < NX_FW_MIN_SIZE) | ||
764 | return -EINVAL; | ||
765 | |||
766 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); | ||
767 | if ((__force u32)val != NETXEN_BDINFO_MAGIC) | ||
768 | return -EINVAL; | ||
769 | |||
770 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); | ||
771 | major = (__force u32)val & 0xff; | ||
772 | minor = ((__force u32)val >> 8) & 0xff; | ||
773 | build = (__force u32)val >> 16; | ||
774 | |||
775 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
776 | min_ver = NETXEN_VERSION_CODE(4, 0, 216); | ||
777 | else | ||
778 | min_ver = NETXEN_VERSION_CODE(3, 4, 216); | ||
779 | |||
780 | ver = NETXEN_VERSION_CODE(major, minor, build); | ||
781 | |||
782 | if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { | ||
783 | dev_err(&pdev->dev, | ||
784 | "%s: firmware version %d.%d.%d unsupported\n", | ||
785 | fwname, major, minor, build); | ||
786 | return -EINVAL; | ||
787 | } | ||
788 | |||
789 | val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); | ||
790 | netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); | ||
791 | if ((__force u32)val != bios) { | ||
792 | dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", | ||
793 | fwname); | ||
794 | return -EINVAL; | ||
795 | } | ||
796 | |||
797 | /* check if flashed firmware is newer */ | ||
798 | if (netxen_rom_fast_read(adapter, | ||
799 | NX_FW_VERSION_OFFSET, (int *)&val)) | ||
800 | return -EIO; | ||
801 | major = (__force u32)val & 0xff; | ||
802 | minor = ((__force u32)val >> 8) & 0xff; | ||
803 | build = (__force u32)val >> 16; | ||
804 | if (NETXEN_VERSION_CODE(major, minor, build) > ver) | ||
805 | return -EINVAL; | ||
806 | |||
807 | NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); | ||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | static char *fw_name[] = { "nxromimg.bin", "nx3fwct.bin", "nx3fwmn.bin" }; | ||
812 | |||
813 | void netxen_request_firmware(struct netxen_adapter *adapter) | ||
814 | { | ||
815 | u32 capability, flashed_ver; | ||
816 | int fw_type; | ||
817 | struct pci_dev *pdev = adapter->pdev; | ||
818 | int rc = 0; | ||
819 | |||
820 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
821 | fw_type = NX_P2_MN_ROMIMAGE; | ||
822 | goto request_fw; | ||
823 | } else { | ||
824 | fw_type = NX_P3_CT_ROMIMAGE; | ||
825 | goto request_fw; | ||
826 | } | ||
827 | |||
828 | request_mn: | ||
829 | capability = 0; | ||
830 | |||
831 | netxen_rom_fast_read(adapter, | ||
832 | NX_FW_VERSION_OFFSET, (int *)&flashed_ver); | ||
833 | if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { | ||
834 | capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); | ||
835 | if (capability & NX_PEG_TUNE_MN_PRESENT) { | ||
836 | fw_type = NX_P3_MN_ROMIMAGE; | ||
837 | goto request_fw; | ||
838 | } | ||
839 | } | ||
840 | |||
841 | request_fw: | ||
842 | rc = request_firmware(&adapter->fw, fw_name[fw_type], &pdev->dev); | ||
843 | if (rc != 0) { | ||
844 | if (fw_type == NX_P3_CT_ROMIMAGE) { | ||
845 | msleep(1); | ||
846 | goto request_mn; | ||
847 | } | ||
848 | |||
849 | adapter->fw = NULL; | ||
850 | goto done; | ||
851 | } | ||
852 | |||
853 | rc = netxen_validate_firmware(adapter, fw_name[fw_type]); | ||
854 | if (rc != 0) { | ||
855 | release_firmware(adapter->fw); | ||
856 | |||
857 | if (fw_type == NX_P3_CT_ROMIMAGE) { | ||
858 | msleep(1); | ||
859 | goto request_mn; | ||
860 | } | ||
861 | |||
862 | adapter->fw = NULL; | ||
863 | goto done; | ||
864 | } | ||
865 | |||
866 | done: | ||
867 | if (adapter->fw) | ||
868 | dev_info(&pdev->dev, "loading firmware from file %s\n", | ||
869 | fw_name[fw_type]); | ||
870 | else | ||
871 | dev_info(&pdev->dev, "loading firmware from flash\n"); | ||
872 | } | ||
873 | |||
874 | |||
875 | void | ||
876 | netxen_release_firmware(struct netxen_adapter *adapter) | ||
877 | { | ||
878 | if (adapter->fw) | ||
879 | release_firmware(adapter->fw); | ||
880 | } | ||
881 | |||
686 | int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) | 882 | int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) |
687 | { | 883 | { |
688 | uint64_t addr; | 884 | uint64_t addr; |