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

firewire: Remove function callback casts

In 1394 OHCI specification, Isochronous Receive DMA context has several
modes. One of mode is 'BufferFill' and Linux FireWire stack uses it to
receive isochronous packets for multiple isochronous channel as
FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL.

The mode is not used by in-kernel driver, while it's available for
userspace. The character device driver in firewire-core includes
cast of function callback for the mode since the type of callback
function is different from the other modes. The case is inconvenient
to effort of Control Flow Integrity builds due to
-Wcast-function-type warning.

This commit removes the cast. A static helper function is newly added
to initialize isochronous context for the mode. The helper function
arranges isochronous context to assign specific callback function
after call of existent kernel API. It's noticeable that the number of
isochronous channel, speed, and the size of header are not required for
the mode. The helper function is used for the mode by character device
driver instead of direct call of existent kernel API.

The same goal can be achieved (in the ioctl_create_iso_context function)
without this helper function as follows:
- Call the fw_iso_context_create function passing NULL to the callback
parameter.
- Then setting the context->callback.sc or context->callback.mc
variables based on the a->type value.

However using the helper function created in this patch makes code more
clear and declarative. This way avoid the call to a function with one
purpose to achieved another one.

Co-developed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Co-developed-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Oscar Carter <oscar.carter@gmx.com>
Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Testeb-by: Takashi Sakamoto<o-takashi@sakamocchi.jp>
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>

authored by

Oscar Carter and committed by
Gustavo A. R. Silva
ebe4560e 71e4bbca

+33 -10
+26 -6
drivers/firewire/core-cdev.c
··· 10 10 #include <linux/delay.h> 11 11 #include <linux/device.h> 12 12 #include <linux/dma-mapping.h> 13 + #include <linux/err.h> 13 14 #include <linux/errno.h> 14 15 #include <linux/firewire.h> 15 16 #include <linux/firewire-cdev.h> ··· 954 953 return DMA_FROM_DEVICE; 955 954 } 956 955 956 + static struct fw_iso_context *fw_iso_mc_context_create(struct fw_card *card, 957 + fw_iso_mc_callback_t callback, 958 + void *callback_data) 959 + { 960 + struct fw_iso_context *ctx; 961 + 962 + ctx = fw_iso_context_create(card, FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL, 963 + 0, 0, 0, NULL, callback_data); 964 + if (!IS_ERR(ctx)) 965 + ctx->callback.mc = callback; 966 + 967 + return ctx; 968 + } 969 + 957 970 static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) 958 971 { 959 972 struct fw_cdev_create_iso_context *a = &arg->create_iso_context; 960 973 struct fw_iso_context *context; 961 - fw_iso_callback_t cb; 974 + union fw_iso_callback cb; 962 975 int ret; 963 976 964 977 BUILD_BUG_ON(FW_CDEV_ISO_CONTEXT_TRANSMIT != FW_ISO_CONTEXT_TRANSMIT || ··· 985 970 if (a->speed > SCODE_3200 || a->channel > 63) 986 971 return -EINVAL; 987 972 988 - cb = iso_callback; 973 + cb.sc = iso_callback; 989 974 break; 990 975 991 976 case FW_ISO_CONTEXT_RECEIVE: ··· 993 978 a->channel > 63) 994 979 return -EINVAL; 995 980 996 - cb = iso_callback; 981 + cb.sc = iso_callback; 997 982 break; 998 983 999 984 case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: 1000 - cb = (fw_iso_callback_t)iso_mc_callback; 985 + cb.mc = iso_mc_callback; 1001 986 break; 1002 987 1003 988 default: 1004 989 return -EINVAL; 1005 990 } 1006 991 1007 - context = fw_iso_context_create(client->device->card, a->type, 1008 - a->channel, a->speed, a->header_size, cb, client); 992 + if (a->type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) 993 + context = fw_iso_mc_context_create(client->device->card, cb.mc, 994 + client); 995 + else 996 + context = fw_iso_context_create(client->device->card, a->type, 997 + a->channel, a->speed, 998 + a->header_size, cb.sc, client); 1009 999 if (IS_ERR(context)) 1010 1000 return PTR_ERR(context); 1011 1001 if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW)
+7 -4
include/linux/firewire.h
··· 436 436 void *header, void *data); 437 437 typedef void (*fw_iso_mc_callback_t)(struct fw_iso_context *context, 438 438 dma_addr_t completed, void *data); 439 + 440 + union fw_iso_callback { 441 + fw_iso_callback_t sc; 442 + fw_iso_mc_callback_t mc; 443 + }; 444 + 439 445 struct fw_iso_context { 440 446 struct fw_card *card; 441 447 int type; ··· 449 443 int speed; 450 444 bool drop_overflow_headers; 451 445 size_t header_size; 452 - union { 453 - fw_iso_callback_t sc; 454 - fw_iso_mc_callback_t mc; 455 - } callback; 446 + union fw_iso_callback callback; 456 447 void *callback_data; 457 448 }; 458 449