#define GS_CAN_FLAG_OVERFLOW BIT(0)
+struct classic_can {
+ u8 data[8];
+} __packed;
+
struct gs_host_frame {
u32 echo_id;
__le32 can_id;
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.
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];
struct gs_can *canch[GS_MAX_INTF];
struct usb_anchor rx_submitted;
struct usb_device *udev;
+ unsigned int hf_size_rx;
u8 active_channels;
};
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)
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);
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");
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;
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);
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);
struct gs_usb *parent = dev->parent;
int rc, i;
struct gs_device_mode *dm;
+ struct gs_host_frame *hf;
u32 ctrlmode;
u32 flags = 0;
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;
/* 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) {
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;
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;
}
init_usb_anchor(&dev->rx_submitted);
+ dev->hf_size_rx = struct_size(hf, classic_can, 1);
usb_set_intfdata(intf, dev);
dev->udev = udev;