diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-23 13:43:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-23 13:43:30 -0400 |
commit | 6cff0a118f23b98c604a3604ea9de11338e24fbe (patch) | |
tree | d766082593eb2f30d61f93d3058cb68c888434e9 | |
parent | 06987dad0a563e406e7841df0f8759368523714f (diff) | |
parent | 6687aeb9cd3d40904d1f9e884d2145603c23adfa (diff) |
Merge tag 'platform-drivers-x86-v4.14-3' of git://git.infradead.org/linux-platform-drivers-x86
Pull x86 platform driver fixes from Darren Hart:
"Use a spin_lock instead of mutex in atomic context. The devm_ fix is a
dependency. Summary:
intel_pmc_ipc:
- Use spin_lock to protect GCR updates
- Use devm_* calls in driver probe function"
* tag 'platform-drivers-x86-v4.14-3' of git://git.infradead.org/linux-platform-drivers-x86:
platform/x86: intel_pmc_ipc: Use spin_lock to protect GCR updates
platform/x86: intel_pmc_ipc: Use devm_* calls in driver probe function
-rw-r--r-- | drivers/platform/x86/intel_pmc_ipc.c | 115 |
1 files changed, 41 insertions, 74 deletions
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index bb792a52248b..e03fa31446ca 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/suspend.h> | 33 | #include <linux/suspend.h> |
34 | #include <linux/acpi.h> | 34 | #include <linux/acpi.h> |
35 | #include <linux/io-64-nonatomic-lo-hi.h> | 35 | #include <linux/io-64-nonatomic-lo-hi.h> |
36 | #include <linux/spinlock.h> | ||
36 | 37 | ||
37 | #include <asm/intel_pmc_ipc.h> | 38 | #include <asm/intel_pmc_ipc.h> |
38 | 39 | ||
@@ -131,6 +132,7 @@ static struct intel_pmc_ipc_dev { | |||
131 | /* gcr */ | 132 | /* gcr */ |
132 | void __iomem *gcr_mem_base; | 133 | void __iomem *gcr_mem_base; |
133 | bool has_gcr_regs; | 134 | bool has_gcr_regs; |
135 | spinlock_t gcr_lock; | ||
134 | 136 | ||
135 | /* punit */ | 137 | /* punit */ |
136 | struct platform_device *punit_dev; | 138 | struct platform_device *punit_dev; |
@@ -225,17 +227,17 @@ int intel_pmc_gcr_read(u32 offset, u32 *data) | |||
225 | { | 227 | { |
226 | int ret; | 228 | int ret; |
227 | 229 | ||
228 | mutex_lock(&ipclock); | 230 | spin_lock(&ipcdev.gcr_lock); |
229 | 231 | ||
230 | ret = is_gcr_valid(offset); | 232 | ret = is_gcr_valid(offset); |
231 | if (ret < 0) { | 233 | if (ret < 0) { |
232 | mutex_unlock(&ipclock); | 234 | spin_unlock(&ipcdev.gcr_lock); |
233 | return ret; | 235 | return ret; |
234 | } | 236 | } |
235 | 237 | ||
236 | *data = readl(ipcdev.gcr_mem_base + offset); | 238 | *data = readl(ipcdev.gcr_mem_base + offset); |
237 | 239 | ||
238 | mutex_unlock(&ipclock); | 240 | spin_unlock(&ipcdev.gcr_lock); |
239 | 241 | ||
240 | return 0; | 242 | return 0; |
241 | } | 243 | } |
@@ -255,17 +257,17 @@ int intel_pmc_gcr_write(u32 offset, u32 data) | |||
255 | { | 257 | { |
256 | int ret; | 258 | int ret; |
257 | 259 | ||
258 | mutex_lock(&ipclock); | 260 | spin_lock(&ipcdev.gcr_lock); |
259 | 261 | ||
260 | ret = is_gcr_valid(offset); | 262 | ret = is_gcr_valid(offset); |
261 | if (ret < 0) { | 263 | if (ret < 0) { |
262 | mutex_unlock(&ipclock); | 264 | spin_unlock(&ipcdev.gcr_lock); |
263 | return ret; | 265 | return ret; |
264 | } | 266 | } |
265 | 267 | ||
266 | writel(data, ipcdev.gcr_mem_base + offset); | 268 | writel(data, ipcdev.gcr_mem_base + offset); |
267 | 269 | ||
268 | mutex_unlock(&ipclock); | 270 | spin_unlock(&ipcdev.gcr_lock); |
269 | 271 | ||
270 | return 0; | 272 | return 0; |
271 | } | 273 | } |
@@ -287,7 +289,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) | |||
287 | u32 new_val; | 289 | u32 new_val; |
288 | int ret = 0; | 290 | int ret = 0; |
289 | 291 | ||
290 | mutex_lock(&ipclock); | 292 | spin_lock(&ipcdev.gcr_lock); |
291 | 293 | ||
292 | ret = is_gcr_valid(offset); | 294 | ret = is_gcr_valid(offset); |
293 | if (ret < 0) | 295 | if (ret < 0) |
@@ -309,7 +311,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) | |||
309 | } | 311 | } |
310 | 312 | ||
311 | gcr_ipc_unlock: | 313 | gcr_ipc_unlock: |
312 | mutex_unlock(&ipclock); | 314 | spin_unlock(&ipcdev.gcr_lock); |
313 | return ret; | 315 | return ret; |
314 | } | 316 | } |
315 | EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); | 317 | EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); |
@@ -480,52 +482,41 @@ static irqreturn_t ioc(int irq, void *dev_id) | |||
480 | 482 | ||
481 | static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 483 | static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
482 | { | 484 | { |
483 | resource_size_t pci_resource; | 485 | struct intel_pmc_ipc_dev *pmc = &ipcdev; |
484 | int ret; | 486 | int ret; |
485 | int len; | ||
486 | 487 | ||
487 | ipcdev.dev = &pci_dev_get(pdev)->dev; | 488 | /* Only one PMC is supported */ |
488 | ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; | 489 | if (pmc->dev) |
490 | return -EBUSY; | ||
489 | 491 | ||
490 | ret = pci_enable_device(pdev); | 492 | pmc->irq_mode = IPC_TRIGGER_MODE_IRQ; |
493 | |||
494 | spin_lock_init(&ipcdev.gcr_lock); | ||
495 | |||
496 | ret = pcim_enable_device(pdev); | ||
491 | if (ret) | 497 | if (ret) |
492 | return ret; | 498 | return ret; |
493 | 499 | ||
494 | ret = pci_request_regions(pdev, "intel_pmc_ipc"); | 500 | ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); |
495 | if (ret) | 501 | if (ret) |
496 | return ret; | 502 | return ret; |
497 | 503 | ||
498 | pci_resource = pci_resource_start(pdev, 0); | 504 | init_completion(&pmc->cmd_complete); |
499 | len = pci_resource_len(pdev, 0); | ||
500 | if (!pci_resource || !len) { | ||
501 | dev_err(&pdev->dev, "Failed to get resource\n"); | ||
502 | return -ENOMEM; | ||
503 | } | ||
504 | 505 | ||
505 | init_completion(&ipcdev.cmd_complete); | 506 | pmc->ipc_base = pcim_iomap_table(pdev)[0]; |
506 | 507 | ||
507 | if (request_irq(pdev->irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) { | 508 | ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc", |
509 | pmc); | ||
510 | if (ret) { | ||
508 | dev_err(&pdev->dev, "Failed to request irq\n"); | 511 | dev_err(&pdev->dev, "Failed to request irq\n"); |
509 | return -EBUSY; | 512 | return ret; |
510 | } | 513 | } |
511 | 514 | ||
512 | ipcdev.ipc_base = ioremap_nocache(pci_resource, len); | 515 | pmc->dev = &pdev->dev; |
513 | if (!ipcdev.ipc_base) { | ||
514 | dev_err(&pdev->dev, "Failed to ioremap ipc base\n"); | ||
515 | free_irq(pdev->irq, &ipcdev); | ||
516 | ret = -ENOMEM; | ||
517 | } | ||
518 | 516 | ||
519 | return ret; | 517 | pci_set_drvdata(pdev, pmc); |
520 | } | ||
521 | 518 | ||
522 | static void ipc_pci_remove(struct pci_dev *pdev) | 519 | return 0; |
523 | { | ||
524 | free_irq(pdev->irq, &ipcdev); | ||
525 | pci_release_regions(pdev); | ||
526 | pci_dev_put(pdev); | ||
527 | iounmap(ipcdev.ipc_base); | ||
528 | ipcdev.dev = NULL; | ||
529 | } | 520 | } |
530 | 521 | ||
531 | static const struct pci_device_id ipc_pci_ids[] = { | 522 | static const struct pci_device_id ipc_pci_ids[] = { |
@@ -540,7 +531,6 @@ static struct pci_driver ipc_pci_driver = { | |||
540 | .name = "intel_pmc_ipc", | 531 | .name = "intel_pmc_ipc", |
541 | .id_table = ipc_pci_ids, | 532 | .id_table = ipc_pci_ids, |
542 | .probe = ipc_pci_probe, | 533 | .probe = ipc_pci_probe, |
543 | .remove = ipc_pci_remove, | ||
544 | }; | 534 | }; |
545 | 535 | ||
546 | static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev, | 536 | static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev, |
@@ -850,17 +840,12 @@ static int ipc_plat_get_res(struct platform_device *pdev) | |||
850 | return -ENXIO; | 840 | return -ENXIO; |
851 | } | 841 | } |
852 | size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; | 842 | size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; |
843 | res->end = res->start + size - 1; | ||
844 | |||
845 | addr = devm_ioremap_resource(&pdev->dev, res); | ||
846 | if (IS_ERR(addr)) | ||
847 | return PTR_ERR(addr); | ||
853 | 848 | ||
854 | if (!request_mem_region(res->start, size, pdev->name)) { | ||
855 | dev_err(&pdev->dev, "Failed to request ipc resource\n"); | ||
856 | return -EBUSY; | ||
857 | } | ||
858 | addr = ioremap_nocache(res->start, size); | ||
859 | if (!addr) { | ||
860 | dev_err(&pdev->dev, "I/O memory remapping failed\n"); | ||
861 | release_mem_region(res->start, size); | ||
862 | return -ENOMEM; | ||
863 | } | ||
864 | ipcdev.ipc_base = addr; | 849 | ipcdev.ipc_base = addr; |
865 | 850 | ||
866 | ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; | 851 | ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; |
@@ -917,12 +902,12 @@ MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids); | |||
917 | 902 | ||
918 | static int ipc_plat_probe(struct platform_device *pdev) | 903 | static int ipc_plat_probe(struct platform_device *pdev) |
919 | { | 904 | { |
920 | struct resource *res; | ||
921 | int ret; | 905 | int ret; |
922 | 906 | ||
923 | ipcdev.dev = &pdev->dev; | 907 | ipcdev.dev = &pdev->dev; |
924 | ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; | 908 | ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; |
925 | init_completion(&ipcdev.cmd_complete); | 909 | init_completion(&ipcdev.cmd_complete); |
910 | spin_lock_init(&ipcdev.gcr_lock); | ||
926 | 911 | ||
927 | ipcdev.irq = platform_get_irq(pdev, 0); | 912 | ipcdev.irq = platform_get_irq(pdev, 0); |
928 | if (ipcdev.irq < 0) { | 913 | if (ipcdev.irq < 0) { |
@@ -939,11 +924,11 @@ static int ipc_plat_probe(struct platform_device *pdev) | |||
939 | ret = ipc_create_pmc_devices(); | 924 | ret = ipc_create_pmc_devices(); |
940 | if (ret) { | 925 | if (ret) { |
941 | dev_err(&pdev->dev, "Failed to create pmc devices\n"); | 926 | dev_err(&pdev->dev, "Failed to create pmc devices\n"); |
942 | goto err_device; | 927 | return ret; |
943 | } | 928 | } |
944 | 929 | ||
945 | if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND, | 930 | if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, |
946 | "intel_pmc_ipc", &ipcdev)) { | 931 | "intel_pmc_ipc", &ipcdev)) { |
947 | dev_err(&pdev->dev, "Failed to request irq\n"); | 932 | dev_err(&pdev->dev, "Failed to request irq\n"); |
948 | ret = -EBUSY; | 933 | ret = -EBUSY; |
949 | goto err_irq; | 934 | goto err_irq; |
@@ -960,40 +945,22 @@ static int ipc_plat_probe(struct platform_device *pdev) | |||
960 | 945 | ||
961 | return 0; | 946 | return 0; |
962 | err_sys: | 947 | err_sys: |
963 | free_irq(ipcdev.irq, &ipcdev); | 948 | devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); |
964 | err_irq: | 949 | err_irq: |
965 | platform_device_unregister(ipcdev.tco_dev); | 950 | platform_device_unregister(ipcdev.tco_dev); |
966 | platform_device_unregister(ipcdev.punit_dev); | 951 | platform_device_unregister(ipcdev.punit_dev); |
967 | platform_device_unregister(ipcdev.telemetry_dev); | 952 | platform_device_unregister(ipcdev.telemetry_dev); |
968 | err_device: | 953 | |
969 | iounmap(ipcdev.ipc_base); | ||
970 | res = platform_get_resource(pdev, IORESOURCE_MEM, | ||
971 | PLAT_RESOURCE_IPC_INDEX); | ||
972 | if (res) { | ||
973 | release_mem_region(res->start, | ||
974 | PLAT_RESOURCE_IPC_SIZE + | ||
975 | PLAT_RESOURCE_GCR_SIZE); | ||
976 | } | ||
977 | return ret; | 954 | return ret; |
978 | } | 955 | } |
979 | 956 | ||
980 | static int ipc_plat_remove(struct platform_device *pdev) | 957 | static int ipc_plat_remove(struct platform_device *pdev) |
981 | { | 958 | { |
982 | struct resource *res; | ||
983 | |||
984 | sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group); | 959 | sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group); |
985 | free_irq(ipcdev.irq, &ipcdev); | 960 | devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); |
986 | platform_device_unregister(ipcdev.tco_dev); | 961 | platform_device_unregister(ipcdev.tco_dev); |
987 | platform_device_unregister(ipcdev.punit_dev); | 962 | platform_device_unregister(ipcdev.punit_dev); |
988 | platform_device_unregister(ipcdev.telemetry_dev); | 963 | platform_device_unregister(ipcdev.telemetry_dev); |
989 | iounmap(ipcdev.ipc_base); | ||
990 | res = platform_get_resource(pdev, IORESOURCE_MEM, | ||
991 | PLAT_RESOURCE_IPC_INDEX); | ||
992 | if (res) { | ||
993 | release_mem_region(res->start, | ||
994 | PLAT_RESOURCE_IPC_SIZE + | ||
995 | PLAT_RESOURCE_GCR_SIZE); | ||
996 | } | ||
997 | ipcdev.dev = NULL; | 964 | ipcdev.dev = NULL; |
998 | return 0; | 965 | return 0; |
999 | } | 966 | } |