diff options
Diffstat (limited to 'drivers/fpga/fpga-mgr.c')
-rw-r--r-- | drivers/fpga/fpga-mgr.c | 319 |
1 files changed, 265 insertions, 54 deletions
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index 953dc9195937..86d2cb203533 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c | |||
@@ -25,85 +25,265 @@ | |||
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/scatterlist.h> | ||
29 | #include <linux/highmem.h> | ||
28 | 30 | ||
29 | static DEFINE_IDA(fpga_mgr_ida); | 31 | static DEFINE_IDA(fpga_mgr_ida); |
30 | static struct class *fpga_mgr_class; | 32 | static struct class *fpga_mgr_class; |
31 | 33 | ||
34 | /* | ||
35 | * Call the low level driver's write_init function. This will do the | ||
36 | * device-specific things to get the FPGA into the state where it is ready to | ||
37 | * receive an FPGA image. The low level driver only gets to see the first | ||
38 | * initial_header_size bytes in the buffer. | ||
39 | */ | ||
40 | static int fpga_mgr_write_init_buf(struct fpga_manager *mgr, | ||
41 | struct fpga_image_info *info, | ||
42 | const char *buf, size_t count) | ||
43 | { | ||
44 | int ret; | ||
45 | |||
46 | mgr->state = FPGA_MGR_STATE_WRITE_INIT; | ||
47 | if (!mgr->mops->initial_header_size) | ||
48 | ret = mgr->mops->write_init(mgr, info, NULL, 0); | ||
49 | else | ||
50 | ret = mgr->mops->write_init( | ||
51 | mgr, info, buf, min(mgr->mops->initial_header_size, count)); | ||
52 | |||
53 | if (ret) { | ||
54 | dev_err(&mgr->dev, "Error preparing FPGA for writing\n"); | ||
55 | mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR; | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static int fpga_mgr_write_init_sg(struct fpga_manager *mgr, | ||
63 | struct fpga_image_info *info, | ||
64 | struct sg_table *sgt) | ||
65 | { | ||
66 | struct sg_mapping_iter miter; | ||
67 | size_t len; | ||
68 | char *buf; | ||
69 | int ret; | ||
70 | |||
71 | if (!mgr->mops->initial_header_size) | ||
72 | return fpga_mgr_write_init_buf(mgr, info, NULL, 0); | ||
73 | |||
74 | /* | ||
75 | * First try to use miter to map the first fragment to access the | ||
76 | * header, this is the typical path. | ||
77 | */ | ||
78 | sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG); | ||
79 | if (sg_miter_next(&miter) && | ||
80 | miter.length >= mgr->mops->initial_header_size) { | ||
81 | ret = fpga_mgr_write_init_buf(mgr, info, miter.addr, | ||
82 | miter.length); | ||
83 | sg_miter_stop(&miter); | ||
84 | return ret; | ||
85 | } | ||
86 | sg_miter_stop(&miter); | ||
87 | |||
88 | /* Otherwise copy the fragments into temporary memory. */ | ||
89 | buf = kmalloc(mgr->mops->initial_header_size, GFP_KERNEL); | ||
90 | if (!buf) | ||
91 | return -ENOMEM; | ||
92 | |||
93 | len = sg_copy_to_buffer(sgt->sgl, sgt->nents, buf, | ||
94 | mgr->mops->initial_header_size); | ||
95 | ret = fpga_mgr_write_init_buf(mgr, info, buf, len); | ||
96 | |||
97 | kfree(buf); | ||
98 | |||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | /* | ||
103 | * After all the FPGA image has been written, do the device specific steps to | ||
104 | * finish and set the FPGA into operating mode. | ||
105 | */ | ||
106 | static int fpga_mgr_write_complete(struct fpga_manager *mgr, | ||
107 | struct fpga_image_info *info) | ||
108 | { | ||
109 | int ret; | ||
110 | |||
111 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE; | ||
112 | ret = mgr->mops->write_complete(mgr, info); | ||
113 | if (ret) { | ||
114 | dev_err(&mgr->dev, "Error after writing image data to FPGA\n"); | ||
115 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR; | ||
116 | return ret; | ||
117 | } | ||
118 | mgr->state = FPGA_MGR_STATE_OPERATING; | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
32 | /** | 123 | /** |
33 | * fpga_mgr_buf_load - load fpga from image in buffer | 124 | * fpga_mgr_buf_load_sg - load fpga from image in buffer from a scatter list |
34 | * @mgr: fpga manager | 125 | * @mgr: fpga manager |
35 | * @flags: flags setting fpga confuration modes | 126 | * @info: fpga image specific information |
36 | * @buf: buffer contain fpga image | 127 | * @sgt: scatterlist table |
37 | * @count: byte count of buf | ||
38 | * | 128 | * |
39 | * Step the low level fpga manager through the device-specific steps of getting | 129 | * Step the low level fpga manager through the device-specific steps of getting |
40 | * an FPGA ready to be configured, writing the image to it, then doing whatever | 130 | * an FPGA ready to be configured, writing the image to it, then doing whatever |
41 | * post-configuration steps necessary. This code assumes the caller got the | 131 | * post-configuration steps necessary. This code assumes the caller got the |
42 | * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code. | 132 | * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is |
133 | * not an error code. | ||
134 | * | ||
135 | * This is the preferred entry point for FPGA programming, it does not require | ||
136 | * any contiguous kernel memory. | ||
43 | * | 137 | * |
44 | * Return: 0 on success, negative error code otherwise. | 138 | * Return: 0 on success, negative error code otherwise. |
45 | */ | 139 | */ |
46 | int fpga_mgr_buf_load(struct fpga_manager *mgr, u32 flags, const char *buf, | 140 | int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info, |
47 | size_t count) | 141 | struct sg_table *sgt) |
48 | { | 142 | { |
49 | struct device *dev = &mgr->dev; | ||
50 | int ret; | 143 | int ret; |
51 | 144 | ||
52 | /* | 145 | ret = fpga_mgr_write_init_sg(mgr, info, sgt); |
53 | * Call the low level driver's write_init function. This will do the | 146 | if (ret) |
54 | * device-specific things to get the FPGA into the state where it is | 147 | return ret; |
55 | * ready to receive an FPGA image. | 148 | |
56 | */ | 149 | /* Write the FPGA image to the FPGA. */ |
57 | mgr->state = FPGA_MGR_STATE_WRITE_INIT; | 150 | mgr->state = FPGA_MGR_STATE_WRITE; |
58 | ret = mgr->mops->write_init(mgr, flags, buf, count); | 151 | if (mgr->mops->write_sg) { |
152 | ret = mgr->mops->write_sg(mgr, sgt); | ||
153 | } else { | ||
154 | struct sg_mapping_iter miter; | ||
155 | |||
156 | sg_miter_start(&miter, sgt->sgl, sgt->nents, SG_MITER_FROM_SG); | ||
157 | while (sg_miter_next(&miter)) { | ||
158 | ret = mgr->mops->write(mgr, miter.addr, miter.length); | ||
159 | if (ret) | ||
160 | break; | ||
161 | } | ||
162 | sg_miter_stop(&miter); | ||
163 | } | ||
164 | |||
59 | if (ret) { | 165 | if (ret) { |
60 | dev_err(dev, "Error preparing FPGA for writing\n"); | 166 | dev_err(&mgr->dev, "Error while writing image data to FPGA\n"); |
61 | mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR; | 167 | mgr->state = FPGA_MGR_STATE_WRITE_ERR; |
62 | return ret; | 168 | return ret; |
63 | } | 169 | } |
64 | 170 | ||
171 | return fpga_mgr_write_complete(mgr, info); | ||
172 | } | ||
173 | EXPORT_SYMBOL_GPL(fpga_mgr_buf_load_sg); | ||
174 | |||
175 | static int fpga_mgr_buf_load_mapped(struct fpga_manager *mgr, | ||
176 | struct fpga_image_info *info, | ||
177 | const char *buf, size_t count) | ||
178 | { | ||
179 | int ret; | ||
180 | |||
181 | ret = fpga_mgr_write_init_buf(mgr, info, buf, count); | ||
182 | if (ret) | ||
183 | return ret; | ||
184 | |||
65 | /* | 185 | /* |
66 | * Write the FPGA image to the FPGA. | 186 | * Write the FPGA image to the FPGA. |
67 | */ | 187 | */ |
68 | mgr->state = FPGA_MGR_STATE_WRITE; | 188 | mgr->state = FPGA_MGR_STATE_WRITE; |
69 | ret = mgr->mops->write(mgr, buf, count); | 189 | ret = mgr->mops->write(mgr, buf, count); |
70 | if (ret) { | 190 | if (ret) { |
71 | dev_err(dev, "Error while writing image data to FPGA\n"); | 191 | dev_err(&mgr->dev, "Error while writing image data to FPGA\n"); |
72 | mgr->state = FPGA_MGR_STATE_WRITE_ERR; | 192 | mgr->state = FPGA_MGR_STATE_WRITE_ERR; |
73 | return ret; | 193 | return ret; |
74 | } | 194 | } |
75 | 195 | ||
196 | return fpga_mgr_write_complete(mgr, info); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * fpga_mgr_buf_load - load fpga from image in buffer | ||
201 | * @mgr: fpga manager | ||
202 | * @flags: flags setting fpga confuration modes | ||
203 | * @buf: buffer contain fpga image | ||
204 | * @count: byte count of buf | ||
205 | * | ||
206 | * Step the low level fpga manager through the device-specific steps of getting | ||
207 | * an FPGA ready to be configured, writing the image to it, then doing whatever | ||
208 | * post-configuration steps necessary. This code assumes the caller got the | ||
209 | * mgr pointer from of_fpga_mgr_get() and checked that it is not an error code. | ||
210 | * | ||
211 | * Return: 0 on success, negative error code otherwise. | ||
212 | */ | ||
213 | int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, | ||
214 | const char *buf, size_t count) | ||
215 | { | ||
216 | struct page **pages; | ||
217 | struct sg_table sgt; | ||
218 | const void *p; | ||
219 | int nr_pages; | ||
220 | int index; | ||
221 | int rc; | ||
222 | |||
76 | /* | 223 | /* |
77 | * After all the FPGA image has been written, do the device specific | 224 | * This is just a fast path if the caller has already created a |
78 | * steps to finish and set the FPGA into operating mode. | 225 | * contiguous kernel buffer and the driver doesn't require SG, non-SG |
226 | * drivers will still work on the slow path. | ||
79 | */ | 227 | */ |
80 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE; | 228 | if (mgr->mops->write) |
81 | ret = mgr->mops->write_complete(mgr, flags); | 229 | return fpga_mgr_buf_load_mapped(mgr, info, buf, count); |
82 | if (ret) { | 230 | |
83 | dev_err(dev, "Error after writing image data to FPGA\n"); | 231 | /* |
84 | mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR; | 232 | * Convert the linear kernel pointer into a sg_table of pages for use |
85 | return ret; | 233 | * by the driver. |
234 | */ | ||
235 | nr_pages = DIV_ROUND_UP((unsigned long)buf + count, PAGE_SIZE) - | ||
236 | (unsigned long)buf / PAGE_SIZE; | ||
237 | pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL); | ||
238 | if (!pages) | ||
239 | return -ENOMEM; | ||
240 | |||
241 | p = buf - offset_in_page(buf); | ||
242 | for (index = 0; index < nr_pages; index++) { | ||
243 | if (is_vmalloc_addr(p)) | ||
244 | pages[index] = vmalloc_to_page(p); | ||
245 | else | ||
246 | pages[index] = kmap_to_page((void *)p); | ||
247 | if (!pages[index]) { | ||
248 | kfree(pages); | ||
249 | return -EFAULT; | ||
250 | } | ||
251 | p += PAGE_SIZE; | ||
86 | } | 252 | } |
87 | mgr->state = FPGA_MGR_STATE_OPERATING; | ||
88 | 253 | ||
89 | return 0; | 254 | /* |
255 | * The temporary pages list is used to code share the merging algorithm | ||
256 | * in sg_alloc_table_from_pages | ||
257 | */ | ||
258 | rc = sg_alloc_table_from_pages(&sgt, pages, index, offset_in_page(buf), | ||
259 | count, GFP_KERNEL); | ||
260 | kfree(pages); | ||
261 | if (rc) | ||
262 | return rc; | ||
263 | |||
264 | rc = fpga_mgr_buf_load_sg(mgr, info, &sgt); | ||
265 | sg_free_table(&sgt); | ||
266 | |||
267 | return rc; | ||
90 | } | 268 | } |
91 | EXPORT_SYMBOL_GPL(fpga_mgr_buf_load); | 269 | EXPORT_SYMBOL_GPL(fpga_mgr_buf_load); |
92 | 270 | ||
93 | /** | 271 | /** |
94 | * fpga_mgr_firmware_load - request firmware and load to fpga | 272 | * fpga_mgr_firmware_load - request firmware and load to fpga |
95 | * @mgr: fpga manager | 273 | * @mgr: fpga manager |
96 | * @flags: flags setting fpga confuration modes | 274 | * @info: fpga image specific information |
97 | * @image_name: name of image file on the firmware search path | 275 | * @image_name: name of image file on the firmware search path |
98 | * | 276 | * |
99 | * Request an FPGA image using the firmware class, then write out to the FPGA. | 277 | * Request an FPGA image using the firmware class, then write out to the FPGA. |
100 | * Update the state before each step to provide info on what step failed if | 278 | * Update the state before each step to provide info on what step failed if |
101 | * there is a failure. This code assumes the caller got the mgr pointer | 279 | * there is a failure. This code assumes the caller got the mgr pointer |
102 | * from of_fpga_mgr_get() and checked that it is not an error code. | 280 | * from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is not an error |
281 | * code. | ||
103 | * | 282 | * |
104 | * Return: 0 on success, negative error code otherwise. | 283 | * Return: 0 on success, negative error code otherwise. |
105 | */ | 284 | */ |
106 | int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags, | 285 | int fpga_mgr_firmware_load(struct fpga_manager *mgr, |
286 | struct fpga_image_info *info, | ||
107 | const char *image_name) | 287 | const char *image_name) |
108 | { | 288 | { |
109 | struct device *dev = &mgr->dev; | 289 | struct device *dev = &mgr->dev; |
@@ -121,7 +301,7 @@ int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags, | |||
121 | return ret; | 301 | return ret; |
122 | } | 302 | } |
123 | 303 | ||
124 | ret = fpga_mgr_buf_load(mgr, flags, fw->data, fw->size); | 304 | ret = fpga_mgr_buf_load(mgr, info, fw->data, fw->size); |
125 | 305 | ||
126 | release_firmware(fw); | 306 | release_firmware(fw); |
127 | 307 | ||
@@ -181,30 +361,11 @@ static struct attribute *fpga_mgr_attrs[] = { | |||
181 | }; | 361 | }; |
182 | ATTRIBUTE_GROUPS(fpga_mgr); | 362 | ATTRIBUTE_GROUPS(fpga_mgr); |
183 | 363 | ||
184 | static int fpga_mgr_of_node_match(struct device *dev, const void *data) | 364 | struct fpga_manager *__fpga_mgr_get(struct device *dev) |
185 | { | ||
186 | return dev->of_node == data; | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * of_fpga_mgr_get - get an exclusive reference to a fpga mgr | ||
191 | * @node: device node | ||
192 | * | ||
193 | * Given a device node, get an exclusive reference to a fpga mgr. | ||
194 | * | ||
195 | * Return: fpga manager struct or IS_ERR() condition containing error code. | ||
196 | */ | ||
197 | struct fpga_manager *of_fpga_mgr_get(struct device_node *node) | ||
198 | { | 365 | { |
199 | struct fpga_manager *mgr; | 366 | struct fpga_manager *mgr; |
200 | struct device *dev; | ||
201 | int ret = -ENODEV; | 367 | int ret = -ENODEV; |
202 | 368 | ||
203 | dev = class_find_device(fpga_mgr_class, NULL, node, | ||
204 | fpga_mgr_of_node_match); | ||
205 | if (!dev) | ||
206 | return ERR_PTR(-ENODEV); | ||
207 | |||
208 | mgr = to_fpga_manager(dev); | 369 | mgr = to_fpga_manager(dev); |
209 | if (!mgr) | 370 | if (!mgr) |
210 | goto err_dev; | 371 | goto err_dev; |
@@ -226,6 +387,55 @@ err_dev: | |||
226 | put_device(dev); | 387 | put_device(dev); |
227 | return ERR_PTR(ret); | 388 | return ERR_PTR(ret); |
228 | } | 389 | } |
390 | |||
391 | static int fpga_mgr_dev_match(struct device *dev, const void *data) | ||
392 | { | ||
393 | return dev->parent == data; | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * fpga_mgr_get - get an exclusive reference to a fpga mgr | ||
398 | * @dev: parent device that fpga mgr was registered with | ||
399 | * | ||
400 | * Given a device, get an exclusive reference to a fpga mgr. | ||
401 | * | ||
402 | * Return: fpga manager struct or IS_ERR() condition containing error code. | ||
403 | */ | ||
404 | struct fpga_manager *fpga_mgr_get(struct device *dev) | ||
405 | { | ||
406 | struct device *mgr_dev = class_find_device(fpga_mgr_class, NULL, dev, | ||
407 | fpga_mgr_dev_match); | ||
408 | if (!mgr_dev) | ||
409 | return ERR_PTR(-ENODEV); | ||
410 | |||
411 | return __fpga_mgr_get(mgr_dev); | ||
412 | } | ||
413 | EXPORT_SYMBOL_GPL(fpga_mgr_get); | ||
414 | |||
415 | static int fpga_mgr_of_node_match(struct device *dev, const void *data) | ||
416 | { | ||
417 | return dev->of_node == data; | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * of_fpga_mgr_get - get an exclusive reference to a fpga mgr | ||
422 | * @node: device node | ||
423 | * | ||
424 | * Given a device node, get an exclusive reference to a fpga mgr. | ||
425 | * | ||
426 | * Return: fpga manager struct or IS_ERR() condition containing error code. | ||
427 | */ | ||
428 | struct fpga_manager *of_fpga_mgr_get(struct device_node *node) | ||
429 | { | ||
430 | struct device *dev; | ||
431 | |||
432 | dev = class_find_device(fpga_mgr_class, NULL, node, | ||
433 | fpga_mgr_of_node_match); | ||
434 | if (!dev) | ||
435 | return ERR_PTR(-ENODEV); | ||
436 | |||
437 | return __fpga_mgr_get(dev); | ||
438 | } | ||
229 | EXPORT_SYMBOL_GPL(of_fpga_mgr_get); | 439 | EXPORT_SYMBOL_GPL(of_fpga_mgr_get); |
230 | 440 | ||
231 | /** | 441 | /** |
@@ -256,8 +466,9 @@ int fpga_mgr_register(struct device *dev, const char *name, | |||
256 | struct fpga_manager *mgr; | 466 | struct fpga_manager *mgr; |
257 | int id, ret; | 467 | int id, ret; |
258 | 468 | ||
259 | if (!mops || !mops->write_init || !mops->write || | 469 | if (!mops || !mops->write_complete || !mops->state || |
260 | !mops->write_complete || !mops->state) { | 470 | !mops->write_init || (!mops->write && !mops->write_sg) || |
471 | (mops->write && mops->write_sg)) { | ||
261 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); | 472 | dev_err(dev, "Attempt to register without fpga_manager_ops\n"); |
262 | return -EINVAL; | 473 | return -EINVAL; |
263 | } | 474 | } |