Commit 40fd050890e08eb6d064aaf074cf3a8b75d1251e
1 parent
7ded959e4d
Exists in
v2017.01-smarct4x
and in
29 other branches
dm: sandbox: Add driver-model block-device support for sandbox
Update the host driver to support driver model for block devices. A future commit will remove the old code, but for now it is useful to be able to use it both with and without CONFIG_BLK. Signed-off-by: Simon Glass <sjg@chromium.org> Tested-by: Stephen Warren <swarren@nvidia.com>
Showing 3 changed files with 127 additions and 2 deletions Side-by-side Diff
cmd/host.c
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | */ |
6 | 6 | |
7 | 7 | #include <common.h> |
8 | +#include <dm.h> | |
8 | 9 | #include <fs.h> |
9 | 10 | #include <part.h> |
10 | 11 | #include <sandboxblockdev.h> |
... | ... | @@ -80,7 +81,13 @@ |
80 | 81 | |
81 | 82 | continue; |
82 | 83 | } |
83 | - struct host_block_dev *host_dev = blk_dev->priv; | |
84 | + struct host_block_dev *host_dev; | |
85 | + | |
86 | +#ifdef CONFIG_BLK | |
87 | + host_dev = dev_get_priv(blk_dev->bdev); | |
88 | +#else | |
89 | + host_dev = blk_dev->priv; | |
90 | +#endif | |
84 | 91 | printf("%12lu %s\n", (unsigned long)blk_dev->lba, |
85 | 92 | host_dev->filename); |
86 | 93 | } |
drivers/block/sandbox.c
... | ... | @@ -4,14 +4,20 @@ |
4 | 4 | * SPDX-License-Identifier: GPL-2.0+ |
5 | 5 | */ |
6 | 6 | |
7 | -#include <config.h> | |
8 | 7 | #include <common.h> |
8 | +#include <blk.h> | |
9 | +#include <dm.h> | |
10 | +#include <fdtdec.h> | |
9 | 11 | #include <part.h> |
10 | 12 | #include <os.h> |
11 | 13 | #include <malloc.h> |
12 | 14 | #include <sandboxblockdev.h> |
13 | 15 | #include <asm/errno.h> |
16 | +#include <dm/device-internal.h> | |
14 | 17 | |
18 | +DECLARE_GLOBAL_DATA_PTR; | |
19 | + | |
20 | +#ifndef CONFIG_BLK | |
15 | 21 | static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES]; |
16 | 22 | |
17 | 23 | static struct host_block_dev *find_host_device(int dev) |
18 | 24 | |
... | ... | @@ -21,7 +27,17 @@ |
21 | 27 | |
22 | 28 | return NULL; |
23 | 29 | } |
30 | +#endif | |
24 | 31 | |
32 | +#ifdef CONFIG_BLK | |
33 | +static unsigned long host_block_read(struct udevice *dev, | |
34 | + unsigned long start, lbaint_t blkcnt, | |
35 | + void *buffer) | |
36 | +{ | |
37 | + struct host_block_dev *host_dev = dev_get_priv(dev); | |
38 | + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); | |
39 | + | |
40 | +#else | |
25 | 41 | static unsigned long host_block_read(struct blk_desc *block_dev, |
26 | 42 | unsigned long start, lbaint_t blkcnt, |
27 | 43 | void *buffer) |
... | ... | @@ -31,6 +47,7 @@ |
31 | 47 | |
32 | 48 | if (!host_dev) |
33 | 49 | return -1; |
50 | +#endif | |
34 | 51 | |
35 | 52 | if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == |
36 | 53 | -1) { |
37 | 54 | |
... | ... | @@ -43,12 +60,21 @@ |
43 | 60 | return -1; |
44 | 61 | } |
45 | 62 | |
63 | +#ifdef CONFIG_BLK | |
64 | +static unsigned long host_block_write(struct udevice *dev, | |
65 | + unsigned long start, lbaint_t blkcnt, | |
66 | + const void *buffer) | |
67 | +{ | |
68 | + struct host_block_dev *host_dev = dev_get_priv(dev); | |
69 | + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); | |
70 | +#else | |
46 | 71 | static unsigned long host_block_write(struct blk_desc *block_dev, |
47 | 72 | unsigned long start, lbaint_t blkcnt, |
48 | 73 | const void *buffer) |
49 | 74 | { |
50 | 75 | int dev = block_dev->devnum; |
51 | 76 | struct host_block_dev *host_dev = find_host_device(dev); |
77 | +#endif | |
52 | 78 | |
53 | 79 | if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == |
54 | 80 | -1) { |
... | ... | @@ -61,6 +87,70 @@ |
61 | 87 | return -1; |
62 | 88 | } |
63 | 89 | |
90 | +#ifdef CONFIG_BLK | |
91 | +int host_dev_bind(int devnum, char *filename) | |
92 | +{ | |
93 | + struct host_block_dev *host_dev; | |
94 | + struct udevice *dev; | |
95 | + char dev_name[20], *str, *fname; | |
96 | + int ret, fd; | |
97 | + | |
98 | + /* Remove and unbind the old device, if any */ | |
99 | + ret = blk_get_device(IF_TYPE_HOST, devnum, &dev); | |
100 | + if (ret == 0) { | |
101 | + ret = device_remove(dev); | |
102 | + if (ret) | |
103 | + return ret; | |
104 | + ret = device_unbind(dev); | |
105 | + if (ret) | |
106 | + return ret; | |
107 | + } else if (ret != -ENODEV) { | |
108 | + return ret; | |
109 | + } | |
110 | + | |
111 | + if (!filename) | |
112 | + return 0; | |
113 | + | |
114 | + snprintf(dev_name, sizeof(dev_name), "host%d", devnum); | |
115 | + str = strdup(dev_name); | |
116 | + if (!str) | |
117 | + return -ENOMEM; | |
118 | + fname = strdup(filename); | |
119 | + if (!fname) { | |
120 | + free(str); | |
121 | + return -ENOMEM; | |
122 | + } | |
123 | + | |
124 | + fd = os_open(filename, OS_O_RDWR); | |
125 | + if (fd == -1) { | |
126 | + printf("Failed to access host backing file '%s'\n", filename); | |
127 | + ret = -ENOENT; | |
128 | + goto err; | |
129 | + } | |
130 | + ret = blk_create_device(gd->dm_root, "sandbox_host_blk", str, | |
131 | + IF_TYPE_HOST, devnum, 512, | |
132 | + os_lseek(fd, 0, OS_SEEK_END), &dev); | |
133 | + if (ret) | |
134 | + goto err_file; | |
135 | + ret = device_probe(dev); | |
136 | + if (ret) { | |
137 | + device_unbind(dev); | |
138 | + goto err_file; | |
139 | + } | |
140 | + | |
141 | + host_dev = dev_get_priv(dev); | |
142 | + host_dev->fd = fd; | |
143 | + host_dev->filename = fname; | |
144 | + | |
145 | + return blk_prepare_device(dev); | |
146 | +err_file: | |
147 | + os_close(fd); | |
148 | +err: | |
149 | + free(fname); | |
150 | + free(str); | |
151 | + return ret; | |
152 | +} | |
153 | +#else | |
64 | 154 | int host_dev_bind(int dev, char *filename) |
65 | 155 | { |
66 | 156 | struct host_block_dev *host_dev = find_host_device(dev); |
67 | 157 | |
... | ... | @@ -100,9 +190,19 @@ |
100 | 190 | |
101 | 191 | return 0; |
102 | 192 | } |
193 | +#endif | |
103 | 194 | |
104 | 195 | int host_get_dev_err(int devnum, struct blk_desc **blk_devp) |
105 | 196 | { |
197 | +#ifdef CONFIG_BLK | |
198 | + struct udevice *dev; | |
199 | + int ret; | |
200 | + | |
201 | + ret = blk_get_device(IF_TYPE_HOST, devnum, &dev); | |
202 | + if (ret) | |
203 | + return ret; | |
204 | + *blk_devp = dev_get_uclass_platdata(dev); | |
205 | +#else | |
106 | 206 | struct host_block_dev *host_dev = find_host_device(devnum); |
107 | 207 | |
108 | 208 | if (!host_dev) |
... | ... | @@ -112,6 +212,8 @@ |
112 | 212 | return -ENOENT; |
113 | 213 | |
114 | 214 | *blk_devp = &host_dev->blk_dev; |
215 | +#endif | |
216 | + | |
115 | 217 | return 0; |
116 | 218 | } |
117 | 219 | |
... | ... | @@ -124,4 +226,18 @@ |
124 | 226 | |
125 | 227 | return blk_dev; |
126 | 228 | } |
229 | + | |
230 | +#ifdef CONFIG_BLK | |
231 | +static const struct blk_ops sandbox_host_blk_ops = { | |
232 | + .read = host_block_read, | |
233 | + .write = host_block_write, | |
234 | +}; | |
235 | + | |
236 | +U_BOOT_DRIVER(sandbox_host_blk) = { | |
237 | + .name = "sandbox_host_blk", | |
238 | + .id = UCLASS_BLK, | |
239 | + .ops = &sandbox_host_blk_ops, | |
240 | + .priv_auto_alloc_size = sizeof(struct host_block_dev), | |
241 | +}; | |
242 | +#endif |