Skip to content

Commit 13a55d6

Browse files
takaswietiwai
authored andcommitted
firewire: core: use kref structure to maintain lifetime of data for fw_request structure
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 87978e6 commit 13a55d6

File tree

3 files changed

+34
-6
lines changed

3 files changed

+34
-6
lines changed

drivers/firewire/core-cdev.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,12 +826,12 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)
826826

827827
if (a->length != fw_get_response_length(r->request)) {
828828
ret = -EINVAL;
829-
kfree(r->request);
829+
fw_request_put(r->request);
830830
goto out;
831831
}
832832
if (copy_from_user(r->data, u64_to_uptr(a->data), a->length)) {
833833
ret = -EFAULT;
834-
kfree(r->request);
834+
fw_request_put(r->request);
835835
goto out;
836836
}
837837
fw_send_response(r->card, r->request, a->rcode);

drivers/firewire/core-transaction.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ void fw_core_remove_address_handler(struct fw_address_handler *handler)
617617
EXPORT_SYMBOL(fw_core_remove_address_handler);
618618

619619
struct fw_request {
620+
struct kref kref;
620621
struct fw_packet response;
621622
u32 request_header[4];
622623
int ack;
@@ -625,13 +626,33 @@ struct fw_request {
625626
u32 data[];
626627
};
627628

629+
void fw_request_get(struct fw_request *request)
630+
{
631+
kref_get(&request->kref);
632+
}
633+
634+
static void release_request(struct kref *kref)
635+
{
636+
struct fw_request *request = container_of(kref, struct fw_request, kref);
637+
638+
kfree(request);
639+
}
640+
641+
void fw_request_put(struct fw_request *request)
642+
{
643+
kref_put(&request->kref, release_request);
644+
}
645+
628646
static void free_response_callback(struct fw_packet *packet,
629647
struct fw_card *card, int status)
630648
{
631-
struct fw_request *request;
649+
struct fw_request *request = container_of(packet, struct fw_request, response);
632650

633-
request = container_of(packet, struct fw_request, response);
634-
kfree(request);
651+
// Decrease the reference count since not at in-flight.
652+
fw_request_put(request);
653+
654+
// Decrease the reference count to release the object.
655+
fw_request_put(request);
635656
}
636657

637658
int fw_get_response_length(struct fw_request *r)
@@ -782,6 +803,7 @@ static struct fw_request *allocate_request(struct fw_card *card,
782803
request = kmalloc(sizeof(*request) + length, GFP_ATOMIC);
783804
if (request == NULL)
784805
return NULL;
806+
kref_init(&request->kref);
785807

786808
request->response.speed = p->speed;
787809
request->response.timestamp =
@@ -809,7 +831,7 @@ void fw_send_response(struct fw_card *card,
809831
/* unified transaction or broadcast transaction: don't respond */
810832
if (request->ack != ACK_PENDING ||
811833
HEADER_DESTINATION_IS_BROADCAST(request->request_header[0])) {
812-
kfree(request);
834+
fw_request_put(request);
813835
return;
814836
}
815837

@@ -821,6 +843,9 @@ void fw_send_response(struct fw_card *card,
821843
fw_fill_response(&request->response, request->request_header,
822844
rcode, NULL, 0);
823845

846+
// Increase the reference count so that the object is kept during in-flight.
847+
fw_request_get(request);
848+
824849
card->driver->send_response(card, &request->response);
825850
}
826851
EXPORT_SYMBOL(fw_send_response);

drivers/firewire/core.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ int fw_get_response_length(struct fw_request *request);
244244
void fw_fill_response(struct fw_packet *response, u32 *request_header,
245245
int rcode, void *payload, size_t length);
246246

247+
void fw_request_get(struct fw_request *request);
248+
void fw_request_put(struct fw_request *request);
249+
247250
#define FW_PHY_CONFIG_NO_NODE_ID -1
248251
#define FW_PHY_CONFIG_CURRENT_GAP_COUNT -1
249252
void fw_send_phy_config(struct fw_card *card,

0 commit comments

Comments
 (0)