diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-28 16:43:10 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-06-28 16:43:10 -0700 |
commit | 3a8a670eeeaa40d87bd38a587438952741980c18 (patch) | |
tree | d5546d311271503eadf75b45d87e12720e72899f /drivers/net/can | |
parent | 6a8cbd9253abc1bd0df4d60c4c24fa555190376d (diff) | |
parent | ae230642190a51b85656d6da2df744d534d59544 (diff) |
Merge tag 'net-next-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking changes from Jakub Kicinski:
"WiFi 7 and sendpage changes are the biggest pieces of work for this
release. The latter will definitely require fixes but I think that we
got it to a reasonable point.
Core:
- Rework the sendpage & splice implementations
Instead of feeding data into sockets page by page extend sendmsg
handlers to support taking a reference on the data, controlled by a
new flag called MSG_SPLICE_PAGES
Rework the handling of unexpected-end-of-file to invoke an
additional callback instead of trying to predict what the right
combination of MORE/NOTLAST flags is
Remove the MSG_SENDPAGE_NOTLAST flag completely
- Implement SCM_PIDFD, a new type of CMSG type analogous to
SCM_CREDENTIALS, but it contains pidfd instead of plain pid
- Enable socket busy polling with CONFIG_RT
- Improve reliability and efficiency of reporting for ref_tracker
- Auto-generate a user space C library for various Netlink families
Protocols:
- Allow TCP to shrink the advertised window when necessary, prevent
sk_rcvbuf auto-tuning from growing the window all the way up to
tcp_rmem[2]
- Use per-VMA locking for "page-flipping" TCP receive zerocopy
- Prepare TCP for device-to-device data transfers, by making sure
that payloads are always attached to skbs as page frags
- Make the backoff time for the first N TCP SYN retransmissions
linear. Exponential backoff is unnecessarily conservative
- Create a new MPTCP getsockopt to retrieve all info
(MPTCP_FULL_INFO)
- Avoid waking up applications using TLS sockets until we have a full
record
- Allow using kernel memory for protocol ioctl callbacks, paving the
way to issuing ioctls over io_uring
- Add nolocalbypass option to VxLAN, forcing packets to be fully
encapsulated even if they are destined for a local IP address
- Make TCPv4 use consistent hash in TIME_WAIT and SYN_RECV. Ensure
in-kernel ECMP implementation (e.g. Open vSwitch) select the same
link for all packets. Support L4 symmetric hashing in Open vSwitch
- PPPoE: make number of hash bits configurable
- Allow DNS to be overwritten by DHCPACK in the in-kernel DHCP client
(ipconfig)
- Add layer 2 miss indication and filtering, allowing higher layers
(e.g. ACL filters) to make forwarding decisions based on whether
packet matched forwarding state in lower devices (bridge)
- Support matching on Connectivity Fault Management (CFM) packets
- Hide the "link becomes ready" IPv6 messages by demoting their
printk level to debug
- HSR: don't enable promiscuous mode if device offloads the proto
- Support active scanning in IEEE 802.15.4
- Continue work on Multi-Link Operation for WiFi 7
BPF:
- Add precision propagation for subprogs and callbacks. This allows
maintaining verification efficiency when subprograms are used, or
in fact passing the verifier at all for complex programs,
especially those using open-coded iterators
- Improve BPF's {g,s}setsockopt() length handling. Previously BPF
assumed the length is always equal to the amount of written data.
But some protos allow passing a NULL buffer to discover what the
output buffer *should* be, without writing anything
- Accept dynptr memory as memory arguments passed to helpers
- Add routing table ID to bpf_fib_lookup BPF helper
- Support O_PATH FDs in BPF_OBJ_PIN and BPF_OBJ_GET commands
- Drop bpf_capable() check in BPF_MAP_FREEZE command (used to mark
maps as read-only)
- Show target_{obj,btf}_id in tracing link fdinfo
- Addition of several new kfuncs (most of the names are
self-explanatory):
- Add a set of new dynptr kfuncs: bpf_dynptr_adjust(),
bpf_dynptr_is_null(), bpf_dynptr_is_rdonly(), bpf_dynptr_size()
and bpf_dynptr_clone().
- bpf_task_under_cgroup()
- bpf_sock_destroy() - force closing sockets
- bpf_cpumask_first_and(), rework bpf_cpumask_any*() kfuncs
Netfilter:
- Relax set/map validation checks in nf_tables. Allow checking
presence of an entry in a map without using the value
- Increase ip_vs_conn_tab_bits range for 64BIT builds
- Allow updating size of a set
- Improve NAT tuple selection when connection is closing
Driver API:
- Integrate netdev with LED subsystem, to allow configuring HW
"offloaded" blinking of LEDs based on link state and activity
(i.e. packets coming in and out)
- Support configuring rate selection pins of SFP modules
- Factor Clause 73 auto-negotiation code out of the drivers, provide
common helper routines
- Add more fool-proof helpers for managing lifetime of MDIO devices
associated with the PCS layer
- Allow drivers to report advanced statistics related to Time Aware
scheduler offload (taprio)
- Allow opting out of VF statistics in link dump, to allow more VFs
to fit into the message
- Split devlink instance and devlink port operations
New hardware / drivers:
- Ethernet:
- Synopsys EMAC4 IP support (stmmac)
- Marvell 88E6361 8 port (5x1GE + 3x2.5GE) switches
- Marvell 88E6250 7 port switches
- Microchip LAN8650/1 Rev.B0 PHYs
- MediaTek MT7981/MT7988 built-in 1GE PHY driver
- WiFi:
- Realtek RTL8192FU, 2.4 GHz, b/g/n mode, 2T2R, 300 Mbps
- Realtek RTL8723DS (SDIO variant)
- Realtek RTL8851BE
- CAN:
- Fintek F81604
Drivers:
- Ethernet NICs:
- Intel (100G, ice):
- support dynamic interrupt allocation
- use meta data match instead of VF MAC addr on slow-path
- nVidia/Mellanox:
- extend link aggregation to handle 4, rather than just 2 ports
- spawn sub-functions without any features by default
- OcteonTX2:
- support HTB (Tx scheduling/QoS) offload
- make RSS hash generation configurable
- support selecting Rx queue using TC filters
- Wangxun (ngbe/txgbe):
- add basic Tx/Rx packet offloads
- add phylink support (SFP/PCS control)
- Freescale/NXP (enetc):
- report TAPRIO packet statistics
- Solarflare/AMD:
- support matching on IP ToS and UDP source port of outer
header
- VxLAN and GENEVE tunnel encapsulation over IPv4 or IPv6
- add devlink dev info support for EF10
- Virtual NICs:
- Microsoft vNIC:
- size the Rx indirection table based on requested
configuration
- support VLAN tagging
- Amazon vNIC:
- try to reuse Rx buffers if not fully consumed, useful for ARM
servers running with 16kB pages
- Google vNIC:
- support TCP segmentation of >64kB frames
- Ethernet embedded switches:
- Marvell (mv88e6xxx):
- enable USXGMII (88E6191X)
- Microchip:
- lan966x: add support for Egress Stage 0 ACL engine
- lan966x: support mapping packet priority to internal switch
priority (based on PCP or DSCP)
- Ethernet PHYs:
- Broadcom PHYs:
- support for Wake-on-LAN for BCM54210E/B50212E
- report LPI counter
- Microsemi PHYs: support RGMII delay configuration (VSC85xx)
- Micrel PHYs: receive timestamp in the frame (LAN8841)
- Realtek PHYs: support optional external PHY clock
- Altera TSE PCS: merge the driver into Lynx PCS which it is a
variant of
- CAN: Kvaser PCIEcan:
- support packet timestamping
- WiFi:
- Intel (iwlwifi):
- major update for new firmware and Multi-Link Operation (MLO)
- configuration rework to drop test devices and split the
different families
- support for segmented PNVM images and power tables
- new vendor entries for PPAG (platform antenna gain) feature
- Qualcomm 802.11ax (ath11k):
- Multiple Basic Service Set Identifier (MBSSID) and Enhanced
MBSSID Advertisement (EMA) support in AP mode
- support factory test mode
- RealTek (rtw89):
- add RSSI based antenna diversity
- support U-NII-4 channels on 5 GHz band
- RealTek (rtl8xxxu):
- AP mode support for 8188f
- support USB RX aggregation for the newer chips"
* tag 'net-next-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1602 commits)
net: scm: introduce and use scm_recv_unix helper
af_unix: Skip SCM_PIDFD if scm->pid is NULL.
net: lan743x: Simplify comparison
netlink: Add __sock_i_ino() for __netlink_diag_dump().
net: dsa: avoid suspicious RCU usage for synced VLAN-aware MAC addresses
Revert "af_unix: Call scm_recv() only after scm_set_cred()."
phylink: ReST-ify the phylink_pcs_neg_mode() kdoc
libceph: Partially revert changes to support MSG_SPLICE_PAGES
net: phy: mscc: fix packet loss due to RGMII delays
net: mana: use vmalloc_array and vcalloc
net: enetc: use vmalloc_array and vcalloc
ionic: use vmalloc_array and vcalloc
pds_core: use vmalloc_array and vcalloc
gve: use vmalloc_array and vcalloc
octeon_ep: use vmalloc_array and vcalloc
net: usb: qmi_wwan: add u-blox 0x1312 composition
perf trace: fix MSG_SPLICE_PAGES build error
ipvlan: Fix return value of ipvlan_queue_xmit()
netfilter: nf_tables: fix underflow in chain reference counter
netfilter: nf_tables: unbind non-anonymous set if rule construction fails
...
Diffstat (limited to 'drivers/net/can')
34 files changed, 1850 insertions, 912 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index b190007c01be..a5c5036dfb94 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -153,8 +153,7 @@ config CAN_JANZ_ICAN3 config CAN_KVASER_PCIEFD depends on PCI tristate "Kvaser PCIe FD cards" - select CRC32 - help + help This is a driver for the Kvaser PCI Express CAN FD family. Supported devices: diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 199cb200f2bd..4621266851ed 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1346,7 +1346,7 @@ static int at91_can_probe(struct platform_device *pdev) return err; } -static int at91_can_remove(struct platform_device *pdev) +static void at91_can_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct at91_priv *priv = netdev_priv(dev); @@ -1362,8 +1362,6 @@ static int at91_can_remove(struct platform_device *pdev) clk_put(priv->clk); free_candev(dev); - - return 0; } static const struct platform_device_id at91_can_id_table[] = { @@ -1381,7 +1379,7 @@ MODULE_DEVICE_TABLE(platform, at91_can_id_table); static struct platform_driver at91_can_driver = { .probe = at91_can_probe, - .remove = at91_can_remove, + .remove_new = at91_can_remove, .driver = { .name = KBUILD_MODNAME, .of_match_table = of_match_ptr(at91_can_dt_ids), diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c index 027a8a162fe4..39de7164bc4e 100644 --- a/drivers/net/can/bxcan.c +++ b/drivers/net/can/bxcan.c @@ -966,22 +966,16 @@ static int bxcan_probe(struct platform_device *pdev) } rx_irq = platform_get_irq_byname(pdev, "rx0"); - if (rx_irq < 0) { - dev_err(dev, "failed to get rx0 irq\n"); + if (rx_irq < 0) return rx_irq; - } tx_irq = platform_get_irq_byname(pdev, "tx"); - if (tx_irq < 0) { - dev_err(dev, "failed to get tx irq\n"); + if (tx_irq < 0) return tx_irq; - } sce_irq = platform_get_irq_byname(pdev, "sce"); - if (sce_irq < 0) { - dev_err(dev, "failed to get sce irq\n"); + if (sce_irq < 0) return sce_irq; - } ndev = alloc_candev(sizeof(struct bxcan_priv), BXCAN_TX_MB_NUM); if (!ndev) { @@ -1039,7 +1033,7 @@ out_free_candev: return err; } -static int bxcan_remove(struct platform_device *pdev) +static void bxcan_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct bxcan_priv *priv = netdev_priv(ndev); @@ -1048,7 +1042,6 @@ static int bxcan_remove(struct platform_device *pdev) clk_disable_unprepare(priv->clk); can_rx_offload_del(&priv->offload); free_candev(ndev); - return 0; } static int __maybe_unused bxcan_suspend(struct device *dev) @@ -1100,7 +1093,7 @@ static struct platform_driver bxcan_driver = { .of_match_table = bxcan_of_match, }, .probe = bxcan_probe, - .remove = bxcan_remove, + .remove_new = bxcan_remove, }; module_platform_driver(bxcan_driver); diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 03ccb7cfacaf..925930b6c4ca 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -410,7 +410,7 @@ exit: return ret; } -static int c_can_plat_remove(struct platform_device *pdev) +static void c_can_plat_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct c_can_priv *priv = netdev_priv(dev); @@ -418,8 +418,6 @@ static int c_can_plat_remove(struct platform_device *pdev) unregister_c_can_dev(dev); pm_runtime_disable(priv->device); free_c_can_dev(dev); - - return 0; } #ifdef CONFIG_PM @@ -487,7 +485,7 @@ static struct platform_driver c_can_plat_driver = { .of_match_table = c_can_of_table, }, .probe = c_can_plat_probe, - .remove = c_can_plat_remove, + .remove_new = c_can_plat_remove, .suspend = c_can_suspend, .resume = c_can_resume, .id_table = c_can_id_table, diff --git a/drivers/net/can/cc770/cc770_isa.c b/drivers/net/can/cc770/cc770_isa.c index 8f6dccd5a587..22009440a983 100644 --- a/drivers/net/can/cc770/cc770_isa.c +++ b/drivers/net/can/cc770/cc770_isa.c @@ -285,7 +285,7 @@ exit: return err; } -static int cc770_isa_remove(struct platform_device *pdev) +static void cc770_isa_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct cc770_priv *priv = netdev_priv(dev); @@ -303,13 +303,11 @@ static int cc770_isa_remove(struct platform_device *pdev) release_region(port[idx], CC770_IOSIZE); } free_cc770dev(dev); - - return 0; } static struct platform_driver cc770_isa_driver = { .probe = cc770_isa_probe, - .remove = cc770_isa_remove, + .remove_new = cc770_isa_remove, .driver = { .name = KBUILD_MODNAME, }, diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c index 8dcc32e4e30e..13bcfba05f18 100644 --- a/drivers/net/can/cc770/cc770_platform.c +++ b/drivers/net/can/cc770/cc770_platform.c @@ -230,7 +230,7 @@ exit_release_mem: return err; } -static int cc770_platform_remove(struct platform_device *pdev) +static void cc770_platform_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct cc770_priv *priv = netdev_priv(dev); @@ -242,8 +242,6 @@ static int cc770_platform_remove(struct platform_device *pdev) mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, resource_size(mem)); - - return 0; } static const struct of_device_id cc770_platform_table[] = { @@ -259,7 +257,7 @@ static struct platform_driver cc770_platform_driver = { .of_match_table = cc770_platform_table, }, .probe = cc770_platform_probe, - .remove = cc770_platform_remove, + .remove_new = cc770_platform_remove, }; module_platform_driver(cc770_platform_driver); diff --git a/drivers/net/can/ctucanfd/ctucanfd_platform.c b/drivers/net/can/ctucanfd/ctucanfd_platform.c index a17561d97192..55bb10b157b4 100644 --- a/drivers/net/can/ctucanfd/ctucanfd_platform.c +++ b/drivers/net/can/ctucanfd/ctucanfd_platform.c @@ -86,7 +86,7 @@ err: * This function frees all the resources allocated to the device. * Return: 0 always */ -static int ctucan_platform_remove(struct platform_device *pdev) +static void ctucan_platform_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct ctucan_priv *priv = netdev_priv(ndev); @@ -97,8 +97,6 @@ static int ctucan_platform_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); netif_napi_del(&priv->napi); free_candev(ndev); - - return 0; } static SIMPLE_DEV_PM_OPS(ctucan_platform_pm_ops, ctucan_suspend, ctucan_resume); @@ -113,7 +111,7 @@ MODULE_DEVICE_TABLE(of, ctucan_of_match); static struct platform_driver ctucanfd_driver = { .probe = ctucan_platform_probe, - .remove = ctucan_platform_remove, + .remove_new = ctucan_platform_remove, .driver = { .name = DRV_NAME, .pm = &ctucan_platform_pm_ops, diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c index b48140b1102e..b7f4d76dd444 100644 --- a/drivers/net/can/dev/length.c +++ b/drivers/net/can/dev/length.c @@ -78,18 +78,7 @@ unsigned int can_skb_get_frame_len(const struct sk_buff *skb) else len = cf->len; - if (can_is_canfd_skb(skb)) { - if (cf->can_id & CAN_EFF_FLAG) - len += CANFD_FRAME_OVERHEAD_EFF; - else - len += CANFD_FRAME_OVERHEAD_SFF; - } else { - if (cf->can_id & CAN_EFF_FLAG) - len += CAN_FRAME_OVERHEAD_EFF; - else - len += CAN_FRAME_OVERHEAD_SFF; - } - - return len; + return can_frame_bytes(can_is_canfd_skb(skb), cf->can_id & CAN_EFF_FLAG, + false, len); } EXPORT_SYMBOL_GPL(can_skb_get_frame_len); diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c index 81ebf0562c89..161e45a7e8c1 100644 --- a/drivers/net/can/dev/rx-offload.c +++ b/drivers/net/can/dev/rx-offload.c @@ -220,7 +220,7 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload) EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo); int can_rx_offload_queue_timestamp(struct can_rx_offload *offload, - struct sk_buff *skb, u32 timestamp) + struct sk_buff *skb, u32 timestamp) { struct can_rx_offload_cb *cb; diff --git a/drivers/net/can/flexcan/flexcan-core.c b/drivers/net/can/flexcan/flexcan-core.c index 6d638c93977b..ff0fc18baf13 100644 --- a/drivers/net/can/flexcan/flexcan-core.c +++ b/drivers/net/can/flexcan/flexcan-core.c @@ -2218,7 +2218,7 @@ static int flexcan_probe(struct platform_device *pdev) return err; } -static int flexcan_remove(struct platform_device *pdev) +static void flexcan_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); @@ -2227,8 +2227,6 @@ static int flexcan_remove(struct platform_device *pdev) unregister_flexcandev(dev); pm_runtime_disable(&pdev->dev); free_candev(dev); - - return 0; } static int __maybe_unused flexcan_suspend(struct device *device) @@ -2379,7 +2377,7 @@ static struct platform_driver flexcan_driver = { .of_match_table = flexcan_of_match, }, .probe = flexcan_probe, - .remove = flexcan_remove, + .remove_new = flexcan_remove, .id_table = flexcan_id_table, }; diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c index 4bedcc3eea0d..3174efdae271 100644 --- a/drivers/net/can/grcan.c +++ b/drivers/net/can/grcan.c @@ -1696,7 +1696,7 @@ exit_error: return err; } -static int grcan_remove(struct platform_device *ofdev) +static void grcan_remove(struct platform_device *ofdev) { struct net_device *dev = platform_get_drvdata(ofdev); struct grcan_priv *priv = netdev_priv(dev); @@ -1706,8 +1706,6 @@ static int grcan_remove(struct platform_device *ofdev) irq_dispose_mapping(dev->irq); netif_napi_del(&priv->napi); free_candev(dev); - - return 0; } static const struct of_device_id grcan_match[] = { @@ -1726,7 +1724,7 @@ static struct platform_driver grcan_driver = { .of_match_table = grcan_match, }, .probe = grcan_probe, - .remove = grcan_remove, + .remove_new = grcan_remove, }; module_platform_driver(grcan_driver); diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index 07eaf724a572..1d6642c94f2f 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -1013,15 +1013,13 @@ err_reg: return ret; } -static int ifi_canfd_plat_remove(struct platform_device *pdev) +static void ifi_canfd_plat_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); unregister_candev(ndev); platform_set_drvdata(pdev, NULL); free_candev(ndev); - - return 0; } static const struct of_device_id ifi_canfd_of_table[] = { @@ -1036,7 +1034,7 @@ static struct platform_driver ifi_canfd_plat_driver = { .of_match_table = ifi_canfd_of_table, }, .probe = ifi_canfd_plat_probe, - .remove = ifi_canfd_plat_remove, + .remove_new = ifi_canfd_plat_remove, }; module_platform_driver(ifi_canfd_plat_driver); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 0732a5092141..d048ea565b89 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -2023,7 +2023,7 @@ out_return: return ret; } -static int ican3_remove(struct platform_device *pdev) +static void ican3_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct ican3_dev *mod = netdev_priv(ndev); @@ -2042,8 +2042,6 @@ static int ican3_remove(struct platform_device *pdev) iounmap(mod->dpm); free_candev(ndev); - - return 0; } static struct platform_driver ican3_driver = { @@ -2051,7 +2049,7 @@ static struct platform_driver ican3_driver = { .name = DRV_NAME, }, .probe = ican3_probe, - .remove = ican3_remove, + .remove_new = ican3_remove, }; module_platform_driver(ican3_driver); diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index be189edb256c..db6256f2b1b3 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -3,19 +3,19 @@ * Parts of this driver are based on the following: * - Kvaser linux pciefd driver (version 5.25) * - PEAK linux canfd driver - * - Altera Avalon EPCS flash controller driver */ -#include <linux/kernel.h> -#include <linux/module.h> +#include <linux/bitfield.h> +#include <linux/can/dev.h> #include <linux/device.h> #include <linux/ethtool.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/minmax.h> +#include <linux/module.h> +#include <linux/netdevice.h> #include <linux/pci.h> -#include <linux/can/dev.h> #include <linux/timer.h> -#include <linux/netdevice.h> -#include <linux/crc32.h> -#include <linux/iopoll.h> MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Kvaser AB <support@kvaser.com>"); @@ -25,42 +25,25 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_WAIT_TIMEOUT msecs_to_jiffies(1000) #define KVASER_PCIEFD_BEC_POLL_FREQ (jiffies + msecs_to_jiffies(200)) -#define KVASER_PCIEFD_MAX_ERR_REP 256 -#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17 -#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4 -#define KVASER_PCIEFD_DMA_COUNT 2 +#define KVASER_PCIEFD_MAX_ERR_REP 256U +#define KVASER_PCIEFD_CAN_TX_MAX_COUNT 17U +#define KVASER_PCIEFD_MAX_CAN_CHANNELS 4UL +#define KVASER_PCIEFD_DMA_COUNT 2U -#define KVASER_PCIEFD_DMA_SIZE (4 * 1024) -#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) +#define KVASER_PCIEFD_DMA_SIZE (4U * 1024U) #define KVASER_PCIEFD_VENDOR 0x1a07 -#define KVASER_PCIEFD_4HS_ID 0x0d -#define KVASER_PCIEFD_2HS_ID 0x0e -#define KVASER_PCIEFD_HS_ID 0x0f -#define KVASER_PCIEFD_MINIPCIE_HS_ID 0x10 -#define KVASER_PCIEFD_MINIPCIE_2HS_ID 0x11 +#define KVASER_PCIEFD_4HS_DEVICE_ID 0x000d +#define KVASER_PCIEFD_2HS_V2_DEVICE_ID 0x000e +#define KVASER_PCIEFD_HS_V2_DEVICE_ID 0x000f +#define KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID 0x0010 +#define KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID 0x0011 /* PCIe IRQ registers */ #define KVASER_PCIEFD_IRQ_REG 0x40 #define KVASER_PCIEFD_IEN_REG 0x50 -/* DMA map */ +/* DMA address translation map register base */ #define KVASER_PCIEFD_DMA_MAP_BASE 0x1000 -/* Kvaser KCAN CAN controller registers */ -#define KVASER_PCIEFD_KCAN0_BASE 0x10000 -#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000 -#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 -#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 -#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 -#define KVASER_PCIEFD_KCAN_CMD_REG 0x400 -#define KVASER_PCIEFD_KCAN_IEN_REG 0x408 -#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410 -#define KVASER_PCIEFD_KCAN_TX_NPACKETS_REG 0x414 -#define KVASER_PCIEFD_KCAN_STAT_REG 0x418 -#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c -#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 -#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 -#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 -#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 /* Loopback control register */ #define KVASER_PCIEFD_LOOP_REG 0x1f000 /* System identification and information registers */ @@ -78,183 +61,196 @@ MODULE_DESCRIPTION("CAN driver for Kvaser CAN/PCIe devices"); #define KVASER_PCIEFD_SRB_STAT_REG (KVASER_PCIEFD_SRB_BASE + 0x210) #define KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG (KVASER_PCIEFD_SRB_BASE + 0x214) #define KVASER_PCIEFD_SRB_CTRL_REG (KVASER_PCIEFD_SRB_BASE + 0x218) -/* EPCS flash controller registers */ -#define KVASER_PCIEFD_SPI_BASE 0x1fc00 -#define KVASER_PCIEFD_SPI_RX_REG KVASER_PCIEFD_SPI_BASE -#define KVASER_PCIEFD_SPI_TX_REG (KVASER_PCIEFD_SPI_BASE + 0x4) -#define KVASER_PCIEFD_SPI_STATUS_REG (KVASER_PCIEFD_SPI_BASE + 0x8) -#define KVASER_PCIEFD_SPI_CTRL_REG (KVASER_PCIEFD_SPI_BASE + 0xc) -#define KVASER_PCIEFD_SPI_SSEL_REG (KVASER_PCIEFD_SPI_BASE + 0x14) - -#define KVASER_PCIEFD_IRQ_ALL_MSK 0x1f +/* Kvaser KCAN CAN controller registers */ +#define KVASER_PCIEFD_KCAN0_BASE 0x10000 +#define KVASER_PCIEFD_KCAN_BASE_OFFSET 0x1000 +#define KVASER_PCIEFD_KCAN_FIFO_REG 0x100 +#define KVASER_PCIEFD_KCAN_FIFO_LAST_REG 0x180 +#define KVASER_PCIEFD_KCAN_CTRL_REG 0x2c0 +#define KVASER_PCIEFD_KCAN_CMD_REG 0x400 +#define KVASER_PCIEFD_KCAN_IEN_REG 0x408 +#define KVASER_PCIEFD_KCAN_IRQ_REG 0x410 +#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG 0x414 +#define KVASER_PCIEFD_KCAN_STAT_REG 0x418 +#define KVASER_PCIEFD_KCAN_MODE_REG 0x41c +#define KVASER_PCIEFD_KCAN_BTRN_REG 0x420 +#define KVASER_PCIEFD_KCAN_BUS_LOAD_REG 0x424 +#define KVASER_PCIEFD_KCAN_BTRD_REG 0x428 +#define KVASER_PCIEFD_KCAN_PWM_REG 0x430 + +/* PCI interrupt fields */ #define KVASER_PCIEFD_IRQ_SRB BIT(4) +#define KVASER_PCIEFD_IRQ_ALL_MASK GENMASK(4, 0) -#define KVASER_PCIEFD_SYSID_NRCHAN_SHIFT 24 -#define KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT 16 -#define KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT 1 +/* Enable 64-bit DMA address translation */ +#define KVASER_PCIEFD_64BIT_DMA_BIT BIT(0) + +/* System build information fields */ +#define KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK GENMASK(31, 24) +#define KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK GENMASK(23, 16) +#define KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK GENMASK(7, 0) +#define KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK GENMASK(15, 1) /* Reset DMA buffer 0, 1 and FIFO offset */ -#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4) #define KVASER_PCIEFD_SRB_CMD_RDB1 BIT(5) +#define KVASER_PCIEFD_SRB_CMD_RDB0 BIT(4) #define KVASER_PCIEFD_SRB_CMD_FOR BIT(0) -/* DMA packet done, buffer 0 and 1 */ -#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8) -#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9) -/* DMA overflow, buffer 0 and 1 */ -#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10) -#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11) /* DMA underflow, buffer 0 and 1 */ -#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12) #define KVASER_PCIEFD_SRB_IRQ_DUF1 BIT(13) +#define KVASER_PCIEFD_SRB_IRQ_DUF0 BIT(12) +/* DMA overflow, buffer 0 and 1 */ +#define KVASER_PCIEFD_SRB_IRQ_DOF1 BIT(11) +#define KVASER_PCIEFD_SRB_IRQ_DOF0 BIT(10) +/* DMA packet done, buffer 0 and 1 */ +#define KVASER_PCIEFD_SRB_IRQ_DPD1 BIT(9) +#define KVASER_PCIEFD_SRB_IRQ_DPD0 BIT(8) +/* Got DMA support */ +#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24) /* DMA idle */ #define KVASER_PCIEFD_SRB_STAT_DI BIT(15) -/* DMA support */ -#define KVASER_PCIEFD_SRB_STAT_DMA BIT(24) /* SRB current packet level */ -#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK 0xff +#define KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK GENMASK(7, 0) /* DMA Enable */ #define KVASER_PCIEFD_SRB_CTRL_DMA_ENABLE BIT(0) -/* EPCS flash controller definitions */ -#define KVASER_PCIEFD_CFG_IMG_SZ (64 * 1024) -#define KVASER_PCIEFD_CFG_IMG_OFFSET (31 * 65536L) -#define KVASER_PCIEFD_CFG_MAX_PARAMS 256 -#define KVASER_PCIEFD_CFG_MAGIC 0xcafef00d -#define KVASER_PCIEFD_CFG_PARAM_MAX_SZ 24 -#define KVASER_PCIEFD_CFG_SYS_VER 1 -#define KVASER_PCIEFD_CFG_PARAM_NR_CHAN 130 -#define KVASER_PCIEFD_SPI_TMT BIT(5) -#define KVASER_PCIEFD_SPI_TRDY BIT(6) -#define KVASER_PCIEFD_SPI_RRDY BIT(7) -#define KVASER_PCIEFD_FLASH_ID_EPCS16 0x14 -/* Commands for controlling the onboard flash */ -#define KVASER_PCIEFD_FLASH_RES_CMD 0xab -#define KVASER_PCIEFD_FLASH_READ_CMD 0x3 -#define KVASER_PCIEFD_FLASH_STATUS_CMD 0x5 - -/* Kvaser KCAN definitions */ -#define KVASER_PCIEFD_KCAN_CTRL_EFLUSH (4 << 29) -#define KVASER_PCIEFD_KCAN_CTRL_EFRAME (5 << 29) - -#define KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT 16 -/* Request status packet */ -#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0) +/* KCAN CTRL packet types */ +#define KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK GENMASK(31, 29) +#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH 0x4 +#define KVASER_PCIEFD_KCAN_CTRL_TYPE_EFRAME 0x5 + +/* Command sequence number */ +#define KVASER_PCIEFD_KCAN_CMD_SEQ_MASK GENMASK(23, 16) +/* Command bits */ +#define KVASER_PCIEFD_KCAN_CMD_MASK GENMASK(5, 0) /* Abort, flush and reset */ #define KVASER_PCIEFD_KCAN_CMD_AT BIT(1) +/* Request status packet */ +#define KVASER_PCIEFD_KCAN_CMD_SRQ BIT(0) -/* Tx FIFO unaligned read */ -#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0) -/* Tx FIFO unaligned end */ -#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1) -/* Bus parameter protection error */ -#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2) -/* FDF bit when controller is in classic mode */ -#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3) -/* Rx FIFO overflow */ -#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5) -/* Abort done */ -#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13) -/* Tx buffer flush done */ -#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14) -/* Tx FIFO overflow */ -#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15) -/* Tx FIFO empty */ -#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16) /* Transmitter unaligned */ #define KVASER_PCIEFD_KCAN_IRQ_TAL BIT(17) +/* Tx FIFO empty */ +#define KVASER_PCIEFD_KCAN_IRQ_TE BIT(16) +/* Tx FIFO overflow */ +#define KVASER_PCIEFD_KCAN_IRQ_TOF BIT(15) +/* Tx buffer flush done */ +#define KVASER_PCIEFD_KCAN_IRQ_TFD BIT(14) +/* Abort done */ +#define KVASER_PCIEFD_KCAN_IRQ_ABD BIT(13) +/* Rx FIFO overflow */ +#define KVASER_PCIEFD_KCAN_IRQ_ROF BIT(5) +/* FDF bit when controller is in classic CAN mode */ +#define KVASER_PCIEFD_KCAN_IRQ_FDIC BIT(3) +/* Bus parameter protection error */ +#define KVASER_PCIEFD_KCAN_IRQ_BPP BIT(2) +/* Tx FIFO unaligned end */ +#define KVASER_PCIEFD_KCAN_IRQ_TAE BIT(1) +/* Tx FIFO unaligned read */ +#define KVASER_PCIEFD_KCAN_IRQ_TAR BIT(0) -#define KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT 16 +/* Tx FIFO size */ +#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK GENMASK(23, 16) +/* Tx FIFO current packet level */ +#define KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK GENMASK(7, 0) -#define KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT 24 -/* Abort request */ -#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7) -/* Idle state. Controller in reset mode and no abort or flush pending */ -#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10) -/* Bus off */ -#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11) -/* Reset mode request */ -#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14) -/* Controller in reset mode */ -#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15) -/* Controller got one-shot capability */ -#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16) +/* Current status packet sequence number */ +#define KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK GENMASK(31, 24) /* Controller got CAN FD capability */ #define KVASER_PCIEFD_KCAN_STAT_FD BIT(19) -#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK (KVASER_PCIEFD_KCAN_STAT_AR | \ - KVASER_PCIEFD_KCAN_STAT_BOFF | KVASER_PCIEFD_KCAN_STAT_RMR | \ - KVASER_PCIEFD_KCAN_STAT_IRM) +/* Controller got one-shot capability */ +#define KVASER_PCIEFD_KCAN_STAT_CAP BIT(16) +/* Controller in reset mode */ +#define KVASER_PCIEFD_KCAN_STAT_IRM BIT(15) +/* Reset mode request */ +#define KVASER_PCIEFD_KCAN_STAT_RMR BIT(14) +/* Bus off */ +#define KVASER_PCIEFD_KCAN_STAT_BOFF BIT(11) +/* Idle state. Controller in reset mode and no abort or flush pending */ +#define KVASER_PCIEFD_KCAN_STAT_IDLE BIT(10) +/* Abort request */ +#define KVASER_PCIEFD_KCAN_STAT_AR BIT(7) +/* Controller is bus off */ +#define KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK \ + (KVASER_PCIEFD_KCAN_STAT_AR | KVASER_PCIEFD_KCAN_STAT_BOFF | \ + KVASER_PCIEFD_KCAN_STAT_RMR | KVASER_PCIEFD_KCAN_STAT_IRM) -/* Reset mode */ -#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8) -/* Listen only mode */ -#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9) -/* Error packet enable */ -#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12) -/* CAN FD non-ISO */ -#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15) -/* Acknowledgment packet type */ -#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20) -/* Active error flag enable. Clear to force error passive */ -#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23) /* Classic CAN mode */ #define KVASER_PCIEFD_KCAN_MODE_CCM BIT(31) +/* Active error flag enable. Clear to force error passive */ +#define KVASER_PCIEFD_KCAN_MODE_EEN BIT(23) +/* Acknowledgment packet type */ +#define KVASER_PCIEFD_KCAN_MODE_APT BIT(20) +/* CAN FD non-ISO */ +#define KVASER_PCIEFD_KCAN_MODE_NIFDEN BIT(15) +/* Error packet enable */ +#define KVASER_PCIEFD_KCAN_MODE_EPEN BIT(12) +/* Listen only mode */ +#define KVASER_PCIEFD_KCAN_MODE_LOM BIT(9) +/* Reset mode */ +#define KVASER_PCIEFD_KCAN_MODE_RM BIT(8) -#define KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT 13 -#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT 17 -#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT 26 - -#define KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT 16 - -/* Kvaser KCAN packet types */ -#define KVASER_PCIEFD_PACK_TYPE_DATA 0 -#define KVASER_PCIEFD_PACK_TYPE_ACK 1 -#define KVASER_PCIEFD_PACK_TYPE_TXRQ 2 -#define KVASER_PCIEFD_PACK_TYPE_ERROR 3 -#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 4 -#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 5 -#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 6 -#define KVASER_PCIEFD_PACK_TYPE_STATUS 8 -#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 9 - -/* Kvaser KCAN packet common definitions */ -#define KVASER_PCIEFD_PACKET_SEQ_MSK 0xff -#define KVASER_PCIEFD_PACKET_CHID_SHIFT 25 -#define KVASER_PCIEFD_PACKET_TYPE_SHIFT 28 - -/* Kvaser KCAN TDATA and RDATA first word */ +/* BTRN and BTRD fields */ +#define KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK GENMASK(30, 26) +#define KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK GENMASK(25, 17) +#define KVASER_PCIEFD_KCAN_BTRN_SJW_MASK GENMASK(16, 13) +#define KVASER_PCIEFD_KCAN_BTRN_BRP_MASK GENMASK(12, 0) + +/* PWM Control fields */ +#define KVASER_PCIEFD_KCAN_PWM_TOP_MASK GENMASK(23, 16) +#define KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK GENMASK(7, 0) + +/* KCAN packet type IDs */ +#define KVASER_PCIEFD_PACK_TYPE_DATA 0x0 +#define KVASER_PCIEFD_PACK_TYPE_ACK 0x1 +#define KVASER_PCIEFD_PACK_TYPE_TXRQ 0x2 +#define KVASER_PCIEFD_PACK_TYPE_ERROR 0x3 +#define KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK 0x4 +#define KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK 0x5 +#define KVASER_PCIEFD_PACK_TYPE_ACK_DATA 0x6 +#define KVASER_PCIEFD_PACK_TYPE_STATUS 0x8 +#define KVASER_PCIEFD_PACK_TYPE_BUS_LOAD 0x9 + +/* Common KCAN packet definitions, second word */ +#define KVASER_PCIEFD_PACKET_TYPE_MASK GENMASK(31, 28) +#define KVASER_PCIEFD_PACKET_CHID_MASK GENMASK(27, 25) +#define KVASER_PCIEFD_PACKET_SEQ_MASK GENMASK(7, 0) + +/* KCAN Transmit/Receive data packet, first word */ #define KVASER_PCIEFD_RPACKET_IDE BIT(30) #define KVASER_PCIEFD_RPACKET_RTR BIT(29) -/* Kvaser KCAN TDATA and RDATA second word */ -#define KVASER_PCIEFD_RPACKET_ESI BIT(13) -#define KVASER_PCIEFD_RPACKET_BRS BIT(14) -#define KVASER_PCIEFD_RPACKET_FDF BIT(15) -#define KVASER_PCIEFD_RPACKET_DLC_SHIFT 8 -/* Kvaser KCAN TDATA second word */ -#define KVASER_PCIEFD_TPACKET_SMS BIT(16) +#define KVASER_PCIEFD_RPACKET_ID_MASK GENMASK(28, 0) +/* KCAN Transmit data packet, second word */ #define KVASER_PCIEFD_TPACKET_AREQ BIT(31) +#define KVASER_PCIEFD_TPACKET_SMS BIT(16) +/* KCAN Transmit/Receive data packet, second word */ +#define KVASER_PCIEFD_RPACKET_FDF BIT(15) +#define KVASER_PCIEFD_RPACKET_BRS BIT(14) +#define KVASER_PCIEFD_RPACKET_ESI BIT(13) +#define KVASER_PCIEFD_RPACKET_DLC_MASK GENMASK(11, 8) -/* Kvaser KCAN APACKET */ -#define KVASER_PCIEFD_APACKET_FLU BIT(8) -#define KVASER_PCIEFD_APACKET_CT BIT(9) -#define KVASER_PCIEFD_APACKET_ABL BIT(10) +/* KCAN Transmit acknowledge packet, first word */ #define KVASER_PCIEFD_APACKET_NACK BIT(11) +#define KVASER_PCIEFD_APACKET_ABL BIT(10) +#define KVASER_PCIEFD_APACKET_CT BIT(9) +#define KVASER_PCIEFD_APACKET_FLU BIT(8) -/* Kvaser KCAN SPACK first word */ -#define KVASER_PCIEFD_SPACK_RXERR_SHIFT 8 -#define KVASER_PCIEFD_SPACK_BOFF BIT(16) -#define KVASER_PCIEFD_SPACK_IDET BIT(20) -#define KVASER_PCIEFD_SPACK_IRM BIT(21) +/* KCAN Status packet, first word */ #define KVASER_PCIEFD_SPACK_RMCD BIT(22) -/* Kvaser KCAN SPACK second word */ -#define KVASER_PCIEFD_SPACK_AUTO BIT(21) -#define KVASER_PCIEFD_SPACK_EWLR BIT(23) +#define KVASER_PCIEFD_SPACK_IRM BIT(21) +#define KVASER_PCIEFD_SPACK_IDET BIT(20) +#define KVASER_PCIEFD_SPACK_BOFF BIT(16) +#define KVASER_PCIEFD_SPACK_RXERR_MASK GENMASK(15, 8) +#define KVASER_PCIEFD_SPACK_TXERR_MASK GENMASK(7, 0) +/* KCAN Status packet, second word */ #define KVASER_PCIEFD_SPACK_EPLR BIT(24) +#define KVASER_PCIEFD_SPACK_EWLR BIT(23) +#define KVASER_PCIEFD_SPACK_AUTO BIT(21) -/* Kvaser KCAN_EPACK second word */ +/* KCAN Error detected packet, second word */ #define KVASER_PCIEFD_EPACK_DIR_TX BIT(0) struct kvaser_pciefd; @@ -306,195 +302,43 @@ static const struct can_bittiming_const kvaser_pciefd_bittiming_const = { .brp_inc = 1, }; -struct kvaser_pciefd_cfg_param { - __le32 magic; - __le32 nr; - __le32 len; - u8 data[KVASER_PCIEFD_CFG_PARAM_MAX_SZ]; -}; - -struct kvaser_pciefd_cfg_img { - __le32 version; - __le32 magic; - __le32 crc; - struct kvaser_pciefd_cfg_param params[KVASER_PCIEFD_CFG_MAX_PARAMS]; -}; - static struct pci_device_id kvaser_pciefd_id_table[] = { - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_ID), }, - { PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_ID), }, - { 0,}, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_4HS_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_2HS_V2_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_HS_V2_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_HS_V2_DEVICE_ID), + }, + { + PCI_DEVICE(KVASER_PCIEFD_VENDOR, KVASER_PCIEFD_MINIPCIE_2HS_V2_DEVICE_ID), + }, + { + 0, + }, }; MODULE_DEVICE_TABLE(pci, kvaser_pciefd_id_table); -/* Onboard flash memory functions */ -static int kvaser_pciefd_spi_wait_loop(struct kvaser_pciefd *pcie, int msk) -{ - u32 res; - - return readl_poll_timeout(pcie->reg_base + KVASER_PCIEFD_SPI_STATUS_REG, - res, res & msk, 0, 10); -} - -static int kvaser_pciefd_spi_cmd(struct kvaser_pciefd *pcie, const u8 *tx, - u32 tx_len, u8 *rx, u32 rx_len) -{ - int c; - - iowrite32(BIT(0), pcie->reg_base + KVASER_PCIEFD_SPI_SSEL_REG); - iowrite32(BIT(10), pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); - ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); - - c = tx_len; - while (c--) { - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) - return -EIO; - - iowrite32(*tx++, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); - - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) - return -EIO; - - ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); - } - - c = rx_len; - while (c-- > 0) { - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TRDY)) - return -EIO; - - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_TX_REG); - - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_RRDY)) - return -EIO; - - *rx++ = ioread32(pcie->reg_base + KVASER_PCIEFD_SPI_RX_REG); - } - - if (kvaser_pciefd_spi_wait_loop(pcie, KVASER_PCIEFD_SPI_TMT)) - return -EIO; - - iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SPI_CTRL_REG); - - if (c != -1) { - dev_err(&pcie->pci->dev, "Flash SPI transfer failed\n"); - return -EIO; - } - - return 0; -} - -static int kvaser_pciefd_cfg_read_and_verify(struct kvaser_pciefd *pcie, - struct kvaser_pciefd_cfg_img *img) -{ - int offset = KVASER_PCIEFD_CFG_IMG_OFFSET; - int res, crc; - u8 *crc_buff; - - u8 cmd[] = { - KVASER_PCIEFD_FLASH_READ_CMD, - (u8)((offset >> 16) & 0xff), - (u8)((offset >> 8) & 0xff), - (u8)(offset & 0xff) - }; - - res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), (u8 *)img, - KVASER_PCIEFD_CFG_IMG_SZ); - if (res) - return res; - - crc_buff = (u8 *)img->params; - - if (le32_to_cpu(img->version) != KVASER_PCIEFD_CFG_SYS_VER) { - dev_err(&pcie->pci->dev, - "Config flash corrupted, version number is wrong\n"); - return -ENODEV; - } - - if (le32_to_cpu(img->magic) != KVASER_PCIEFD_CFG_MAGIC) { - dev_err(&pcie->pci->dev, - "Config flash corrupted, magic number is wrong\n"); - return -ENODEV; - } - - crc = ~crc32_be(0xffffffff, crc_buff, sizeof(img->params)); - if (le32_to_cpu(img->crc) != crc) { - dev_err(&pcie->pci->dev, - "Stored CRC does not match flash image contents\n"); - return -EIO; - } - - return 0; -} - -static void kvaser_pciefd_cfg_read_params(struct kvaser_pciefd *pcie, - struct kvaser_pciefd_cfg_img *img) +static inline void kvaser_pciefd_send_kcan_cmd(struct kvaser_pciefd_can *can, u32 cmd) { - struct kvaser_pciefd_cfg_param *param; - - param = &img->params[KVASER_PCIEFD_CFG_PARAM_NR_CHAN]; - memcpy(&pcie->nr_channels, param->data, le32_to_cpu(param->len)); + iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_MASK, cmd) | + FIELD_PREP(KVASER_PCIEFD_KCAN_CMD_SEQ_MASK, ++can->cmd_seq), + can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); } -static int kvaser_pciefd_read_cfg(struct kvaser_pciefd *pcie) +static inline void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can) { - int res; - struct kvaser_pciefd_cfg_img *img; - - /* Read electronic signature */ - u8 cmd[] = {KVASER_PCIEFD_FLASH_RES_CMD, 0, 0, 0}; - - res = kvaser_pciefd_spi_cmd(pcie, cmd, ARRAY_SIZE(cmd), cmd, 1); - if (res) - return -EIO; - - img = kmalloc(KVASER_PCIEFD_CFG_IMG_SZ, GFP_KERNEL); - if (!img) - return -ENOMEM; - - if (cmd[0] != KVASER_PCIEFD_FLASH_ID_EPCS16) { - dev_err(&pcie->pci->dev, - "Flash id is 0x%x instead of expected EPCS16 (0x%x)\n", - cmd[0], KVASER_PCIEFD_FLASH_ID_EPCS16); - - res = -ENODEV; - goto image_free; - } - - cmd[0] = KVASER_PCIEFD_FLASH_STATUS_CMD; - res = kvaser_pciefd_spi_cmd(pcie, cmd, 1, cmd, 1); - if (res) { - goto image_free; - } else if (cmd[0] & 1) { - res = -EIO; - /* No write is ever done, the WIP should never be set */ - dev_err(&pcie->pci->dev, "Unexpected WIP bit set in flash\n"); - goto image_free; - } - - res = kvaser_pciefd_cfg_read_and_verify(pcie, img); - if (res) { - res = -EIO; - goto image_free; - } - - kvaser_pciefd_cfg_read_params(pcie, img); - -image_free: - kfree(img); - return res; + kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_SRQ); } -static void kvaser_pciefd_request_status(struct kvaser_pciefd_can *can) +static inline void kvaser_pciefd_abort_flush_reset(struct kvaser_pciefd_can *can) { - u32 cmd; - - cmd = KVASER_PCIEFD_KCAN_CMD_SRQ; - cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; - iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + kvaser_pciefd_send_kcan_cmd(can, KVASER_PCIEFD_KCAN_CMD_AT); } static void kvaser_pciefd_enable_err_gen(struct kvaser_pciefd_can *can) @@ -523,7 +367,7 @@ static void kvaser_pciefd_disable_err_gen(struct kvaser_pciefd_can *can) spin_unlock_irqrestore(&can->lock, irq); } -static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) +static void kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) { u32 msk; @@ -534,8 +378,13 @@ static int kvaser_pciefd_set_tx_irq(struct kvaser_pciefd_can *can) KVASER_PCIEFD_KCAN_IRQ_TAR; iowrite32(msk, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); +} - return 0; +static inline void kvaser_pciefd_set_skb_timestamp(const struct kvaser_pciefd *pcie, + struct sk_buff *skb, u64 timestamp) +{ + skb_hwtstamps(skb)->hwtstamp = + ns_to_ktime(div_u64(timestamp * 1000, pcie->freq_to_ticks_div)); } static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) @@ -544,7 +393,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) unsigned long irq; spin_lock_irqsave(&can->lock, irq); - mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); if (can->can.ctrlmode & CAN_CTRLMODE_FD) { mode &= ~KVASER_PCIEFD_KCAN_MODE_CCM; @@ -561,7 +409,6 @@ static void kvaser_pciefd_setup_controller(struct kvaser_pciefd_can *can) mode |= KVASER_PCIEFD_KCAN_MODE_LOM; else mode &= ~KVASER_PCIEFD_KCAN_MODE_LOM; - mode |= KVASER_PCIEFD_KCAN_MODE_EEN; mode |= KVASER_PCIEFD_KCAN_MODE_EPEN; /* Use ACK packet type */ @@ -578,18 +425,13 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can) unsigned long irq; spin_lock_irqsave(&can->lock, irq); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); if (status & KVASER_PCIEFD_KCAN_STAT_IDLE) { - u32 cmd; - /* If controller is already idle, run abort, flush and reset */ - cmd = KVASER_PCIEFD_KCAN_CMD_AT; - cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; - iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + kvaser_pciefd_abort_flush_reset(can); } else if (!(status & KVASER_PCIEFD_KCAN_STAT_RMR)) { u32 mode; @@ -598,7 +440,6 @@ static void kvaser_pciefd_start_controller_flush(struct kvaser_pciefd_can *can) mode |= KVASER_PCIEFD_KCAN_MODE_RM; iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); } - spin_unlock_irqrestore(&can->lock, irq); } @@ -608,7 +449,6 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) unsigned long irq; del_timer(&can->bec_poll_timer); - if (!completion_done(&can->flush_comp)) kvaser_pciefd_start_controller_flush(can); @@ -620,11 +460,9 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) spin_lock_irqsave(&can->lock, irq); iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); - + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); mode &= ~KVASER_PCIEFD_KCAN_MODE_RM; iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); @@ -637,11 +475,10 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) } /* Reset interrupt handling */ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); kvaser_pciefd_set_tx_irq(can); kvaser_pciefd_setup_controller(can); - can->can.state = CAN_STATE_ERROR_ACTIVE; netif_wake_queue(can->can.dev); can->bec.txerr = 0; @@ -659,10 +496,9 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can) spin_lock_irqsave(&can->lock, irq); pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); - top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff; - + top = FIELD_GET(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, pwm_ctrl); /* Set duty cycle to zero */ - pwm_ctrl |= top; + pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top); iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); spin_unlock_irqrestore(&can->lock, irq); } @@ -675,18 +511,17 @@ static void kvaser_pciefd_pwm_start(struct kvaser_pciefd_can *can) kvaser_pciefd_pwm_stop(can); spin_lock_irqsave(&can->lock, irq); - - /* Set frequency to 500 KHz*/ + /* Set frequency to 500 KHz */ top = can->kv_pcie->bus_freq / (2 * 500000) - 1; - pwm_ctrl = top & 0xff; - pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, top); + pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top); iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); /* Set duty cycle to 95 */ trigger = (100 * top - 95 * (top + 1) + 50) / 100; - pwm_ctrl = trigger & 0xff; - pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + pwm_ctrl = FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TRIGGER_MASK, trigger); + pwm_ctrl |= FIELD_PREP(KVASER_PCIEFD_KCAN_PWM_TOP_MASK, top); iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); spin_unlock_irqrestore(&can->lock, irq); } @@ -741,7 +576,6 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p, int seq = can->echo_idx; memset(p, 0, sizeof(*p)); - if (can->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) p->header[1] |= KVASER_PCIEFD_TPACKET_SMS; @@ -751,19 +585,24 @@ static int kvaser_pciefd_prepare_tx_packet(struct kvaser_pciefd_tx_packet *p, if (cf->can_id & CAN_EFF_FLAG) p->header[0] |= KVASER_PCIEFD_RPACKET_IDE; - p->header[0] |= cf->can_id & CAN_EFF_MASK; - p->header[1] |= can_fd_len2dlc(cf->len) << KVASER_PCIEFD_RPACKET_DLC_SHIFT; + p->header[0] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_ID_MASK, cf->can_id); p->header[1] |= KVASER_PCIEFD_TPACKET_AREQ; if (can_is_canfd_skb(skb)) { + p->header[1] |= FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK, + can_fd_len2dlc(cf->len)); p->header[1] |= KVASER_PCIEFD_RPACKET_FDF; if (cf->flags & CANFD_BRS) p->header[1] |= KVASER_PCIEFD_RPACKET_BRS; if (cf->flags & CANFD_ESI) p->header[1] |= KVASER_PCIEFD_RPACKET_ESI; + } else { + p->header[1] |= + FIELD_PREP(KVASER_PCIEFD_RPACKET_DLC_MASK, + can_get_cc_dlc((struct can_frame *)cf, can->can.ctrlmode)); } - p->header[1] |= seq & KVASER_PCIEFD_PACKET_SEQ_MSK; + p->header[1] |= FIELD_PREP(KVASER_PCIEFD_PACKET_SEQ_MASK, seq); packet_size = cf->len; memcpy(p->data, cf->data, packet_size); @@ -777,16 +616,15 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, struct kvaser_pciefd_can *can = netdev_priv(netdev); unsigned long irq_flags; struct kvaser_pciefd_tx_packet packet; - int nwords; + int nr_words; u8 count; if (can_dev_dropped_skb(netdev, skb)) return NETDEV_TX_OK; - nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); + nr_words = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); spin_lock_irqsave(&can->echo_lock, irq_flags); - /* Prepare and save echo skb in internal slot */ can_put_echo_skb(skb, netdev, can->echo_idx, 0); @@ -799,13 +637,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, iowrite32(packet.header[1], can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG); - if (nwords) { - u32 data_last = ((u32 *)packet.data)[nwords - 1]; + if (nr_words) { + u32 data_last = ((u32 *)packet.data)[nr_words - 1]; /* Write data to fifo, except last word */ iowrite32_rep(can->reg_base + KVASER_PCIEFD_KCAN_FIFO_REG, packet.data, - nwords - 1); + nr_words - 1); /* Write last word to end of fifo */ __raw_writel(data_last, can->reg_base + KVASER_PCIEFD_KCAN_FIFO_LAST_REG); @@ -815,14 +653,13 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb, KVASER_PCIEFD_KCAN_FIFO_LAST_REG); } - count = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); + count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); /* No room for a new message, stop the queue until at least one * successful transmit */ - if (count >= KVASER_PCIEFD_CAN_TX_MAX_COUNT || - can->can.echo_skb[can->echo_idx]) + if (count >= can->can.echo_skb_max || can->can.echo_skb[can->echo_idx]) netif_stop_queue(netdev); - spin_unlock_irqrestore(&can->echo_lock, irq_flags); return NETDEV_TX_OK; @@ -840,25 +677,20 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data) else bt = &can->can.bittiming; - btrn = ((bt->phase_seg2 - 1) & 0x1f) << - KVASER_PCIEFD_KCAN_BTRN_TSEG2_SHIFT | - (((bt->prop_seg + bt->phase_seg1) - 1) & 0x1ff) << - KVASER_PCIEFD_KCAN_BTRN_TSEG1_SHIFT | - ((bt->sjw - 1) & 0xf) << KVASER_PCIEFD_KCAN_BTRN_SJW_SHIFT | - ((bt->brp - 1) & 0x1fff); + btrn = FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG2_MASK, bt->phase_seg2 - 1) | + FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_TSEG1_MASK, bt->prop_seg + bt->phase_seg1 - 1) | + FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_SJW_MASK, bt->sjw - 1) | + FIELD_PREP(KVASER_PCIEFD_KCAN_BTRN_BRP_MASK, bt->brp - 1); spin_lock_irqsave(&can->lock, irq_flags); mode = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); - /* Put the circuit in reset mode */ iowrite32(mode | KVASER_PCIEFD_KCAN_MODE_RM, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); /* Can only set bittiming if in reset mode */ ret = readl_poll_timeout(can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG, - test, test & KVASER_PCIEFD_KCAN_MODE_RM, - 0, 10); - + test, test & KVASER_PCIEFD_KCAN_MODE_RM, 0, 10); if (ret) { spin_unlock_irqrestore(&can->lock, irq_flags); return -EBUSY; @@ -868,11 +700,10 @@ static int kvaser_pciefd_set_bittiming(struct kvaser_pciefd_can *can, bool data) iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRD_REG); else iowrite32(btrn, can->reg_base + KVASER_PCIEFD_KCAN_BTRN_REG); - /* Restore previous reset mode status */ iowrite32(mode, can->reg_base + KVASER_PCIEFD_KCAN_MODE_REG); - spin_unlock_irqrestore(&can->lock, irq_flags); + return 0; } @@ -910,6 +741,7 @@ static int kvaser_pciefd_get_berr_counter(const struct net_device *ndev, bec->rxerr = can->bec.rxerr; bec->txerr = can->bec.txerr; + return 0; } @@ -941,7 +773,7 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) for (i = 0; i < pcie->nr_channels; i++) { struct net_device *netdev; struct kvaser_pciefd_can *can; - u32 status, tx_npackets; + u32 status, tx_nr_packets_max; netdev = alloc_candev(sizeof(struct kvaser_pciefd_can), KVASER_PCIEFD_CAN_TX_MAX_COUNT); @@ -953,7 +785,6 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) netdev->ethtool_ops = &kvaser_pciefd_ethtool_ops; can->reg_base = pcie->reg_base + KVASER_PCIEFD_KCAN0_BASE + i * KVASER_PCIEFD_KCAN_BASE_OFFSET; - can->kv_pcie = pcie; can->cmd_seq = 0; can->err_rep_cnt = 0; @@ -962,41 +793,31 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) init_completion(&can->start_comp); init_completion(&can->flush_comp); - timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, - 0); + timer_setup(&can->bec_poll_timer, kvaser_pciefd_bec_poll_timer, 0); /* Disable Bus load reporting */ iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_BUS_LOAD_REG); - tx_npackets = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG); - if (((tx_npackets >> KVASER_PCIEFD_KCAN_TX_NPACKETS_MAX_SHIFT) & - 0xff) < KVASER_PCIEFD_CAN_TX_MAX_COUNT) { - dev_err(&pcie->pci->dev, - "Max Tx count is smaller than expected\n"); - - free_candev(netdev); - return -ENODEV; - } + tx_nr_packets_max = + FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_MAX_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); can->can.clock.freq = pcie->freq; - can->can.echo_skb_max = KVASER_PCIEFD_CAN_TX_MAX_COUNT; + can->can.echo_skb_max = min(KVASER_PCIEFD_CAN_TX_MAX_COUNT, tx_nr_packets_max - 1); can->echo_idx = 0; spin_lock_init(&can->echo_lock); spin_lock_init(&can->lock); + can->can.bittiming_const = &kvaser_pciefd_bittiming_const; can->can.data_bittiming_const = &kvaser_pciefd_bittiming_const; - can->can.do_set_bittiming = kvaser_pciefd_set_nominal_bittiming; - can->can.do_set_data_bittiming = - kvaser_pciefd_set_data_bittiming; - + can->can.do_set_data_bittiming = kvaser_pciefd_set_data_bittiming; can->can.do_set_mode = kvaser_pciefd_set_mode; can->can.do_get_berr_counter = kvaser_pciefd_get_berr_counter; - can->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD | - CAN_CTRLMODE_FD_NON_ISO; + CAN_CTRLMODE_FD_NON_ISO | + CAN_CTRLMODE_CC_LEN8_DLC; status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); if (!(status & KVASER_PCIEFD_KCAN_STAT_FD)) { @@ -1011,10 +832,9 @@ static int kvaser_pciefd_setup_can_ctrls(struct kvaser_pciefd *pcie) can->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; netdev->flags |= IFF_ECHO; - SET_NETDEV_DEV(netdev, &pcie->pci->dev); - iowrite32(-1, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); + iowrite32(GENMASK(31, 0), can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); @@ -1073,18 +893,16 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) for (i = 0; i < KVASER_PCIEFD_DMA_COUNT; i++) { unsigned int offset = KVASER_PCIEFD_DMA_MAP_BASE + 8 * i; - pcie->dma_data[i] = - dmam_alloc_coherent(&pcie->pci->dev, - KVASER_PCIEFD_DMA_SIZE, - &dma_addr[i], - GFP_KERNEL); + pcie->dma_data[i] = dmam_alloc_coherent(&pcie->pci->dev, + KVASER_PCIEFD_DMA_SIZE, + &dma_addr[i], + GFP_KERNEL); if (!pcie->dma_data[i] || !dma_addr[i]) { dev_err(&pcie->pci->dev, "Rx dma_alloc(%u) failure\n", KVASER_PCIEFD_DMA_SIZE); return -ENOMEM; } - kvaser_pciefd_write_dma_map(pcie, dma_addr[i], offset); } @@ -1092,10 +910,10 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) iowrite32(KVASER_PCIEFD_SRB_CMD_FOR | KVASER_PCIEFD_SRB_CMD_RDB0 | KVASER_PCIEFD_SRB_CMD_RDB1, pcie->reg_base + KVASER_PCIEFD_SRB_CMD_REG); - /* Empty Rx FIFO */ - srb_packet_count = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG) & - KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK; + srb_packet_count = + FIELD_GET(KVASER_PCIEFD_SRB_RX_NR_PACKETS_MASK, + ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_RX_NR_PACKETS_REG)); while (srb_packet_count) { /* Drop current packet in FIFO */ ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_FIFO_LAST_REG); @@ -1117,37 +935,21 @@ static int kvaser_pciefd_setup_dma(struct kvaser_pciefd *pcie) static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) { - u32 sysid, srb_status, build; - u8 sysid_nr_chan; - int ret; - - ret = kvaser_pciefd_read_cfg(pcie); - if (ret) - return ret; - - sysid = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); - sysid_nr_chan = (sysid >> KVASER_PCIEFD_SYSID_NRCHAN_SHIFT) & 0xff; - if (pcie->nr_channels != sysid_nr_chan) { - dev_err(&pcie->pci->dev, - "Number of channels does not match: %u vs %u\n", - pcie->nr_channels, - sysid_nr_chan); - return -ENODEV; - } + u32 version, srb_status, build; - if (pcie->nr_channels > KVASER_PCIEFD_MAX_CAN_CHANNELS) - pcie->nr_channels = KVASER_PCIEFD_MAX_CAN_CHANNELS; + version = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_VERSION_REG); + pcie->nr_channels = min(KVASER_PCIEFD_MAX_CAN_CHANNELS, + FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_NR_CHAN_MASK, version)); build = ioread32(pcie->reg_base + KVASER_PCIEFD_SYSID_BUILD_REG); - dev_dbg(&pcie->pci->dev, "Version %u.%u.%u\n", - (sysid >> KVASER_PCIEFD_SYSID_MAJOR_VER_SHIFT) & 0xff, - sysid & 0xff, - (build >> KVASER_PCIEFD_SYSID_BUILD_VER_SHIFT) & 0x7fff); + dev_dbg(&pcie->pci->dev, "Version %lu.%lu.%lu\n", + FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MAJOR_MASK, version), + FIELD_GET(KVASER_PCIEFD_SYSID_VERSION_MINOR_MASK, version), + FIELD_GET(KVASER_PCIEFD_SYSID_BUILD_SEQ_MASK, build)); srb_status = ioread32(pcie->reg_base + KVASER_PCIEFD_SRB_STAT_REG); if (!(srb_status & KVASER_PCIEFD_SRB_STAT_DMA)) { - dev_err(&pcie->pci->dev, - "Hardware without DMA is not supported\n"); + dev_err(&pcie->pci->dev, "Hardware without DMA is not supported\n"); return -ENODEV; } @@ -1157,10 +959,10 @@ static int kvaser_pciefd_setup_board(struct kvaser_pciefd *pcie) pcie->freq_to_ticks_div = pcie->freq / 1000000; if (pcie->freq_to_ticks_div == 0) pcie->freq_to_ticks_div = 1; - /* Turn off all loopback functionality */ iowrite32(0, pcie->reg_base + KVASER_PCIEFD_LOOP_REG); - return ret; + + return 0; } static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie, @@ -1170,56 +972,48 @@ static int kvaser_pciefd_handle_data_packet(struct kvaser_pciefd *pcie, struct sk_buff *skb; struct canfd_frame *cf; struct can_priv *priv; - struct net_device_stats *stats; - struct skb_shared_hwtstamps *shhwtstamps; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); + u8 dlc; if (ch_id >= pcie->nr_channels) return -EIO; priv = &pcie->can[ch_id]->can; - stats = &priv->dev->stats; + dlc = FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, p->header[1]); if (p->header[1] & KVASER_PCIEFD_RPACKET_FDF) { skb = alloc_canfd_skb(priv->dev, &cf); if (!skb) { - stats->rx_dropped++; + priv->dev->stats.rx_dropped++; return -ENOMEM; } + cf->len = can_fd_dlc2len(dlc); if (p->header[1] & KVASER_PCIEFD_RPACKET_BRS) cf->flags |= CANFD_BRS; - if (p->header[1] & KVASER_PCIEFD_RPACKET_ESI) cf->flags |= CANFD_ESI; } else { skb = alloc_can_skb(priv->dev, (struct can_frame **)&cf); if (!skb) { - stats->rx_dropped++; + priv->dev->stats.rx_dropped++; return -ENOMEM; } + can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->ctrlmode); } - cf->can_id = p->header[0] & CAN_EFF_MASK; + cf->can_id = FIELD_GET(KVASER_PCIEFD_RPACKET_ID_MASK, p->header[0]); if (p->header[0] & KVASER_PCIEFD_RPACKET_IDE) cf->can_id |= CAN_EFF_FLAG; - cf->len = can_fd_dlc2len(p->header[1] >> KVASER_PCIEFD_RPACKET_DLC_SHIFT); - if (p->header[0] & KVASER_PCIEFD_RPACKET_RTR) { cf->can_id |= CAN_RTR_FLAG; } else { memcpy(cf->data, data, cf->len); - - stats->rx_bytes += cf->len; + priv->dev->stats.rx_bytes += cf->len; } - stats->rx_packets++; - - shhwtstamps = skb_hwtstamps(skb); - - shhwtstamps->hwtstamp = - ns_to_ktime(div_u64(p->timestamp * 1000, - pcie->freq_to_ticks_div)); + priv->dev->stats.rx_packets++; + kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp); return netif_rx(skb); } @@ -1239,7 +1033,6 @@ static void kvaser_pciefd_change_state(struct kvaser_pciefd_can *can, spin_lock_irqsave(&can->lock, irq_flags); netif_stop_queue(can->can.dev); spin_unlock_irqrestore(&can->lock, irq_flags); - /* Prevent CAN controller from auto recover from bus off */ if (!can->can.restart_ms) { kvaser_pciefd_start_controller_flush(can); @@ -1257,7 +1050,7 @@ static void kvaser_pciefd_packet_to_state(struct kvaser_pciefd_rx_packet *p, if (p->header[0] & KVASER_PCIEFD_SPACK_BOFF || p->header[0] & KVASER_PCIEFD_SPACK_IRM) *new_state = CAN_STATE_BUS_OFF; - else if (bec->txerr >= 255 || bec->rxerr >= 255) + else if (bec->txerr >= 255 || bec->rxerr >= 255) *new_state = CAN_STATE_BUS_OFF; else if (p->header[1] & KVASER_PCIEFD_SPACK_EPLR) *new_state = CAN_STATE_ERROR_PASSIVE; @@ -1282,23 +1075,16 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, struct net_device *ndev = can->can.dev; struct sk_buff *skb; struct can_frame *cf = NULL; - struct skb_shared_hwtstamps *shhwtstamps; - struct net_device_stats *stats = &ndev->stats; old_state = can->can.state; - bec.txerr = p->header[0] & 0xff; - bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; - - kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, - &rx_state); + bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]); + bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]); + kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state); skb = alloc_can_err_skb(ndev, &cf); - if (new_state != old_state) { - kvaser_pciefd_change_state(can, cf, new_state, tx_state, - rx_state); - + kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state); if (old_state == CAN_STATE_BUS_OFF && new_state == CAN_STATE_ERROR_ACTIVE && can->can.restart_ms) { @@ -1311,28 +1097,25 @@ static int kvaser_pciefd_rx_error_frame(struct kvaser_pciefd_can *can, can->err_rep_cnt++; can->can.can_stats.bus_error++; if (p->header[1] & KVASER_PCIEFD_EPACK_DIR_TX) - stats->tx_errors++; + ndev->stats.tx_errors++; else - stats->rx_errors++; + ndev->stats.rx_errors++; can->bec.txerr = bec.txerr; can->bec.rxerr = bec.rxerr; if (!skb) { - stats->rx_dropped++; + ndev->stats.rx_dropped++; return -ENOMEM; } - shhwtstamps = skb_hwtstamps(skb); - shhwtstamps->hwtstamp = - ns_to_ktime(div_u64(p->timestamp * 1000, - can->kv_pcie->freq_to_ticks_div)); + kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_CNT; - cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; netif_rx(skb); + return 0; } @@ -1340,19 +1123,19 @@ static int kvaser_pciefd_handle_error_packet(struct kvaser_pciefd *pcie, struct kvaser_pciefd_rx_packet *p) { struct kvaser_pciefd_can *can; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; can = pcie->can[ch_id]; - kvaser_pciefd_rx_error_frame(can, p); if (can->err_rep_cnt >= KVASER_PCIEFD_MAX_ERR_REP) /* Do not report more errors, until bec_poll_timer expires */ kvaser_pciefd_disable_err_gen(can); /* Start polling the error counters */ mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); + return 0; } @@ -1364,29 +1147,22 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can, old_state = can->can.state; - bec.txerr = p->header[0] & 0xff; - bec.rxerr = (p->header[0] >> KVASER_PCIEFD_SPACK_RXERR_SHIFT) & 0xff; - - kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, - &rx_state); + bec.txerr = FIELD_GET(KVASER_PCIEFD_SPACK_TXERR_MASK, p->header[0]); + bec.rxerr = FIELD_GET(KVASER_PCIEFD_SPACK_RXERR_MASK, p->header[0]); + kvaser_pciefd_packet_to_state(p, &bec, &new_state, &tx_state, &rx_state); if (new_state != old_state) { struct net_device *ndev = can->can.dev; struct sk_buff *skb; struct can_frame *cf; - struct skb_shared_hwtstamps *shhwtstamps; skb = alloc_can_err_skb(ndev, &cf); if (!skb) { - struct net_device_stats *stats = &ndev->stats; - - stats->rx_dropped++; + ndev->stats.rx_dropped++; return -ENOMEM; } - kvaser_pciefd_change_state(can, cf, new_state, tx_state, - rx_state); - + kvaser_pciefd_change_state(can, cf, new_state, tx_state, rx_state); if (old_state == CAN_STATE_BUS_OFF && new_state == CAN_STATE_ERROR_ACTIVE && can->can.restart_ms) { @@ -1394,10 +1170,7 @@ static int kvaser_pciefd_handle_status_resp(struct kvaser_pciefd_can *can, cf->can_id |= CAN_ERR_RESTARTED; } - shhwtstamps = skb_hwtstamps(skb); - shhwtstamps->hwtstamp = - ns_to_ktime(div_u64(p->timestamp * 1000, - can->kv_pcie->freq_to_ticks_div)); + kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); cf->data[6] = bec.txerr; cf->data[7] = bec.rxerr; @@ -1419,7 +1192,7 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, struct kvaser_pciefd_can *can; u8 cmdseq; u32 status; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; @@ -1427,43 +1200,40 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, can = pcie->can[ch_id]; status = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_STAT_REG); - cmdseq = (status >> KVASER_PCIEFD_KCAN_STAT_SEQNO_SHIFT) & 0xff; + cmdseq = FIELD_GET(KVASER_PCIEFD_KCAN_STAT_SEQNO_MASK, status); /* Reset done, start abort and flush */ if (p->header[0] & KVASER_PCIEFD_SPACK_IRM && p->header[0] & KVASER_PCIEFD_SPACK_RMCD && p->header[1] & KVASER_PCIEFD_SPACK_AUTO && - cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && + cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) && status & KVASER_PCIEFD_KCAN_STAT_IDLE) { - u32 cmd; - iowrite32(KVASER_PCIEFD_KCAN_IRQ_ABD, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); - cmd = KVASER_PCIEFD_KCAN_CMD_AT; - cmd |= ++can->cmd_seq << KVASER_PCIEFD_KCAN_CMD_SEQ_SHIFT; - iowrite32(cmd, can->reg_base + KVASER_PCIEFD_KCAN_CMD_REG); + kvaser_pciefd_abort_flush_reset(can); } else if (p->header[0] & KVASER_PCIEFD_SPACK_IDET && p->header[0] & KVASER_PCIEFD_SPACK_IRM && - cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK) && + cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1]) && status & KVASER_PCIEFD_KCAN_STAT_IDLE) { /* Reset detected, send end of flush if no packet are in FIFO */ - u8 count = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + u8 count; + count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); if (!count) - iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, + iowrite32(FIELD_PREP(KVASER_PCIEFD_KCAN_CTRL_TYPE_MASK, + KVASER_PCIEFD_KCAN_CTRL_TYPE_EFLUSH), can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); } else if (!(p->header[1] & KVASER_PCIEFD_SPACK_AUTO) && - cmdseq == (p->header[1] & KVASER_PCIEFD_PACKET_SEQ_MSK)) { + cmdseq == FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[1])) { /* Response to status request received */ kvaser_pciefd_handle_status_resp(can, p); if (can->can.state != CAN_STATE_BUS_OFF && can->can.state != CAN_STATE_ERROR_ACTIVE) { - mod_timer(&can->bec_poll_timer, - KVASER_PCIEFD_BEC_POLL_FREQ); + mod_timer(&can->bec_poll_timer, KVASER_PCIEFD_BEC_POLL_FREQ); } } else if (p->header[0] & KVASER_PCIEFD_SPACK_RMCD && - !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MSK)) { + !(status & KVASER_PCIEFD_KCAN_STAT_BUS_OFF_MASK)) { /* Reset to bus on detected */ if (!completion_done(&can->start_comp)) complete(&can->start_comp); @@ -1472,50 +1242,14 @@ static int kvaser_pciefd_handle_status_packet(struct kvaser_pciefd *pcie, return 0; } -static int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie, - struct kvaser_pciefd_rx_packet *p) -{ - struct kvaser_pciefd_can *can; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; - - if (ch_id >= pcie->nr_channels) - return -EIO; - - can = pcie->can[ch_id]; - - /* If this is the last flushed packet, send end of flush */ - if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { - u8 count = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; - - if (count == 0) - iowrite32(KVASER_PCIEFD_KCAN_CTRL_EFLUSH, - can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG); - } else { - int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; - int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL); - struct net_device_stats *stats = &can->can.dev->stats; - - stats->tx_bytes += dlc; - stats->tx_packets++; - - if (netif_queue_stopped(can->can.dev)) - netif_wake_queue(can->can.dev); - } - - return 0; -} - static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can, struct kvaser_pciefd_rx_packet *p) { struct sk_buff *skb; - struct net_device_stats *stats = &can->can.dev->stats; struct can_frame *cf; skb = alloc_can_err_skb(can->can.dev, &cf); - - stats->tx_errors++; + can->can.dev->stats.tx_errors++; if (p->header[0] & KVASER_PCIEFD_APACKET_ABL) { if (skb) cf->can_id |= CAN_ERR_LOSTARB; @@ -1526,9 +1260,10 @@ static void kvaser_pciefd_handle_nack_packet(struct kvaser_pciefd_can *can, if (skb) { cf->can_id |= CAN_ERR_BUSERROR; + kvaser_pciefd_set_skb_timestamp(can->kv_pcie, skb, p->timestamp); netif_rx(skb); } else { - stats->rx_dropped++; + can->can.dev->stats.rx_dropped++; netdev_warn(can->can.dev, "No memory left for err_skb\n"); } } @@ -1538,7 +1273,7 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie, { struct kvaser_pciefd_can *can; bool one_shot_fail = false; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; @@ -1556,20 +1291,24 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie, if (p->header[0] & KVASER_PCIEFD_APACKET_FLU) { netdev_dbg(can->can.dev, "Packet was flushed\n"); } else { - int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK; - int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL); - u8 count = ioread32(can->reg_base + - KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff; + int echo_idx = FIELD_GET(KVASER_PCIEFD_PACKET_SEQ_MASK, p->header[0]); + int len; + u8 count; + struct sk_buff *skb; - if (count < KVASER_PCIEFD_CAN_TX_MAX_COUNT && - netif_queue_stopped(can->can.dev)) + skb = can->can.echo_skb[echo_idx]; + if (skb) + kvaser_pciefd_set_skb_timestamp(pcie, skb, p->timestamp); + len = can_get_echo_skb(can->can.dev, echo_idx, NULL); + count = FIELD_GET(KVASER_PCIEFD_KCAN_TX_NR_PACKETS_CURRENT_MASK, + ioread32(can->reg_base + KVASER_PCIEFD_KCAN_TX_NR_PACKETS_REG)); + + if (count < can->can.echo_skb_max && netif_queue_stopped(can->can.dev)) netif_wake_queue(can->can.dev); if (!one_shot_fail) { - struct net_device_stats *stats = &can->can.dev->stats; - - stats->tx_bytes += dlc; - stats->tx_packets++; + can->can.dev->stats.tx_bytes += len; + can->can.dev->stats.tx_packets++; } } @@ -1580,7 +1319,7 @@ static int kvaser_pciefd_handle_eflush_packet(struct kvaser_pciefd *pcie, struct kvaser_pciefd_rx_packet *p) { struct kvaser_pciefd_can *can; - u8 ch_id = (p->header[1] >> KVASER_PCIEFD_PACKET_CHID_SHIFT) & 0x7; + u8 ch_id = FIELD_GET(KVASER_PCIEFD_PACKET_CHID_MASK, p->header[1]); if (ch_id >= pcie->nr_channels) return -EIO; @@ -1619,15 +1358,15 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos, pos += 2; p->timestamp = le64_to_cpu(timestamp); - type = (p->header[1] >> KVASER_PCIEFD_PACKET_TYPE_SHIFT) & 0xf; + type = FIELD_GET(KVASER_PCIEFD_PACKET_TYPE_MASK, p->header[1]); switch (type) { case KVASER_PCIEFD_PACK_TYPE_DATA: ret = kvaser_pciefd_handle_data_packet(pcie, p, &buffer[pos]); if (!(p->header[0] & KVASER_PCIEFD_RPACKET_RTR)) { u8 data_len; - data_len = can_fd_dlc2len(p->header[1] >> - KVASER_PCIEFD_RPACKET_DLC_SHIFT); + data_len = can_fd_dlc2len(FIELD_GET(KVASER_PCIEFD_RPACKET_DLC_MASK, + p->header[1])); pos += DIV_ROUND_UP(data_len, 4); } break; @@ -1644,16 +1383,13 @@ static int kvaser_pciefd_read_packet(struct kvaser_pciefd *pcie, int *start_pos, ret = kvaser_pciefd_handle_error_packet(pcie, p); break; - case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK: - ret = kvaser_pciefd_handle_eack_packet(pcie, p); - break; - case KVASER_PCIEFD_PACK_TYPE_EFLUSH_ACK: ret = kvaser_pciefd_handle_eflush_packet(pcie, p); break; case KVASER_PCIEFD_PACK_TYPE_ACK_DATA: case KVASER_PCIEFD_PACK_TYPE_BUS_LOAD: + case KVASER_PCIEFD_PACK_TYPE_EFRAME_ACK: case KVASER_PCIEFD_PACK_TYPE_TXRQ: dev_info(&pcie->pci->dev, "Received unexpected packet type 0x%08X\n", type); @@ -1692,7 +1428,7 @@ static int kvaser_pciefd_read_buffer(struct kvaser_pciefd *pcie, int dma_buf) return res; } -static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) +static void kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) { u32 irq; @@ -1718,10 +1454,9 @@ static int kvaser_pciefd_receive_irq(struct kvaser_pciefd *pcie) dev_err(&pcie->pci->dev, "DMA IRQ error 0x%08X\n", irq); iowrite32(irq, pcie->reg_base + KVASER_PCIEFD_SRB_IRQ_REG); - return 0; } -static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) +static void kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) { u32 irq = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); @@ -1739,7 +1474,6 @@ static int kvaser_pciefd_transmit_irq(struct kvaser_pciefd_can *can) netdev_err(can->can.dev, "Rx FIFO overflow\n"); iowrite32(irq, can->reg_base + KVASER_PCIEFD_KCAN_IRQ_REG); - return 0; } static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) @@ -1750,7 +1484,7 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) board_irq = ioread32(pcie->reg_base + KVASER_PCIEFD_IRQ_REG); - if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MSK)) + if (!(board_irq & KVASER_PCIEFD_IRQ_ALL_MASK)) return IRQ_NONE; if (board_irq & KVASER_PCIEFD_IRQ_SRB) @@ -1768,20 +1502,18 @@ static irqreturn_t kvaser_pciefd_irq_handler(int irq, void *dev) kvaser_pciefd_transmit_irq(pcie->can[i]); } - iowrite32(board_irq, pcie->reg_base + KVASER_PCIEFD_IRQ_REG); return IRQ_HANDLED; } static void kvaser_pciefd_teardown_can_ctrls(struct kvaser_pciefd *pcie) { int i; - struct kvaser_pciefd_can *can; for (i = 0; i < pcie->nr_channels; i++) { - can = pcie->can[i]; + struct kvaser_pciefd_can *can = pcie->can[i]; + if (can) { - iowrite32(0, - can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); kvaser_pciefd_pwm_stop(can); free_candev(can->can.dev); } @@ -1842,10 +1574,8 @@ static int kvaser_pciefd_probe(struct pci_dev *pdev, KVASER_PCIEFD_SRB_IRQ_DUF0 | KVASER_PCIEFD_SRB_IRQ_DUF1, pcie->reg_base + KVASER_PCIEFD_SRB_IEN_REG); - /* Reset IRQ handling, expected to be off before */ - iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, - pcie->reg_base + KVASER_PCIEFD_IRQ_REG); - iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, + /* Enable PCI interrupts */ + iowrite32(KVASER_PCIEFD_IRQ_ALL_MASK, pcie->reg_base + KVASER_PCIEFD_IEN_REG); /* Ready the DMA buffers */ @@ -1884,14 +1614,13 @@ err_disable_pci: static void kvaser_pciefd_remove_all_ctrls(struct kvaser_pciefd *pcie) { - struct kvaser_pciefd_can *can; int i; for (i = 0; i < pcie->nr_channels; i++) { - can = pcie->can[i]; + struct kvaser_pciefd_can *can = pcie->can[i]; + if (can) { - iowrite32(0, - can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); + iowrite32(0, can->reg_base + KVASER_PCIEFD_KCAN_IEN_REG); unregister_candev(can->can.dev); del_timer(&can->bec_poll_timer); kvaser_pciefd_pwm_stop(can); @@ -1906,10 +1635,8 @@ static void kvaser_pciefd_remove(struct pci_dev *pdev) kvaser_pciefd_remove_all_ctrls(pcie); - /* Turn off IRQ generation */ + /* Disable interrupts */ iowrite32(0, pcie->reg_base + KVASER_PCIEFD_SRB_CTRL_REG); - iowrite32(KVASER_PCIEFD_IRQ_ALL_MSK, - pcie->reg_base + KVASER_PCIEFD_IRQ_REG); iowrite32(0, pcie->reg_base + KVASER_PCIEFD_IEN_REG); free_irq(pcie->pci->irq, pcie); diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index a5003435802b..c5af92bcc9c9 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -469,7 +469,7 @@ static void m_can_receive_skb(struct m_can_classdev *cdev, int err; err = can_rx_offload_queue_timestamp(&cdev->offload, skb, - timestamp); + timestamp); if (err) stats->rx_fifo_errors++; } else { @@ -895,7 +895,7 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, netdev_dbg(dev, "Arbitration phase error detected\n"); work_done += m_can_handle_lec_err(dev, lec); } - + if (is_lec_err(dlec)) { netdev_dbg(dev, "Data phase error detected\n"); work_done += m_can_handle_lec_err(dev, dlec); diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c index 9c1dcf838006..94dc82644113 100644 --- a/drivers/net/can/m_can/m_can_platform.c +++ b/drivers/net/can/m_can/m_can_platform.c @@ -164,7 +164,7 @@ static __maybe_unused int m_can_resume(struct device *dev) return m_can_class_resume(dev); } -static int m_can_plat_remove(struct platform_device *pdev) +static void m_can_plat_remove(struct platform_device *pdev) { struct m_can_plat_priv *priv = platform_get_drvdata(pdev); struct m_can_classdev *mcan_class = &priv->cdev; @@ -172,8 +172,6 @@ static int m_can_plat_remove(struct platform_device *pdev) m_can_class_unregister(mcan_class); m_can_class_free_dev(mcan_class->net); - - return 0; } static int __maybe_unused m_can_runtime_suspend(struct device *dev) @@ -223,7 +221,7 @@ static struct platform_driver m_can_plat_driver = { .pm = &m_can_pmops, }, .probe = m_can_plat_probe, - .remove = m_can_plat_remove, + .remove_new = m_can_plat_remove, }; module_platform_driver(m_can_plat_driver); diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index b0ed798ae70f..4837df6efa92 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -349,7 +349,7 @@ exit_unmap_mem: return err; } -static int mpc5xxx_can_remove(struct platform_device *ofdev) +static void mpc5xxx_can_remove(struct platform_device *ofdev) { const struct of_device_id *match; const struct mpc5xxx_can_data *data; @@ -365,8 +365,6 @@ static int mpc5xxx_can_remove(struct platform_device *ofdev) iounmap(priv->reg_base); irq_dispose_mapping(dev->irq); free_candev(dev); - - return 0; } #ifdef CONFIG_PM @@ -437,7 +435,7 @@ static struct platform_driver mpc5xxx_can_driver = { .of_match_table = mpc5xxx_can_table, }, .probe = mpc5xxx_can_probe, - .remove = mpc5xxx_can_remove, + .remove_new = mpc5xxx_can_remove, #ifdef CONFIG_PM .suspend = mpc5xxx_can_suspend, .resume = mpc5xxx_can_resume, diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index cc43c9c5e38c..f5aa5dbacaf2 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -824,7 +824,7 @@ fail: return err; } -static int rcar_can_remove(struct platform_device *pdev) +static void rcar_can_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct rcar_can_priv *priv = netdev_priv(ndev); @@ -832,7 +832,6 @@ static int rcar_can_remove(struct platform_device *pdev) unregister_candev(ndev); netif_napi_del(&priv->napi); free_candev(ndev); - return 0; } static int __maybe_unused rcar_can_suspend(struct device *dev) @@ -908,7 +907,7 @@ static struct platform_driver rcar_can_driver = { .pm = &rcar_can_pm_ops, }, .probe = rcar_can_probe, - .remove = rcar_can_remove, + .remove_new = rcar_can_remove, }; module_platform_driver(rcar_can_driver); diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c index 963c42f43755..e4d748913439 100644 --- a/drivers/net/can/rcar/rcar_canfd.c +++ b/drivers/net/can/rcar/rcar_canfd.c @@ -2078,7 +2078,7 @@ fail_dev: return err; } -static int rcar_canfd_remove(struct platform_device *pdev) +static void rcar_canfd_remove(struct platform_device *pdev) { struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev); u32 ch; @@ -2096,8 +2096,6 @@ static int rcar_canfd_remove(struct platform_device *pdev) clk_disable_unprepare(gpriv->clkp); reset_control_assert(gpriv->rstc1); reset_control_assert(gpriv->rstc2); - - return 0; } static int __maybe_unused rcar_canfd_suspend(struct device *dev) @@ -2130,7 +2128,7 @@ static struct platform_driver rcar_canfd_driver = { .pm = &rcar_canfd_pm_ops, }, .probe = rcar_canfd_probe, - .remove = rcar_canfd_remove, + .remove_new = rcar_canfd_remove, }; module_platform_driver(rcar_canfd_driver); diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index aac5956e4a53..0ada0e160e93 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -387,6 +387,16 @@ static void sja1000_rx(struct net_device *dev) netif_rx(skb); } +static irqreturn_t sja1000_reset_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = (struct net_device *)dev_id; + + netdev_dbg(dev, "performing a soft reset upon overrun\n"); + sja1000_start(dev); + + return IRQ_HANDLED; +} + static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) { struct sja1000_priv *priv = netdev_priv(dev); @@ -397,6 +407,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) enum can_state rx_state, tx_state; unsigned int rxerr, txerr; uint8_t ecc, alc; + int ret = 0; skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) @@ -413,6 +424,15 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) stats->rx_over_errors++; stats->rx_errors++; sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */ + + /* Some controllers needs additional handling upon overrun + * condition: the controller may sometimes be totally confused + * and refuse any new frame while its buffer is empty. The only + * way to re-sync the read vs. write buffer offsets is to + * stop any current handling and perform a reset. + */ + if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN) + ret = IRQ_WAKE_THREAD; } if (isrc & IRQ_EI) { @@ -492,7 +512,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) netif_rx(skb); - return 0; + return ret; } irqreturn_t sja1000_interrupt(int irq, void *dev_id) @@ -501,7 +521,8 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) struct sja1000_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; uint8_t isrc, status; - int n = 0; + irqreturn_t ret = 0; + int n = 0, err; if (priv->pre_irq) priv->pre_irq(priv); @@ -546,19 +567,25 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) } if (isrc & (IRQ_DOI | IRQ_EI | IRQ_BEI | IRQ_EPI | IRQ_ALI)) { /* error interrupt */ - if (sja1000_err(dev, isrc, status)) + err = sja1000_err(dev, isrc, status); + if (err == IRQ_WAKE_THREAD) + ret = err; + if (err) break; } n++; } out: + if (!ret) + ret = (n) ? IRQ_HANDLED : IRQ_NONE; + if (priv->post_irq) priv->post_irq(priv); if (n >= SJA1000_MAX_IRQ) netdev_dbg(dev, "%d messages handled in ISR", n); - return (n) ? IRQ_HANDLED : IRQ_NONE; + return ret; } EXPORT_SYMBOL_GPL(sja1000_interrupt); @@ -577,8 +604,9 @@ static int sja1000_open(struct net_device *dev) /* register interrupt handler, if not done by the device driver */ if (!(priv->flags & SJA1000_CUSTOM_IRQ_HANDLER)) { - err = request_irq(dev->irq, sja1000_interrupt, priv->irq_flags, - dev->name, (void *)dev); + err = request_threaded_irq(dev->irq, sja1000_interrupt, + sja1000_reset_interrupt, + priv->irq_flags, dev->name, (void *)dev); if (err) { close_candev(dev); return -EAGAIN; diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h index 7f736f1df547..f015e39e2224 100644 --- a/drivers/net/can/sja1000/sja1000.h +++ b/drivers/net/can/sja1000/sja1000.h @@ -147,6 +147,7 @@ */ #define SJA1000_CUSTOM_IRQ_HANDLER BIT(0) #define SJA1000_QUIRK_NO_CDR_REG BIT(1) +#define SJA1000_QUIRK_RESET_ON_OVERRUN BIT(2) /* * SJA1000 private data structure diff --git a/drivers/net/can/sja1000/sja1000_isa.c b/drivers/net/can/sja1000/sja1000_isa.c index db3e767d5320..fca5a9a1d857 100644 --- a/drivers/net/can/sja1000/sja1000_isa.c +++ b/drivers/net/can/sja1000/sja1000_isa.c @@ -223,7 +223,7 @@ exit: return err; } -static int sja1000_isa_remove(struct platform_device *pdev) +static void sja1000_isa_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); struct sja1000_priv *priv = netdev_priv(dev); @@ -241,13 +241,11 @@ static int sja1000_isa_remove(struct platform_device *pdev) release_region(port[idx], SJA1000_IOSIZE); } free_sja1000dev(dev); - - return 0; } static struct platform_driver sja1000_isa_driver = { .probe = sja1000_isa_probe, - .remove = sja1000_isa_remove, + .remove_new = sja1000_isa_remove, .driver = { .name = DRV_NAME, }, diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index 6779d5357069..4e59952c66d4 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -106,7 +106,7 @@ static void sp_technologic_init(struct sja1000_priv *priv, struct device_node *o static void sp_rzn1_init(struct sja1000_priv *priv, struct device_node *of) { - priv->flags = SJA1000_QUIRK_NO_CDR_REG; + priv->flags = SJA1000_QUIRK_NO_CDR_REG | SJA1000_QUIRK_RESET_ON_OVERRUN; } static void sp_populate(struct sja1000_priv *priv, @@ -277,6 +277,9 @@ static int sp_probe(struct platform_device *pdev) priv->irq_flags = IRQF_SHARED; } + if (priv->flags & SJA1000_QUIRK_RESET_ON_OVERRUN) + priv->irq_flags |= IRQF_ONESHOT; + dev->irq = irq; priv->reg_base = addr; @@ -317,19 +320,17 @@ static int sp_probe(struct platform_device *pdev) return err; } -static int sp_remove(struct platform_device *pdev) +static void sp_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); unregister_sja1000dev(dev); free_sja1000dev(dev); - - return 0; } static struct platform_driver sp_driver = { .probe = sp_probe, - .remove = sp_remove, + .remove_new = sp_remove, .driver = { .name = DRV_NAME, .of_match_table = sp_of_table, diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index c72f505d29fe..bd25137062c5 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -729,7 +729,7 @@ static const struct attribute_group softing_pdev_group = { /* * platform driver */ -static int softing_pdev_remove(struct platform_device *pdev) +static void softing_pdev_remove(struct platform_device *pdev) { struct softing *card = platform_get_drvdata(pdev); int j; @@ -747,7 +747,6 @@ static int softing_pdev_remove(struct platform_device *pdev) iounmap(card->dpram); kfree(card); - return 0; } static int softing_pdev_probe(struct platform_device *pdev) @@ -855,7 +854,7 @@ static struct platform_driver softing_driver = { .name = KBUILD_MODNAME, }, .probe = softing_pdev_probe, - .remove = softing_pdev_remove, + .remove_new = softing_pdev_remove, }; module_platform_driver(softing_driver); diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 2b78f9197681..0827830bbf28 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -791,14 +791,12 @@ static const struct of_device_id sun4ican_of_match[] = { MODULE_DEVICE_TABLE(of, sun4ican_of_match); -static int sun4ican_remove(struct platform_device *pdev) +static void sun4ican_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); unregister_netdev(dev); free_candev(dev); - - return 0; } static int sun4ican_probe(struct platform_device *pdev) @@ -901,7 +899,7 @@ static struct platform_driver sun4i_can_driver = { .of_match_table = sun4ican_of_match, }, .probe = sun4ican_probe, - .remove = sun4ican_remove, + .remove_new = sun4ican_remove, }; module_platform_driver(sun4i_can_driver); diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 27700f72eac2..54284661992e 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -625,7 +625,7 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, timestamp = hecc_read(priv, HECC_CANLNT); err = can_rx_offload_queue_timestamp(&priv->offload, skb, - timestamp); + timestamp); if (err) ndev->stats.rx_fifo_errors++; } @@ -963,7 +963,7 @@ probe_exit_candev: return err; } -static int ti_hecc_remove(struct platform_device *pdev) +static void ti_hecc_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); @@ -973,8 +973,6 @@ static int ti_hecc_remove(struct platform_device *pdev) clk_put(priv->clk); can_rx_offload_del(&priv->offload); free_candev(ndev); - - return 0; } #ifdef CONFIG_PM @@ -1028,7 +1026,7 @@ static struct platform_driver ti_hecc_driver = { .of_match_table = ti_hecc_dt_ids, }, .probe = ti_hecc_probe, - .remove = ti_hecc_remove, + .remove_new = ti_hecc_remove, .suspend = ti_hecc_suspend, .resume = ti_hecc_resume, }; diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig index 445504ababce..58fcd2b34820 100644 --- a/drivers/net/can/usb/Kconfig +++ b/drivers/net/can/usb/Kconfig @@ -38,6 +38,18 @@ config CAN_ETAS_ES58X To compile this driver as a module, choose M here: the module will be called etas_es58x. +config CAN_F81604 + tristate "Fintek F81604 USB to 2CAN interface" + help + This driver supports the Fintek F81604 USB to 2CAN interface. + The device can support CAN2.0A/B protocol and also support + 2 output pins to control external terminator (optional). + + To compile this driver as a module, choose M here: the module will + be called f81604. + + (see also https://www.fintek.com.tw). + config CAN_GS_USB tristate "Geschwister Schneider UG and candleLight compatible interfaces" help diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile index 1ea16be5743b..8b11088e9a59 100644 --- a/drivers/net/can/usb/Makefile +++ b/drivers/net/can/usb/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o obj-$(CONFIG_CAN_ESD_USB) += esd_usb.o obj-$(CONFIG_CAN_ETAS_ES58X) += etas_es58x/ +obj-$(CONFIG_CAN_F81604) += f81604.o obj-$(CONFIG_CAN_GS_USB) += gs_usb.o obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb/ obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index d33bac3a6c10..6201637ac0ff 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -3,18 +3,19 @@ * CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Micro * * Copyright (C) 2010-2012 esd electronic system design gmbh, Matthias Fuchs <socketcan@esd.eu> - * Copyright (C) 2022 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu> + * Copyright (C) 2022-2023 esd electronics gmbh, Frank Jungclaus <frank.jungclaus@esd.eu> */ -#include <linux/ethtool.h> -#include <linux/signal.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/usb.h> #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/ethtool.h> +#include <linux/module.h> +#include <linux/netdevice.h> +#include <linux/signal.h> +#include <linux/slab.h> +#include <linux/units.h> +#include <linux/usb.h> MODULE_AUTHOR("Matthias Fuchs <socketcan@esd.eu>"); MODULE_AUTHOR("Frank Jungclaus <frank.jungclaus@esd.eu>"); @@ -22,95 +23,87 @@ MODULE_DESCRIPTION("CAN driver for esd electronics gmbh CAN-USB/2 and CAN-USB/Mi MODULE_LICENSE("GPL v2"); /* USB vendor and product ID */ -#define USB_ESDGMBH_VENDOR_ID 0x0ab4 -#define USB_CANUSB2_PRODUCT_ID 0x0010 -#define USB_CANUSBM_PRODUCT_ID 0x0011 +#define ESD_USB_ESDGMBH_VENDOR_ID 0x0ab4 +#define ESD_USB_CANUSB2_PRODUCT_ID 0x0010 +#define ESD_USB_CANUSBM_PRODUCT_ID 0x0011 /* CAN controller clock frequencies */ -#define ESD_USB2_CAN_CLOCK 60000000 -#define ESD_USBM_CAN_CLOCK 36000000 +#define ESD_USB_2_CAN_CLOCK (60 * MEGA) /* Hz */ +#define ESD_USB_M_CAN_CLOCK (36 * MEGA) /* Hz */ /* Maximum number of CAN nets */ #define ESD_USB_MAX_NETS 2 /* USB commands */ -#define CMD_VERSION 1 /* also used for VERSION_REPLY */ -#define CMD_CAN_RX 2 /* device to host only */ -#define CMD_CAN_TX 3 /* also used for TX_DONE */ -#define CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */ -#define CMD_TS 5 /* also used for TS_REPLY */ -#define CMD_IDADD 6 /* also used for IDADD_REPLY */ +#define ESD_USB_CMD_VERSION 1 /* also used for VERSION_REPLY */ +#define ESD_USB_CMD_CAN_RX 2 /* device to host only */ +#define ESD_USB_CMD_CAN_TX 3 /* also used for TX_DONE */ +#define ESD_USB_CMD_SETBAUD 4 /* also used for SETBAUD_REPLY */ +#define ESD_USB_CMD_TS 5 /* also used for TS_REPLY */ +#define ESD_USB_CMD_IDADD 6 /* also used for IDADD_REPLY */ /* esd CAN message flags - dlc field */ -#define ESD_RTR 0x10 +#define ESD_USB_RTR BIT(4) /* esd CAN message flags - id field */ -#define ESD_EXTID 0x20000000 -#define ESD_EVENT 0x40000000 -#define ESD_IDMASK 0x1fffffff +#define ESD_USB_EXTID BIT(29) +#define ESD_USB_EVENT BIT(30) +#define ESD_USB_IDMASK GENMASK(28, 0) /* esd CAN event ids */ -#define ESD_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */ +#define ESD_USB_EV_CAN_ERROR_EXT 2 /* CAN controller specific diagnostic data */ /* baudrate message flags */ -#define ESD_USB_UBR 0x80000000 -#define ESD_USB_LOM 0x40000000 -#define ESD_USB_NO_BAUDRATE 0x7fffffff - -/* bit timing CAN-USB/2 */ -#define ESD_USB2_TSEG1_MIN 1 -#define ESD_USB2_TSEG1_MAX 16 -#define ESD_USB2_TSEG1_SHIFT 16 -#define ESD_USB2_TSEG2_MIN 1 -#define ESD_USB2_TSEG2_MAX 8 -#define ESD_USB2_TSEG2_SHIFT 20 -#define ESD_USB2_SJW_MAX 4 -#define ESD_USB2_SJW_SHIFT 14 -#define ESD_USBM_SJW_SHIFT 24 -#define ESD_USB2_BRP_MIN 1 -#define ESD_USB2_BRP_MAX 1024 -#define ESD_USB2_BRP_INC 1 -#define ESD_USB2_3_SAMPLES 0x00800000 +#define ESD_USB_LOM BIT(30) /* Listen Only Mode */ +#define ESD_USB_UBR BIT(31) /* User Bit Rate (controller BTR) in bits 0..27 */ +#define ESD_USB_NO_BAUDRATE GENMASK(30, 0) /* bit rate unconfigured */ + +/* bit timing esd CAN-USB */ +#define ESD_USB_2_TSEG1_SHIFT 16 +#define ESD_USB_2_TSEG2_SHIFT 20 +#define ESD_USB_2_SJW_SHIFT 14 +#define ESD_USB_M_SJW_SHIFT 24 +#define ESD_USB_TRIPLE_SAMPLES BIT(23) /* esd IDADD message */ -#define ESD_ID_ENABLE 0x80 -#define ESD_MAX_ID_SEGMENT 64 +#define ESD_USB_ID_ENABLE BIT(7) +#define ESD_USB_MAX_ID_SEGMENT 64 /* SJA1000 ECC register (emulated by usb firmware) */ -#define SJA1000_ECC_SEG 0x1F -#define SJA1000_ECC_DIR 0x20 -#define SJA1000_ECC_ERR 0x06 -#define SJA1000_ECC_BIT 0x00 -#define SJA1000_ECC_FORM 0x40 -#define SJA1000_ECC_STUFF 0x80 -#define SJA1000_ECC_MASK 0xc0 +#define ESD_USB_SJA1000_ECC_SEG GENMASK(4, 0) +#define ESD_USB_SJA1000_ECC_DIR BIT(5) +#define ESD_USB_SJA1000_ECC_ERR BIT(2, 1) +#define ESD_USB_SJA1000_ECC_BIT 0x00 +#define ESD_USB_SJA1000_ECC_FORM BIT(6) +#define ESD_USB_SJA1000_ECC_STUFF BIT(7) +#define ESD_USB_SJA1000_ECC_MASK GENMASK(7, 6) /* esd bus state event codes */ -#define ESD_BUSSTATE_MASK 0xc0 -#define ESD_BUSSTATE_WARN 0x40 -#define ESD_BUSSTATE_ERRPASSIVE 0x80 -#define ESD_BUSSTATE_BUSOFF 0xc0 +#define ESD_USB_BUSSTATE_MASK GENMASK(7, 6) +#define ESD_USB_BUSSTATE_WARN BIT(6) +#define ESD_USB_BUSSTATE_ERRPASSIVE BIT(7) +#define ESD_USB_BUSSTATE_BUSOFF GENMASK(7, 6) -#define RX_BUFFER_SIZE 1024 -#define MAX_RX_URBS 4 -#define MAX_TX_URBS 16 /* must be power of 2 */ +#define ESD_USB_RX_BUFFER_SIZE 1024 +#define ESD_USB_MAX_RX_URBS 4 +#define ESD_USB_MAX_TX_URBS 16 /* must be power of 2 */ -struct header_msg { - u8 len; /* len is always the total message length in 32bit words */ +struct esd_usb_header_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 rsvd[2]; }; -struct version_msg { - u8 len; +struct esd_usb_version_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 rsvd; u8 flags; __le32 drv_version; }; -struct version_reply_msg { - u8 len; +struct esd_usb_version_reply_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 nets; u8 features; @@ -120,15 +113,15 @@ struct version_reply_msg { __le32 ts; }; -struct rx_msg { - u8 len; +struct esd_usb_rx_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 dlc; __le32 ts; __le32 id; /* upper 3 bits contain flags */ union { - u8 data[8]; + u8 data[CAN_MAX_DLEN]; struct { u8 status; /* CAN Controller Status */ u8 ecc; /* Error Capture Register */ @@ -138,18 +131,18 @@ struct rx_msg { }; }; -struct tx_msg { - u8 len; +struct esd_usb_tx_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 dlc; u32 hnd; /* opaque handle, not used by device */ __le32 id; /* upper 3 bits contain flags */ - u8 data[8]; + u8 data[CAN_MAX_DLEN]; }; -struct tx_done_msg { - u8 len; +struct esd_usb_tx_done_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 status; @@ -157,16 +150,16 @@ struct tx_done_msg { __le32 ts; }; -struct id_filter_msg { - u8 len; +struct esd_usb_id_filter_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 option; - __le32 mask[ESD_MAX_ID_SEGMENT + 1]; + __le32 mask[ESD_USB_MAX_ID_SEGMENT + 1]; /* +1 for 29bit extended IDs */ }; -struct set_baudrate_msg { - u8 len; +struct esd_usb_set_baudrate_msg { + u8 len; /* total message length in 32bit words */ u8 cmd; u8 net; u8 rsvd; @@ -175,19 +168,19 @@ struct set_baudrate_msg { /* Main message type used between library and application */ union __packed esd_usb_msg { - struct header_msg hdr; - struct version_msg version; - struct version_reply_msg version_reply; - struct rx_msg rx; - struct tx_msg tx; - struct tx_done_msg txdone; - struct set_baudrate_msg setbaud; - struct id_filter_msg filter; + struct esd_usb_header_msg hdr; + struct esd_usb_version_msg version; + struct esd_usb_version_reply_msg version_reply; + struct esd_usb_rx_msg rx; + struct esd_usb_tx_msg tx; + struct esd_usb_tx_done_msg txdone; + struct esd_usb_set_baudrate_msg setbaud; + struct esd_usb_id_filter_msg filter; }; static struct usb_device_id esd_usb_table[] = { - {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)}, - {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)}, + {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSB2_PRODUCT_ID)}, + {USB_DEVICE(ESD_USB_ESDGMBH_VENDOR_ID, ESD_USB_CANUSBM_PRODUCT_ID)}, {} }; MODULE_DEVICE_TABLE(usb, esd_usb_table); @@ -208,8 +201,8 @@ struct esd_usb { int net_count; u32 version; int rxinitdone; - void *rxbuf[MAX_RX_URBS]; - dma_addr_t rxbuf_dma[MAX_RX_URBS]; + void *rxbuf[ESD_USB_MAX_RX_URBS]; + dma_addr_t rxbuf_dma[ESD_USB_MAX_RX_URBS]; }; struct esd_usb_net_priv { @@ -217,7 +210,7 @@ struct esd_usb_net_priv { atomic_t active_tx_jobs; struct usb_anchor tx_submitted; - struct esd_tx_urb_context tx_contexts[MAX_TX_URBS]; + struct esd_tx_urb_context tx_contexts[ESD_USB_MAX_TX_URBS]; struct esd_usb *usb; struct net_device *netdev; @@ -232,9 +225,9 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, struct net_device_stats *stats = &priv->netdev->stats; struct can_frame *cf; struct sk_buff *skb; - u32 id = le32_to_cpu(msg->rx.id) & ESD_IDMASK; + u32 id = le32_to_cpu(msg->rx.id) & ESD_USB_IDMASK; - if (id == ESD_EV_CAN_ERROR_EXT) { + if (id == ESD_USB_EV_CAN_ERROR_EXT) { u8 state = msg->rx.ev_can_err_ext.status; u8 ecc = msg->rx.ev_can_err_ext.ecc; @@ -261,15 +254,15 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, priv->old_state = state; - switch (state & ESD_BUSSTATE_MASK) { - case ESD_BUSSTATE_BUSOFF: + switch (state & ESD_USB_BUSSTATE_MASK) { + case ESD_USB_BUSSTATE_BUSOFF: new_state = CAN_STATE_BUS_OFF; can_bus_off(priv->netdev); break; - case ESD_BUSSTATE_WARN: + case ESD_USB_BUSSTATE_WARN: new_state = CAN_STATE_ERROR_WARNING; break; - case ESD_BUSSTATE_ERRPASSIVE: + case ESD_USB_BUSSTATE_ERRPASSIVE: new_state = CAN_STATE_ERROR_PASSIVE; break; default: @@ -291,14 +284,14 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; - switch (ecc & SJA1000_ECC_MASK) { - case SJA1000_ECC_BIT: + switch (ecc & ESD_USB_SJA1000_ECC_MASK) { + case ESD_USB_SJA1000_ECC_BIT: cf->data[2] |= CAN_ERR_PROT_BIT; break; - case SJA1000_ECC_FORM: + case ESD_USB_SJA1000_ECC_FORM: cf->data[2] |= CAN_ERR_PROT_FORM; break; - case SJA1000_ECC_STUFF: + case ESD_USB_SJA1000_ECC_STUFF: cf->data[2] |= CAN_ERR_PROT_STUFF; break; default: @@ -306,11 +299,11 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, } /* Error occurred during transmission? */ - if (!(ecc & SJA1000_ECC_DIR)) + if (!(ecc & ESD_USB_SJA1000_ECC_DIR)) cf->data[2] |= CAN_ERR_PROT_TX; /* Bit stream position in CAN frame as the error was detected */ - cf->data[3] = ecc & SJA1000_ECC_SEG; + cf->data[3] = ecc & ESD_USB_SJA1000_ECC_SEG; } if (skb) { @@ -337,7 +330,7 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, id = le32_to_cpu(msg->rx.id); - if (id & ESD_EVENT) { + if (id & ESD_USB_EVENT) { esd_usb_rx_event(priv, msg); } else { skb = alloc_can_skb(priv->netdev, &cf); @@ -346,14 +339,14 @@ static void esd_usb_rx_can_msg(struct esd_usb_net_priv *priv, return; } - cf->can_id = id & ESD_IDMASK; - can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_RTR, + cf->can_id = id & ESD_USB_IDMASK; + can_frame_set_cc_len(cf, msg->rx.dlc & ~ESD_USB_RTR, priv->can.ctrlmode); - if (id & ESD_EXTID) + if (id & ESD_USB_EXTID) cf->can_id |= CAN_EFF_FLAG; - if (msg->rx.dlc & ESD_RTR) { + if (msg->rx.dlc & ESD_USB_RTR) { cf->can_id |= CAN_RTR_FLAG; } else { for (i = 0; i < cf->len; i++) @@ -377,7 +370,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv, if (!netif_device_present(netdev)) return; - context = &priv->tx_contexts[msg->txdone.hnd & (MAX_TX_URBS - 1)]; + context = &priv->tx_contexts[msg->txdone.hnd & (ESD_USB_MAX_TX_URBS - 1)]; if (!msg->txdone.status) { stats->tx_packets++; @@ -389,7 +382,7 @@ static void esd_usb_tx_done_msg(struct esd_usb_net_priv *priv, } /* Release context */ - context->echo_index = MAX_TX_URBS; + context->echo_index = ESD_USB_MAX_TX_URBS; atomic_dec(&priv->active_tx_jobs); netif_wake_queue(netdev); @@ -424,7 +417,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) msg = (union esd_usb_msg *)(urb->transfer_buffer + pos); switch (msg->hdr.cmd) { - case CMD_CAN_RX: + case ESD_USB_CMD_CAN_RX: if (msg->rx.net >= dev->net_count) { dev_err(dev->udev->dev.parent, "format error\n"); break; @@ -433,7 +426,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) esd_usb_rx_can_msg(dev->nets[msg->rx.net], msg); break; - case CMD_CAN_TX: + case ESD_USB_CMD_CAN_TX: if (msg->txdone.net >= dev->net_count) { dev_err(dev->udev->dev.parent, "format error\n"); break; @@ -444,7 +437,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) break; } - pos += msg->hdr.len << 2; + pos += msg->hdr.len * sizeof(u32); /* convert to # of bytes */ if (pos > urb->actual_length) { dev_err(dev->udev->dev.parent, "format error\n"); @@ -454,7 +447,7 @@ static void esd_usb_read_bulk_callback(struct urb *urb) resubmit_urb: usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - urb->transfer_buffer, RX_BUFFER_SIZE, + urb->transfer_buffer, ESD_USB_RX_BUFFER_SIZE, esd_usb_read_bulk_callback, dev); retval = usb_submit_urb(urb, GFP_ATOMIC); @@ -538,7 +531,7 @@ static int esd_usb_send_msg(struct esd_usb *dev, union esd_usb_msg *msg) return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), msg, - msg->hdr.len << 2, + msg->hdr.len * sizeof(u32), /* convert to # of bytes */ &actual_length, 1000); } @@ -563,7 +556,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) if (dev->rxinitdone) return 0; - for (i = 0; i < MAX_RX_URBS; i++) { + for (i = 0; i < ESD_USB_MAX_RX_URBS; i++) { struct urb *urb = NULL; u8 *buf = NULL; dma_addr_t buf_dma; @@ -575,7 +568,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) break; } - buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL, + buf = usb_alloc_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, GFP_KERNEL, &buf_dma); if (!buf) { dev_warn(dev->udev->dev.parent, @@ -588,7 +581,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - buf, RX_BUFFER_SIZE, + buf, ESD_USB_RX_BUFFER_SIZE, esd_usb_read_bulk_callback, dev); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; usb_anchor_urb(urb, &dev->rx_submitted); @@ -596,7 +589,7 @@ static int esd_usb_setup_rx_urbs(struct esd_usb *dev) err = usb_submit_urb(urb, GFP_KERNEL); if (err) { usb_unanchor_urb(urb); - usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf, + usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, buf, urb->transfer_dma); goto freeurb; } @@ -618,7 +611,7 @@ freeurb: } /* Warn if we've couldn't transmit all the URBs */ - if (i < MAX_RX_URBS) { + if (i < ESD_USB_MAX_RX_URBS) { dev_warn(dev->udev->dev.parent, "rx performance may be slow\n"); } @@ -653,14 +646,14 @@ static int esd_usb_start(struct esd_usb_net_priv *priv) * the number of the starting bitmask (0..64) to the filter.option * field followed by only some bitmasks. */ - msg->hdr.cmd = CMD_IDADD; - msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT; + msg->hdr.cmd = ESD_USB_CMD_IDADD; + msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32); /* # of 32bit words */ msg->filter.net = priv->index; - msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */ - for (i = 0; i < ESD_MAX_ID_SEGMENT; i++) - msg->filter.mask[i] = cpu_to_le32(0xffffffff); + msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */ + for (i = 0; i < ESD_USB_MAX_ID_SEGMENT; i++) + msg->filter.mask[i] = cpu_to_le32(GENMASK(31, 0)); /* enable 29bit extended IDs */ - msg->filter.mask[ESD_MAX_ID_SEGMENT] = cpu_to_le32(0x00000001); + msg->filter.mask[ESD_USB_MAX_ID_SEGMENT] = cpu_to_le32(BIT(0)); err = esd_usb_send_msg(dev, msg); if (err) @@ -689,8 +682,8 @@ static void unlink_all_urbs(struct esd_usb *dev) usb_kill_anchored_urbs(&dev->rx_submitted); - for (i = 0; i < MAX_RX_URBS; ++i) - usb_free_coherent(dev->udev, RX_BUFFER_SIZE, + for (i = 0; i < ESD_USB_MAX_RX_URBS; ++i) + usb_free_coherent(dev->udev, ESD_USB_RX_BUFFER_SIZE, dev->rxbuf[i], dev->rxbuf_dma[i]); for (i = 0; i < dev->net_count; i++) { @@ -699,8 +692,8 @@ static void unlink_all_urbs(struct esd_usb *dev) usb_kill_anchored_urbs(&priv->tx_submitted); atomic_set(&priv->active_tx_jobs, 0); - for (j = 0; j < MAX_TX_URBS; j++) - priv->tx_contexts[j].echo_index = MAX_TX_URBS; + for (j = 0; j < ESD_USB_MAX_TX_URBS; j++) + priv->tx_contexts[j].echo_index = ESD_USB_MAX_TX_URBS; } } } @@ -765,25 +758,27 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, msg = (union esd_usb_msg *)buf; - msg->hdr.len = 3; /* minimal length */ - msg->hdr.cmd = CMD_CAN_TX; + /* minimal length as # of 32bit words */ + msg->hdr.len = offsetof(struct esd_usb_tx_msg, data) / sizeof(u32); + msg->hdr.cmd = ESD_USB_CMD_CAN_TX; msg->tx.net = priv->index; msg->tx.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode); msg->tx.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK); if (cf->can_id & CAN_RTR_FLAG) - msg->tx.dlc |= ESD_RTR; + msg->tx.dlc |= ESD_USB_RTR; if (cf->can_id & CAN_EFF_FLAG) - msg->tx.id |= cpu_to_le32(ESD_EXTID); + msg->tx.id |= cpu_to_le32(ESD_USB_EXTID); for (i = 0; i < cf->len; i++) msg->tx.data[i] = cf->data[i]; - msg->hdr.len += (cf->len + 3) >> 2; + /* round up, then divide by 4 to add the payload length as # of 32bit words */ + msg->hdr.len += DIV_ROUND_UP(cf->len, sizeof(u32)); - for (i = 0; i < MAX_TX_URBS; i++) { - if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) { + for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) { + if (priv->tx_contexts[i].echo_index == ESD_USB_MAX_TX_URBS) { context = &priv->tx_contexts[i]; break; } @@ -800,10 +795,10 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, context->echo_index = i; /* hnd must not be 0 - MSB is stripped in txdone handling */ - msg->tx.hnd = 0x80000000 | i; /* returned in TX done message */ + msg->tx.hnd = BIT(31) | i; /* returned in TX done message */ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf, - msg->hdr.len << 2, + msg->hdr.len * sizeof(u32), /* convert to # of bytes */ esd_usb_write_bulk_callback, context); urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -815,7 +810,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb, atomic_inc(&priv->active_tx_jobs); /* Slow down tx path */ - if (atomic_read(&priv->active_tx_jobs) >= MAX_TX_URBS) + if (atomic_read(&priv->active_tx_jobs) >= ESD_USB_MAX_TX_URBS) netif_stop_queue(netdev); err = usb_submit_urb(urb, GFP_ATOMIC); @@ -865,18 +860,18 @@ static int esd_usb_close(struct net_device *netdev) return -ENOMEM; /* Disable all IDs (see esd_usb_start()) */ - msg->hdr.cmd = CMD_IDADD; - msg->hdr.len = 2 + ESD_MAX_ID_SEGMENT; + msg->hdr.cmd = ESD_USB_CMD_IDADD; + msg->hdr.len = sizeof(struct esd_usb_id_filter_msg) / sizeof(u32);/* # of 32bit words */ msg->filter.net = priv->index; - msg->filter.option = ESD_ID_ENABLE; /* start with segment 0 */ - for (i = 0; i <= ESD_MAX_ID_SEGMENT; i++) + msg->filter.option = ESD_USB_ID_ENABLE; /* start with segment 0 */ + for (i = 0; i <= ESD_USB_MAX_ID_SEGMENT; i++) msg->filter.mask[i] = 0; if (esd_usb_send_msg(priv->usb, msg) < 0) netdev_err(netdev, "sending idadd message failed\n"); /* set CAN controller to reset mode */ - msg->hdr.len = 2; - msg->hdr.cmd = CMD_SETBAUD; + msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */ + msg->hdr.cmd = ESD_USB_CMD_SETBAUD; msg->setbaud.net = priv->index; msg->setbaud.rsvd = 0; msg->setbaud.baud = cpu_to_le32(ESD_USB_NO_BAUDRATE); @@ -905,20 +900,21 @@ static const struct ethtool_ops esd_usb_ethtool_ops = { .get_ts_info = ethtool_op_get_ts_info, }; -static const struct can_bittiming_const esd_usb2_bittiming_const = { - .name = "esd_usb2", - .tseg1_min = ESD_USB2_TSEG1_MIN, - .tseg1_max = ESD_USB2_TSEG1_MAX, - .tseg2_min = ESD_USB2_TSEG2_MIN, - .tseg2_max = ESD_USB2_TSEG2_MAX, - .sjw_max = ESD_USB2_SJW_MAX, - .brp_min = ESD_USB2_BRP_MIN, - .brp_max = ESD_USB2_BRP_MAX, - .brp_inc = ESD_USB2_BRP_INC, +static const struct can_bittiming_const esd_usb_2_bittiming_const = { + .name = "esd_usb_2", + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 1024, + .brp_inc = 1, }; -static int esd_usb2_set_bittiming(struct net_device *netdev) +static int esd_usb_2_set_bittiming(struct net_device *netdev) { + const struct can_bittiming_const *btc = &esd_usb_2_bittiming_const; struct esd_usb_net_priv *priv = netdev_priv(netdev); struct can_bittiming *bt = &priv->can.bittiming; union esd_usb_msg *msg; @@ -930,35 +926,35 @@ static int esd_usb2_set_bittiming(struct net_device *netdev) if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) canbtr |= ESD_USB_LOM; - canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1); + canbtr |= (bt->brp - 1) & (btc->brp_max - 1); if (le16_to_cpu(priv->usb->udev->descriptor.idProduct) == - USB_CANUSBM_PRODUCT_ID) - sjw_shift = ESD_USBM_SJW_SHIFT; + ESD_USB_CANUSBM_PRODUCT_ID) + sjw_shift = ESD_USB_M_SJW_SHIFT; else - sjw_shift = ESD_USB2_SJW_SHIFT; + sjw_shift = ESD_USB_2_SJW_SHIFT; - canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1)) + canbtr |= ((bt->sjw - 1) & (btc->sjw_max - 1)) << sjw_shift; canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1) - & (ESD_USB2_TSEG1_MAX - 1)) - << ESD_USB2_TSEG1_SHIFT; - canbtr |= ((bt->phase_seg2 - 1) & (ESD_USB2_TSEG2_MAX - 1)) - << ESD_USB2_TSEG2_SHIFT; + & (btc->tseg1_max - 1)) + << ESD_USB_2_TSEG1_SHIFT; + canbtr |= ((bt->phase_seg2 - 1) & (btc->tseg2_max - 1)) + << ESD_USB_2_TSEG2_SHIFT; if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) - canbtr |= ESD_USB2_3_SAMPLES; + canbtr |= ESD_USB_TRIPLE_SAMPLES; msg = kmalloc(sizeof(*msg), GFP_KERNEL); if (!msg) return -ENOMEM; - msg->hdr.len = 2; - msg->hdr.cmd = CMD_SETBAUD; + msg->hdr.len = sizeof(struct esd_usb_set_baudrate_msg) / sizeof(u32); /* # of 32bit words */ + msg->hdr.cmd = ESD_USB_CMD_SETBAUD; msg->setbaud.net = priv->index; msg->setbaud.rsvd = 0; msg->setbaud.baud = cpu_to_le32(canbtr); - netdev_info(netdev, "setting BTR=%#x\n", canbtr); + netdev_dbg(netdev, "setting BTR=%#x\n", canbtr); err = esd_usb_send_msg(priv->usb, msg); @@ -999,7 +995,7 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) int err = 0; int i; - netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS); + netdev = alloc_candev(sizeof(*priv), ESD_USB_MAX_TX_URBS); if (!netdev) { dev_err(&intf->dev, "couldn't alloc candev\n"); err = -ENOMEM; @@ -1011,8 +1007,8 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) init_usb_anchor(&priv->tx_submitted); atomic_set(&priv->active_tx_jobs, 0); - for (i = 0; i < MAX_TX_URBS; i++) - priv->tx_contexts[i].echo_index = MAX_TX_URBS; + for (i = 0; i < ESD_USB_MAX_TX_URBS; i++) + priv->tx_contexts[i].echo_index = ESD_USB_MAX_TX_URBS; priv->usb = dev; priv->netdev = netdev; @@ -1024,15 +1020,15 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) CAN_CTRLMODE_BERR_REPORTING; if (le16_to_cpu(dev->udev->descriptor.idProduct) == - USB_CANUSBM_PRODUCT_ID) - priv->can.clock.freq = ESD_USBM_CAN_CLOCK; + ESD_USB_CANUSBM_PRODUCT_ID) + priv->can.clock.freq = ESD_USB_M_CAN_CLOCK; else { - priv->can.clock.freq = ESD_USB2_CAN_CLOCK; + priv->can.clock.freq = ESD_USB_2_CAN_CLOCK; priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; } - priv->can.bittiming_const = &esd_usb2_bittiming_const; - priv->can.do_set_bittiming = esd_usb2_set_bittiming; + priv->can.bittiming_const = &esd_usb_2_bittiming_const; + priv->can.do_set_bittiming = esd_usb_2_set_bittiming; priv->can.do_set_mode = esd_usb_set_mode; priv->can.do_get_berr_counter = esd_usb_get_berr_counter; @@ -1090,8 +1086,8 @@ static int esd_usb_probe(struct usb_interface *intf, } /* query number of CAN interfaces (nets) */ - msg->hdr.cmd = CMD_VERSION; - msg->hdr.len = 2; + msg->hdr.cmd = ESD_USB_CMD_VERSION; + msg->hdr.len = sizeof(struct esd_usb_version_msg) / sizeof(u32); /* # of 32bit words */ msg->version.rsvd = 0; msg->version.flags = 0; msg->version.drv_version = 0; diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c new file mode 100644 index 000000000000..ec8cef7fd2d5 --- /dev/null +++ b/drivers/net/can/usb/f81604.c @@ -0,0 +1,1201 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Fintek F81604 USB-to-2CAN controller driver. + * + * Copyright (C) 2023 Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw> + */ +#include <linux/bitfield.h> +#include <linux/netdevice.h> +#include <linux/units.h> +#include <linux/usb.h> + +#include <linux/can.h> +#include <linux/can/dev.h> +#include <linux/can/error.h> +#include <linux/can/platform/sja1000.h> + +#include <asm-generic/unaligned.h> + +/* vendor and product id */ +#define F81604_VENDOR_ID 0x2c42 +#define F81604_PRODUCT_ID 0x1709 +#define F81604_CAN_CLOCK (12 * MEGA) +#define F81604_MAX_DEV 2 +#define F81604_SET_DEVICE_RETRY 10 + +#define F81604_USB_TIMEOUT 2000 +#define F81604_SET_GET_REGISTER 0xA0 +#define F81604_PORT_OFFSET 0x1000 +#define F81604_MAX_RX_URBS 4 + +#define F81604_CMD_DATA 0x00 + +#define F81604_DLC_LEN_MASK GENMASK(3, 0) +#define F81604_DLC_EFF_BIT BIT(7) +#define F81604_DLC_RTR_BIT BIT(6) + +#define F81604_SFF_SHIFT 5 +#define F81604_EFF_SHIFT 3 + +#define F81604_BRP_MASK GENMASK(5, 0) +#define F81604_SJW_MASK GENMASK(7, 6) + +#define F81604_SEG1_MASK GENMASK(3, 0) +#define F81604_SEG2_MASK GENMASK(6, 4) + +#define F81604_CLEAR_ALC 0 +#define F81604_CLEAR_ECC 1 +#define F81604_CLEAR_OVERRUN 2 + +/* device setting */ +#define F81604_CTRL_MODE_REG 0x80 +#define F81604_TX_ONESHOT (0x03 << 3) +#define F81604_TX_NORMAL (0x01 << 3) +#define F81604_RX_AUTO_RELEASE_BUF BIT(1) +#define F81604_INT_WHEN_CHANGE BIT(0) + +#define F81604_TERMINATOR_REG 0x105 +#define F81604_CAN0_TERM BIT(2) +#define F81604_CAN1_TERM BIT(3) + +#define F81604_TERMINATION_DISABLED CAN_TERMINATION_DISABLED +#define F81604_TERMINATION_ENABLED 120 + +/* SJA1000 registers - manual section 6.4 (Pelican Mode) */ +#define F81604_SJA1000_MOD 0x00 +#define F81604_SJA1000_CMR 0x01 +#define F81604_SJA1000_IR 0x03 +#define F81604_SJA1000_IER 0x04 +#define F81604_SJA1000_ALC 0x0B +#define F81604_SJA1000_ECC 0x0C +#define F81604_SJA1000_RXERR 0x0E +#define F81604_SJA1000_TXERR 0x0F +#define F81604_SJA1000_ACCC0 0x10 +#define F81604_SJA1000_ACCM0 0x14 +#define F81604_MAX_FILTER_CNT 4 + +/* Common registers - manual section 6.5 */ +#define F81604_SJA1000_BTR0 0x06 +#define F81604_SJA1000_BTR1 0x07 +#define F81604_SJA1000_BTR1_SAMPLE_TRIPLE BIT(7) +#define F81604_SJA1000_OCR 0x08 +#define F81604_SJA1000_CDR 0x1F + +/* mode register */ +#define F81604_SJA1000_MOD_RM 0x01 +#define F81604_SJA1000_MOD_LOM 0x02 +#define F81604_SJA1000_MOD_STM 0x04 + +/* commands */ +#define F81604_SJA1000_CMD_CDO 0x08 + +/* interrupt sources */ +#define F81604_SJA1000_IRQ_BEI 0x80 +#define F81604_SJA1000_IRQ_ALI 0x40 +#define F81604_SJA1000_IRQ_EPI 0x20 +#define F81604_SJA1000_IRQ_DOI 0x08 +#define F81604_SJA1000_IRQ_EI 0x04 +#define F81604_SJA1000_IRQ_TI 0x02 +#define F81604_SJA1000_IRQ_RI 0x01 +#define F81604_SJA1000_IRQ_ALL 0xFF +#define F81604_SJA1000_IRQ_OFF 0x00 + +/* status register content */ +#define F81604_SJA1000_SR_BS 0x80 +#define F81604_SJA1000_SR_ES 0x40 +#define F81604_SJA1000_SR_TCS 0x08 + +/* ECC register */ +#define F81604_SJA1000_ECC_SEG 0x1F +#define F81604_SJA1000_ECC_DIR 0x20 +#define F81604_SJA1000_ECC_BIT 0x00 +#define F81604_SJA1000_ECC_FORM 0x40 +#define F81604_SJA1000_ECC_STUFF 0x80 +#define F81604_SJA1000_ECC_MASK 0xc0 + +/* ALC register */ +#define F81604_SJA1000_ALC_MASK 0x1f + +/* table of devices that work with this driver */ +static const struct usb_device_id f81604_table[] = { + { USB_DEVICE(F81604_VENDOR_ID, F81604_PRODUCT_ID) }, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, f81604_table); + +static const struct ethtool_ops f81604_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + +static const u16 f81604_termination[] = { F81604_TERMINATION_DISABLED, + F81604_TERMINATION_ENABLED }; + +struct f81604_priv { + struct net_device *netdev[F81604_MAX_DEV]; +}; + +struct f81604_port_priv { + struct can_priv can; + struct net_device *netdev; + struct sk_buff *echo_skb; + + unsigned long clear_flags; + struct work_struct clear_reg_work; + + struct usb_device *dev; + struct usb_interface *intf; + + struct usb_anchor urbs_anchor; +}; + +/* Interrupt endpoint data format: + * Byte 0: Status register. + * Byte 1: Interrupt register. + * Byte 2: Interrupt enable register. + * Byte 3: Arbitration lost capture(ALC) register. + * Byte 4: Error code capture(ECC) register. + * Byte 5: Error warning limit register. + * Byte 6: RX error counter register. + * Byte 7: TX error counter register. + * Byte 8: Reserved. + */ +struct f81604_int_data { + u8 sr; + u8 isrc; + u8 ier; + u8 alc; + u8 ecc; + u8 ewlr; + u8 rxerr; + u8 txerr; + u8 val; +} __packed __aligned(4); + +struct f81604_sff { + __be16 id; + u8 data[CAN_MAX_DLEN]; +} __packed __aligned(2); + +struct f81604_eff { + __be32 id; + u8 data[CAN_MAX_DLEN]; +} __packed __aligned(2); + +struct f81604_can_frame { + u8 cmd; + + /* According for F81604 DLC define: + * bit 3~0: data length (0~8) + * bit6: is RTR flag. + * bit7: is EFF frame. + */ + u8 dlc; + + union { + struct f81604_sff sff; + struct f81604_eff eff; + }; +} __packed __aligned(2); + +static const u8 bulk_in_addr[F81604_MAX_DEV] = { 2, 4 }; +static const u8 bulk_out_addr[F81604_MAX_DEV] = { 1, 3 }; +static const u8 int_in_addr[F81604_MAX_DEV] = { 1, 3 }; + +static int f81604_write(struct usb_device *dev, u16 reg, u8 data) +{ + int ret; + + ret = usb_control_msg_send(dev, 0, F81604_SET_GET_REGISTER, + USB_TYPE_VENDOR | USB_DIR_OUT, 0, reg, + &data, sizeof(data), F81604_USB_TIMEOUT, + GFP_KERNEL); + if (ret) + dev_err(&dev->dev, "%s: reg: %x data: %x failed: %pe\n", + __func__, reg, data, ERR_PTR(ret)); + + return ret; +} + +static int f81604_read(struct usb_device *dev, u16 reg, u8 *data) +{ + int ret; + + ret = usb_control_msg_recv(dev, 0, F81604_SET_GET_REGISTER, + USB_TYPE_VENDOR | USB_DIR_IN, 0, reg, data, + sizeof(*data), F81604_USB_TIMEOUT, + GFP_KERNEL); + + if (ret < 0) + dev_err(&dev->dev, "%s: reg: %x failed: %pe\n", __func__, reg, + ERR_PTR(ret)); + + return ret; +} + +static int f81604_update_bits(struct usb_device *dev, u16 reg, u8 mask, + u8 data) +{ + int ret; + u8 tmp; + + ret = f81604_read(dev, reg, &tmp); + if (ret) + return ret; + + tmp &= ~mask; + tmp |= (mask & data); + + return f81604_write(dev, reg, tmp); +} + +static int f81604_sja1000_write(struct f81604_port_priv *priv, u16 reg, + u8 data) +{ + int port = priv->netdev->dev_port; + int real_reg; + + real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET; + return f81604_write(priv->dev, real_reg, data); +} + +static int f81604_sja1000_read(struct f81604_port_priv *priv, u16 reg, + u8 *data) +{ + int port = priv->netdev->dev_port; + int real_reg; + + real_reg = reg + F81604_PORT_OFFSET * port + F81604_PORT_OFFSET; + return f81604_read(priv->dev, real_reg, data); +} + +static int f81604_set_reset_mode(struct f81604_port_priv *priv) +{ + int ret, i; + u8 tmp; + + /* disable interrupts */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_IER, + F81604_SJA1000_IRQ_OFF); + if (ret) + return ret; + + for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) { + ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp); + if (ret) + return ret; + + /* check reset bit */ + if (tmp & F81604_SJA1000_MOD_RM) { + priv->can.state = CAN_STATE_STOPPED; + return 0; + } + + /* reset chip */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, + F81604_SJA1000_MOD_RM); + if (ret) + return ret; + } + + return -EPERM; +} + +static int f81604_set_normal_mode(struct f81604_port_priv *priv) +{ + u8 tmp, ier = 0; + u8 mod_reg = 0; + int ret, i; + + for (i = 0; i < F81604_SET_DEVICE_RETRY; i++) { + ret = f81604_sja1000_read(priv, F81604_SJA1000_MOD, &tmp); + if (ret) + return ret; + + /* check reset bit */ + if ((tmp & F81604_SJA1000_MOD_RM) == 0) { + priv->can.state = CAN_STATE_ERROR_ACTIVE; + /* enable interrupts, RI handled by bulk-in */ + ier = F81604_SJA1000_IRQ_ALL & ~F81604_SJA1000_IRQ_RI; + if (!(priv->can.ctrlmode & + CAN_CTRLMODE_BERR_REPORTING)) + ier &= ~F81604_SJA1000_IRQ_BEI; + + return f81604_sja1000_write(priv, F81604_SJA1000_IER, + ier); + } + + /* set chip to normal mode */ + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) + mod_reg |= F81604_SJA1000_MOD_LOM; + if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) + mod_reg |= F81604_SJA1000_MOD_STM; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_MOD, mod_reg); + if (ret) + return ret; + } + + return -EPERM; +} + +static int f81604_chipset_init(struct f81604_port_priv *priv) +{ + int i, ret; + + /* set clock divider and output control register */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_CDR, + CDR_CBP | CDR_PELICAN); + if (ret) + return ret; + + /* set acceptance filter (accept all) */ + for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) { + ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCC0 + i, 0); + if (ret) + return ret; + } + + for (i = 0; i < F81604_MAX_FILTER_CNT; ++i) { + ret = f81604_sja1000_write(priv, F81604_SJA1000_ACCM0 + i, + 0xFF); + if (ret) + return ret; + } + + return f81604_sja1000_write(priv, F81604_SJA1000_OCR, + OCR_TX0_PUSHPULL | OCR_TX1_PUSHPULL | + OCR_MODE_NORMAL); +} + +static void f81604_process_rx_packet(struct net_device *netdev, + struct f81604_can_frame *frame) +{ + struct net_device_stats *stats = &netdev->stats; + struct can_frame *cf; + struct sk_buff *skb; + + if (frame->cmd != F81604_CMD_DATA) + return; + + skb = alloc_can_skb(netdev, &cf); + if (!skb) { + stats->rx_dropped++; + return; + } + + cf->len = can_cc_dlc2len(frame->dlc & F81604_DLC_LEN_MASK); + + if (frame->dlc & F81604_DLC_EFF_BIT) { + cf->can_id = get_unaligned_be32(&frame->eff.id) >> + F81604_EFF_SHIFT; + cf->can_id |= CAN_EFF_FLAG; + + if (!(frame->dlc & F81604_DLC_RTR_BIT)) + memcpy(cf->data, frame->eff.data, cf->len); + } else { + cf->can_id = get_unaligned_be16(&frame->sff.id) >> + F81604_SFF_SHIFT; + + if (!(frame->dlc & F81604_DLC_RTR_BIT)) + memcpy(cf->data, frame->sff.data, cf->len); + } + + if (frame->dlc & F81604_DLC_RTR_BIT) + cf->can_id |= CAN_RTR_FLAG; + else + stats->rx_bytes += cf->len; + + stats->rx_packets++; + netif_rx(skb); +} + +static void f81604_read_bulk_callback(struct urb *urb) +{ + struct f81604_can_frame *frame = urb->transfer_buffer; + struct net_device *netdev = urb->context; + int ret; + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: URB aborted %pe\n", __func__, + ERR_PTR(urb->status)); + + switch (urb->status) { + case 0: /* success */ + break; + + case -ENOENT: + case -EPIPE: + case -EPROTO: + case -ESHUTDOWN: + return; + + default: + goto resubmit_urb; + } + + if (urb->actual_length != sizeof(*frame)) { + netdev_warn(netdev, "URB length %u not equal to %zu\n", + urb->actual_length, sizeof(*frame)); + goto resubmit_urb; + } + + f81604_process_rx_packet(netdev, frame); + +resubmit_urb: + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret == -ENODEV) + netif_device_detach(netdev); + else if (ret) + netdev_err(netdev, + "%s: failed to resubmit read bulk urb: %pe\n", + __func__, ERR_PTR(ret)); +} + +static void f81604_handle_tx(struct f81604_port_priv *priv, + struct f81604_int_data *data) +{ + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + + /* transmission buffer released */ + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT && + !(data->sr & F81604_SJA1000_SR_TCS)) { + stats->tx_errors++; + can_free_echo_skb(netdev, 0, NULL); + } else { + /* transmission complete */ + stats->tx_bytes += can_get_echo_skb(netdev, 0, NULL); + stats->tx_packets++; + } + + netif_wake_queue(netdev); +} + +static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv, + struct f81604_int_data *data) +{ + enum can_state can_state = priv->can.state; + struct net_device *netdev = priv->netdev; + struct net_device_stats *stats = &netdev->stats; + struct can_frame *cf; + struct sk_buff *skb; + + /* Note: ALC/ECC will not auto clear by read here, must be cleared by + * read register (via clear_reg_work). + */ + + skb = alloc_can_err_skb(netdev, &cf); + if (skb) { + cf->can_id |= CAN_ERR_CNT; + cf->data[6] = data->txerr; + cf->data[7] = data->rxerr; + } + + if (data->isrc & F81604_SJA1000_IRQ_DOI) { + /* data overrun interrupt */ + netdev_dbg(netdev, "data overrun interrupt\n"); + + if (skb) { + cf->can_id |= CAN_ERR_CRTL; + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; + } + + stats->rx_over_errors++; + stats->rx_errors++; + + set_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags); + } + + if (data->isrc & F81604_SJA1000_IRQ_EI) { + /* error warning interrupt */ + netdev_dbg(netdev, "error warning interrupt\n"); + + if (data->sr & F81604_SJA1000_SR_BS) + can_state = CAN_STATE_BUS_OFF; + else if (data->sr & F81604_SJA1000_SR_ES) + can_state = CAN_STATE_ERROR_WARNING; + else + can_state = CAN_STATE_ERROR_ACTIVE; + } + + if (data->isrc & F81604_SJA1000_IRQ_BEI) { + /* bus error interrupt */ + netdev_dbg(netdev, "bus error interrupt\n"); + + priv->can.can_stats.bus_error++; + stats->rx_errors++; + + if (skb) { + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + /* set error type */ + switch (data->ecc & F81604_SJA1000_ECC_MASK) { + case F81604_SJA1000_ECC_BIT: + cf->data[2] |= CAN_ERR_PROT_BIT; + break; + case F81604_SJA1000_ECC_FORM: + cf->data[2] |= CAN_ERR_PROT_FORM; + break; + case F81604_SJA1000_ECC_STUFF: + cf->data[2] |= CAN_ERR_PROT_STUFF; + break; + default: + break; + } + + /* set error location */ + cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG; + + /* Error occurred during transmission? */ + if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) + cf->data[2] |= CAN_ERR_PROT_TX; + } + + set_bit(F81604_CLEAR_ECC, &priv->clear_flags); + } + + if (data->isrc & F81604_SJA1000_IRQ_EPI) { + if (can_state == CAN_STATE_ERROR_PASSIVE) + can_state = CAN_STATE_ERROR_WARNING; + else + can_state = CAN_STATE_ERROR_PASSIVE; + + /* error passive interrupt */ + netdev_dbg(netdev, "error passive interrupt: %d\n", can_state); + } + + if (data->isrc & F81604_SJA1000_IRQ_ALI) { + /* arbitration lost interrupt */ + netdev_dbg(netdev, "arbitration lost interrupt\n"); + + priv->can.can_stats.arbitration_lost++; + + if (skb) { + cf->can_id |= CAN_ERR_LOSTARB; + cf->data[0] = data->alc & F81604_SJA1000_ALC_MASK; + } + + set_bit(F81604_CLEAR_ALC, &priv->clear_flags); + } + + if (can_state != priv->can.state) { + enum can_state tx_state, rx_state; + + tx_state = data->txerr >= data->rxerr ? can_state : 0; + rx_state = data->txerr <= data->rxerr ? can_state : 0; + + can_change_state(netdev, cf, tx_state, rx_state); + + if (can_state == CAN_STATE_BUS_OFF) + can_bus_off(netdev); + } + + if (priv->clear_flags) + schedule_work(&priv->clear_reg_work); + + if (skb) + netif_rx(skb); +} + +static void f81604_read_int_callback(struct urb *urb) +{ + struct f81604_int_data *data = urb->transfer_buffer; + struct net_device *netdev = urb->context; + struct f81604_port_priv *priv; + int ret; + + priv = netdev_priv(netdev); + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: Int URB aborted: %pe\n", __func__, + ERR_PTR(urb->status)); + + switch (urb->status) { + case 0: /* success */ + break; + + case -ENOENT: + case -EPIPE: + case -EPROTO: + case -ESHUTDOWN: + return; + + default: + goto resubmit_urb; + } + + /* handle Errors */ + if (data->isrc & (F81604_SJA1000_IRQ_DOI | F81604_SJA1000_IRQ_EI | + F81604_SJA1000_IRQ_BEI | F81604_SJA1000_IRQ_EPI | + F81604_SJA1000_IRQ_ALI)) + f81604_handle_can_bus_errors(priv, data); + + /* handle TX */ + if (priv->can.state != CAN_STATE_BUS_OFF && + (data->isrc & F81604_SJA1000_IRQ_TI)) + f81604_handle_tx(priv, data); + +resubmit_urb: + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret == -ENODEV) + netif_device_detach(netdev); + else if (ret) + netdev_err(netdev, "%s: failed to resubmit int urb: %pe\n", + __func__, ERR_PTR(ret)); +} + +static void f81604_unregister_urbs(struct f81604_port_priv *priv) +{ + usb_kill_anchored_urbs(&priv->urbs_anchor); +} + +static int f81604_register_urbs(struct f81604_port_priv *priv) +{ + struct net_device *netdev = priv->netdev; + struct f81604_int_data *int_data; + int id = netdev->dev_port; + struct urb *int_urb; + int rx_urb_cnt; + int ret; + + for (rx_urb_cnt = 0; rx_urb_cnt < F81604_MAX_RX_URBS; ++rx_urb_cnt) { + struct f81604_can_frame *frame; + struct urb *rx_urb; + + rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!rx_urb) { + ret = -ENOMEM; + break; + } + + frame = kmalloc(sizeof(*frame), GFP_KERNEL); + if (!frame) { + usb_free_urb(rx_urb); + ret = -ENOMEM; + break; + } + + usb_fill_bulk_urb(rx_urb, priv->dev, + usb_rcvbulkpipe(priv->dev, bulk_in_addr[id]), + frame, sizeof(*frame), + f81604_read_bulk_callback, netdev); + + rx_urb->transfer_flags |= URB_FREE_BUFFER; + usb_anchor_urb(rx_urb, &priv->urbs_anchor); + + ret = usb_submit_urb(rx_urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(rx_urb); + usb_free_urb(rx_urb); + break; + } + + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(rx_urb); + } + + if (rx_urb_cnt == 0) { + netdev_warn(netdev, "%s: submit rx urb failed: %pe\n", + __func__, ERR_PTR(ret)); + + goto error; + } + + int_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!int_urb) { + ret = -ENOMEM; + goto error; + } + + int_data = kmalloc(sizeof(*int_data), GFP_KERNEL); + if (!int_data) { + usb_free_urb(int_urb); + ret = -ENOMEM; + goto error; + } + + usb_fill_int_urb(int_urb, priv->dev, + usb_rcvintpipe(priv->dev, int_in_addr[id]), int_data, + sizeof(*int_data), f81604_read_int_callback, netdev, + 1); + + int_urb->transfer_flags |= URB_FREE_BUFFER; + usb_anchor_urb(int_urb, &priv->urbs_anchor); + + ret = usb_submit_urb(int_urb, GFP_KERNEL); + if (ret) { + usb_unanchor_urb(int_urb); + usb_free_urb(int_urb); + + netdev_warn(netdev, "%s: submit int urb failed: %pe\n", + __func__, ERR_PTR(ret)); + goto error; + } + + /* Drop reference, USB core will take care of freeing it */ + usb_free_urb(int_urb); + + return 0; + +error: + f81604_unregister_urbs(priv); + return ret; +} + +static int f81604_start(struct net_device *netdev) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + int ret; + u8 mode; + u8 tmp; + + mode = F81604_RX_AUTO_RELEASE_BUF | F81604_INT_WHEN_CHANGE; + + /* Set TR/AT mode */ + if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + mode |= F81604_TX_ONESHOT; + else + mode |= F81604_TX_NORMAL; + + ret = f81604_sja1000_write(priv, F81604_CTRL_MODE_REG, mode); + if (ret) + return ret; + + /* set reset mode */ + ret = f81604_set_reset_mode(priv); + if (ret) + return ret; + + ret = f81604_chipset_init(priv); + if (ret) + return ret; + + /* Clear error counters and error code capture */ + ret = f81604_sja1000_write(priv, F81604_SJA1000_TXERR, 0); + if (ret) + return ret; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_RXERR, 0); + if (ret) + return ret; + + /* Read clear for ECC/ALC/IR register */ + ret = f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_IR, &tmp); + if (ret) + return ret; + + ret = f81604_register_urbs(priv); + if (ret) + return ret; + + ret = f81604_set_normal_mode(priv); + if (ret) { + f81604_unregister_urbs(priv); + return ret; + } + + return 0; +} + +static int f81604_set_bittiming(struct net_device *dev) +{ + struct f81604_port_priv *priv = netdev_priv(dev); + struct can_bittiming *bt = &priv->can.bittiming; + u8 btr0, btr1; + int ret; + + btr0 = FIELD_PREP(F81604_BRP_MASK, bt->brp - 1) | + FIELD_PREP(F81604_SJW_MASK, bt->sjw - 1); + + btr1 = FIELD_PREP(F81604_SEG1_MASK, + bt->prop_seg + bt->phase_seg1 - 1) | + FIELD_PREP(F81604_SEG2_MASK, bt->phase_seg2 - 1); + + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) + btr1 |= F81604_SJA1000_BTR1_SAMPLE_TRIPLE; + + ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR0, btr0); + if (ret) { + netdev_warn(dev, "%s: Set BTR0 failed: %pe\n", __func__, + ERR_PTR(ret)); + return ret; + } + + ret = f81604_sja1000_write(priv, F81604_SJA1000_BTR1, btr1); + if (ret) { + netdev_warn(dev, "%s: Set BTR1 failed: %pe\n", __func__, + ERR_PTR(ret)); + return ret; + } + + return 0; +} + +static int f81604_set_mode(struct net_device *netdev, enum can_mode mode) +{ + int ret; + + switch (mode) { + case CAN_MODE_START: + ret = f81604_start(netdev); + if (!ret && netif_queue_stopped(netdev)) + netif_wake_queue(netdev); + break; + + default: + ret = -EOPNOTSUPP; + } + + return ret; +} + +static void f81604_write_bulk_callback(struct urb *urb) +{ + struct net_device *netdev = urb->context; + + if (!netif_device_present(netdev)) + return; + + if (urb->status) + netdev_info(netdev, "%s: Tx URB error: %pe\n", __func__, + ERR_PTR(urb->status)); +} + +static void f81604_clear_reg_work(struct work_struct *work) +{ + struct f81604_port_priv *priv; + u8 tmp; + + priv = container_of(work, struct f81604_port_priv, clear_reg_work); + + /* dummy read for clear Arbitration lost capture(ALC) register. */ + if (test_and_clear_bit(F81604_CLEAR_ALC, &priv->clear_flags)) + f81604_sja1000_read(priv, F81604_SJA1000_ALC, &tmp); + + /* dummy read for clear Error code capture(ECC) register. */ + if (test_and_clear_bit(F81604_CLEAR_ECC, &priv->clear_flags)) + f81604_sja1000_read(priv, F81604_SJA1000_ECC, &tmp); + + /* dummy write for clear data overrun flag. */ + if (test_and_clear_bit(F81604_CLEAR_OVERRUN, &priv->clear_flags)) + f81604_sja1000_write(priv, F81604_SJA1000_CMR, + F81604_SJA1000_CMD_CDO); +} + +static netdev_tx_t f81604_start_xmit(struct sk_buff *skb, + struct net_device *netdev) +{ + struct can_frame *cf = (struct can_frame *)skb->data; + struct f81604_port_priv *priv = netdev_priv(netdev); + struct net_device_stats *stats = &netdev->stats; + struct f81604_can_frame *frame; + struct urb *write_urb; + int ret; + + if (can_dev_dropped_skb(netdev, skb)) + return NETDEV_TX_OK; + + netif_stop_queue(netdev); + + write_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!write_urb) + goto nomem_urb; + + frame = kzalloc(sizeof(*frame), GFP_ATOMIC); + if (!frame) + goto nomem_buf; + + usb_fill_bulk_urb(write_urb, priv->dev, + usb_sndbulkpipe(priv->dev, + bulk_out_addr[netdev->dev_port]), + frame, sizeof(*frame), f81604_write_bulk_callback, + priv->netdev); + + write_urb->transfer_flags |= URB_FREE_BUFFER; + + frame->cmd = F81604_CMD_DATA; + frame->dlc = cf->len; + + if (cf->can_id & CAN_RTR_FLAG) + frame->dlc |= F81604_DLC_RTR_BIT; + + if (cf->can_id & CAN_EFF_FLAG) { + u32 id = (cf->can_id & CAN_EFF_MASK) << F81604_EFF_SHIFT; + + put_unaligned_be32(id, &frame->eff.id); + + frame->dlc |= F81604_DLC_EFF_BIT; + + if (!(cf->can_id & CAN_RTR_FLAG)) + memcpy(&frame->eff.data, cf->data, cf->len); + } else { + u32 id = (cf->can_id & CAN_SFF_MASK) << F81604_SFF_SHIFT; + + put_unaligned_be16(id, &frame->sff.id); + + if (!(cf->can_id & CAN_RTR_FLAG)) + memcpy(&frame->sff.data, cf->data, cf->len); + } + + can_put_echo_skb(skb, netdev, 0, 0); + + ret = usb_submit_urb(write_urb, GFP_ATOMIC); + if (ret) { + netdev_err(netdev, "%s: failed to resubmit tx bulk urb: %pe\n", + __func__, ERR_PTR(ret)); + + can_free_echo_skb(netdev, 0, NULL); + stats->tx_dropped++; + stats->tx_errors++; + + if (ret == -ENODEV) + netif_device_detach(netdev); + else + netif_wake_queue(netdev); + } + + /* let usb core take care of this urb */ + usb_free_urb(write_urb); + + return NETDEV_TX_OK; + +nomem_buf: + usb_free_urb(write_urb); + +nomem_urb: + dev_kfree_skb(skb); + stats->tx_dropped++; + stats->tx_errors++; + netif_wake_queue(netdev); + + return NETDEV_TX_OK; +} + +static int f81604_get_berr_counter(const struct net_device *netdev, + struct can_berr_counter *bec) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + u8 txerr, rxerr; + int ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_TXERR, &txerr); + if (ret) + return ret; + + ret = f81604_sja1000_read(priv, F81604_SJA1000_RXERR, &rxerr); + if (ret) + return ret; + + bec->txerr = txerr; + bec->rxerr = rxerr; + + return 0; +} + +/* Open USB device */ +static int f81604_open(struct net_device *netdev) +{ + int ret; + + ret = open_candev(netdev); + if (ret) + return ret; + + ret = f81604_start(netdev); + if (ret) { + if (ret == -ENODEV) + netif_device_detach(netdev); + + close_candev(netdev); + return ret; + } + + netif_start_queue(netdev); + return 0; +} + +/* Close USB device */ +static int f81604_close(struct net_device *netdev) +{ + struct f81604_port_priv *priv = netdev_priv(netdev); + + f81604_set_reset_mode(priv); + + netif_stop_queue(netdev); + cancel_work_sync(&priv->clear_reg_work); + close_candev(netdev); + + f81604_unregister_urbs(priv); + + return 0; +} + +static const struct net_device_ops f81604_netdev_ops = { + .ndo_open = f81604_open, + .ndo_stop = f81604_close, + .ndo_start_xmit = f81604_start_xmit, + .ndo_change_mtu = can_change_mtu, +}; + +static const struct can_bittiming_const f81604_bittiming_const = { + .name = KBUILD_MODNAME, + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; + +/* Called by the usb core when driver is unloaded or device is removed */ +static void f81604_disconnect(struct usb_interface *intf) +{ + struct f81604_priv *priv = usb_get_intfdata(intf); + int i; + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + if (!priv->netdev[i]) + continue; + + unregister_netdev(priv->netdev[i]); + free_candev(priv->netdev[i]); + } +} + +static int __f81604_set_termination(struct usb_device *dev, int idx, u16 term) +{ + u8 mask, data = 0; + + if (idx == 0) + mask = F81604_CAN0_TERM; + else + mask = F81604_CAN1_TERM; + + if (term) + data = mask; + + return f81604_update_bits(dev, F81604_TERMINATOR_REG, mask, data); +} + +static int f81604_set_termination(struct net_device *netdev, u16 term) +{ + struct f81604_port_priv *port_priv = netdev_priv(netdev); + + ASSERT_RTNL(); + + return __f81604_set_termination(port_priv->dev, netdev->dev_port, + term); +} + +static int f81604_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct net_device *netdev; + struct f81604_priv *priv; + int i, ret; + + priv = devm_kzalloc(&intf->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + usb_set_intfdata(intf, priv); + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + ret = __f81604_set_termination(dev, i, 0); + if (ret) { + dev_err(&intf->dev, + "Setting termination of CH#%d failed: %pe\n", + i, ERR_PTR(ret)); + return ret; + } + } + + for (i = 0; i < ARRAY_SIZE(priv->netdev); ++i) { + struct f81604_port_priv *port_priv; + + netdev = alloc_candev(sizeof(*port_priv), 1); + if (!netdev) { + dev_err(&intf->dev, "Couldn't alloc candev: %d\n", i); + ret = -ENOMEM; + + goto failure_cleanup; + } + + port_priv = netdev_priv(netdev); + + INIT_WORK(&port_priv->clear_reg_work, f81604_clear_reg_work); + init_usb_anchor(&port_priv->urbs_anchor); + + port_priv->intf = intf; + port_priv->dev = dev; + port_priv->netdev = netdev; + port_priv->can.clock.freq = F81604_CAN_CLOCK; + + port_priv->can.termination_const = f81604_termination; + port_priv->can.termination_const_cnt = + ARRAY_SIZE(f81604_termination); + port_priv->can.bittiming_const = &f81604_bittiming_const; + port_priv->can.do_set_bittiming = f81604_set_bittiming; + port_priv->can.do_set_mode = f81604_set_mode; + port_priv->can.do_set_termination = f81604_set_termination; + port_priv->can.do_get_berr_counter = f81604_get_berr_counter; + port_priv->can.ctrlmode_supported = + CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | + CAN_CTRLMODE_ONE_SHOT | CAN_CTRLMODE_BERR_REPORTING | + CAN_CTRLMODE_PRESUME_ACK; + + netdev->ethtool_ops = &f81604_ethtool_ops; + netdev->netdev_ops = &f81604_netdev_ops; + netdev->flags |= IFF_ECHO; + netdev->dev_port = i; + + SET_NETDEV_DEV(netdev, &intf->dev); + + ret = register_candev(netdev); + if (ret) { + netdev_err(netdev, "register CAN device failed: %pe\n", + ERR_PTR(ret)); + free_candev(netdev); + + goto failure_cleanup; + } + + priv->netdev[i] = netdev; + } + + return 0; + +failure_cleanup: + f81604_disconnect(intf); + return ret; +} + +static struct usb_driver f81604_driver = { + .name = KBUILD_MODNAME, + .probe = f81604_probe, + .disconnect = f81604_disconnect, + .id_table = f81604_table, +}; + +module_usb_driver(f81604_driver); + +MODULE_AUTHOR("Ji-Ze Hong (Peter Hong) <peter_hong@fintek.com.tw>"); +MODULE_DESCRIPTION("Fintek F81604 USB to 2xCANBUS"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index 7135ec851341..71ef4db5c09f 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -816,7 +816,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel) init_completion(&priv->stop_comp); init_completion(&priv->flush_comp); init_completion(&priv->get_busparams_comp); - priv->can.ctrlmode_supported = 0; + priv->can.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC; priv->dev = dev; priv->netdev = netdev; diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index ef341c4254fc..c7ba768dfe17 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -1263,7 +1263,7 @@ static void kvaser_usb_hydra_rx_msg_std(const struct kvaser_usb *dev, if (flags & KVASER_USB_HYDRA_CF_FLAG_OVERRUN) kvaser_usb_can_rx_over_error(priv->netdev); - cf->len = can_cc_dlc2len(cmd->rx_can.dlc); + can_frame_set_cc_len((struct can_frame *)cf, cmd->rx_can.dlc, priv->can.ctrlmode); if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) { cf->can_id |= CAN_RTR_FLAG; @@ -1342,7 +1342,7 @@ static void kvaser_usb_hydra_rx_msg_ext(const struct kvaser_usb *dev, if (flags & KVASER_USB_HYDRA_CF_FLAG_ESI) cf->flags |= CANFD_ESI; } else { - cf->len = can_cc_dlc2len(dlc); + can_frame_set_cc_len((struct can_frame *)cf, dlc, priv->can.ctrlmode); } if (flags & KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME) { @@ -1442,7 +1442,7 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv, struct kvaser_usb *dev = priv->dev; struct kvaser_cmd_ext *cmd; struct canfd_frame *cf = (struct canfd_frame *)skb->data; - u8 dlc = can_fd_len2dlc(cf->len); + u8 dlc; u8 nbr_of_bytes = cf->len; u32 flags; u32 id; @@ -1467,6 +1467,11 @@ kvaser_usb_hydra_frame_to_cmd_ext(const struct kvaser_usb_net_priv *priv, cmd->len = cpu_to_le16(*cmd_len); + if (can_is_canfd_skb(skb)) + dlc = can_fd_len2dlc(cf->len); + else + dlc = can_get_cc_dlc((struct can_frame *)cf, priv->can.ctrlmode); + cmd->tx_can.databytes = nbr_of_bytes; cmd->tx_can.dlc = dlc; @@ -1542,7 +1547,7 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv, id = cf->can_id & CAN_SFF_MASK; } - cmd->tx_can.dlc = cf->len; + cmd->tx_can.dlc = can_get_cc_dlc(cf, priv->can.ctrlmode); flags = (cf->can_id & CAN_EFF_FLAG ? KVASER_USB_HYDRA_CF_FLAG_EXTENDED_ID : 0); diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c index 1c2f99ce4c6c..23bd7574b1c7 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c @@ -573,7 +573,7 @@ kvaser_usb_leaf_frame_to_cmd(const struct kvaser_usb_net_priv *priv, cmd->u.tx_can.data[1] = cf->can_id & 0x3f; } - cmd->u.tx_can.data[5] = cf->len; + cmd->u.tx_can.data[5] = can_get_cc_dlc(cf, priv->can.ctrlmode); memcpy(&cmd->u.tx_can.data[6], cf->data, cf->len); if (cf->can_id & CAN_RTR_FLAG) @@ -1349,7 +1349,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, else cf->can_id &= CAN_SFF_MASK; - cf->len = can_cc_dlc2len(cmd->u.leaf.log_message.dlc); + can_frame_set_cc_len(cf, cmd->u.leaf.log_message.dlc & 0xF, priv->can.ctrlmode); if (cmd->u.leaf.log_message.flags & MSG_FLAG_REMOTE_FRAME) cf->can_id |= CAN_RTR_FLAG; @@ -1367,7 +1367,7 @@ static void kvaser_usb_leaf_rx_can_msg(const struct kvaser_usb *dev, cf->can_id |= CAN_EFF_FLAG; } - cf->len = can_cc_dlc2len(rx_data[5]); + can_frame_set_cc_len(cf, rx_data[5] & 0xF, priv->can.ctrlmode); if (cmd->u.rx_can_header.flag & MSG_FLAG_REMOTE_FRAME) cf->can_id |= CAN_RTR_FLAG; diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 43c812ea1de0..4d3283db3a13 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -28,6 +28,7 @@ #include <linux/types.h> #include <linux/can/dev.h> #include <linux/can/error.h> +#include <linux/phy/phy.h> #include <linux/pm_runtime.h> #define DRIVER_NAME "xilinx_can" @@ -198,6 +199,7 @@ struct xcan_devtype_data { * @bus_clk: Pointer to struct clk * @can_clk: Pointer to struct clk * @devtype: Device type specific constants + * @transceiver: Optional pointer to associated CAN transceiver */ struct xcan_priv { struct can_priv can; @@ -215,6 +217,7 @@ struct xcan_priv { struct clk *bus_clk; struct clk *can_clk; struct xcan_devtype_data devtype; + struct phy *transceiver; }; /* CAN Bittiming constants as per Xilinx CAN specs */ @@ -1419,6 +1422,10 @@ static int xcan_open(struct net_device *ndev) struct xcan_priv *priv = netdev_priv(ndev); int ret; + ret = phy_power_on(priv->transceiver); + if (ret) + return ret; + ret = pm_runtime_get_sync(priv->dev); if (ret < 0) { netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n", @@ -1462,6 +1469,7 @@ err_irq: free_irq(ndev->irq, ndev); err: pm_runtime_put(priv->dev); + phy_power_off(priv->transceiver); return ret; } @@ -1483,6 +1491,7 @@ static int xcan_close(struct net_device *ndev) close_candev(ndev); pm_runtime_put(priv->dev); + phy_power_off(priv->transceiver); return 0; } @@ -1713,6 +1722,7 @@ static int xcan_probe(struct platform_device *pdev) { struct net_device *ndev; struct xcan_priv *priv; + struct phy *transceiver; const struct of_device_id *of_id; const struct xcan_devtype_data *devtype = &xcan_axi_data; void __iomem *addr; @@ -1843,6 +1853,14 @@ static int xcan_probe(struct platform_device *pdev) goto err_free; } + transceiver = devm_phy_optional_get(&pdev->dev, NULL); + if (IS_ERR(transceiver)) { + ret = PTR_ERR(transceiver); + dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); + goto err_free; + } + priv->transceiver = transceiver; + priv->write_reg = xcan_write_reg_le; priv->read_reg = xcan_read_reg_le; @@ -1869,6 +1887,7 @@ static int xcan_probe(struct platform_device *pdev) goto err_disableclks; } + of_can_transceiver(ndev); pm_runtime_put(&pdev->dev); if (priv->devtype.flags & XCAN_FLAG_CANFD_2) { @@ -1898,20 +1917,18 @@ err: * This function frees all the resources allocated to the device. * Return: 0 always */ -static int xcan_remove(struct platform_device *pdev) +static void xcan_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); unregister_candev(ndev); pm_runtime_disable(&pdev->dev); free_candev(ndev); - - return 0; } static struct platform_driver xcan_driver = { .probe = xcan_probe, - .remove = xcan_remove, + .remove_new = xcan_remove, .driver = { .name = DRIVER_NAME, .pm = &xcan_dev_pm_ops, |