aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2012-08-04 00:01:20 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-08-16 16:15:08 -0400
commit1244691c73b250be522e77ac1a00ad53b601b4c4 (patch)
tree84547800970274ed513d60cec3751e17e8c080f3 /drivers/base/firmware_class.c
parent99c2aa72306079976369aad7fc62cc71931d692a (diff)
firmware loader: introduce firmware_buf
This patch introduces struct firmware_buf to describe the buffer which holds the firmware data, which will make the following cache_firmware/uncache_firmware implemented easily. Signed-off-by: Ming Lei <ming.lei@canonical.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r--drivers/base/firmware_class.c180
1 files changed, 102 insertions, 78 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 04c75b56f4fc..5f2076e5d5b1 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -89,7 +89,7 @@ static inline long firmware_loading_timeout(void)
89 * guarding for corner cases a global lock should be OK */ 89 * guarding for corner cases a global lock should be OK */
90static DEFINE_MUTEX(fw_lock); 90static DEFINE_MUTEX(fw_lock);
91 91
92struct firmware_priv { 92struct firmware_buf {
93 struct completion completion; 93 struct completion completion;
94 struct firmware *fw; 94 struct firmware *fw;
95 unsigned long status; 95 unsigned long status;
@@ -98,10 +98,14 @@ struct firmware_priv {
98 struct page **pages; 98 struct page **pages;
99 int nr_pages; 99 int nr_pages;
100 int page_array_size; 100 int page_array_size;
101 char fw_id[];
102};
103
104struct firmware_priv {
101 struct timer_list timeout; 105 struct timer_list timeout;
102 struct device dev;
103 bool nowait; 106 bool nowait;
104 char fw_id[]; 107 struct device dev;
108 struct firmware_buf *buf;
105}; 109};
106 110
107static struct firmware_priv *to_firmware_priv(struct device *dev) 111static struct firmware_priv *to_firmware_priv(struct device *dev)
@@ -111,8 +115,10 @@ static struct firmware_priv *to_firmware_priv(struct device *dev)
111 115
112static void fw_load_abort(struct firmware_priv *fw_priv) 116static void fw_load_abort(struct firmware_priv *fw_priv)
113{ 117{
114 set_bit(FW_STATUS_ABORT, &fw_priv->status); 118 struct firmware_buf *buf = fw_priv->buf;
115 complete(&fw_priv->completion); 119
120 set_bit(FW_STATUS_ABORT, &buf->status);
121 complete(&buf->completion);
116} 122}
117 123
118static ssize_t firmware_timeout_show(struct class *class, 124static ssize_t firmware_timeout_show(struct class *class,
@@ -152,15 +158,21 @@ static struct class_attribute firmware_class_attrs[] = {
152 __ATTR_NULL 158 __ATTR_NULL
153}; 159};
154 160
155static void fw_dev_release(struct device *dev) 161static void fw_free_buf(struct firmware_buf *buf)
156{ 162{
157 struct firmware_priv *fw_priv = to_firmware_priv(dev);
158 int i; 163 int i;
159 164
160 /* free untransfered pages buffer */ 165 if (!buf)
161 for (i = 0; i < fw_priv->nr_pages; i++) 166 return;
162 __free_page(fw_priv->pages[i]); 167
163 kfree(fw_priv->pages); 168 for (i = 0; i < buf->nr_pages; i++)
169 __free_page(buf->pages[i]);
170 kfree(buf->pages);
171}
172
173static void fw_dev_release(struct device *dev)
174{
175 struct firmware_priv *fw_priv = to_firmware_priv(dev);
164 176
165 kfree(fw_priv); 177 kfree(fw_priv);
166 178
@@ -171,7 +183,7 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env)
171{ 183{
172 struct firmware_priv *fw_priv = to_firmware_priv(dev); 184 struct firmware_priv *fw_priv = to_firmware_priv(dev);
173 185
174 if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->fw_id)) 186 if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id))
175 return -ENOMEM; 187 return -ENOMEM;
176 if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) 188 if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout))
177 return -ENOMEM; 189 return -ENOMEM;
@@ -192,7 +204,7 @@ static ssize_t firmware_loading_show(struct device *dev,
192 struct device_attribute *attr, char *buf) 204 struct device_attribute *attr, char *buf)
193{ 205{
194 struct firmware_priv *fw_priv = to_firmware_priv(dev); 206 struct firmware_priv *fw_priv = to_firmware_priv(dev);
195 int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); 207 int loading = test_bit(FW_STATUS_LOADING, &fw_priv->buf->status);
196 208
197 return sprintf(buf, "%d\n", loading); 209 return sprintf(buf, "%d\n", loading);
198} 210}
@@ -231,32 +243,33 @@ static ssize_t firmware_loading_store(struct device *dev,
231 const char *buf, size_t count) 243 const char *buf, size_t count)
232{ 244{
233 struct firmware_priv *fw_priv = to_firmware_priv(dev); 245 struct firmware_priv *fw_priv = to_firmware_priv(dev);
246 struct firmware_buf *fw_buf = fw_priv->buf;
234 int loading = simple_strtol(buf, NULL, 10); 247 int loading = simple_strtol(buf, NULL, 10);
235 int i; 248 int i;
236 249
237 mutex_lock(&fw_lock); 250 mutex_lock(&fw_lock);
238 251
239 if (!fw_priv->fw) 252 if (!fw_buf)
240 goto out; 253 goto out;
241 254
242 switch (loading) { 255 switch (loading) {
243 case 1: 256 case 1:
244 /* discarding any previous partial load */ 257 /* discarding any previous partial load */
245 if (!test_bit(FW_STATUS_DONE, &fw_priv->status)) { 258 if (!test_bit(FW_STATUS_DONE, &fw_buf->status)) {
246 for (i = 0; i < fw_priv->nr_pages; i++) 259 for (i = 0; i < fw_buf->nr_pages; i++)
247 __free_page(fw_priv->pages[i]); 260 __free_page(fw_buf->pages[i]);
248 kfree(fw_priv->pages); 261 kfree(fw_buf->pages);
249 fw_priv->pages = NULL; 262 fw_buf->pages = NULL;
250 fw_priv->page_array_size = 0; 263 fw_buf->page_array_size = 0;
251 fw_priv->nr_pages = 0; 264 fw_buf->nr_pages = 0;
252 set_bit(FW_STATUS_LOADING, &fw_priv->status); 265 set_bit(FW_STATUS_LOADING, &fw_buf->status);
253 } 266 }
254 break; 267 break;
255 case 0: 268 case 0:
256 if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { 269 if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
257 set_bit(FW_STATUS_DONE, &fw_priv->status); 270 set_bit(FW_STATUS_DONE, &fw_buf->status);
258 clear_bit(FW_STATUS_LOADING, &fw_priv->status); 271 clear_bit(FW_STATUS_LOADING, &fw_buf->status);
259 complete(&fw_priv->completion); 272 complete(&fw_buf->completion);
260 break; 273 break;
261 } 274 }
262 /* fallthrough */ 275 /* fallthrough */
@@ -280,21 +293,21 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj,
280{ 293{
281 struct device *dev = kobj_to_dev(kobj); 294 struct device *dev = kobj_to_dev(kobj);
282 struct firmware_priv *fw_priv = to_firmware_priv(dev); 295 struct firmware_priv *fw_priv = to_firmware_priv(dev);
283 struct firmware *fw; 296 struct firmware_buf *buf;
284 ssize_t ret_count; 297 ssize_t ret_count;
285 298
286 mutex_lock(&fw_lock); 299 mutex_lock(&fw_lock);
287 fw = fw_priv->fw; 300 buf = fw_priv->buf;
288 if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { 301 if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) {
289 ret_count = -ENODEV; 302 ret_count = -ENODEV;
290 goto out; 303 goto out;
291 } 304 }
292 if (offset > fw_priv->size) { 305 if (offset > buf->size) {
293 ret_count = 0; 306 ret_count = 0;
294 goto out; 307 goto out;
295 } 308 }
296 if (count > fw_priv->size - offset) 309 if (count > buf->size - offset)
297 count = fw_priv->size - offset; 310 count = buf->size - offset;
298 311
299 ret_count = count; 312 ret_count = count;
300 313
@@ -304,11 +317,11 @@ static ssize_t firmware_data_read(struct file *filp, struct kobject *kobj,
304 int page_ofs = offset & (PAGE_SIZE-1); 317 int page_ofs = offset & (PAGE_SIZE-1);
305 int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); 318 int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
306 319
307 page_data = kmap(fw_priv->pages[page_nr]); 320 page_data = kmap(buf->pages[page_nr]);
308 321
309 memcpy(buffer, page_data + page_ofs, page_cnt); 322 memcpy(buffer, page_data + page_ofs, page_cnt);
310 323
311 kunmap(fw_priv->pages[page_nr]); 324 kunmap(buf->pages[page_nr]);
312 buffer += page_cnt; 325 buffer += page_cnt;
313 offset += page_cnt; 326 offset += page_cnt;
314 count -= page_cnt; 327 count -= page_cnt;
@@ -320,12 +333,13 @@ out:
320 333
321static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) 334static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
322{ 335{
336 struct firmware_buf *buf = fw_priv->buf;
323 int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT; 337 int pages_needed = ALIGN(min_size, PAGE_SIZE) >> PAGE_SHIFT;
324 338
325 /* If the array of pages is too small, grow it... */ 339 /* If the array of pages is too small, grow it... */
326 if (fw_priv->page_array_size < pages_needed) { 340 if (buf->page_array_size < pages_needed) {
327 int new_array_size = max(pages_needed, 341 int new_array_size = max(pages_needed,
328 fw_priv->page_array_size * 2); 342 buf->page_array_size * 2);
329 struct page **new_pages; 343 struct page **new_pages;
330 344
331 new_pages = kmalloc(new_array_size * sizeof(void *), 345 new_pages = kmalloc(new_array_size * sizeof(void *),
@@ -334,24 +348,24 @@ static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
334 fw_load_abort(fw_priv); 348 fw_load_abort(fw_priv);
335 return -ENOMEM; 349 return -ENOMEM;
336 } 350 }
337 memcpy(new_pages, fw_priv->pages, 351 memcpy(new_pages, buf->pages,
338 fw_priv->page_array_size * sizeof(void *)); 352 buf->page_array_size * sizeof(void *));
339 memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) * 353 memset(&new_pages[buf->page_array_size], 0, sizeof(void *) *
340 (new_array_size - fw_priv->page_array_size)); 354 (new_array_size - buf->page_array_size));
341 kfree(fw_priv->pages); 355 kfree(buf->pages);
342 fw_priv->pages = new_pages; 356 buf->pages = new_pages;
343 fw_priv->page_array_size = new_array_size; 357 buf->page_array_size = new_array_size;
344 } 358 }
345 359
346 while (fw_priv->nr_pages < pages_needed) { 360 while (buf->nr_pages < pages_needed) {
347 fw_priv->pages[fw_priv->nr_pages] = 361 buf->pages[buf->nr_pages] =
348 alloc_page(GFP_KERNEL | __GFP_HIGHMEM); 362 alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
349 363
350 if (!fw_priv->pages[fw_priv->nr_pages]) { 364 if (!buf->pages[buf->nr_pages]) {
351 fw_load_abort(fw_priv); 365 fw_load_abort(fw_priv);
352 return -ENOMEM; 366 return -ENOMEM;
353 } 367 }
354 fw_priv->nr_pages++; 368 buf->nr_pages++;
355 } 369 }
356 return 0; 370 return 0;
357} 371}
@@ -374,15 +388,15 @@ static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj,
374{ 388{
375 struct device *dev = kobj_to_dev(kobj); 389 struct device *dev = kobj_to_dev(kobj);
376 struct firmware_priv *fw_priv = to_firmware_priv(dev); 390 struct firmware_priv *fw_priv = to_firmware_priv(dev);
377 struct firmware *fw; 391 struct firmware_buf *buf;
378 ssize_t retval; 392 ssize_t retval;
379 393
380 if (!capable(CAP_SYS_RAWIO)) 394 if (!capable(CAP_SYS_RAWIO))
381 return -EPERM; 395 return -EPERM;
382 396
383 mutex_lock(&fw_lock); 397 mutex_lock(&fw_lock);
384 fw = fw_priv->fw; 398 buf = fw_priv->buf;
385 if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { 399 if (!buf || test_bit(FW_STATUS_DONE, &buf->status)) {
386 retval = -ENODEV; 400 retval = -ENODEV;
387 goto out; 401 goto out;
388 } 402 }
@@ -399,17 +413,17 @@ static ssize_t firmware_data_write(struct file *filp, struct kobject *kobj,
399 int page_ofs = offset & (PAGE_SIZE - 1); 413 int page_ofs = offset & (PAGE_SIZE - 1);
400 int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count); 414 int page_cnt = min_t(size_t, PAGE_SIZE - page_ofs, count);
401 415
402 page_data = kmap(fw_priv->pages[page_nr]); 416 page_data = kmap(buf->pages[page_nr]);
403 417
404 memcpy(page_data + page_ofs, buffer, page_cnt); 418 memcpy(page_data + page_ofs, buffer, page_cnt);
405 419
406 kunmap(fw_priv->pages[page_nr]); 420 kunmap(buf->pages[page_nr]);
407 buffer += page_cnt; 421 buffer += page_cnt;
408 offset += page_cnt; 422 offset += page_cnt;
409 count -= page_cnt; 423 count -= page_cnt;
410 } 424 }
411 425
412 fw_priv->size = max_t(size_t, offset, fw_priv->size); 426 buf->size = max_t(size_t, offset, buf->size);
413out: 427out:
414 mutex_unlock(&fw_lock); 428 mutex_unlock(&fw_lock);
415 return retval; 429 return retval;
@@ -434,20 +448,31 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
434 struct device *device, bool uevent, bool nowait) 448 struct device *device, bool uevent, bool nowait)
435{ 449{
436 struct firmware_priv *fw_priv; 450 struct firmware_priv *fw_priv;
451 struct firmware_buf *buf;
437 struct device *f_dev; 452 struct device *f_dev;
438 453
439 fw_priv = kzalloc(sizeof(*fw_priv) + strlen(fw_name) + 1 , GFP_KERNEL); 454 fw_priv = kzalloc(sizeof(*fw_priv), GFP_KERNEL);
440 if (!fw_priv) { 455 if (!fw_priv) {
441 dev_err(device, "%s: kmalloc failed\n", __func__); 456 dev_err(device, "%s: kmalloc failed\n", __func__);
442 return ERR_PTR(-ENOMEM); 457 fw_priv = ERR_PTR(-ENOMEM);
458 goto exit;
459 }
460
461 buf = kzalloc(sizeof(*buf) + strlen(fw_name) + 1, GFP_KERNEL);
462 if (!buf) {
463 dev_err(device, "%s: kmalloc failed\n", __func__);
464 kfree(fw_priv);
465 fw_priv = ERR_PTR(-ENOMEM);
466 goto exit;
443 } 467 }
444 468
445 fw_priv->fw = firmware; 469 buf->fw = firmware;
470 fw_priv->buf = buf;
446 fw_priv->nowait = nowait; 471 fw_priv->nowait = nowait;
447 strcpy(fw_priv->fw_id, fw_name);
448 init_completion(&fw_priv->completion);
449 setup_timer(&fw_priv->timeout, 472 setup_timer(&fw_priv->timeout,
450 firmware_class_timeout, (u_long) fw_priv); 473 firmware_class_timeout, (u_long) fw_priv);
474 strcpy(buf->fw_id, fw_name);
475 init_completion(&buf->completion);
451 476
452 f_dev = &fw_priv->dev; 477 f_dev = &fw_priv->dev;
453 478
@@ -455,7 +480,7 @@ fw_create_instance(struct firmware *firmware, const char *fw_name,
455 dev_set_name(f_dev, "%s", fw_name); 480 dev_set_name(f_dev, "%s", fw_name);
456 f_dev->parent = device; 481 f_dev->parent = device;
457 f_dev->class = &firmware_class; 482 f_dev->class = &firmware_class;
458 483exit:
459 return fw_priv; 484 return fw_priv;
460} 485}
461 486
@@ -496,24 +521,18 @@ static void _request_firmware_cleanup(const struct firmware **firmware_p)
496} 521}
497 522
498/* transfer the ownership of pages to firmware */ 523/* transfer the ownership of pages to firmware */
499static int fw_set_page_data(struct firmware_priv *fw_priv) 524static int fw_set_page_data(struct firmware_buf *buf)
500{ 525{
501 struct firmware *fw = fw_priv->fw; 526 struct firmware *fw = buf->fw;
502 527
503 fw_priv->data = vmap(fw_priv->pages, fw_priv->nr_pages, 528 buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
504 0, PAGE_KERNEL_RO); 529 if (!buf->data)
505 if (!fw_priv->data)
506 return -ENOMEM; 530 return -ENOMEM;
507 531
508 fw->data = fw_priv->data; 532 fw->data = buf->data;
509 fw->pages = fw_priv->pages; 533 fw->pages = buf->pages;
510 fw->size = fw_priv->size; 534 fw->size = buf->size;
511 535 WARN_ON(PFN_UP(fw->size) != buf->nr_pages);
512 WARN_ON(PFN_UP(fw->size) != fw_priv->nr_pages);
513
514 fw_priv->nr_pages = 0;
515 fw_priv->pages = NULL;
516 fw_priv->data = NULL;
517 536
518 return 0; 537 return 0;
519} 538}
@@ -523,6 +542,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
523{ 542{
524 int retval = 0; 543 int retval = 0;
525 struct device *f_dev = &fw_priv->dev; 544 struct device *f_dev = &fw_priv->dev;
545 struct firmware_buf *buf = fw_priv->buf;
526 546
527 dev_set_uevent_suppress(f_dev, true); 547 dev_set_uevent_suppress(f_dev, true);
528 548
@@ -549,7 +569,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
549 569
550 if (uevent) { 570 if (uevent) {
551 dev_set_uevent_suppress(f_dev, false); 571 dev_set_uevent_suppress(f_dev, false);
552 dev_dbg(f_dev, "firmware: requesting %s\n", fw_priv->fw_id); 572 dev_dbg(f_dev, "firmware: requesting %s\n", buf->fw_id);
553 if (timeout != MAX_SCHEDULE_TIMEOUT) 573 if (timeout != MAX_SCHEDULE_TIMEOUT)
554 mod_timer(&fw_priv->timeout, 574 mod_timer(&fw_priv->timeout,
555 round_jiffies_up(jiffies + timeout)); 575 round_jiffies_up(jiffies + timeout));
@@ -557,18 +577,22 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
557 kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD); 577 kobject_uevent(&fw_priv->dev.kobj, KOBJ_ADD);
558 } 578 }
559 579
560 wait_for_completion(&fw_priv->completion); 580 wait_for_completion(&buf->completion);
561 581
562 del_timer_sync(&fw_priv->timeout); 582 del_timer_sync(&fw_priv->timeout);
563 583
564 mutex_lock(&fw_lock); 584 mutex_lock(&fw_lock);
565 if (!fw_priv->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) 585 if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
566 retval = -ENOENT; 586 retval = -ENOENT;
567 587
568 /* transfer pages ownership at the last minute */ 588 /* transfer pages ownership at the last minute */
569 if (!retval) 589 if (!retval)
570 retval = fw_set_page_data(fw_priv); 590 retval = fw_set_page_data(buf);
571 fw_priv->fw = NULL; 591 if (retval)
592 fw_free_buf(buf); /* free untransfered pages buffer */
593
594 kfree(buf);
595 fw_priv->buf = NULL;
572 mutex_unlock(&fw_lock); 596 mutex_unlock(&fw_lock);
573 597
574 device_remove_file(f_dev, &dev_attr_loading); 598 device_remove_file(f_dev, &dev_attr_loading);