forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-09 244b2c5ca8b14627e4a17755e5922221e121c771
kernel/drivers/virtio/virtio_mmio.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Virtio memory mapped device driver
34 *
....@@ -48,12 +49,7 @@
4849 * virtio_mmio.device=0x100@0x100b0000:48 \
4950 * virtio_mmio.device=1K@0x1001e000:74
5051 *
51
- *
52
- *
5352 * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007
54
- *
55
- * This work is licensed under the terms of the GNU GPL, version 2 or later.
56
- * See the COPYING file in the top-level directory.
5753 */
5854
5955 #define pr_fmt(fmt) "virtio-mmio: " fmt
....@@ -66,6 +62,7 @@
6662 #include <linux/list.h>
6763 #include <linux/module.h>
6864 #include <linux/platform_device.h>
65
+#include <linux/pm.h>
6966 #include <linux/slab.h>
7067 #include <linux/spinlock.h>
7168 #include <linux/virtio.h>
....@@ -467,8 +464,11 @@
467464 struct irq_affinity *desc)
468465 {
469466 struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
470
- unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
471
- int i, err;
467
+ int irq = platform_get_irq(vm_dev->pdev, 0);
468
+ int i, err, queue_idx = 0;
469
+
470
+ if (irq < 0)
471
+ return irq;
472472
473473 err = request_irq(irq, vm_interrupt, IRQF_SHARED,
474474 dev_name(&vdev->dev), vm_dev);
....@@ -476,7 +476,12 @@
476476 return err;
477477
478478 for (i = 0; i < nvqs; ++i) {
479
- vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i],
479
+ if (!names[i]) {
480
+ vqs[i] = NULL;
481
+ continue;
482
+ }
483
+
484
+ vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
480485 ctx ? ctx[i] : false);
481486 if (IS_ERR(vqs[i])) {
482487 vm_del_vqs(vdev);
....@@ -494,6 +499,36 @@
494499 return vm_dev->pdev->name;
495500 }
496501
502
+static bool vm_get_shm_region(struct virtio_device *vdev,
503
+ struct virtio_shm_region *region, u8 id)
504
+{
505
+ struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
506
+ u64 len, addr;
507
+
508
+ /* Select the region we're interested in */
509
+ writel(id, vm_dev->base + VIRTIO_MMIO_SHM_SEL);
510
+
511
+ /* Read the region size */
512
+ len = (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_LEN_LOW);
513
+ len |= (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_LEN_HIGH) << 32;
514
+
515
+ region->len = len;
516
+
517
+ /* Check if region length is -1. If that's the case, the shared memory
518
+ * region does not exist and there is no need to proceed further.
519
+ */
520
+ if (len == ~(u64)0)
521
+ return false;
522
+
523
+ /* Read the region base address */
524
+ addr = (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_BASE_LOW);
525
+ addr |= (u64) readl(vm_dev->base + VIRTIO_MMIO_SHM_BASE_HIGH) << 32;
526
+
527
+ region->addr = addr;
528
+
529
+ return true;
530
+}
531
+
497532 static const struct virtio_config_ops virtio_mmio_config_ops = {
498533 .get = vm_get,
499534 .set = vm_set,
....@@ -506,18 +541,39 @@
506541 .get_features = vm_get_features,
507542 .finalize_features = vm_finalize_features,
508543 .bus_name = vm_bus_name,
544
+ .get_shm_region = vm_get_shm_region,
509545 };
510546
547
+#ifdef CONFIG_PM_SLEEP
548
+static int virtio_mmio_freeze(struct device *dev)
549
+{
550
+ struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
551
+
552
+ return virtio_device_freeze(&vm_dev->vdev);
553
+}
554
+
555
+static int virtio_mmio_restore(struct device *dev)
556
+{
557
+ struct virtio_mmio_device *vm_dev = dev_get_drvdata(dev);
558
+
559
+ if (vm_dev->version == 1)
560
+ writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE);
561
+
562
+ return virtio_device_restore(&vm_dev->vdev);
563
+}
564
+
565
+static const struct dev_pm_ops virtio_mmio_pm_ops = {
566
+ SET_SYSTEM_SLEEP_PM_OPS(virtio_mmio_freeze, virtio_mmio_restore)
567
+};
568
+#endif
511569
512570 static void virtio_mmio_release_dev(struct device *_d)
513571 {
514572 struct virtio_device *vdev =
515573 container_of(_d, struct virtio_device, dev);
516
- struct virtio_mmio_device *vm_dev =
517
- container_of(vdev, struct virtio_mmio_device, vdev);
518
- struct platform_device *pdev = vm_dev->pdev;
574
+ struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
519575
520
- devm_kfree(&pdev->dev, vm_dev);
576
+ kfree(vm_dev);
521577 }
522578
523579 /* Platform device */
....@@ -525,19 +581,10 @@
525581 static int virtio_mmio_probe(struct platform_device *pdev)
526582 {
527583 struct virtio_mmio_device *vm_dev;
528
- struct resource *mem;
529584 unsigned long magic;
530585 int rc;
531586
532
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
533
- if (!mem)
534
- return -EINVAL;
535
-
536
- if (!devm_request_mem_region(&pdev->dev, mem->start,
537
- resource_size(mem), pdev->name))
538
- return -EBUSY;
539
-
540
- vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL);
587
+ vm_dev = kzalloc(sizeof(*vm_dev), GFP_KERNEL);
541588 if (!vm_dev)
542589 return -ENOMEM;
543590
....@@ -548,9 +595,9 @@
548595 INIT_LIST_HEAD(&vm_dev->virtqueues);
549596 spin_lock_init(&vm_dev->lock);
550597
551
- vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
552
- if (vm_dev->base == NULL)
553
- return -EFAULT;
598
+ vm_dev->base = devm_platform_ioremap_resource(pdev, 0);
599
+ if (IS_ERR(vm_dev->base))
600
+ return PTR_ERR(vm_dev->base);
554601
555602 /* Check magic value */
556603 magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE);
....@@ -646,11 +693,11 @@
646693 &vm_cmdline_id, &consumed);
647694
648695 /*
649
- * sscanf() must processes at least 2 chunks; also there
696
+ * sscanf() must process at least 2 chunks; also there
650697 * must be no extra characters after the last chunk, so
651698 * str[consumed] must be '\0'
652699 */
653
- if (processed < 2 || str[consumed])
700
+ if (processed < 2 || str[consumed] || irq == 0)
654701 return -EINVAL;
655702
656703 resources[0].flags = IORESOURCE_MEM;
....@@ -663,6 +710,7 @@
663710 if (!vm_cmdline_parent_registered) {
664711 err = device_register(&vm_cmdline_parent);
665712 if (err) {
713
+ put_device(&vm_cmdline_parent);
666714 pr_err("Failed to register parent device!\n");
667715 return err;
668716 }
....@@ -760,6 +808,9 @@
760808 .name = "virtio-mmio",
761809 .of_match_table = virtio_mmio_match,
762810 .acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match),
811
+#ifdef CONFIG_PM_SLEEP
812
+ .pm = &virtio_mmio_pm_ops,
813
+#endif
763814 },
764815 };
765816