aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2017-02-01 14:48:44 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-10 09:20:44 -0500
commitbaa6d396635129d8a67793e884f3b2182c7354b3 (patch)
treee836ac87b5a67011ef9f1c14d0443b4de8f9c309
parentb496df86ac1bbe393a55ddbfed35d46e74ef9767 (diff)
fpga: Add scatterlist based programming
Requiring contiguous kernel memory is not a good idea, this is a limited resource and allocation can fail under normal work loads. This introduces a .write_sg op that supporting drivers can provide to DMA directly from dis-contiguous memory and a new entry point fpga_mgr_buf_load_sg that users can call to directly provide page lists. The full matrix of compatibility is provided, either the linear or sg interface can be used by the user with a driver supporting either interface. A notable change for drivers is that the .write op can now be called multiple times. Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Acked-by: Alan Tull <atull@opensource.altera.com> Acked-by: Moritz Fischer <moritz.fischer@ettus.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/fpga/fpga-mgr.txt19
-rw-r--r--drivers/fpga/fpga-mgr.c236
-rw-r--r--include/linux/fpga/fpga-mgr.h5
3 files changed, 227 insertions, 33 deletions
diff --git a/Documentation/fpga/fpga-mgr.txt b/Documentation/fpga/fpga-mgr.txt
index 86ee5078fd03..78f197fadfd1 100644
--- a/Documentation/fpga/fpga-mgr.txt
+++ b/Documentation/fpga/fpga-mgr.txt
@@ -22,7 +22,16 @@ To program the FPGA from a file or from a buffer:
22 struct fpga_image_info *info, 22 struct fpga_image_info *info,
23 const char *buf, size_t count); 23 const char *buf, size_t count);
24 24
25Load the FPGA from an image which exists as a buffer in memory. 25Load the FPGA from an image which exists as a contiguous buffer in
26memory. Allocating contiguous kernel memory for the buffer should be avoided,
27users are encouraged to use the _sg interface instead of this.
28
29 int fpga_mgr_buf_load_sg(struct fpga_manager *mgr,
30 struct fpga_image_info *info,
31 struct sg_table *sgt);
32
33Load the FPGA from an image from non-contiguous in memory. Callers can
34construct a sg_table using alloc_page backed memory.
26 35
27 int fpga_mgr_firmware_load(struct fpga_manager *mgr, 36 int fpga_mgr_firmware_load(struct fpga_manager *mgr,
28 struct fpga_image_info *info, 37 struct fpga_image_info *info,
@@ -166,7 +175,7 @@ success or negative error codes otherwise.
166 175
167The programming sequence is: 176The programming sequence is:
168 1. .write_init 177 1. .write_init
169 2. .write (may be called once or multiple times) 178 2. .write or .write_sg (may be called once or multiple times)
170 3. .write_complete 179 3. .write_complete
171 180
172The .write_init function will prepare the FPGA to receive the image data. The 181The .write_init function will prepare the FPGA to receive the image data. The
@@ -176,7 +185,11 @@ buffer up at least this much before starting.
176 185
177The .write function writes a buffer to the FPGA. The buffer may be contain the 186The .write function writes a buffer to the FPGA. The buffer may be contain the
178whole FPGA image or may be a smaller chunk of an FPGA image. In the latter 187whole FPGA image or may be a smaller chunk of an FPGA image. In the latter
179case, this function is called multiple times for successive chunks. 188case, this function is called multiple times for successive chunks. This interface
189is suitable for drivers which use PIO.
190
191The .write_sg version behaves the same as .write except the input is a sg_table
192scatter list. This interface is suitable for drivers which use DMA.
180 193
181The .write_complete function is called after all the image has been written 194The .write_complete function is called after all the image has been written
182to put the FPGA into operating mode. 195to put the FPGA into operating mode.
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index f0a69d3e60a5..86d2cb203533 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -25,16 +25,106 @@
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
29static DEFINE_IDA(fpga_mgr_ida); 31static DEFINE_IDA(fpga_mgr_ida);
30static struct class *fpga_mgr_class; 32static 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 */
40static 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
62static 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 */
106static 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 * @info: fpga image specific information 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
@@ -42,54 +132,139 @@ static struct class *fpga_mgr_class;
42 * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is 132 * mgr pointer from of_fpga_mgr_get() or fpga_mgr_get() and checked that it is
43 * not an error code. 133 * not an error code.
44 * 134 *
135 * This is the preferred entry point for FPGA programming, it does not require
136 * any contiguous kernel memory.
137 *
45 * Return: 0 on success, negative error code otherwise. 138 * Return: 0 on success, negative error code otherwise.
46 */ 139 */
47int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, 140int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info,
48 const char *buf, size_t count) 141 struct sg_table *sgt)
49{ 142{
50 struct device *dev = &mgr->dev;
51 int ret; 143 int ret;
52 144
53 /* 145 ret = fpga_mgr_write_init_sg(mgr, info, sgt);
54 * Call the low level driver's write_init function. This will do the 146 if (ret)
55 * device-specific things to get the FPGA into the state where it is 147 return ret;
56 * ready to receive an FPGA image. The low level driver only gets to 148
57 * see the first initial_header_size bytes in the buffer. 149 /* Write the FPGA image to the FPGA. */
58 */ 150 mgr->state = FPGA_MGR_STATE_WRITE;
59 mgr->state = FPGA_MGR_STATE_WRITE_INIT; 151 if (mgr->mops->write_sg) {
60 ret = mgr->mops->write_init(mgr, info, buf, 152 ret = mgr->mops->write_sg(mgr, sgt);
61 min(mgr->mops->initial_header_size, count)); 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
62 if (ret) { 165 if (ret) {
63 dev_err(dev, "Error preparing FPGA for writing\n"); 166 dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
64 mgr->state = FPGA_MGR_STATE_WRITE_INIT_ERR; 167 mgr->state = FPGA_MGR_STATE_WRITE_ERR;
65 return ret; 168 return ret;
66 } 169 }
67 170
171 return fpga_mgr_write_complete(mgr, info);
172}
173EXPORT_SYMBOL_GPL(fpga_mgr_buf_load_sg);
174
175static 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
68 /* 185 /*
69 * Write the FPGA image to the FPGA. 186 * Write the FPGA image to the FPGA.
70 */ 187 */
71 mgr->state = FPGA_MGR_STATE_WRITE; 188 mgr->state = FPGA_MGR_STATE_WRITE;
72 ret = mgr->mops->write(mgr, buf, count); 189 ret = mgr->mops->write(mgr, buf, count);
73 if (ret) { 190 if (ret) {
74 dev_err(dev, "Error while writing image data to FPGA\n"); 191 dev_err(&mgr->dev, "Error while writing image data to FPGA\n");
75 mgr->state = FPGA_MGR_STATE_WRITE_ERR; 192 mgr->state = FPGA_MGR_STATE_WRITE_ERR;
76 return ret; 193 return ret;
77 } 194 }
78 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 */
213int 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
79 /* 223 /*
80 * 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
81 * 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.
82 */ 227 */
83 mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE; 228 if (mgr->mops->write)
84 ret = mgr->mops->write_complete(mgr, info); 229 return fpga_mgr_buf_load_mapped(mgr, info, buf, count);
85 if (ret) { 230
86 dev_err(dev, "Error after writing image data to FPGA\n"); 231 /*
87 mgr->state = FPGA_MGR_STATE_WRITE_COMPLETE_ERR; 232 * Convert the linear kernel pointer into a sg_table of pages for use
88 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;
89 } 252 }
90 mgr->state = FPGA_MGR_STATE_OPERATING;
91 253
92 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;
93} 268}
94EXPORT_SYMBOL_GPL(fpga_mgr_buf_load); 269EXPORT_SYMBOL_GPL(fpga_mgr_buf_load);
95 270
@@ -291,8 +466,9 @@ int fpga_mgr_register(struct device *dev, const char *name,
291 struct fpga_manager *mgr; 466 struct fpga_manager *mgr;
292 int id, ret; 467 int id, ret;
293 468
294 if (!mops || !mops->write_init || !mops->write || 469 if (!mops || !mops->write_complete || !mops->state ||
295 !mops->write_complete || !mops->state) { 470 !mops->write_init || (!mops->write && !mops->write_sg) ||
471 (mops->write && mops->write_sg)) {
296 dev_err(dev, "Attempt to register without fpga_manager_ops\n"); 472 dev_err(dev, "Attempt to register without fpga_manager_ops\n");
297 return -EINVAL; 473 return -EINVAL;
298 } 474 }
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 16551d5eac36..57beb5d09bfc 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -22,6 +22,7 @@
22#define _LINUX_FPGA_MGR_H 22#define _LINUX_FPGA_MGR_H
23 23
24struct fpga_manager; 24struct fpga_manager;
25struct sg_table;
25 26
26/** 27/**
27 * enum fpga_mgr_states - fpga framework states 28 * enum fpga_mgr_states - fpga framework states
@@ -88,6 +89,7 @@ struct fpga_image_info {
88 * @state: returns an enum value of the FPGA's state 89 * @state: returns an enum value of the FPGA's state
89 * @write_init: prepare the FPGA to receive confuration data 90 * @write_init: prepare the FPGA to receive confuration data
90 * @write: write count bytes of configuration data to the FPGA 91 * @write: write count bytes of configuration data to the FPGA
92 * @write_sg: write the scatter list of configuration data to the FPGA
91 * @write_complete: set FPGA to operating state after writing is done 93 * @write_complete: set FPGA to operating state after writing is done
92 * @fpga_remove: optional: Set FPGA into a specific state during driver remove 94 * @fpga_remove: optional: Set FPGA into a specific state during driver remove
93 * 95 *
@@ -102,6 +104,7 @@ struct fpga_manager_ops {
102 struct fpga_image_info *info, 104 struct fpga_image_info *info,
103 const char *buf, size_t count); 105 const char *buf, size_t count);
104 int (*write)(struct fpga_manager *mgr, const char *buf, size_t count); 106 int (*write)(struct fpga_manager *mgr, const char *buf, size_t count);
107 int (*write_sg)(struct fpga_manager *mgr, struct sg_table *sgt);
105 int (*write_complete)(struct fpga_manager *mgr, 108 int (*write_complete)(struct fpga_manager *mgr,
106 struct fpga_image_info *info); 109 struct fpga_image_info *info);
107 void (*fpga_remove)(struct fpga_manager *mgr); 110 void (*fpga_remove)(struct fpga_manager *mgr);
@@ -129,6 +132,8 @@ struct fpga_manager {
129 132
130int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info, 133int fpga_mgr_buf_load(struct fpga_manager *mgr, struct fpga_image_info *info,
131 const char *buf, size_t count); 134 const char *buf, size_t count);
135int fpga_mgr_buf_load_sg(struct fpga_manager *mgr, struct fpga_image_info *info,
136 struct sg_table *sgt);
132 137
133int fpga_mgr_firmware_load(struct fpga_manager *mgr, 138int fpga_mgr_firmware_load(struct fpga_manager *mgr,
134 struct fpga_image_info *info, 139 struct fpga_image_info *info,