// SPDX-License-Identifier: GPL-2.0 
 | 
/* Parts of this driver are based on the following: 
 | 
 *  - Kvaser linux leaf driver (version 4.78) 
 | 
 *  - CAN driver for esd CAN-USB/2 
 | 
 *  - Kvaser linux usbcanII driver (version 5.3) 
 | 
 * 
 | 
 * Copyright (C) 2002-2018 KVASER AB, Sweden. All rights reserved. 
 | 
 * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh 
 | 
 * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be> 
 | 
 * Copyright (C) 2015 Valeo S.A. 
 | 
 */ 
 | 
  
 | 
#include <linux/completion.h> 
 | 
#include <linux/device.h> 
 | 
#include <linux/gfp.h> 
 | 
#include <linux/jiffies.h> 
 | 
#include <linux/kernel.h> 
 | 
#include <linux/netdevice.h> 
 | 
#include <linux/spinlock.h> 
 | 
#include <linux/string.h> 
 | 
#include <linux/types.h> 
 | 
#include <linux/usb.h> 
 | 
  
 | 
#include <linux/can.h> 
 | 
#include <linux/can/dev.h> 
 | 
#include <linux/can/error.h> 
 | 
#include <linux/can/netlink.h> 
 | 
  
 | 
#include "kvaser_usb.h" 
 | 
  
 | 
#define MAX_USBCAN_NET_DEVICES        2 
 | 
  
 | 
/* Command header size */ 
 | 
#define CMD_HEADER_LEN            2 
 | 
  
 | 
/* Kvaser CAN message flags */ 
 | 
#define MSG_FLAG_ERROR_FRAME        BIT(0) 
 | 
#define MSG_FLAG_OVERRUN        BIT(1) 
 | 
#define MSG_FLAG_NERR            BIT(2) 
 | 
#define MSG_FLAG_WAKEUP            BIT(3) 
 | 
#define MSG_FLAG_REMOTE_FRAME        BIT(4) 
 | 
#define MSG_FLAG_RESERVED        BIT(5) 
 | 
#define MSG_FLAG_TX_ACK            BIT(6) 
 | 
#define MSG_FLAG_TX_REQUEST        BIT(7) 
 | 
  
 | 
/* CAN states (M16C CxSTRH register) */ 
 | 
#define M16C_STATE_BUS_RESET        BIT(0) 
 | 
#define M16C_STATE_BUS_ERROR        BIT(4) 
 | 
#define M16C_STATE_BUS_PASSIVE        BIT(5) 
 | 
#define M16C_STATE_BUS_OFF        BIT(6) 
 | 
  
 | 
/* Leaf/usbcan command ids */ 
 | 
#define CMD_RX_STD_MESSAGE        12 
 | 
#define CMD_TX_STD_MESSAGE        13 
 | 
#define CMD_RX_EXT_MESSAGE        14 
 | 
#define CMD_TX_EXT_MESSAGE        15 
 | 
#define CMD_SET_BUS_PARAMS        16 
 | 
#define CMD_CHIP_STATE_EVENT        20 
 | 
#define CMD_SET_CTRL_MODE        21 
 | 
#define CMD_RESET_CHIP            24 
 | 
#define CMD_START_CHIP            26 
 | 
#define CMD_START_CHIP_REPLY        27 
 | 
#define CMD_STOP_CHIP            28 
 | 
#define CMD_STOP_CHIP_REPLY        29 
 | 
  
 | 
#define CMD_USBCAN_CLOCK_OVERFLOW_EVENT    33 
 | 
  
 | 
#define CMD_GET_CARD_INFO        34 
 | 
#define CMD_GET_CARD_INFO_REPLY        35 
 | 
#define CMD_GET_SOFTWARE_INFO        38 
 | 
#define CMD_GET_SOFTWARE_INFO_REPLY    39 
 | 
#define CMD_FLUSH_QUEUE            48 
 | 
#define CMD_TX_ACKNOWLEDGE        50 
 | 
#define CMD_CAN_ERROR_EVENT        51 
 | 
#define CMD_FLUSH_QUEUE_REPLY        68 
 | 
  
 | 
#define CMD_LEAF_LOG_MESSAGE        106 
 | 
  
 | 
/* Leaf frequency options */ 
 | 
#define KVASER_USB_LEAF_SWOPTION_FREQ_MASK 0x60 
 | 
#define KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK 0 
 | 
#define KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK BIT(5) 
 | 
#define KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK BIT(6) 
 | 
  
 | 
/* error factors */ 
 | 
#define M16C_EF_ACKE            BIT(0) 
 | 
#define M16C_EF_CRCE            BIT(1) 
 | 
#define M16C_EF_FORME            BIT(2) 
 | 
#define M16C_EF_STFE            BIT(3) 
 | 
#define M16C_EF_BITE0            BIT(4) 
 | 
#define M16C_EF_BITE1            BIT(5) 
 | 
#define M16C_EF_RCVE            BIT(6) 
 | 
#define M16C_EF_TRE            BIT(7) 
 | 
  
 | 
/* Only Leaf-based devices can report M16C error factors, 
 | 
 * thus define our own error status flags for USBCANII 
 | 
 */ 
 | 
#define USBCAN_ERROR_STATE_NONE        0 
 | 
#define USBCAN_ERROR_STATE_TX_ERROR    BIT(0) 
 | 
#define USBCAN_ERROR_STATE_RX_ERROR    BIT(1) 
 | 
#define USBCAN_ERROR_STATE_BUSERROR    BIT(2) 
 | 
  
 | 
/* ctrl modes */ 
 | 
#define KVASER_CTRL_MODE_NORMAL        1 
 | 
#define KVASER_CTRL_MODE_SILENT        2 
 | 
#define KVASER_CTRL_MODE_SELFRECEPTION    3 
 | 
#define KVASER_CTRL_MODE_OFF        4 
 | 
  
 | 
/* Extended CAN identifier flag */ 
 | 
#define KVASER_EXTENDED_FRAME        BIT(31) 
 | 
  
 | 
struct kvaser_cmd_simple { 
 | 
    u8 tid; 
 | 
    u8 channel; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd_cardinfo { 
 | 
    u8 tid; 
 | 
    u8 nchannels; 
 | 
    __le32 serial_number; 
 | 
    __le32 padding0; 
 | 
    __le32 clock_resolution; 
 | 
    __le32 mfgdate; 
 | 
    u8 ean[8]; 
 | 
    u8 hw_revision; 
 | 
    union { 
 | 
        struct { 
 | 
            u8 usb_hs_mode; 
 | 
        } __packed leaf1; 
 | 
        struct { 
 | 
            u8 padding; 
 | 
        } __packed usbcan1; 
 | 
    } __packed; 
 | 
    __le16 padding1; 
 | 
} __packed; 
 | 
  
 | 
struct leaf_cmd_softinfo { 
 | 
    u8 tid; 
 | 
    u8 padding0; 
 | 
    __le32 sw_options; 
 | 
    __le32 fw_version; 
 | 
    __le16 max_outstanding_tx; 
 | 
    __le16 padding1[9]; 
 | 
} __packed; 
 | 
  
