aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2009-01-19 19:57:45 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-19 19:57:45 -0500
commit9e9fd12dc0679643c191fc9795a3021807e77de4 (patch)
tree926f64934af8f762b92bd5b103d37ebe151a2ada
parent1da100bb47ef32cb43bb6a365f64183898f830b5 (diff)
tg3: Fix firmware loading
This patch modifies how the tg3 driver handles device firmware. The patch starts by consolidating David Woodhouse's earlier patch under the same name. Specifically, the patch moves the request_firmware call into a separate tg3_request_firmware() function and calls that function from tg3_open() rather than tg3_init_one(). The patch then goes on to limit the number of devices that will make request_firmware calls. The original firmware patch unnecessarily requested TSO firmware for devices that did not need it. This patch reduces the set of devices making TSO firmware patches to approximately the following device set : 5703, 5704, and 5705. Finally, the patch reduces the effects of a request_firmware() failure. For those devices that are requesting TSO firmware, the driver will turn off the TSO capability. If TSO firmware becomes available at a later time, the device can be closed and then opened again to reacquire the TSO capability. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tg3.c81
-rw-r--r--drivers/net/tg3.h1
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
7538static 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
7538static int tg3_open(struct net_device *dev) 7569static 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};