aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2007-07-19 00:49:10 -0400
committerDavid S. Miller <davem@davemloft.net>2007-07-19 00:49:10 -0400
commitee6a99b539a50b4e9398938a0a6d37f8bf911550 (patch)
tree51547e0b9c299be15cc3f54ff3c33b6e3e9c346c /drivers/net
parent7dc12d6dd6cc1aa489c6f3e34a75e8023c945da8 (diff)
[TG3]: Fix msi issue with kexec/kdump.
Tina Yang <tina.yang@oracle.com> discovered an MSI related problem when doing kdump. The problem is that the kexec kernel is booted without going through system reset, and as a result, MSI may already be enabled when tg3_init_one() is called. tg3_init_one() calls pci_save_state() which will save the stale MSI state. Later on in tg3_open(), we call pci_enable_msi() to reconfigure MSI on the chip before we reset the chip. After chip reset, we call pci_restore_state() which will put the stale MSI address/data back onto the chip. This is no longer a problem in the latest kernel because pci_restore_state() has been changed to restore MSI state from internal data structures which will guarantee restoring the proper MSI state. But I think we should still fix it. Our save and restore sequence can still cause very subtle problems down the road. The fix is to have our own functions save and restore precisely what we need. We also change it to save and restore state inside tg3_chip_reset() in a more straight forward way. Thanks to Tina for helping to test and debug the problem. [ Bump driver version and release date. -DaveM ] Signed-off-by: Michael Chan <mchan@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/tg3.c114
-rw-r--r--drivers/net/tg3.h1
2 files changed, 66 insertions, 49 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 5ee14764fd74..887b9a5cfe48 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -64,8 +64,8 @@
64 64
65#define DRV_MODULE_NAME "tg3" 65#define DRV_MODULE_NAME "tg3"
66#define PFX DRV_MODULE_NAME ": " 66#define PFX DRV_MODULE_NAME ": "
67#define DRV_MODULE_VERSION "3.78" 67#define DRV_MODULE_VERSION "3.79"
68#define DRV_MODULE_RELDATE "July 11, 2007" 68#define DRV_MODULE_RELDATE "July 18, 2007"
69 69
70#define TG3_DEF_MAC_MODE 0 70#define TG3_DEF_MAC_MODE 0
71#define TG3_DEF_RX_MODE 0 71#define TG3_DEF_RX_MODE 0
@@ -4847,6 +4847,59 @@ static int tg3_poll_fw(struct tg3 *tp)
4847 return 0; 4847 return 0;
4848} 4848}
4849 4849
4850/* Save PCI command register before chip reset */
4851static void tg3_save_pci_state(struct tg3 *tp)
4852{
4853 u32 val;
4854
4855 pci_read_config_dword(tp->pdev, TG3PCI_COMMAND, &val);
4856 tp->pci_cmd = val;
4857}
4858
4859/* Restore PCI state after chip reset */
4860static void tg3_restore_pci_state(struct tg3 *tp)
4861{
4862 u32 val;
4863
4864 /* Re-enable indirect register accesses. */
4865 pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
4866 tp->misc_host_ctrl);
4867
4868 /* Set MAX PCI retry to zero. */
4869 val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
4870 if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
4871 (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
4872 val |= PCISTATE_RETRY_SAME_DMA;
4873 pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
4874
4875 pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
4876
4877 /* Make sure PCI-X relaxed ordering bit is clear. */
4878 pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val);
4879 val &= ~PCIX_CAPS_RELAXED_ORDERING;
4880 pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
4881
4882 if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
4883 u32 val;
4884
4885 /* Chip reset on 5780 will reset MSI enable bit,
4886 * so need to restore it.
4887 */
4888 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
4889 u16 ctrl;
4890
4891 pci_read_config_word(tp->pdev,
4892 tp->msi_cap + PCI_MSI_FLAGS,
4893 &ctrl);
4894 pci_write_config_word(tp->pdev,
4895 tp->msi_cap + PCI_MSI_FLAGS,
4896 ctrl | PCI_MSI_FLAGS_ENABLE);
4897 val = tr32(MSGINT_MODE);
4898 tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
4899 }
4900 }
4901}
4902
4850static void tg3_stop_fw(struct tg3 *); 4903static void tg3_stop_fw(struct tg3 *);
4851 4904
4852/* tp->lock is held. */ 4905/* tp->lock is held. */
@@ -4863,6 +4916,12 @@ static int tg3_chip_reset(struct tg3 *tp)
4863 */ 4916 */
4864 tp->nvram_lock_cnt = 0; 4917 tp->nvram_lock_cnt = 0;
4865 4918
4919 /* GRC_MISC_CFG core clock reset will clear the memory
4920 * enable bit in PCI register 4 and the MSI enable bit
4921 * on some chips, so we save relevant registers here.
4922 */
4923 tg3_save_pci_state(tp);
4924
4866 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 || 4925 if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
4867 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 || 4926 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
4868 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) 4927 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787)
@@ -4961,50 +5020,14 @@ static int tg3_chip_reset(struct tg3 *tp)
4961 pci_write_config_dword(tp->pdev, 0xd8, 0xf5000); 5020 pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
4962 } 5021 }
4963 5022
4964 /* Re-enable indirect register accesses. */ 5023 tg3_restore_pci_state(tp);
4965 pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
4966 tp->misc_host_ctrl);
4967
4968 /* Set MAX PCI retry to zero. */
4969 val = (PCISTATE_ROM_ENABLE | PCISTATE_ROM_RETRY_ENABLE);
4970 if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
4971 (tp->tg3_flags & TG3_FLAG_PCIX_MODE))
4972 val |= PCISTATE_RETRY_SAME_DMA;
4973 pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);
4974
4975 pci_restore_state(tp->pdev);
4976 5024
4977 tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING; 5025 tp->tg3_flags &= ~TG3_FLAG_CHIP_RESETTING;
4978 5026
4979 /* Make sure PCI-X relaxed ordering bit is clear. */ 5027 val = 0;
4980 pci_read_config_dword(tp->pdev, TG3PCI_X_CAPS, &val); 5028 if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)
4981 val &= ~PCIX_CAPS_RELAXED_ORDERING;
4982 pci_write_config_dword(tp->pdev, TG3PCI_X_CAPS, val);
4983
4984 if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) {
4985 u32 val;
4986
4987 /* Chip reset on 5780 will reset MSI enable bit,
4988 * so need to restore it.
4989 */
4990 if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
4991 u16 ctrl;
4992
4993 pci_read_config_word(tp->pdev,
4994 tp->msi_cap + PCI_MSI_FLAGS,
4995 &ctrl);
4996 pci_write_config_word(tp->pdev,
4997 tp->msi_cap + PCI_MSI_FLAGS,
4998 ctrl | PCI_MSI_FLAGS_ENABLE);
4999 val = tr32(MSGINT_MODE);
5000 tw32(MSGINT_MODE, val | MSGINT_MODE_ENABLE);
5001 }
5002
5003 val = tr32(MEMARB_MODE); 5029 val = tr32(MEMARB_MODE);
5004 tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE); 5030 tw32(MEMARB_MODE, val | MEMARB_MODE_ENABLE);
5005
5006 } else
5007 tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
5008 5031
5009 if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) { 5032 if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A3) {
5010 tg3_stop_fw(tp); 5033 tg3_stop_fw(tp);
@@ -11978,7 +12001,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
11978 */ 12001 */
11979 if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) || 12002 if ((tr32(HOSTCC_MODE) & HOSTCC_MODE_ENABLE) ||
11980 (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) { 12003 (tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
11981 pci_save_state(tp->pdev);
11982 tw32(MEMARB_MODE, MEMARB_MODE_ENABLE); 12004 tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
11983 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); 12005 tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
11984 } 12006 }
@@ -12007,12 +12029,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
12007 12029
12008 tg3_init_coal(tp); 12030 tg3_init_coal(tp);
12009 12031
12010 /* Now that we have fully setup the chip, save away a snapshot
12011 * of the PCI config space. We need to restore this after
12012 * GRC_MISC_CFG core clock resets and some resume events.
12013 */
12014 pci_save_state(tp->pdev);
12015
12016 pci_set_drvdata(pdev, dev); 12032 pci_set_drvdata(pdev, dev);
12017 12033
12018 err = register_netdev(dev); 12034 err = register_netdev(dev);
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index d84e75e7365d..5c21f49026c9 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2345,6 +2345,7 @@ struct tg3 {
2345#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */ 2345#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */
2346 2346
2347 u32 led_ctrl; 2347 u32 led_ctrl;
2348 u32 pci_cmd;
2348 2349
2349 char board_part_number[24]; 2350 char board_part_number[24];
2350 char fw_ver[16]; 2351 char fw_ver[16];