 | 
struct usbcan_cmd_softinfo { 
 | 
    u8 tid; 
 | 
    u8 fw_name[5]; 
 | 
    __le16 max_outstanding_tx; 
 | 
    u8 padding[6]; 
 | 
    __le32 fw_version; 
 | 
    __le16 checksum; 
 | 
    __le16 sw_options; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd_busparams { 
 | 
    u8 tid; 
 | 
    u8 channel; 
 | 
    __le32 bitrate; 
 | 
    u8 tseg1; 
 | 
    u8 tseg2; 
 | 
    u8 sjw; 
 | 
    u8 no_samp; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd_tx_can { 
 | 
    u8 channel; 
 | 
    u8 tid; 
 | 
    u8 data[14]; 
 | 
    union { 
 | 
        struct { 
 | 
            u8 padding; 
 | 
            u8 flags; 
 | 
        } __packed leaf; 
 | 
        struct { 
 | 
            u8 flags; 
 | 
            u8 padding; 
 | 
        } __packed usbcan; 
 | 
    } __packed; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd_rx_can_header { 
 | 
    u8 channel; 
 | 
    u8 flag; 
 | 
} __packed; 
 | 
  
 | 
struct leaf_cmd_rx_can { 
 | 
    u8 channel; 
 | 
    u8 flag; 
 | 
  
 | 
    __le16 time[3]; 
 | 
    u8 data[14]; 
 | 
} __packed; 
 | 
  
 | 
struct usbcan_cmd_rx_can { 
 | 
    u8 channel; 
 | 
    u8 flag; 
 | 
  
 | 
    u8 data[14]; 
 | 
    __le16 time; 
 | 
} __packed; 
 | 
  
 | 
struct leaf_cmd_chip_state_event { 
 | 
    u8 tid; 
 | 
    u8 channel; 
 | 
  
 | 
    __le16 time[3]; 
 | 
    u8 tx_errors_count; 
 | 
    u8 rx_errors_count; 
 | 
  
 | 
    u8 status; 
 | 
    u8 padding[3]; 
 | 
} __packed; 
 | 
  
 | 
struct usbcan_cmd_chip_state_event { 
 | 
    u8 tid; 
 | 
    u8 channel; 
 | 
  
 | 
    u8 tx_errors_count; 
 | 
    u8 rx_errors_count; 
 | 
    __le16 time; 
 | 
  
 | 
    u8 status; 
 | 
    u8 padding[3]; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd_tx_acknowledge_header { 
 | 
    u8 channel; 
 | 
    u8 tid; 
 | 
} __packed; 
 | 
  
 | 
struct leaf_cmd_error_event { 
 | 
    u8 tid; 
 | 
    u8 flags; 
 | 
    __le16 time[3]; 
 | 
    u8 channel; 
 | 
    u8 padding; 
 | 
    u8 tx_errors_count; 
 | 
    u8 rx_errors_count; 
 | 
    u8 status; 
 | 
    u8 error_factor; 
 | 
} __packed; 
 | 
  
 | 
struct usbcan_cmd_error_event { 
 | 
    u8 tid; 
 | 
    u8 padding; 
 | 
    u8 tx_errors_count_ch0; 
 | 
    u8 rx_errors_count_ch0; 
 | 
    u8 tx_errors_count_ch1; 
 | 
    u8 rx_errors_count_ch1; 
 | 
    u8 status_ch0; 
 | 
    u8 status_ch1; 
 | 
    __le16 time; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd_ctrl_mode { 
 | 
    u8 tid; 
 | 
    u8 channel; 
 | 
    u8 ctrl_mode; 
 | 
    u8 padding[3]; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd_flush_queue { 
 | 
    u8 tid; 
 | 
    u8 channel; 
 | 
    u8 flags; 
 | 
    u8 padding[3]; 
 | 
} __packed; 
 | 
  
 | 
struct leaf_cmd_log_message { 
 | 
    u8 channel; 
 | 
    u8 flags; 
 | 
    __le16 time[3]; 
 | 
    u8 dlc; 
 | 
    u8 time_offset; 
 | 
    __le32 id; 
 | 
    u8 data[8]; 
 | 
} __packed; 
 | 
  
 | 
struct kvaser_cmd { 
 | 
    u8 len; 
 | 
    u8 id; 
 | 
    union    { 
 | 
        struct kvaser_cmd_simple simple; 
 | 
        struct kvaser_cmd_cardinfo cardinfo; 
 | 
        struct kvaser_cmd_busparams busparams; 
 | 
  
 | 
        struct kvaser_cmd_rx_can_header rx_can_header; 
 | 
        struct kvaser_cmd_tx_acknowledge_header tx_acknowledge_header; 
 | 
  
 | 
        union { 
 | 
            struct leaf_cmd_softinfo softinfo; 
 | 
            struct leaf_cmd_rx_can rx_can; 
 | 
            struct leaf_cmd_chip_state_event chip_state_event; 
 | 
            struct leaf_cmd_error_event error_event; 
 | 
            struct leaf_cmd_log_message log_message; 
 | 
        } __packed leaf; 
 | 
  
 | 
        union { 
 | 
            struct usbcan_cmd_softinfo softinfo; 
 | 
            struct usbcan_cmd_rx_can rx_can; 
 | 
            struct usbcan_cmd_chip_state_event chip_state_event; 
 | 
            struct usbcan_cmd_error_event error_event; 
 | 
        } __packed usbcan; 
 | 
  
 | 
        struct kvaser_cmd_tx_can tx_can; 
 | 
        struct kvaser_cmd_ctrl_mode ctrl_mode; 
 | 
        struct kvaser_cmd_flush_queue flush_queue; 
 | 
    } u; 
 | 
} __packed; 
 | 
  
 | 
#define CMD_SIZE_ANY 0xff 
 | 
#define kvaser_fsize(field) sizeof_field(struct kvaser_cmd, field) 
 | 
  
 | 
static const u8 kvaser_usb_leaf_cmd_sizes_leaf[] = { 
 | 
    [CMD_START_CHIP_REPLY]        = kvaser_fsize(u.simple), 
 | 
    [CMD_STOP_CHIP_REPLY]        = kvaser_fsize(u.simple), 
 | 
    [CMD_GET_CARD_INFO_REPLY]    = kvaser_fsize(u.cardinfo), 
 | 
    [CMD_TX_ACKNOWLEDGE]        = kvaser_fsize(u.tx_acknowledge_header), 
 | 
    [CMD_GET_SOFTWARE_INFO_REPLY]    = kvaser_fsize(u.leaf.softinfo), 
 | 
    [CMD_RX_STD_MESSAGE]        = kvaser_fsize(u.leaf.rx_can), 
 | 
    [CMD_RX_EXT_MESSAGE]        = kvaser_fsize(u.leaf.rx_can), 
 | 
    [CMD_LEAF_LOG_MESSAGE]        = kvaser_fsize(u.leaf.log_message), 
 | 
    [CMD_CHIP_STATE_EVENT]        = kvaser_fsize(u.leaf.chip_state_event), 
 | 
    [CMD_CAN_ERROR_EVENT]        = kvaser_fsize(u.leaf.error_event), 
 | 
    /* ignored events: */ 
 | 
    [CMD_FLUSH_QUEUE_REPLY]        = CMD_SIZE_ANY, 
 | 
}; 
 | 
  
 | 
static const u8 kvaser_usb_leaf_cmd_sizes_usbcan[] = { 
 | 
    [CMD_START_CHIP_REPLY]        = kvaser_fsize(u.simple), 
 | 
    [CMD_STOP_CHIP_REPLY]        = kvaser_fsize(u.simple), 
 | 
    [CMD_GET_CARD_INFO_REPLY]    = kvaser_fsize(u.cardinfo), 
 | 
    [CMD_TX_ACKNOWLEDGE]        = kvaser_fsize(u.tx_acknowledge_header), 
 | 
    [CMD_GET_SOFTWARE_INFO_REPLY]    = kvaser_fsize(u.usbcan.softinfo), 
 | 
    [CMD_RX_STD_MESSAGE]        = kvaser_fsize(u.usbcan.rx_can), 
 | 
    [CMD_RX_EXT_MESSAGE]        = kvaser_fsize(u.usbcan.rx_can), 
 | 
    [CMD_CHIP_STATE_EVENT]        = kvaser_fsize(u.usbcan.chip_state_event), 
 | 
    [CMD_CAN_ERROR_EVENT]        = kvaser_fsize(u.usbcan.error_event), 
 | 
    /* ignored events: */ 
 | 
    [CMD_USBCAN_CLOCK_OVERFLOW_EVENT] = CMD_SIZE_ANY, 
 | 
}; 
 | 
  
 | 
/* Summary of a kvaser error event, for a unified Leaf/Usbcan error 
 | 
 * handling. Some discrepancies between the two families exist: 
 | 
 * 
 | 
 * - USBCAN firmware does not report M16C "error factors" 
 | 
 * - USBCAN controllers has difficulties reporting if the raised error 
 | 
 *   event is for ch0 or ch1. They leave such arbitration to the OS 
 | 
 *   driver by letting it compare error counters with previous values 
 | 
 *   and decide the error event's channel. Thus for USBCAN, the channel 
 | 
 *   field is only advisory. 
 | 
 */ 
 | 
struct kvaser_usb_err_summary { 
 | 
    u8 channel, status, txerr, rxerr; 
 | 
    union { 
 | 
        struct { 
 | 
            u8 error_factor; 
 | 
        } leaf; 
 | 
        struct { 
 | 
            u8 other_ch_status; 
 | 
            u8 error_state; 
 | 
        } usbcan; 
 | 
    }; 
 | 
}; 
 | 
  
 | 
static const struct can_bittiming_const kvaser_usb_leaf_m16c_bittiming_const = { 
 | 
    .name = "kvaser_usb_ucii", 
 | 
    .tseg1_min = 4, 
 | 
    .tseg1_max = 16, 
 | 
    .tseg2_min = 2, 
 | 
    .tseg2_max = 8, 
 | 
    .sjw_max = 4, 
 | 
    .brp_min = 1, 
 | 
    .brp_max = 16, 
 | 
    .brp_inc = 1, 
 | 
}; 
 | 
  
 | 
static const struct can_bittiming_const kvaser_usb_leaf_m32c_bittiming_const = { 
 | 
    .name = "kvaser_usb_leaf", 
 | 
    .tseg1_min = 3, 
 | 
    .tseg1_max = 16, 
 | 
    .tseg2_min = 2, 
 | 
    .tseg2_max = 8, 
 | 
    .sjw_max = 4, 
 | 
    .brp_min = 2, 
 | 
    .brp_max = 128, 
 | 
    .brp_inc = 2, 
 | 
}; 
 | 
  
 | 
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_usbcan_dev_cfg = { 
 | 
    .clock = { 
 | 
        .freq = 8000000, 
 | 
    }, 
 | 
    .timestamp_freq = 1, 
 | 
    .bittiming_const = &kvaser_usb_leaf_m16c_bittiming_const, 
 | 
}; 
 | 
  
 | 
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_m32c_dev_cfg = { 
 | 
    .clock = { 
 | 
        .freq = 16000000, 
 | 
    }, 
 | 
    .timestamp_freq = 1, 
 | 
    .bittiming_const = &kvaser_usb_leaf_m32c_bittiming_const, 
 | 
}; 
 | 
  
 | 
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_16mhz = { 
 | 
    .clock = { 
 | 
        .freq = 16000000, 
 | 
    }, 
 | 
    .timestamp_freq = 1, 
 | 
    .bittiming_const = &kvaser_usb_flexc_bittiming_const, 
 | 
}; 
 | 
  
 | 
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_24mhz = { 
 | 
    .clock = { 
 | 
        .freq = 24000000, 
 | 
    }, 
 | 
    .timestamp_freq = 1, 
 | 
    .bittiming_const = &kvaser_usb_flexc_bittiming_const, 
 | 
}; 
 | 
  
 | 
static const struct kvaser_usb_dev_cfg kvaser_usb_leaf_imx_dev_cfg_32mhz = { 
 | 
    .clock = { 
 | 
        .freq = 32000000, 
 | 
    }, 
 | 
    .timestamp_freq = 1, 
 | 
    .bittiming_const = &kvaser_usb_flexc_bittiming_const, 
 | 
}; 
 | 
  
 | 
static int kvaser_usb_leaf_verify_size(const struct kvaser_usb *dev, 
 | 
                       const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    /* buffer size >= cmd->len ensured by caller */ 
 | 
    u8 min_size = 0; 
 | 
  
 | 
    switch (dev->driver_info->family) { 
 | 
    case KVASER_LEAF: 
 | 
        if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_leaf)) 
 | 
            min_size = kvaser_usb_leaf_cmd_sizes_leaf[cmd->id]; 
 | 
        break; 
 | 
    case KVASER_USBCAN: 
 | 
        if (cmd->id < ARRAY_SIZE(kvaser_usb_leaf_cmd_sizes_usbcan)) 
 | 
            min_size = kvaser_usb_leaf_cmd_sizes_usbcan[cmd->id]; 
 | 
        break; 
 | 
    } 
 | 
  
 | 
    if (min_size == CMD_SIZE_ANY) 
 | 
        return 0; 
 | 
  
 | 
    if (min_size) { 
 | 
        min_size += CMD_HEADER_LEN; 
 | 
        if (cmd->len >= min_size) 
 | 
            return 0; 
 | 
  
 | 
        dev_err_ratelimited(&dev->intf->dev, 
 | 
                    "Received command %u too short (size %u, needed %u)", 
 | 
                    cmd->id, cmd->len, min_size); 
 | 
        return -EIO; 
 | 
    } 
 | 
  
 | 
    dev_warn_ratelimited(&dev->intf->dev, 
 | 
                 "Unhandled command (%d, size %d)\n", 
 | 
                 cmd->id, cmd->len); 
 | 
    return -EINVAL; 
 | 
} 
 | 
  
 | 
static void * 
 | 
kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, 
 | 
                 const struct sk_buff *skb, int *frame_len, 
 | 
                 int *cmd_len, u16 transid) 
 | 
{ 
 | 
    struct kvaser_usb *dev = priv->dev; 
 | 
    struct kvaser_cmd *cmd; 
 | 
    u8 *cmd_tx_can_flags = NULL;        /* GCC */ 
 | 
    struct can_frame *cf = (struct can_frame *)skb->data; 
 | 
  
 | 
    *frame_len = cf->can_dlc; 
 | 
  
 | 
    cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC); 
 | 
    if (cmd) { 
 | 
        cmd->u.tx_can.tid = transid & 0xff; 
 | 
        cmd->len = *cmd_len = CMD_HEADER_LEN + 
 | 
                      sizeof(struct kvaser_cmd_tx_can); 
 | 
        cmd->u.tx_can.channel = priv->channel; 
 | 
  
 | 
        switch (dev->driver_info->family) { 
 | 
        case KVASER_LEAF: 
 | 
            cmd_tx_can_flags = &cmd->u.tx_can.leaf.flags; 
 | 
            break; 
 | 
        case KVASER_USBCAN: 
 | 
            cmd_tx_can_flags = &cmd->u.tx_can.usbcan.flags; 
 | 
            break; 
 | 
        } 
 | 
  
 | 
        *cmd_tx_can_flags = 0; 
 | 
  
 | 
        if (cf->can_id & CAN_EFF_FLAG) { 
 | 
            cmd->id = CMD_TX_EXT_MESSAGE; 
 | 
            cmd->u.tx_can.data[0] = (cf->can_id >> 24) & 0x1f; 
 | 
            cmd->u.tx_can.data[1] = (cf->can_id >> 18) & 0x3f; 
 | 
            cmd->u.tx_can.data[2] = (cf->can_id >> 14) & 0x0f; 
 | 
            cmd->u.tx_can.data[3] = (cf->can_id >> 6) & 0xff; 
 | 
            cmd->u.tx_can.data[4] = cf->can_id & 0x3f; 
 | 
        } else { 
 | 
            cmd->id = CMD_TX_STD_MESSAGE; 
 | 
            cmd->u.tx_can.data[0] = (cf->can_id >> 6) & 0x1f; 
 | 
            cmd->u.tx_can.data[1] = cf->can_id & 0x3f; 
 | 
        } 
 | 
  
 | 
        cmd->u.tx_can.data[5] = cf->can_dlc; 
 | 
        memcpy(&cmd->u.tx_can.data[6], cf->data, cf->can_dlc); 
 | 
  
 | 
        if (cf->can_id & CAN_RTR_FLAG) 
 | 
            *cmd_tx_can_flags |= MSG_FLAG_REMOTE_FRAME; 
 | 
    } 
 | 
    return cmd; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_wait_cmd(const struct kvaser_usb *dev, u8 id, 
 | 
                    struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    struct kvaser_cmd *tmp; 
 | 
    void *buf; 
 | 
    int actual_len; 
 | 
    int err; 
 | 
    int pos; 
 | 
    unsigned long to = jiffies + msecs_to_jiffies(KVASER_USB_TIMEOUT); 
 | 
  
 | 
    buf = kzalloc(KVASER_USB_RX_BUFFER_SIZE, GFP_KERNEL); 
 | 
    if (!buf) 
 | 
        return -ENOMEM; 
 | 
  
 | 
    do { 
 | 
        err = kvaser_usb_recv_cmd(dev, buf, KVASER_USB_RX_BUFFER_SIZE, 
 | 
                      &actual_len); 
 | 
        if (err < 0) 
 | 
            goto end; 
 | 
  
 | 
        pos = 0; 
 | 
        while (pos <= actual_len - CMD_HEADER_LEN) { 
 | 
            tmp = buf + pos; 
 | 
  
 | 
            /* Handle commands crossing the USB endpoint max packet 
 | 
             * size boundary. Check kvaser_usb_read_bulk_callback() 
 | 
             * for further details. 
 | 
             */ 
 | 
            if (tmp->len == 0) { 
 | 
                pos = round_up(pos, 
 | 
                           le16_to_cpu 
 | 
                        (dev->bulk_in->wMaxPacketSize)); 
 | 
                continue; 
 | 
            } 
 | 
  
 | 
            if (pos + tmp->len > actual_len) { 
 | 
                dev_err_ratelimited(&dev->intf->dev, 
 | 
                            "Format error\n"); 
 | 
                break; 
 | 
            } 
 | 
  
 | 
            if (tmp->id == id) { 
 | 
                memcpy(cmd, tmp, tmp->len); 
 | 
                goto end; 
 | 
            } 
 | 
  
 | 
            pos += tmp->len; 
 | 
        } 
 | 
    } while (time_before(jiffies, to)); 
 | 
  
 | 
    err = -EINVAL; 
 | 
  
 | 
end: 
 | 
    kfree(buf); 
 | 
  
 | 
    if (err == 0) 
 | 
        err = kvaser_usb_leaf_verify_size(dev, cmd); 
 | 
  
 | 
    return err; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_send_simple_cmd(const struct kvaser_usb *dev, 
 | 
                       u8 cmd_id, int channel) 
 | 
{ 
 | 
    struct kvaser_cmd *cmd; 
 | 
    int rc; 
 | 
  
 | 
    cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); 
 | 
    if (!cmd) 
 | 
        return -ENOMEM; 
 | 
  
 | 
    cmd->id = cmd_id; 
 | 
    cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_simple); 
 | 
    cmd->u.simple.channel = channel; 
 | 
    cmd->u.simple.tid = 0xff; 
 | 
  
 | 
    rc = kvaser_usb_send_cmd(dev, cmd, cmd->len); 
 | 
  
 | 
    kfree(cmd); 
 | 
    return rc; 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_get_software_info_leaf(struct kvaser_usb *dev, 
 | 
                           const struct leaf_cmd_softinfo *softinfo) 
 | 
{ 
 | 
    u32 sw_options = le32_to_cpu(softinfo->sw_options); 
 | 
  
 | 
    dev->fw_version = le32_to_cpu(softinfo->fw_version); 
 | 
    dev->max_tx_urbs = le16_to_cpu(softinfo->max_outstanding_tx); 
 | 
  
 | 
    if (dev->driver_info->quirks & KVASER_USB_QUIRK_IGNORE_CLK_FREQ) { 
 | 
        /* Firmware expects bittiming parameters calculated for 16MHz 
 | 
         * clock, regardless of the actual clock 
 | 
         */ 
 | 
        dev->cfg = &kvaser_usb_leaf_m32c_dev_cfg; 
 | 
    } else { 
 | 
        switch (sw_options & KVASER_USB_LEAF_SWOPTION_FREQ_MASK) { 
 | 
        case KVASER_USB_LEAF_SWOPTION_FREQ_16_MHZ_CLK: 
 | 
            dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_16mhz; 
 | 
            break; 
 | 
        case KVASER_USB_LEAF_SWOPTION_FREQ_24_MHZ_CLK: 
 | 
            dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_24mhz; 
 | 
            break; 
 | 
        case KVASER_USB_LEAF_SWOPTION_FREQ_32_MHZ_CLK: 
 | 
            dev->cfg = &kvaser_usb_leaf_imx_dev_cfg_32mhz; 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_get_software_info_inner(struct kvaser_usb *dev) 
 | 
{ 
 | 
    struct kvaser_cmd cmd; 
 | 
    int err; 
 | 
  
 | 
    err = kvaser_usb_leaf_send_simple_cmd(dev, CMD_GET_SOFTWARE_INFO, 0); 
 | 
    if (err) 
 | 
        return err; 
 | 
  
 | 
    err = kvaser_usb_leaf_wait_cmd(dev, CMD_GET_SOFTWARE_INFO_REPLY, &cmd); 
 | 
    if (err) 
 | 
        return err; 
 | 
  
 | 
    switch (dev->driver_info->family) { 
 | 
    case KVASER_LEAF: 
 | 
        kvaser_usb_leaf_get_software_info_leaf(dev, &cmd.u.leaf.softinfo); 
 | 
        break; 
 | 
    case KVASER_USBCAN: 
 | 
        dev->fw_version = le32_to_cpu(cmd.u.usbcan.softinfo.fw_version); 
 | 
        dev->max_tx_urbs = 
 | 
            le16_to_cpu(cmd.u.usbcan.softinfo.max_outstanding_tx); 
 | 
        dev->cfg = &kvaser_usb_leaf_usbcan_dev_cfg; 
 | 
        break; 
 | 
    } 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_get_software_info(struct kvaser_usb *dev) 
 | 
{ 
 | 
    int err; 
 | 
    int retry = 3; 
 | 
  
 | 
    /* On some x86 laptops, plugging a Kvaser device again after 
 | 
     * an unplug makes the firmware always ignore the very first 
 | 
     * command. For such a case, provide some room for retries 
 | 
     * instead of completely exiting the driver. 
 | 
     */ 
 | 
    do { 
 | 
        err = kvaser_usb_leaf_get_software_info_inner(dev); 
 | 
    } while (--retry && err == -ETIMEDOUT); 
 | 
  
 | 
    return err; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_get_card_info(struct kvaser_usb *dev) 
 | 
{ 
 | 
    struct kvaser_cmd cmd; 
 | 
    int err; 
 | 
  
 | 
    err = kvaser_usb_leaf_send_simple_cmd(dev, CMD_GET_CARD_INFO, 0); 
 | 
    if (err) 
 | 
        return err; 
 | 
  
 | 
    err = kvaser_usb_leaf_wait_cmd(dev, CMD_GET_CARD_INFO_REPLY, &cmd); 
 | 
    if (err) 
 | 
        return err; 
 | 
  
 | 
    dev->nchannels = cmd.u.cardinfo.nchannels; 
 | 
    if (dev->nchannels > KVASER_USB_MAX_NET_DEVICES || 
 | 
        (dev->driver_info->family == KVASER_USBCAN && 
 | 
         dev->nchannels > MAX_USBCAN_NET_DEVICES)) 
 | 
        return -EINVAL; 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev, 
 | 
                       const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    struct net_device_stats *stats; 
 | 
    struct kvaser_usb_tx_urb_context *context; 
 | 
    struct kvaser_usb_net_priv *priv; 
 | 
    unsigned long flags; 
 | 
    u8 channel, tid; 
 | 
  
 | 
    channel = cmd->u.tx_acknowledge_header.channel; 
 | 
    tid = cmd->u.tx_acknowledge_header.tid; 
 | 
  
 | 
    if (channel >= dev->nchannels) { 
 | 
        dev_err(&dev->intf->dev, 
 | 
            "Invalid channel number (%d)\n", channel); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    priv = dev->nets[channel]; 
 | 
  
 | 
    if (!netif_device_present(priv->netdev)) 
 | 
        return; 
 | 
  
 | 
    stats = &priv->netdev->stats; 
 | 
  
 | 
    context = &priv->tx_contexts[tid % dev->max_tx_urbs]; 
 | 
  
 | 
    /* Sometimes the state change doesn't come after a bus-off event */ 
 | 
    if (priv->can.restart_ms && priv->can.state >= CAN_STATE_BUS_OFF) { 
 | 
        struct sk_buff *skb; 
 | 
        struct can_frame *cf; 
 | 
  
 | 
        skb = alloc_can_err_skb(priv->netdev, &cf); 
 | 
        if (skb) { 
 | 
            cf->can_id |= CAN_ERR_RESTARTED; 
 | 
  
 | 
            stats->rx_packets++; 
 | 
            stats->rx_bytes += cf->can_dlc; 
 | 
            netif_rx(skb); 
 | 
        } else { 
 | 
            netdev_err(priv->netdev, 
 | 
                   "No memory left for err_skb\n"); 
 | 
        } 
 | 
  
 | 
        priv->can.can_stats.restarts++; 
 | 
        netif_carrier_on(priv->netdev); 
 | 
  
 | 
        priv->can.state = CAN_STATE_ERROR_ACTIVE; 
 | 
    } 
 | 
  
 | 
    stats->tx_packets++; 
 | 
    stats->tx_bytes += context->dlc; 
 | 
  
 | 
    spin_lock_irqsave(&priv->tx_contexts_lock, flags); 
 | 
  
 | 
    can_get_echo_skb(priv->netdev, context->echo_index); 
 | 
    context->echo_index = dev->max_tx_urbs; 
 | 
    --priv->active_tx_contexts; 
 | 
    netif_wake_queue(priv->netdev); 
 | 
  
 | 
    spin_unlock_irqrestore(&priv->tx_contexts_lock, flags); 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_simple_cmd_async(struct kvaser_usb_net_priv *priv, 
 | 
                        u8 cmd_id) 
 | 
{ 
 | 
    struct kvaser_cmd *cmd; 
 | 
    int err; 
 | 
  
 | 
    cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); 
 | 
    if (!cmd) 
 | 
        return -ENOMEM; 
 | 
  
 | 
    cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_simple); 
 | 
    cmd->id = cmd_id; 
 | 
    cmd->u.simple.channel = priv->channel; 
 | 
  
 | 
    err = kvaser_usb_send_cmd_async(priv, cmd, cmd->len); 
 | 
    if (err) 
 | 
        kfree(cmd); 
 | 
  
 | 
    return err; 
 | 
} 
 | 
  
 | 
static void 
 | 
kvaser_usb_leaf_rx_error_update_can_state(struct kvaser_usb_net_priv *priv, 
 | 
                    const struct kvaser_usb_err_summary *es, 
 | 
                    struct can_frame *cf) 
 | 
{ 
 | 
    struct kvaser_usb *dev = priv->dev; 
 | 
    struct net_device_stats *stats = &priv->netdev->stats; 
 | 
    enum can_state cur_state, new_state, tx_state, rx_state; 
 | 
  
 | 
    netdev_dbg(priv->netdev, "Error status: 0x%02x\n", es->status); 
 | 
  
 | 
    new_state = priv->can.state; 
 | 
    cur_state = priv->can.state; 
 | 
  
 | 
    if (es->status & (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { 
 | 
        new_state = CAN_STATE_BUS_OFF; 
 | 
    } else if (es->status & M16C_STATE_BUS_PASSIVE) { 
 | 
        new_state = CAN_STATE_ERROR_PASSIVE; 
 | 
    } else if (es->status & M16C_STATE_BUS_ERROR) { 
 | 
        /* Guard against spurious error events after a busoff */ 
 | 
        if (cur_state < CAN_STATE_BUS_OFF) { 
 | 
            if (es->txerr >= 128 || es->rxerr >= 128) 
 | 
                new_state = CAN_STATE_ERROR_PASSIVE; 
 | 
            else if (es->txerr >= 96 || es->rxerr >= 96) 
 | 
                new_state = CAN_STATE_ERROR_WARNING; 
 | 
            else if (cur_state > CAN_STATE_ERROR_ACTIVE) 
 | 
                new_state = CAN_STATE_ERROR_ACTIVE; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    if (!es->status) 
 | 
        new_state = CAN_STATE_ERROR_ACTIVE; 
 | 
  
 | 
    if (new_state != cur_state) { 
 | 
        tx_state = (es->txerr >= es->rxerr) ? new_state : 0; 
 | 
        rx_state = (es->txerr <= es->rxerr) ? new_state : 0; 
 | 
  
 | 
        can_change_state(priv->netdev, cf, tx_state, rx_state); 
 | 
    } 
 | 
  
 | 
    if (priv->can.restart_ms && 
 | 
        cur_state >= CAN_STATE_BUS_OFF && 
 | 
        new_state < CAN_STATE_BUS_OFF) 
 | 
        priv->can.can_stats.restarts++; 
 | 
  
 | 
    switch (dev->driver_info->family) { 
 | 
    case KVASER_LEAF: 
 | 
        if (es->leaf.error_factor) { 
 | 
            priv->can.can_stats.bus_error++; 
 | 
            stats->rx_errors++; 
 | 
        } 
 | 
        break; 
 | 
    case KVASER_USBCAN: 
 | 
        if (es->usbcan.error_state & USBCAN_ERROR_STATE_TX_ERROR) 
 | 
            stats->tx_errors++; 
 | 
        if (es->usbcan.error_state & USBCAN_ERROR_STATE_RX_ERROR) 
 | 
            stats->rx_errors++; 
 | 
        if (es->usbcan.error_state & USBCAN_ERROR_STATE_BUSERROR) 
 | 
            priv->can.can_stats.bus_error++; 
 | 
        break; 
 | 
    } 
 | 
  
 | 
    priv->bec.txerr = es->txerr; 
 | 
    priv->bec.rxerr = es->rxerr; 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_rx_error(const struct kvaser_usb *dev, 
 | 
                     const struct kvaser_usb_err_summary *es) 
 | 
{ 
 | 
    struct can_frame *cf; 
 | 
    struct can_frame tmp_cf = { .can_id = CAN_ERR_FLAG, 
 | 
                    .can_dlc = CAN_ERR_DLC }; 
 | 
    struct sk_buff *skb; 
 | 
    struct net_device_stats *stats; 
 | 
    struct kvaser_usb_net_priv *priv; 
 | 
    enum can_state old_state, new_state; 
 | 
  
 | 
    if (es->channel >= dev->nchannels) { 
 | 
        dev_err(&dev->intf->dev, 
 | 
            "Invalid channel number (%d)\n", es->channel); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    priv = dev->nets[es->channel]; 
 | 
    stats = &priv->netdev->stats; 
 | 
  
 | 
    /* Update all of the CAN interface's state and error counters before 
 | 
     * trying any memory allocation that can actually fail with -ENOMEM. 
 | 
     * 
 | 
     * We send a temporary stack-allocated error CAN frame to 
 | 
     * can_change_state() for the very same reason. 
 | 
     * 
 | 
     * TODO: Split can_change_state() responsibility between updating the 
 | 
     * CAN interface's state and counters, and the setting up of CAN error 
 | 
     * frame ID and data to userspace. Remove stack allocation afterwards. 
 | 
     */ 
 | 
    old_state = priv->can.state; 
 | 
    kvaser_usb_leaf_rx_error_update_can_state(priv, es, &tmp_cf); 
 | 
    new_state = priv->can.state; 
 | 
  
 | 
    skb = alloc_can_err_skb(priv->netdev, &cf); 
 | 
    if (!skb) { 
 | 
        stats->rx_dropped++; 
 | 
        return; 
 | 
    } 
 | 
    memcpy(cf, &tmp_cf, sizeof(*cf)); 
 | 
  
 | 
    if (new_state != old_state) { 
 | 
        if (es->status & 
 | 
            (M16C_STATE_BUS_OFF | M16C_STATE_BUS_RESET)) { 
 | 
            if (!priv->can.restart_ms) 
 | 
                kvaser_usb_leaf_simple_cmd_async(priv, 
 | 
                                 CMD_STOP_CHIP); 
 | 
            netif_carrier_off(priv->netdev); 
 | 
        } 
 | 
  
 | 
        if (priv->can.restart_ms && 
 | 
            old_state >= CAN_STATE_BUS_OFF && 
 | 
            new_state < CAN_STATE_BUS_OFF) { 
 | 
            cf->can_id |= CAN_ERR_RESTARTED; 
 | 
            netif_carrier_on(priv->netdev); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    switch (dev->driver_info->family) { 
 | 
    case KVASER_LEAF: 
 | 
        if (es->leaf.error_factor) { 
 | 
            cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; 
 | 
  
 | 
            if (es->leaf.error_factor & M16C_EF_ACKE) 
 | 
                cf->data[3] = CAN_ERR_PROT_LOC_ACK; 
 | 
            if (es->leaf.error_factor & M16C_EF_CRCE) 
 | 
                cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; 
 | 
            if (es->leaf.error_factor & M16C_EF_FORME) 
 | 
                cf->data[2] |= CAN_ERR_PROT_FORM; 
 | 
            if (es->leaf.error_factor & M16C_EF_STFE) 
 | 
                cf->data[2] |= CAN_ERR_PROT_STUFF; 
 | 
            if (es->leaf.error_factor & M16C_EF_BITE0) 
 | 
                cf->data[2] |= CAN_ERR_PROT_BIT0; 
 | 
            if (es->leaf.error_factor & M16C_EF_BITE1) 
 | 
                cf->data[2] |= CAN_ERR_PROT_BIT1; 
 | 
            if (es->leaf.error_factor & M16C_EF_TRE) 
 | 
                cf->data[2] |= CAN_ERR_PROT_TX; 
 | 
        } 
 | 
        break; 
 | 
    case KVASER_USBCAN: 
 | 
        if (es->usbcan.error_state & USBCAN_ERROR_STATE_BUSERROR) 
 | 
            cf->can_id |= CAN_ERR_BUSERROR; 
 | 
        break; 
 | 
    } 
 | 
  
 | 
    if (new_state != CAN_STATE_BUS_OFF) { 
 | 
        cf->data[6] = es->txerr; 
 | 
        cf->data[7] = es->rxerr; 
 | 
    } 
 | 
  
 | 
    stats->rx_packets++; 
 | 
    stats->rx_bytes += cf->can_dlc; 
 | 
    netif_rx(skb); 
 | 
} 
 | 
  
 | 
/* For USBCAN, report error to userspace if the channels's errors counter 
 | 
 * has changed, or we're the only channel seeing a bus error state. 
 | 
 */ 
 | 
static void 
 | 
kvaser_usb_leaf_usbcan_conditionally_rx_error(const struct kvaser_usb *dev, 
 | 
                          struct kvaser_usb_err_summary *es) 
 | 
{ 
 | 
    struct kvaser_usb_net_priv *priv; 
 | 
    unsigned int channel; 
 | 
    bool report_error; 
 | 
  
 | 
    channel = es->channel; 
 | 
    if (channel >= dev->nchannels) { 
 | 
        dev_err(&dev->intf->dev, 
 | 
            "Invalid channel number (%d)\n", channel); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    priv = dev->nets[channel]; 
 | 
    report_error = false; 
 | 
  
 | 
    if (es->txerr != priv->bec.txerr) { 
 | 
        es->usbcan.error_state |= USBCAN_ERROR_STATE_TX_ERROR; 
 | 
        report_error = true; 
 | 
    } 
 | 
    if (es->rxerr != priv->bec.rxerr) { 
 | 
        es->usbcan.error_state |= USBCAN_ERROR_STATE_RX_ERROR; 
 | 
        report_error = true; 
 | 
    } 
 | 
    if ((es->status & M16C_STATE_BUS_ERROR) && 
 | 
        !(es->usbcan.other_ch_status & M16C_STATE_BUS_ERROR)) { 
 | 
        es->usbcan.error_state |= USBCAN_ERROR_STATE_BUSERROR; 
 | 
        report_error = true; 
 | 
    } 
 | 
  
 | 
    if (report_error) 
 | 
        kvaser_usb_leaf_rx_error(dev, es); 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_usbcan_rx_error(const struct kvaser_usb *dev, 
 | 
                        const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    struct kvaser_usb_err_summary es = { }; 
 | 
  
 | 
    switch (cmd->id) { 
 | 
    /* Sometimes errors are sent as unsolicited chip state events */ 
 | 
    case CMD_CHIP_STATE_EVENT: 
 | 
        es.channel = cmd->u.usbcan.chip_state_event.channel; 
 | 
        es.status = cmd->u.usbcan.chip_state_event.status; 
 | 
        es.txerr = cmd->u.usbcan.chip_state_event.tx_errors_count; 
 | 
        es.rxerr = cmd->u.usbcan.chip_state_event.rx_errors_count; 
 | 
        kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); 
 | 
        break; 
 | 
  
 | 
    case CMD_CAN_ERROR_EVENT: 
 | 
        es.channel = 0; 
 | 
        es.status = cmd->u.usbcan.error_event.status_ch0; 
 | 
        es.txerr = cmd->u.usbcan.error_event.tx_errors_count_ch0; 
 | 
        es.rxerr = cmd->u.usbcan.error_event.rx_errors_count_ch0; 
 | 
        es.usbcan.other_ch_status = 
 | 
            cmd->u.usbcan.error_event.status_ch1; 
 | 
        kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); 
 | 
  
 | 
        /* The USBCAN firmware supports up to 2 channels. 
 | 
         * Now that ch0 was checked, check if ch1 has any errors. 
 | 
         */ 
 | 
        if (dev->nchannels == MAX_USBCAN_NET_DEVICES) { 
 | 
            es.channel = 1; 
 | 
            es.status = cmd->u.usbcan.error_event.status_ch1; 
 | 
            es.txerr = 
 | 
                cmd->u.usbcan.error_event.tx_errors_count_ch1; 
 | 
            es.rxerr = 
 | 
                cmd->u.usbcan.error_event.rx_errors_count_ch1; 
 | 
            es.usbcan.other_ch_status = 
 | 
                cmd->u.usbcan.error_event.status_ch0; 
 | 
            kvaser_usb_leaf_usbcan_conditionally_rx_error(dev, &es); 
 | 
        } 
 | 
        break; 
 | 
  
 | 
    default: 
 | 
        dev_err(&dev->intf->dev, "Invalid cmd id (%d)\n", cmd->id); 
 | 
    } 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_leaf_rx_error(const struct kvaser_usb *dev, 
 | 
                      const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    struct kvaser_usb_err_summary es = { }; 
 | 
  
 | 
    switch (cmd->id) { 
 | 
    case CMD_CAN_ERROR_EVENT: 
 | 
        es.channel = cmd->u.leaf.error_event.channel; 
 | 
        es.status = cmd->u.leaf.error_event.status; 
 | 
        es.txerr = cmd->u.leaf.error_event.tx_errors_count; 
 | 
        es.rxerr = cmd->u.leaf.error_event.rx_errors_count; 
 | 
        es.leaf.error_factor = cmd->u.leaf.error_event.error_factor; 
 | 
        break; 
 | 
    case CMD_LEAF_LOG_MESSAGE: 
 | 
        es.channel = cmd->u.leaf.log_message.channel; 
 | 
        es.status = cmd->u.leaf.log_message.data[0]; 
 | 
        es.txerr = cmd->u.leaf.log_message.data[2]; 
 | 
        es.rxerr = cmd->u.leaf.log_message.data[3]; 
 | 
        es.leaf.error_factor = cmd->u.leaf.log_message.data[1]; 
 | 
        break; 
 | 
    case CMD_CHIP_STATE_EVENT: 
 | 
        es.channel = cmd->u.leaf.chip_state_event.channel; 
 | 
        es.status = cmd->u.leaf.chip_state_event.status; 
 | 
        es.txerr = cmd->u.leaf.chip_state_event.tx_errors_count; 
 | 
        es.rxerr = cmd->u.leaf.chip_state_event.rx_errors_count; 
 | 
        es.leaf.error_factor = 0; 
 | 
        break; 
 | 
    default: 
 | 
        dev_err(&dev->intf->dev, "Invalid cmd id (%d)\n", cmd->id); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    kvaser_usb_leaf_rx_error(dev, &es); 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_rx_can_err(const struct kvaser_usb_net_priv *priv, 
 | 
                       const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    if (cmd->u.rx_can_header.flag & (MSG_FLAG_ERROR_FRAME | 
 | 
                     MSG_FLAG_NERR)) { 
 | 
        struct net_device_stats *stats = &priv->netdev->stats; 
 | 
  
 | 
        netdev_err(priv->netdev, "Unknown error (flags: 0x%02x)\n", 
 | 
               cmd->u.rx_can_header.flag); 
 | 
  
 | 
        stats->rx_errors++; 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    if (cmd->u.rx_can_header.flag & MSG_FLAG_OVERRUN) 
 | 
        kvaser_usb_can_rx_over_error(priv->netdev); 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, 
 | 
                       const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    struct kvaser_usb_net_priv *priv; 
 | 
    struct can_frame *cf; 
 | 
    struct sk_buff *skb; 
 | 
    struct net_device_stats *stats; 
 | 
    u8 channel = cmd->u.rx_can_header.channel; 
 | 
    const u8 *rx_data = NULL;    /* GCC */ 
 | 
  
 | 
    if (channel >= dev->nchannels) { 
 | 
        dev_err(&dev->intf->dev, 
 | 
            "Invalid channel number (%d)\n", channel); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    priv = dev->nets[channel]; 
 | 
    stats = &priv->netdev->stats; 
 | 
  
 | 
    if ((cmd->u.rx_can_header.flag & MSG_FLAG_ERROR_FRAME) && 
 | 
        (dev->driver_info->family == KVASER_LEAF && 
 | 
         cmd->id == CMD_LEAF_LOG_MESSAGE)) { 
 | 
        kvaser_usb_leaf_leaf_rx_error(dev, cmd); 
 | 
        return; 
 | 
    } else if (cmd->u.rx_can_header.flag & (MSG_FLAG_ERROR_FRAME | 
 | 
                        MSG_FLAG_NERR | 
 | 
                        MSG_FLAG_OVERRUN)) { 
 | 
        kvaser_usb_leaf_rx_can_err(priv, cmd); 
 | 
        return; 
 | 
    } else if (cmd->u.rx_can_header.flag & ~MSG_FLAG_REMOTE_FRAME) { 
 | 
        netdev_warn(priv->netdev, 
 | 
                "Unhandled frame (flags: 0x%02x)\n", 
 | 
                cmd->u.rx_can_header.flag); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    switch (dev->driver_info->family) { 
 | 
    case KVASER_LEAF: 
 | 
        rx_data = cmd->u.leaf.rx_can.data; 
 | 
        break; 
 | 
    case KVASER_USBCAN: 
 | 
        rx_data = cmd->u.usbcan.rx_can.data; 
 | 
        break; 
 | 
    } 
 | 
  
 | 
    skb = alloc_can_skb(priv->netdev, &cf); 
 | 
    if (!skb) { 
 | 
        stats->rx_dropped++; 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    if (dev->driver_info->family == KVASER_LEAF && cmd->id == 
 | 
        CMD_LEAF_LOG_MESSAGE) { 
 | 
        cf->can_id = le32_to_cpu(cmd->u.leaf.log_message.id); 
 | 
        if (cf->can_id & KVASER_EXTENDED_FRAME) 
 | 
            cf->can_id &= CAN_EFF_MASK | CAN_EFF_FLAG; 
 | 
        else 
 | 
            cf->can_id &= CAN_SFF_MASK; 
 | 
  
 | 
        cf->can_dlc = get_can_dlc(cmd->u.leaf.log_message.dlc); 
 | 
  
 | 
        if (cmd->u.leaf.log_message.flags & MSG_FLAG_REMOTE_FRAME) 
 | 
            cf->can_id |= CAN_RTR_FLAG; 
 | 
        else 
 | 
            memcpy(cf->data, &cmd->u.leaf.log_message.data, 
 | 
                   cf->can_dlc); 
 | 
    } else { 
 | 
        cf->can_id = ((rx_data[0] & 0x1f) << 6) | (rx_data[1] & 0x3f); 
 | 
  
 | 
        if (cmd->id == CMD_RX_EXT_MESSAGE) { 
 | 
            cf->can_id <<= 18; 
 | 
            cf->can_id |= ((rx_data[2] & 0x0f) << 14) | 
 | 
                      ((rx_data[3] & 0xff) << 6) | 
 | 
                      (rx_data[4] & 0x3f); 
 | 
            cf->can_id |= CAN_EFF_FLAG; 
 | 
        } 
 | 
  
 | 
        cf->can_dlc = get_can_dlc(rx_data[5]); 
 | 
  
 | 
        if (cmd->u.rx_can_header.flag & MSG_FLAG_REMOTE_FRAME) 
 | 
            cf->can_id |= CAN_RTR_FLAG; 
 | 
        else 
 | 
            memcpy(cf->data, &rx_data[6], cf->can_dlc); 
 | 
    } 
 | 
  
 | 
    stats->rx_packets++; 
 | 
    stats->rx_bytes += cf->can_dlc; 
 | 
    netif_rx(skb); 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_start_chip_reply(const struct kvaser_usb *dev, 
 | 
                         const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    struct kvaser_usb_net_priv *priv; 
 | 
    u8 channel = cmd->u.simple.channel; 
 | 
  
 | 
    if (channel >= dev->nchannels) { 
 | 
        dev_err(&dev->intf->dev, 
 | 
            "Invalid channel number (%d)\n", channel); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    priv = dev->nets[channel]; 
 | 
  
 | 
    if (completion_done(&priv->start_comp) && 
 | 
        netif_queue_stopped(priv->netdev)) { 
 | 
        netif_wake_queue(priv->netdev); 
 | 
    } else { 
 | 
        netif_start_queue(priv->netdev); 
 | 
        complete(&priv->start_comp); 
 | 
    } 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_stop_chip_reply(const struct kvaser_usb *dev, 
 | 
                        const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    struct kvaser_usb_net_priv *priv; 
 | 
    u8 channel = cmd->u.simple.channel; 
 | 
  
 | 
    if (channel >= dev->nchannels) { 
 | 
        dev_err(&dev->intf->dev, 
 | 
            "Invalid channel number (%d)\n", channel); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    priv = dev->nets[channel]; 
 | 
  
 | 
    complete(&priv->stop_comp); 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_handle_command(const struct kvaser_usb *dev, 
 | 
                       const struct kvaser_cmd *cmd) 
 | 
{ 
 | 
    if (kvaser_usb_leaf_verify_size(dev, cmd) < 0) 
 | 
        return; 
 | 
  
 | 
    switch (cmd->id) { 
 | 
    case CMD_START_CHIP_REPLY: 
 | 
        kvaser_usb_leaf_start_chip_reply(dev, cmd); 
 | 
        break; 
 | 
  
 | 
    case CMD_STOP_CHIP_REPLY: 
 | 
        kvaser_usb_leaf_stop_chip_reply(dev, cmd); 
 | 
        break; 
 | 
  
 | 
    case CMD_RX_STD_MESSAGE: 
 | 
    case CMD_RX_EXT_MESSAGE: 
 | 
        kvaser_usb_leaf_rx_can_msg(dev, cmd); 
 | 
        break; 
 | 
  
 | 
    case CMD_LEAF_LOG_MESSAGE: 
 | 
        if (dev->driver_info->family != KVASER_LEAF) 
 | 
            goto warn; 
 | 
        kvaser_usb_leaf_rx_can_msg(dev, cmd); 
 | 
        break; 
 | 
  
 | 
    case CMD_CHIP_STATE_EVENT: 
 | 
    case CMD_CAN_ERROR_EVENT: 
 | 
        if (dev->driver_info->family == KVASER_LEAF) 
 | 
            kvaser_usb_leaf_leaf_rx_error(dev, cmd); 
 | 
        else 
 | 
            kvaser_usb_leaf_usbcan_rx_error(dev, cmd); 
 | 
        break; 
 | 
  
 | 
    case CMD_TX_ACKNOWLEDGE: 
 | 
        kvaser_usb_leaf_tx_acknowledge(dev, cmd); 
 | 
        break; 
 | 
  
 | 
    /* Ignored commands */ 
 | 
    case CMD_USBCAN_CLOCK_OVERFLOW_EVENT: 
 | 
        if (dev->driver_info->family != KVASER_USBCAN) 
 | 
            goto warn; 
 | 
        break; 
 | 
  
 | 
    case CMD_FLUSH_QUEUE_REPLY: 
 | 
        if (dev->driver_info->family != KVASER_LEAF) 
 | 
            goto warn; 
 | 
        break; 
 | 
  
 | 
    default: 
 | 
warn:        dev_warn(&dev->intf->dev, "Unhandled command (%d)\n", cmd->id); 
 | 
        break; 
 | 
    } 
 | 
} 
 | 
  
 | 
static void kvaser_usb_leaf_read_bulk_callback(struct kvaser_usb *dev, 
 | 
                           void *buf, int len) 
 | 
{ 
 | 
    struct kvaser_cmd *cmd; 
 | 
    int pos = 0; 
 | 
  
 | 
    while (pos <= len - CMD_HEADER_LEN) { 
 | 
        cmd = buf + pos; 
 | 
  
 | 
        /* The Kvaser firmware can only read and write commands that 
 | 
         * does not cross the USB's endpoint wMaxPacketSize boundary. 
 | 
         * If a follow-up command crosses such boundary, firmware puts 
 | 
         * a placeholder zero-length command in its place then aligns 
 | 
         * the real command to the next max packet size. 
 | 
         * 
 | 
         * Handle such cases or we're going to miss a significant 
 | 
         * number of events in case of a heavy rx load on the bus. 
 | 
         */ 
 | 
        if (cmd->len == 0) { 
 | 
            pos = round_up(pos, le16_to_cpu 
 | 
                        (dev->bulk_in->wMaxPacketSize)); 
 | 
            continue; 
 | 
        } 
 | 
  
 | 
        if (pos + cmd->len > len) { 
 | 
            dev_err_ratelimited(&dev->intf->dev, "Format error\n"); 
 | 
            break; 
 | 
        } 
 | 
  
 | 
        kvaser_usb_leaf_handle_command(dev, cmd); 
 | 
        pos += cmd->len; 
 | 
    } 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_set_opt_mode(const struct kvaser_usb_net_priv *priv) 
 | 
{ 
 | 
    struct kvaser_cmd *cmd; 
 | 
    int rc; 
 | 
  
 | 
    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 
 | 
    if (!cmd) 
 | 
        return -ENOMEM; 
 | 
  
 | 
    cmd->id = CMD_SET_CTRL_MODE; 
 | 
    cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_ctrl_mode); 
 | 
    cmd->u.ctrl_mode.tid = 0xff; 
 | 
    cmd->u.ctrl_mode.channel = priv->channel; 
 | 
  
 | 
    if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 
 | 
        cmd->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_SILENT; 
 | 
    else 
 | 
        cmd->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_NORMAL; 
 | 
  
 | 
    rc = kvaser_usb_send_cmd(priv->dev, cmd, cmd->len); 
 | 
  
 | 
    kfree(cmd); 
 | 
    return rc; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_start_chip(struct kvaser_usb_net_priv *priv) 
 | 
{ 
 | 
    int err; 
 | 
  
 | 
    reinit_completion(&priv->start_comp); 
 | 
  
 | 
    err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_START_CHIP, 
 | 
                          priv->channel); 
 | 
    if (err) 
 | 
        return err; 
 | 
  
 | 
    if (!wait_for_completion_timeout(&priv->start_comp, 
 | 
                     msecs_to_jiffies(KVASER_USB_TIMEOUT))) 
 | 
        return -ETIMEDOUT; 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_stop_chip(struct kvaser_usb_net_priv *priv) 
 | 
{ 
 | 
    int err; 
 | 
  
 | 
    reinit_completion(&priv->stop_comp); 
 | 
  
 | 
    err = kvaser_usb_leaf_send_simple_cmd(priv->dev, CMD_STOP_CHIP, 
 | 
                          priv->channel); 
 | 
    if (err) 
 | 
        return err; 
 | 
  
 | 
    if (!wait_for_completion_timeout(&priv->stop_comp, 
 | 
                     msecs_to_jiffies(KVASER_USB_TIMEOUT))) 
 | 
        return -ETIMEDOUT; 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_reset_chip(struct kvaser_usb *dev, int channel) 
 | 
{ 
 | 
    return kvaser_usb_leaf_send_simple_cmd(dev, CMD_RESET_CHIP, channel); 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_flush_queue(struct kvaser_usb_net_priv *priv) 
 | 
{ 
 | 
    struct kvaser_cmd *cmd; 
 | 
    int rc; 
 | 
  
 | 
    cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 
 | 
    if (!cmd) 
 | 
        return -ENOMEM; 
 | 
  
 | 
    cmd->id = CMD_FLUSH_QUEUE; 
 | 
    cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_flush_queue); 
 | 
    cmd->u.flush_queue.channel = priv->channel; 
 | 
    cmd->u.flush_queue.flags = 0x00; 
 | 
  
 | 
    rc = kvaser_usb_send_cmd(priv->dev, cmd, cmd->len); 
 | 
  
 | 
    kfree(cmd); 
 | 
    return rc; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_init_card(struct kvaser_usb *dev) 
 | 
{ 
 | 
    struct kvaser_usb_dev_card_data *card_data = &dev->card_data; 
 | 
  
 | 
    card_data->ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_set_bittiming(struct net_device *netdev) 
 | 
{ 
 | 
    struct kvaser_usb_net_priv *priv = netdev_priv(netdev); 
 | 
    struct can_bittiming *bt = &priv->can.bittiming; 
 | 
    struct kvaser_usb *dev = priv->dev; 
 | 
    struct kvaser_cmd *cmd; 
 | 
    int rc; 
 | 
  
 | 
    cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); 
 | 
    if (!cmd) 
 | 
        return -ENOMEM; 
 | 
  
 | 
    cmd->id = CMD_SET_BUS_PARAMS; 
 | 
    cmd->len = CMD_HEADER_LEN + sizeof(struct kvaser_cmd_busparams); 
 | 
    cmd->u.busparams.channel = priv->channel; 
 | 
    cmd->u.busparams.tid = 0xff; 
 | 
    cmd->u.busparams.bitrate = cpu_to_le32(bt->bitrate); 
 | 
    cmd->u.busparams.sjw = bt->sjw; 
 | 
    cmd->u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1; 
 | 
    cmd->u.busparams.tseg2 = bt->phase_seg2; 
 | 
  
 | 
    if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) 
 | 
        cmd->u.busparams.no_samp = 3; 
 | 
    else 
 | 
        cmd->u.busparams.no_samp = 1; 
 | 
  
 | 
    rc = kvaser_usb_send_cmd(dev, cmd, cmd->len); 
 | 
  
 | 
    kfree(cmd); 
 | 
    return rc; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_set_mode(struct net_device *netdev, 
 | 
                    enum can_mode mode) 
 | 
{ 
 | 
    struct kvaser_usb_net_priv *priv = netdev_priv(netdev); 
 | 
    int err; 
 | 
  
 | 
    switch (mode) { 
 | 
    case CAN_MODE_START: 
 | 
        kvaser_usb_unlink_tx_urbs(priv); 
 | 
  
 | 
        err = kvaser_usb_leaf_simple_cmd_async(priv, CMD_START_CHIP); 
 | 
        if (err) 
 | 
            return err; 
 | 
  
 | 
        priv->can.state = CAN_STATE_ERROR_ACTIVE; 
 | 
        break; 
 | 
    default: 
 | 
        return -EOPNOTSUPP; 
 | 
    } 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_get_berr_counter(const struct net_device *netdev, 
 | 
                        struct can_berr_counter *bec) 
 | 
{ 
 | 
    struct kvaser_usb_net_priv *priv = netdev_priv(netdev); 
 | 
  
 | 
    *bec = priv->bec; 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev) 
 | 
{ 
 | 
    const struct usb_host_interface *iface_desc; 
 | 
    struct usb_endpoint_descriptor *endpoint; 
 | 
    int i; 
 | 
  
 | 
    iface_desc = dev->intf->cur_altsetting; 
 | 
  
 | 
    for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 
 | 
        endpoint = &iface_desc->endpoint[i].desc; 
 | 
  
 | 
        if (!dev->bulk_in && usb_endpoint_is_bulk_in(endpoint)) 
 | 
            dev->bulk_in = endpoint; 
 | 
  
 | 
        if (!dev->bulk_out && usb_endpoint_is_bulk_out(endpoint)) 
 | 
            dev->bulk_out = endpoint; 
 | 
  
 | 
        /* use first bulk endpoint for in and out */ 
 | 
        if (dev->bulk_in && dev->bulk_out) 
 | 
            return 0; 
 | 
    } 
 | 
  
 | 
    return -ENODEV; 
 | 
} 
 | 
  
 | 
const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops = { 
 | 
    .dev_set_mode = kvaser_usb_leaf_set_mode, 
 | 
    .dev_set_bittiming = kvaser_usb_leaf_set_bittiming, 
 | 
    .dev_set_data_bittiming = NULL, 
 | 
    .dev_get_berr_counter = kvaser_usb_leaf_get_berr_counter, 
 | 
    .dev_setup_endpoints = kvaser_usb_leaf_setup_endpoints, 
 | 
    .dev_init_card = kvaser_usb_leaf_init_card, 
 | 
    .dev_get_software_info = kvaser_usb_leaf_get_software_info, 
 | 
    .dev_get_software_details = NULL, 
 | 
    .dev_get_card_info = kvaser_usb_leaf_get_card_info, 
 | 
    .dev_get_capabilities = NULL, 
 | 
    .dev_set_opt_mode = kvaser_usb_leaf_set_opt_mode, 
 | 
    .dev_start_chip = kvaser_usb_leaf_start_chip, 
 | 
    .dev_stop_chip = kvaser_usb_leaf_stop_chip, 
 | 
    .dev_reset_chip = kvaser_usb_leaf_reset_chip, 
 | 
    .dev_flush_queue = kvaser_usb_leaf_flush_queue, 
 | 
    .dev_read_bulk_callback = kvaser_usb_leaf_read_bulk_callback, 
 | 
    .dev_frame_to_cmd = kvaser_usb_leaf_frame_to_cmd, 
 | 
}; 
 |