Commit c359931d authored by Peter Fink's avatar Peter Fink Committed by Marc Kleine-Budde

can: gs_usb: use union and FLEX_ARRAY for data in struct gs_host_frame

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.

Link: https://lore.kernel.org/all/20220309124132.291861-15-mkl@pengutronix.deSigned-off-by: default avatarPeter Fink <pfink@christ-es.de>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent e10ab8b3
...@@ -146,6 +146,10 @@ struct gs_device_bt_const { ...@@ -146,6 +146,10 @@ struct gs_device_bt_const {
#define GS_CAN_FLAG_OVERFLOW BIT(0) #define GS_CAN_FLAG_OVERFLOW BIT(0)
struct classic_can {
u8 data[8];
} __packed;
struct gs_host_frame { struct gs_host_frame {
u32 echo_id; u32 echo_id;
__le32 can_id; __le32 can_id;
...@@ -155,7 +159,9 @@ struct gs_host_frame { ...@@ -155,7 +159,9 @@ struct gs_host_frame {
u8 flags; u8 flags;
u8 reserved; u8 reserved;
u8 data[8]; union {
DECLARE_FLEX_ARRAY(struct classic_can, classic_can);
};
} __packed; } __packed;
/* The GS USB devices make use of the same flags and masks as in /* 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. * linux/can.h and linux/can/error.h, and no additional mapping is necessary.
...@@ -187,6 +193,8 @@ struct gs_can { ...@@ -187,6 +193,8 @@ struct gs_can {
struct can_bittiming_const bt_const; struct can_bittiming_const bt_const;
unsigned int channel; /* channel number */ unsigned int channel; /* channel number */
unsigned int hf_size_tx;
/* This lock prevents a race condition between xmit and receive. */ /* This lock prevents a race condition between xmit and receive. */
spinlock_t tx_ctx_lock; spinlock_t tx_ctx_lock;
struct gs_tx_context tx_context[GS_MAX_TX_URBS]; struct gs_tx_context tx_context[GS_MAX_TX_URBS];
...@@ -200,6 +208,7 @@ struct gs_usb { ...@@ -200,6 +208,7 @@ struct gs_usb {
struct gs_can *canch[GS_MAX_INTF]; struct gs_can *canch[GS_MAX_INTF];
struct usb_anchor rx_submitted; struct usb_anchor rx_submitted;
struct usb_device *udev; struct usb_device *udev;
unsigned int hf_size_rx;
u8 active_channels; u8 active_channels;
}; };
...@@ -343,7 +352,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) ...@@ -343,7 +352,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
cf->can_id = le32_to_cpu(hf->can_id); cf->can_id = le32_to_cpu(hf->can_id);
can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); 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 */ /* ERROR frames tell us information about the controller */
if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG)
...@@ -398,7 +407,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) ...@@ -398,7 +407,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
resubmit_urb: resubmit_urb:
usb_fill_bulk_urb(urb, usbcan->udev, usb_fill_bulk_urb(urb, usbcan->udev,
usb_rcvbulkpipe(usbcan->udev, GSUSB_ENDPOINT_IN), 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); gs_usb_receive_bulk_callback, usbcan);
rc = usb_submit_urb(urb, GFP_ATOMIC); rc = usb_submit_urb(urb, GFP_ATOMIC);
...@@ -485,7 +494,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, ...@@ -485,7 +494,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
if (!urb) if (!urb)
goto nomem_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); &urb->transfer_dma);
if (!hf) { if (!hf) {
netdev_err(netdev, "No memory left for USB buffer\n"); 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, ...@@ -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_id = cpu_to_le32(cf->can_id);
hf->can_dlc = can_get_cc_dlc(cf, dev->can.ctrlmode); 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_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, GSUSB_ENDPOINT_OUT), usb_sndbulkpipe(dev->udev, GSUSB_ENDPOINT_OUT),
hf, sizeof(*hf), hf, dev->hf_size_tx,
gs_usb_xmit_callback, txc); gs_usb_xmit_callback, txc);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
...@@ -531,8 +540,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, ...@@ -531,8 +540,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
gs_free_tx_context(txc); gs_free_tx_context(txc);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
usb_free_coherent(dev->udev, usb_free_coherent(dev->udev, urb->transfer_buffer_length,
sizeof(*hf), hf, urb->transfer_dma); urb->transfer_buffer, urb->transfer_dma);
if (rc == -ENODEV) { if (rc == -ENODEV) {
netif_device_detach(netdev); netif_device_detach(netdev);
...@@ -552,7 +561,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, ...@@ -552,7 +561,8 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK; return NETDEV_TX_OK;
badidx: 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: nomem_hf:
usb_free_urb(urb); usb_free_urb(urb);
...@@ -569,6 +579,7 @@ static int gs_can_open(struct net_device *netdev) ...@@ -569,6 +579,7 @@ static int gs_can_open(struct net_device *netdev)
struct gs_usb *parent = dev->parent; struct gs_usb *parent = dev->parent;
int rc, i; int rc, i;
struct gs_device_mode *dm; struct gs_device_mode *dm;
struct gs_host_frame *hf;
u32 ctrlmode; u32 ctrlmode;
u32 flags = 0; u32 flags = 0;
...@@ -576,6 +587,8 @@ static int gs_can_open(struct net_device *netdev) ...@@ -576,6 +587,8 @@ static int gs_can_open(struct net_device *netdev)
if (rc) if (rc)
return rc; return rc;
dev->hf_size_tx = struct_size(hf, classic_can, 1);
if (!parent->active_channels) { if (!parent->active_channels) {
for (i = 0; i < GS_MAX_RX_URBS; i++) { for (i = 0; i < GS_MAX_RX_URBS; i++) {
struct urb *urb; struct urb *urb;
...@@ -588,7 +601,7 @@ static int gs_can_open(struct net_device *netdev) ...@@ -588,7 +601,7 @@ static int gs_can_open(struct net_device *netdev)
/* alloc rx buffer */ /* alloc rx buffer */
buf = usb_alloc_coherent(dev->udev, buf = usb_alloc_coherent(dev->udev,
sizeof(struct gs_host_frame), dev->parent->hf_size_rx,
GFP_KERNEL, GFP_KERNEL,
&urb->transfer_dma); &urb->transfer_dma);
if (!buf) { if (!buf) {
...@@ -604,7 +617,7 @@ static int gs_can_open(struct net_device *netdev) ...@@ -604,7 +617,7 @@ static int gs_can_open(struct net_device *netdev)
usb_rcvbulkpipe(dev->udev, usb_rcvbulkpipe(dev->udev,
GSUSB_ENDPOINT_IN), GSUSB_ENDPOINT_IN),
buf, buf,
sizeof(struct gs_host_frame), dev->parent->hf_size_rx,
gs_usb_receive_bulk_callback, parent); gs_usb_receive_bulk_callback, parent);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
...@@ -886,6 +899,7 @@ static int gs_usb_probe(struct usb_interface *intf, ...@@ -886,6 +899,7 @@ static int gs_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
struct gs_host_frame *hf;
struct gs_usb *dev; struct gs_usb *dev;
int rc = -ENOMEM; int rc = -ENOMEM;
unsigned int icount, i; unsigned int icount, i;
...@@ -947,6 +961,7 @@ static int gs_usb_probe(struct usb_interface *intf, ...@@ -947,6 +961,7 @@ static int gs_usb_probe(struct usb_interface *intf,
} }
init_usb_anchor(&dev->rx_submitted); init_usb_anchor(&dev->rx_submitted);
dev->hf_size_rx = struct_size(hf, classic_can, 1);
usb_set_intfdata(intf, dev); usb_set_intfdata(intf, dev);
dev->udev = udev; dev->udev = udev;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment