diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tg3.c | 81 | ||||
-rw-r--r-- | drivers/net/tg3.h | 1 |
2 files changed, 51 insertions, 31 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 5e2dbaee125b..8b3f84685387 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -7535,11 +7535,58 @@ static int tg3_test_msi(struct tg3 *tp) | |||
7535 | return err; | 7535 | return err; |
7536 | } | 7536 | } |
7537 | 7537 | ||
7538 | static int tg3_request_firmware(struct tg3 *tp) | ||
7539 | { | ||
7540 | const __be32 *fw_data; | ||
7541 | |||
7542 | if (request_firmware(&tp->fw, tp->fw_needed, &tp->pdev->dev)) { | ||
7543 | printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n", | ||
7544 | tp->dev->name, tp->fw_needed); | ||
7545 | return -ENOENT; | ||
7546 | } | ||
7547 | |||
7548 | fw_data = (void *)tp->fw->data; | ||
7549 | |||
7550 | /* Firmware blob starts with version numbers, followed by | ||
7551 | * start address and _full_ length including BSS sections | ||
7552 | * (which must be longer than the actual data, of course | ||
7553 | */ | ||
7554 | |||
7555 | tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ | ||
7556 | if (tp->fw_len < (tp->fw->size - 12)) { | ||
7557 | printk(KERN_ERR "%s: bogus length %d in \"%s\"\n", | ||
7558 | tp->dev->name, tp->fw_len, tp->fw_needed); | ||
7559 | release_firmware(tp->fw); | ||
7560 | tp->fw = NULL; | ||
7561 | return -EINVAL; | ||
7562 | } | ||
7563 | |||
7564 | /* We no longer need firmware; we have it. */ | ||
7565 | tp->fw_needed = NULL; | ||
7566 | return 0; | ||
7567 | } | ||
7568 | |||
7538 | static int tg3_open(struct net_device *dev) | 7569 | static int tg3_open(struct net_device *dev) |
7539 | { | 7570 | { |
7540 | struct tg3 *tp = netdev_priv(dev); | 7571 | struct tg3 *tp = netdev_priv(dev); |
7541 | int err; | 7572 | int err; |
7542 | 7573 | ||
7574 | if (tp->fw_needed) { | ||
7575 | err = tg3_request_firmware(tp); | ||
7576 | if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) { | ||
7577 | if (err) | ||
7578 | return err; | ||
7579 | } else if (err) { | ||
7580 | printk(KERN_WARNING "%s: TSO capability disabled.\n", | ||
7581 | tp->dev->name); | ||
7582 | tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; | ||
7583 | } else if (!(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE)) { | ||
7584 | printk(KERN_NOTICE "%s: TSO capability restored.\n", | ||
7585 | tp->dev->name); | ||
7586 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; | ||
7587 | } | ||
7588 | } | ||
7589 | |||
7543 | netif_carrier_off(tp->dev); | 7590 | netif_carrier_off(tp->dev); |
7544 | 7591 | ||
7545 | err = tg3_set_power_state(tp, PCI_D0); | 7592 | err = tg3_set_power_state(tp, PCI_D0); |
@@ -12934,7 +12981,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
12934 | struct net_device *dev; | 12981 | struct net_device *dev; |
12935 | struct tg3 *tp; | 12982 | struct tg3 *tp; |
12936 | int err, pm_cap; | 12983 | int err, pm_cap; |
12937 | const char *fw_name = NULL; | ||
12938 | char str[40]; | 12984 | char str[40]; |
12939 | u64 dma_mask, persist_dma_mask; | 12985 | u64 dma_mask, persist_dma_mask; |
12940 | 12986 | ||
@@ -13091,7 +13137,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
13091 | tg3_init_bufmgr_config(tp); | 13137 | tg3_init_bufmgr_config(tp); |
13092 | 13138 | ||
13093 | if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) | 13139 | if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0) |
13094 | fw_name = FIRMWARE_TG3; | 13140 | tp->fw_needed = FIRMWARE_TG3; |
13095 | 13141 | ||
13096 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { | 13142 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) { |
13097 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; | 13143 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE; |
@@ -13104,37 +13150,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
13104 | tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; | 13150 | tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; |
13105 | } else { | 13151 | } else { |
13106 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG; | 13152 | tp->tg3_flags2 |= TG3_FLG2_TSO_CAPABLE | TG3_FLG2_TSO_BUG; |
13107 | } | ||
13108 | if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) { | ||
13109 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) | 13153 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) |
13110 | fw_name = FIRMWARE_TG3TSO5; | 13154 | tp->fw_needed = FIRMWARE_TG3TSO5; |
13111 | else | 13155 | else |
13112 | fw_name = FIRMWARE_TG3TSO; | 13156 | tp->fw_needed = FIRMWARE_TG3TSO; |
13113 | } | ||
13114 | |||
13115 | if (fw_name) { | ||
13116 | const __be32 *fw_data; | ||
13117 | |||
13118 | err = request_firmware(&tp->fw, fw_name, &tp->pdev->dev); | ||
13119 | if (err) { | ||
13120 | printk(KERN_ERR "tg3: Failed to load firmware \"%s\"\n", | ||
13121 | fw_name); | ||
13122 | goto err_out_iounmap; | ||
13123 | } | ||
13124 | |||
13125 | fw_data = (void *)tp->fw->data; | ||
13126 | |||
13127 | /* Firmware blob starts with version numbers, followed by | ||
13128 | start address and _full_ length including BSS sections | ||
13129 | (which must be longer than the actual data, of course */ | ||
13130 | |||
13131 | tp->fw_len = be32_to_cpu(fw_data[2]); /* includes bss */ | ||
13132 | if (tp->fw_len < (tp->fw->size - 12)) { | ||
13133 | printk(KERN_ERR "tg3: bogus length %d in \"%s\"\n", | ||
13134 | tp->fw_len, fw_name); | ||
13135 | err = -EINVAL; | ||
13136 | goto err_out_fw; | ||
13137 | } | ||
13138 | } | 13157 | } |
13139 | 13158 | ||
13140 | /* TSO is on by default on chips that support hardware TSO. | 13159 | /* TSO is on by default on chips that support hardware TSO. |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index ae5da603c6af..508def3e077f 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2764,6 +2764,7 @@ struct tg3 { | |||
2764 | struct ethtool_coalesce coal; | 2764 | struct ethtool_coalesce coal; |
2765 | 2765 | ||
2766 | /* firmware info */ | 2766 | /* firmware info */ |
2767 | const char *fw_needed; | ||
2767 | const struct firmware *fw; | 2768 | const struct firmware *fw; |
2768 | u32 fw_len; /* includes BSS */ | 2769 | u32 fw_len; /* includes BSS */ |
2769 | }; | 2770 | }; |