linux-can-next-for-6.1-20220923
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEBsvAIBsPu6mG7thcrX5LkNig010FAmMtnygTHG1rbEBwZW5n dXRyb25peC5kZQAKCRCtfkuQ2KDTXXOLCACFQGHCZrUGdWBw83UDA9r/lHuiIRuX ELaSq1h9PJ2BC2+4t/4uDClJgvSYkxJkomNUVDDvbMK8gNTdVdIuHzaR12kerVWs ArG/g0tjRE3ed5I3JWIOZ/ukfVmsVy/Rm/cwtqtWibJNSFtZuiodN1sYtS3Bv4i3 9sAdU6++LW/4OSAMss0+6VakC27/D5GJEZuEdYveqtf/TunrqNKGL2M5YmbenRoD Bnx7FIiPHeL8pYz97W5ZEyGzZH90AuKOvHmx3+cHgZVHDzyBKd0UNLgisYFwXo9w +9tfyZMZqzIZL2R0f3GVGPSvJGnLaX73bdgc8FAas/mY9WJze7plYWKt =8zkH -----END PGP SIGNATURE----- Merge tag 'linux-can-next-for-6.1-20220923' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next Marc Kleine-Budde says: ==================== pull-request: can-next 2022-09-23 The first 2 patches are by Ziyang Xuan and optimize registration and the sending in the CAN BCM protocol a bit. The next 8 patches target the gs_usb driver. 7 are by me and first fix the time hardware stamping support (added during this net-next cycle), rename a variable, convert the usb_control_msg + manual kmalloc()/kfree() to usb_control_msg_{send,rev}(), clean up the error handling and add switchable termination support. The patch by Rhett Aultman and Vasanth Sadhasivan convert the driver from usb_alloc_coherent()/usb_free_coherent() to kmalloc()/URB_FREE_BUFFER. The last patch is by Shang XiaoJing and removes an unneeded call to dev_err() from the ctucanfd driver. * tag 'linux-can-next-for-6.1-20220923' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: can: ctucanfd: Remove redundant dev_err call can: gs_usb: remove dma allocations can: gs_usb: add switchable termination support can: gs_usb: gs_make_candev(): clean up error handling can: gs_usb: convert from usb_control_msg() to usb_control_msg_{send,recv}() can: gs_usb: gs_cmd_reset(): rename variable holding struct gs_can pointer to dev can: gs_usb: gs_can_open(): initialize time counter before starting device can: gs_usb: add missing lock to protect struct timecounter::cycle_last can: gs_usb: gs_usb_get_timestamp(): fix endpoint parameter for usb_control_msg_recv() can: bcm: check the result of can_send() in bcm_can_tx() can: bcm: registration process optimization in bcm_module_init() ==================== Link: https://lore.kernel.org/r/20220923120859.740577-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
4dfa5f05ff
|
@ -58,7 +58,6 @@ static int ctucan_platform_probe(struct platform_device *pdev)
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
addr = devm_ioremap_resource(dev, res);
|
addr = devm_ioremap_resource(dev, res);
|
||||||
if (IS_ERR(addr)) {
|
if (IS_ERR(addr)) {
|
||||||
dev_err(dev, "Cannot remap address.\n");
|
|
||||||
ret = PTR_ERR(addr);
|
ret = PTR_ERR(addr);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,8 @@ enum gs_usb_breq {
|
||||||
GS_USB_BREQ_SET_USER_ID,
|
GS_USB_BREQ_SET_USER_ID,
|
||||||
GS_USB_BREQ_DATA_BITTIMING,
|
GS_USB_BREQ_DATA_BITTIMING,
|
||||||
GS_USB_BREQ_BT_CONST_EXT,
|
GS_USB_BREQ_BT_CONST_EXT,
|
||||||
|
GS_USB_BREQ_SET_TERMINATION,
|
||||||
|
GS_USB_BREQ_GET_TERMINATION,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum gs_can_mode {
|
enum gs_can_mode {
|
||||||
|
@ -87,6 +89,14 @@ enum gs_can_identify_mode {
|
||||||
GS_CAN_IDENTIFY_ON
|
GS_CAN_IDENTIFY_ON
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum gs_can_termination_state {
|
||||||
|
GS_CAN_TERMINATION_STATE_OFF = 0,
|
||||||
|
GS_CAN_TERMINATION_STATE_ON
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GS_USB_TERMINATION_DISABLED CAN_TERMINATION_DISABLED
|
||||||
|
#define GS_USB_TERMINATION_ENABLED 120
|
||||||
|
|
||||||
/* data types passed between host and device */
|
/* data types passed between host and device */
|
||||||
|
|
||||||
/* The firmware on the original USB2CAN by Geschwister Schneider
|
/* The firmware on the original USB2CAN by Geschwister Schneider
|
||||||
|
@ -123,6 +133,7 @@ struct gs_device_config {
|
||||||
#define GS_CAN_MODE_FD BIT(8)
|
#define GS_CAN_MODE_FD BIT(8)
|
||||||
/* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */
|
/* GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9) */
|
||||||
/* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */
|
/* GS_CAN_FEATURE_BT_CONST_EXT BIT(10) */
|
||||||
|
/* GS_CAN_FEATURE_TERMINATION BIT(11) */
|
||||||
|
|
||||||
struct gs_device_mode {
|
struct gs_device_mode {
|
||||||
__le32 mode;
|
__le32 mode;
|
||||||
|
@ -147,6 +158,10 @@ struct gs_identify_mode {
|
||||||
__le32 mode;
|
__le32 mode;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
struct gs_device_termination_state {
|
||||||
|
__le32 state;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0)
|
#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0)
|
||||||
#define GS_CAN_FEATURE_LOOP_BACK BIT(1)
|
#define GS_CAN_FEATURE_LOOP_BACK BIT(1)
|
||||||
#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2)
|
#define GS_CAN_FEATURE_TRIPLE_SAMPLE BIT(2)
|
||||||
|
@ -158,7 +173,8 @@ struct gs_identify_mode {
|
||||||
#define GS_CAN_FEATURE_FD BIT(8)
|
#define GS_CAN_FEATURE_FD BIT(8)
|
||||||
#define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9)
|
#define GS_CAN_FEATURE_REQ_USB_QUIRK_LPC546XX BIT(9)
|
||||||
#define GS_CAN_FEATURE_BT_CONST_EXT BIT(10)
|
#define GS_CAN_FEATURE_BT_CONST_EXT BIT(10)
|
||||||
#define GS_CAN_FEATURE_MASK GENMASK(10, 0)
|
#define GS_CAN_FEATURE_TERMINATION BIT(11)
|
||||||
|
#define GS_CAN_FEATURE_MASK GENMASK(11, 0)
|
||||||
|
|
||||||
/* internal quirks - keep in GS_CAN_FEATURE space for now */
|
/* internal quirks - keep in GS_CAN_FEATURE space for now */
|
||||||
|
|
||||||
|
@ -286,6 +302,7 @@ struct gs_can {
|
||||||
/* time counter for hardware timestamps */
|
/* time counter for hardware timestamps */
|
||||||
struct cyclecounter cc;
|
struct cyclecounter cc;
|
||||||
struct timecounter tc;
|
struct timecounter tc;
|
||||||
|
spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
|
||||||
struct delayed_work timestamp;
|
struct delayed_work timestamp;
|
||||||
|
|
||||||
u32 feature;
|
u32 feature;
|
||||||
|
@ -297,8 +314,6 @@ struct gs_can {
|
||||||
|
|
||||||
struct usb_anchor tx_submitted;
|
struct usb_anchor tx_submitted;
|
||||||
atomic_t active_tx_urbs;
|
atomic_t active_tx_urbs;
|
||||||
void *rxbuf[GS_MAX_RX_URBS];
|
|
||||||
dma_addr_t rxbuf_dma[GS_MAX_RX_URBS];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* usb interface struct */
|
/* usb interface struct */
|
||||||
|
@ -357,27 +372,17 @@ static struct gs_tx_context *gs_get_tx_context(struct gs_can *dev,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gs_cmd_reset(struct gs_can *gsdev)
|
static int gs_cmd_reset(struct gs_can *dev)
|
||||||
{
|
{
|
||||||
struct gs_device_mode *dm;
|
struct gs_device_mode dm = {
|
||||||
struct usb_interface *intf = gsdev->iface;
|
.mode = GS_CAN_MODE_RESET,
|
||||||
int rc;
|
};
|
||||||
|
|
||||||
dm = kzalloc(sizeof(*dm), GFP_KERNEL);
|
return usb_control_msg_send(interface_to_usbdev(dev->iface), 0,
|
||||||
if (!dm)
|
GS_USB_BREQ_MODE,
|
||||||
return -ENOMEM;
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
|
dev->channel, 0, &dm, sizeof(dm), 1000,
|
||||||
dm->mode = GS_CAN_MODE_RESET;
|
GFP_KERNEL);
|
||||||
|
|
||||||
rc = usb_control_msg(interface_to_usbdev(intf),
|
|
||||||
usb_sndctrlpipe(interface_to_usbdev(intf), 0),
|
|
||||||
GS_USB_BREQ_MODE,
|
|
||||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
|
||||||
gsdev->channel, 0, dm, sizeof(*dm), 1000);
|
|
||||||
|
|
||||||
kfree(dm);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int gs_usb_get_timestamp(const struct gs_can *dev,
|
static inline int gs_usb_get_timestamp(const struct gs_can *dev,
|
||||||
|
@ -386,8 +391,7 @@ static inline int gs_usb_get_timestamp(const struct gs_can *dev,
|
||||||
__le32 timestamp;
|
__le32 timestamp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = usb_control_msg_recv(interface_to_usbdev(dev->iface),
|
rc = usb_control_msg_recv(interface_to_usbdev(dev->iface), 0,
|
||||||
usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0),
|
|
||||||
GS_USB_BREQ_TIMESTAMP,
|
GS_USB_BREQ_TIMESTAMP,
|
||||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
dev->channel, 0,
|
dev->channel, 0,
|
||||||
|
@ -402,14 +406,18 @@ static inline int gs_usb_get_timestamp(const struct gs_can *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u64 gs_usb_timestamp_read(const struct cyclecounter *cc)
|
static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
|
||||||
{
|
{
|
||||||
const struct gs_can *dev;
|
struct gs_can *dev = container_of(cc, struct gs_can, cc);
|
||||||
u32 timestamp = 0;
|
u32 timestamp = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
dev = container_of(cc, struct gs_can, cc);
|
lockdep_assert_held(&dev->tc_lock);
|
||||||
|
|
||||||
|
/* drop lock for synchronous USB transfer */
|
||||||
|
spin_unlock_bh(&dev->tc_lock);
|
||||||
err = gs_usb_get_timestamp(dev, ×tamp);
|
err = gs_usb_get_timestamp(dev, ×tamp);
|
||||||
|
spin_lock_bh(&dev->tc_lock);
|
||||||
if (err)
|
if (err)
|
||||||
netdev_err(dev->netdev,
|
netdev_err(dev->netdev,
|
||||||
"Error %d while reading timestamp. HW timestamps may be inaccurate.",
|
"Error %d while reading timestamp. HW timestamps may be inaccurate.",
|
||||||
|
@ -424,19 +432,24 @@ static void gs_usb_timestamp_work(struct work_struct *work)
|
||||||
struct gs_can *dev;
|
struct gs_can *dev;
|
||||||
|
|
||||||
dev = container_of(delayed_work, struct gs_can, timestamp);
|
dev = container_of(delayed_work, struct gs_can, timestamp);
|
||||||
|
spin_lock_bh(&dev->tc_lock);
|
||||||
timecounter_read(&dev->tc);
|
timecounter_read(&dev->tc);
|
||||||
|
spin_unlock_bh(&dev->tc_lock);
|
||||||
|
|
||||||
schedule_delayed_work(&dev->timestamp,
|
schedule_delayed_work(&dev->timestamp,
|
||||||
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
|
GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gs_usb_skb_set_timestamp(const struct gs_can *dev,
|
static void gs_usb_skb_set_timestamp(struct gs_can *dev,
|
||||||
struct sk_buff *skb, u32 timestamp)
|
struct sk_buff *skb, u32 timestamp)
|
||||||
{
|
{
|
||||||
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
|
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
|
||||||
u64 ns;
|
u64 ns;
|
||||||
|
|
||||||
|
spin_lock_bh(&dev->tc_lock);
|
||||||
ns = timecounter_cyc2time(&dev->tc, timestamp);
|
ns = timecounter_cyc2time(&dev->tc, timestamp);
|
||||||
|
spin_unlock_bh(&dev->tc_lock);
|
||||||
|
|
||||||
hwtstamps->hwtstamp = ns_to_ktime(ns);
|
hwtstamps->hwtstamp = ns_to_ktime(ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +462,10 @@ static void gs_usb_timestamp_init(struct gs_can *dev)
|
||||||
cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
|
cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
|
||||||
cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
|
cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
|
||||||
|
|
||||||
|
spin_lock_init(&dev->tc_lock);
|
||||||
|
spin_lock_bh(&dev->tc_lock);
|
||||||
timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns());
|
timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns());
|
||||||
|
spin_unlock_bh(&dev->tc_lock);
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work);
|
INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work);
|
||||||
schedule_delayed_work(&dev->timestamp,
|
schedule_delayed_work(&dev->timestamp,
|
||||||
|
@ -486,7 +502,7 @@ static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gs_usb_set_timestamp(const struct gs_can *dev, struct sk_buff *skb,
|
static void gs_usb_set_timestamp(struct gs_can *dev, struct sk_buff *skb,
|
||||||
const struct gs_host_frame *hf)
|
const struct gs_host_frame *hf)
|
||||||
{
|
{
|
||||||
u32 timestamp;
|
u32 timestamp;
|
||||||
|
@ -644,72 +660,44 @@ static int gs_usb_set_bittiming(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct gs_can *dev = netdev_priv(netdev);
|
struct gs_can *dev = netdev_priv(netdev);
|
||||||
struct can_bittiming *bt = &dev->can.bittiming;
|
struct can_bittiming *bt = &dev->can.bittiming;
|
||||||
struct usb_interface *intf = dev->iface;
|
struct gs_device_bittiming dbt = {
|
||||||
int rc;
|
.prop_seg = cpu_to_le32(bt->prop_seg),
|
||||||
struct gs_device_bittiming *dbt;
|
.phase_seg1 = cpu_to_le32(bt->phase_seg1),
|
||||||
|
.phase_seg2 = cpu_to_le32(bt->phase_seg2),
|
||||||
dbt = kmalloc(sizeof(*dbt), GFP_KERNEL);
|
.sjw = cpu_to_le32(bt->sjw),
|
||||||
if (!dbt)
|
.brp = cpu_to_le32(bt->brp),
|
||||||
return -ENOMEM;
|
};
|
||||||
|
|
||||||
dbt->prop_seg = cpu_to_le32(bt->prop_seg);
|
|
||||||
dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1);
|
|
||||||
dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2);
|
|
||||||
dbt->sjw = cpu_to_le32(bt->sjw);
|
|
||||||
dbt->brp = cpu_to_le32(bt->brp);
|
|
||||||
|
|
||||||
/* request bit timings */
|
/* request bit timings */
|
||||||
rc = usb_control_msg(interface_to_usbdev(intf),
|
return usb_control_msg_send(interface_to_usbdev(dev->iface), 0,
|
||||||
usb_sndctrlpipe(interface_to_usbdev(intf), 0),
|
GS_USB_BREQ_BITTIMING,
|
||||||
GS_USB_BREQ_BITTIMING,
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
dev->channel, 0, &dbt, sizeof(dbt), 1000,
|
||||||
dev->channel, 0, dbt, sizeof(*dbt), 1000);
|
GFP_KERNEL);
|
||||||
|
|
||||||
kfree(dbt);
|
|
||||||
|
|
||||||
if (rc < 0)
|
|
||||||
dev_err(netdev->dev.parent, "Couldn't set bittimings (err=%d)",
|
|
||||||
rc);
|
|
||||||
|
|
||||||
return (rc > 0) ? 0 : rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gs_usb_set_data_bittiming(struct net_device *netdev)
|
static int gs_usb_set_data_bittiming(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct gs_can *dev = netdev_priv(netdev);
|
struct gs_can *dev = netdev_priv(netdev);
|
||||||
struct can_bittiming *bt = &dev->can.data_bittiming;
|
struct can_bittiming *bt = &dev->can.data_bittiming;
|
||||||
struct usb_interface *intf = dev->iface;
|
struct gs_device_bittiming dbt = {
|
||||||
struct gs_device_bittiming *dbt;
|
.prop_seg = cpu_to_le32(bt->prop_seg),
|
||||||
|
.phase_seg1 = cpu_to_le32(bt->phase_seg1),
|
||||||
|
.phase_seg2 = cpu_to_le32(bt->phase_seg2),
|
||||||
|
.sjw = cpu_to_le32(bt->sjw),
|
||||||
|
.brp = cpu_to_le32(bt->brp),
|
||||||
|
};
|
||||||
u8 request = GS_USB_BREQ_DATA_BITTIMING;
|
u8 request = GS_USB_BREQ_DATA_BITTIMING;
|
||||||
int rc;
|
|
||||||
|
|
||||||
dbt = kmalloc(sizeof(*dbt), GFP_KERNEL);
|
|
||||||
if (!dbt)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
dbt->prop_seg = cpu_to_le32(bt->prop_seg);
|
|
||||||
dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1);
|
|
||||||
dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2);
|
|
||||||
dbt->sjw = cpu_to_le32(bt->sjw);
|
|
||||||
dbt->brp = cpu_to_le32(bt->brp);
|
|
||||||
|
|
||||||
if (dev->feature & GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO)
|
if (dev->feature & GS_CAN_FEATURE_QUIRK_BREQ_CANTACT_PRO)
|
||||||
request = GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING;
|
request = GS_USB_BREQ_QUIRK_CANTACT_PRO_DATA_BITTIMING;
|
||||||
|
|
||||||
/* request bit timings */
|
/* request data bit timings */
|
||||||
rc = usb_control_msg(interface_to_usbdev(intf),
|
return usb_control_msg_send(interface_to_usbdev(dev->iface), 0,
|
||||||
usb_sndctrlpipe(interface_to_usbdev(intf), 0),
|
request,
|
||||||
request,
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
dev->channel, 0, &dbt, sizeof(dbt), 1000,
|
||||||
dev->channel, 0, dbt, sizeof(*dbt), 1000);
|
GFP_KERNEL);
|
||||||
|
|
||||||
kfree(dbt);
|
|
||||||
|
|
||||||
if (rc < 0)
|
|
||||||
dev_err(netdev->dev.parent,
|
|
||||||
"Couldn't set data bittimings (err=%d)", rc);
|
|
||||||
|
|
||||||
return (rc > 0) ? 0 : rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gs_usb_xmit_callback(struct urb *urb)
|
static void gs_usb_xmit_callback(struct urb *urb)
|
||||||
|
@ -720,9 +708,6 @@ static void gs_usb_xmit_callback(struct urb *urb)
|
||||||
|
|
||||||
if (urb->status)
|
if (urb->status)
|
||||||
netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id);
|
netdev_info(netdev, "usb xmit fail %u\n", txc->echo_id);
|
||||||
|
|
||||||
usb_free_coherent(urb->dev, urb->transfer_buffer_length,
|
|
||||||
urb->transfer_buffer, urb->transfer_dma);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
||||||
|
@ -751,8 +736,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
||||||
if (!urb)
|
if (!urb)
|
||||||
goto nomem_urb;
|
goto nomem_urb;
|
||||||
|
|
||||||
hf = usb_alloc_coherent(dev->udev, dev->hf_size_tx, GFP_ATOMIC,
|
hf = kmalloc(dev->hf_size_tx, GFP_ATOMIC);
|
||||||
&urb->transfer_dma);
|
|
||||||
if (!hf) {
|
if (!hf) {
|
||||||
netdev_err(netdev, "No memory left for USB buffer\n");
|
netdev_err(netdev, "No memory left for USB buffer\n");
|
||||||
goto nomem_hf;
|
goto nomem_hf;
|
||||||
|
@ -796,7 +780,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
||||||
hf, dev->hf_size_tx,
|
hf, dev->hf_size_tx,
|
||||||
gs_usb_xmit_callback, txc);
|
gs_usb_xmit_callback, txc);
|
||||||
|
|
||||||
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
urb->transfer_flags |= URB_FREE_BUFFER;
|
||||||
usb_anchor_urb(urb, &dev->tx_submitted);
|
usb_anchor_urb(urb, &dev->tx_submitted);
|
||||||
|
|
||||||
can_put_echo_skb(skb, netdev, idx, 0);
|
can_put_echo_skb(skb, netdev, idx, 0);
|
||||||
|
@ -811,8 +795,6 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
||||||
gs_free_tx_context(txc);
|
gs_free_tx_context(txc);
|
||||||
|
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
usb_free_coherent(dev->udev, urb->transfer_buffer_length,
|
|
||||||
urb->transfer_buffer, urb->transfer_dma);
|
|
||||||
|
|
||||||
if (rc == -ENODEV) {
|
if (rc == -ENODEV) {
|
||||||
netif_device_detach(netdev);
|
netif_device_detach(netdev);
|
||||||
|
@ -832,8 +814,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
badidx:
|
badidx:
|
||||||
usb_free_coherent(dev->udev, urb->transfer_buffer_length,
|
kfree(hf);
|
||||||
urb->transfer_buffer, urb->transfer_dma);
|
|
||||||
nomem_hf:
|
nomem_hf:
|
||||||
usb_free_urb(urb);
|
usb_free_urb(urb);
|
||||||
|
|
||||||
|
@ -848,11 +829,13 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct gs_can *dev = netdev_priv(netdev);
|
struct gs_can *dev = netdev_priv(netdev);
|
||||||
struct gs_usb *parent = dev->parent;
|
struct gs_usb *parent = dev->parent;
|
||||||
int rc, i;
|
struct gs_device_mode dm = {
|
||||||
struct gs_device_mode *dm;
|
.mode = cpu_to_le32(GS_CAN_MODE_START),
|
||||||
|
};
|
||||||
struct gs_host_frame *hf;
|
struct gs_host_frame *hf;
|
||||||
u32 ctrlmode;
|
u32 ctrlmode;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
|
int rc, i;
|
||||||
|
|
||||||
rc = open_candev(netdev);
|
rc = open_candev(netdev);
|
||||||
if (rc)
|
if (rc)
|
||||||
|
@ -877,7 +860,6 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
for (i = 0; i < GS_MAX_RX_URBS; i++) {
|
for (i = 0; i < GS_MAX_RX_URBS; i++) {
|
||||||
struct urb *urb;
|
struct urb *urb;
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
dma_addr_t buf_dma;
|
|
||||||
|
|
||||||
/* alloc rx urb */
|
/* alloc rx urb */
|
||||||
urb = usb_alloc_urb(0, GFP_KERNEL);
|
urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
|
@ -885,10 +867,8 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* alloc rx buffer */
|
/* alloc rx buffer */
|
||||||
buf = usb_alloc_coherent(dev->udev,
|
buf = kmalloc(dev->parent->hf_size_rx,
|
||||||
dev->parent->hf_size_rx,
|
GFP_KERNEL);
|
||||||
GFP_KERNEL,
|
|
||||||
&buf_dma);
|
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
netdev_err(netdev,
|
netdev_err(netdev,
|
||||||
"No memory left for USB buffer\n");
|
"No memory left for USB buffer\n");
|
||||||
|
@ -896,8 +876,6 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
urb->transfer_dma = buf_dma;
|
|
||||||
|
|
||||||
/* fill, anchor, and submit rx urb */
|
/* fill, anchor, and submit rx urb */
|
||||||
usb_fill_bulk_urb(urb,
|
usb_fill_bulk_urb(urb,
|
||||||
dev->udev,
|
dev->udev,
|
||||||
|
@ -906,7 +884,7 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
buf,
|
buf,
|
||||||
dev->parent->hf_size_rx,
|
dev->parent->hf_size_rx,
|
||||||
gs_usb_receive_bulk_callback, parent);
|
gs_usb_receive_bulk_callback, parent);
|
||||||
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
urb->transfer_flags |= URB_FREE_BUFFER;
|
||||||
|
|
||||||
usb_anchor_urb(urb, &parent->rx_submitted);
|
usb_anchor_urb(urb, &parent->rx_submitted);
|
||||||
|
|
||||||
|
@ -919,17 +897,10 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
"usb_submit failed (err=%d)\n", rc);
|
"usb_submit failed (err=%d)\n", rc);
|
||||||
|
|
||||||
usb_unanchor_urb(urb);
|
usb_unanchor_urb(urb);
|
||||||
usb_free_coherent(dev->udev,
|
|
||||||
sizeof(struct gs_host_frame),
|
|
||||||
buf,
|
|
||||||
buf_dma);
|
|
||||||
usb_free_urb(urb);
|
usb_free_urb(urb);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->rxbuf[i] = buf;
|
|
||||||
dev->rxbuf_dma[i] = buf_dma;
|
|
||||||
|
|
||||||
/* Drop reference,
|
/* Drop reference,
|
||||||
* USB core will take care of freeing it
|
* USB core will take care of freeing it
|
||||||
*/
|
*/
|
||||||
|
@ -937,10 +908,6 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dm = kmalloc(sizeof(*dm), GFP_KERNEL);
|
|
||||||
if (!dm)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* flags */
|
/* flags */
|
||||||
if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
|
if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
|
||||||
flags |= GS_CAN_MODE_LOOP_BACK;
|
flags |= GS_CAN_MODE_LOOP_BACK;
|
||||||
|
@ -960,29 +927,26 @@ static int gs_can_open(struct net_device *netdev)
|
||||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||||
flags |= GS_CAN_MODE_HW_TIMESTAMP;
|
flags |= GS_CAN_MODE_HW_TIMESTAMP;
|
||||||
|
|
||||||
/* finally start device */
|
|
||||||
dev->can.state = CAN_STATE_ERROR_ACTIVE;
|
|
||||||
dm->mode = cpu_to_le32(GS_CAN_MODE_START);
|
|
||||||
dm->flags = cpu_to_le32(flags);
|
|
||||||
rc = usb_control_msg(interface_to_usbdev(dev->iface),
|
|
||||||
usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0),
|
|
||||||
GS_USB_BREQ_MODE,
|
|
||||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
|
||||||
dev->channel, 0, dm, sizeof(*dm), 1000);
|
|
||||||
|
|
||||||
if (rc < 0) {
|
|
||||||
netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
|
|
||||||
kfree(dm);
|
|
||||||
dev->can.state = CAN_STATE_STOPPED;
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
kfree(dm);
|
|
||||||
|
|
||||||
/* start polling timestamp */
|
/* start polling timestamp */
|
||||||
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||||
gs_usb_timestamp_init(dev);
|
gs_usb_timestamp_init(dev);
|
||||||
|
|
||||||
|
/* finally start device */
|
||||||
|
dev->can.state = CAN_STATE_ERROR_ACTIVE;
|
||||||
|
dm.flags = cpu_to_le32(flags);
|
||||||
|
rc = usb_control_msg_send(interface_to_usbdev(dev->iface), 0,
|
||||||
|
GS_USB_BREQ_MODE,
|
||||||
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
|
dev->channel, 0, &dm, sizeof(dm), 1000,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (rc) {
|
||||||
|
netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
|
||||||
|
if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
|
||||||
|
gs_usb_timestamp_stop(dev);
|
||||||
|
dev->can.state = CAN_STATE_STOPPED;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
parent->active_channels++;
|
parent->active_channels++;
|
||||||
if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
|
if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
|
||||||
netif_start_queue(netdev);
|
netif_start_queue(netdev);
|
||||||
|
@ -995,7 +959,6 @@ static int gs_can_close(struct net_device *netdev)
|
||||||
int rc;
|
int rc;
|
||||||
struct gs_can *dev = netdev_priv(netdev);
|
struct gs_can *dev = netdev_priv(netdev);
|
||||||
struct gs_usb *parent = dev->parent;
|
struct gs_usb *parent = dev->parent;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
netif_stop_queue(netdev);
|
netif_stop_queue(netdev);
|
||||||
|
|
||||||
|
@ -1007,11 +970,6 @@ static int gs_can_close(struct net_device *netdev)
|
||||||
parent->active_channels--;
|
parent->active_channels--;
|
||||||
if (!parent->active_channels) {
|
if (!parent->active_channels) {
|
||||||
usb_kill_anchored_urbs(&parent->rx_submitted);
|
usb_kill_anchored_urbs(&parent->rx_submitted);
|
||||||
for (i = 0; i < GS_MAX_RX_URBS; i++)
|
|
||||||
usb_free_coherent(dev->udev,
|
|
||||||
sizeof(struct gs_host_frame),
|
|
||||||
dev->rxbuf[i],
|
|
||||||
dev->rxbuf_dma[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stop sending URBs */
|
/* Stop sending URBs */
|
||||||
|
@ -1056,28 +1014,18 @@ static const struct net_device_ops gs_usb_netdev_ops = {
|
||||||
static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
|
static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
|
||||||
{
|
{
|
||||||
struct gs_can *dev = netdev_priv(netdev);
|
struct gs_can *dev = netdev_priv(netdev);
|
||||||
struct gs_identify_mode *imode;
|
struct gs_identify_mode imode;
|
||||||
int rc;
|
|
||||||
|
|
||||||
imode = kmalloc(sizeof(*imode), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!imode)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
if (do_identify)
|
if (do_identify)
|
||||||
imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
|
imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
|
||||||
else
|
else
|
||||||
imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);
|
imode.mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);
|
||||||
|
|
||||||
rc = usb_control_msg(interface_to_usbdev(dev->iface),
|
return usb_control_msg_send(interface_to_usbdev(dev->iface), 0,
|
||||||
usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0),
|
GS_USB_BREQ_IDENTIFY,
|
||||||
GS_USB_BREQ_IDENTIFY,
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
dev->channel, 0, &imode, sizeof(imode), 100,
|
||||||
dev->channel, 0, imode, sizeof(*imode), 100);
|
GFP_KERNEL);
|
||||||
|
|
||||||
kfree(imode);
|
|
||||||
|
|
||||||
return (rc > 0) ? 0 : rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* blink LED's for finding the this interface */
|
/* blink LED's for finding the this interface */
|
||||||
|
@ -1121,6 +1069,52 @@ static const struct ethtool_ops gs_usb_ethtool_ops = {
|
||||||
.get_ts_info = gs_usb_get_ts_info,
|
.get_ts_info = gs_usb_get_ts_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int gs_usb_get_termination(struct net_device *netdev, u16 *term)
|
||||||
|
{
|
||||||
|
struct gs_can *dev = netdev_priv(netdev);
|
||||||
|
struct gs_device_termination_state term_state;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = usb_control_msg_recv(interface_to_usbdev(dev->iface), 0,
|
||||||
|
GS_USB_BREQ_GET_TERMINATION,
|
||||||
|
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
|
dev->channel, 0,
|
||||||
|
&term_state, sizeof(term_state), 1000,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (term_state.state == cpu_to_le32(GS_CAN_TERMINATION_STATE_ON))
|
||||||
|
*term = GS_USB_TERMINATION_ENABLED;
|
||||||
|
else
|
||||||
|
*term = GS_USB_TERMINATION_DISABLED;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gs_usb_set_termination(struct net_device *netdev, u16 term)
|
||||||
|
{
|
||||||
|
struct gs_can *dev = netdev_priv(netdev);
|
||||||
|
struct gs_device_termination_state term_state;
|
||||||
|
|
||||||
|
if (term == GS_USB_TERMINATION_ENABLED)
|
||||||
|
term_state.state = cpu_to_le32(GS_CAN_TERMINATION_STATE_ON);
|
||||||
|
else
|
||||||
|
term_state.state = cpu_to_le32(GS_CAN_TERMINATION_STATE_OFF);
|
||||||
|
|
||||||
|
return usb_control_msg_send(interface_to_usbdev(dev->iface), 0,
|
||||||
|
GS_USB_BREQ_SET_TERMINATION,
|
||||||
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
|
dev->channel, 0,
|
||||||
|
&term_state, sizeof(term_state), 1000,
|
||||||
|
GFP_KERNEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const u16 gs_usb_termination_const[] = {
|
||||||
|
GS_USB_TERMINATION_DISABLED,
|
||||||
|
GS_USB_TERMINATION_ENABLED
|
||||||
|
};
|
||||||
|
|
||||||
static struct gs_can *gs_make_candev(unsigned int channel,
|
static struct gs_can *gs_make_candev(unsigned int channel,
|
||||||
struct usb_interface *intf,
|
struct usb_interface *intf,
|
||||||
struct gs_device_config *dconf)
|
struct gs_device_config *dconf)
|
||||||
|
@ -1128,26 +1122,21 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
||||||
struct gs_can *dev;
|
struct gs_can *dev;
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
int rc;
|
int rc;
|
||||||
struct gs_device_bt_const *bt_const;
|
struct gs_device_bt_const_extended bt_const_extended;
|
||||||
struct gs_device_bt_const_extended *bt_const_extended;
|
struct gs_device_bt_const bt_const;
|
||||||
u32 feature;
|
u32 feature;
|
||||||
|
|
||||||
bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL);
|
|
||||||
if (!bt_const)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
/* fetch bit timing constants */
|
/* fetch bit timing constants */
|
||||||
rc = usb_control_msg(interface_to_usbdev(intf),
|
rc = usb_control_msg_recv(interface_to_usbdev(intf), 0,
|
||||||
usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
|
GS_USB_BREQ_BT_CONST,
|
||||||
GS_USB_BREQ_BT_CONST,
|
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
channel, 0, &bt_const, sizeof(bt_const), 1000,
|
||||||
channel, 0, bt_const, sizeof(*bt_const), 1000);
|
GFP_KERNEL);
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc) {
|
||||||
dev_err(&intf->dev,
|
dev_err(&intf->dev,
|
||||||
"Couldn't get bit timing const for channel (err=%d)\n",
|
"Couldn't get bit timing const for channel %d (%pe)\n",
|
||||||
rc);
|
channel, ERR_PTR(rc));
|
||||||
kfree(bt_const);
|
|
||||||
return ERR_PTR(rc);
|
return ERR_PTR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1155,7 +1144,6 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
||||||
netdev = alloc_candev(sizeof(struct gs_can), GS_MAX_TX_URBS);
|
netdev = alloc_candev(sizeof(struct gs_can), GS_MAX_TX_URBS);
|
||||||
if (!netdev) {
|
if (!netdev) {
|
||||||
dev_err(&intf->dev, "Couldn't allocate candev\n");
|
dev_err(&intf->dev, "Couldn't allocate candev\n");
|
||||||
kfree(bt_const);
|
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1168,14 +1156,14 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
||||||
|
|
||||||
/* dev setup */
|
/* dev setup */
|
||||||
strcpy(dev->bt_const.name, KBUILD_MODNAME);
|
strcpy(dev->bt_const.name, KBUILD_MODNAME);
|
||||||
dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min);
|
dev->bt_const.tseg1_min = le32_to_cpu(bt_const.tseg1_min);
|
||||||
dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max);
|
dev->bt_const.tseg1_max = le32_to_cpu(bt_const.tseg1_max);
|
||||||
dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min);
|
dev->bt_const.tseg2_min = le32_to_cpu(bt_const.tseg2_min);
|
||||||
dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max);
|
dev->bt_const.tseg2_max = le32_to_cpu(bt_const.tseg2_max);
|
||||||
dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max);
|
dev->bt_const.sjw_max = le32_to_cpu(bt_const.sjw_max);
|
||||||
dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min);
|
dev->bt_const.brp_min = le32_to_cpu(bt_const.brp_min);
|
||||||
dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max);
|
dev->bt_const.brp_max = le32_to_cpu(bt_const.brp_max);
|
||||||
dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc);
|
dev->bt_const.brp_inc = le32_to_cpu(bt_const.brp_inc);
|
||||||
|
|
||||||
dev->udev = interface_to_usbdev(intf);
|
dev->udev = interface_to_usbdev(intf);
|
||||||
dev->iface = intf;
|
dev->iface = intf;
|
||||||
|
@ -1192,13 +1180,13 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
||||||
|
|
||||||
/* can setup */
|
/* can setup */
|
||||||
dev->can.state = CAN_STATE_STOPPED;
|
dev->can.state = CAN_STATE_STOPPED;
|
||||||
dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can);
|
dev->can.clock.freq = le32_to_cpu(bt_const.fclk_can);
|
||||||
dev->can.bittiming_const = &dev->bt_const;
|
dev->can.bittiming_const = &dev->bt_const;
|
||||||
dev->can.do_set_bittiming = gs_usb_set_bittiming;
|
dev->can.do_set_bittiming = gs_usb_set_bittiming;
|
||||||
|
|
||||||
dev->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC;
|
dev->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC;
|
||||||
|
|
||||||
feature = le32_to_cpu(bt_const->feature);
|
feature = le32_to_cpu(bt_const.feature);
|
||||||
dev->feature = FIELD_GET(GS_CAN_FEATURE_MASK, feature);
|
dev->feature = FIELD_GET(GS_CAN_FEATURE_MASK, feature);
|
||||||
if (feature & GS_CAN_FEATURE_LISTEN_ONLY)
|
if (feature & GS_CAN_FEATURE_LISTEN_ONLY)
|
||||||
dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
|
dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
|
||||||
|
@ -1221,6 +1209,21 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
||||||
dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming;
|
dev->can.do_set_data_bittiming = gs_usb_set_data_bittiming;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (feature & GS_CAN_FEATURE_TERMINATION) {
|
||||||
|
rc = gs_usb_get_termination(netdev, &dev->can.termination);
|
||||||
|
if (rc) {
|
||||||
|
dev->feature &= ~GS_CAN_FEATURE_TERMINATION;
|
||||||
|
|
||||||
|
dev_info(&intf->dev,
|
||||||
|
"Disabling termination support for channel %d (%pe)\n",
|
||||||
|
channel, ERR_PTR(rc));
|
||||||
|
} else {
|
||||||
|
dev->can.termination_const = gs_usb_termination_const;
|
||||||
|
dev->can.termination_const_cnt = ARRAY_SIZE(gs_usb_termination_const);
|
||||||
|
dev->can.do_set_termination = gs_usb_set_termination;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The CANtact Pro from LinkLayer Labs is based on the
|
/* The CANtact Pro from LinkLayer Labs is based on the
|
||||||
* LPC54616 µC, which is affected by the NXP LPC USB transfer
|
* LPC54616 µC, which is affected by the NXP LPC USB transfer
|
||||||
* erratum. However, the current firmware (version 2) doesn't
|
* erratum. However, the current firmware (version 2) doesn't
|
||||||
|
@ -1249,57 +1252,52 @@ static struct gs_can *gs_make_candev(unsigned int channel,
|
||||||
feature & GS_CAN_FEATURE_IDENTIFY))
|
feature & GS_CAN_FEATURE_IDENTIFY))
|
||||||
dev->feature &= ~GS_CAN_FEATURE_IDENTIFY;
|
dev->feature &= ~GS_CAN_FEATURE_IDENTIFY;
|
||||||
|
|
||||||
kfree(bt_const);
|
|
||||||
|
|
||||||
/* fetch extended bit timing constants if device has feature
|
/* fetch extended bit timing constants if device has feature
|
||||||
* GS_CAN_FEATURE_FD and GS_CAN_FEATURE_BT_CONST_EXT
|
* GS_CAN_FEATURE_FD and GS_CAN_FEATURE_BT_CONST_EXT
|
||||||
*/
|
*/
|
||||||
if (feature & GS_CAN_FEATURE_FD &&
|
if (feature & GS_CAN_FEATURE_FD &&
|
||||||
feature & GS_CAN_FEATURE_BT_CONST_EXT) {
|
feature & GS_CAN_FEATURE_BT_CONST_EXT) {
|
||||||
bt_const_extended = kmalloc(sizeof(*bt_const_extended), GFP_KERNEL);
|
rc = usb_control_msg_recv(interface_to_usbdev(intf), 0,
|
||||||
if (!bt_const_extended)
|
GS_USB_BREQ_BT_CONST_EXT,
|
||||||
return ERR_PTR(-ENOMEM);
|
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
|
channel, 0, &bt_const_extended,
|
||||||
rc = usb_control_msg(interface_to_usbdev(intf),
|
sizeof(bt_const_extended),
|
||||||
usb_rcvctrlpipe(interface_to_usbdev(intf), 0),
|
1000, GFP_KERNEL);
|
||||||
GS_USB_BREQ_BT_CONST_EXT,
|
if (rc) {
|
||||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
|
||||||
channel, 0, bt_const_extended,
|
|
||||||
sizeof(*bt_const_extended),
|
|
||||||
1000);
|
|
||||||
if (rc < 0) {
|
|
||||||
dev_err(&intf->dev,
|
dev_err(&intf->dev,
|
||||||
"Couldn't get extended bit timing const for channel (err=%d)\n",
|
"Couldn't get extended bit timing const for channel %d (%pe)\n",
|
||||||
rc);
|
channel, ERR_PTR(rc));
|
||||||
kfree(bt_const_extended);
|
goto out_free_candev;
|
||||||
return ERR_PTR(rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(dev->data_bt_const.name, KBUILD_MODNAME);
|
strcpy(dev->data_bt_const.name, KBUILD_MODNAME);
|
||||||
dev->data_bt_const.tseg1_min = le32_to_cpu(bt_const_extended->dtseg1_min);
|
dev->data_bt_const.tseg1_min = le32_to_cpu(bt_const_extended.dtseg1_min);
|
||||||
dev->data_bt_const.tseg1_max = le32_to_cpu(bt_const_extended->dtseg1_max);
|
dev->data_bt_const.tseg1_max = le32_to_cpu(bt_const_extended.dtseg1_max);
|
||||||
dev->data_bt_const.tseg2_min = le32_to_cpu(bt_const_extended->dtseg2_min);
|
dev->data_bt_const.tseg2_min = le32_to_cpu(bt_const_extended.dtseg2_min);
|
||||||
dev->data_bt_const.tseg2_max = le32_to_cpu(bt_const_extended->dtseg2_max);
|
dev->data_bt_const.tseg2_max = le32_to_cpu(bt_const_extended.dtseg2_max);
|
||||||
dev->data_bt_const.sjw_max = le32_to_cpu(bt_const_extended->dsjw_max);
|
dev->data_bt_const.sjw_max = le32_to_cpu(bt_const_extended.dsjw_max);
|
||||||
dev->data_bt_const.brp_min = le32_to_cpu(bt_const_extended->dbrp_min);
|
dev->data_bt_const.brp_min = le32_to_cpu(bt_const_extended.dbrp_min);
|
||||||
dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended->dbrp_max);
|
dev->data_bt_const.brp_max = le32_to_cpu(bt_const_extended.dbrp_max);
|
||||||
dev->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended->dbrp_inc);
|
dev->data_bt_const.brp_inc = le32_to_cpu(bt_const_extended.dbrp_inc);
|
||||||
|
|
||||||
dev->can.data_bittiming_const = &dev->data_bt_const;
|
dev->can.data_bittiming_const = &dev->data_bt_const;
|
||||||
|
|
||||||
kfree(bt_const_extended);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_NETDEV_DEV(netdev, &intf->dev);
|
SET_NETDEV_DEV(netdev, &intf->dev);
|
||||||
|
|
||||||
rc = register_candev(dev->netdev);
|
rc = register_candev(dev->netdev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
free_candev(dev->netdev);
|
dev_err(&intf->dev,
|
||||||
dev_err(&intf->dev, "Couldn't register candev (err=%d)\n", rc);
|
"Couldn't register candev for channel %d (%pe)\n",
|
||||||
return ERR_PTR(rc);
|
channel, ERR_PTR(rc));
|
||||||
|
goto out_free_candev;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev;
|
return dev;
|
||||||
|
|
||||||
|
out_free_candev:
|
||||||
|
free_candev(dev->netdev);
|
||||||
|
return ERR_PTR(rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gs_destroy_candev(struct gs_can *dev)
|
static void gs_destroy_candev(struct gs_can *dev)
|
||||||
|
@ -1315,64 +1313,51 @@ static int gs_usb_probe(struct usb_interface *intf,
|
||||||
struct usb_device *udev = interface_to_usbdev(intf);
|
struct usb_device *udev = interface_to_usbdev(intf);
|
||||||
struct gs_host_frame *hf;
|
struct gs_host_frame *hf;
|
||||||
struct gs_usb *dev;
|
struct gs_usb *dev;
|
||||||
int rc = -ENOMEM;
|
struct gs_host_config hconf = {
|
||||||
|
.byte_order = cpu_to_le32(0x0000beef),
|
||||||
|
};
|
||||||
|
struct gs_device_config dconf;
|
||||||
unsigned int icount, i;
|
unsigned int icount, i;
|
||||||
struct gs_host_config *hconf;
|
int rc;
|
||||||
struct gs_device_config *dconf;
|
|
||||||
|
|
||||||
hconf = kmalloc(sizeof(*hconf), GFP_KERNEL);
|
|
||||||
if (!hconf)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
hconf->byte_order = cpu_to_le32(0x0000beef);
|
|
||||||
|
|
||||||
/* send host config */
|
/* send host config */
|
||||||
rc = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
|
rc = usb_control_msg_send(udev, 0,
|
||||||
GS_USB_BREQ_HOST_FORMAT,
|
GS_USB_BREQ_HOST_FORMAT,
|
||||||
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
1, intf->cur_altsetting->desc.bInterfaceNumber,
|
1, intf->cur_altsetting->desc.bInterfaceNumber,
|
||||||
hconf, sizeof(*hconf), 1000);
|
&hconf, sizeof(hconf), 1000,
|
||||||
|
GFP_KERNEL);
|
||||||
kfree(hconf);
|
if (rc) {
|
||||||
|
|
||||||
if (rc < 0) {
|
|
||||||
dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", rc);
|
dev_err(&intf->dev, "Couldn't send data format (err=%d)\n", rc);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
dconf = kmalloc(sizeof(*dconf), GFP_KERNEL);
|
|
||||||
if (!dconf)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
/* read device config */
|
/* read device config */
|
||||||
rc = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
|
rc = usb_control_msg_recv(udev, 0,
|
||||||
GS_USB_BREQ_DEVICE_CONFIG,
|
GS_USB_BREQ_DEVICE_CONFIG,
|
||||||
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
1, intf->cur_altsetting->desc.bInterfaceNumber,
|
1, intf->cur_altsetting->desc.bInterfaceNumber,
|
||||||
dconf, sizeof(*dconf), 1000);
|
&dconf, sizeof(dconf), 1000,
|
||||||
if (rc < 0) {
|
GFP_KERNEL);
|
||||||
|
if (rc) {
|
||||||
dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n",
|
dev_err(&intf->dev, "Couldn't get device config: (err=%d)\n",
|
||||||
rc);
|
rc);
|
||||||
kfree(dconf);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
icount = dconf->icount + 1;
|
icount = dconf.icount + 1;
|
||||||
dev_info(&intf->dev, "Configuring for %u interfaces\n", icount);
|
dev_info(&intf->dev, "Configuring for %u interfaces\n", icount);
|
||||||
|
|
||||||
if (icount > GS_MAX_INTF) {
|
if (icount > GS_MAX_INTF) {
|
||||||
dev_err(&intf->dev,
|
dev_err(&intf->dev,
|
||||||
"Driver cannot handle more that %u CAN interfaces\n",
|
"Driver cannot handle more that %u CAN interfaces\n",
|
||||||
GS_MAX_INTF);
|
GS_MAX_INTF);
|
||||||
kfree(dconf);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||||
if (!dev) {
|
if (!dev)
|
||||||
kfree(dconf);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
init_usb_anchor(&dev->rx_submitted);
|
init_usb_anchor(&dev->rx_submitted);
|
||||||
|
|
||||||
|
@ -1382,7 +1367,7 @@ static int gs_usb_probe(struct usb_interface *intf,
|
||||||
for (i = 0; i < icount; i++) {
|
for (i = 0; i < icount; i++) {
|
||||||
unsigned int hf_size_rx = 0;
|
unsigned int hf_size_rx = 0;
|
||||||
|
|
||||||
dev->canch[i] = gs_make_candev(i, intf, dconf);
|
dev->canch[i] = gs_make_candev(i, intf, &dconf);
|
||||||
if (IS_ERR_OR_NULL(dev->canch[i])) {
|
if (IS_ERR_OR_NULL(dev->canch[i])) {
|
||||||
/* save error code to return later */
|
/* save error code to return later */
|
||||||
rc = PTR_ERR(dev->canch[i]);
|
rc = PTR_ERR(dev->canch[i]);
|
||||||
|
@ -1393,7 +1378,6 @@ static int gs_usb_probe(struct usb_interface *intf,
|
||||||
gs_destroy_candev(dev->canch[i]);
|
gs_destroy_candev(dev->canch[i]);
|
||||||
|
|
||||||
usb_kill_anchored_urbs(&dev->rx_submitted);
|
usb_kill_anchored_urbs(&dev->rx_submitted);
|
||||||
kfree(dconf);
|
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1416,8 +1400,6 @@ static int gs_usb_probe(struct usb_interface *intf,
|
||||||
dev->hf_size_rx = max(dev->hf_size_rx, hf_size_rx);
|
dev->hf_size_rx = max(dev->hf_size_rx, hf_size_rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
kfree(dconf);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -274,6 +274,7 @@ static void bcm_can_tx(struct bcm_op *op)
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct canfd_frame *cf = op->frames + op->cfsiz * op->currframe;
|
struct canfd_frame *cf = op->frames + op->cfsiz * op->currframe;
|
||||||
|
int err;
|
||||||
|
|
||||||
/* no target device? => exit */
|
/* no target device? => exit */
|
||||||
if (!op->ifindex)
|
if (!op->ifindex)
|
||||||
|
@ -298,11 +299,11 @@ static void bcm_can_tx(struct bcm_op *op)
|
||||||
/* send with loopback */
|
/* send with loopback */
|
||||||
skb->dev = dev;
|
skb->dev = dev;
|
||||||
can_skb_set_owner(skb, op->sk);
|
can_skb_set_owner(skb, op->sk);
|
||||||
can_send(skb, 1);
|
err = can_send(skb, 1);
|
||||||
|
if (!err)
|
||||||
|
op->frames_abs++;
|
||||||
|
|
||||||
/* update statistics */
|
|
||||||
op->currframe++;
|
op->currframe++;
|
||||||
op->frames_abs++;
|
|
||||||
|
|
||||||
/* reached last frame? */
|
/* reached last frame? */
|
||||||
if (op->currframe >= op->nframes)
|
if (op->currframe >= op->nframes)
|
||||||
|
@ -1749,15 +1750,27 @@ static int __init bcm_module_init(void)
|
||||||
|
|
||||||
pr_info("can: broadcast manager protocol\n");
|
pr_info("can: broadcast manager protocol\n");
|
||||||
|
|
||||||
|
err = register_pernet_subsys(&canbcm_pernet_ops);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = register_netdevice_notifier(&canbcm_notifier);
|
||||||
|
if (err)
|
||||||
|
goto register_notifier_failed;
|
||||||
|
|
||||||
err = can_proto_register(&bcm_can_proto);
|
err = can_proto_register(&bcm_can_proto);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
printk(KERN_ERR "can: registration of bcm protocol failed\n");
|
printk(KERN_ERR "can: registration of bcm protocol failed\n");
|
||||||
return err;
|
goto register_proto_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
register_pernet_subsys(&canbcm_pernet_ops);
|
|
||||||
register_netdevice_notifier(&canbcm_notifier);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
register_proto_failed:
|
||||||
|
unregister_netdevice_notifier(&canbcm_notifier);
|
||||||
|
register_notifier_failed:
|
||||||
|
unregister_pernet_subsys(&canbcm_pernet_ops);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit bcm_module_exit(void)
|
static void __exit bcm_module_exit(void)
|
||||||
|
|
Loading…
Reference in New Issue