axon_ram: add dax_operations support
authorDan Williams <dan.j.williams@intel.com>
Wed, 25 Jan 2017 23:25:11 +0000 (15:25 -0800)
committerDan Williams <dan.j.williams@intel.com>
Wed, 19 Apr 2017 22:14:36 +0000 (15:14 -0700)
Setup a dax_device to have the same lifetime as the axon_ram block
device and add a ->direct_access() method that is equivalent to
axon_ram_direct_access(). Once fs/dax.c has been converted to use
dax_operations the old axon_ram_direct_access() will be removed.

Reported-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
arch/powerpc/platforms/Kconfig
arch/powerpc/sysdev/axonram.c

index 7e3a2eb..33244e3 100644 (file)
@@ -284,6 +284,7 @@ config CPM2
 config AXON_RAM
        tristate "Axon DDR2 memory device driver"
        depends on PPC_IBM_CELL_BLADE && BLOCK
+       select DAX
        default m
        help
          It registers one block device per Axon's DDR2 memory bank found
index f523ac8..171ba86 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <linux/bio.h>
 #include <linux/blkdev.h>
+#include <linux/dax.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
@@ -62,6 +63,7 @@ static int azfs_major, azfs_minor;
 struct axon_ram_bank {
        struct platform_device  *device;
        struct gendisk          *disk;
+       struct dax_device       *dax_dev;
        unsigned int            irq_id;
        unsigned long           ph_addr;
        unsigned long           io_addr;
@@ -137,25 +139,47 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
        return BLK_QC_T_NONE;
 }
 
+static long
+__axon_ram_direct_access(struct axon_ram_bank *bank, pgoff_t pgoff, long nr_pages,
+                      void **kaddr, pfn_t *pfn)
+{
+       resource_size_t offset = pgoff * PAGE_SIZE;
+
+       *kaddr = (void *) bank->io_addr + offset;
+       *pfn = phys_to_pfn_t(bank->ph_addr + offset, PFN_DEV);
+       return (bank->size - offset) / PAGE_SIZE;
+}
+
 /**
  * axon_ram_direct_access - direct_access() method for block device
  * @device, @sector, @data: see block_device_operations method
  */
 static long
-axon_ram_direct_access(struct block_device *device, sector_t sector,
+axon_ram_blk_direct_access(struct block_device *device, sector_t sector,
                       void **kaddr, pfn_t *pfn, long size)
 {
        struct axon_ram_bank *bank = device->bd_disk->private_data;
-       loff_t offset = (loff_t)sector << AXON_RAM_SECTOR_SHIFT;
 
-       *kaddr = (void *) bank->io_addr + offset;
-       *pfn = phys_to_pfn_t(bank->ph_addr + offset, PFN_DEV);
-       return bank->size - offset;
+       return __axon_ram_direct_access(bank, (sector * 512) / PAGE_SIZE,
+                       size / PAGE_SIZE, kaddr, pfn) * PAGE_SIZE;
 }
 
 static const struct block_device_operations axon_ram_devops = {
        .owner          = THIS_MODULE,
-       .direct_access  = axon_ram_direct_access
+       .direct_access  = axon_ram_blk_direct_access
+};
+
+static long
+axon_ram_dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
+                      void **kaddr, pfn_t *pfn)
+{
+       struct axon_ram_bank *bank = dax_get_private(dax_dev);
+
+       return __axon_ram_direct_access(bank, pgoff, nr_pages, kaddr, pfn);
+}
+
+static const struct dax_operations axon_ram_dax_ops = {
+       .direct_access = axon_ram_dax_direct_access,
 };
 
 /**
@@ -219,6 +243,7 @@ static int axon_ram_probe(struct platform_device *device)
                goto failed;
        }
 
+
        bank->disk->major = azfs_major;
        bank->disk->first_minor = azfs_minor;
        bank->disk->fops = &axon_ram_devops;
@@ -227,6 +252,13 @@ static int axon_ram_probe(struct platform_device *device)
        sprintf(bank->disk->disk_name, "%s%d",
                        AXON_RAM_DEVICE_NAME, axon_ram_bank_id);
 
+       bank->dax_dev = alloc_dax(bank, bank->disk->disk_name,
+                       &axon_ram_dax_ops);
+       if (!bank->dax_dev) {
+               rc = -ENOMEM;
+               goto failed;
+       }
+
        bank->disk->queue = blk_alloc_queue(GFP_KERNEL);
        if (bank->disk->queue == NULL) {
                dev_err(&device->dev, "Cannot register disk queue\n");
@@ -278,6 +310,8 @@ failed:
                                del_gendisk(bank->disk);
                        put_disk(bank->disk);
                }
+               kill_dax(bank->dax_dev);
+               put_dax(bank->dax_dev);
                device->dev.platform_data = NULL;
                if (bank->io_addr != 0)
                        iounmap((void __iomem *) bank->io_addr);
@@ -300,6 +334,8 @@ axon_ram_remove(struct platform_device *device)
 
        device_remove_file(&device->dev, &dev_attr_ecc);
        free_irq(bank->irq_id, device);
+       kill_dax(bank->dax_dev);
+       put_dax(bank->dax_dev);
        del_gendisk(bank->disk);
        put_disk(bank->disk);
        iounmap((void __iomem *) bank->io_addr);