aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-10-23 13:43:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-10-23 13:43:30 -0400
commit6cff0a118f23b98c604a3604ea9de11338e24fbe (patch)
treed766082593eb2f30d61f93d3058cb68c888434e9
parent06987dad0a563e406e7841df0f8759368523714f (diff)
parent6687aeb9cd3d40904d1f9e884d2145603c23adfa (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.c115
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
311gcr_ipc_unlock: 313gcr_ipc_unlock:
312 mutex_unlock(&ipclock); 314 spin_unlock(&ipcdev.gcr_lock);
313 return ret; 315 return ret;
314} 316}
315EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); 317EXPORT_SYMBOL_GPL(intel_pmc_gcr_update);
@@ -480,52 +482,41 @@ static irqreturn_t ioc(int irq, void *dev_id)
480 482
481static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 483static 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
522static 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
531static const struct pci_device_id ipc_pci_ids[] = { 522static 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
546static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev, 536static 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
918static int ipc_plat_probe(struct platform_device *pdev) 903static 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;
962err_sys: 947err_sys:
963 free_irq(ipcdev.irq, &ipcdev); 948 devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
964err_irq: 949err_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);
968err_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
980static int ipc_plat_remove(struct platform_device *pdev) 957static 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}