summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@jsg.id.au>2013-08-01 13:05:38 +1000
committerJonathan Gray <jsg@jsg.id.au>2013-08-12 10:46:56 +1000
commite484f6db203edb7e5cdfd179a97d0792d4427975 (patch)
tree6274eb6ac3940befd1bb496b8a52b9389ae9aba5
parent1352406bcf76c84c891f2bfb18a23f8028e4c24c (diff)
detach and reprobe vga if we hit a fatal error in the roothook
suggested by kettenis
-rw-r--r--sys/dev/pci/drm/radeon/radeon.h1
-rw-r--r--sys/dev/pci/drm/radeon/radeon_kms.c31
2 files changed, 32 insertions, 0 deletions
diff --git a/sys/dev/pci/drm/radeon/radeon.h b/sys/dev/pci/drm/radeon/radeon.h
index faa8f066ec5..8fb2c5a7a86 100644
--- a/sys/dev/pci/drm/radeon/radeon.h
+++ b/sys/dev/pci/drm/radeon/radeon.h
@@ -1553,6 +1553,7 @@ struct radeon_device {
struct device dev;
struct drm_device *ddev;
+ struct pci_attach_args pa;
pci_chipset_tag_t pc;
pcitag_t pa_tag;
pci_intr_handle_t intrh;
diff --git a/sys/dev/pci/drm/radeon/radeon_kms.c b/sys/dev/pci/drm/radeon/radeon_kms.c
index a4fdc709d9b..fa13f8c52e8 100644
--- a/sys/dev/pci/drm/radeon/radeon_kms.c
+++ b/sys/dev/pci/drm/radeon/radeon_kms.c
@@ -104,6 +104,7 @@ void radeondrm_attach_kms(struct device *, struct device *, void *);
int radeondrm_detach_kms(struct device *, int);
int radeondrm_activate_kms(struct device *, int);
void radeondrm_attachhook(void *);
+int radeondrm_forcedetach(struct radeon_device *);
struct cfattach radeondrm_ca = {
sizeof (struct radeon_device), radeondrm_probe, radeondrm_attach_kms,
@@ -165,6 +166,12 @@ int radeon_msi = -1;
/* GPU lockup timeout in ms (defaul 10000 = 10 seconds, 0 = disable) */
int radeon_lockup_timeout = 10000;
+/*
+ * set if the mountroot hook has a fatal error
+ * such as not being able to find the firmware on newer cards
+ */
+int radeon_fatal_error = 0;
+
const struct drm_pcidev radeondrm_pciidlist[] = {
{PCI_VENDOR_ATI, PCI_PRODUCT_ATI_RADEON_M241P,
CHIP_RV380|RADEON_IS_MOBILITY},
@@ -1348,6 +1355,8 @@ static struct drm_driver_info kms_driver = {
int
radeondrm_probe(struct device *parent, void *match, void *aux)
{
+ if (radeon_fatal_error)
+ return 0;
if (drm_pciprobe(aux, radeondrm_pciidlist))
return 20;
return 0;
@@ -1538,6 +1547,7 @@ radeondrm_attach_kms(struct device *parent, struct device *self, void *aux)
id_entry = drm_find_description(PCI_VENDOR(pa->pa_id),
PCI_PRODUCT(pa->pa_id), radeondrm_pciidlist);
rdev->flags = id_entry->driver_private;
+ rdev->pa = *pa;
rdev->pc = pa->pa_pc;
rdev->pa_tag = pa->pa_tag;
rdev->iot = pa->pa_iot;
@@ -1666,6 +1676,25 @@ radeondrm_attach_kms(struct device *parent, struct device *self, void *aux)
radeondrm_attachhook(rdev);
}
+int
+radeondrm_forcedetach(struct radeon_device *rdev)
+{
+ struct pci_softc *sc = (struct pci_softc *)rdev->dev.dv_parent;
+ struct pci_attach_args pa;
+ pcitag_t tag = rdev->pa_tag;
+
+ radeon_vga_set_state(rdev, true);
+ rdev->console = 0;
+ memcpy(&pa, &rdev->pa, sizeof(pa));
+#ifndef __sparc64__
+ extern int vga_console_attached;
+ vga_console_attached = 0;
+ bus_space_unmap(pa.pa_iot, 0x3c0, 0x10);
+#endif
+ config_detach(&rdev->dev, 0);
+ return (pci_probe_device(sc, tag, NULL, &pa));
+}
+
void
radeondrm_attachhook(void *xsc)
{
@@ -1681,6 +1710,8 @@ radeondrm_attachhook(void *xsc)
r = radeon_device_init(rdev, rdev->ddev);
if (r) {
printf(": Fatal error during GPU init\n");
+ radeon_fatal_error = 1;
+ radeondrm_forcedetach(rdev);
return;
}