aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp')
-rw-r--r--drivers/pnp/isapnp/core.c25
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c8
-rw-r--r--drivers/pnp/quirks.c100
3 files changed, 86 insertions, 47 deletions
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 2c925b7cd93e..257f5d827d83 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -88,6 +88,15 @@ MODULE_LICENSE("GPL");
88#define _LTAG_MEM32RANGE 0x85 88#define _LTAG_MEM32RANGE 0x85
89#define _LTAG_FIXEDMEM32RANGE 0x86 89#define _LTAG_FIXEDMEM32RANGE 0x86
90 90
91/*
92 * Sizes of ISAPNP logical device configuration register sets.
93 * See PNP-ISA-v1.0a.pdf, Appendix A.
94 */
95#define ISAPNP_MAX_MEM 4
96#define ISAPNP_MAX_PORT 8
97#define ISAPNP_MAX_IRQ 2
98#define ISAPNP_MAX_DMA 2
99
91static unsigned char isapnp_checksum_value; 100static unsigned char isapnp_checksum_value;
92static DEFINE_MUTEX(isapnp_cfg_mutex); 101static DEFINE_MUTEX(isapnp_cfg_mutex);
93static int isapnp_csn_count; 102static int isapnp_csn_count;
@@ -945,14 +954,14 @@ static int isapnp_read_resources(struct pnp_dev *dev,
945 954
946 dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE); 955 dev->active = isapnp_read_byte(ISAPNP_CFG_ACTIVATE);
947 if (dev->active) { 956 if (dev->active) {
948 for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { 957 for (tmp = 0; tmp < ISAPNP_MAX_PORT; tmp++) {
949 ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1)); 958 ret = isapnp_read_word(ISAPNP_CFG_PORT + (tmp << 1));
950 if (!ret) 959 if (!ret)
951 continue; 960 continue;
952 res->port_resource[tmp].start = ret; 961 res->port_resource[tmp].start = ret;
953 res->port_resource[tmp].flags = IORESOURCE_IO; 962 res->port_resource[tmp].flags = IORESOURCE_IO;
954 } 963 }
955 for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { 964 for (tmp = 0; tmp < ISAPNP_MAX_MEM; tmp++) {
956 ret = 965 ret =
957 isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8; 966 isapnp_read_word(ISAPNP_CFG_MEM + (tmp << 3)) << 8;
958 if (!ret) 967 if (!ret)
@@ -960,7 +969,7 @@ static int isapnp_read_resources(struct pnp_dev *dev,
960 res->mem_resource[tmp].start = ret; 969 res->mem_resource[tmp].start = ret;
961 res->mem_resource[tmp].flags = IORESOURCE_MEM; 970 res->mem_resource[tmp].flags = IORESOURCE_MEM;
962 } 971 }
963 for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { 972 for (tmp = 0; tmp < ISAPNP_MAX_IRQ; tmp++) {
964 ret = 973 ret =
965 (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >> 974 (isapnp_read_word(ISAPNP_CFG_IRQ + (tmp << 1)) >>
966 8); 975 8);
@@ -970,7 +979,7 @@ static int isapnp_read_resources(struct pnp_dev *dev,
970 res->irq_resource[tmp].end = ret; 979 res->irq_resource[tmp].end = ret;
971 res->irq_resource[tmp].flags = IORESOURCE_IRQ; 980 res->irq_resource[tmp].flags = IORESOURCE_IRQ;
972 } 981 }
973 for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { 982 for (tmp = 0; tmp < ISAPNP_MAX_DMA; tmp++) {
974 ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp); 983 ret = isapnp_read_byte(ISAPNP_CFG_DMA + tmp);
975 if (ret == 4) 984 if (ret == 4)
976 continue; 985 continue;
@@ -1002,14 +1011,14 @@ static int isapnp_set_resources(struct pnp_dev *dev,
1002 isapnp_cfg_begin(dev->card->number, dev->number); 1011 isapnp_cfg_begin(dev->card->number, dev->number);
1003 dev->active = 1; 1012 dev->active = 1;
1004 for (tmp = 0; 1013 for (tmp = 0;
1005 tmp < PNP_MAX_PORT 1014 tmp < ISAPNP_MAX_PORT
1006 && (res->port_resource[tmp]. 1015 && (res->port_resource[tmp].
1007 flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO; 1016 flags & (IORESOURCE_IO | IORESOURCE_UNSET)) == IORESOURCE_IO;
1008 tmp++) 1017 tmp++)
1009 isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1), 1018 isapnp_write_word(ISAPNP_CFG_PORT + (tmp << 1),
1010 res->port_resource[tmp].start); 1019 res->port_resource[tmp].start);
1011 for (tmp = 0; 1020 for (tmp = 0;
1012 tmp < PNP_MAX_IRQ 1021 tmp < ISAPNP_MAX_IRQ
1013 && (res->irq_resource[tmp]. 1022 && (res->irq_resource[tmp].
1014 flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ; 1023 flags & (IORESOURCE_IRQ | IORESOURCE_UNSET)) == IORESOURCE_IRQ;
1015 tmp++) { 1024 tmp++) {
@@ -1019,14 +1028,14 @@ static int isapnp_set_resources(struct pnp_dev *dev,
1019 isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq); 1028 isapnp_write_byte(ISAPNP_CFG_IRQ + (tmp << 1), irq);
1020 } 1029 }
1021 for (tmp = 0; 1030 for (tmp = 0;
1022 tmp < PNP_MAX_DMA 1031 tmp < ISAPNP_MAX_DMA
1023 && (res->dma_resource[tmp]. 1032 && (res->dma_resource[tmp].
1024 flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA; 1033 flags & (IORESOURCE_DMA | IORESOURCE_UNSET)) == IORESOURCE_DMA;
1025 tmp++) 1034 tmp++)
1026 isapnp_write_byte(ISAPNP_CFG_DMA + tmp, 1035 isapnp_write_byte(ISAPNP_CFG_DMA + tmp,
1027 res->dma_resource[tmp].start); 1036 res->dma_resource[tmp].start);
1028 for (tmp = 0; 1037 for (tmp = 0;
1029 tmp < PNP_MAX_MEM 1038 tmp < ISAPNP_MAX_MEM
1030 && (res->mem_resource[tmp]. 1039 && (res->mem_resource[tmp].
1031 flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM; 1040 flags & (IORESOURCE_MEM | IORESOURCE_UNSET)) == IORESOURCE_MEM;
1032 tmp++) 1041 tmp++)
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 6aa231ef642d..2dcd1960aca8 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -85,7 +85,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
85 i < PNP_MAX_IRQ) 85 i < PNP_MAX_IRQ)
86 i++; 86 i++;
87 if (i >= PNP_MAX_IRQ && !warned) { 87 if (i >= PNP_MAX_IRQ && !warned) {
88 printk(KERN_ERR "pnpacpi: exceeded the max number of IRQ " 88 printk(KERN_WARNING "pnpacpi: exceeded the max number of IRQ "
89 "resources: %d \n", PNP_MAX_IRQ); 89 "resources: %d \n", PNP_MAX_IRQ);
90 warned = 1; 90 warned = 1;
91 return; 91 return;
@@ -187,7 +187,7 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res,
187 res->dma_resource[i].start = dma; 187 res->dma_resource[i].start = dma;
188 res->dma_resource[i].end = dma; 188 res->dma_resource[i].end = dma;
189 } else if (!warned) { 189 } else if (!warned) {
190 printk(KERN_ERR "pnpacpi: exceeded the max number of DMA " 190 printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA "
191 "resources: %d \n", PNP_MAX_DMA); 191 "resources: %d \n", PNP_MAX_DMA);
192 warned = 1; 192 warned = 1;
193 } 193 }
@@ -213,7 +213,7 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
213 res->port_resource[i].start = io; 213 res->port_resource[i].start = io;
214 res->port_resource[i].end = io + len - 1; 214 res->port_resource[i].end = io + len - 1;
215 } else if (!warned) { 215 } else if (!warned) {
216 printk(KERN_ERR "pnpacpi: exceeded the max number of IO " 216 printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
217 "resources: %d \n", PNP_MAX_PORT); 217 "resources: %d \n", PNP_MAX_PORT);
218 warned = 1; 218 warned = 1;
219 } 219 }
@@ -241,7 +241,7 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
241 res->mem_resource[i].start = mem; 241 res->mem_resource[i].start = mem;
242 res->mem_resource[i].end = mem + len - 1; 242 res->mem_resource[i].end = mem + len - 1;
243 } else if (!warned) { 243 } else if (!warned) {
244 printk(KERN_ERR "pnpacpi: exceeded the max number of mem " 244 printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
245 "resources: %d\n", PNP_MAX_MEM); 245 "resources: %d\n", PNP_MAX_MEM);
246 warned = 1; 246 warned = 1;
247 } 247 }
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index 4065139753b6..37993206ae5d 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -17,7 +17,6 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/pnp.h> 18#include <linux/pnp.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/dmi.h>
21#include <linux/kallsyms.h> 20#include <linux/kallsyms.h>
22#include "base.h" 21#include "base.h"
23 22
@@ -109,42 +108,73 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev)
109 "pnp: SB audio device quirk - increasing port range\n"); 108 "pnp: SB audio device quirk - increasing port range\n");
110} 109}
111 110
112static void quirk_supermicro_h8dce_system(struct pnp_dev *dev) 111
112#include <linux/pci.h>
113
114static void quirk_system_pci_resources(struct pnp_dev *dev)
113{ 115{
114 int i; 116 struct pci_dev *pdev = NULL;
115 static struct dmi_system_id supermicro_h8dce[] = { 117 resource_size_t pnp_start, pnp_end, pci_start, pci_end;
116 { 118 int i, j;
117 .ident = "Supermicro H8DCE",
118 .matches = {
119 DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
120 DMI_MATCH(DMI_PRODUCT_NAME, "H8DCE"),
121 },
122 },
123 { }
124 };
125
126 if (!dmi_check_system(supermicro_h8dce))
127 return;
128 119
129 /* 120 /*
130 * On the Supermicro H8DCE, there's a system device with resources 121 * Some BIOSes have PNP motherboard devices with resources that
131 * that overlap BAR 6 of the built-in SATA PCI adapter. If the PNP 122 * partially overlap PCI BARs. The PNP system driver claims these
132 * system device claims them, the sata_nv driver won't be able to. 123 * motherboard resources, which prevents the normal PCI driver from
133 * More details at: 124 * requesting them later.
134 * https://bugzilla.redhat.com/show_bug.cgi?id=280641 125 *
135 * https://bugzilla.redhat.com/show_bug.cgi?id=313491 126 * This patch disables the PNP resources that conflict with PCI BARs
136 * http://lkml.org/lkml/2008/1/9/449 127 * so they won't be claimed by the PNP system driver.
137 * http://thread.gmane.org/gmane.linux.acpi.devel/27312
138 */ 128 */
139 for (i = 0; i < PNP_MAX_MEM; i++) { 129 for_each_pci_dev(pdev) {
140 if (pnp_mem_valid(dev, i) && pnp_mem_len(dev, i) && 130 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
141 (pnp_mem_start(dev, i) & 0xdfef0000) == 0xdfef0000) { 131 if (!(pci_resource_flags(pdev, i) & IORESOURCE_MEM) ||
142 dev_warn(&dev->dev, "disabling 0x%llx-0x%llx to prevent" 132 pci_resource_len(pdev, i) == 0)
143 " conflict with sata_nv PCI device\n", 133 continue;
144 (unsigned long long) pnp_mem_start(dev, i), 134
145 (unsigned long long) (pnp_mem_start(dev, i) + 135 pci_start = pci_resource_start(pdev, i);
146 pnp_mem_len(dev, i) - 1)); 136 pci_end = pci_resource_end(pdev, i);
147 pnp_mem_flags(dev, i) = 0; 137 for (j = 0; j < PNP_MAX_MEM; j++) {
138 if (!pnp_mem_valid(dev, j) ||
139 pnp_mem_len(dev, j) == 0)
140 continue;
141
142 pnp_start = pnp_mem_start(dev, j);
143 pnp_end = pnp_mem_end(dev, j);
144
145 /*
146 * If the PNP region doesn't overlap the PCI
147 * region at all, there's no problem.
148 */
149 if (pnp_end < pci_start || pnp_start > pci_end)
150 continue;
151
152 /*
153 * If the PNP region completely encloses (or is
154 * at least as large as) the PCI region, that's
155 * also OK. For example, this happens when the
156 * PNP device describes a bridge with PCI
157 * behind it.
158 */
159 if (pnp_start <= pci_start &&
160 pnp_end >= pci_end)
161 continue;
162
163 /*
164 * Otherwise, the PNP region overlaps *part* of
165 * the PCI region, and that might prevent a PCI
166 * driver from requesting its resources.
167 */
168 dev_warn(&dev->dev, "mem resource "
169 "(0x%llx-0x%llx) overlaps %s BAR %d "
170 "(0x%llx-0x%llx), disabling\n",
171 (unsigned long long) pnp_start,
172 (unsigned long long) pnp_end,
173 pci_name(pdev), i,
174 (unsigned long long) pci_start,
175 (unsigned long long) pci_end);
176 pnp_mem_flags(dev, j) = 0;
177 }
148 } 178 }
149 } 179 }
150} 180}
@@ -169,8 +199,8 @@ static struct pnp_fixup pnp_fixups[] = {
169 {"CTL0043", quirk_sb16audio_resources}, 199 {"CTL0043", quirk_sb16audio_resources},
170 {"CTL0044", quirk_sb16audio_resources}, 200 {"CTL0044", quirk_sb16audio_resources},
171 {"CTL0045", quirk_sb16audio_resources}, 201 {"CTL0045", quirk_sb16audio_resources},
172 {"PNP0c01", quirk_supermicro_h8dce_system}, 202 {"PNP0c01", quirk_system_pci_resources},
173 {"PNP0c02", quirk_supermicro_h8dce_system}, 203 {"PNP0c02", quirk_system_pci_resources},
174 {""} 204 {""}
175}; 205};
176 206