diff options
Diffstat (limited to 'drivers/net/acenic.c')
| -rw-r--r-- | drivers/net/acenic.c | 117 |
1 files changed, 71 insertions, 46 deletions
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 517fce48d94a..5b396ff6c83f 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #include <linux/mm.h> | 66 | #include <linux/mm.h> |
| 67 | #include <linux/highmem.h> | 67 | #include <linux/highmem.h> |
| 68 | #include <linux/sockios.h> | 68 | #include <linux/sockios.h> |
| 69 | #include <linux/firmware.h> | ||
| 69 | 70 | ||
| 70 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) | 71 | #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |
| 71 | #include <linux/if_vlan.h> | 72 | #include <linux/if_vlan.h> |
| @@ -186,8 +187,6 @@ MODULE_DEVICE_TABLE(pci, acenic_pci_tbl); | |||
| 186 | #define MAX_RODATA_LEN 8*1024 | 187 | #define MAX_RODATA_LEN 8*1024 |
| 187 | #define MAX_DATA_LEN 2*1024 | 188 | #define MAX_DATA_LEN 2*1024 |
| 188 | 189 | ||
| 189 | #include "acenic_firmware.h" | ||
| 190 | |||
| 191 | #ifndef tigon2FwReleaseLocal | 190 | #ifndef tigon2FwReleaseLocal |
| 192 | #define tigon2FwReleaseLocal 0 | 191 | #define tigon2FwReleaseLocal 0 |
| 193 | #endif | 192 | #endif |
| @@ -417,6 +416,10 @@ static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; | |||
| 417 | MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>"); | 416 | MODULE_AUTHOR("Jes Sorensen <jes@trained-monkey.org>"); |
| 418 | MODULE_LICENSE("GPL"); | 417 | MODULE_LICENSE("GPL"); |
| 419 | MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); | 418 | MODULE_DESCRIPTION("AceNIC/3C985/GA620 Gigabit Ethernet driver"); |
| 419 | #ifndef CONFIG_ACENIC_OMIT_TIGON_I | ||
| 420 | MODULE_FIRMWARE("acenic/tg1.bin"); | ||
| 421 | #endif | ||
| 422 | MODULE_FIRMWARE("acenic/tg2.bin"); | ||
| 420 | 423 | ||
| 421 | module_param_array_named(link, link_state, int, NULL, 0); | 424 | module_param_array_named(link, link_state, int, NULL, 0); |
| 422 | module_param_array(trace, int, NULL, 0); | 425 | module_param_array(trace, int, NULL, 0); |
| @@ -943,8 +946,8 @@ static int __devinit ace_init(struct net_device *dev) | |||
| 943 | case 4: | 946 | case 4: |
| 944 | case 5: | 947 | case 5: |
| 945 | printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ", | 948 | printk(KERN_INFO " Tigon I (Rev. %i), Firmware: %i.%i.%i, ", |
| 946 | tig_ver, tigonFwReleaseMajor, tigonFwReleaseMinor, | 949 | tig_ver, ap->firmware_major, ap->firmware_minor, |
| 947 | tigonFwReleaseFix); | 950 | ap->firmware_fix); |
| 948 | writel(0, ®s->LocalCtrl); | 951 | writel(0, ®s->LocalCtrl); |
| 949 | ap->version = 1; | 952 | ap->version = 1; |
| 950 | ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES; | 953 | ap->tx_ring_entries = TIGON_I_TX_RING_ENTRIES; |
| @@ -952,8 +955,8 @@ static int __devinit ace_init(struct net_device *dev) | |||
| 952 | #endif | 955 | #endif |
| 953 | case 6: | 956 | case 6: |
| 954 | printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ", | 957 | printk(KERN_INFO " Tigon II (Rev. %i), Firmware: %i.%i.%i, ", |
| 955 | tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor, | 958 | tig_ver, ap->firmware_major, ap->firmware_minor, |
| 956 | tigon2FwReleaseFix); | 959 | ap->firmware_fix); |
| 957 | writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); | 960 | writel(readl(®s->CpuBCtrl) | CPU_HALT, ®s->CpuBCtrl); |
| 958 | readl(®s->CpuBCtrl); /* PCI write posting */ | 961 | readl(®s->CpuBCtrl); /* PCI write posting */ |
| 959 | /* | 962 | /* |
| @@ -1205,7 +1208,9 @@ static int __devinit ace_init(struct net_device *dev) | |||
| 1205 | memset(ap->info, 0, sizeof(struct ace_info)); | 1208 | memset(ap->info, 0, sizeof(struct ace_info)); |
| 1206 | memset(ap->skb, 0, sizeof(struct ace_skb)); | 1209 | memset(ap->skb, 0, sizeof(struct ace_skb)); |
| 1207 | 1210 | ||
| 1208 | ace_load_firmware(dev); | 1211 | if (ace_load_firmware(dev)) |
| 1212 | goto init_error; | ||
| 1213 | |||
| 1209 | ap->fw_running = 0; | 1214 | ap->fw_running = 0; |
| 1210 | 1215 | ||
| 1211 | tmp_ptr = ap->info_dma; | 1216 | tmp_ptr = ap->info_dma; |
| @@ -1441,10 +1446,7 @@ static int __devinit ace_init(struct net_device *dev) | |||
| 1441 | if (ap->version >= 2) | 1446 | if (ap->version >= 2) |
| 1442 | writel(tmp, ®s->TuneFastLink); | 1447 | writel(tmp, ®s->TuneFastLink); |
| 1443 | 1448 | ||
| 1444 | if (ACE_IS_TIGON_I(ap)) | 1449 | writel(ap->firmware_start, ®s->Pc); |
| 1445 | writel(tigonFwStartAddr, ®s->Pc); | ||
| 1446 | if (ap->version == 2) | ||
| 1447 | writel(tigon2FwStartAddr, ®s->Pc); | ||
| 1448 | 1450 | ||
| 1449 | writel(0, ®s->Mb0Lo); | 1451 | writel(0, ®s->Mb0Lo); |
| 1450 | 1452 | ||
| @@ -2761,8 +2763,8 @@ static void ace_get_drvinfo(struct net_device *dev, | |||
| 2761 | 2763 | ||
| 2762 | strlcpy(info->driver, "acenic", sizeof(info->driver)); | 2764 | strlcpy(info->driver, "acenic", sizeof(info->driver)); |
| 2763 | snprintf(info->version, sizeof(info->version), "%i.%i.%i", | 2765 | snprintf(info->version, sizeof(info->version), "%i.%i.%i", |
| 2764 | tigonFwReleaseMajor, tigonFwReleaseMinor, | 2766 | ap->firmware_major, ap->firmware_minor, |
| 2765 | tigonFwReleaseFix); | 2767 | ap->firmware_fix); |
| 2766 | 2768 | ||
| 2767 | if (ap->pdev) | 2769 | if (ap->pdev) |
| 2768 | strlcpy(info->bus_info, pci_name(ap->pdev), | 2770 | strlcpy(info->bus_info, pci_name(ap->pdev), |
| @@ -2869,11 +2871,10 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev) | |||
| 2869 | } | 2871 | } |
| 2870 | 2872 | ||
| 2871 | 2873 | ||
| 2872 | static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, | 2874 | static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src, |
| 2873 | u32 dest, int size) | 2875 | u32 dest, int size) |
| 2874 | { | 2876 | { |
| 2875 | void __iomem *tdest; | 2877 | void __iomem *tdest; |
| 2876 | u32 *wsrc; | ||
| 2877 | short tsize, i; | 2878 | short tsize, i; |
| 2878 | 2879 | ||
| 2879 | if (size <= 0) | 2880 | if (size <= 0) |
| @@ -2885,20 +2886,15 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, void *src, | |||
| 2885 | tdest = (void __iomem *) ®s->Window + | 2886 | tdest = (void __iomem *) ®s->Window + |
| 2886 | (dest & (ACE_WINDOW_SIZE - 1)); | 2887 | (dest & (ACE_WINDOW_SIZE - 1)); |
| 2887 | writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); | 2888 | writel(dest & ~(ACE_WINDOW_SIZE - 1), ®s->WinBase); |
| 2888 | /* | ||
| 2889 | * This requires byte swapping on big endian, however | ||
| 2890 | * writel does that for us | ||
| 2891 | */ | ||
| 2892 | wsrc = src; | ||
| 2893 | for (i = 0; i < (tsize / 4); i++) { | 2889 | for (i = 0; i < (tsize / 4); i++) { |
| 2894 | writel(wsrc[i], tdest + i*4); | 2890 | /* Firmware is big-endian */ |
| 2891 | writel(be32_to_cpup(src), tdest); | ||
| 2892 | src++; | ||
| 2893 | tdest += 4; | ||
| 2894 | dest += 4; | ||
| 2895 | size -= 4; | ||
| 2895 | } | 2896 | } |
| 2896 | dest += tsize; | ||
| 2897 | src += tsize; | ||
| 2898 | size -= tsize; | ||
| 2899 | } | 2897 | } |
| 2900 | |||
| 2901 | return; | ||
| 2902 | } | 2898 | } |
| 2903 | 2899 | ||
| 2904 | 2900 | ||
| @@ -2937,8 +2933,13 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz | |||
| 2937 | */ | 2933 | */ |
| 2938 | static int __devinit ace_load_firmware(struct net_device *dev) | 2934 | static int __devinit ace_load_firmware(struct net_device *dev) |
| 2939 | { | 2935 | { |
| 2936 | const struct firmware *fw; | ||
| 2937 | const char *fw_name = "acenic/tg2.bin"; | ||
| 2940 | struct ace_private *ap = netdev_priv(dev); | 2938 | struct ace_private *ap = netdev_priv(dev); |
| 2941 | struct ace_regs __iomem *regs = ap->regs; | 2939 | struct ace_regs __iomem *regs = ap->regs; |
| 2940 | const __be32 *fw_data; | ||
| 2941 | u32 load_addr; | ||
| 2942 | int ret; | ||
| 2942 | 2943 | ||
| 2943 | if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { | 2944 | if (!(readl(®s->CpuCtrl) & CPU_HALTED)) { |
| 2944 | printk(KERN_ERR "%s: trying to download firmware while the " | 2945 | printk(KERN_ERR "%s: trying to download firmware while the " |
| @@ -2946,28 +2947,52 @@ static int __devinit ace_load_firmware(struct net_device *dev) | |||
| 2946 | return -EFAULT; | 2947 | return -EFAULT; |
| 2947 | } | 2948 | } |
| 2948 | 2949 | ||
| 2950 | if (ACE_IS_TIGON_I(ap)) | ||
| 2951 | fw_name = "acenic/tg1.bin"; | ||
| 2952 | |||
| 2953 | ret = request_firmware(&fw, fw_name, &ap->pdev->dev); | ||
| 2954 | if (ret) { | ||
| 2955 | printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", | ||
| 2956 | ap->name, fw_name); | ||
| 2957 | return ret; | ||
| 2958 | } | ||
| 2959 | |||
| 2960 | fw_data = (void *)fw->data; | ||
| 2961 | |||
| 2962 | /* Firmware blob starts with version numbers, followed by | ||
| 2963 | load and start address. Remainder is the blob to be loaded | ||
| 2964 | contiguously from load address. We don't bother to represent | ||
| 2965 | the BSS/SBSS sections any more, since we were clearing the | ||
| 2966 | whole thing anyway. */ | ||
| 2967 | ap->firmware_major = fw->data[0]; | ||
| 2968 | ap->firmware_minor = fw->data[1]; | ||
| 2969 | ap->firmware_fix = fw->data[2]; | ||
| 2970 | |||
| 2971 | ap->firmware_start = be32_to_cpu(fw_data[1]); | ||
| 2972 | if (ap->firmware_start < 0x4000 || ap->firmware_start >= 0x80000) { | ||
| 2973 | printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", | ||
| 2974 | ap->name, ap->firmware_start, fw_name); | ||
| 2975 | ret = -EINVAL; | ||
| 2976 | goto out; | ||
| 2977 | } | ||
| 2978 | |||
| 2979 | load_addr = be32_to_cpu(fw_data[2]); | ||
| 2980 | if (load_addr < 0x4000 || load_addr >= 0x80000) { | ||
| 2981 | printk(KERN_ERR "%s: bogus load address %08x in \"%s\"\n", | ||
| 2982 | ap->name, load_addr, fw_name); | ||
| 2983 | ret = -EINVAL; | ||
| 2984 | goto out; | ||
| 2985 | } | ||
| 2986 | |||
| 2949 | /* | 2987 | /* |
| 2950 | * Do not try to clear more than 512KB or we end up seeing | 2988 | * Do not try to clear more than 512KiB or we end up seeing |
| 2951 | * funny things on NICs with only 512KB SRAM | 2989 | * funny things on NICs with only 512KiB SRAM |
| 2952 | */ | 2990 | */ |
| 2953 | ace_clear(regs, 0x2000, 0x80000-0x2000); | 2991 | ace_clear(regs, 0x2000, 0x80000-0x2000); |
| 2954 | if (ACE_IS_TIGON_I(ap)) { | 2992 | ace_copy(regs, &fw_data[3], load_addr, fw->size-12); |
| 2955 | ace_copy(regs, tigonFwText, tigonFwTextAddr, tigonFwTextLen); | 2993 | out: |
| 2956 | ace_copy(regs, tigonFwData, tigonFwDataAddr, tigonFwDataLen); | 2994 | release_firmware(fw); |
| 2957 | ace_copy(regs, tigonFwRodata, tigonFwRodataAddr, | 2995 | return ret; |
| 2958 | tigonFwRodataLen); | ||
| 2959 | ace_clear(regs, tigonFwBssAddr, tigonFwBssLen); | ||
| 2960 | ace_clear(regs, tigonFwSbssAddr, tigonFwSbssLen); | ||
| 2961 | }else if (ap->version == 2) { | ||
| 2962 | ace_clear(regs, tigon2FwBssAddr, tigon2FwBssLen); | ||
| 2963 | ace_clear(regs, tigon2FwSbssAddr, tigon2FwSbssLen); | ||
| 2964 | ace_copy(regs, tigon2FwText, tigon2FwTextAddr,tigon2FwTextLen); | ||
| 2965 | ace_copy(regs, tigon2FwRodata, tigon2FwRodataAddr, | ||
| 2966 | tigon2FwRodataLen); | ||
| 2967 | ace_copy(regs, tigon2FwData, tigon2FwDataAddr,tigon2FwDataLen); | ||
| 2968 | } | ||
| 2969 | |||
| 2970 | return 0; | ||
| 2971 | } | 2996 | } |
| 2972 | 2997 | ||
| 2973 | 2998 | ||
