[PATCH 0/3] firewire: use single object for user space listeners to dispatch request to IEC 61883-1 FCP region
Hi,
This patch solves long standing issue mentioned by code comment[1] and a commit 281e20323ab7 ("firewire: core: fix use-after-free regression in FCP handler")[2]. This patchset is based on the kernel tree to which another fix is applied[3].
To Iwai-san, I would like to ask you picking them to your local tree, then send them to mainline tree as well as sound patches when the merge window is open for v6.3 kernel, unless any question and objection is posted. (Additionally, I have prepared the other patchset for the subsystem.)
Linux FireWire subsystem allows multiple listeners to inbound request to IEC 61883-1 FCP region. The listeners need to access to the payload of request, while the core function needs to guarantee transaction completion by sending response. It is a risk to use-after-free by accessing to the object of request released at completion.
The commit 281e20323ab7 solves the risk by the duplication of payload, while it is slightly redundant (and a risk of memory leak[3]). Developers have acknowledged that the advantage of reference count to maintain the lifetime of object.
Furthermore, the commit uses NULL pointer for the listeners to distinguish whether the request is to FCP region or not. It is a risk that the listeners retrieve parameters by dereferencing it. For instance, a commit b2405aa948b9 ("firewire: add kernel API to access packet structure in request structure for AR context")[4] adds a kernel API to retrieve time stamp from the data of request, while it is not available in the case of request to FCP region.
As a solution, this patchset uses kref structure to maintain lifetime of data for fw_request structure, then dismisses NULL pointer passing to the listeners. Finally, the duplication is obsoleted.
This is a log to probe kmalloc/kfree tracepoints events in the case to handle the request to FCP region.
irq/35-firewire-273881 [002] 373149.138580: kmalloc: (fw_core_handle_request+0x7b) call_site=fw_core_handle_request+0x7b ptr=0xffff99e93f007300 bytes_req=155 bytes_alloc=192 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138582: kmalloc: (handle_request+0x22e) call_site=handle_request+0x22e ptr=0xffff99e96e54f240 bytes_req=56 bytes_alloc=64 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138583: kmalloc: (handle_request+0x24b) call_site=handle_request+0x24b ptr=0xffff99e8b8a6ed20 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138587: kmalloc: (handle_request+0x22e) call_site=handle_request+0x22e ptr=0xffff99e96e54fa80 bytes_req=56 bytes_alloc=64 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138587: kmalloc: (handle_request+0x24b) call_site=handle_request+0x24b ptr=0xffff99e8a3f06960 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138591: kmalloc: (handle_request+0x22e) call_site=handle_request+0x22e ptr=0xffff99e96e54f380 bytes_req=56 bytes_alloc=64 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138591: kmalloc: (handle_request+0x24b) call_site=handle_request+0x24b ptr=0xffff99e8a3f06600 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138598: kmalloc: (handle_request+0x22e) call_site=handle_request+0x22e ptr=0xffff99e96e54f7c0 bytes_req=56 bytes_alloc=64 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138598: kmalloc: (handle_request+0x24b) call_site=handle_request+0x24b ptr=0xffff99e8a3f06180 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138602: kmalloc: (handle_request+0x22e) call_site=handle_request+0x22e ptr=0xffff99e96e54f4c0 bytes_req=56 bytes_alloc=64 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 373149.138603: kmalloc: (handle_request+0x24b) call_site=handle_request+0x24b ptr=0xffff99e94d48b660 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_ATOMIC python3-278050 [000] 373149.138605: kfree: (fw_device_op_read+0x148) call_site=fw_device_op_read+0x148 ptr=0xffff99e8b8a6ed20 python3-278050 [000] 373149.138611: kfree: (ioctl_send_response+0x10a) call_site=ioctl_send_response+0x10a ptr=0xffff99e96e54f240 python3-278053 [001] 373149.138612: kfree: (fw_device_op_read+0x148) call_site=fw_device_op_read+0x148 ptr=0xffff99e8a3f06960 snd-oxfw-ctl-se-278061 [003] 373149.138618: kfree: (fw_device_op_read+0x148) call_site=fw_device_op_read+0x148 ptr=0xffff99e94d48b660 python3-278053 [001] 373149.138621: kfree: (ioctl_send_response+0x10a) call_site=ioctl_send_response+0x10a ptr=0xffff99e96e54fa80 python3-278057 [002] 373149.138627: kfree: (fw_device_op_read+0x148) call_site=fw_device_op_read+0x148 ptr=0xffff99e8a3f06180 snd-oxfw-ctl-se-278061 [003] 373149.138636: kfree: (ioctl_send_response+0x10a) call_site=ioctl_send_response+0x10a ptr=0xffff99e96e54f4c0 python3-278055 [000] 373149.138637: kfree: (fw_device_op_read+0x148) call_site=fw_device_op_read+0x148 ptr=0xffff99e8a3f06600 python3-278055 [000] 373149.138642: kfree: (ioctl_send_response+0x10a) call_site=ioctl_send_response+0x10a ptr=0xffff99e96e54f380 python3-278057 [002] 373149.138654: kfree: (fw_request_put+0x2c) call_site=fw_request_put+0x2c ptr=0xffff99e93f007300 python3-278057 [002] 373149.138654: kfree: (ioctl_send_response+0x10a) call_site=ioctl_send_response+0x10a ptr=0xffff99e96e54f7c0
There are five listeners of IEC 61883-1 FCP region:
* Python 3: PID 278050 * Python 3: PID 278053 * Python 3: PID 278055 * Python 3: PID 278057 * snd-oxfw-ctl-service: PID 278061
When handling 1394 OHCI Asynchronous Receive context (for request) in softIRQ context, an object is allocated for the request (ptr=0xffff99e93f007300). When queueing event per client, the reference count of object is increased.
The object is released when the last listener (PID 278057) executes ioctl(2) with FW_CDEV_IOC_SEND_REQUEST request to decrease the reference count and release event resource.
Between the event queueing and event dispatching, the core function send response to complete transaction. The object is not released in the timing, expectedly.
This is another log in the case to handle request to non-FCP region:
irq/35-firewire-273881 [002] 377484.348477: kmalloc: (fw_core_handle_request+0x7b) call_site=fw_core_handle_request+0x7b ptr=0xffff99e96140cd80 bytes_req=148 bytes_alloc=192 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 377484.348478: kmalloc: (handle_request+0xa8) call_site=handle_request+0xa8 ptr=0xffff99e9669303c0 bytes_req=56 bytes_alloc=64 gfp_flags=GFP_ATOMIC irq/35-firewire-273881 [002] 377484.348479: kmalloc: (handle_request+0xc4) call_site=handle_request+0xc4 ptr=0xffff99e99eaed0c0 bytes_req=96 bytes_alloc=96 gfp_flags=GFP_ATOMIC python3-280425 [001] 377484.348494: kfree: (fw_device_op_read+0x148) call_site=fw_device_op_read+0x148 ptr=0xffff99e99eaed0c0 python3-280425 [001] 377484.348563: kfree: (ioctl_send_response+0x10a) call_site=ioctl_send_response+0x10a ptr=0xffff99e9669303c0 irq/35-firewire-273881 [002] 377484.348603: kfree: (free_response_callback+0x5a) call_site=free_response_callback+0x5a ptr=0xffff99e96140cd80
The object is allocated (ptr=0xffff99e96140cd80) in the softIRQ, then event is queued. Python 3 process (PID 280425) dispatches the event, then execute ioctl(2) to send response. In softIRQ for 1394 OHCI Asynchronous Receive context (for response), the object is finally released as a result to decrease the reference count.
The reference count looks to prevent memory leak.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/driv... [2] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... [3] https://lore.kernel.org/lkml/20230117090610.93792-1-o-takashi@sakamocchi.jp/ [4] I should have elaborated the patch title... https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
Takashi Sakamoto (3): firewire: core: use kref structure to maintain lifetime of data for fw_request structure firewire: cdev: obsolete NULL check to detect IEC 61883-1 FCP region firewire: cdev: use single object to dispatch event for request to IEC 61883-1 FCP region
drivers/firewire/core-cdev.c | 43 +++++++++-------------- drivers/firewire/core-transaction.c | 53 +++++++++++++++++++++-------- drivers/firewire/core.h | 9 +++++ include/linux/firewire.h | 5 ++- 4 files changed, 67 insertions(+), 43 deletions(-)
Developers have acknowledged that maintenance of lifetime for fw_transaction structure is effective when handling asynchronous transaction to IEC 61883-1 FCP region, since the core function allows multiples listeners to the region. Some of them needs to access to the payload of request in process context after the callback to listener, while the core function releases the object for the structure just after completing the callbacks to listeners.
One of the listeners is character device. Current implementation of the character device duplicates the object for the payload of transaction, while it's a cost in kernel memory consumption. The lifetime management can reduce it.
The typical way to maintain the lifetime is reference count. This commit uses kref structure as a first step for the purpose.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- drivers/firewire/core-cdev.c | 4 ++-- drivers/firewire/core-transaction.c | 33 +++++++++++++++++++++++++---- drivers/firewire/core.h | 3 +++ 3 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 958aa4662ccb..93dd80d8d4e1 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -826,12 +826,12 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
if (a->length != fw_get_response_length(r->request)) { ret = -EINVAL; - kfree(r->request); + fw_request_put(r->request); goto out; } if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) { ret = -EFAULT; - kfree(r->request); + fw_request_put(r->request); goto out; } fw_send_response(r->card, r->request, a->rcode); diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index af498d767702..83f61cf1aa8f 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -617,6 +617,7 @@ void fw_core_remove_address_handler(struct fw_address_handler *handler) EXPORT_SYMBOL(fw_core_remove_address_handler);
struct fw_request { + struct kref kref; struct fw_packet response; u32 request_header[4]; int ack; @@ -625,13 +626,33 @@ struct fw_request { u32 data[]; };
+void fw_request_get(struct fw_request *request) +{ + kref_get(&request->kref); +} + +static void release_request(struct kref *kref) +{ + struct fw_request *request = container_of(kref, struct fw_request, kref); + + kfree(request); +} + +void fw_request_put(struct fw_request *request) +{ + kref_put(&request->kref, release_request); +} + static void free_response_callback(struct fw_packet *packet, struct fw_card *card, int status) { - struct fw_request *request; + struct fw_request *request = container_of(packet, struct fw_request, response);
- request = container_of(packet, struct fw_request, response); - kfree(request); + // Decrease the reference count since not at in-flight. + fw_request_put(request); + + // Decrease the reference count to release the object. + fw_request_put(request); }
int fw_get_response_length(struct fw_request *r) @@ -782,6 +803,7 @@ static struct fw_request *allocate_request(struct fw_card *card, request = kmalloc(sizeof(*request) + length, GFP_ATOMIC); if (request == NULL) return NULL; + kref_init(&request->kref);
request->response.speed = p->speed; request->response.timestamp = @@ -809,7 +831,7 @@ void fw_send_response(struct fw_card *card, /* unified transaction or broadcast transaction: don't respond */ if (request->ack != ACK_PENDING || HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) { - kfree(request); + fw_request_put(request); return; }
@@ -821,6 +843,9 @@ void fw_send_response(struct fw_card *card, fw_fill_response(&request->response, request->request_header, rcode, NULL, 0);
+ // Increase the reference count so that the object is kept during in-flight. + fw_request_get(request); + card->driver->send_response(card, &request->response); } EXPORT_SYMBOL(fw_send_response); diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 71d5f16f311c..78c99f1d27fa 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -244,6 +244,9 @@ int fw_get_response_length(struct fw_request *request); void fw_fill_response(struct fw_packet *response, u32 *request_header, int rcode, void *payload, size_t length);
+void fw_request_get(struct fw_request *request); +void fw_request_put(struct fw_request *request); + #define FW_PHY_CONFIG_NO_NODE_ID -1 #define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1 void fw_send_phy_config(struct fw_card *card,
In the character device, the listener to address space should distinguish whether the request is to IEC 61883-1 FCP region or not. The user space application needs to access to the object of request in enough later by read(2), while the core function releases the object of request in the FCP case after completing the callback to handler.
The handler guarantees the access safe by some way. It's done by duplication of the object after NULL check to the request, since core function passes NULL in the FCP case. It's inconvenient since the object of request includes some helpful information. It's better to add another way to check whether the request is to FCP region or not.
Conveniently the file of transaction layer includes local implementation for the purpose. This commit moves it to module local file and use it instead of the NULL check, then the result of check is stored to per-client data for the inbound transaction so that the result can be referred by later to release the data.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- drivers/firewire/core-cdev.c | 16 +++++++--------- drivers/firewire/core-transaction.c | 20 ++++++++++---------- drivers/firewire/core.h | 6 ++++++ include/linux/firewire.h | 5 ++--- 4 files changed, 25 insertions(+), 22 deletions(-)
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 93dd80d8d4e1..7fa49e51bae8 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -111,6 +111,7 @@ struct inbound_transaction_resource { struct client_resource resource; struct fw_card *card; struct fw_request *request; + bool is_fcp; void *data; size_t length; }; @@ -643,18 +644,13 @@ static int ioctl_send_request(struct client *client, union ioctl_arg *arg) client->device->max_speed); }
-static inline bool is_fcp_request(struct fw_request *request) -{ - return request == NULL; -} - static void release_request(struct client *client, struct client_resource *resource) { struct inbound_transaction_resource *r = container_of(resource, struct inbound_transaction_resource, resource);
- if (is_fcp_request(r->request)) + if (r->is_fcp) kfree(r->data); else fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR); @@ -669,6 +665,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request, void *payload, size_t length, void *callback_data) { struct address_handler_resource *handler = callback_data; + bool is_fcp = is_in_fcp_region(offset, length); struct inbound_transaction_resource *r; struct inbound_transaction_event *e; size_t event_size0; @@ -685,10 +682,11 @@ static void handle_request(struct fw_card *card, struct fw_request *request,
r->card = card; r->request = request; + r->is_fcp = is_fcp; r->data = payload; r->length = length;
- if (is_fcp_request(request)) { + if (is_fcp) { /* * FIXME: Let core-transaction.c manage a * single reference-counted copy? @@ -743,7 +741,7 @@ static void handle_request(struct fw_card *card, struct fw_request *request, kfree(e); kfree(fcp_frame);
- if (!is_fcp_request(request)) + if (!is_fcp) fw_send_response(card, request, RCODE_CONFLICT_ERROR);
fw_card_put(card); @@ -819,7 +817,7 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
r = container_of(resource, struct inbound_transaction_resource, resource); - if (is_fcp_request(r->request)) { + if (r->is_fcp) { kfree(r->data); goto out; } diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 83f61cf1aa8f..a9f70c96323e 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -535,12 +535,6 @@ const struct fw_address_region fw_unit_space_region = { .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, }; #endif /* 0 */
-static bool is_in_fcp_region(u64 offset, size_t length) -{ - return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && - offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END); -} - /** * fw_core_add_address_handler() - register for incoming requests * @handler: callback @@ -822,12 +816,18 @@ static struct fw_request *allocate_request(struct fw_card *card, return request; }
+/** + * fw_send_response: - send response packet for asynchronous transaction. + * @card: interface to send the response at. + * @request: firewire request data for the transaction. + * @rcode: response code to send. + * + * Submit a response packet into the asynchronous response transmission queue. The @request + * is going to be released when the transmission successfully finishes later. + */ void fw_send_response(struct fw_card *card, struct fw_request *request, int rcode) { - if (WARN_ONCE(!request, "invalid for FCP address handlers")) - return; - /* unified transaction or broadcast transaction: don't respond */ if (request->ack != ACK_PENDING || HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) { @@ -935,7 +935,7 @@ static void handle_fcp_region_request(struct fw_card *card, rcu_read_lock(); list_for_each_entry_rcu(handler, &address_handler_list, link) { if (is_enclosing_handler(handler, offset, request->length)) - handler->address_callback(card, NULL, tcode, + handler->address_callback(card, request, tcode, destination, source, p->generation, offset, request->data, diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index 78c99f1d27fa..eafa4eaae737 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -257,4 +257,10 @@ static inline bool is_ping_packet(u32 *data) return (data[0] & 0xc0ffffff) == 0 && ~data[0] == data[1]; }
+static inline bool is_in_fcp_region(u64 offset, size_t length) +{ + return offset >= (CSR_REGISTER_BASE | CSR_FCP_COMMAND) && + offset + length <= (CSR_REGISTER_BASE | CSR_FCP_END); +} + #endif /* _FIREWIRE_CORE_H */ diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 980019053e54..56505436d159 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -278,9 +278,8 @@ typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode, * Otherwise there is a danger of recursion of inbound and outbound * transactions from and to the local node. * - * The callback is responsible that either fw_send_response() or kfree() - * is called on the @request, except for FCP registers for which the core - * takes care of that. + * The callback is responsible that fw_send_response() is called on the @request, except for FCP + * registers for which the core takes care of that. */ typedef void (*fw_address_callback_t)(struct fw_card *card, struct fw_request *request,
The core function always passes the data of request to the callback of listener in any case. Additionally, the listener can maintain the lifetime of data by reference count. In character device, no need to duplicate the payload of request anymore to copy it to user space.
This commit extends the lifetime of data to obsolete duplication of payload for request in character device.
Signed-off-by: Takashi Sakamoto o-takashi@sakamocchi.jp --- drivers/firewire/core-cdev.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-)
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 7fa49e51bae8..2c16ee8fd842 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -651,7 +651,7 @@ static void release_request(struct client *client, struct inbound_transaction_resource, resource);
if (r->is_fcp) - kfree(r->data); + fw_request_put(r->request); else fw_send_response(r->card, r->request, RCODE_CONFLICT_ERROR);
@@ -669,12 +669,16 @@ static void handle_request(struct fw_card *card, struct fw_request *request, struct inbound_transaction_resource *r; struct inbound_transaction_event *e; size_t event_size0; - void *fcp_frame = NULL; int ret;
/* card may be different from handler->client->device->card */ fw_card_get(card);
+ // Extend the lifetime of data for request so that its payload is safely accessible in + // the process context for the client. + if (is_fcp) + fw_request_get(request); + r = kmalloc(sizeof(*r), GFP_ATOMIC); e = kmalloc(sizeof(*e), GFP_ATOMIC); if (r == NULL || e == NULL) @@ -686,18 +690,6 @@ static void handle_request(struct fw_card *card, struct fw_request *request, r->data = payload; r->length = length;
- if (is_fcp) { - /* - * FIXME: Let core-transaction.c manage a - * single reference-counted copy? - */ - fcp_frame = kmemdup(payload, length, GFP_ATOMIC); - if (fcp_frame == NULL) - goto failed; - - r->data = fcp_frame; - } - r->resource.release = release_request; ret = add_client_resource(handler->client, &r->resource, GFP_ATOMIC); if (ret < 0) @@ -739,10 +731,11 @@ static void handle_request(struct fw_card *card, struct fw_request *request, failed: kfree(r); kfree(e); - kfree(fcp_frame);
if (!is_fcp) fw_send_response(card, request, RCODE_CONFLICT_ERROR); + else + fw_request_put(request);
fw_card_put(card); } @@ -818,7 +811,7 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg) r = container_of(resource, struct inbound_transaction_resource, resource); if (r->is_fcp) { - kfree(r->data); + fw_request_put(r->request); goto out; }
On Fri, 20 Jan 2023 10:03:41 +0100, Takashi Sakamoto wrote:
Hi,
This patch solves long standing issue mentioned by code comment[1] and a commit 281e20323ab7 ("firewire: core: fix use-after-free regression in FCP handler")[2]. This patchset is based on the kernel tree to which another fix is applied[3].
To Iwai-san, I would like to ask you picking them to your local tree, then send them to mainline tree as well as sound patches when the merge window is open for v6.3 kernel, unless any question and objection is posted. (Additionally, I have prepared the other patchset for the subsystem.)
As those are spontaneous small fixes, now I merged all three patches on topic/firewire branch (on top of the for-linus including your previous FireWire core fix), merged back to for-next branch for 6.3.
But, I have no will to keep doing this in a long term. I suppose the best would be that you'd step up as a maintainer for FireWire stack...
thanks,
Takashi
Hi,
On Mon, Jan 23, 2023 at 09:22:51AM +0100, Takashi Iwai wrote:
On Fri, 20 Jan 2023 10:03:41 +0100, Takashi Sakamoto wrote:
Hi,
This patch solves long standing issue mentioned by code comment[1] and a commit 281e20323ab7 ("firewire: core: fix use-after-free regression in FCP handler")[2]. This patchset is based on the kernel tree to which another fix is applied[3].
To Iwai-san, I would like to ask you picking them to your local tree, then send them to mainline tree as well as sound patches when the merge window is open for v6.3 kernel, unless any question and objection is posted. (Additionally, I have prepared the other patchset for the subsystem.)
As those are spontaneous small fixes, now I merged all three patches on topic/firewire branch (on top of the for-linus including your previous FireWire core fix), merged back to for-next branch for 6.3.
Thanks for your applying.
But, I have no will to keep doing this in a long term. I suppose the best would be that you'd step up as a maintainer for FireWire stack...
Indeed. The next patchset is beyond your courtesy. I posted it to LKML with my concern. I'm pleased if you follow to it.
* https://lore.kernel.org/lkml/20230125120301.51585-1-o-takashi@sakamocchi.jp/
thanks,
Takashi
Thanks
Takashi Sakamoto
participants (2)
-
Takashi Iwai
-
Takashi Sakamoto