From: Peter Fink <pfink@xxxxxxxxxxxx> Modify struct gs_host_frame to make use of a union and DECLARE_FLEX_ARRAY to be able to store different data (lengths), which will be added in later commits. Store the gs_host_frame length in TX direction (host -> device) in struct gs_can::hf_size_tx and RX direction (device -> host) in struct gs_usb::hf_size_rx so it must be calculated only once. Signed-off-by: Peter Fink <pfink@xxxxxxxxxxxx> Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> --- drivers/net/can/usb/gs_usb.c | 37 +++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index 4bc10264005b..1fe9d9f08c17 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -146,6 +146,10 @@ struct gs_device_bt_const { #define GS_CAN_FLAG_OVERFLOW BIT(0) +struct classic_can { + u8 data[8]; +} __packed; + struct gs_host_frame { u32 echo_id; __le32 can_id; @@ -155,7 +159,9 @@ struct gs_host_frame { u8 flags; u8 reserved; - u8 data[8]; + union { + DECLARE_FLEX_ARRAY(struct classic_can, classic_can); + }; } __packed; /* The GS USB devices make use of the same flags and masks as in * linux/can.h and linux/can/error.h, and no additional mapping is necessary. @@ -187,6 +193,8 @@ struct gs_can { struct can_bittiming_const bt_const; unsigned int channel; /* channel number */ + unsigned int hf_size_tx; + /* This lock prevents a race condition between xmit and receive. */ spinlock_t tx_ctx_lock; struct gs_tx_context tx_context[GS_MAX_TX_URBS]; @@ -200,6 +208,7 @@ struct gs_usb { struct gs_can *canch[GS_MAX_INTF]; struct usb_anchor rx_submitted; struct usb_device *udev; + unsigned int hf_size_rx; u8 active_channels; }; @@ -343,7 +352,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) cf->can_id = le32_to_cpu(hf->can_id); can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); - memcpy(cf->data, hf->data, 8); + memcpy(cf->data, hf->classic_can->data, 8); /* ERROR frames tell us information about the controller */ if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) @@ -398,7 +407,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) resubmit_urb: usb_fill_bulk_urb(urb, usbcan->udev, usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN), - hf, sizeof(struct gs_host_frame), + hf, dev->parent->hf_size_rx, gs_usb_receive_bulk_callback, usbcan); rc = usb_submit_urb(urb, GFP_ATOMIC); @@ -485,7 +494,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, if (!urb) goto nomem_urb; - hf = usb_alloc_coherent(dev->udev, sizeof(*hf), GFP_ATOMIC, + hf = usb_alloc_coherent(dev->udev, dev->hf_size_tx, GFP_ATOMIC, &urb->transfer_dma); if (!hf) { netdev_err(netdev, "No memory left for USB buffer\n"); @@ -509,11 +518,11 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, hf->can_id = cpu_to_le32(cf->can_id); hf->can_dlc = can_get_cc_dlc(cf, dev->can.ctrlmode); - memcpy(hf->data, cf->data, cf->len); + memcpy(hf->classic_can->data, cf->data, cf->len); usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, GSUSB_ENDPOINT_OUT), - hf, sizeof(*hf), + hf, dev->hf_size_tx, gs_usb_xmit_callback, txc); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -531,8 +540,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, gs_free_tx_context(txc); usb_unanchor_urb(urb); - usb_free_coherent(dev->udev, - sizeof(*hf), hf, urb->transfer_dma); + usb_free_coherent(dev->udev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); if (rc == -ENODEV) { netif_device_detach(netdev); @@ -552,7 +561,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; badidx: - usb_free_coherent(dev->udev, sizeof(*hf), hf, urb->transfer_dma); + usb_free_coherent(dev->udev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); nomem_hf: usb_free_urb(urb); @@ -569,6 +579,7 @@ static int gs_can_open(struct net_device *netdev) struct gs_usb *parent = dev->parent; int rc, i; struct gs_device_mode *dm; + struct gs_host_frame *hf; u32 ctrlmode; u32 flags = 0; @@ -576,6 +587,8 @@ static int gs_can_open(struct net_device *netdev) if (rc) return rc; + dev->hf_size_tx = struct_size(hf, classic_can, 1); + if (!parent->active_channels) { for (i = 0; i < GS_MAX_RX_URBS; i++) { struct urb *urb; @@ -588,7 +601,7 @@ static int gs_can_open(struct net_device *netdev) /* alloc rx buffer */ buf = usb_alloc_coherent(dev->udev, - sizeof(struct gs_host_frame), + dev->parent->hf_size_rx, GFP_KERNEL, &urb->transfer_dma); if (!buf) { @@ -604,7 +617,7 @@ static int gs_can_open(struct net_device *netdev) usb_rcvbulkpipe(dev->udev, GSUSB_ENDPOINT_IN), buf, - sizeof(struct gs_host_frame), + dev->parent->hf_size_rx, gs_usb_receive_bulk_callback, parent); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -886,6 +899,7 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); + struct gs_host_frame *hf; struct gs_usb *dev; int rc = -ENOMEM; unsigned int icount, i; @@ -947,6 +961,7 @@ static int gs_usb_probe(struct usb_interface *intf, } init_usb_anchor(&dev->rx_submitted); + dev->hf_size_rx = struct_size(hf, classic_can, 1); usb_set_intfdata(intf, dev); dev->udev = udev; -- 2.34.1