diff options
author | Michael Chan <mchan@broadcom.com> | 2006-01-17 05:40:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-01-17 05:40:55 -0500 |
commit | ec41c7dfd525468decb9da9281dbc9ed82d98c98 (patch) | |
tree | 02ac7f0b1318c69d53a2405972f8a6880dc8b7c6 /drivers | |
parent | f0daaa654af68c1651add9d21188d81c19672551 (diff) |
[TG3]: Refine nvram locking
Add nvram lock count so that calls to tg3_nvram_lock()/unlock() can
be nested. Add error checking to all callers of tg3_nvram_lock()
where appropriate. To prevent nvram lock failures after halting the
firmware, it is also necessary to release firmware's nvram lock in
tg3_halt_cpu().
Update version to 3.48.
Based on David Miller's initial patch.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/tg3.c | 82 | ||||
-rw-r--r-- | drivers/net/tg3.h | 1 |
2 files changed, 55 insertions, 28 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index eb86b059809b..f2d1dafde087 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -69,8 +69,8 @@ | |||
69 | 69 | ||
70 | #define DRV_MODULE_NAME "tg3" | 70 | #define DRV_MODULE_NAME "tg3" |
71 | #define PFX DRV_MODULE_NAME ": " | 71 | #define PFX DRV_MODULE_NAME ": " |
72 | #define DRV_MODULE_VERSION "3.47" | 72 | #define DRV_MODULE_VERSION "3.48" |
73 | #define DRV_MODULE_RELDATE "Dec 28, 2005" | 73 | #define DRV_MODULE_RELDATE "Jan 16, 2006" |
74 | 74 | ||
75 | #define TG3_DEF_MAC_MODE 0 | 75 | #define TG3_DEF_MAC_MODE 0 |
76 | #define TG3_DEF_RX_MODE 0 | 76 | #define TG3_DEF_RX_MODE 0 |
@@ -1325,10 +1325,12 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1325 | val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); | 1325 | val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1); |
1326 | tw32(0x7d00, val); | 1326 | tw32(0x7d00, val); |
1327 | if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { | 1327 | if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) { |
1328 | tg3_nvram_lock(tp); | 1328 | int err; |
1329 | |||
1330 | err = tg3_nvram_lock(tp); | ||
1329 | tg3_halt_cpu(tp, RX_CPU_BASE); | 1331 | tg3_halt_cpu(tp, RX_CPU_BASE); |
1330 | tw32_f(NVRAM_SWARB, SWARB_REQ_CLR0); | 1332 | if (!err) |
1331 | tg3_nvram_unlock(tp); | 1333 | tg3_nvram_unlock(tp); |
1332 | } | 1334 | } |
1333 | } | 1335 | } |
1334 | 1336 | ||
@@ -4193,14 +4195,19 @@ static int tg3_nvram_lock(struct tg3 *tp) | |||
4193 | if (tp->tg3_flags & TG3_FLAG_NVRAM) { | 4195 | if (tp->tg3_flags & TG3_FLAG_NVRAM) { |
4194 | int i; | 4196 | int i; |
4195 | 4197 | ||
4196 | tw32(NVRAM_SWARB, SWARB_REQ_SET1); | 4198 | if (tp->nvram_lock_cnt == 0) { |
4197 | for (i = 0; i < 8000; i++) { | 4199 | tw32(NVRAM_SWARB, SWARB_REQ_SET1); |
4198 | if (tr32(NVRAM_SWARB) & SWARB_GNT1) | 4200 | for (i = 0; i < 8000; i++) { |
4199 | break; | 4201 | if (tr32(NVRAM_SWARB) & SWARB_GNT1) |
4200 | udelay(20); | 4202 | break; |
4203 | udelay(20); | ||
4204 | } | ||
4205 | if (i == 8000) { | ||
4206 | tw32(NVRAM_SWARB, SWARB_REQ_CLR1); | ||
4207 | return -ENODEV; | ||
4208 | } | ||
4201 | } | 4209 | } |
4202 | if (i == 8000) | 4210 | tp->nvram_lock_cnt++; |
4203 | return -ENODEV; | ||
4204 | } | 4211 | } |
4205 | return 0; | 4212 | return 0; |
4206 | } | 4213 | } |
@@ -4208,8 +4215,12 @@ static int tg3_nvram_lock(struct tg3 *tp) | |||
4208 | /* tp->lock is held. */ | 4215 | /* tp->lock is held. */ |
4209 | static void tg3_nvram_unlock(struct tg3 *tp) | 4216 | static void tg3_nvram_unlock(struct tg3 *tp) |
4210 | { | 4217 | { |
4211 | if (tp->tg3_flags & TG3_FLAG_NVRAM) | 4218 | if (tp->tg3_flags & TG3_FLAG_NVRAM) { |
4212 | tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1); | 4219 | if (tp->nvram_lock_cnt > 0) |
4220 | tp->nvram_lock_cnt--; | ||
4221 | if (tp->nvram_lock_cnt == 0) | ||
4222 | tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1); | ||
4223 | } | ||
4213 | } | 4224 | } |
4214 | 4225 | ||
4215 | /* tp->lock is held. */ | 4226 | /* tp->lock is held. */ |
@@ -4320,8 +4331,13 @@ static int tg3_chip_reset(struct tg3 *tp) | |||
4320 | void (*write_op)(struct tg3 *, u32, u32); | 4331 | void (*write_op)(struct tg3 *, u32, u32); |
4321 | int i; | 4332 | int i; |
4322 | 4333 | ||
4323 | if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) | 4334 | if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) { |
4324 | tg3_nvram_lock(tp); | 4335 | tg3_nvram_lock(tp); |
4336 | /* No matching tg3_nvram_unlock() after this because | ||
4337 | * chip reset below will undo the nvram lock. | ||
4338 | */ | ||
4339 | tp->nvram_lock_cnt = 0; | ||
4340 | } | ||
4325 | 4341 | ||
4326 | /* | 4342 | /* |
4327 | * We must avoid the readl() that normally takes place. | 4343 | * We must avoid the readl() that normally takes place. |
@@ -4717,6 +4733,10 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) | |||
4717 | (offset == RX_CPU_BASE ? "RX" : "TX")); | 4733 | (offset == RX_CPU_BASE ? "RX" : "TX")); |
4718 | return -ENODEV; | 4734 | return -ENODEV; |
4719 | } | 4735 | } |
4736 | |||
4737 | /* Clear firmware's nvram arbitration. */ | ||
4738 | if (tp->tg3_flags & TG3_FLAG_NVRAM) | ||
4739 | tw32(NVRAM_SWARB, SWARB_REQ_CLR0); | ||
4720 | return 0; | 4740 | return 0; |
4721 | } | 4741 | } |
4722 | 4742 | ||
@@ -4736,7 +4756,7 @@ struct fw_info { | |||
4736 | static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base, | 4756 | static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base, |
4737 | int cpu_scratch_size, struct fw_info *info) | 4757 | int cpu_scratch_size, struct fw_info *info) |
4738 | { | 4758 | { |
4739 | int err, i; | 4759 | int err, lock_err, i; |
4740 | void (*write_op)(struct tg3 *, u32, u32); | 4760 | void (*write_op)(struct tg3 *, u32, u32); |
4741 | 4761 | ||
4742 | if (cpu_base == TX_CPU_BASE && | 4762 | if (cpu_base == TX_CPU_BASE && |
@@ -4755,9 +4775,10 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b | |||
4755 | /* It is possible that bootcode is still loading at this point. | 4775 | /* It is possible that bootcode is still loading at this point. |
4756 | * Get the nvram lock first before halting the cpu. | 4776 | * Get the nvram lock first before halting the cpu. |
4757 | */ | 4777 | */ |
4758 | tg3_nvram_lock(tp); | 4778 | lock_err = tg3_nvram_lock(tp); |
4759 | err = tg3_halt_cpu(tp, cpu_base); | 4779 | err = tg3_halt_cpu(tp, cpu_base); |
4760 | tg3_nvram_unlock(tp); | 4780 | if (!lock_err) |
4781 | tg3_nvram_unlock(tp); | ||
4761 | if (err) | 4782 | if (err) |
4762 | goto out; | 4783 | goto out; |
4763 | 4784 | ||
@@ -8182,7 +8203,7 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | |||
8182 | data[1] = 1; | 8203 | data[1] = 1; |
8183 | } | 8204 | } |
8184 | if (etest->flags & ETH_TEST_FL_OFFLINE) { | 8205 | if (etest->flags & ETH_TEST_FL_OFFLINE) { |
8185 | int irq_sync = 0; | 8206 | int err, irq_sync = 0; |
8186 | 8207 | ||
8187 | if (netif_running(dev)) { | 8208 | if (netif_running(dev)) { |
8188 | tg3_netif_stop(tp); | 8209 | tg3_netif_stop(tp); |
@@ -8192,11 +8213,12 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest, | |||
8192 | tg3_full_lock(tp, irq_sync); | 8213 | tg3_full_lock(tp, irq_sync); |
8193 | 8214 | ||
8194 | tg3_halt(tp, RESET_KIND_SUSPEND, 1); | 8215 | tg3_halt(tp, RESET_KIND_SUSPEND, 1); |
8195 | tg3_nvram_lock(tp); | 8216 | err = tg3_nvram_lock(tp); |
8196 | tg3_halt_cpu(tp, RX_CPU_BASE); | 8217 | tg3_halt_cpu(tp, RX_CPU_BASE); |
8197 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) | 8218 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) |
8198 | tg3_halt_cpu(tp, TX_CPU_BASE); | 8219 | tg3_halt_cpu(tp, TX_CPU_BASE); |
8199 | tg3_nvram_unlock(tp); | 8220 | if (!err) |
8221 | tg3_nvram_unlock(tp); | ||
8200 | 8222 | ||
8201 | if (tg3_test_registers(tp) != 0) { | 8223 | if (tg3_test_registers(tp) != 0) { |
8202 | etest->flags |= ETH_TEST_FL_FAILED; | 8224 | etest->flags |= ETH_TEST_FL_FAILED; |
@@ -8588,7 +8610,11 @@ static void __devinit tg3_nvram_init(struct tg3 *tp) | |||
8588 | GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { | 8610 | GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) { |
8589 | tp->tg3_flags |= TG3_FLAG_NVRAM; | 8611 | tp->tg3_flags |= TG3_FLAG_NVRAM; |
8590 | 8612 | ||
8591 | tg3_nvram_lock(tp); | 8613 | if (tg3_nvram_lock(tp)) { |
8614 | printk(KERN_WARNING PFX "%s: Cannot get nvarm lock, " | ||
8615 | "tg3_nvram_init failed.\n", tp->dev->name); | ||
8616 | return; | ||
8617 | } | ||
8592 | tg3_enable_nvram_access(tp); | 8618 | tg3_enable_nvram_access(tp); |
8593 | 8619 | ||
8594 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) | 8620 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752) |
@@ -8686,7 +8712,9 @@ static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val) | |||
8686 | if (offset > NVRAM_ADDR_MSK) | 8712 | if (offset > NVRAM_ADDR_MSK) |
8687 | return -EINVAL; | 8713 | return -EINVAL; |
8688 | 8714 | ||
8689 | tg3_nvram_lock(tp); | 8715 | ret = tg3_nvram_lock(tp); |
8716 | if (ret) | ||
8717 | return ret; | ||
8690 | 8718 | ||
8691 | tg3_enable_nvram_access(tp); | 8719 | tg3_enable_nvram_access(tp); |
8692 | 8720 | ||
@@ -8785,10 +8813,6 @@ static int tg3_nvram_write_block_unbuffered(struct tg3 *tp, u32 offset, u32 len, | |||
8785 | 8813 | ||
8786 | offset = offset + (pagesize - page_off); | 8814 | offset = offset + (pagesize - page_off); |
8787 | 8815 | ||
8788 | /* Nvram lock released by tg3_nvram_read() above, | ||
8789 | * so need to get it again. | ||
8790 | */ | ||
8791 | tg3_nvram_lock(tp); | ||
8792 | tg3_enable_nvram_access(tp); | 8816 | tg3_enable_nvram_access(tp); |
8793 | 8817 | ||
8794 | /* | 8818 | /* |
@@ -8925,7 +8949,9 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf) | |||
8925 | else { | 8949 | else { |
8926 | u32 grc_mode; | 8950 | u32 grc_mode; |
8927 | 8951 | ||
8928 | tg3_nvram_lock(tp); | 8952 | ret = tg3_nvram_lock(tp); |
8953 | if (ret) | ||
8954 | return ret; | ||
8929 | 8955 | ||
8930 | tg3_enable_nvram_access(tp); | 8956 | tg3_enable_nvram_access(tp); |
8931 | if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && | 8957 | if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 890e1635996b..e8243305f0e8 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2275,6 +2275,7 @@ struct tg3 { | |||
2275 | dma_addr_t stats_mapping; | 2275 | dma_addr_t stats_mapping; |
2276 | struct work_struct reset_task; | 2276 | struct work_struct reset_task; |
2277 | 2277 | ||
2278 | int nvram_lock_cnt; | ||
2278 | u32 nvram_size; | 2279 | u32 nvram_size; |
2279 | u32 nvram_pagesize; | 2280 | u32 nvram_pagesize; |
2280 | u32 nvram_jedecnum; | 2281 | u32 nvram_jedecnum; |