wcte13xp: Workaround rare nmi on modprobe on select systems

With certain pci controllers that support pci hotplug, during the reset
sequence of the fpga, the host controller can get confused about the state of
the card and throw an nmi.

Known affected systems:
 HP proliant DL160 & DL360p
 Dell poweredge R520
 Super Micro X7SPA-HF

This patch attempts to work around that by removing the fpga reset sequence
from the driver startup, then setting various control registers to known
starting state values.

This patch removes the field upgradeable firmware logic temporarily for the
te133 card to prevent fpga reset.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
Russ Meyerriecks 2013-08-14 16:49:06 -05:00
parent 2ad4dc555f
commit ce3f1f2650

View File

@ -2839,6 +2839,11 @@ static int t13x_check_firmware(struct t13x *wc)
if (force_firmware) { if (force_firmware) {
dev_info(&wc->dev->dev, dev_info(&wc->dev->dev,
"force_firmware module parameter is set. Forcing firmware load, regardless of version\n"); "force_firmware module parameter is set. Forcing firmware load, regardless of version\n");
} else if (is_pcie(wc)) {
dev_info(&wc->dev->dev,
"Firmware %x is running, but we require %x. ERROR: This version of dahdi temporarily disabled field upgradeable firmware. Please upgrade your dahdi revision.\n",
version, FIRMWARE_VERSION);
return -EIO;
} else { } else {
dev_info(&wc->dev->dev, dev_info(&wc->dev->dev,
"Firmware %x is running, but we require %x\n", "Firmware %x is running, but we require %x\n",
@ -2903,6 +2908,26 @@ cleanup:
return res; return res;
} }
static void soft_reset_fpga(struct t13x *wc)
{
/* digium_gpo */
iowrite32be(0x0, wc->membase);
/* xps_intc */
iowrite32be(0x0, wc->membase + 0x300);
iowrite32be(0x0, wc->membase + 0x308);
iowrite32be(0x0, wc->membase + 0x310);
iowrite32be(0x0, wc->membase + 0x31C);
/* xps_spi_config_flash */
iowrite32be(0xA, wc->membase + 0x200);
/* tdm engine */
iowrite32be(0x0, wc->membase + 0x2000);
iowrite32be(0x0, wc->membase + 0x2000);
iowrite32be(0x0, wc->membase + 0x2000);
}
static int __devinit te13xp_init_one(struct pci_dev *pdev, static int __devinit te13xp_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
@ -2979,10 +3004,7 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
dev_info(&wc->dev->dev, "Unable to request regions\n"); dev_info(&wc->dev->dev, "Unable to request regions\n");
/* Reset entire fpga */ /* Reset entire fpga */
pci_save_state(pdev); soft_reset_fpga(wc);
iowrite32be(0xe00, wc->membase + TDM_CONTROL);
msleep(2000);
pci_restore_state(pdev);
/* Enable writes to fpga status register */ /* Enable writes to fpga status register */
iowrite32be(0, wc->membase + 0x04); iowrite32be(0, wc->membase + 0x04);