firewire updates for v7.2

This update includes the following changes.
 
 Unit drivers have been able to assign an arbitrary value in the mod_device
 entry, which is typed as kernel_ulong_t. While storing the pointer value
 is legitimate, conversion back to a pointer has been performed without
 preserving const qualifier. Uwe Kleine-König introduced an union to
 provide safer and more robust conversions, as part of the ongoing CHERI
 enhancement work for ARM and RISC-V architectures. This update includes
 changes in the sound subsystem, since the conversion pattern is widely
 used in ALSA firewire stack.
 
 The userspace applications can request the core function to perform
 isochronous resource management procedures. Dingsoul reported
 reference-count leak when these procedures are processed in workqueue
 contexts. This update refactors the relevant code paths following a divide
 and conquer approach. Consequently, it became clear that the issue still
 remain only in the path when userspace applications delegate automatic
 resource reallocation after bus resets to the core. In practice, the leak
 is rarely triggered, and a complete fix is still in progress.
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQQE66IEYNDXNBPeGKSsLtaWM8LwEwUCajZH8gAKCRCsLtaWM8Lw
 E5zDAP4gyY1cTSdvIeKay8yYRLqZXtBQTzMeqfSsptLBQgemCAEAwAFP+KKghjU7
 sDhDPgBD4bTDvYtjyh/RFb0lkTGV7wA=
 =3J0T
 -----END PGP SIGNATURE-----

Merge tag 'firewire-updates-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394

Pull firewire updates from Takashi Sakamoto:

 - firewire drivers have been able to assign an arbitrary value in the
   mod_device entry, which is typed as kernel_ulong_t.

   While storing the pointer value is legitimate, conversion back to a
   pointer has been performed without preserving the const qualifier.

   Uwe Kleine-König introduced an union to provide safer and more robust
   conversions, as part of the ongoing CHERI enhancement work for ARM
   and RISC-V architectures. This includes changes to the sound
   subsystem, since the conversion pattern is widely used in ALSA
   firewire stack.

 - Userspace applications can request the core function to perform
   isochronous resource management procedures. Dingsoul reported a
   reference-count leak when these procedures are processed in workqueue
   contexts.

   This refactors the relevant code paths following a divide and conquer
   approach. Consequently, it became clear that the issue still remain
   in the path when userspace applications delegate automatic resource
   reallocation after bus resets to the core.

   In practice, the leak is rarely triggered, and a complete fix is
   still in progress.

* tag 'firewire-updates-7.2' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394:
  firewire: core: Open-code topology list walk
  firewire: core: cancel using delayed work for iso_resource_once management
  firewire: core: rename member name for channel mask of isoc resource
  firewire: core: minor code refactoring for case-dependent parameters of iso resources management
  ALSA: firewire: Make use of ieee1394's .driver_data_ptr
  firewire: Simplify storing pointers in device id struct
  firewire: core: move allocation/reallocation paths into specific branch after isoc resource management in cdev
  firewire: core: refactor notification type determination after isoc resource management in cdev
  firewire: core: use switch statement for post-processing of isoc resource management in cdev
  firewire: core: reduce critical section duration in pre-processing of isoc resource management in cdev
  firewire: core: code cleanup for iso resource auto creation
  firewire: core: append _auto suffix for non-once iso resource operations
  firewire: core: code cleanup to remove old implementations for once operation
  firewire: core: split functions for iso_resource once operation
  firewire: core: code refactoring for helper function to fill iso_resource parameters
  firewire: core: code refactoring to queue work item for iso_resource
  firewire: core: code refactoring for early return at client resource allocation
This commit is contained in:
Linus Torvalds 2026-06-21 10:05:11 -07:00
commit aff3ca32f3
7 changed files with 259 additions and 177 deletions

View File

