Commit 30afcb4bd2762fa4b87b17ada9500aa46dc10b1b

Authored by Jared Hulbert
Committed by Linus Torvalds
1 parent 423bad6004

return pfn from direct_access, for XIP

Alter the block device ->direct_access() API to work with the new
get_xip_mem() API (that requires both kaddr and pfn are returned).

Some architectures will not do the right thing in their virt_to_page() for use
by XIP (to translate from the kernel virtual address returned by
direct_access(), to a user mappable pfn in XIP's page fault handler.

However, we can't switch it to just return the pfn and not the kaddr, because
we have no good way to get a kva from a pfn, and XIP requires the kva for its
read(2) and write(2) handlers.  So we have to return both.

Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Carsten Otte <cotte@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: linux-mm@kvack.org
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 5 changed files with 27 additions and 18 deletions Side-by-side Diff

arch/powerpc/sysdev/axonram.c
... ... @@ -143,7 +143,7 @@
143 143 */
144 144 static int
145 145 axon_ram_direct_access(struct block_device *device, sector_t sector,
146   - unsigned long *data)
  146 + void **kaddr, unsigned long *pfn)
147 147 {
148 148 struct axon_ram_bank *bank = device->bd_disk->private_data;
149 149 loff_t offset;
... ... @@ -154,7 +154,8 @@
154 154 return -ERANGE;
155 155 }
156 156  
157   - *data = bank->ph_addr + offset;
  157 + *kaddr = (void *)(bank->ph_addr + offset);
  158 + *pfn = virt_to_phys(kaddr) >> PAGE_SHIFT;
158 159  
159 160 return 0;
160 161 }
... ... @@ -319,7 +319,7 @@
319 319  
320 320 #ifdef CONFIG_BLK_DEV_XIP
321 321 static int brd_direct_access (struct block_device *bdev, sector_t sector,
322   - unsigned long *data)
  322 + void **kaddr, unsigned long *pfn)
323 323 {
324 324 struct brd_device *brd = bdev->bd_disk->private_data;
325 325 struct page *page;
... ... @@ -333,7 +333,8 @@
333 333 page = brd_insert_page(brd, sector);
334 334 if (!page)
335 335 return -ENOMEM;
336   - *data = (unsigned long)page_address(page);
  336 + *kaddr = page_address(page);
  337 + *pfn = page_to_pfn(page);
337 338  
338 339 return 0;
339 340 }
drivers/s390/block/dcssblk.c
... ... @@ -36,7 +36,7 @@
36 36 static int dcssblk_release(struct inode *inode, struct file *filp);
37 37 static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
38 38 static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
39   - unsigned long *data);
  39 + void **kaddr, unsigned long *pfn);
40 40  
41 41 static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
42 42  
... ... @@ -636,7 +636,7 @@
636 636  
637 637 static int
638 638 dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
639   - unsigned long *data)
  639 + void **kaddr, unsigned long *pfn)
640 640 {
641 641 struct dcssblk_dev_info *dev_info;
642 642 unsigned long pgoff;
... ... @@ -649,7 +649,9 @@
649 649 pgoff = secnum / (PAGE_SIZE / 512);
650 650 if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
651 651 return -ERANGE;
652   - *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
  652 + *kaddr = (void *) (dev_info->start+pgoff*PAGE_SIZE);
  653 + *pfn = virt_to_phys(*kaddr) >> PAGE_SHIFT;
  654 +
653 655 return 0;
654 656 }
655 657  
... ... @@ -16,11 +16,13 @@
16 16  
17 17 static inline int
18 18 __inode_direct_access(struct inode *inode, sector_t sector,
19   - unsigned long *data)
  19 + void **kaddr, unsigned long *pfn)
20 20 {
21   - BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
22   - return inode->i_sb->s_bdev->bd_disk->fops
23   - ->direct_access(inode->i_sb->s_bdev,sector,data);
  21 + struct block_device *bdev = inode->i_sb->s_bdev;
  22 + struct block_device_operations *ops = bdev->bd_disk->fops;
  23 +
  24 + BUG_ON(!ops->direct_access);
  25 + return ops->direct_access(bdev, sector, kaddr, pfn);
24 26 }
25 27  
26 28 static inline int
27 29  
28 30  
... ... @@ -48,12 +50,13 @@
48 50 ext2_clear_xip_target(struct inode *inode, int block)
49 51 {
50 52 sector_t sector = block * (PAGE_SIZE/512);
51   - unsigned long data;
  53 + void *kaddr;
  54 + unsigned long pfn;
52 55 int rc;
53 56  
54   - rc = __inode_direct_access(inode, sector, &data);
  57 + rc = __inode_direct_access(inode, sector, &kaddr, &pfn);
55 58 if (!rc)
56   - clear_page((void*)data);
  59 + clear_page(kaddr);
57 60 return rc;
58 61 }
59 62  
... ... @@ -74,7 +77,8 @@
74 77 int create)
75 78 {
76 79 int rc;
77   - unsigned long data;
  80 + void *kaddr;
  81 + unsigned long pfn;
78 82 sector_t sector;
79 83  
80 84 /* first, retrieve the sector number */
81 85  
... ... @@ -84,9 +88,9 @@
84 88  
85 89 /* retrieve address of the target data */
86 90 rc = __inode_direct_access
87   - (mapping->host, sector * (PAGE_SIZE/512), &data);
  91 + (mapping->host, sector * (PAGE_SIZE/512), &kaddr, &pfn);
88 92 if (!rc)
89   - return virt_to_page(data);
  93 + return pfn_to_page(pfn);
90 94  
91 95 error:
92 96 return ERR_PTR(rc);
... ... @@ -1178,7 +1178,8 @@
1178 1178 int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
1179 1179 long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
1180 1180 long (*compat_ioctl) (struct file *, unsigned, unsigned long);
1181   - int (*direct_access) (struct block_device *, sector_t, unsigned long *);
  1181 + int (*direct_access) (struct block_device *, sector_t,
  1182 + void **, unsigned long *);
1182 1183 int (*media_changed) (struct gendisk *);
1183 1184 int (*revalidate_disk) (struct gendisk *);
1184 1185 int (*getgeo)(struct block_device *, struct hd_geometry *);