diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/ats.c | 90 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_core.c | 11 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 4 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 1 | ||||
-rw-r--r-- | drivers/pci/msi.c | 121 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 13 | ||||
-rw-r--r-- | drivers/pci/pcie/aspm.c | 58 |
8 files changed, 214 insertions, 85 deletions
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index b0dd08e6a9da..9dd90b30f91a 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c | |||
@@ -175,21 +175,22 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs) | |||
175 | u32 max_requests; | 175 | u32 max_requests; |
176 | int pos; | 176 | int pos; |
177 | 177 | ||
178 | pos = pci_find_ext_capability(pdev, PCI_PRI_CAP); | 178 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); |
179 | if (!pos) | 179 | if (!pos) |
180 | return -EINVAL; | 180 | return -EINVAL; |
181 | 181 | ||
182 | pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control); | 182 | pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); |
183 | pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status); | 183 | pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); |
184 | if ((control & PCI_PRI_ENABLE) || !(status & PCI_PRI_STATUS_STOPPED)) | 184 | if ((control & PCI_PRI_CTRL_ENABLE) || |
185 | !(status & PCI_PRI_STATUS_STOPPED)) | ||
185 | return -EBUSY; | 186 | return -EBUSY; |
186 | 187 | ||
187 | pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ_OFF, &max_requests); | 188 | pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ, &max_requests); |
188 | reqs = min(max_requests, reqs); | 189 | reqs = min(max_requests, reqs); |
189 | pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ_OFF, reqs); | 190 | pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs); |
190 | 191 | ||
191 | control |= PCI_PRI_ENABLE; | 192 | control |= PCI_PRI_CTRL_ENABLE; |
192 | pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control); | 193 | pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); |
193 | 194 | ||
194 | return 0; | 195 | return 0; |
195 | } | 196 | } |
@@ -206,13 +207,13 @@ void pci_disable_pri(struct pci_dev *pdev) | |||
206 | u16 control; | 207 | u16 control; |
207 | int pos; | 208 | int pos; |
208 | 209 | ||
209 | pos = pci_find_ext_capability(pdev, PCI_PRI_CAP); | 210 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); |
210 | if (!pos) | 211 | if (!pos) |
211 | return; | 212 | return; |
212 | 213 | ||
213 | pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control); | 214 | pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); |
214 | control &= ~PCI_PRI_ENABLE; | 215 | control &= ~PCI_PRI_CTRL_ENABLE; |
215 | pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control); | 216 | pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); |
216 | } | 217 | } |
217 | EXPORT_SYMBOL_GPL(pci_disable_pri); | 218 | EXPORT_SYMBOL_GPL(pci_disable_pri); |
218 | 219 | ||
@@ -227,13 +228,13 @@ bool pci_pri_enabled(struct pci_dev *pdev) | |||
227 | u16 control; | 228 | u16 control; |
228 | int pos; | 229 | int pos; |
229 | 230 | ||
230 | pos = pci_find_ext_capability(pdev, PCI_PRI_CAP); | 231 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); |
231 | if (!pos) | 232 | if (!pos) |
232 | return false; | 233 | return false; |
233 | 234 | ||
234 | pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control); | 235 | pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); |
235 | 236 | ||
236 | return (control & PCI_PRI_ENABLE) ? true : false; | 237 | return (control & PCI_PRI_CTRL_ENABLE) ? true : false; |
237 | } | 238 | } |
238 | EXPORT_SYMBOL_GPL(pci_pri_enabled); | 239 | EXPORT_SYMBOL_GPL(pci_pri_enabled); |
239 | 240 | ||
@@ -249,17 +250,17 @@ int pci_reset_pri(struct pci_dev *pdev) | |||
249 | u16 control; | 250 | u16 control; |
250 | int pos; | 251 | int pos; |
251 | 252 | ||
252 | pos = pci_find_ext_capability(pdev, PCI_PRI_CAP); | 253 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); |
253 | if (!pos) | 254 | if (!pos) |
254 | return -EINVAL; | 255 | return -EINVAL; |
255 | 256 | ||
256 | pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control); | 257 | pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); |
257 | if (control & PCI_PRI_ENABLE) | 258 | if (control & PCI_PRI_CTRL_ENABLE) |
258 | return -EBUSY; | 259 | return -EBUSY; |
259 | 260 | ||
260 | control |= PCI_PRI_RESET; | 261 | control |= PCI_PRI_CTRL_RESET; |
261 | 262 | ||
262 | pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control); | 263 | pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); |
263 | 264 | ||
264 | return 0; | 265 | return 0; |
265 | } | 266 | } |
@@ -282,14 +283,14 @@ bool pci_pri_stopped(struct pci_dev *pdev) | |||
282 | u16 control, status; | 283 | u16 control, status; |
283 | int pos; | 284 | int pos; |
284 | 285 | ||
285 | pos = pci_find_ext_capability(pdev, PCI_PRI_CAP); | 286 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); |
286 | if (!pos) | 287 | if (!pos) |
287 | return true; | 288 | return true; |
288 | 289 | ||
289 | pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control); | 290 | pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); |
290 | pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status); | 291 | pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); |
291 | 292 | ||
292 | if (control & PCI_PRI_ENABLE) | 293 | if (control & PCI_PRI_CTRL_ENABLE) |
293 | return false; | 294 | return false; |
294 | 295 | ||
295 | return (status & PCI_PRI_STATUS_STOPPED) ? true : false; | 296 | return (status & PCI_PRI_STATUS_STOPPED) ? true : false; |
@@ -311,15 +312,15 @@ int pci_pri_status(struct pci_dev *pdev) | |||
311 | u16 status, control; | 312 | u16 status, control; |
312 | int pos; | 313 | int pos; |
313 | 314 | ||
314 | pos = pci_find_ext_capability(pdev, PCI_PRI_CAP); | 315 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); |
315 | if (!pos) | 316 | if (!pos) |
316 | return -EINVAL; | 317 | return -EINVAL; |
317 | 318 | ||
318 | pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control); | 319 | pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); |
319 | pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status); | 320 | pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); |
320 | 321 | ||
321 | /* Stopped bit is undefined when enable == 1, so clear it */ | 322 | /* Stopped bit is undefined when enable == 1, so clear it */ |
322 | if (control & PCI_PRI_ENABLE) | 323 | if (control & PCI_PRI_CTRL_ENABLE) |
323 | status &= ~PCI_PRI_STATUS_STOPPED; | 324 | status &= ~PCI_PRI_STATUS_STOPPED; |
324 | 325 | ||
325 | return status; | 326 | return status; |
@@ -342,25 +343,25 @@ int pci_enable_pasid(struct pci_dev *pdev, int features) | |||
342 | u16 control, supported; | 343 | u16 control, supported; |
343 | int pos; | 344 | int pos; |
344 | 345 | ||
345 | pos = pci_find_ext_capability(pdev, PCI_PASID_CAP); | 346 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); |
346 | if (!pos) | 347 | if (!pos) |
347 | return -EINVAL; | 348 | return -EINVAL; |
348 | 349 | ||
349 | pci_read_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, &control); | 350 | pci_read_config_word(pdev, pos + PCI_PASID_CTRL, &control); |
350 | pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported); | 351 | pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); |
351 | 352 | ||
352 | if (!(supported & PCI_PASID_ENABLE)) | 353 | if (control & PCI_PASID_CTRL_ENABLE) |
353 | return -EINVAL; | 354 | return -EINVAL; |
354 | 355 | ||
355 | supported &= PCI_PASID_EXEC | PCI_PASID_PRIV; | 356 | supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; |
356 | 357 | ||
357 | /* User wants to enable anything unsupported? */ | 358 | /* User wants to enable anything unsupported? */ |
358 | if ((supported & features) != features) | 359 | if ((supported & features) != features) |
359 | return -EINVAL; | 360 | return -EINVAL; |
360 | 361 | ||
361 | control = PCI_PASID_ENABLE | features; | 362 | control = PCI_PASID_CTRL_ENABLE | features; |
362 | 363 | ||
363 | pci_write_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, control); | 364 | pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control); |
364 | 365 | ||
365 | return 0; | 366 | return 0; |
366 | } | 367 | } |
@@ -376,11 +377,11 @@ void pci_disable_pasid(struct pci_dev *pdev) | |||
376 | u16 control = 0; | 377 | u16 control = 0; |
377 | int pos; | 378 | int pos; |
378 | 379 | ||
379 | pos = pci_find_ext_capability(pdev, PCI_PASID_CAP); | 380 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); |
380 | if (!pos) | 381 | if (!pos) |
381 | return; | 382 | return; |
382 | 383 | ||
383 | pci_write_config_word(pdev, pos + PCI_PASID_CONTROL_OFF, control); | 384 | pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control); |
384 | } | 385 | } |
385 | EXPORT_SYMBOL_GPL(pci_disable_pasid); | 386 | EXPORT_SYMBOL_GPL(pci_disable_pasid); |
386 | 387 | ||
@@ -391,22 +392,21 @@ EXPORT_SYMBOL_GPL(pci_disable_pasid); | |||
391 | * Returns a negative value when no PASI capability is present. | 392 | * Returns a negative value when no PASI capability is present. |
392 | * Otherwise is returns a bitmask with supported features. Current | 393 | * Otherwise is returns a bitmask with supported features. Current |
393 | * features reported are: | 394 | * features reported are: |
394 | * PCI_PASID_ENABLE - PASID capability can be enabled | 395 | * PCI_PASID_CAP_EXEC - Execute permission supported |
395 | * PCI_PASID_EXEC - Execute permission supported | 396 | * PCI_PASID_CAP_PRIV - Priviledged mode supported |
396 | * PCI_PASID_PRIV - Priviledged mode supported | ||
397 | */ | 397 | */ |
398 | int pci_pasid_features(struct pci_dev *pdev) | 398 | int pci_pasid_features(struct pci_dev *pdev) |
399 | { | 399 | { |
400 | u16 supported; | 400 | u16 supported; |
401 | int pos; | 401 | int pos; |
402 | 402 | ||
403 | pos = pci_find_ext_capability(pdev, PCI_PASID_CAP); | 403 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); |
404 | if (!pos) | 404 | if (!pos) |
405 | return -EINVAL; | 405 | return -EINVAL; |
406 | 406 | ||
407 | pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported); | 407 | pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); |
408 | 408 | ||
409 | supported &= PCI_PASID_ENABLE | PCI_PASID_EXEC | PCI_PASID_PRIV; | 409 | supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; |
410 | 410 | ||
411 | return supported; | 411 | return supported; |
412 | } | 412 | } |
@@ -426,11 +426,11 @@ int pci_max_pasids(struct pci_dev *pdev) | |||
426 | u16 supported; | 426 | u16 supported; |
427 | int pos; | 427 | int pos; |
428 | 428 | ||
429 | pos = pci_find_ext_capability(pdev, PCI_PASID_CAP); | 429 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); |
430 | if (!pos) | 430 | if (!pos) |
431 | return -EINVAL; | 431 | return -EINVAL; |
432 | 432 | ||
433 | pci_read_config_word(pdev, pos + PCI_PASID_CAP_OFF, &supported); | 433 | pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); |
434 | 434 | ||
435 | supported = (supported & PASID_NUMBER_MASK) >> PASID_NUMBER_SHIFT; | 435 | supported = (supported & PASID_NUMBER_MASK) >> PASID_NUMBER_SHIFT; |
436 | 436 | ||
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 838f571027b7..9a33fdde2d16 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -45,7 +45,6 @@ extern int pciehp_poll_time; | |||
45 | extern int pciehp_debug; | 45 | extern int pciehp_debug; |
46 | extern int pciehp_force; | 46 | extern int pciehp_force; |
47 | extern struct workqueue_struct *pciehp_wq; | 47 | extern struct workqueue_struct *pciehp_wq; |
48 | extern struct workqueue_struct *pciehp_ordered_wq; | ||
49 | 48 | ||
50 | #define dbg(format, arg...) \ | 49 | #define dbg(format, arg...) \ |
51 | do { \ | 50 | do { \ |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 7ac8358df8fd..b8c99d35ac97 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -43,7 +43,6 @@ int pciehp_poll_mode; | |||
43 | int pciehp_poll_time; | 43 | int pciehp_poll_time; |
44 | int pciehp_force; | 44 | int pciehp_force; |
45 | struct workqueue_struct *pciehp_wq; | 45 | struct workqueue_struct *pciehp_wq; |
46 | struct workqueue_struct *pciehp_ordered_wq; | ||
47 | 46 | ||
48 | #define DRIVER_VERSION "0.4" | 47 | #define DRIVER_VERSION "0.4" |
49 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 48 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -345,18 +344,11 @@ static int __init pcied_init(void) | |||
345 | if (!pciehp_wq) | 344 | if (!pciehp_wq) |
346 | return -ENOMEM; | 345 | return -ENOMEM; |
347 | 346 | ||
348 | pciehp_ordered_wq = alloc_ordered_workqueue("pciehp_ordered", 0); | ||
349 | if (!pciehp_ordered_wq) { | ||
350 | destroy_workqueue(pciehp_wq); | ||
351 | return -ENOMEM; | ||
352 | } | ||
353 | |||
354 | pciehp_firmware_init(); | 347 | pciehp_firmware_init(); |
355 | retval = pcie_port_service_register(&hpdriver_portdrv); | 348 | retval = pcie_port_service_register(&hpdriver_portdrv); |
356 | dbg("pcie_port_service_register = %d\n", retval); | 349 | dbg("pcie_port_service_register = %d\n", retval); |
357 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 350 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
358 | if (retval) { | 351 | if (retval) { |
359 | destroy_workqueue(pciehp_ordered_wq); | ||
360 | destroy_workqueue(pciehp_wq); | 352 | destroy_workqueue(pciehp_wq); |
361 | dbg("Failure to register service\n"); | 353 | dbg("Failure to register service\n"); |
362 | } | 354 | } |
@@ -366,9 +358,8 @@ static int __init pcied_init(void) | |||
366 | static void __exit pcied_cleanup(void) | 358 | static void __exit pcied_cleanup(void) |
367 | { | 359 | { |
368 | dbg("unload_pciehpd()\n"); | 360 | dbg("unload_pciehpd()\n"); |
369 | destroy_workqueue(pciehp_ordered_wq); | ||
370 | destroy_workqueue(pciehp_wq); | ||
371 | pcie_port_service_unregister(&hpdriver_portdrv); | 361 | pcie_port_service_unregister(&hpdriver_portdrv); |
362 | destroy_workqueue(pciehp_wq); | ||
372 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 363 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
373 | } | 364 | } |
374 | 365 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 085dbb5fc168..27f44295a657 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
344 | kfree(info); | 344 | kfree(info); |
345 | goto out; | 345 | goto out; |
346 | } | 346 | } |
347 | queue_work(pciehp_ordered_wq, &info->work); | 347 | queue_work(pciehp_wq, &info->work); |
348 | out: | 348 | out: |
349 | mutex_unlock(&p_slot->lock); | 349 | mutex_unlock(&p_slot->lock); |
350 | } | 350 | } |
@@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) | |||
439 | else | 439 | else |
440 | p_slot->state = POWERON_STATE; | 440 | p_slot->state = POWERON_STATE; |
441 | 441 | ||
442 | queue_work(pciehp_ordered_wq, &info->work); | 442 | queue_work(pciehp_wq, &info->work); |
443 | } | 443 | } |
444 | 444 | ||
445 | static void interrupt_event_handler(struct work_struct *work) | 445 | static void interrupt_event_handler(struct work_struct *work) |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7b1414810ae3..bcdbb1643621 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -806,7 +806,6 @@ static void pcie_cleanup_slot(struct controller *ctrl) | |||
806 | struct slot *slot = ctrl->slot; | 806 | struct slot *slot = ctrl->slot; |
807 | cancel_delayed_work(&slot->work); | 807 | cancel_delayed_work(&slot->work); |
808 | flush_workqueue(pciehp_wq); | 808 | flush_workqueue(pciehp_wq); |
809 | flush_workqueue(pciehp_ordered_wq); | ||
810 | kfree(slot); | 809 | kfree(slot); |
811 | } | 810 | } |
812 | 811 | ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 0e6d04d7ba4f..337e16ab4a92 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -323,6 +323,8 @@ static void free_msi_irqs(struct pci_dev *dev) | |||
323 | if (list_is_last(&entry->list, &dev->msi_list)) | 323 | if (list_is_last(&entry->list, &dev->msi_list)) |
324 | iounmap(entry->mask_base); | 324 | iounmap(entry->mask_base); |
325 | } | 325 | } |
326 | kobject_del(&entry->kobj); | ||
327 | kobject_put(&entry->kobj); | ||
326 | list_del(&entry->list); | 328 | list_del(&entry->list); |
327 | kfree(entry); | 329 | kfree(entry); |
328 | } | 330 | } |
@@ -403,6 +405,98 @@ void pci_restore_msi_state(struct pci_dev *dev) | |||
403 | } | 405 | } |
404 | EXPORT_SYMBOL_GPL(pci_restore_msi_state); | 406 | EXPORT_SYMBOL_GPL(pci_restore_msi_state); |
405 | 407 | ||
408 | |||
409 | #define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr) | ||
410 | #define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj) | ||
411 | |||
412 | struct msi_attribute { | ||
413 | struct attribute attr; | ||
414 | ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr, | ||
415 | char *buf); | ||
416 | ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr, | ||
417 | const char *buf, size_t count); | ||
418 | }; | ||
419 | |||
420 | static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr, | ||
421 | char *buf) | ||
422 | { | ||
423 | return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi"); | ||
424 | } | ||
425 | |||
426 | static ssize_t msi_irq_attr_show(struct kobject *kobj, | ||
427 | struct attribute *attr, char *buf) | ||
428 | { | ||
429 | struct msi_attribute *attribute = to_msi_attr(attr); | ||
430 | struct msi_desc *entry = to_msi_desc(kobj); | ||
431 | |||
432 | if (!attribute->show) | ||
433 | return -EIO; | ||
434 | |||
435 | return attribute->show(entry, attribute, buf); | ||
436 | } | ||
437 | |||
438 | static const struct sysfs_ops msi_irq_sysfs_ops = { | ||
439 | .show = msi_irq_attr_show, | ||
440 | }; | ||
441 | |||
442 | static struct msi_attribute mode_attribute = | ||
443 | __ATTR(mode, S_IRUGO, show_msi_mode, NULL); | ||
444 | |||
445 | |||
446 | struct attribute *msi_irq_default_attrs[] = { | ||
447 | &mode_attribute.attr, | ||
448 | NULL | ||
449 | }; | ||
450 | |||
451 | void msi_kobj_release(struct kobject *kobj) | ||
452 | { | ||
453 | struct msi_desc *entry = to_msi_desc(kobj); | ||
454 | |||
455 | pci_dev_put(entry->dev); | ||
456 | } | ||
457 | |||
458 | static struct kobj_type msi_irq_ktype = { | ||
459 | .release = msi_kobj_release, | ||
460 | .sysfs_ops = &msi_irq_sysfs_ops, | ||
461 | .default_attrs = msi_irq_default_attrs, | ||
462 | }; | ||
463 | |||
464 | static int populate_msi_sysfs(struct pci_dev *pdev) | ||
465 | { | ||
466 | struct msi_desc *entry; | ||
467 | struct kobject *kobj; | ||
468 | int ret; | ||
469 | int count = 0; | ||
470 | |||
471 | pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); | ||
472 | if (!pdev->msi_kset) | ||
473 | return -ENOMEM; | ||
474 | |||
475 | list_for_each_entry(entry, &pdev->msi_list, list) { | ||
476 | kobj = &entry->kobj; | ||
477 | kobj->kset = pdev->msi_kset; | ||
478 | pci_dev_get(pdev); | ||
479 | ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL, | ||
480 | "%u", entry->irq); | ||
481 | if (ret) | ||
482 | goto out_unroll; | ||
483 | |||
484 | count++; | ||
485 | } | ||
486 | |||
487 | return 0; | ||
488 | |||
489 | out_unroll: | ||
490 | list_for_each_entry(entry, &pdev->msi_list, list) { | ||
491 | if (!count) | ||
492 | break; | ||
493 | kobject_del(&entry->kobj); | ||
494 | kobject_put(&entry->kobj); | ||
495 | count--; | ||
496 | } | ||
497 | return ret; | ||
498 | } | ||
499 | |||
406 | /** | 500 | /** |
407 | * msi_capability_init - configure device's MSI capability structure | 501 | * msi_capability_init - configure device's MSI capability structure |
408 | * @dev: pointer to the pci_dev data structure of MSI device function | 502 | * @dev: pointer to the pci_dev data structure of MSI device function |
@@ -454,6 +548,13 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) | |||
454 | return ret; | 548 | return ret; |
455 | } | 549 | } |
456 | 550 | ||
551 | ret = populate_msi_sysfs(dev); | ||
552 | if (ret) { | ||
553 | msi_mask_irq(entry, mask, ~mask); | ||
554 | free_msi_irqs(dev); | ||
555 | return ret; | ||
556 | } | ||
557 | |||
457 | /* Set MSI enabled bits */ | 558 | /* Set MSI enabled bits */ |
458 | pci_intx_for_msi(dev, 0); | 559 | pci_intx_for_msi(dev, 0); |
459 | msi_set_enable(dev, pos, 1); | 560 | msi_set_enable(dev, pos, 1); |
@@ -574,6 +675,12 @@ static int msix_capability_init(struct pci_dev *dev, | |||
574 | 675 | ||
575 | msix_program_entries(dev, entries); | 676 | msix_program_entries(dev, entries); |
576 | 677 | ||
678 | ret = populate_msi_sysfs(dev); | ||
679 | if (ret) { | ||
680 | ret = 0; | ||
681 | goto error; | ||
682 | } | ||
683 | |||
577 | /* Set MSI-X enabled bits and unmask the function */ | 684 | /* Set MSI-X enabled bits and unmask the function */ |
578 | pci_intx_for_msi(dev, 0); | 685 | pci_intx_for_msi(dev, 0); |
579 | dev->msix_enabled = 1; | 686 | dev->msix_enabled = 1; |
@@ -732,6 +839,8 @@ void pci_disable_msi(struct pci_dev *dev) | |||
732 | 839 | ||
733 | pci_msi_shutdown(dev); | 840 | pci_msi_shutdown(dev); |
734 | free_msi_irqs(dev); | 841 | free_msi_irqs(dev); |
842 | kset_unregister(dev->msi_kset); | ||
843 | dev->msi_kset = NULL; | ||
735 | } | 844 | } |
736 | EXPORT_SYMBOL(pci_disable_msi); | 845 | EXPORT_SYMBOL(pci_disable_msi); |
737 | 846 | ||
@@ -830,6 +939,8 @@ void pci_disable_msix(struct pci_dev *dev) | |||
830 | 939 | ||
831 | pci_msix_shutdown(dev); | 940 | pci_msix_shutdown(dev); |
832 | free_msi_irqs(dev); | 941 | free_msi_irqs(dev); |
942 | kset_unregister(dev->msi_kset); | ||
943 | dev->msi_kset = NULL; | ||
833 | } | 944 | } |
834 | EXPORT_SYMBOL(pci_disable_msix); | 945 | EXPORT_SYMBOL(pci_disable_msix); |
835 | 946 | ||
@@ -870,5 +981,15 @@ EXPORT_SYMBOL(pci_msi_enabled); | |||
870 | 981 | ||
871 | void pci_msi_init_pci_dev(struct pci_dev *dev) | 982 | void pci_msi_init_pci_dev(struct pci_dev *dev) |
872 | { | 983 | { |
984 | int pos; | ||
873 | INIT_LIST_HEAD(&dev->msi_list); | 985 | INIT_LIST_HEAD(&dev->msi_list); |
986 | |||
987 | /* Disable the msi hardware to avoid screaming interrupts | ||
988 | * during boot. This is the power on reset default so | ||
989 | * usually this should be a noop. | ||
990 | */ | ||
991 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | ||
992 | if (pos) | ||
993 | msi_set_enable(dev, pos, 0); | ||
994 | msix_set_enable(dev, 0); | ||
874 | } | 995 | } |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 4ecb6408b0d6..060fd22a1103 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -45,16 +45,20 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) | |||
45 | { | 45 | { |
46 | struct pci_dev *pci_dev = context; | 46 | struct pci_dev *pci_dev = context; |
47 | 47 | ||
48 | if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) { | 48 | if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev) |
49 | return; | ||
50 | |||
51 | if (!pci_dev->pm_cap || !pci_dev->pme_support | ||
52 | || pci_check_pme_status(pci_dev)) { | ||
49 | if (pci_dev->pme_poll) | 53 | if (pci_dev->pme_poll) |
50 | pci_dev->pme_poll = false; | 54 | pci_dev->pme_poll = false; |
51 | 55 | ||
52 | pci_wakeup_event(pci_dev); | 56 | pci_wakeup_event(pci_dev); |
53 | pci_check_pme_status(pci_dev); | ||
54 | pm_runtime_resume(&pci_dev->dev); | 57 | pm_runtime_resume(&pci_dev->dev); |
55 | if (pci_dev->subordinate) | ||
56 | pci_pme_wakeup_bus(pci_dev->subordinate); | ||
57 | } | 58 | } |
59 | |||
60 | if (pci_dev->subordinate) | ||
61 | pci_pme_wakeup_bus(pci_dev->subordinate); | ||
58 | } | 62 | } |
59 | 63 | ||
60 | /** | 64 | /** |
@@ -395,7 +399,6 @@ static int __init acpi_pci_init(void) | |||
395 | 399 | ||
396 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { | 400 | if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { |
397 | printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); | 401 | printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); |
398 | pcie_clear_aspm(); | ||
399 | pcie_no_aspm(); | 402 | pcie_no_aspm(); |
400 | } | 403 | } |
401 | 404 | ||
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index cbfbab18be91..1cfbf228fbb1 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -68,7 +68,7 @@ struct pcie_link_state { | |||
68 | struct aspm_latency acceptable[8]; | 68 | struct aspm_latency acceptable[8]; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int aspm_disabled, aspm_force, aspm_clear_state; | 71 | static int aspm_disabled, aspm_force; |
72 | static bool aspm_support_enabled = true; | 72 | static bool aspm_support_enabled = true; |
73 | static DEFINE_MUTEX(aspm_lock); | 73 | static DEFINE_MUTEX(aspm_lock); |
74 | static LIST_HEAD(link_list); | 74 | static LIST_HEAD(link_list); |
@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
500 | int pos; | 500 | int pos; |
501 | u32 reg32; | 501 | u32 reg32; |
502 | 502 | ||
503 | if (aspm_clear_state) | ||
504 | return -EINVAL; | ||
505 | |||
506 | /* | 503 | /* |
507 | * Some functions in a slot might not all be PCIe functions, | 504 | * Some functions in a slot might not all be PCIe functions, |
508 | * very strange. Disable ASPM for the whole slot | 505 | * very strange. Disable ASPM for the whole slot |
@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
574 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) | 571 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) |
575 | return; | 572 | return; |
576 | 573 | ||
577 | if (aspm_disabled && !aspm_clear_state) | ||
578 | return; | ||
579 | |||
580 | /* VIA has a strange chipset, root port is under a bridge */ | 574 | /* VIA has a strange chipset, root port is under a bridge */ |
581 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && | 575 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && |
582 | pdev->bus->self) | 576 | pdev->bus->self) |
@@ -608,7 +602,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
608 | * the BIOS's expectation, we'll do so once pci_enable_device() is | 602 | * the BIOS's expectation, we'll do so once pci_enable_device() is |
609 | * called. | 603 | * called. |
610 | */ | 604 | */ |
611 | if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) { | 605 | if (aspm_policy != POLICY_POWERSAVE) { |
612 | pcie_config_aspm_path(link); | 606 | pcie_config_aspm_path(link); |
613 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); | 607 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); |
614 | } | 608 | } |
@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) | |||
649 | struct pci_dev *parent = pdev->bus->self; | 643 | struct pci_dev *parent = pdev->bus->self; |
650 | struct pcie_link_state *link, *root, *parent_link; | 644 | struct pcie_link_state *link, *root, *parent_link; |
651 | 645 | ||
652 | if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || | 646 | if (!pci_is_pcie(pdev) || !parent || !parent->link_state) |
653 | !parent || !parent->link_state) | ||
654 | return; | 647 | return; |
655 | if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && | 648 | if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && |
656 | (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) | 649 | (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) |
@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) | |||
734 | * pci_disable_link_state - disable pci device's link state, so the link will | 727 | * pci_disable_link_state - disable pci device's link state, so the link will |
735 | * never enter specific states | 728 | * never enter specific states |
736 | */ | 729 | */ |
737 | static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) | 730 | static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, |
731 | bool force) | ||
738 | { | 732 | { |
739 | struct pci_dev *parent = pdev->bus->self; | 733 | struct pci_dev *parent = pdev->bus->self; |
740 | struct pcie_link_state *link; | 734 | struct pcie_link_state *link; |
741 | 735 | ||
742 | if (aspm_disabled || !pci_is_pcie(pdev)) | 736 | if (aspm_disabled && !force) |
737 | return; | ||
738 | |||
739 | if (!pci_is_pcie(pdev)) | ||
743 | return; | 740 | return; |
741 | |||
744 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || | 742 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || |
745 | pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) | 743 | pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) |
746 | parent = pdev; | 744 | parent = pdev; |
@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) | |||
768 | 766 | ||
769 | void pci_disable_link_state_locked(struct pci_dev *pdev, int state) | 767 | void pci_disable_link_state_locked(struct pci_dev *pdev, int state) |
770 | { | 768 | { |
771 | __pci_disable_link_state(pdev, state, false); | 769 | __pci_disable_link_state(pdev, state, false, false); |
772 | } | 770 | } |
773 | EXPORT_SYMBOL(pci_disable_link_state_locked); | 771 | EXPORT_SYMBOL(pci_disable_link_state_locked); |
774 | 772 | ||
775 | void pci_disable_link_state(struct pci_dev *pdev, int state) | 773 | void pci_disable_link_state(struct pci_dev *pdev, int state) |
776 | { | 774 | { |
777 | __pci_disable_link_state(pdev, state, true); | 775 | __pci_disable_link_state(pdev, state, true, false); |
778 | } | 776 | } |
779 | EXPORT_SYMBOL(pci_disable_link_state); | 777 | EXPORT_SYMBOL(pci_disable_link_state); |
780 | 778 | ||
779 | void pcie_clear_aspm(struct pci_bus *bus) | ||
780 | { | ||
781 | struct pci_dev *child; | ||
782 | |||
783 | /* | ||
784 | * Clear any ASPM setup that the firmware has carried out on this bus | ||
785 | */ | ||
786 | list_for_each_entry(child, &bus->devices, bus_list) { | ||
787 | __pci_disable_link_state(child, PCIE_LINK_STATE_L0S | | ||
788 | PCIE_LINK_STATE_L1 | | ||
789 | PCIE_LINK_STATE_CLKPM, | ||
790 | false, true); | ||
791 | } | ||
792 | } | ||
793 | |||
781 | static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) | 794 | static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) |
782 | { | 795 | { |
783 | int i; | 796 | int i; |
@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
935 | static int __init pcie_aspm_disable(char *str) | 948 | static int __init pcie_aspm_disable(char *str) |
936 | { | 949 | { |
937 | if (!strcmp(str, "off")) { | 950 | if (!strcmp(str, "off")) { |
951 | aspm_policy = POLICY_DEFAULT; | ||
938 | aspm_disabled = 1; | 952 | aspm_disabled = 1; |
939 | aspm_support_enabled = false; | 953 | aspm_support_enabled = false; |
940 | printk(KERN_INFO "PCIe ASPM is disabled\n"); | 954 | printk(KERN_INFO "PCIe ASPM is disabled\n"); |
@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str) | |||
947 | 961 | ||
948 | __setup("pcie_aspm=", pcie_aspm_disable); | 962 | __setup("pcie_aspm=", pcie_aspm_disable); |
949 | 963 | ||
950 | void pcie_clear_aspm(void) | ||
951 | { | ||
952 | if (!aspm_force) | ||
953 | aspm_clear_state = 1; | ||
954 | } | ||
955 | |||
956 | void pcie_no_aspm(void) | 964 | void pcie_no_aspm(void) |
957 | { | 965 | { |
958 | if (!aspm_force) | 966 | /* |
967 | * Disabling ASPM is intended to prevent the kernel from modifying | ||
968 | * existing hardware state, not to clear existing state. To that end: | ||
969 | * (a) set policy to POLICY_DEFAULT in order to avoid changing state | ||
970 | * (b) prevent userspace from changing policy | ||
971 | */ | ||
972 | if (!aspm_force) { | ||
973 | aspm_policy = POLICY_DEFAULT; | ||
959 | aspm_disabled = 1; | 974 | aspm_disabled = 1; |
975 | } | ||
960 | } | 976 | } |
961 | 977 | ||
962 | /** | 978 | /** |