Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.14-rc1 614 lines 15 kB view raw
1/* 2 * firmware_class.c - Multi purpose firmware loading support 3 * 4 * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org> 5 * 6 * Please see Documentation/firmware_class/ for more information. 7 * 8 */ 9 10#include <linux/device.h> 11#include <linux/module.h> 12#include <linux/init.h> 13#include <linux/timer.h> 14#include <linux/vmalloc.h> 15#include <linux/interrupt.h> 16#include <linux/bitops.h> 17#include <asm/semaphore.h> 18 19#include <linux/firmware.h> 20#include "base.h" 21 22MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>"); 23MODULE_DESCRIPTION("Multi purpose firmware loading support"); 24MODULE_LICENSE("GPL"); 25 26enum { 27 FW_STATUS_LOADING, 28 FW_STATUS_DONE, 29 FW_STATUS_ABORT, 30 FW_STATUS_READY, 31 FW_STATUS_READY_NOHOTPLUG, 32}; 33 34static int loading_timeout = 10; /* In seconds */ 35 36/* fw_lock could be moved to 'struct firmware_priv' but since it is just 37 * guarding for corner cases a global lock should be OK */ 38static DECLARE_MUTEX(fw_lock); 39 40struct firmware_priv { 41 char fw_id[FIRMWARE_NAME_MAX]; 42 struct completion completion; 43 struct bin_attribute attr_data; 44 struct firmware *fw; 45 unsigned long status; 46 int alloc_size; 47 struct timer_list timeout; 48}; 49 50static inline void 51fw_load_abort(struct firmware_priv *fw_priv) 52{ 53 set_bit(FW_STATUS_ABORT, &fw_priv->status); 54 wmb(); 55 complete(&fw_priv->completion); 56} 57 58static ssize_t 59firmware_timeout_show(struct class *class, char *buf) 60{ 61 return sprintf(buf, "%d\n", loading_timeout); 62} 63 64/** 65 * firmware_timeout_store: 66 * Description: 67 * Sets the number of seconds to wait for the firmware. Once 68 * this expires an error will be return to the driver and no 69 * firmware will be provided. 70 * 71 * Note: zero means 'wait for ever' 72 * 73 **/ 74static ssize_t 75firmware_timeout_store(struct class *class, const char *buf, size_t count) 76{ 77 loading_timeout = simple_strtol(buf, NULL, 10); 78 if (loading_timeout < 0) 79 loading_timeout = 0; 80 return count; 81} 82 83static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); 84 85static void fw_class_dev_release(struct class_device *class_dev); 86int firmware_class_hotplug(struct class_device *dev, char **envp, 87 int num_envp, char *buffer, int buffer_size); 88 89static struct class firmware_class = { 90 .name = "firmware", 91 .hotplug = firmware_class_hotplug, 92 .release = fw_class_dev_release, 93}; 94 95int 96firmware_class_hotplug(struct class_device *class_dev, char **envp, 97 int num_envp, char *buffer, int buffer_size) 98{ 99 struct firmware_priv *fw_priv = class_get_devdata(class_dev); 100 int i = 0, len = 0; 101 102 if (!test_bit(FW_STATUS_READY, &fw_priv->status)) 103 return -ENODEV; 104 105 if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, 106 "FIRMWARE=%s", fw_priv->fw_id)) 107 return -ENOMEM; 108 if (add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &len, 109 "TIMEOUT=%i", loading_timeout)) 110 return -ENOMEM; 111 112 envp[i] = NULL; 113 114 return 0; 115} 116 117static ssize_t 118firmware_loading_show(struct class_device *class_dev, char *buf) 119{ 120 struct firmware_priv *fw_priv = class_get_devdata(class_dev); 121 int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); 122 return sprintf(buf, "%d\n", loading); 123} 124 125/** 126 * firmware_loading_store: - loading control file 127 * Description: 128 * The relevant values are: 129 * 130 * 1: Start a load, discarding any previous partial load. 131 * 0: Conclude the load and handle the data to the driver code. 132 * -1: Conclude the load with an error and discard any written data. 133 **/ 134static ssize_t 135firmware_loading_store(struct class_device *class_dev, 136 const char *buf, size_t count) 137{ 138 struct firmware_priv *fw_priv = class_get_devdata(class_dev); 139 int loading = simple_strtol(buf, NULL, 10); 140 141 switch (loading) { 142 case 1: 143 down(&fw_lock); 144 if (!fw_priv->fw) { 145 up(&fw_lock); 146 break; 147 } 148 vfree(fw_priv->fw->data); 149 fw_priv->fw->data = NULL; 150 fw_priv->fw->size = 0; 151 fw_priv->alloc_size = 0; 152 set_bit(FW_STATUS_LOADING, &fw_priv->status); 153 up(&fw_lock); 154 break; 155 case 0: 156 if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { 157 complete(&fw_priv->completion); 158 clear_bit(FW_STATUS_LOADING, &fw_priv->status); 159 break; 160 } 161 /* fallthrough */ 162 default: 163 printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__, 164 loading); 165 /* fallthrough */ 166 case -1: 167 fw_load_abort(fw_priv); 168 break; 169 } 170 171 return count; 172} 173 174static CLASS_DEVICE_ATTR(loading, 0644, 175 firmware_loading_show, firmware_loading_store); 176 177static ssize_t 178firmware_data_read(struct kobject *kobj, 179 char *buffer, loff_t offset, size_t count) 180{ 181 struct class_device *class_dev = to_class_dev(kobj); 182 struct firmware_priv *fw_priv = class_get_devdata(class_dev); 183 struct firmware *fw; 184 ssize_t ret_count = count; 185 186 down(&fw_lock); 187 fw = fw_priv->fw; 188 if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { 189 ret_count = -ENODEV; 190 goto out; 191 } 192 if (offset > fw->size) { 193 ret_count = 0; 194 goto out; 195 } 196 if (offset + ret_count > fw->size) 197 ret_count = fw->size - offset; 198 199 memcpy(buffer, fw->data + offset, ret_count); 200out: 201 up(&fw_lock); 202 return ret_count; 203} 204static int 205fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) 206{ 207 u8 *new_data; 208 209 if (min_size <= fw_priv->alloc_size) 210 return 0; 211 212 new_data = vmalloc(fw_priv->alloc_size + PAGE_SIZE); 213 if (!new_data) { 214 printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__); 215 /* Make sure that we don't keep incomplete data */ 216 fw_load_abort(fw_priv); 217 return -ENOMEM; 218 } 219 fw_priv->alloc_size += PAGE_SIZE; 220 if (fw_priv->fw->data) { 221 memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size); 222 vfree(fw_priv->fw->data); 223 } 224 fw_priv->fw->data = new_data; 225 BUG_ON(min_size > fw_priv->alloc_size); 226 return 0; 227} 228 229/** 230 * firmware_data_write: 231 * 232 * Description: 233 * 234 * Data written to the 'data' attribute will be later handled to 235 * the driver as a firmware image. 236 **/ 237static ssize_t 238firmware_data_write(struct kobject *kobj, 239 char *buffer, loff_t offset, size_t count) 240{ 241 struct class_device *class_dev = to_class_dev(kobj); 242 struct firmware_priv *fw_priv = class_get_devdata(class_dev); 243 struct firmware *fw; 244 ssize_t retval; 245 246 if (!capable(CAP_SYS_RAWIO)) 247 return -EPERM; 248 249 down(&fw_lock); 250 fw = fw_priv->fw; 251 if (!fw || test_bit(FW_STATUS_DONE, &fw_priv->status)) { 252 retval = -ENODEV; 253 goto out; 254 } 255 retval = fw_realloc_buffer(fw_priv, offset + count); 256 if (retval) 257 goto out; 258 259 memcpy(fw->data + offset, buffer, count); 260 261 fw->size = max_t(size_t, offset + count, fw->size); 262 retval = count; 263out: 264 up(&fw_lock); 265 return retval; 266} 267static struct bin_attribute firmware_attr_data_tmpl = { 268 .attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE}, 269 .size = 0, 270 .read = firmware_data_read, 271 .write = firmware_data_write, 272}; 273 274static void 275fw_class_dev_release(struct class_device *class_dev) 276{ 277 struct firmware_priv *fw_priv = class_get_devdata(class_dev); 278 279 kfree(fw_priv); 280 kfree(class_dev); 281 282 module_put(THIS_MODULE); 283} 284 285static void 286firmware_class_timeout(u_long data) 287{ 288 struct firmware_priv *fw_priv = (struct firmware_priv *) data; 289 fw_load_abort(fw_priv); 290} 291 292static inline void 293fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) 294{ 295 /* XXX warning we should watch out for name collisions */ 296 strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); 297} 298 299static int 300fw_register_class_device(struct class_device **class_dev_p, 301 const char *fw_name, struct device *device) 302{ 303 int retval; 304 struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv), 305 GFP_KERNEL); 306 struct class_device *class_dev = kmalloc(sizeof (struct class_device), 307 GFP_KERNEL); 308 309 *class_dev_p = NULL; 310 311 if (!fw_priv || !class_dev) { 312 printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__); 313 retval = -ENOMEM; 314 goto error_kfree; 315 } 316 memset(fw_priv, 0, sizeof (*fw_priv)); 317 memset(class_dev, 0, sizeof (*class_dev)); 318 319 init_completion(&fw_priv->completion); 320 fw_priv->attr_data = firmware_attr_data_tmpl; 321 strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); 322 323 fw_priv->timeout.function = firmware_class_timeout; 324 fw_priv->timeout.data = (u_long) fw_priv; 325 init_timer(&fw_priv->timeout); 326 327 fw_setup_class_device_id(class_dev, device); 328 class_dev->dev = device; 329 class_dev->class = &firmware_class; 330 class_set_devdata(class_dev, fw_priv); 331 retval = class_device_register(class_dev); 332 if (retval) { 333 printk(KERN_ERR "%s: class_device_register failed\n", 334 __FUNCTION__); 335 goto error_kfree; 336 } 337 *class_dev_p = class_dev; 338 return 0; 339 340error_kfree: 341 kfree(fw_priv); 342 kfree(class_dev); 343 return retval; 344} 345 346static int 347fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, 348 const char *fw_name, struct device *device, int hotplug) 349{ 350 struct class_device *class_dev; 351 struct firmware_priv *fw_priv; 352 int retval; 353 354 *class_dev_p = NULL; 355 retval = fw_register_class_device(&class_dev, fw_name, device); 356 if (retval) 357 goto out; 358 359 /* Need to pin this module until class device is destroyed */ 360 __module_get(THIS_MODULE); 361 362 fw_priv = class_get_devdata(class_dev); 363 364 fw_priv->fw = fw; 365 retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data); 366 if (retval) { 367 printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", 368 __FUNCTION__); 369 goto error_unreg; 370 } 371 372 retval = class_device_create_file(class_dev, 373 &class_device_attr_loading); 374 if (retval) { 375 printk(KERN_ERR "%s: class_device_create_file failed\n", 376 __FUNCTION__); 377 goto error_unreg; 378 } 379 380 if (hotplug) 381 set_bit(FW_STATUS_READY, &fw_priv->status); 382 else 383 set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); 384 *class_dev_p = class_dev; 385 goto out; 386 387error_unreg: 388 class_device_unregister(class_dev); 389out: 390 return retval; 391} 392 393static int 394_request_firmware(const struct firmware **firmware_p, const char *name, 395 struct device *device, int hotplug) 396{ 397 struct class_device *class_dev; 398 struct firmware_priv *fw_priv; 399 struct firmware *firmware; 400 int retval; 401 402 if (!firmware_p) 403 return -EINVAL; 404 405 *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL); 406 if (!firmware) { 407 printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", 408 __FUNCTION__); 409 retval = -ENOMEM; 410 goto out; 411 } 412 memset(firmware, 0, sizeof (*firmware)); 413 414 retval = fw_setup_class_device(firmware, &class_dev, name, device, 415 hotplug); 416 if (retval) 417 goto error_kfree_fw; 418 419 fw_priv = class_get_devdata(class_dev); 420 421 if (hotplug) { 422 if (loading_timeout > 0) { 423 fw_priv->timeout.expires = jiffies + loading_timeout * HZ; 424 add_timer(&fw_priv->timeout); 425 } 426 427 kobject_hotplug(&class_dev->kobj, KOBJ_ADD); 428 wait_for_completion(&fw_priv->completion); 429 set_bit(FW_STATUS_DONE, &fw_priv->status); 430 del_timer_sync(&fw_priv->timeout); 431 } else 432 wait_for_completion(&fw_priv->completion); 433 434 down(&fw_lock); 435 if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) { 436 retval = -ENOENT; 437 release_firmware(fw_priv->fw); 438 *firmware_p = NULL; 439 } 440 fw_priv->fw = NULL; 441 up(&fw_lock); 442 class_device_unregister(class_dev); 443 goto out; 444 445error_kfree_fw: 446 kfree(firmware); 447 *firmware_p = NULL; 448out: 449 return retval; 450} 451 452/** 453 * request_firmware: - request firmware to hotplug and wait for it 454 * Description: 455 * @firmware will be used to return a firmware image by the name 456 * of @name for device @device. 457 * 458 * Should be called from user context where sleeping is allowed. 459 * 460 * @name will be use as $FIRMWARE in the hotplug environment and 461 * should be distinctive enough not to be confused with any other 462 * firmware image for this or any other device. 463 **/ 464int 465request_firmware(const struct firmware **firmware_p, const char *name, 466 struct device *device) 467{ 468 int hotplug = 1; 469 return _request_firmware(firmware_p, name, device, hotplug); 470} 471 472/** 473 * release_firmware: - release the resource associated with a firmware image 474 **/ 475void 476release_firmware(const struct firmware *fw) 477{ 478 if (fw) { 479 vfree(fw->data); 480 kfree(fw); 481 } 482} 483 484/** 485 * register_firmware: - provide a firmware image for later usage 486 * 487 * Description: 488 * Make sure that @data will be available by requesting firmware @name. 489 * 490 * Note: This will not be possible until some kind of persistence 491 * is available. 492 **/ 493void 494register_firmware(const char *name, const u8 *data, size_t size) 495{ 496 /* This is meaningless without firmware caching, so until we 497 * decide if firmware caching is reasonable just leave it as a 498 * noop */ 499} 500 501/* Async support */ 502struct firmware_work { 503 struct work_struct work; 504 struct module *module; 505 const char *name; 506 struct device *device; 507 void *context; 508 void (*cont)(const struct firmware *fw, void *context); 509 int hotplug; 510}; 511 512static int 513request_firmware_work_func(void *arg) 514{ 515 struct firmware_work *fw_work = arg; 516 const struct firmware *fw; 517 if (!arg) { 518 WARN_ON(1); 519 return 0; 520 } 521 daemonize("%s/%s", "firmware", fw_work->name); 522 _request_firmware(&fw, fw_work->name, fw_work->device, 523 fw_work->hotplug); 524 fw_work->cont(fw, fw_work->context); 525 release_firmware(fw); 526 module_put(fw_work->module); 527 kfree(fw_work); 528 return 0; 529} 530 531/** 532 * request_firmware_nowait: 533 * 534 * Description: 535 * Asynchronous variant of request_firmware() for contexts where 536 * it is not possible to sleep. 537 * 538 * @hotplug invokes hotplug event to copy the firmware image if this flag 539 * is non-zero else the firmware copy must be done manually. 540 * 541 * @cont will be called asynchronously when the firmware request is over. 542 * 543 * @context will be passed over to @cont. 544 * 545 * @fw may be %NULL if firmware request fails. 546 * 547 **/ 548int 549request_firmware_nowait( 550 struct module *module, int hotplug, 551 const char *name, struct device *device, void *context, 552 void (*cont)(const struct firmware *fw, void *context)) 553{ 554 struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), 555 GFP_ATOMIC); 556 int ret; 557 558 if (!fw_work) 559 return -ENOMEM; 560 if (!try_module_get(module)) { 561 kfree(fw_work); 562 return -EFAULT; 563 } 564 565 *fw_work = (struct firmware_work) { 566 .module = module, 567 .name = name, 568 .device = device, 569 .context = context, 570 .cont = cont, 571 .hotplug = hotplug, 572 }; 573 574 ret = kernel_thread(request_firmware_work_func, fw_work, 575 CLONE_FS | CLONE_FILES); 576 577 if (ret < 0) { 578 fw_work->cont(NULL, fw_work->context); 579 return ret; 580 } 581 return 0; 582} 583 584static int __init 585firmware_class_init(void) 586{ 587 int error; 588 error = class_register(&firmware_class); 589 if (error) { 590 printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__); 591 return error; 592 } 593 error = class_create_file(&firmware_class, &class_attr_timeout); 594 if (error) { 595 printk(KERN_ERR "%s: class_create_file failed\n", 596 __FUNCTION__); 597 class_unregister(&firmware_class); 598 } 599 return error; 600 601} 602static void __exit 603firmware_class_exit(void) 604{ 605 class_unregister(&firmware_class); 606} 607 608module_init(firmware_class_init); 609module_exit(firmware_class_exit); 610 611EXPORT_SYMBOL(release_firmware); 612EXPORT_SYMBOL(request_firmware); 613EXPORT_SYMBOL(request_firmware_nowait); 614EXPORT_SYMBOL(register_firmware);