diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pnp/quirks.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index a1af2f989482..ffdb12a59c40 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -111,6 +111,113 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) | |||
111 | dev_info(&dev->dev, "SB audio device quirk - increased port range\n"); | 111 | dev_info(&dev->dev, "SB audio device quirk - increased port range\n"); |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev) | ||
115 | { | ||
116 | struct pnp_option *head = NULL; | ||
117 | struct pnp_option *prev = NULL; | ||
118 | struct pnp_option *res; | ||
119 | |||
120 | /* | ||
121 | * Build a functional IRQ-less variant of each MPU option. | ||
122 | */ | ||
123 | |||
124 | for (res = dev->dependent; res; res = res->next) { | ||
125 | struct pnp_option *curr; | ||
126 | struct pnp_port *port; | ||
127 | struct pnp_port *copy; | ||
128 | |||
129 | port = res->port; | ||
130 | if (!port || !res->irq) | ||
131 | continue; | ||
132 | |||
133 | copy = pnp_alloc(sizeof *copy); | ||
134 | if (!copy) | ||
135 | break; | ||
136 | |||
137 | copy->min = port->min; | ||
138 | copy->max = port->max; | ||
139 | copy->align = port->align; | ||
140 | copy->size = port->size; | ||
141 | copy->flags = port->flags; | ||
142 | |||
143 | curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL); | ||
144 | if (!curr) { | ||
145 | kfree(copy); | ||
146 | break; | ||
147 | } | ||
148 | curr->port = copy; | ||
149 | |||
150 | if (prev) | ||
151 | prev->next = curr; | ||
152 | else | ||
153 | head = curr; | ||
154 | prev = curr; | ||
155 | } | ||
156 | if (head) | ||
157 | dev_info(&dev->dev, "adding IRQ-less MPU options\n"); | ||
158 | |||
159 | return head; | ||
160 | } | ||
161 | |||
162 | static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) | ||
163 | { | ||
164 | struct pnp_option *res; | ||
165 | struct pnp_irq *irq; | ||
166 | |||
167 | /* | ||
168 | * Distribute the independent IRQ over the dependent options | ||
169 | */ | ||
170 | |||
171 | res = dev->independent; | ||
172 | if (!res) | ||
173 | return; | ||
174 | |||
175 | irq = res->irq; | ||
176 | if (!irq || irq->next) | ||
177 | return; | ||
178 | |||
179 | res = dev->dependent; | ||
180 | if (!res) | ||
181 | return; | ||
182 | |||
183 | while (1) { | ||
184 | struct pnp_irq *copy; | ||
185 | |||
186 | copy = pnp_alloc(sizeof *copy); | ||
187 | if (!copy) | ||
188 | break; | ||
189 | |||
190 | memcpy(copy->map, irq->map, sizeof copy->map); | ||
191 | copy->flags = irq->flags; | ||
192 | |||
193 | copy->next = res->irq; /* Yes, this is NULL */ | ||
194 | res->irq = copy; | ||
195 | |||
196 | if (!res->next) | ||
197 | break; | ||
198 | res = res->next; | ||
199 | } | ||
200 | kfree(irq); | ||
201 | |||
202 | res->next = quirk_isapnp_mpu_options(dev); | ||
203 | |||
204 | res = dev->independent; | ||
205 | res->irq = NULL; | ||
206 | } | ||
207 | |||
208 | static void quirk_isapnp_mpu_resources(struct pnp_dev *dev) | ||
209 | { | ||
210 | struct pnp_option *res; | ||
211 | |||
212 | res = dev->dependent; | ||
213 | if (!res) | ||
214 | return; | ||
215 | |||
216 | while (res->next) | ||
217 | res = res->next; | ||
218 | |||
219 | res->next = quirk_isapnp_mpu_options(dev); | ||
220 | } | ||
114 | 221 | ||
115 | #include <linux/pci.h> | 222 | #include <linux/pci.h> |
116 | 223 | ||
@@ -205,6 +312,11 @@ static struct pnp_fixup pnp_fixups[] = { | |||
205 | {"CTL0043", quirk_sb16audio_resources}, | 312 | {"CTL0043", quirk_sb16audio_resources}, |
206 | {"CTL0044", quirk_sb16audio_resources}, | 313 | {"CTL0044", quirk_sb16audio_resources}, |
207 | {"CTL0045", quirk_sb16audio_resources}, | 314 | {"CTL0045", quirk_sb16audio_resources}, |
315 | /* Add IRQ-less MPU options */ | ||
316 | {"ADS7151", quirk_ad1815_mpu_resources}, | ||
317 | {"ADS7181", quirk_isapnp_mpu_resources}, | ||
318 | {"AZT0002", quirk_isapnp_mpu_resources}, | ||
319 | /* PnP resources that might overlap PCI BARs */ | ||
208 | {"PNP0c01", quirk_system_pci_resources}, | 320 | {"PNP0c01", quirk_system_pci_resources}, |
209 | {"PNP0c02", quirk_system_pci_resources}, | 321 | {"PNP0c02", quirk_system_pci_resources}, |
210 | {""} | 322 | {""} |