diff options
Diffstat (limited to 'drivers/net/can/janz-ican3.c')
-rw-r--r-- | drivers/net/can/janz-ican3.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index a761092e6ac9..0732a5092141 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -9,6 +9,7 @@ #include <linux/module.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/ethtool.h> #include <linux/platform_device.h> #include <linux/netdevice.h> @@ -916,10 +917,10 @@ static void ican3_to_can_frame(struct ican3_dev *mod, cf->can_id |= desc->data[0] << 3; cf->can_id |= (desc->data[1] & 0xe0) >> 5; - cf->can_dlc = get_can_dlc(desc->data[1] & ICAN3_CAN_DLC_MASK); - memcpy(cf->data, &desc->data[2], cf->can_dlc); + cf->len = can_cc_dlc2len(desc->data[1] & ICAN3_CAN_DLC_MASK); + memcpy(cf->data, &desc->data[2], cf->len); } else { - cf->can_dlc = get_can_dlc(desc->data[0] & ICAN3_CAN_DLC_MASK); + cf->len = can_cc_dlc2len(desc->data[0] & ICAN3_CAN_DLC_MASK); if (desc->data[0] & ICAN3_EFF_RTR) cf->can_id |= CAN_RTR_FLAG; @@ -934,7 +935,7 @@ static void ican3_to_can_frame(struct ican3_dev *mod, cf->can_id |= desc->data[3] >> 5; /* 2-0 */ } - memcpy(cf->data, &desc->data[6], cf->can_dlc); + memcpy(cf->data, &desc->data[6], cf->len); } } @@ -947,7 +948,7 @@ static void can_frame_to_ican3(struct ican3_dev *mod, /* we always use the extended format, with the ECHO flag set */ desc->command = ICAN3_CAN_TYPE_EFF; - desc->data[0] |= cf->can_dlc; + desc->data[0] |= cf->len; desc->data[1] |= ICAN3_ECHO; /* support single transmission (no retries) mode */ @@ -970,7 +971,7 @@ static void can_frame_to_ican3(struct ican3_dev *mod, } /* copy the data bits into the descriptor */ - memcpy(&desc->data[6], cf->data, cf->can_dlc); + memcpy(&desc->data[6], cf->data, cf->len); } /* @@ -1127,7 +1128,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) /* bus error interrupt */ if (isrc == CEVTIND_BEI) { mod->can.can_stats.bus_error++; - cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR | CAN_ERR_CNT; switch (ecc & ECC_MASK) { case ECC_BIT: @@ -1153,7 +1154,7 @@ static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) if (state != mod->can.state && (state == CAN_STATE_ERROR_WARNING || state == CAN_STATE_ERROR_PASSIVE)) { - cf->can_id |= CAN_ERR_CRTL; + cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; if (state == CAN_STATE_ERROR_WARNING) { mod->can.can_stats.error_warning++; cf->data[1] = (txerr > rxerr) ? @@ -1277,6 +1278,8 @@ static void ican3_put_echo_skb(struct ican3_dev *mod, struct sk_buff *skb) if (!skb) return; + skb_tx_timestamp(skb); + /* save this skb for tx interrupt echo handling */ skb_queue_tail(&mod->echoq, skb); } @@ -1285,7 +1288,7 @@ static unsigned int ican3_get_echo_skb(struct ican3_dev *mod) { struct sk_buff *skb = skb_dequeue(&mod->echoq); struct can_frame *cf; - u8 dlc; + u8 dlc = 0; /* this should never trigger unless there is a driver bug */ if (!skb) { @@ -1294,7 +1297,8 @@ static unsigned int ican3_get_echo_skb(struct ican3_dev *mod) } cf = (struct can_frame *)skb->data; - dlc = cf->can_dlc; + if (!(cf->can_id & CAN_RTR_FLAG)) + dlc = cf->len; /* check flag whether this packet has to be looped back */ if (skb->pkt_type != PACKET_LOOPBACK) { @@ -1332,10 +1336,10 @@ static bool ican3_echo_skb_matches(struct ican3_dev *mod, struct sk_buff *skb) if (cf->can_id != echo_cf->can_id) return false; - if (cf->can_dlc != echo_cf->can_dlc) + if (cf->len != echo_cf->len) return false; - return memcmp(cf->data, echo_cf->data, cf->can_dlc) == 0; + return memcmp(cf->data, echo_cf->data, cf->len) == 0; } /* @@ -1421,7 +1425,8 @@ static int ican3_recv_skb(struct ican3_dev *mod) /* update statistics, receive the skb */ stats->rx_packets++; - stats->rx_bytes += cf->can_dlc; + if (!(cf->can_id & CAN_RTR_FLAG)) + stats->rx_bytes += cf->len; netif_receive_skb(skb); err_noalloc: @@ -1451,7 +1456,7 @@ static int ican3_napi(struct napi_struct *napi, int budget) /* process all communication messages */ while (true) { - struct ican3_msg uninitialized_var(msg); + struct ican3_msg msg; ret = ican3_recv_msg(mod, &msg); if (ret) break; @@ -1688,7 +1693,7 @@ static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev) void __iomem *desc_addr; unsigned long flags; - if (can_dropped_invalid_skb(ndev, skb)) + if (can_dev_dropped_skb(ndev, skb)) return NETDEV_TX_OK; spin_lock_irqsave(&mod->lock, flags); @@ -1750,6 +1755,10 @@ static const struct net_device_ops ican3_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +static const struct ethtool_ops ican3_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + /* * Low-level CAN Device */ @@ -1815,9 +1824,9 @@ static int ican3_get_berr_counter(const struct net_device *ndev, * Sysfs Attributes */ -static ssize_t ican3_sysfs_show_term(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t termination_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); int ret; @@ -1831,12 +1840,12 @@ static ssize_t ican3_sysfs_show_term(struct device *dev, return -ETIMEDOUT; } - return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled); + return sysfs_emit(buf, "%u\n", mod->termination_enabled); } -static ssize_t ican3_sysfs_set_term(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t termination_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); unsigned long enable; @@ -1852,18 +1861,17 @@ static ssize_t ican3_sysfs_set_term(struct device *dev, return count; } -static ssize_t ican3_sysfs_show_fwinfo(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t fwinfo_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); return scnprintf(buf, PAGE_SIZE, "%s\n", mod->fwinfo); } -static DEVICE_ATTR(termination, 0644, ican3_sysfs_show_term, - ican3_sysfs_set_term); -static DEVICE_ATTR(fwinfo, 0444, ican3_sysfs_show_fwinfo, NULL); +static DEVICE_ATTR_RW(termination); +static DEVICE_ATTR_RO(fwinfo); static struct attribute *ican3_sysfs_attrs[] = { &dev_attr_termination.attr, @@ -1909,7 +1917,7 @@ static int ican3_probe(struct platform_device *pdev) mod = netdev_priv(ndev); mod->ndev = ndev; mod->num = pdata->modno; - netif_napi_add(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS); + netif_napi_add_weight(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS); skb_queue_head_init(&mod->echoq); spin_lock_init(&mod->lock); init_completion(&mod->termination_comp); @@ -1922,6 +1930,7 @@ static int ican3_probe(struct platform_device *pdev) mod->free_page = DPM_FREE_START; ndev->netdev_ops = &ican3_netdev_ops; + ndev->ethtool_ops = &ican3_ethtool_ops; ndev->flags |= IFF_ECHO; SET_NETDEV_DEV(ndev, &pdev->dev); |