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

ALSA: hwdep: Embed struct device

Like the previous patch, this one embeds the device object into hwdep
object. For a proper object lifecycle, it's freed in the release
callback.

This also allows us to create sysfs entries via passing to the groups
field of the device without explicit function calls. Since each
driver can see the device and touch its groups field directly, we
don't need to delegate in hwdep core any longer. So, remove the
groups field from snd_hwdep, and let the user (in this case only
hda_hwdep.c) modify the device groups.

Reviewed-by: Jaroslav Kysela <perex@perex.cz>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+38 -54
+1 -2
include/sound/hwdep.h
··· 68 68 wait_queue_head_t open_wait; 69 69 void *private_data; 70 70 void (*private_free) (struct snd_hwdep *hwdep); 71 - struct device *dev; 72 - const struct attribute_group **groups; 71 + struct device dev; 73 72 74 73 struct mutex open_mutex; 75 74 int used; /* reference counter */
+32 -50
sound/core/hwdep.c
··· 38 38 static LIST_HEAD(snd_hwdep_devices); 39 39 static DEFINE_MUTEX(register_mutex); 40 40 41 - static int snd_hwdep_free(struct snd_hwdep *hwdep); 42 41 static int snd_hwdep_dev_free(struct snd_device *device); 43 42 static int snd_hwdep_dev_register(struct snd_device *device); 44 43 static int snd_hwdep_dev_disconnect(struct snd_device *device); ··· 344 345 .mmap = snd_hwdep_mmap, 345 346 }; 346 347 348 + static void release_hwdep_device(struct device *dev) 349 + { 350 + kfree(container_of(dev, struct snd_hwdep, dev)); 351 + } 352 + 347 353 /** 348 354 * snd_hwdep_new - create a new hwdep instance 349 355 * @card: the card instance ··· 382 378 dev_err(card->dev, "hwdep: cannot allocate\n"); 383 379 return -ENOMEM; 384 380 } 381 + 382 + init_waitqueue_head(&hwdep->open_wait); 383 + mutex_init(&hwdep->open_mutex); 385 384 hwdep->card = card; 386 385 hwdep->device = device; 387 386 if (id) 388 387 strlcpy(hwdep->id, id, sizeof(hwdep->id)); 388 + 389 + snd_device_initialize(&hwdep->dev, card); 390 + hwdep->dev.release = release_hwdep_device; 391 + dev_set_name(&hwdep->dev, "hwC%iD%i", card->number, device); 389 392 #ifdef CONFIG_SND_OSSEMUL 390 393 hwdep->oss_type = -1; 391 394 #endif 392 - if ((err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops)) < 0) { 393 - snd_hwdep_free(hwdep); 395 + 396 + err = snd_device_new(card, SNDRV_DEV_HWDEP, hwdep, &ops); 397 + if (err < 0) { 398 + put_device(&hwdep->dev); 394 399 return err; 395 400 } 396 - init_waitqueue_head(&hwdep->open_wait); 397 - mutex_init(&hwdep->open_mutex); 401 + 398 402 if (rhwdep) 399 403 *rhwdep = hwdep; 400 404 return 0; 401 405 } 402 406 EXPORT_SYMBOL(snd_hwdep_new); 403 407 404 - static int snd_hwdep_free(struct snd_hwdep *hwdep) 408 + static int snd_hwdep_dev_free(struct snd_device *device) 405 409 { 410 + struct snd_hwdep *hwdep = device->device_data; 406 411 if (!hwdep) 407 412 return 0; 408 413 if (hwdep->private_free) 409 414 hwdep->private_free(hwdep); 410 - kfree(hwdep); 415 + put_device(&hwdep->dev); 411 416 return 0; 412 - } 413 - 414 - static int snd_hwdep_dev_free(struct snd_device *device) 415 - { 416 - struct snd_hwdep *hwdep = device->device_data; 417 - return snd_hwdep_free(hwdep); 418 417 } 419 418 420 419 static int snd_hwdep_dev_register(struct snd_device *device) 421 420 { 422 421 struct snd_hwdep *hwdep = device->device_data; 423 422 struct snd_card *card = hwdep->card; 424 - struct device *dev; 425 423 int err; 426 - char name[32]; 427 424 428 425 mutex_lock(&register_mutex); 429 426 if (snd_hwdep_search(card, hwdep->device)) { ··· 432 427 return -EBUSY; 433 428 } 434 429 list_add_tail(&hwdep->list, &snd_hwdep_devices); 435 - sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); 436 - dev = hwdep->dev; 437 - if (!dev) 438 - dev = snd_card_get_device_link(hwdep->card); 439 430 err = snd_register_device_for_dev(SNDRV_DEVICE_TYPE_HWDEP, 440 431 hwdep->card, hwdep->device, 441 432 &snd_hwdep_f_ops, hwdep, 442 - NULL, dev, name); 433 + &hwdep->dev, NULL, NULL); 443 434 if (err < 0) { 444 - dev_err(dev, 445 - "unable to register hardware dependent device %i:%i\n", 446 - card->number, hwdep->device); 435 + dev_err(&hwdep->dev, "unable to register\n"); 447 436 list_del(&hwdep->list); 448 437 mutex_unlock(&register_mutex); 449 438 return err; 450 439 } 451 440 452 - if (hwdep->groups) { 453 - struct device *d = snd_get_device(SNDRV_DEVICE_TYPE_HWDEP, 454 - hwdep->card, hwdep->device); 455 - if (d) { 456 - if (hwdep->private_data) 457 - dev_set_drvdata(d, hwdep->private_data); 458 - err = sysfs_create_groups(&d->kobj, hwdep->groups); 459 - if (err < 0) 460 - dev_warn(dev, 461 - "hwdep %d:%d: cannot create sysfs groups\n", 462 - card->number, hwdep->device); 463 - put_device(d); 464 - } 465 - } 466 - 467 441 #ifdef CONFIG_SND_OSSEMUL 468 442 hwdep->ossreg = 0; 469 443 if (hwdep->oss_type >= 0) { 470 - if ((hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM) && (hwdep->device != 0)) { 471 - dev_warn(dev, 444 + if (hwdep->oss_type == SNDRV_OSS_DEVICE_TYPE_DMFM && 445 + hwdep->device) 446 + dev_warn(&hwdep->dev, 472 447 "only hwdep device 0 can be registered as OSS direct FM device!\n"); 473 - } else { 474 - if (snd_register_oss_device(hwdep->oss_type, 475 - card, hwdep->device, 476 - &snd_hwdep_f_ops, hwdep) < 0) { 477 - dev_err(dev, 478 - "unable to register OSS compatibility device %i:%i\n", 479 - card->number, hwdep->device); 480 - } else 481 - hwdep->ossreg = 1; 482 - } 448 + else if (snd_register_oss_device(hwdep->oss_type, 449 + card, hwdep->device, 450 + &snd_hwdep_f_ops, hwdep) < 0) 451 + dev_warn(&hwdep->dev, 452 + "unable to register OSS compatibility device\n"); 453 + else 454 + hwdep->ossreg = 1; 483 455 } 484 456 #endif 485 457 mutex_unlock(&register_mutex);
+5 -2
sound/pci/hda/hda_hwdep.c
··· 109 109 hwdep->iface = SNDRV_HWDEP_IFACE_HDA; 110 110 hwdep->private_data = codec; 111 111 hwdep->exclusive = 1; 112 - hwdep->groups = snd_hda_dev_attr_groups; 113 112 114 113 hwdep->ops.open = hda_hwdep_open; 115 114 hwdep->ops.ioctl = hda_hwdep_ioctl; ··· 117 118 #endif 118 119 119 120 /* link to codec */ 120 - hwdep->dev = &codec->dev; 121 + hwdep->dev.parent = &codec->dev; 122 + 123 + /* for sysfs */ 124 + hwdep->dev.groups = snd_hda_dev_attr_groups; 125 + dev_set_drvdata(&hwdep->dev, codec); 121 126 122 127 return 0; 123 128 }