196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* 296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * CAN driver for esd CAN-USB/2 396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * 496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh 596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * 696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * This program is free software; you can redistribute it and/or modify it 796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * under the terms of the GNU General Public License as published 896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * by the Free Software Foundation; version 2 of the License. 996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * 1096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * This program is distributed in the hope that it will be useful, but 1196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * WITHOUT ANY WARRANTY; without even the implied warranty of 1296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * General Public License for more details. 1496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * 1596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * You should have received a copy of the GNU General Public License along 1696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * with this program; if not, write to the Free Software Foundation, Inc., 1796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 1896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 1996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/init.h> 2096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/signal.h> 2196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/slab.h> 2296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/module.h> 2396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/netdevice.h> 2496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/usb.h> 2596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 2696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/can.h> 2796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/can/dev.h> 2896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#include <linux/can/error.h> 2996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 3096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias FuchsMODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd.eu>"); 3196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias FuchsMODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 interfaces"); 3296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias FuchsMODULE_LICENSE("GPL v2"); 3396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 3496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* Define these values to match your devices */ 3596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define USB_ESDGMBH_VENDOR_ID 0x0ab4 3696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define USB_CANUSB2_PRODUCT_ID 0x0010 3796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 3896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_CAN_CLOCK 60000000 3996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_MAX_NETS 2 4096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 4196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* USB2 commands */ 4296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define CMD_VERSION 1 /* also used for VERSION_REPLY */ 4396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define CMD_CAN_RX 2 /* device to host only */ 4496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define CMD_CAN_TX 3 /* also used for TX_DONE */ 4596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */ 4696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define CMD_TS 5 /* also used for TS_REPLY */ 4796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define CMD_IDADD 6 /* also used for IDADD_REPLY */ 4896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 4996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* esd CAN message flags - dlc field */ 5096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_RTR 0x10 5196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 5296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* esd CAN message flags - id field */ 5396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_EXTID 0x20000000 5496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_EVENT 0x40000000 5596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_IDMASK 0x1fffffff 5696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 5796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* esd CAN event ids used by this driver */ 5896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_EV_CAN_ERROR_EXT 2 5996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 6096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* baudrate message flags */ 6196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_UBR 0x80000000 6296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_LOM 0x40000000 6396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_NO_BAUDRATE 0x7fffffff 6496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_TSEG1_MIN 1 6596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_TSEG1_MAX 16 6696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_TSEG1_SHIFT 16 6796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_TSEG2_MIN 1 6896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_TSEG2_MAX 8 6996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_TSEG2_SHIFT 20 7096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_SJW_MAX 4 7196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_SJW_SHIFT 14 7296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_BRP_MIN 1 7396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_BRP_MAX 1024 7496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_BRP_INC 1 7596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_USB2_3_SAMPLES 0x00800000 7696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 7796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* esd IDADD message */ 7896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_ID_ENABLE 0x80 7996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_MAX_ID_SEGMENT 64 8096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 8196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* SJA1000 ECC register (emulated by usb2 firmware) */ 8296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define SJA1000_ECC_SEG 0x1F 8396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define SJA1000_ECC_DIR 0x20 8496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define SJA1000_ECC_ERR 0x06 8596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define SJA1000_ECC_BIT 0x00 8696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define SJA1000_ECC_FORM 0x40 8796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define SJA1000_ECC_STUFF 0x80 8896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define SJA1000_ECC_MASK 0xc0 8996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 9096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* esd bus state event codes */ 9196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_BUSSTATE_MASK 0xc0 9296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_BUSSTATE_WARN 0x40 9396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_BUSSTATE_ERRPASSIVE 0x80 9496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define ESD_BUSSTATE_BUSOFF 0xc0 9596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 9696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define RX_BUFFER_SIZE 1024 9796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define MAX_RX_URBS 4 9896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs#define MAX_TX_URBS 16 /* must be power of 2 */ 9996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 10096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct header_msg { 10196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; /* len is always the total message length in 32bit words */ 10296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 10396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 rsvd[2]; 10496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 10596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 10696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct version_msg { 10796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; 10896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 10996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 rsvd; 11096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 flags; 11196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 drv_version; 11296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 11396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 11496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct version_reply_msg { 11596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; 11696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 11796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 nets; 11896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 features; 11996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 version; 12096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 name[16]; 12196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 rsvd; 12296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 ts; 12396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 12496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 12596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct rx_msg { 12696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; 12796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 12896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 net; 12996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 dlc; 13096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 ts; 13196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 id; /* upper 3 bits contain flags */ 13296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 data[8]; 13396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 13496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 13596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct tx_msg { 13696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; 13796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 13896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 net; 13996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 dlc; 14096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 hnd; 14196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 id; /* upper 3 bits contain flags */ 14296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 data[8]; 14396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 14496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 14596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct tx_done_msg { 14696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; 14796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 14896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 net; 14996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 status; 15096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 hnd; 15196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 ts; 15296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 15396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 15496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct id_filter_msg { 15596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; 15696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 15796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 net; 15896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 option; 15996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 mask[ESD_MAX_ID_SEGMENT + 1]; 16096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 16196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 16296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct set_baudrate_msg { 16396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 len; 16496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 cmd; 16596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 net; 16696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 rsvd; 16796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs __le32 baud; 16896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 16996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 17096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* Main message type used between library and application */ 17196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct __attribute__ ((packed)) esd_usb2_msg { 17296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs union { 17396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct header_msg hdr; 17496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct version_msg version; 17596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct version_reply_msg version_reply; 17696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct rx_msg rx; 17796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct tx_msg tx; 17896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct tx_done_msg txdone; 17996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct set_baudrate_msg setbaud; 18096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct id_filter_msg filter; 18196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } msg; 18296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 18396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 18496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic struct usb_device_id esd_usb2_table[] = { 18596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)}, 18696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs {} 18796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 18896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias FuchsMODULE_DEVICE_TABLE(usb, esd_usb2_table); 18996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 19096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct esd_usb2_net_priv; 19196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 19296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct esd_tx_urb_context { 19396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv; 19496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u32 echo_index; 19596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int dlc; 19696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 19796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 19896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct esd_usb2 { 19996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct usb_device *udev; 20096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *nets[ESD_USB2_MAX_NETS]; 20196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 20296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct usb_anchor rx_submitted; 20396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 20496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int net_count; 20596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u32 version; 20696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int rxinitdone; 20796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 20896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 20996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstruct esd_usb2_net_priv { 21096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct can_priv can; /* must be the first member */ 21196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 21296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs atomic_t active_tx_jobs; 21396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct usb_anchor tx_submitted; 21496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_tx_urb_context tx_contexts[MAX_TX_URBS]; 21596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 21696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int open_time; 21796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *usb2; 21896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device *netdev; 21996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int index; 22096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 old_state; 22196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct can_berr_counter bec; 22296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 22396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 22496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic void esd_usb2_rx_event(struct esd_usb2_net_priv *priv, 22596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg *msg) 22696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 22796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device_stats *stats = &priv->netdev->stats; 22896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct can_frame *cf; 22996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct sk_buff *skb; 23096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u32 id = le32_to_cpu(msg->msg.rx.id) & ESD_IDMASK; 23196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 23296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (id == ESD_EV_CAN_ERROR_EXT) { 23396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 state = msg->msg.rx.data[0]; 23496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 ecc = msg->msg.rx.data[1]; 23596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 txerr = msg->msg.rx.data[2]; 23696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 rxerr = msg->msg.rx.data[3]; 23796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 23896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs skb = alloc_can_err_skb(priv->netdev, &cf); 23996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (skb == NULL) { 24096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->rx_dropped++; 24196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 24296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 24396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 24496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (state != priv->old_state) { 24596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->old_state = state; 24696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 24796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs switch (state & ESD_BUSSTATE_MASK) { 24896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case ESD_BUSSTATE_BUSOFF: 24996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state = CAN_STATE_BUS_OFF; 25096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->can_id |= CAN_ERR_BUSOFF; 25196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs can_bus_off(priv->netdev); 25296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 25396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case ESD_BUSSTATE_WARN: 25496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state = CAN_STATE_ERROR_WARNING; 25596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.can_stats.error_warning++; 25696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 25796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case ESD_BUSSTATE_ERRPASSIVE: 25896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state = CAN_STATE_ERROR_PASSIVE; 25996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.can_stats.error_passive++; 26096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 26196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs default: 26296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state = CAN_STATE_ERROR_ACTIVE; 26396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 26496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 26596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } else { 26696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.can_stats.bus_error++; 26796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->rx_errors++; 26896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 26996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; 27096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 27196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs switch (ecc & SJA1000_ECC_MASK) { 27296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case SJA1000_ECC_BIT: 27396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[2] |= CAN_ERR_PROT_BIT; 27496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 27596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case SJA1000_ECC_FORM: 27696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[2] |= CAN_ERR_PROT_FORM; 27796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 27896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case SJA1000_ECC_STUFF: 27996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[2] |= CAN_ERR_PROT_STUFF; 28096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 28196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs default: 28296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[2] |= CAN_ERR_PROT_UNSPEC; 28396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[3] = ecc & SJA1000_ECC_SEG; 28496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 28596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 28696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 28725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi /* Error occurred during transmission? */ 28896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!(ecc & SJA1000_ECC_DIR)) 28996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[2] |= CAN_ERR_PROT_TX; 29096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 29196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (priv->can.state == CAN_STATE_ERROR_WARNING || 29296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state == CAN_STATE_ERROR_PASSIVE) { 29396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[1] = (txerr > rxerr) ? 29496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs CAN_ERR_CRTL_TX_PASSIVE : 29596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs CAN_ERR_CRTL_RX_PASSIVE; 29696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 29796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[6] = txerr; 29896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[7] = rxerr; 29996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 30096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 30196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_rx(skb); 30296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 30396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->bec.txerr = txerr; 30496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->bec.rxerr = rxerr; 30596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 30696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->rx_packets++; 30796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->rx_bytes += cf->can_dlc; 30896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 30996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 31096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 31196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, 31296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg *msg) 31396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 31496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device_stats *stats = &priv->netdev->stats; 31596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct can_frame *cf; 31696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct sk_buff *skb; 31796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i; 31896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u32 id; 31996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 32096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!netif_device_present(priv->netdev)) 32196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 32296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 32396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs id = le32_to_cpu(msg->msg.rx.id); 32496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 32596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (id & ESD_EVENT) { 32696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs esd_usb2_rx_event(priv, msg); 32796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } else { 32896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs skb = alloc_can_skb(priv->netdev, &cf); 32996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (skb == NULL) { 33096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->rx_dropped++; 33196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 33296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 33396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 33496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->can_id = id & ESD_IDMASK; 33596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->can_dlc = get_can_dlc(msg->msg.rx.dlc); 33696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 33796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (id & ESD_EXTID) 33896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->can_id |= CAN_EFF_FLAG; 33996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 34096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (msg->msg.rx.dlc & ESD_RTR) { 34196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->can_id |= CAN_RTR_FLAG; 34296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } else { 34396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < cf->can_dlc; i++) 34496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs cf->data[i] = msg->msg.rx.data[i]; 34596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 34696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 34796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_rx(skb); 34896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 34996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->rx_packets++; 35096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->rx_bytes += cf->can_dlc; 35196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 35296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 35396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 35496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 35596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 35696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic void esd_usb2_tx_done_msg(struct esd_usb2_net_priv *priv, 35796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg *msg) 35896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 35996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device_stats *stats = &priv->netdev->stats; 36096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device *netdev = priv->netdev; 36196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_tx_urb_context *context; 36296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 36396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!netif_device_present(netdev)) 36496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 36596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 36696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs context = &priv->tx_contexts[msg->msg.txdone.hnd & (MAX_TX_URBS - 1)]; 36796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 36896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!msg->msg.txdone.status) { 36996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->tx_packets++; 37096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->tx_bytes += context->dlc; 37196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs can_get_echo_skb(netdev, context->echo_index); 37296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } else { 37396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->tx_errors++; 37496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs can_free_echo_skb(netdev, context->echo_index); 37596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 37696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 37796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* Release context */ 37896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs context->echo_index = MAX_TX_URBS; 37996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs atomic_dec(&priv->active_tx_jobs); 38096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 38196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_wake_queue(netdev); 38296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 38396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 38496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic void esd_usb2_read_bulk_callback(struct urb *urb) 38596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 38696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = urb->context; 38796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int retval; 38896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int pos = 0; 38996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i; 39096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 39196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs switch (urb->status) { 39296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case 0: /* success */ 39396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 39496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 39596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case -ENOENT: 39696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case -ESHUTDOWN: 39796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 39896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 39996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs default: 40096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_info(dev->udev->dev.parent, 40196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "Rx URB aborted (%d)\n", urb->status); 40296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto resubmit_urb; 40396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 40496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 40596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs while (pos < urb->actual_length) { 40696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg *msg; 40796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 40896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg = (struct esd_usb2_msg *)(urb->transfer_buffer + pos); 40996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 41096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs switch (msg->msg.hdr.cmd) { 41196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case CMD_CAN_RX: 41296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs esd_usb2_rx_can_msg(dev->nets[msg->msg.rx.net], msg); 41396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 41496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 41596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case CMD_CAN_TX: 41696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs esd_usb2_tx_done_msg(dev->nets[msg->msg.txdone.net], 41796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg); 41896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 41996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 42096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 42196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs pos += msg->msg.hdr.len << 2; 42296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 42396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (pos > urb->actual_length) { 42496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(dev->udev->dev.parent, "format error\n"); 42596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 42696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 42796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 42896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 42996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsresubmit_urb: 43096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), 43196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb->transfer_buffer, RX_BUFFER_SIZE, 43296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs esd_usb2_read_bulk_callback, dev); 43396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 43496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs retval = usb_submit_urb(urb, GFP_ATOMIC); 43596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (retval == -ENODEV) { 43696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < dev->net_count; i++) { 43796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (dev->nets[i]) 43896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_device_detach(dev->nets[i]->netdev); 43996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 44096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } else if (retval) { 44196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(dev->udev->dev.parent, 44296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "failed resubmitting read bulk urb: %d\n", retval); 44396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 44496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 44596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 44696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 44796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 44896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* 44996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * callback for bulk IN urb 45096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 45196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic void esd_usb2_write_bulk_callback(struct urb *urb) 45296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 45396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_tx_urb_context *context = urb->context; 45496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv; 45596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev; 45696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device *netdev; 45796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs size_t size = sizeof(struct esd_usb2_msg); 45896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 45996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs WARN_ON(!context); 46096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 46196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv = context->priv; 46296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netdev = priv->netdev; 46396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev = priv->usb2; 46496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 46596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* free up our allocated buffer */ 46696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_free_coherent(urb->dev, size, 46796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb->transfer_buffer, urb->transfer_dma); 46896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 46996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!netif_device_present(netdev)) 47096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return; 47196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 47296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (urb->status) 47396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_info(netdev->dev.parent, "Tx URB aborted (%d)\n", 47496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb->status); 47596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 47696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netdev->trans_start = jiffies; 47796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 47896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 47996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic ssize_t show_firmware(struct device *d, 48096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct device_attribute *attr, char *buf) 48196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 48296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct usb_interface *intf = to_usb_interface(d); 48396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = usb_get_intfdata(intf); 48496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 48596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return sprintf(buf, "%d.%d.%d\n", 48696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs (dev->version >> 12) & 0xf, 48796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs (dev->version >> 8) & 0xf, 48896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev->version & 0xff); 48996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 49096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic DEVICE_ATTR(firmware, S_IRUGO, show_firmware, NULL); 49196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 49296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic ssize_t show_hardware(struct device *d, 49396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct device_attribute *attr, char *buf) 49496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 49596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct usb_interface *intf = to_usb_interface(d); 49696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = usb_get_intfdata(intf); 49796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 49896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return sprintf(buf, "%d.%d.%d\n", 49996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs (dev->version >> 28) & 0xf, 50096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs (dev->version >> 24) & 0xf, 50196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs (dev->version >> 16) & 0xff); 50296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 50396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL); 50496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 50596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic ssize_t show_nets(struct device *d, 50696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct device_attribute *attr, char *buf) 50796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 50896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct usb_interface *intf = to_usb_interface(d); 50996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = usb_get_intfdata(intf); 51096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 51196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return sprintf(buf, "%d", dev->net_count); 51296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 51396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic DEVICE_ATTR(nets, S_IRUGO, show_nets, NULL); 51496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 51596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg) 51696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 51796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int actual_length; 51896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 51996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return usb_bulk_msg(dev->udev, 52096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_sndbulkpipe(dev->udev, 2), 52196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg, 52296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.hdr.len << 2, 52396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs &actual_length, 52496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 1000); 52596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 52696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 52796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_wait_msg(struct esd_usb2 *dev, 52896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg *msg) 52996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 53096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int actual_length; 53196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 53296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return usb_bulk_msg(dev->udev, 53396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_rcvbulkpipe(dev->udev, 1), 53496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg, 53596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs sizeof(*msg), 53696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs &actual_length, 53796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 1000); 53896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 53996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 54096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_setup_rx_urbs(struct esd_usb2 *dev) 54196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 54296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i, err = 0; 54396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 54496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (dev->rxinitdone) 54596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 54696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 54796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < MAX_RX_URBS; i++) { 54896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct urb *urb = NULL; 54996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 *buf = NULL; 55096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 55196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* create a URB, and a buffer for it */ 55296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb = usb_alloc_urb(0, GFP_KERNEL); 55396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!urb) { 55496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_warn(dev->udev->dev.parent, 55596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "No memory left for URBs\n"); 55696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = -ENOMEM; 55796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 55896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 55996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 56096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, 56196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs &urb->transfer_dma); 56296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!buf) { 56396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_warn(dev->udev->dev.parent, 56496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "No memory left for USB buffer\n"); 56596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = -ENOMEM; 56696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto freeurb; 56796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 56896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 56996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_fill_bulk_urb(urb, dev->udev, 57096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_rcvbulkpipe(dev->udev, 1), 57196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs buf, RX_BUFFER_SIZE, 57296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs esd_usb2_read_bulk_callback, dev); 57396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 57496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_anchor_urb(urb, &dev->rx_submitted); 57596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 57696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = usb_submit_urb(urb, GFP_KERNEL); 57796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) { 57896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_unanchor_urb(urb); 57996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, 58096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb->transfer_dma); 58196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 58296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 58396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsfreeurb: 58496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* Drop reference, USB core will take care of freeing it */ 58596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_free_urb(urb); 58696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) 58796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 58896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 58996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 59096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* Did we submit any URBs */ 59196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (i == 0) { 59296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(dev->udev->dev.parent, "couldn't setup read URBs\n"); 59396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return err; 59496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 59596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 59696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* Warn if we've couldn't transmit all the URBs */ 59796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (i < MAX_RX_URBS) { 59896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_warn(dev->udev->dev.parent, 59996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "rx performance may be slow\n"); 60096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 60196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 60296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev->rxinitdone = 1; 60396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 60496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 60596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 60696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* 60796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * Start interface 60896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 60996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_start(struct esd_usb2_net_priv *priv) 61096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 61196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = priv->usb2; 61296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device *netdev = priv->netdev; 61396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg msg; 61496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int err, i; 61596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 61696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* 61796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * Enable all IDs 61896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * The IDADD message takes up to 64 32 bit bitmasks (2048 bits). 61996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * Each bit represents one 11 bit CAN identifier. A set bit 62096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * enables reception of the corresponding CAN identifier. A cleared 62196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * bit disabled this identifier. An additional bitmask value 62296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * following the CAN 2.0A bits is used to enable reception of 62396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * extended CAN frames. Only the LSB of this final mask is checked 62496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * for the complete 29 bit ID range. The IDADD message also allows 62596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * filter configuration for an ID subset. In this case you can add 62696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * the number of the starting bitmask (0..64) to the filter.option 62796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * field followed by only some bitmasks. 62896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 62996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.cmd = CMD_IDADD; 63096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; 63196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.filter.net = priv->index; 63296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */ 63396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < ESD_MAX_ID_SEGMENT; i++) 63496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.filter.mask[i] = cpu_to_le32(0xffffffff); 63596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* enable 29bit extended IDs */ 63696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); 63796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 63896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = esd_usb2_send_msg(dev, &msg); 63996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) 64096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto failed; 64196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 64296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = esd_usb2_setup_rx_urbs(dev); 64396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) 64496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto failed; 64596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 64696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state = CAN_STATE_ERROR_ACTIVE; 64796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 64896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 64996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 65096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsfailed: 65196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err == -ENODEV) 65296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_device_detach(netdev); 65396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 65496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(netdev->dev.parent, "couldn't start device: %d\n", err); 65596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 65696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return err; 65796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 65896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 65996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic void unlink_all_urbs(struct esd_usb2 *dev) 66096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 66196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv; 6620b32211164da2b100553cb45e4e862f09c5cab11roel kluin int i, j; 66396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 66496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_kill_anchored_urbs(&dev->rx_submitted); 66596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < dev->net_count; i++) { 66696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv = dev->nets[i]; 66796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (priv) { 66896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_kill_anchored_urbs(&priv->tx_submitted); 66996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs atomic_set(&priv->active_tx_jobs, 0); 67096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 6710b32211164da2b100553cb45e4e862f09c5cab11roel kluin for (j = 0; j < MAX_TX_URBS; j++) 6720b32211164da2b100553cb45e4e862f09c5cab11roel kluin priv->tx_contexts[j].echo_index = MAX_TX_URBS; 67396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 67496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 67596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 67696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 67796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_open(struct net_device *netdev) 67896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 67996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv = netdev_priv(netdev); 68096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int err; 68196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 68296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* common open */ 68396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = open_candev(netdev); 68496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) 68596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return err; 68696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 68796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* finally start device */ 68896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = esd_usb2_start(priv); 68996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) { 69096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_warn(netdev->dev.parent, 69196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "couldn't start device: %d\n", err); 69296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs close_candev(netdev); 69396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return err; 69496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 69596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 69696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->open_time = jiffies; 69796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 69896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_start_queue(netdev); 69996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 70096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 70196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 70296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 70396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb, 70496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device *netdev) 70596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 70696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv = netdev_priv(netdev); 70796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = priv->usb2; 70896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_tx_urb_context *context = NULL; 70996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device_stats *stats = &netdev->stats; 71096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct can_frame *cf = (struct can_frame *)skb->data; 71196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg *msg; 71296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct urb *urb; 71396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u8 *buf; 71496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i, err; 71596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int ret = NETDEV_TX_OK; 71696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs size_t size = sizeof(struct esd_usb2_msg); 71796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 71896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (can_dropped_invalid_skb(netdev, skb)) 71996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return NETDEV_TX_OK; 72096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 72196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* create a URB, and a buffer for it, and copy the data to the URB */ 72296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb = usb_alloc_urb(0, GFP_ATOMIC); 72396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!urb) { 72496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(netdev->dev.parent, "No memory left for URBs\n"); 72596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->tx_dropped++; 72696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_kfree_skb(skb); 72796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto nourbmem; 72896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 72996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 73096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, 73196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs &urb->transfer_dma); 73296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!buf) { 73396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(netdev->dev.parent, "No memory left for USB buffer\n"); 73496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->tx_dropped++; 73596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_kfree_skb(skb); 73696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto nobufmem; 73796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 73896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 73996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg = (struct esd_usb2_msg *)buf; 74096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 74196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.hdr.len = 3; /* minimal length */ 74296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.hdr.cmd = CMD_CAN_TX; 74396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.tx.net = priv->index; 74496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.tx.dlc = cf->can_dlc; 74596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.tx.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK); 74696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 74796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (cf->can_id & CAN_RTR_FLAG) 74896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.tx.dlc |= ESD_RTR; 74996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 75096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (cf->can_id & CAN_EFF_FLAG) 75196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.tx.id |= cpu_to_le32(ESD_EXTID); 75296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 75396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < cf->can_dlc; i++) 75496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.tx.data[i] = cf->data[i]; 75596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 75696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.hdr.len += (cf->can_dlc + 3) >> 2; 75796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 75896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < MAX_TX_URBS; i++) { 75996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) { 76096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs context = &priv->tx_contexts[i]; 76196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 76296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 76396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 76496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 76596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* 76696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * This may never happen. 76796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 76896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!context) { 76996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_warn(netdev->dev.parent, "couldn't find free context\n"); 77096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs ret = NETDEV_TX_BUSY; 77196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto releasebuf; 77296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 77396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 77496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs context->priv = priv; 77596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs context->echo_index = i; 77696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs context->dlc = cf->can_dlc; 77796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 77896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* hnd must not be 0 - MSB is stripped in txdone handling */ 77996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.tx.hnd = 0x80000000 | i; /* returned in TX done message */ 78096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 78196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf, 78296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg->msg.hdr.len << 2, 78396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs esd_usb2_write_bulk_callback, context); 78496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 78596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; 78696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 78796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_anchor_urb(urb, &priv->tx_submitted); 78896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 78996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs can_put_echo_skb(skb, netdev, context->echo_index); 79096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 79196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs atomic_inc(&priv->active_tx_jobs); 79296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 79396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* Slow down tx path */ 79496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (atomic_read(&priv->active_tx_jobs) >= MAX_TX_URBS) 79596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_stop_queue(netdev); 79696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 79796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = usb_submit_urb(urb, GFP_ATOMIC); 79896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) { 79996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs can_free_echo_skb(netdev, context->echo_index); 80096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 80196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs atomic_dec(&priv->active_tx_jobs); 80296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_unanchor_urb(urb); 80396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 80496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs stats->tx_dropped++; 80596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 80696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err == -ENODEV) 80796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_device_detach(netdev); 80896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs else 80996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_warn(netdev->dev.parent, "failed tx_urb %d\n", err); 81096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 81196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto releasebuf; 81296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 81396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 81496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netdev->trans_start = jiffies; 81596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 81696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* 81796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * Release our reference to this URB, the USB core will eventually free 81896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * it entirely. 81996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 82096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_free_urb(urb); 82196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 82296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return NETDEV_TX_OK; 82396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 82496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsreleasebuf: 82596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_free_coherent(dev->udev, size, buf, urb->transfer_dma); 82696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 82796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsnobufmem: 82896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_free_urb(urb); 82996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 83096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsnourbmem: 83196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return ret; 83296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 83396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 83496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_close(struct net_device *netdev) 83596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 83696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv = netdev_priv(netdev); 83796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg msg; 83896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i; 83996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 84096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* Disable all IDs (see esd_usb2_start()) */ 84196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.cmd = CMD_IDADD; 84296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.len = 2 + ESD_MAX_ID_SEGMENT; 84396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.filter.net = priv->index; 84496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.filter.option = ESD_ID_ENABLE; /* start with segment 0 */ 84596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++) 84696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.filter.mask[i] = 0; 84796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (esd_usb2_send_msg(priv->usb2, &msg) < 0) 84896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(netdev->dev.parent, "sending idadd message failed\n"); 84996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 85096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* set CAN controller to reset mode */ 85196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.len = 2; 85296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.cmd = CMD_SETBAUD; 85396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.setbaud.net = priv->index; 85496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.setbaud.rsvd = 0; 85596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.setbaud.baud = cpu_to_le32(ESD_USB2_NO_BAUDRATE); 85696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (esd_usb2_send_msg(priv->usb2, &msg) < 0) 85796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(netdev->dev.parent, "sending setbaud message failed\n"); 85896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 85996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state = CAN_STATE_STOPPED; 86096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 86196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_stop_queue(netdev); 86296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 86396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs close_candev(netdev); 86496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 86596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->open_time = 0; 86696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 86796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 86896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 86996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 87096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic const struct net_device_ops esd_usb2_netdev_ops = { 87196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .ndo_open = esd_usb2_open, 87296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .ndo_stop = esd_usb2_close, 87396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .ndo_start_xmit = esd_usb2_start_xmit, 87496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 87596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 87696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic struct can_bittiming_const esd_usb2_bittiming_const = { 87796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .name = "esd_usb2", 87896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .tseg1_min = ESD_USB2_TSEG1_MIN, 87996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .tseg1_max = ESD_USB2_TSEG1_MAX, 88096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .tseg2_min = ESD_USB2_TSEG2_MIN, 88196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .tseg2_max = ESD_USB2_TSEG2_MAX, 88296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .sjw_max = ESD_USB2_SJW_MAX, 88396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .brp_min = ESD_USB2_BRP_MIN, 88496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .brp_max = ESD_USB2_BRP_MAX, 88596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .brp_inc = ESD_USB2_BRP_INC, 88696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 88796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 88896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_set_bittiming(struct net_device *netdev) 88996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 89096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv = netdev_priv(netdev); 89196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct can_bittiming *bt = &priv->can.bittiming; 89296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg msg; 89396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs u32 canbtr; 89496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 89596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs canbtr = ESD_USB2_UBR; 89696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1); 89796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1)) 89896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs << ESD_USB2_SJW_SHIFT; 89996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1) 90096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs & (ESD_USB2_TSEG1_MAX - 1)) 90196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs << ESD_USB2_TSEG1_SHIFT; 90296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs canbtr |= ((bt->phase_seg2 - 1) & (ESD_USB2_TSEG2_MAX - 1)) 90396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs << ESD_USB2_TSEG2_SHIFT; 90496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) 90596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs canbtr |= ESD_USB2_3_SAMPLES; 90696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 90796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.len = 2; 90896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.cmd = CMD_SETBAUD; 90996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.setbaud.net = priv->index; 91096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.setbaud.rsvd = 0; 91196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.setbaud.baud = cpu_to_le32(canbtr); 91296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 91396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_info(netdev->dev.parent, "setting BTR=%#x\n", canbtr); 91496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 91596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return esd_usb2_send_msg(priv->usb2, &msg); 91696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 91796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 91896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_get_berr_counter(const struct net_device *netdev, 91996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct can_berr_counter *bec) 92096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 92196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv = netdev_priv(netdev); 92296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 92396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs bec->txerr = priv->bec.txerr; 92496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs bec->rxerr = priv->bec.rxerr; 92596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 92696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 92796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 92896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 92996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode) 93096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 93196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv = netdev_priv(netdev); 93296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 93396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!priv->open_time) 93496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return -EINVAL; 93596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 93696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs switch (mode) { 93796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs case CAN_MODE_START: 93896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netif_wake_queue(netdev); 93996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs break; 94096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 94196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs default: 94296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return -EOPNOTSUPP; 94396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 94496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 94596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 94696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 94796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 94896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_probe_one_net(struct usb_interface *intf, int index) 94996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 95096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = usb_get_intfdata(intf); 95196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device *netdev; 95296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_net_priv *priv; 95396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int err = 0; 95496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i; 95596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 95696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS); 95796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!netdev) { 95896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(&intf->dev, "couldn't alloc candev\n"); 95996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = -ENOMEM; 96096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto done; 96196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 96296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 96396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv = netdev_priv(netdev); 96496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 96596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs init_usb_anchor(&priv->tx_submitted); 96696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs atomic_set(&priv->active_tx_jobs, 0); 96796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 96896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < MAX_TX_URBS; i++) 96996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->tx_contexts[i].echo_index = MAX_TX_URBS; 97096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 97196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->usb2 = dev; 97296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->netdev = netdev; 97396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->index = index; 97496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 97596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.state = CAN_STATE_STOPPED; 97696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.clock.freq = ESD_USB2_CAN_CLOCK; 97796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.bittiming_const = &esd_usb2_bittiming_const; 97896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.do_set_bittiming = esd_usb2_set_bittiming; 97996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.do_set_mode = esd_usb2_set_mode; 98096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.do_get_berr_counter = esd_usb2_get_berr_counter; 98196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; 98296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 98396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netdev->flags |= IFF_ECHO; /* we support local echo */ 98496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 98596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netdev->netdev_ops = &esd_usb2_netdev_ops; 98696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 98796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs SET_NETDEV_DEV(netdev, &intf->dev); 98896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 98996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = register_candev(netdev); 99096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err) { 99196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(&intf->dev, 99296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "couldn't register CAN device: %d\n", err); 99396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs free_candev(netdev); 99496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = -ENOMEM; 99596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto done; 99696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 99796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 99896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev->nets[index] = priv; 99996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_info(netdev->dev.parent, "device %s registered\n", netdev->name); 100096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 100196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsdone: 100296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return err; 100396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 100496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 100596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* 100696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * probe function for new USB2 devices 100796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * 100896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * check version information and number of available 100996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * CAN interfaces 101096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 101196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic int esd_usb2_probe(struct usb_interface *intf, 101296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs const struct usb_device_id *id) 101396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 101496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev; 101596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2_msg msg; 101696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i, err; 101796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 101896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev = kzalloc(sizeof(*dev), GFP_KERNEL); 101996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (!dev) { 102096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = -ENOMEM; 102196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto done; 102296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 102396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 102496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev->udev = interface_to_usbdev(intf); 102596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 102696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs init_usb_anchor(&dev->rx_submitted); 102796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 102896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_set_intfdata(intf, dev); 102996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 103096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* query number of CAN interfaces (nets) */ 103196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.cmd = CMD_VERSION; 103296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.hdr.len = 2; 103396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.version.rsvd = 0; 103496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.version.flags = 0; 103596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs msg.msg.version.drv_version = 0; 103696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 103796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = esd_usb2_send_msg(dev, &msg); 103896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err < 0) { 103996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(&intf->dev, "sending version message failed\n"); 104096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto free_dev; 104196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 104296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 104396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs err = esd_usb2_wait_msg(dev, &msg); 104496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (err < 0) { 104596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(&intf->dev, "no version message answer\n"); 104696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs goto free_dev; 104796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 104896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 104996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev->net_count = (int)msg.msg.version_reply.nets; 105096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev->version = le32_to_cpu(msg.msg.version_reply.version); 105196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 105296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (device_create_file(&intf->dev, &dev_attr_firmware)) 105396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(&intf->dev, 105496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "Couldn't create device file for firmware\n"); 105596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 105696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (device_create_file(&intf->dev, &dev_attr_hardware)) 105796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(&intf->dev, 105896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "Couldn't create device file for hardware\n"); 105996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 106096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (device_create_file(&intf->dev, &dev_attr_nets)) 106196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs dev_err(&intf->dev, 106296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs "Couldn't create device file for nets\n"); 106396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 106496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs /* do per device probing */ 106596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < dev->net_count; i++) 106696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs esd_usb2_probe_one_net(intf, i); 106796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 106896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return 0; 106996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 107096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsfree_dev: 107196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs kfree(dev); 107296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsdone: 107396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs return err; 107496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 107596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 107696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* 107796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs * called by the usb core when the device is removed from the system 107896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs */ 107996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic void esd_usb2_disconnect(struct usb_interface *intf) 108096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs{ 108196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct esd_usb2 *dev = usb_get_intfdata(intf); 108296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs struct net_device *netdev; 108396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs int i; 108496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 108596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs device_remove_file(&intf->dev, &dev_attr_firmware); 108696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs device_remove_file(&intf->dev, &dev_attr_hardware); 108796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs device_remove_file(&intf->dev, &dev_attr_nets); 108896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 108996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs usb_set_intfdata(intf, NULL); 109096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 109196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (dev) { 109296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs for (i = 0; i < dev->net_count; i++) { 109396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs if (dev->nets[i]) { 109496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs netdev = dev->nets[i]->netdev; 109596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs unregister_netdev(netdev); 109696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs free_candev(netdev); 109796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 109896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 109996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs unlink_all_urbs(dev); 110096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs } 110196d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs} 110296d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 110396d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs/* usb specific object needed to register this driver with the usb subsystem */ 110496d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchsstatic struct usb_driver esd_usb2_driver = { 110596d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .name = "esd_usb2", 110696d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .probe = esd_usb2_probe, 110796d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .disconnect = esd_usb2_disconnect, 110896d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs .id_table = esd_usb2_table, 110996d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs}; 111096d8e90382dc336b5de401164597edfdc2e8d9f1Matthias Fuchs 1111d632eb1bf22e11def74e4e53cc47d790fbdba105Greg Kroah-Hartmanmodule_usb_driver(esd_usb2_driver); 1112