diff options
author | Dhananjay Phadke <dhananjay@netxen.com> | 2009-02-24 19:38:22 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-24 19:38:22 -0500 |
commit | ba599d4f0d2071abc049cb6345eab510a8a3643e (patch) | |
tree | e42bac74b45238e373d8d4b4de779ce83c1fd833 | |
parent | 32344a394029baeca5bcc9fa839694b23a82cc64 (diff) |
netxen: firmware download support
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 9 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hdr.h | 3 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 175 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 125 |
4 files changed, 238 insertions, 74 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f4dd9acb6877..b7261823189d 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
@@ -712,6 +712,15 @@ typedef enum { | |||
712 | NETXEN_FIXED_START = 0x3F0000 /* backup of crbinit */ | 712 | NETXEN_FIXED_START = 0x3F0000 /* backup of crbinit */ |
713 | } netxen_flash_map_t; | 713 | } netxen_flash_map_t; |
714 | 714 | ||
715 | #define NX_FW_VERSION_OFFSET (NETXEN_USER_START+0x408) | ||
716 | #define NX_FW_SIZE_OFFSET (NETXEN_USER_START+0x40c) | ||
717 | #define NX_BIOS_VERSION_OFFSET (NETXEN_USER_START+0x83c) | ||
718 | #define NX_FW_MAGIC_OFFSET (NETXEN_BRDCFG_START+0x128) | ||
719 | #define NX_FW_MIN_SIZE (0x3fffff) | ||
720 | #define NX_P2_MN_ROMIMAGE "nxromimg.bin" | ||
721 | #define NX_P3_CT_ROMIMAGE "nx3fwct.bin" | ||
722 | #define NX_P3_MN_ROMIMAGE "nx3fwmn.bin" | ||
723 | |||
715 | #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ | 724 | #define NETXEN_USER_START_OLD NETXEN_PXE_START /* for backward compatibility */ |
716 | 725 | ||
717 | #define NETXEN_FLASH_START (NETXEN_CRBINIT_START) | 726 | #define NETXEN_FLASH_START (NETXEN_CRBINIT_START) |
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index e80f9e3e5973..269a1f706889 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h | |||
@@ -858,6 +858,9 @@ enum { | |||
858 | #define NETXEN_PORT_MODE_ADDR (NETXEN_CAM_RAM(0x24)) | 858 | #define NETXEN_PORT_MODE_ADDR (NETXEN_CAM_RAM(0x24)) |
859 | #define NETXEN_WOL_PORT_MODE (NETXEN_CAM_RAM(0x198)) | 859 | #define NETXEN_WOL_PORT_MODE (NETXEN_CAM_RAM(0x198)) |
860 | 860 | ||
861 | #define NX_PEG_TUNE_MN_PRESENT 0x1 | ||
862 | #define NX_PEG_TUNE_CAPABILITY (NETXEN_CAM_RAM(0x02c)) | ||
863 | |||
861 | #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) | 864 | #define NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL (0x14) |
862 | 865 | ||
863 | #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) | 866 | #define ISR_MSI_INT_TRIGGER(FUNC) (NETXEN_PCIX_PS_REG(PCIX_MSI_F(FUNC))) |
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index b2f67b98c934..aef39e7a5e29 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include "netxen_nic_hw.h" | 35 | #include "netxen_nic_hw.h" |
36 | #include "netxen_nic_phan_reg.h" | 36 | #include "netxen_nic_phan_reg.h" |
37 | 37 | ||
38 | 38 | #include <linux/firmware.h> | |
39 | #include <net/ip.h> | 39 | #include <net/ip.h> |
40 | 40 | ||
41 | #define MASK(n) ((1ULL<<(n))-1) | 41 | #define MASK(n) ((1ULL<<(n))-1) |
@@ -951,24 +951,69 @@ netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) | |||
951 | (ulong)adapter->ahw.pci_base0; | 951 | (ulong)adapter->ahw.pci_base0; |
952 | } | 952 | } |
953 | 953 | ||
954 | int netxen_load_firmware(struct netxen_adapter *adapter) | 954 | static int |
955 | netxen_do_load_firmware(struct netxen_adapter *adapter, const char *fwname, | ||
956 | const struct firmware *fw) | ||
955 | { | 957 | { |
956 | int i; | 958 | u64 *ptr64; |
957 | u32 data, size = 0; | 959 | u32 i, flashaddr, size; |
958 | u32 flashaddr = NETXEN_BOOTLD_START; | 960 | struct pci_dev *pdev = adapter->pdev; |
959 | 961 | ||
960 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START)/4; | 962 | if (fw) |
963 | dev_info(&pdev->dev, "loading firmware from file %s\n", fwname); | ||
964 | else | ||
965 | dev_info(&pdev->dev, "loading firmware from flash\n"); | ||
961 | 966 | ||
962 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | 967 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
963 | adapter->pci_write_normalize(adapter, | 968 | adapter->pci_write_normalize(adapter, |
964 | NETXEN_ROMUSB_GLB_CAS_RST, 1); | 969 | NETXEN_ROMUSB_GLB_CAS_RST, 1); |
965 | 970 | ||
966 | for (i = 0; i < size; i++) { | 971 | if (fw) { |
967 | if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) | 972 | __le64 data; |
968 | return -EIO; | 973 | |
974 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; | ||
975 | |||
976 | ptr64 = (u64 *)&fw->data[NETXEN_BOOTLD_START]; | ||
977 | flashaddr = NETXEN_BOOTLD_START; | ||
978 | |||
979 | for (i = 0; i < size; i++) { | ||
980 | data = cpu_to_le64(ptr64[i]); | ||
981 | adapter->pci_mem_write(adapter, flashaddr, &data, 8); | ||
982 | flashaddr += 8; | ||
983 | } | ||
984 | |||
985 | size = *(u32 *)&fw->data[NX_FW_SIZE_OFFSET]; | ||
986 | size = (__force u32)cpu_to_le32(size) / 8; | ||
987 | |||
988 | ptr64 = (u64 *)&fw->data[NETXEN_IMAGE_START]; | ||
989 | flashaddr = NETXEN_IMAGE_START; | ||
990 | |||
991 | for (i = 0; i < size; i++) { | ||
992 | data = cpu_to_le64(ptr64[i]); | ||
993 | |||
994 | if (adapter->pci_mem_write(adapter, | ||
995 | flashaddr, &data, 8)) | ||
996 | return -EIO; | ||
997 | |||
998 | flashaddr += 8; | ||
999 | } | ||
1000 | } else { | ||
1001 | u32 data; | ||
1002 | |||
1003 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 4; | ||
1004 | flashaddr = NETXEN_BOOTLD_START; | ||
969 | 1005 | ||
970 | adapter->pci_mem_write(adapter, flashaddr, &data, 4); | 1006 | for (i = 0; i < size; i++) { |
971 | flashaddr += 4; | 1007 | if (netxen_rom_fast_read(adapter, |
1008 | flashaddr, (int *)&data) != 0) | ||
1009 | return -EIO; | ||
1010 | |||
1011 | if (adapter->pci_mem_write(adapter, | ||
1012 | flashaddr, &data, 4)) | ||
1013 | return -EIO; | ||
1014 | |||
1015 | flashaddr += 4; | ||
1016 | } | ||
972 | } | 1017 | } |
973 | msleep(1); | 1018 | msleep(1); |
974 | 1019 | ||
@@ -985,6 +1030,114 @@ int netxen_load_firmware(struct netxen_adapter *adapter) | |||
985 | return 0; | 1030 | return 0; |
986 | } | 1031 | } |
987 | 1032 | ||
1033 | static int | ||
1034 | netxen_validate_firmware(struct netxen_adapter *adapter, const char *fwname, | ||
1035 | const struct firmware *fw) | ||
1036 | { | ||
1037 | __le32 val; | ||
1038 | u32 major, minor, build, ver, min_ver, bios; | ||
1039 | struct pci_dev *pdev = adapter->pdev; | ||
1040 | |||
1041 | if (fw->size < NX_FW_MIN_SIZE) | ||
1042 | return -EINVAL; | ||
1043 | |||
1044 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); | ||
1045 | if ((__force u32)val != NETXEN_BDINFO_MAGIC) | ||
1046 | return -EINVAL; | ||
1047 | |||
1048 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); | ||
1049 | major = (__force u32)val & 0xff; | ||
1050 | minor = ((__force u32)val >> 8) & 0xff; | ||
1051 | build = (__force u32)val >> 16; | ||
1052 | |||
1053 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
1054 | min_ver = NETXEN_VERSION_CODE(4, 0, 216); | ||
1055 | else | ||
1056 | min_ver = NETXEN_VERSION_CODE(3, 4, 216); | ||
1057 | |||
1058 | ver = NETXEN_VERSION_CODE(major, minor, build); | ||
1059 | |||
1060 | if ((major > _NETXEN_NIC_LINUX_MAJOR) || (ver < min_ver)) { | ||
1061 | dev_err(&pdev->dev, | ||
1062 | "%s: firmware version %d.%d.%d unsupported\n", | ||
1063 | fwname, major, minor, build); | ||
1064 | return -EINVAL; | ||
1065 | } | ||
1066 | |||
1067 | val = cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); | ||
1068 | netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); | ||
1069 | if ((__force u32)val != bios) { | ||
1070 | dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", | ||
1071 | fwname); | ||
1072 | return -EINVAL; | ||
1073 | } | ||
1074 | |||
1075 | netxen_nic_reg_write(adapter, NETXEN_CAM_RAM(0x1fc), | ||
1076 | NETXEN_BDINFO_MAGIC); | ||
1077 | return 0; | ||
1078 | } | ||
1079 | |||
1080 | int netxen_load_firmware(struct netxen_adapter *adapter) | ||
1081 | { | ||
1082 | u32 capability, flashed_ver; | ||
1083 | const struct firmware *fw; | ||
1084 | char *fw_name = NULL; | ||
1085 | struct pci_dev *pdev = adapter->pdev; | ||
1086 | int rc = 0; | ||
1087 | |||
1088 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1089 | fw_name = NX_P2_MN_ROMIMAGE; | ||
1090 | goto request_fw; | ||
1091 | } | ||
1092 | |||
1093 | capability = 0; | ||
1094 | |||
1095 | netxen_rom_fast_read(adapter, | ||
1096 | NX_FW_VERSION_OFFSET, (int *)&flashed_ver); | ||
1097 | if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { | ||
1098 | adapter->hw_read_wx(adapter, | ||
1099 | NX_PEG_TUNE_CAPABILITY, &capability, 4); | ||
1100 | if (capability & NX_PEG_TUNE_MN_PRESENT) { | ||
1101 | fw_name = NX_P3_MN_ROMIMAGE; | ||
1102 | goto request_fw; | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1106 | request_ct: | ||
1107 | fw_name = NX_P3_CT_ROMIMAGE; | ||
1108 | |||
1109 | request_fw: | ||
1110 | rc = request_firmware(&fw, fw_name, &pdev->dev); | ||
1111 | if (rc != 0) { | ||
1112 | if (fw_name == NX_P3_MN_ROMIMAGE) { | ||
1113 | msleep(1); | ||
1114 | goto request_ct; | ||
1115 | } | ||
1116 | |||
1117 | fw = NULL; | ||
1118 | goto load_fw; | ||
1119 | } | ||
1120 | |||
1121 | rc = netxen_validate_firmware(adapter, fw_name, fw); | ||
1122 | if (rc != 0) { | ||
1123 | release_firmware(fw); | ||
1124 | |||
1125 | if (fw_name == NX_P3_MN_ROMIMAGE) { | ||
1126 | msleep(1); | ||
1127 | goto request_ct; | ||
1128 | } | ||
1129 | |||
1130 | fw = NULL; | ||
1131 | } | ||
1132 | |||
1133 | load_fw: | ||
1134 | rc = netxen_do_load_firmware(adapter, fw_name, fw); | ||
1135 | |||
1136 | if (fw) | ||
1137 | release_firmware(fw); | ||
1138 | return rc; | ||
1139 | } | ||
1140 | |||
988 | int | 1141 | int |
989 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, | 1142 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, |
990 | ulong off, void *data, int len) | 1143 | ulong off, void *data, int len) |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 2648e9026726..9d6e68fe0c94 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -457,18 +457,65 @@ static const struct net_device_ops netxen_netdev_ops = { | |||
457 | #endif | 457 | #endif |
458 | }; | 458 | }; |
459 | 459 | ||
460 | /* | 460 | static int |
461 | * netxen_nic_probe() | 461 | netxen_start_firmware(struct netxen_adapter *adapter) |
462 | * | 462 | { |
463 | * The Linux system will invoke this after identifying the vendor ID and | 463 | int val, err, first_boot; |
464 | * device Id in the pci_tbl supported by this module. | 464 | struct pci_dev *pdev = adapter->pdev; |
465 | * | 465 | |
466 | * A quad port card has one operational PCI config space, (function 0), | 466 | first_boot = adapter->pci_read_normalize(adapter, |
467 | * which is used to access all four ports. | 467 | NETXEN_CAM_RAM(0x1fc)); |
468 | * | 468 | |
469 | * This routine will initialize the adapter, and setup the global parameters | 469 | err = netxen_check_hw_init(adapter, first_boot); |
470 | * along with the port's specific structure. | 470 | if (err) { |
471 | */ | 471 | dev_err(&pdev->dev, "error in init HW init sequence\n"); |
472 | return err; | ||
473 | } | ||
474 | |||
475 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
476 | netxen_set_port_mode(adapter); | ||
477 | |||
478 | if (first_boot != 0x55555555) { | ||
479 | adapter->pci_write_normalize(adapter, | ||
480 | CRB_CMDPEG_STATE, 0); | ||
481 | netxen_pinit_from_rom(adapter, 0); | ||
482 | msleep(1); | ||
483 | } | ||
484 | netxen_load_firmware(adapter); | ||
485 | |||
486 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
487 | |||
488 | /* Initialize multicast addr pool owners */ | ||
489 | val = 0x7654; | ||
490 | if (adapter->ahw.board_type == NETXEN_NIC_XGBE) | ||
491 | val |= 0x0f000000; | ||
492 | netxen_crb_writelit_adapter(adapter, | ||
493 | NETXEN_MAC_ADDR_CNTL_REG, val); | ||
494 | |||
495 | } | ||
496 | |||
497 | err = netxen_initialize_adapter_offload(adapter); | ||
498 | if (err) | ||
499 | return err; | ||
500 | |||
501 | /* | ||
502 | * Tell the hardware our version number. | ||
503 | */ | ||
504 | val = (_NETXEN_NIC_LINUX_MAJOR << 16) | ||
505 | | ((_NETXEN_NIC_LINUX_MINOR << 8)) | ||
506 | | (_NETXEN_NIC_LINUX_SUBVERSION); | ||
507 | adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, val); | ||
508 | |||
509 | /* Handshake with the card before we register the devices. */ | ||
510 | err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); | ||
511 | if (err) { | ||
512 | netxen_free_adapter_offload(adapter); | ||
513 | return err; | ||
514 | } | ||
515 | |||
516 | return 0; | ||
517 | } | ||
518 | |||
472 | static int __devinit | 519 | static int __devinit |
473 | netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 520 | netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
474 | { | 521 | { |
@@ -484,7 +531,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
484 | u8 __iomem *db_ptr = NULL; | 531 | u8 __iomem *db_ptr = NULL; |
485 | unsigned long mem_base, mem_len, db_base, db_len = 0, pci_len0 = 0; | 532 | unsigned long mem_base, mem_len, db_base, db_len = 0, pci_len0 = 0; |
486 | int i = 0, err; | 533 | int i = 0, err; |
487 | int first_driver, first_boot; | 534 | int first_driver; |
488 | u32 val; | 535 | u32 val; |
489 | int pci_func_id = PCI_FUNC(pdev->devfn); | 536 | int pci_func_id = PCI_FUNC(pdev->devfn); |
490 | struct netxen_legacy_intr_set *legacy_intrp; | 537 | struct netxen_legacy_intr_set *legacy_intrp; |
@@ -736,56 +783,10 @@ skip_doorbell: | |||
736 | } | 783 | } |
737 | 784 | ||
738 | if (first_driver) { | 785 | if (first_driver) { |
739 | first_boot = adapter->pci_read_normalize(adapter, | 786 | err = netxen_start_firmware(adapter); |
740 | NETXEN_CAM_RAM(0x1fc)); | ||
741 | |||
742 | err = netxen_check_hw_init(adapter, first_boot); | ||
743 | if (err) { | ||
744 | printk(KERN_ERR "%s: error in init HW init sequence\n", | ||
745 | netxen_nic_driver_name); | ||
746 | goto err_out_iounmap; | ||
747 | } | ||
748 | |||
749 | if (NX_IS_REVISION_P3(revision_id)) | ||
750 | netxen_set_port_mode(adapter); | ||
751 | |||
752 | if (first_boot != 0x55555555) { | ||
753 | adapter->pci_write_normalize(adapter, | ||
754 | CRB_CMDPEG_STATE, 0); | ||
755 | netxen_pinit_from_rom(adapter, 0); | ||
756 | msleep(1); | ||
757 | } | ||
758 | netxen_load_firmware(adapter); | ||
759 | |||
760 | if (NX_IS_REVISION_P2(revision_id)) { | ||
761 | |||
762 | /* Initialize multicast addr pool owners */ | ||
763 | val = 0x7654; | ||
764 | if (adapter->ahw.board_type == NETXEN_NIC_XGBE) | ||
765 | val |= 0x0f000000; | ||
766 | netxen_crb_writelit_adapter(adapter, | ||
767 | NETXEN_MAC_ADDR_CNTL_REG, val); | ||
768 | |||
769 | } | ||
770 | |||
771 | err = netxen_initialize_adapter_offload(adapter); | ||
772 | if (err) | 787 | if (err) |
773 | goto err_out_iounmap; | 788 | goto err_out_iounmap; |
774 | 789 | } | |
775 | /* | ||
776 | * Tell the hardware our version number. | ||
777 | */ | ||
778 | i = (_NETXEN_NIC_LINUX_MAJOR << 16) | ||
779 | | ((_NETXEN_NIC_LINUX_MINOR << 8)) | ||
780 | | (_NETXEN_NIC_LINUX_SUBVERSION); | ||
781 | adapter->pci_write_normalize(adapter, CRB_DRIVER_VERSION, i); | ||
782 | |||
783 | /* Handshake with the card before we register the devices. */ | ||
784 | err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); | ||
785 | if (err) | ||
786 | goto err_out_free_offload; | ||
787 | |||
788 | } /* first_driver */ | ||
789 | 790 | ||
790 | netxen_nic_flash_print(adapter); | 791 | netxen_nic_flash_print(adapter); |
791 | 792 | ||
@@ -890,14 +891,12 @@ err_out_disable_msi: | |||
890 | if (adapter->flags & NETXEN_NIC_MSI_ENABLED) | 891 | if (adapter->flags & NETXEN_NIC_MSI_ENABLED) |
891 | pci_disable_msi(pdev); | 892 | pci_disable_msi(pdev); |
892 | 893 | ||
893 | err_out_free_offload: | ||
894 | if (first_driver) | 894 | if (first_driver) |
895 | netxen_free_adapter_offload(adapter); | 895 | netxen_free_adapter_offload(adapter); |
896 | 896 | ||
897 | err_out_iounmap: | 897 | err_out_iounmap: |
898 | if (db_ptr) | 898 | if (db_ptr) |
899 | iounmap(db_ptr); | 899 | iounmap(db_ptr); |
900 | |||
901 | if (mem_ptr0) | 900 | if (mem_ptr0) |
902 | iounmap(mem_ptr0); | 901 | iounmap(mem_ptr0); |
903 | if (mem_ptr1) | 902 | if (mem_ptr1) |