[GIT PULL] devm_kmalloc_obj conversion for v7.4-rc1 https://lore.kernel.org/lkml/202610301154.4B5EBBF13@keescook/
It contains uneven ways to handle the second argument, hmm…
commit 7e9903bd1909100fdc647c110353f6daaaecbf72
Author: Kees Cook <kees+treewide@kernel.org>
Date: Wed Oct 28 23:16:33 2026 -0700
treewide: Convert devm_kmalloc() family to the devm_kmalloc_obj() family
Mirroring the earlier kmalloc_obj() conversion, convert the
device-managed allocators over to the type-based API using the now
updated scripts/coccinelle/api/kmalloc_objs.cocci. The size is derived
from the type rather than written out as a sizeof(), and the result is
a pointer to that type rather than void *, so a mismatch between the
size requested and the variable assigned becomes a build error instead
of being silently accepted.
The conversions break down as:
6699 devm_kzalloc_obj()
1749 devm_kzalloc_objs()
303 devm_kzalloc_flex()
91 devm_kmalloc_objs()
82 devm_kmalloc_obj()
2 devm_kmalloc_flex()
The rules deliberately leave alone allocations sized by a string or a
byte-sized type, or assigned to a pointer to a byte-sized type, since
those are byte buffers rather than objects. Allocations sized by a
multi-byte integer type are only converted when they are assigned to a
pointer to that same type, and allocations of pointers to integers or of
void pointers are left alone too. After this change, 528 files still
call devm_kmalloc(), devm_kzalloc(), devm_kcalloc(), or
devm_kmalloc_array().
No functional change intended: every conversion allocates the same number
of bytes as before, and GFP_KERNEL is the macro default where it was
dropped.
Build tested with allmodconfig on x86_64, arm64, arm, riscv, s390, m68k,
mips, parisc, sparc, loongarch, arc, xtensa, and openrisc with GCC
16.2.0 with no new warnings.
Signed-off-by: Kees Cook <kees+treewide@kernel.org>
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index c06e8d872..20e561ed3 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -3788,7 +3788,8 @@ static int pci_probe(struct pci_dev *dev,
reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
ohci->ir_context_mask = ohci->ir_context_support;
ohci->n_ir = hweight32(ohci->ir_context_mask);
- ohci->ir_context_list = devm_kcalloc(&dev->dev, ohci->n_ir, sizeof(struct iso_context), GFP_KERNEL);
+ ohci->ir_context_list = devm_kzalloc_objs(&dev->dev, struct iso_context,
+ ohci->n_ir);
if (!ohci->ir_context_list)
return -ENOMEM;
@@ -3802,7 +3803,8 @@ static int pci_probe(struct pci_dev *dev,
reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
ohci->it_context_mask = ohci->it_context_support;
ohci->n_it = hweight32(ohci->it_context_mask);
- ohci->it_context_list = devm_kcalloc(&dev->dev, ohci->n_it, sizeof(struct iso_context), GFP_KERNEL);
+ ohci->it_context_list = devm_kzalloc_objs(&dev->dev, struct iso_context,
+ ohci->n_it);
if (!ohci->it_context_list)
return -ENOMEM;
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c
index 8079a938a..4ca5e0421 100644
--- a/sound/firewire/bebob/bebob_maudio.c
+++ b/sound/firewire/bebob/bebob_maudio.c
@@ -260,8 +260,7 @@ snd_bebob_maudio_special_discover(struct snd_bebob *bebob, bool is1814)
struct special_params *params;
int err;
- params = devm_kzalloc(&bebob->card->card_dev,
- sizeof(struct special_params), GFP_KERNEL);
+ params = devm_kzalloc_obj(&bebob->card->card_dev, struct special_params);
if (!params)
return -ENOMEM;
diff --git a/sound/firewire/motu/motu-command-dsp-message-parser.c b/sound/firewire/motu/motu-command-dsp-message-parser.c
index c6440e6e3..8caeb1019 100644
--- a/sound/firewire/motu/motu-command-dsp-message-parser.c
+++ b/sound/firewire/motu/motu-command-dsp-message-parser.c
@@ -37,7 +37,7 @@ int snd_motu_command_dsp_message_parser_new(struct snd_motu *motu)
{
struct msg_parser *parser;
- parser = devm_kzalloc(&motu->card->card_dev, sizeof(*parser), GFP_KERNEL);
+ parser = devm_kzalloc_obj(&motu->card->card_dev, *parser);
if (!parser)
return -ENOMEM;
spin_lock_init(&parser->lock);
diff --git a/sound/firewire/motu/motu-register-dsp-message-parser.c b/sound/firewire/motu/motu-register-dsp-message-parser.c
index 4ec23e688..3541d540b 100644
--- a/sound/firewire/motu/motu-register-dsp-message-parser.c
+++ b/sound/firewire/motu/motu-register-dsp-message-parser.c
@@ -101,7 +101,7 @@ struct msg_parser {
int snd_motu_register_dsp_message_parser_new(struct snd_motu *motu)
{
struct msg_parser *parser;
- parser = devm_kzalloc(&motu->card->card_dev, sizeof(*parser), GFP_KERNEL);
+ parser = devm_kzalloc_obj(&motu->card->card_dev, *parser);
if (!parser)
return -ENOMEM;
spin_lock_init(&parser->lock);
diff --git a/sound/firewire/oxfw/oxfw-scs1x.c b/sound/firewire/oxfw/oxfw-scs1x.c
index 21412a3ca..9a6e572af 100644
--- a/sound/firewire/oxfw/oxfw-scs1x.c
+++ b/sound/firewire/oxfw/oxfw-scs1x.c
@@ -371,8 +371,7 @@ int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw)
struct fw_scs1x *scs;
int err;
- scs = devm_kzalloc(&oxfw->card->card_dev, sizeof(struct fw_scs1x),
- GFP_KERNEL);
+ scs = devm_kzalloc_obj(&oxfw->card->card_dev, struct fw_scs1x);
if (!scs)
return -ENOMEM;
scs->fw_dev = fw_parent_device(oxfw->unit);
diff --git a/sound/firewire/oxfw/oxfw-spkr.c b/sound/firewire/oxfw/oxfw-spkr.c
index f2767fb19..1bf19310f 100644
--- a/sound/firewire/oxfw/oxfw-spkr.c
+++ b/sound/firewire/oxfw/oxfw-spkr.c
@@ -270,8 +270,7 @@ int snd_oxfw_add_spkr(struct snd_oxfw *oxfw, bool is_lacie)
unsigned int i, first_ch;
int err;
- spkr = devm_kzalloc(&oxfw->card->card_dev, sizeof(struct fw_spkr),
- GFP_KERNEL);
+ spkr = devm_kzalloc_obj(&oxfw->card->card_dev, struct fw_spkr);
if (!spkr)
return -ENOMEM;
oxfw->spec = spkr;
I sent:
[GIT PULL] firewire updates for v7.4 https://lore.kernel.org/lkml/20261024115915.GA518900@sakamocchi.jp/
firewire updates for v7.4
- Guarantee asynchronous packet and transaction callbacks in process context
Both the 1394 OHCI driver and the core transaction layer have been changed
to guarantee that asynchronous packet and transaction callbacks are
invoked in process context. In v6.17, the execution context depended on
the transaction destination: callbacks for transactions destined for
remote nodes were invoked from a workqueue, whereas callbacks for
transactions destined for the local node or terminated due to internal
errors were invoked in the transaction initiator's context. All such
callbacks are now guaranteed to execute in process context, eliminating
the need to account for different execution contexts when implementing
callback functions.
- Fill kerneldoc for transaction layer
The above change guarantees a consistent execution context for packet and
transaction callbacks, making it possible to document their execution
context in kerneldoc.
- Enable compiler-based context analysis for the transaction layer
The core transaction layer is sufficiently complex that compiler-based
context analysis can help detect invalid call paths.
- Fix a reference count leak in the cdev layer
A reference count leak was reported when a user space application
delegated isochronous resource management. This issue has now been fixed.
- Add KUnit tests for the configuration ROM parser and generator
In recent years, questions have been raised about how the configuration
ROM parser and generator handle boundary conditions and edge cases. KUnit
tests have been added to verify their behavior in these situations.
KUNIT_STATIC_STUB_REDIRECT is used to stub the transaction responder so
that it returns the configuration ROM contents.
- Misc fixes for kerneldoc and nosy-dump application
Hm.
$ git show
commit ba003f0c08ead39934425cb3a70e0e8f83ed7a5b (HEAD -> topic/cdev/iso-resource-once-rework)
Author: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Date: Mon Aug 24 23:12:18 2026 +0900
firewire: ohci: don't handle AT request/response packets in caller's context
It is inconvenient to handle AT request/response packets in the context of
__fw_send_request() call, since it could be any type of IRQ contexts. In
the case, the address handler implementation should take care of the lock
type.
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index e947227e..1195eab1 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1535,11 +1535,23 @@ static void handle_local_lock(struct fw_ohci *ohci,
fw_core_handle_response(&ohci->card, &response);
}
-static void handle_local_request(struct at_context *ctx, struct fw_packet *packet)
+struct local_at_packet {
+ struct work_struct work;
+ struct at_context *ctx;
+ struct fw_packet *p;
+};
+
+static void local_at_run(struct work_struct *work)
{
+ struct local_at_packet *local_packet = from_work(local_packet, work, work);
+ struct fw_packet *packet = local_packet->p;
+ struct at_context *ctx = local_packet->ctx;
struct fw_ohci *ohci = ctx->context.ohci;
u64 offset, csr;
+ // Timestamping on behalf of the hardware.
+ packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
+
if (ctx == &ohci->at_request_ctx) {
packet->ack = ACK_PENDING;
packet->callback(packet, &ohci->card, packet->ack);
@@ -1570,6 +1582,8 @@ static void handle_local_request(struct at_context *ctx, struct fw_packet *packe
packet->ack = ACK_COMPLETE;
packet->callback(packet, &ohci->card, packet->ack);
}
+
+ kfree(local_packet);
}
static void at_context_transmit(struct at_context *ctx, struct fw_packet *packet)
@@ -1584,10 +1598,18 @@ static void at_context_transmit(struct at_context *ctx, struct fw_packet *packet
ohci->generation == packet->generation) {
spin_unlock_irqrestore(&ohci->lock, flags);
- // Timestamping on behalf of the hardware.
- packet->timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
+ struct local_at_packet *local_packet = kmalloc_obj(*local_packet);
+
+ // TODO:
+ if (!local_packet)
+ return;
+
+ INIT_WORK(&local_packet->work, local_at_run);
+ local_packet->ctx = ctx;
+ local_packet->p = packet;
+
+ queue_work(ohci->card.async_wq, &local_packet->work);
- handle_local_request(ctx, packet);
return;
}
static void iso_resource_auto_work(struct work_struct *work)
{
struct iso_resource_auto *r = from_work(r, work, work.work);
struct client *client = r->client;
unsigned long index = r->resource.handle;
u64 reset_jiffies;
struct iso_resource_event *e;
int resource_generation, current_generation;
int channel, bandwidth, todo;
bool free = false;
scoped_guard(spinlock_irq, &client->device->card->lock) {
reset_jiffies = client->device->card->reset_jiffies;
current_generation = client->device->generation;
}
scoped_guard(spinlock_irq, &client->lock) {
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 (time_is_after_jiffies64(reset_jiffies + secs_to_jiffies(1))) {
scoped_guard(spinlock_irq, &client->lock)
schedule_iso_resource_auto(r, msecs_to_jiffies(333));
goto out;
}
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;
}
bandwidth = r->bandwidth;
fw_iso_resource_manage(client->device->card, current_generation,
r->channels, &channel, &bandwidth,
todo == ISO_RES_AUTO_ALLOC ||
todo == ISO_RES_AUTO_REALLOC);
if (todo == ISO_RES_AUTO_DEALLOC) {
e = no_free_ptr(r->e_dealloc);
} else {
// 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;
// Finishes successfully.
if (channel >= 0 || bandwidth > 0) {
// Generate no event at reallocation.
if (todo == ISO_RES_AUTO_REALLOC)
goto out;
scoped_guard(spinlock_irq, &client->lock) {
// Transit from allocation to reallocation, except if the client
// requested deallocation in the meantime.
r->todo = ISO_RES_AUTO_REALLOC;
r->channels = 1ULL << channel;
}
} else {
// 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;
}
}
}
e = no_free_ptr(r->e_alloc);
}
e->iso_resource.handle = r->resource.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);
if (free) {
cancel_delayed_work(&r->work);
kfree(r->e_alloc);
kfree(r->e_dealloc);
kfree(r);
}
out:
client_put(client);
}
static void iso_resource_once_work(struct work_struct *work)
{
struct iso_resource_once *r = from_work(r, work, work.work);
struct client *client = r->client;
struct iso_resource_event *e;
int generation, channel, bandwidth;
generation = client->device->generation;
bandwidth = r->bandwidth;
r->generation = generation;
fw_iso_resource_manage(client->device->card, generation, r->channels, &channel, &bandwidth,
r->todo == ISO_RES_ONCE_ALLOC);
e = no_free_ptr(r->event);
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_delayed_work(&r->work);
client_put(r->client);
kfree(r);
}