Skip to content

Commit

Permalink
parisc: Disable HP HSC-PCI Cards to prevent kernel crash
Browse files Browse the repository at this point in the history
The HP Dino PCI controller chip can be used in two variants: as on-board
controller (e.g. in B160L), or on an Add-On card ("Card-Mode") to bridge
PCI components to systems without a PCI bus, e.g. to a HSC/GSC bus.  One
such Add-On card is the HP HSC-PCI Card which has one or more DEC Tulip
PCI NIC chips connected to the on-card Dino PCI controller.

Dino in Card-Mode has a big disadvantage: All PCI memory accesses need
to go through the DINO_MEM_DATA register, so Linux drivers will not be
able to use the ioremap() function. Without ioremap() many drivers will
not work, one example is the tulip driver which then simply crashes the
kernel if it tries to access the ports on the HP HSC card.

This patch disables the HP HSC card if it finds one, and as such
fixes the kernel crash on a HP D350/2 machine.

Signed-off-by: Helge Deller <deller@gmx.de>
Noticed-by: Phil Scarr <phil.scarr@pm.me>
Cc: stable@vger.kernel.org
  • Loading branch information
hdeller committed Sep 8, 2019
1 parent 1191cf4 commit 5fa1659
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions drivers/parisc/dino.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,15 @@ static inline struct dino_device *DINO_DEV(struct pci_hba_data *hba)
return container_of(hba, struct dino_device, hba);
}

/* Check if PCI device is behind a Card-mode Dino. */
static int pci_dev_is_behind_card_dino(struct pci_dev *dev)
{
struct dino_device *dino_dev;

dino_dev = DINO_DEV(parisc_walk_tree(dev->bus->bridge));
return is_card_dino(&dino_dev->hba.dev->id);
}

/*
* Dino Configuration Space Accessor Functions
*/
Expand Down Expand Up @@ -437,6 +446,21 @@ static void quirk_cirrus_cardbus(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832, quirk_cirrus_cardbus );

#ifdef CONFIG_TULIP
static void pci_fixup_tulip(struct pci_dev *dev)
{
if (!pci_dev_is_behind_card_dino(dev))
return;
if (!(pci_resource_flags(dev, 1) & IORESOURCE_MEM))
return;
pr_warn("%s: HP HSC-PCI Cards with card-mode Dino not yet supported.\n",
pci_name(dev));
/* Disable this card by zeroing the PCI resources */
memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
memset(&dev->resource[1], 0, sizeof(dev->resource[1]));
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_DEC, PCI_ANY_ID, pci_fixup_tulip);
#endif /* CONFIG_TULIP */

static void __init
dino_bios_init(void)
Expand Down

0 comments on commit 5fa1659

Please sign in to comment.