@ -128,19 +128,37 @@ struct descriptor_resource {
u32 data[];
};
struct iso_resource {
struct iso_resource_params {
u64 channels_mask;
s32 bandwidth;
};
struct iso_resource_auto {
struct client_resource resource;
struct client *client;
/* Schedule work and access todo only with client->lock held. */
struct delayed_work work;
enum {ISO_RES_ALLOC, ISO_RES_REALLOC, ISO_RES_DEALLOC,
ISO_RES_ALLOC_ONCE, ISO_RES_DEALLOC_ONCE,} todo;
enum {
ISO_RES_AUTO_ALLOC,
ISO_RES_AUTO_REALLOC,
ISO_RES_AUTO_DEALLOC,
} todo;
int generation;
u64 channels;
s32 bandwidth;
struct iso_resource_params params;
struct iso_resource_event *e_alloc, *e_dealloc;
};
struct iso_resource_once {
struct client *client;
struct work_struct work;
enum {
ISO_RES_ONCE_ALLOC,
ISO_RES_ONCE_DEALLOC,
} todo;
struct iso_resource_params params;
struct iso_resource_event *event;
};
static struct address_handler_resource *to_address_handler_resource(struct client_resource *resource)
{
return container_of(resource, struct address_handler_resource, resource);
@ -156,16 +174,16 @@ static struct descriptor_resource *to_descriptor_resource(struct client_resource
return container_of(resource, struct descriptor_resource, resource);
}
static struct iso_resource *to_iso_resource(struct client_resource *resource)
static struct iso_resource_auto *to_iso_resource_auto(struct client_resource *resource)
{
return container_of(resource, struct iso_resource, resource);
return container_of(resource, struct iso_resource_auto, resource);
}
static void release_iso_resource(struct client *, struct client_resource *);
static void release_iso_resource_auto(struct client *, struct client_resource *);
static int is_iso_resource(const struct client_resource *resource)
static int is_iso_resource_auto(const struct client_resource *resource)
{
return resource->release == release_iso_resource;
return resource->release == release_iso_resource_auto;
}
static void release_transaction(struct client *client,
@ -176,7 +194,7 @@ static int is_outbound_transaction_resource(const struct client_resource *resour
return resource->release == release_transaction;
}
static void schedule_iso_resource(struct iso_resource *r, unsigned long delay)
static void schedule_iso_resource_auto(struct iso_resource_auto *r, unsigned long delay)
{
client_get(r->client);
if (!queue_delayed_work(fw_workqueue, &r->work, delay))
@ -424,8 +442,8 @@ static void queue_bus_reset_event(struct client *client)
guard(spinlock_irq)(&client->lock);
xa_for_each(&client->resource_xa, index, resource) {
if (is_iso_resource(resource))
schedule_iso_resource(to_iso_resource(resource), 0);
if (is_iso_resource_auto(resource))
schedule_iso_resource_auto(to_iso_resource_auto(resource), 0);
}
}
@ -507,31 +525,28 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
static int add_client_resource(struct client *client, struct client_resource *resource,
gfp_t gfp_mask)
{
int ret;
scoped_guard(spinlock_irqsave, &client->lock) {
u32 index;
int ret;
if (client->in_shutdown) {
ret = -ECANCELED;
if (client->in_shutdown)
return -ECANCELED;
if (gfpflags_allow_blocking(gfp_mask)) {
ret = xa_alloc(&client->resource_xa, &index, resource, xa_limit_32b,
GFP_NOWAIT);
} else {
if (gfpflags_allow_blocking(gfp_mask)) {
ret = xa_alloc(&client->resource_xa, &index, resource, xa_limit_32b,
GFP_NOWAIT);
} else {
ret = xa_alloc_bh(&client->resource_xa, &index, resource,
xa_limit_32b, GFP_NOWAIT);
}
}
if (ret >= 0) {
resource->handle = index;
client_get(client);
if (is_iso_resource(resource))
schedule_iso_resource(to_iso_resource(resource), 0);
ret = xa_alloc_bh(&client->resource_xa, &index, resource,
xa_limit_32b, GFP_NOWAIT);
}
if (ret < 0)
return ret;
resource->handle = index;
client_get(client);
}
return ret < 0 ? ret : 0;
return 0;
}
static int release_client_resource(struct client *client, u32 handle,
@ -1293,83 +1308,106 @@ static int ioctl_get_cycle_timer(struct client *client, union ioctl_arg *arg)
return 0;
}
static void iso_resource_work(struct work_struct *work)
static int fill_iso_resource_params(struct iso_resource_params *params,
struct fw_cdev_allocate_iso_resource *request)
{
if ((request->channels == 0 && request->bandwidth == 0) ||
request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL)
return -EINVAL;
params->channels_mask = request->channels;
params->bandwidth = request->bandwidth;
return 0;
}
static void iso_resource_auto_work(struct work_struct *work)
{
struct iso_resource_event *e;
struct iso_resource *r = from_work(r, work, work.work);
struct iso_resource_auto *r = from_work(r, work, work.work);
struct client *client = r->client;
unsigned long index = r->resource.handle;
int generation, channel, bandwidth, todo;
bool skip, free, success;
int current_generation, resource_generation, channel, bandwidth, todo;
u64 reset_jiffies;
bool free;
scoped_guard(spinlock_irq, &client->lock) {
generation = client->device->generation;
reset_jiffies = client->device->card->reset_jiffies;
current_generation = client->device->generation;
resource_generation = r->generation;
r->generation = current_generation;
todo = r->todo;
}
switch (todo) {
case ISO_RES_AUTO_ALLOC:
// Allow 1000ms grace period for other reallocations.
if (todo == ISO_RES_ALLOC &&
time_is_after_jiffies64(client->device->card->reset_jiffies + secs_to_jiffies(1))) {
schedule_iso_resource(r, msecs_to_jiffies(333));
skip = true;
} else {
// We could be called twice within the same generation.
skip = todo == ISO_RES_REALLOC &&
r->generation == generation;
if (time_is_after_jiffies64(reset_jiffies + secs_to_jiffies(1))) {
schedule_iso_resource_auto(r, msecs_to_jiffies(333));
goto out;
}
free = todo == ISO_RES_DEALLOC ||
todo == ISO_RES_ALLOC_ONCE ||
todo == ISO_RES_DEALLOC_ONCE;
r->generation = generation;
break;
case ISO_RES_AUTO_REALLOC:
// We could be called twice within the same generation.
if (resource_generation == current_generation)
goto out;
break;
case ISO_RES_AUTO_DEALLOC:
default:
break;
}
if (skip)
goto out;
bandwidth = r->params.bandwidth;
bandwidth = r->bandwidth;
fw_iso_resource_manage(client->device->card, current_generation, r->params.channels_mask,
&channel, &bandwidth, todo != ISO_RES_AUTO_DEALLOC);
fw_iso_resource_manage(client->device->card, generation,
r->channels, &channel, &bandwidth,
todo == ISO_RES_ALLOC ||
todo == ISO_RES_REALLOC ||
todo == ISO_RES_ALLOC_ONCE);
/*
* Is this generation outdated already? As long as this resource sticks
* in the xarray, it will be scheduled again for a newer generation or at
* shutdown.
*/
if (channel == -EAGAIN &&
(todo == ISO_RES_ALLOC || todo == ISO_RES_REALLOC))
goto out;
success = channel >= 0 || bandwidth > 0;
scoped_guard(spinlock_irq, &client->lock) {
// Transit from allocation to reallocation, except if the client
// requested deallocation in the meantime.
if (r->todo == ISO_RES_ALLOC)
r->todo = ISO_RES_REALLOC;
// Allocation or reallocation failure? Pull this resource out of the
// xarray and prepare for deletion, unless the client is shutting down.
if (r->todo == ISO_RES_REALLOC && !success &&
!client->in_shutdown &&
xa_erase(&client->resource_xa, index)) {
client_put(client);
free = true;
}
}
if (todo == ISO_RES_ALLOC && channel >= 0)
r->channels = 1ULL << channel;
if (todo == ISO_RES_REALLOC && success)
goto out;
if (todo == ISO_RES_ALLOC || todo == ISO_RES_ALLOC_ONCE) {
e = r->e_alloc;
r->e_alloc = NULL;
} else {
if (todo == ISO_RES_AUTO_DEALLOC) {
free = true;
e = r->e_dealloc;
r->e_dealloc = NULL;
} else {
free = false;
// Is this generation outdated already? As long as this resource sticks in the
// xarray, it will be scheduled again for a newer generation or at shutdown.
if (channel == -EAGAIN)
goto out;
bool success = channel >= 0 || bandwidth > 0;
if (!success) {
// Allocation or reallocation failure? Pull this resource out of the
// xarray and prepare for deletion, unless the client is shutting down.
scoped_guard(spinlock_irq, &client->lock) {
if (!client->in_shutdown && xa_erase(&client->resource_xa, index)) {
client_put(client);
free = true;
}
}
}
if (todo == ISO_RES_AUTO_REALLOC) {
if (success)
goto out;
// Notify the userspace client of the failure through a deallocation event.
e = r->e_dealloc;
r->e_dealloc = NULL;
} else {
// Transit from allocation to reallocation, except if the client requested
// deallocation in the meantime.
scoped_guard(spinlock_irq, &client->lock)
r->todo = ISO_RES_AUTO_REALLOC;
if (channel >= 0)
r->params.channels_mask = BIT_ULL(channel);
e = r->e_alloc;
r->e_alloc = NULL;
}
}
e->iso_resource.handle = r->resource.handle;
e->iso_resource.channel = channel;
e->iso_resource.bandwidth = bandwidth;
@ -1387,97 +1425,136 @@ static void iso_resource_work(struct work_struct *work)
client_put(client);
}
static void release_iso_resource(struct client *client,
struct client_resource *resource)
static void release_iso_resource_auto(struct client *client, struct client_resource *resource)
{
struct iso_resource *r = to_iso_resource(resource);
struct iso_resource_auto *r = to_iso_resource_auto(resource);
guard(spinlock_irq)(&client->lock);
r->todo = ISO_RES_DEALLOC;
schedule_iso_resource(r, 0);
r->todo = ISO_RES_AUTO_DEALLOC;
schedule_iso_resource_auto(r, 0);
}
static int init_iso_resource(struct client *client,
struct fw_cdev_allocate_iso_resource *request, int todo)
static int ioctl_allocate_iso_resource(struct client *client, union ioctl_arg *arg)
{
struct iso_resource_event *e1, *e2;
struct iso_resource *r;
int ret;
struct fw_cdev_allocate_iso_resource *request = &arg->allocate_iso_resource;
struct iso_resource_event *e1 __free(kfree) = kmalloc_obj(*e1);
struct iso_resource_event *e2 __free(kfree) = kmalloc_obj(*e2);
struct iso_resource_auto *r __free(kfree) = kmalloc_obj(*r);
int err;
if ((request->channels == 0 && request->bandwidth == 0) ||
request->bandwidth > BANDWIDTH_AVAILABLE_INITIAL)
return -EINVAL;
if (!r || !e1 || !e2)
return -ENOMEM;
r = kmalloc_obj(*r);
e1 = kmalloc_obj(*e1);
e2 = kmalloc_obj(*e2);
if (r == NULL || e1 == NULL || e2 == NULL) {
ret = -ENOMEM;
goto fail;
}
err = fill_iso_resource_params(&r->params, request);
if (err < 0)
return err;
INIT_DELAYED_WORK(&r->work, iso_resource_work);
INIT_DELAYED_WORK(&r->work, iso_resource_auto_work);
r->client = client;
r->todo = todo;
r->generation = -1;
r->channels = request->channels;
r->bandwidth = request->bandwidth;
r->todo = ISO_RES_AUTO_ALLOC;
r->e_alloc = e1;
r->e_dealloc = e2;
e1->iso_resource.closure = request->closure;
e1->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
e1->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
e2->iso_resource.closure = request->closure;
e2->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
e2->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
if (todo == ISO_RES_ALLOC) {
r->resource.release = release_iso_resource;
ret = add_client_resource(client, &r->resource, GFP_KERNEL);
if (ret < 0)
goto fail;
} else {
r->resource.release = NULL;
r->resource.handle = -1;
schedule_iso_resource(r, 0);
}
r->resource.release = release_iso_resource_auto;
err = add_client_resource(client, &r->resource, GFP_KERNEL);
if (err < 0)
return err;
request->handle = r->resource.handle;
retain_and_null_ptr(e1);
retain_and_null_ptr(e2);
schedule_iso_resource_auto(no_free_ptr(r), 0);
return 0;
fail:
kfree(r);
kfree(e1);
kfree(e2);
return ret;
}
static int ioctl_allocate_iso_resource(struct client *client,
union ioctl_arg *arg)
{
return init_iso_resource(client,
&arg->allocate_iso_resource, ISO_RES_ALLOC);
}
static int ioctl_deallocate_iso_resource(struct client *client,
union ioctl_arg *arg)
{
return release_client_resource(client,
arg->deallocate.handle, release_iso_resource, NULL);
arg->deallocate.handle, release_iso_resource_auto, NULL);
}
#define UNAVAILABLE_HANDLE -1
static void iso_resource_once_work(struct work_struct *work)
{
struct iso_resource_once *r = from_work(r, work, work);
struct client *client = r->client;
struct iso_resource_event *e = r->event;
int generation, channel, bandwidth;
scoped_guard(spinlock_irq, &client->lock)
generation = client->device->generation;
bandwidth = r->params.bandwidth;
fw_iso_resource_manage(client->device->card, generation, r->params.channels_mask, &channel,
&bandwidth, r->todo == ISO_RES_ONCE_ALLOC);
e->iso_resource.handle = UNAVAILABLE_HANDLE;
e->iso_resource.channel = channel;
e->iso_resource.bandwidth = bandwidth;
queue_event(client, &e->event, &e->iso_resource, sizeof(e->iso_resource), NULL, 0);
cancel_work(&r->work);
kfree(r);
client_put(client);
}
static int init_iso_resource_once(struct client *client,
struct fw_cdev_allocate_iso_resource *request, int todo)
{
struct iso_resource_event *e __free(kfree) = kmalloc_obj(*e);
struct iso_resource_once *r __free(kfree) = kmalloc_obj(*r);
int err;
if (!r || !e)
return -ENOMEM;
err = fill_iso_resource_params(&r->params, request);
if (err < 0)
return err;
INIT_WORK(&r->work, iso_resource_once_work);
r->client = client;
r->todo = todo;
if (todo == ISO_RES_ONCE_ALLOC)
e->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED;
else
e->iso_resource.type = FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED;
e->iso_resource.closure = request->closure;
r->event = no_free_ptr(e);
// Keep the client until work item finishing.
client_get(r->client);
queue_work(fw_workqueue, &no_free_ptr(r)->work);
request->handle = UNAVAILABLE_HANDLE;
return 0;
}
static int ioctl_allocate_iso_resource_once(struct client *client,
union ioctl_arg *arg)
{
return init_iso_resource(client,
&arg->allocate_iso_resource, ISO_RES_ALLOC_ONCE);
return init_iso_resource_once(client, &arg->allocate_iso_resource, ISO_RES_ONCE_ALLOC);
}
static int ioctl_deallocate_iso_resource_once(struct client *client,
union ioctl_arg *arg)
{
return init_iso_resource(client,
&arg->allocate_iso_resource, ISO_RES_DEALLOC_ONCE);
return init_iso_resource_once(client, &arg->allocate_iso_resource, ISO_RES_ONCE_DEALLOC);
}
/*

View File

@ -272,7 +272,9 @@ static void for_each_fw_node(struct fw_card *card, struct fw_node *root,
fw_node_get(root);
list_add_tail(&root->link, &list);
parent = NULL;
list_for_each_entry(node, &list, link) {
for (node = list_first_entry(&list, typeof(*node), link);
!list_entry_is_head(node, &list, link);
node = list_next_entry(node, link)) {
node->color = card->color;
for (i = 0; i < node->port_count; i++) {

View File

@ -61,7 +61,10 @@ struct ieee1394_device_id {
__u32 model_id;
__u32 specifier_id;
__u32 version;
kernel_ulong_t driver_data;
union {
kernel_ulong_t driver_data;
const void *driver_data_ptr;
};
};

View File

@ -148,7 +148,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *ent
snd_dice_detect_formats_t detect_formats;
int err;
if (!entry->driver_data && entry->vendor_id != OUI_SSL) {
if (!entry->driver_data_ptr && entry->vendor_id != OUI_SSL) {
err = check_dice_category(unit);
if (err < 0)
return -ENODEV;
@ -164,10 +164,10 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *ent
dev_set_drvdata(&unit->device, dice);
dice->card = card;
if (!entry->driver_data)
if (!entry->driver_data_ptr)
detect_formats = snd_dice_stream_detect_current_formats;
else
detect_formats = (snd_dice_detect_formats_t)entry->driver_data;
detect_formats = entry->driver_data_ptr;
// Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer
// frequency.
@ -255,7 +255,7 @@ static void dice_bus_reset(struct fw_unit *unit)
.model_id = (model), \
.specifier_id = (vendor), \
.version = DICE_INTERFACE, \
.driver_data = (kernel_ulong_t)(data), \
.driver_data_ptr = (data), \
}
static const struct ieee1394_device_id dice_id_table[] = {
@ -267,7 +267,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MAUDIO,
.model_id = 0x000010,
.driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
.driver_data_ptr = snd_dice_detect_extension_formats,
},
/* M-Audio Profire 610 has a different value in version field. */
{
@ -275,7 +275,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MAUDIO,
.model_id = 0x000011,
.driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
.driver_data_ptr = snd_dice_detect_extension_formats,
},
/* TC Electronic Konnekt 24D. */
{
@ -283,7 +283,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000020,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
.driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Konnekt 8. */
{
@ -291,7 +291,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000021,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
.driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Studio Konnekt 48. */
{
@ -299,7 +299,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000022,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
.driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Konnekt Live. */
{
@ -307,7 +307,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000023,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
.driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Desktop Konnekt 6. */
{
@ -315,7 +315,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000024,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
.driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Impact Twin. */
{
@ -323,7 +323,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000027,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
.driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Digital Konnekt x32. */
{
@ -331,7 +331,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000030,
.driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
.driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* Alesis iO14/iO26. */
{
@ -339,7 +339,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_ALESIS,
.model_id = MODEL_ALESIS_IO_BOTH,
.driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats,
.driver_data_ptr = snd_dice_detect_alesis_formats,
},
// Alesis MasterControl.
{
@ -347,7 +347,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_ALESIS,
.model_id = 0x000002,
.driver_data = (kernel_ulong_t)snd_dice_detect_alesis_mastercontrol_formats,
.driver_data_ptr = snd_dice_detect_alesis_mastercontrol_formats,
},
/* Mytek Stereo 192 DSD-DAC. */
{
@ -355,7 +355,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MYTEK,
.model_id = 0x000002,
.driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats,
.driver_data_ptr = snd_dice_detect_mytek_formats,
},
// Solid State Logic, Duende Classic and Mini.
// NOTE: each field of GUID in config ROM is not compliant to standard
@ -469,7 +469,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
.model_id = OUI_TEAC,
.specifier_id = OUI_TEAC,
.version = 0x800006,
.driver_data = (kernel_ulong_t)snd_dice_detect_teac_formats,
.driver_data_ptr = snd_dice_detect_teac_formats,
},
{ }
};

View File

@ -70,7 +70,7 @@ static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *e
init_waitqueue_head(&ff->hwdep_wait);
ff->unit_version = entry->version;
ff->spec = (const struct snd_ff_spec *)entry->driver_data;
ff->spec = entry->driver_data_ptr;
err = snd_ff_transaction_register(ff);
if (err < 0)
@ -186,7 +186,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_FF800,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ff800,
.driver_data_ptr = &spec_ff800,
},
/* Fireface 400 */
{
@ -198,7 +198,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_FF400,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ff400,
.driver_data_ptr = &spec_ff400,
},
// Fireface UFX.
{
@ -210,7 +210,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_UFX,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ufx_802,
.driver_data_ptr = &spec_ufx_802,
},
// Fireface UCX.
{
@ -222,7 +222,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_UCX,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ucx,
.driver_data_ptr = &spec_ucx,
},
// Fireface 802.
{
@ -234,7 +234,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_802,
.model_id = 0x101800,
.driver_data = (kernel_ulong_t)&spec_ufx_802,
.driver_data_ptr = &spec_ufx_802,
},
{}
};

View File

@ -78,7 +78,7 @@ static int motu_probe(struct fw_unit *unit, const struct ieee1394_device_id *ent
dev_set_drvdata(&unit->device, motu);
motu->card = card;
motu->spec = (const struct snd_motu_spec *)entry->driver_data;
motu->spec = entry->driver_data_ptr;
mutex_init(&motu->mutex);
spin_lock_init(&motu->lock);
init_waitqueue_head(&motu->hwdep_wait);
@ -148,7 +148,7 @@ static void motu_bus_update(struct fw_unit *unit)
snd_motu_transaction_reregister(motu);
}
#define SND_MOTU_DEV_ENTRY(model, data) \
#define SND_MOTU_DEV_ENTRY(model, data_ptr) \
{ \
.match_flags = IEEE1394_MATCH_VENDOR_ID | \
IEEE1394_MATCH_SPECIFIER_ID | \
@ -156,7 +156,7 @@ static void motu_bus_update(struct fw_unit *unit)
.vendor_id = OUI_MOTU, \
.specifier_id = OUI_MOTU, \
.version = model, \
.driver_data = (kernel_ulong_t)data, \
.driver_data_ptr = data_ptr, \
}
static const struct ieee1394_device_id motu_id_table[] = {

View File

@ -95,7 +95,7 @@ static int name_card(struct snd_oxfw *oxfw, const struct ieee1394_device_id *ent
/* to apply card definitions */
if (entry->vendor_id == VENDOR_GRIFFIN || entry->vendor_id == VENDOR_LACIE) {
info = (const struct compat_info *)entry->driver_data;
info = entry->driver_data_ptr;
d = info->driver_name;
v = info->vendor_name;
m = info->model_name;
@ -321,7 +321,7 @@ static const struct compat_info lacie_speakers = {
.model_id = model, \
.specifier_id = SPECIFIER_1394TA, \
.version = VERSION_AVC, \
.driver_data = (kernel_ulong_t)data, \
.driver_data_ptr = data, \
}
static const struct ieee1394_device_id oxfw_id_table[] = {