restore lost packages from 0.2.3 + fix overwritten 0.2.4 files
- Restore 29 recipe symlinks (libdrm, qtbase, dbus, sddm, pipewire, etc.) - Restore 33 patches (KDE, libdrm, mesa, pipewire, sddm, wireplumber) - Restore 20+ local/scripts (audit, lint, test, build helpers) - Restore src/cook/scheduler.rs, status.rs, gnu-config/ - Restore scripts/patch-inclusion-gate.sh, run_mini1.sh, validate-collision-log.sh - Recover TLC source from HEAD (was overwritten by 0.2.3 checkout) - Recover 11 local/docs plans from HEAD (were overwritten) - Recover qt6-wayland-smoke symlink from HEAD - Fix MOTD: remove garbled ASCII art, use clean text - Update version: 0.2.0 -> 0.2.4 in os-release, motd, config - Reduce filesystem_size: 1536 -> 512 MiB - Add ABSOLUTE RULE to AGENTS.md: never delete/ignore packages - Reduce pcid scheme log verbosity: info -> debug
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2020 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
|
||||
* Copyright (c) 2021-2025 Vincent Mailhol <mailhol@kernel.org>
|
||||
*/
|
||||
|
||||
#ifndef _CAN_BITTIMING_H
|
||||
#define _CAN_BITTIMING_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/can/netlink.h>
|
||||
|
||||
#define CAN_SYNC_SEG 1
|
||||
|
||||
#define CAN_BITRATE_UNSET 0
|
||||
#define CAN_BITRATE_UNKNOWN (-1U)
|
||||
|
||||
#define CAN_CTRLMODE_FD_TDC_MASK \
|
||||
(CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL)
|
||||
#define CAN_CTRLMODE_XL_TDC_MASK \
|
||||
(CAN_CTRLMODE_XL_TDC_AUTO | CAN_CTRLMODE_XL_TDC_MANUAL)
|
||||
#define CAN_CTRLMODE_TDC_AUTO_MASK \
|
||||
(CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_XL_TDC_AUTO)
|
||||
#define CAN_CTRLMODE_TDC_MANUAL_MASK \
|
||||
(CAN_CTRLMODE_TDC_MANUAL | CAN_CTRLMODE_XL_TDC_MANUAL)
|
||||
|
||||
/*
|
||||
* struct can_tdc - CAN FD Transmission Delay Compensation parameters
|
||||
*
|
||||
* At high bit rates, the propagation delay from the TX pin to the RX
|
||||
* pin of the transceiver causes measurement errors: the sample point
|
||||
* on the RX pin might occur on the previous bit.
|
||||
*
|
||||
* To solve this issue, ISO 11898-1 introduces in section 11.3.3
|
||||
* "Transmitter delay compensation" a SSP (Secondary Sample Point)
|
||||
* equal to the distance from the start of the bit time on the TX pin
|
||||
* to the actual measurement on the RX pin.
|
||||
*
|
||||
* This structure contains the parameters to calculate that SSP.
|
||||
*
|
||||
* -+----------- one bit ----------+-- TX pin
|
||||
* |<--- Sample Point --->|
|
||||
*
|
||||
* --+----------- one bit ----------+-- RX pin
|
||||
* |<-------- TDCV -------->|
|
||||
* |<------- TDCO ------->|
|
||||
* |<----------- Secondary Sample Point ---------->|
|
||||
*
|
||||
* To increase precision, contrary to the other bittiming parameters
|
||||
* which are measured in time quanta, the TDC parameters are measured
|
||||
* in clock periods (also referred as "minimum time quantum" in ISO
|
||||
* 11898-1).
|
||||
*
|
||||
* @tdcv: Transmitter Delay Compensation Value. The time needed for
|
||||
* the signal to propagate, i.e. the distance, in clock periods,
|
||||
* from the start of the bit on the TX pin to when it is received
|
||||
* on the RX pin. @tdcv depends on the controller modes:
|
||||
*
|
||||
* CAN_CTRLMODE_TDC_AUTO is set: The transceiver dynamically
|
||||
* measures @tdcv for each transmitted CAN FD frame and the
|
||||
* value provided here should be ignored.
|
||||
*
|
||||
* CAN_CTRLMODE_TDC_MANUAL is set: use the fixed provided @tdcv
|
||||
* value.
|
||||
*
|
||||
* N.B. CAN_CTRLMODE_TDC_AUTO and CAN_CTRLMODE_TDC_MANUAL are
|
||||
* mutually exclusive. Only one can be set at a time. If both
|
||||
* CAN_TDC_CTRLMODE_AUTO and CAN_TDC_CTRLMODE_MANUAL are unset,
|
||||
* TDC is disabled and all the values of this structure should be
|
||||
* ignored.
|
||||
*
|
||||
* @tdco: Transmitter Delay Compensation Offset. Offset value, in
|
||||
* clock periods, defining the distance between the start of the
|
||||
* bit reception on the RX pin of the transceiver and the SSP
|
||||
* position such that SSP = @tdcv + @tdco.
|
||||
*
|
||||
* @tdcf: Transmitter Delay Compensation Filter window. Defines the
|
||||
* minimum value for the SSP position in clock periods. If the
|
||||
* SSP position is less than @tdcf, then no delay compensations
|
||||
* occur and the normal sampling point is used instead. The
|
||||
* feature is enabled if and only if @tdcv is set to zero
|
||||
* (automatic mode) and @tdcf is configured to a value greater
|
||||
* than @tdco.
|
||||
*/
|
||||
struct can_tdc {
|
||||
u32 tdcv;
|
||||
u32 tdco;
|
||||
u32 tdcf;
|
||||
};
|
||||
|
||||
/* The transceiver decoding margin corresponds to t_Decode in ISO 11898-2 */
|
||||
#define CAN_PWM_DECODE_NS 5
|
||||
/* Maximum PWM symbol duration. Corresponds to t_SymbolNom_MAX - t_Decode */
|
||||
#define CAN_PWM_NS_MAX (205 - CAN_PWM_DECODE_NS)
|
||||
|
||||
/*
|
||||
* struct can_tdc_const - CAN hardware-dependent constant for
|
||||
* Transmission Delay Compensation
|
||||
*
|
||||
* @tdcv_min: Transmitter Delay Compensation Value minimum value. If
|
||||
* the controller does not support manual mode for tdcv
|
||||
* (c.f. flag CAN_CTRLMODE_TDC_MANUAL) then this value is
|
||||
* ignored.
|
||||
* @tdcv_max: Transmitter Delay Compensation Value maximum value. If
|
||||
* the controller does not support manual mode for tdcv
|
||||
* (c.f. flag CAN_CTRLMODE_TDC_MANUAL) then this value is
|
||||
* ignored.
|
||||
*
|
||||
* @tdco_min: Transmitter Delay Compensation Offset minimum value.
|
||||
* @tdco_max: Transmitter Delay Compensation Offset maximum value.
|
||||
* Should not be zero. If the controller does not support TDC,
|
||||
* then the pointer to this structure should be NULL.
|
||||
*
|
||||
* @tdcf_min: Transmitter Delay Compensation Filter window minimum
|
||||
* value. If @tdcf_max is zero, this value is ignored.
|
||||
* @tdcf_max: Transmitter Delay Compensation Filter window maximum
|
||||
* value. Should be set to zero if the controller does not
|
||||
* support this feature.
|
||||
*/
|
||||
struct can_tdc_const {
|
||||
u32 tdcv_min;
|
||||
u32 tdcv_max;
|
||||
u32 tdco_min;
|
||||
u32 tdco_max;
|
||||
u32 tdcf_min;
|
||||
u32 tdcf_max;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct can_pwm - CAN Pulse-Width Modulation (PWM) parameters
|
||||
*
|
||||
* @pwms: pulse width modulation short phase
|
||||
* @pwml: pulse width modulation long phase
|
||||
* @pwmo: pulse width modulation offset
|
||||
*/
|
||||
struct can_pwm {
|
||||
u32 pwms;
|
||||
u32 pwml;
|
||||
u32 pwmo;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct can_pwm - CAN hardware-dependent constants for Pulse-Width
|
||||
* Modulation (PWM)
|
||||
*
|
||||
* @pwms_min: PWM short phase minimum value. Must be at least 1.
|
||||
* @pwms_max: PWM short phase maximum value
|
||||
* @pwml_min: PWM long phase minimum value. Must be at least 1.
|
||||
* @pwml_max: PWM long phase maximum value
|
||||
* @pwmo_min: PWM offset phase minimum value
|
||||
* @pwmo_max: PWM offset phase maximum value
|
||||
*/
|
||||
struct can_pwm_const {
|
||||
u32 pwms_min;
|
||||
u32 pwms_max;
|
||||
u32 pwml_min;
|
||||
u32 pwml_max;
|
||||
u32 pwmo_min;
|
||||
u32 pwmo_max;
|
||||
};
|
||||
|
||||
struct data_bittiming_params {
|
||||
const struct can_bittiming_const *data_bittiming_const;
|
||||
struct can_bittiming data_bittiming;
|
||||
const struct can_tdc_const *tdc_const;
|
||||
const struct can_pwm_const *pwm_const;
|
||||
union {
|
||||
struct can_tdc tdc;
|
||||
struct can_pwm pwm;
|
||||
};
|
||||
const u32 *data_bitrate_const;
|
||||
unsigned int data_bitrate_const_cnt;
|
||||
int (*do_set_data_bittiming)(struct net_device *dev);
|
||||
int (*do_get_auto_tdcv)(const struct net_device *dev, u32 *tdcv);
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CAN_CALC_BITTIMING
|
||||
int can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
|
||||
const struct can_bittiming_const *btc, struct netlink_ext_ack *extack);
|
||||
|
||||
void can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
|
||||
const struct can_bittiming *dbt,
|
||||
u32 tdc_mask, u32 *ctrlmode, u32 ctrlmode_supported);
|
||||
|
||||
int can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack);
|
||||
#else /* !CONFIG_CAN_CALC_BITTIMING */
|
||||
static inline int
|
||||
can_calc_bittiming(const struct net_device *dev, struct can_bittiming *bt,
|
||||
const struct can_bittiming_const *btc, struct netlink_ext_ack *extack)
|
||||
{
|
||||
NL_SET_ERR_MSG(extack, "bit-timing calculation not available\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
can_calc_tdco(struct can_tdc *tdc, const struct can_tdc_const *tdc_const,
|
||||
const struct can_bittiming *dbt,
|
||||
u32 tdc_mask, u32 *ctrlmode, u32 ctrlmode_supported)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int
|
||||
can_calc_pwm(struct net_device *dev, struct netlink_ext_ack *extack)
|
||||
{
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"bit-timing calculation not available: manually provide PWML and PWMS\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif /* CONFIG_CAN_CALC_BITTIMING */
|
||||
|
||||
void can_sjw_set_default(struct can_bittiming *bt);
|
||||
|
||||
int can_sjw_check(const struct net_device *dev, const struct can_bittiming *bt,
|
||||
const struct can_bittiming_const *btc, struct netlink_ext_ack *extack);
|
||||
|
||||
int can_get_bittiming(const struct net_device *dev, struct can_bittiming *bt,
|
||||
const struct can_bittiming_const *btc,
|
||||
const u32 *bitrate_const,
|
||||
const unsigned int bitrate_const_cnt,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
int can_validate_pwm_bittiming(const struct net_device *dev,
|
||||
const struct can_pwm *pwm,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
/*
|
||||
* can_get_relative_tdco() - TDCO relative to the sample point
|
||||
*
|
||||
* struct can_tdc::tdco represents the absolute offset from TDCV. Some
|
||||
* controllers use instead an offset relative to the Sample Point (SP)
|
||||
* such that:
|
||||
*
|
||||
* SSP = TDCV + absolute TDCO
|
||||
* = TDCV + SP + relative TDCO
|
||||
*
|
||||
* -+----------- one bit ----------+-- TX pin
|
||||
* |<--- Sample Point --->|
|
||||
*
|
||||
* --+----------- one bit ----------+-- RX pin
|
||||
* |<-------- TDCV -------->|
|
||||
* |<------------------------>| absolute TDCO
|
||||
* |<--- Sample Point --->|
|
||||
* | |<->| relative TDCO
|
||||
* |<------------- Secondary Sample Point ------------>|
|
||||
*/
|
||||
static inline s32 can_get_relative_tdco(const struct data_bittiming_params *dbt_params)
|
||||
{
|
||||
const struct can_bittiming *dbt = &dbt_params->data_bittiming;
|
||||
s32 sample_point_in_tc = (CAN_SYNC_SEG + dbt->prop_seg +
|
||||
dbt->phase_seg1) * dbt->brp;
|
||||
|
||||
return (s32)dbt_params->tdc.tdco - sample_point_in_tc;
|
||||
}
|
||||
|
||||
/*
|
||||
* can_bit_time() - Duration of one bit
|
||||
*
|
||||
* Please refer to ISO 11898-1:2015, section 11.3.1.1 "Bit time" for
|
||||
* additional information.
|
||||
*
|
||||
* Return: the number of time quanta in one bit.
|
||||
*/
|
||||
static inline unsigned int can_bit_time(const struct can_bittiming *bt)
|
||||
{
|
||||
return CAN_SYNC_SEG + bt->prop_seg + bt->phase_seg1 + bt->phase_seg2;
|
||||
}
|
||||
|
||||
/* Duration of one bit in minimum time quantum */
|
||||
static inline unsigned int can_bit_time_tqmin(const struct can_bittiming *bt)
|
||||
{
|
||||
return can_bit_time(bt) * bt->brp;
|
||||
}
|
||||
|
||||
/* Convert a duration from minimum a minimum time quantum to nano seconds */
|
||||
static inline u32 can_tqmin_to_ns(u32 tqmin, u32 clock_freq)
|
||||
{
|
||||
return DIV_U64_ROUND_CLOSEST(mul_u32_u32(tqmin, NSEC_PER_SEC),
|
||||
clock_freq);
|
||||
}
|
||||
|
||||
#endif /* !_CAN_BITTIMING_H */
|
||||
@@ -0,0 +1,104 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
||||
/* Copyright (c) 2002-2007 Volkswagen Group Electronic Research
|
||||
* Copyright (c) 2017 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Volkswagen nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* Alternatively, provided that this notice is retained in full, this
|
||||
* software may be distributed under the terms of the GNU General
|
||||
* Public License ("GPL") version 2, in which case the provisions of the
|
||||
* GPL apply INSTEAD OF those given above.
|
||||
*
|
||||
* The provided data structures and external interfaces from this code
|
||||
* are not restricted to be used by modules with a GPL compatible license.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CAN_ML_H
|
||||
#define CAN_ML_H
|
||||
|
||||
#include <linux/can.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
/* exposed CAN device capabilities for network layer */
|
||||
#define CAN_CAP_CC BIT(0) /* CAN CC aka Classical CAN */
|
||||
#define CAN_CAP_FD BIT(1) /* CAN FD */
|
||||
#define CAN_CAP_XL BIT(2) /* CAN XL */
|
||||
#define CAN_CAP_RO BIT(3) /* read-only mode (LISTEN/RESTRICTED) */
|
||||
|
||||
#define CAN_SFF_RCV_ARRAY_SZ (1 << CAN_SFF_ID_BITS)
|
||||
#define CAN_EFF_RCV_HASH_BITS 10
|
||||
#define CAN_EFF_RCV_ARRAY_SZ (1 << CAN_EFF_RCV_HASH_BITS)
|
||||
|
||||
enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_MAX };
|
||||
|
||||
struct can_dev_rcv_lists {
|
||||
struct hlist_head rx[RX_MAX];
|
||||
struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ];
|
||||
struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ];
|
||||
int entries;
|
||||
};
|
||||
|
||||
struct can_ml_priv {
|
||||
struct can_dev_rcv_lists dev_rcv_lists;
|
||||
#ifdef CAN_J1939
|
||||
struct j1939_priv *j1939_priv;
|
||||
#endif
|
||||
u32 can_cap;
|
||||
};
|
||||
|
||||
static inline struct can_ml_priv *can_get_ml_priv(struct net_device *dev)
|
||||
{
|
||||
return netdev_get_ml_priv(dev, ML_PRIV_CAN);
|
||||
}
|
||||
|
||||
static inline void can_set_ml_priv(struct net_device *dev,
|
||||
struct can_ml_priv *ml_priv)
|
||||
{
|
||||
netdev_set_ml_priv(dev, ml_priv, ML_PRIV_CAN);
|
||||
}
|
||||
|
||||
static inline bool can_cap_enabled(struct net_device *dev, u32 cap)
|
||||
{
|
||||
struct can_ml_priv *can_ml = can_get_ml_priv(dev);
|
||||
|
||||
if (!can_ml)
|
||||
return false;
|
||||
|
||||
return (can_ml->can_cap & cap);
|
||||
}
|
||||
|
||||
static inline void can_set_cap(struct net_device *dev, u32 cap)
|
||||
{
|
||||
struct can_ml_priv *can_ml = can_get_ml_priv(dev);
|
||||
|
||||
can_ml->can_cap = cap;
|
||||
}
|
||||
|
||||
#endif /* CAN_ML_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
||||
/*
|
||||
* linux/can/core.h
|
||||
*
|
||||
* Prototypes and definitions for CAN protocol modules using the PF_CAN core
|
||||
*
|
||||
* Authors: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
|
||||
* Urs Thuermann <urs.thuermann@volkswagen.de>
|
||||
* Copyright (c) 2002-2017 Volkswagen Group Electronic Research
|
||||
* All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CAN_CORE_H
|
||||
#define _CAN_CORE_H
|
||||
|
||||
#include <linux/can.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#define DNAME(dev) ((dev) ? (dev)->name : "any")
|
||||
|
||||
/**
|
||||
* struct can_proto - CAN protocol structure
|
||||
* @type: type argument in socket() syscall, e.g. SOCK_DGRAM.
|
||||
* @protocol: protocol number in socket() syscall.
|
||||
* @ops: pointer to struct proto_ops for sock->ops.
|
||||
* @prot: pointer to struct proto structure.
|
||||
*/
|
||||
struct can_proto {
|
||||
int type;
|
||||
int protocol;
|
||||
const struct proto_ops *ops;
|
||||
struct proto *prot;
|
||||
};
|
||||
|
||||
/* required_size
|
||||
* macro to find the minimum size of a struct
|
||||
* that includes a requested member
|
||||
*/
|
||||
#define CAN_REQUIRED_SIZE(struct_type, member) \
|
||||
(offsetof(typeof(struct_type), member) + \
|
||||
sizeof(((typeof(struct_type) *)(NULL))->member))
|
||||
|
||||
/* function prototypes for the CAN networklayer core (af_can.c) */
|
||||
|
||||
extern int can_proto_register(const struct can_proto *cp);
|
||||
extern void can_proto_unregister(const struct can_proto *cp);
|
||||
|
||||
int can_rx_register(struct net *net, struct net_device *dev,
|
||||
canid_t can_id, canid_t mask,
|
||||
void (*func)(struct sk_buff *, void *),
|
||||
void *data, char *ident, struct sock *sk);
|
||||
|
||||
extern void can_rx_unregister(struct net *net, struct net_device *dev,
|
||||
canid_t can_id, canid_t mask,
|
||||
void (*func)(struct sk_buff *, void *),
|
||||
void *data);
|
||||
|
||||
extern int can_send(struct sk_buff *skb, int loop);
|
||||
void can_set_skb_uid(struct sk_buff *skb);
|
||||
void can_sock_destruct(struct sock *sk);
|
||||
|
||||
#endif /* !_CAN_CORE_H */
|
||||
@@ -0,0 +1,201 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* linux/can/dev.h
|
||||
*
|
||||
* Definitions for the CAN network device driver interface
|
||||
*
|
||||
* Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
|
||||
* Varma Electronics Oy
|
||||
*
|
||||
* Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CAN_DEV_H
|
||||
#define _CAN_DEV_H
|
||||
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/bittiming.h>
|
||||
#include <linux/can/error.h>
|
||||
#include <linux/can/length.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/can/skb.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
/*
|
||||
* CAN mode
|
||||
*/
|
||||
enum can_mode {
|
||||
CAN_MODE_STOP = 0,
|
||||
CAN_MODE_START,
|
||||
CAN_MODE_SLEEP
|
||||
};
|
||||
|
||||
enum can_termination_gpio {
|
||||
CAN_TERMINATION_GPIO_DISABLED = 0,
|
||||
CAN_TERMINATION_GPIO_ENABLED,
|
||||
CAN_TERMINATION_GPIO_MAX,
|
||||
};
|
||||
|
||||
/*
|
||||
* CAN common private data
|
||||
*/
|
||||
struct can_priv {
|
||||
struct net_device *dev;
|
||||
struct can_device_stats can_stats;
|
||||
|
||||
const struct can_bittiming_const *bittiming_const;
|
||||
struct can_bittiming bittiming;
|
||||
struct data_bittiming_params fd, xl;
|
||||
unsigned int bitrate_const_cnt;
|
||||
const u32 *bitrate_const;
|
||||
u32 bitrate_max;
|
||||
struct can_clock clock;
|
||||
|
||||
unsigned int termination_const_cnt;
|
||||
const u16 *termination_const;
|
||||
u16 termination;
|
||||
struct gpio_desc *termination_gpio;
|
||||
u16 termination_gpio_ohms[CAN_TERMINATION_GPIO_MAX];
|
||||
|
||||
unsigned int echo_skb_max;
|
||||
struct sk_buff **echo_skb;
|
||||
|
||||
enum can_state state;
|
||||
|
||||
/* CAN controller features - see include/uapi/linux/can/netlink.h */
|
||||
u32 ctrlmode; /* current options setting */
|
||||
u32 ctrlmode_supported; /* options that can be modified by netlink */
|
||||
|
||||
int restart_ms;
|
||||
struct delayed_work restart_work;
|
||||
|
||||
int (*do_set_bittiming)(struct net_device *dev);
|
||||
int (*do_set_mode)(struct net_device *dev, enum can_mode mode);
|
||||
int (*do_set_termination)(struct net_device *dev, u16 term);
|
||||
int (*do_get_state)(const struct net_device *dev,
|
||||
enum can_state *state);
|
||||
int (*do_get_berr_counter)(const struct net_device *dev,
|
||||
struct can_berr_counter *bec);
|
||||
};
|
||||
|
||||
static inline bool can_fd_tdc_is_enabled(const struct can_priv *priv)
|
||||
{
|
||||
return !!(priv->ctrlmode & CAN_CTRLMODE_FD_TDC_MASK);
|
||||
}
|
||||
|
||||
static inline bool can_xl_tdc_is_enabled(const struct can_priv *priv)
|
||||
{
|
||||
return !!(priv->ctrlmode & CAN_CTRLMODE_XL_TDC_MASK);
|
||||
}
|
||||
|
||||
static inline u32 can_get_static_ctrlmode(struct can_priv *priv)
|
||||
{
|
||||
return priv->ctrlmode & ~priv->ctrlmode_supported;
|
||||
}
|
||||
|
||||
static inline bool can_is_canxl_dev_mtu(unsigned int mtu)
|
||||
{
|
||||
return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU);
|
||||
}
|
||||
|
||||
void can_setup(struct net_device *dev);
|
||||
|
||||
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
||||
unsigned int txqs, unsigned int rxqs);
|
||||
#define alloc_candev(sizeof_priv, echo_skb_max) \
|
||||
alloc_candev_mqs(sizeof_priv, echo_skb_max, 1, 1)
|
||||
#define alloc_candev_mq(sizeof_priv, echo_skb_max, count) \
|
||||
alloc_candev_mqs(sizeof_priv, echo_skb_max, count, count)
|
||||
void free_candev(struct net_device *dev);
|
||||
|
||||
/* a candev safe wrapper around netdev_priv */
|
||||
struct can_priv *safe_candev_priv(struct net_device *dev);
|
||||
|
||||
int open_candev(struct net_device *dev);
|
||||
void close_candev(struct net_device *dev);
|
||||
void can_set_default_mtu(struct net_device *dev);
|
||||
void can_set_cap_info(struct net_device *dev);
|
||||
int __must_check can_set_static_ctrlmode(struct net_device *dev,
|
||||
u32 static_mode);
|
||||
int can_hwtstamp_get(struct net_device *netdev,
|
||||
struct kernel_hwtstamp_config *cfg);
|
||||
int can_hwtstamp_set(struct net_device *netdev,
|
||||
struct kernel_hwtstamp_config *cfg,
|
||||
struct netlink_ext_ack *extack);
|
||||
int can_ethtool_op_get_ts_info_hwts(struct net_device *dev,
|
||||
struct kernel_ethtool_ts_info *info);
|
||||
|
||||
int register_candev(struct net_device *dev);
|
||||
void unregister_candev(struct net_device *dev);
|
||||
|
||||
int can_restart_now(struct net_device *dev);
|
||||
void can_bus_off(struct net_device *dev);
|
||||
|
||||
const char *can_get_state_str(const enum can_state state);
|
||||
const char *can_get_ctrlmode_str(u32 ctrlmode);
|
||||
|
||||
static inline bool can_dev_in_xl_only_mode(struct can_priv *priv)
|
||||
{
|
||||
const u32 mixed_mode = CAN_CTRLMODE_FD | CAN_CTRLMODE_XL;
|
||||
|
||||
/* When CAN XL is enabled but FD is disabled we are running in
|
||||
* the so-called 'CANXL-only mode' where the error signalling is
|
||||
* disabled. This helper function determines the required value
|
||||
* to disable error signalling in the CAN XL controller.
|
||||
* The so-called CC/FD/XL 'mixed mode' requires error signalling.
|
||||
*/
|
||||
return ((priv->ctrlmode & mixed_mode) == CAN_CTRLMODE_XL);
|
||||
}
|
||||
|
||||
/* drop skb if it does not contain a valid CAN frame for sending */
|
||||
static inline bool can_dev_dropped_skb(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
u32 silent_mode = priv->ctrlmode & (CAN_CTRLMODE_LISTENONLY |
|
||||
CAN_CTRLMODE_RESTRICTED);
|
||||
|
||||
if (silent_mode) {
|
||||
netdev_info_once(dev, "interface in %s mode, dropping skb\n",
|
||||
can_get_ctrlmode_str(silent_mode));
|
||||
goto invalid_skb;
|
||||
}
|
||||
|
||||
if (!(priv->ctrlmode & CAN_CTRLMODE_FD) && can_is_canfd_skb(skb)) {
|
||||
netdev_info_once(dev, "CAN FD is disabled, dropping skb\n");
|
||||
goto invalid_skb;
|
||||
}
|
||||
|
||||
if (can_dev_in_xl_only_mode(priv) && !can_is_canxl_skb(skb)) {
|
||||
netdev_info_once(dev,
|
||||
"Error signaling is disabled, dropping skb\n");
|
||||
goto invalid_skb;
|
||||
}
|
||||
|
||||
return can_dropped_invalid_skb(dev, skb);
|
||||
|
||||
invalid_skb:
|
||||
kfree_skb(skb);
|
||||
dev->stats.tx_dropped++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void can_state_get_by_berr_counter(const struct net_device *dev,
|
||||
const struct can_berr_counter *bec,
|
||||
enum can_state *tx_state,
|
||||
enum can_state *rx_state);
|
||||
void can_change_state(struct net_device *dev, struct can_frame *cf,
|
||||
enum can_state tx_state, enum can_state rx_state);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
void of_can_transceiver(struct net_device *dev);
|
||||
#else
|
||||
static inline void of_can_transceiver(struct net_device *dev) { }
|
||||
#endif
|
||||
|
||||
extern struct rtnl_link_ops can_link_ops;
|
||||
int can_netlink_register(void);
|
||||
void can_netlink_unregister(void);
|
||||
|
||||
#endif /* !_CAN_DEV_H */
|
||||
@@ -0,0 +1,300 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* CAN driver for PEAK System micro-CAN based adapters
|
||||
*
|
||||
* Copyright (C) 2003-2025 PEAK System-Technik GmbH
|
||||
* Author: Stéphane Grosjean <stephane.grosjean@hms-networks.com>
|
||||
*/
|
||||
#ifndef PUCAN_H
|
||||
#define PUCAN_H
|
||||
|
||||
/* uCAN commands opcodes list (low-order 10 bits) */
|
||||
#define PUCAN_CMD_NOP 0x000
|
||||
#define PUCAN_CMD_RESET_MODE 0x001
|
||||
#define PUCAN_CMD_NORMAL_MODE 0x002
|
||||
#define PUCAN_CMD_LISTEN_ONLY_MODE 0x003
|
||||
#define PUCAN_CMD_TIMING_SLOW 0x004
|
||||
#define PUCAN_CMD_TIMING_FAST 0x005
|
||||
#define PUCAN_CMD_SET_STD_FILTER 0x006
|
||||
#define PUCAN_CMD_RESERVED2 0x007
|
||||
#define PUCAN_CMD_FILTER_STD 0x008
|
||||
#define PUCAN_CMD_TX_ABORT 0x009
|
||||
#define PUCAN_CMD_WR_ERR_CNT 0x00a
|
||||
#define PUCAN_CMD_SET_EN_OPTION 0x00b
|
||||
#define PUCAN_CMD_CLR_DIS_OPTION 0x00c
|
||||
#define PUCAN_CMD_RX_BARRIER 0x010
|
||||
#define PUCAN_CMD_END_OF_COLLECTION 0x3ff
|
||||
|
||||
/* uCAN received messages list */
|
||||
#define PUCAN_MSG_CAN_RX 0x0001
|
||||
#define PUCAN_MSG_ERROR 0x0002
|
||||
#define PUCAN_MSG_STATUS 0x0003
|
||||
#define PUCAN_MSG_BUSLOAD 0x0004
|
||||
|
||||
#define PUCAN_MSG_CACHE_CRITICAL 0x0102
|
||||
|
||||
/* uCAN transmitted messages */
|
||||
#define PUCAN_MSG_CAN_TX 0x1000
|
||||
|
||||
/* uCAN command common header */
|
||||
struct __packed pucan_command {
|
||||
__le16 opcode_channel;
|
||||
u16 args[3];
|
||||
};
|
||||
|
||||
/* return the opcode from the opcode_channel field of a command */
|
||||
static inline u16 pucan_cmd_get_opcode(struct pucan_command *c)
|
||||
{
|
||||
return le16_to_cpu(c->opcode_channel) & 0x3ff;
|
||||
}
|
||||
|
||||
#define PUCAN_TSLOW_BRP_BITS 10
|
||||
#define PUCAN_TSLOW_TSGEG1_BITS 8
|
||||
#define PUCAN_TSLOW_TSGEG2_BITS 7
|
||||
#define PUCAN_TSLOW_SJW_BITS 7
|
||||
|
||||
#define PUCAN_TSLOW_BRP_MASK ((1 << PUCAN_TSLOW_BRP_BITS) - 1)
|
||||
#define PUCAN_TSLOW_TSEG1_MASK ((1 << PUCAN_TSLOW_TSGEG1_BITS) - 1)
|
||||
#define PUCAN_TSLOW_TSEG2_MASK ((1 << PUCAN_TSLOW_TSGEG2_BITS) - 1)
|
||||
#define PUCAN_TSLOW_SJW_MASK ((1 << PUCAN_TSLOW_SJW_BITS) - 1)
|
||||
|
||||
/* uCAN TIMING_SLOW command fields */
|
||||
#define PUCAN_TSLOW_SJW_T(s, t) (((s) & PUCAN_TSLOW_SJW_MASK) | \
|
||||
((!!(t)) << 7))
|
||||
#define PUCAN_TSLOW_TSEG2(t) ((t) & PUCAN_TSLOW_TSEG2_MASK)
|
||||
#define PUCAN_TSLOW_TSEG1(t) ((t) & PUCAN_TSLOW_TSEG1_MASK)
|
||||
#define PUCAN_TSLOW_BRP(b) ((b) & PUCAN_TSLOW_BRP_MASK)
|
||||
|
||||
struct __packed pucan_timing_slow {
|
||||
__le16 opcode_channel;
|
||||
|
||||
u8 ewl; /* Error Warning limit */
|
||||
u8 sjw_t; /* Sync Jump Width + Triple sampling */
|
||||
u8 tseg2; /* Timing SEGment 2 */
|
||||
u8 tseg1; /* Timing SEGment 1 */
|
||||
|
||||
__le16 brp; /* BaudRate Prescaler */
|
||||
};
|
||||
|
||||
#define PUCAN_TFAST_BRP_BITS 10
|
||||
#define PUCAN_TFAST_TSGEG1_BITS 5
|
||||
#define PUCAN_TFAST_TSGEG2_BITS 4
|
||||
#define PUCAN_TFAST_SJW_BITS 4
|
||||
|
||||
#define PUCAN_TFAST_BRP_MASK ((1 << PUCAN_TFAST_BRP_BITS) - 1)
|
||||
#define PUCAN_TFAST_TSEG1_MASK ((1 << PUCAN_TFAST_TSGEG1_BITS) - 1)
|
||||
#define PUCAN_TFAST_TSEG2_MASK ((1 << PUCAN_TFAST_TSGEG2_BITS) - 1)
|
||||
#define PUCAN_TFAST_SJW_MASK ((1 << PUCAN_TFAST_SJW_BITS) - 1)
|
||||
|
||||
/* uCAN TIMING_FAST command fields */
|
||||
#define PUCAN_TFAST_SJW(s) ((s) & PUCAN_TFAST_SJW_MASK)
|
||||
#define PUCAN_TFAST_TSEG2(t) ((t) & PUCAN_TFAST_TSEG2_MASK)
|
||||
#define PUCAN_TFAST_TSEG1(t) ((t) & PUCAN_TFAST_TSEG1_MASK)
|
||||
#define PUCAN_TFAST_BRP(b) ((b) & PUCAN_TFAST_BRP_MASK)
|
||||
|
||||
struct __packed pucan_timing_fast {
|
||||
__le16 opcode_channel;
|
||||
|
||||
u8 unused;
|
||||
u8 sjw; /* Sync Jump Width */
|
||||
u8 tseg2; /* Timing SEGment 2 */
|
||||
u8 tseg1; /* Timing SEGment 1 */
|
||||
|
||||
__le16 brp; /* BaudRate Prescaler */
|
||||
};
|
||||
|
||||
/* uCAN FILTER_STD command fields */
|
||||
#define PUCAN_FLTSTD_ROW_IDX_BITS 6
|
||||
|
||||
struct __packed pucan_filter_std {
|
||||
__le16 opcode_channel;
|
||||
|
||||
__le16 idx;
|
||||
__le32 mask; /* CAN-ID bitmask in idx range */
|
||||
};
|
||||
|
||||
#define PUCAN_FLTSTD_ROW_IDX_MAX ((1 << PUCAN_FLTSTD_ROW_IDX_BITS) - 1)
|
||||
|
||||
/* uCAN SET_STD_FILTER command fields */
|
||||
struct __packed pucan_std_filter {
|
||||
__le16 opcode_channel;
|
||||
|
||||
u8 unused;
|
||||
u8 idx;
|
||||
__le32 mask; /* CAN-ID bitmask in idx range */
|
||||
};
|
||||
|
||||
/* uCAN TX_ABORT commands fields */
|
||||
#define PUCAN_TX_ABORT_FLUSH 0x0001
|
||||
|
||||
struct __packed pucan_tx_abort {
|
||||
__le16 opcode_channel;
|
||||
|
||||
__le16 flags;
|
||||
u32 unused;
|
||||
};
|
||||
|
||||
/* uCAN WR_ERR_CNT command fields */
|
||||
#define PUCAN_WRERRCNT_TE 0x4000 /* Tx error cntr write Enable */
|
||||
#define PUCAN_WRERRCNT_RE 0x8000 /* Rx error cntr write Enable */
|
||||
|
||||
struct __packed pucan_wr_err_cnt {
|
||||
__le16 opcode_channel;
|
||||
|
||||
__le16 sel_mask;
|
||||
u8 tx_counter; /* Tx error counter new value */
|
||||
u8 rx_counter; /* Rx error counter new value */
|
||||
|
||||
u16 unused;
|
||||
};
|
||||
|
||||
/* uCAN SET_EN/CLR_DIS _OPTION command fields */
|
||||
#define PUCAN_OPTION_ERROR 0x0001
|
||||
#define PUCAN_OPTION_BUSLOAD 0x0002
|
||||
#define PUCAN_OPTION_CANDFDISO 0x0004
|
||||
|
||||
struct __packed pucan_options {
|
||||
__le16 opcode_channel;
|
||||
|
||||
__le16 options;
|
||||
u32 unused;
|
||||
};
|
||||
|
||||
/* uCAN received messages global format */
|
||||
struct __packed pucan_msg {
|
||||
__le16 size;
|
||||
__le16 type;
|
||||
__le32 ts_low;
|
||||
__le32 ts_high;
|
||||
};
|
||||
|
||||
/* uCAN flags for CAN/CANFD messages */
|
||||
#define PUCAN_MSG_SELF_RECEIVE 0x80
|
||||
#define PUCAN_MSG_ERROR_STATE_IND 0x40 /* error state indicator */
|
||||
#define PUCAN_MSG_BITRATE_SWITCH 0x20 /* bitrate switch */
|
||||
#define PUCAN_MSG_EXT_DATA_LEN 0x10 /* extended data length */
|
||||
#define PUCAN_MSG_SINGLE_SHOT 0x08
|
||||
#define PUCAN_MSG_LOOPED_BACK 0x04
|
||||
#define PUCAN_MSG_EXT_ID 0x02
|
||||
#define PUCAN_MSG_RTR 0x01
|
||||
|
||||
struct __packed pucan_rx_msg {
|
||||
__le16 size;
|
||||
__le16 type;
|
||||
__le32 ts_low;
|
||||
__le32 ts_high;
|
||||
__le32 tag_low;
|
||||
__le32 tag_high;
|
||||
u8 channel_dlc;
|
||||
u8 client;
|
||||
__le16 flags;
|
||||
__le32 can_id;
|
||||
u8 d[];
|
||||
};
|
||||
|
||||
/* uCAN error types */
|
||||
#define PUCAN_ERMSG_BIT_ERROR 0
|
||||
#define PUCAN_ERMSG_FORM_ERROR 1
|
||||
#define PUCAN_ERMSG_STUFF_ERROR 2
|
||||
#define PUCAN_ERMSG_OTHER_ERROR 3
|
||||
#define PUCAN_ERMSG_ERR_CNT_DEC 4
|
||||
|
||||
struct __packed pucan_error_msg {
|
||||
__le16 size;
|
||||
__le16 type;
|
||||
__le32 ts_low;
|
||||
__le32 ts_high;
|
||||
u8 channel_type_d;
|
||||
u8 code_g;
|
||||
u8 tx_err_cnt;
|
||||
u8 rx_err_cnt;
|
||||
};
|
||||
|
||||
static inline int pucan_error_get_channel(const struct pucan_error_msg *msg)
|
||||
{
|
||||
return msg->channel_type_d & 0x0f;
|
||||
}
|
||||
|
||||
#define PUCAN_RX_BARRIER 0x10
|
||||
#define PUCAN_BUS_PASSIVE 0x20
|
||||
#define PUCAN_BUS_WARNING 0x40
|
||||
#define PUCAN_BUS_BUSOFF 0x80
|
||||
|
||||
struct __packed pucan_status_msg {
|
||||
__le16 size;
|
||||
__le16 type;
|
||||
__le32 ts_low;
|
||||
__le32 ts_high;
|
||||
u8 channel_p_w_b;
|
||||
u8 unused[3];
|
||||
};
|
||||
|
||||
static inline int pucan_status_get_channel(const struct pucan_status_msg *msg)
|
||||
{
|
||||
return msg->channel_p_w_b & 0x0f;
|
||||
}
|
||||
|
||||
static inline int pucan_status_is_rx_barrier(const struct pucan_status_msg *msg)
|
||||
{
|
||||
return msg->channel_p_w_b & PUCAN_RX_BARRIER;
|
||||
}
|
||||
|
||||
static inline int pucan_status_is_passive(const struct pucan_status_msg *msg)
|
||||
{
|
||||
return msg->channel_p_w_b & PUCAN_BUS_PASSIVE;
|
||||
}
|
||||
|
||||
static inline int pucan_status_is_warning(const struct pucan_status_msg *msg)
|
||||
{
|
||||
return msg->channel_p_w_b & PUCAN_BUS_WARNING;
|
||||
}
|
||||
|
||||
static inline int pucan_status_is_busoff(const struct pucan_status_msg *msg)
|
||||
{
|
||||
return msg->channel_p_w_b & PUCAN_BUS_BUSOFF;
|
||||
}
|
||||
|
||||
/* uCAN transmitted message format */
|
||||
#define PUCAN_MSG_CHANNEL_DLC(c, d) (((c) & 0xf) | ((d) << 4))
|
||||
|
||||
struct __packed pucan_tx_msg {
|
||||
__le16 size;
|
||||
__le16 type;
|
||||
__le32 tag_low;
|
||||
__le32 tag_high;
|
||||
u8 channel_dlc;
|
||||
u8 client;
|
||||
__le16 flags;
|
||||
__le32 can_id;
|
||||
u8 d[];
|
||||
};
|
||||
|
||||
/* build the cmd opcode_channel field with respect to the correct endianness */
|
||||
static inline __le16 pucan_cmd_opcode_channel(int index, int opcode)
|
||||
{
|
||||
return cpu_to_le16(((index) << 12) | ((opcode) & 0x3ff));
|
||||
}
|
||||
|
||||
/* return the channel number part from any received message channel_dlc field */
|
||||
static inline int pucan_msg_get_channel(const struct pucan_rx_msg *msg)
|
||||
{
|
||||
return msg->channel_dlc & 0xf;
|
||||
}
|
||||
|
||||
/* return the dlc value from any received message channel_dlc field */
|
||||
static inline u8 pucan_msg_get_dlc(const struct pucan_rx_msg *msg)
|
||||
{
|
||||
return msg->channel_dlc >> 4;
|
||||
}
|
||||
|
||||
static inline int pucan_ermsg_get_channel(const struct pucan_error_msg *msg)
|
||||
{
|
||||
return msg->channel_type_d & 0x0f;
|
||||
}
|
||||
|
||||
static inline int pucan_stmsg_get_channel(const struct pucan_status_msg *msg)
|
||||
{
|
||||
return msg->channel_p_w_b & 0x0f;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,306 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2020 Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
* Copyright (C) 2020 Marc Kleine-Budde <kernel@pengutronix.de>
|
||||
* Copyright (C) 2020, 2023 Vincent Mailhol <mailhol.vincent@wanadoo.fr>
|
||||
*/
|
||||
|
||||
#ifndef _CAN_LENGTH_H
|
||||
#define _CAN_LENGTH_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/can.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/math.h>
|
||||
|
||||
/*
|
||||
* Size of a Classical CAN Standard Frame header in bits
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* Start Of Frame (SOF) 1
|
||||
* Arbitration field:
|
||||
* base ID 11
|
||||
* Remote Transmission Request (RTR) 1
|
||||
* Control field:
|
||||
* IDentifier Extension bit (IDE) 1
|
||||
* FD Format indicator (FDF) 1
|
||||
* Data Length Code (DLC) 4
|
||||
*
|
||||
* including all fields preceding the data field, ignoring bitstuffing
|
||||
*/
|
||||
#define CAN_FRAME_HEADER_SFF_BITS 19
|
||||
|
||||
/*
|
||||
* Size of a Classical CAN Extended Frame header in bits
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* Start Of Frame (SOF) 1
|
||||
* Arbitration field:
|
||||
* base ID 11
|
||||
* Substitute Remote Request (SRR) 1
|
||||
* IDentifier Extension bit (IDE) 1
|
||||
* ID extension 18
|
||||
* Remote Transmission Request (RTR) 1
|
||||
* Control field:
|
||||
* FD Format indicator (FDF) 1
|
||||
* Reserved bit (r0) 1
|
||||
* Data length code (DLC) 4
|
||||
*
|
||||
* including all fields preceding the data field, ignoring bitstuffing
|
||||
*/
|
||||
#define CAN_FRAME_HEADER_EFF_BITS 39
|
||||
|
||||
/*
|
||||
* Size of a CAN-FD Standard Frame in bits
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* Start Of Frame (SOF) 1
|
||||
* Arbitration field:
|
||||
* base ID 11
|
||||
* Remote Request Substitution (RRS) 1
|
||||
* Control field:
|
||||
* IDentifier Extension bit (IDE) 1
|
||||
* FD Format indicator (FDF) 1
|
||||
* Reserved bit (res) 1
|
||||
* Bit Rate Switch (BRS) 1
|
||||
* Error Status Indicator (ESI) 1
|
||||
* Data length code (DLC) 4
|
||||
*
|
||||
* including all fields preceding the data field, ignoring bitstuffing
|
||||
*/
|
||||
#define CANFD_FRAME_HEADER_SFF_BITS 22
|
||||
|
||||
/*
|
||||
* Size of a CAN-FD Extended Frame in bits
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* Start Of Frame (SOF) 1
|
||||
* Arbitration field:
|
||||
* base ID 11
|
||||
* Substitute Remote Request (SRR) 1
|
||||
* IDentifier Extension bit (IDE) 1
|
||||
* ID extension 18
|
||||
* Remote Request Substitution (RRS) 1
|
||||
* Control field:
|
||||
* FD Format indicator (FDF) 1
|
||||
* Reserved bit (res) 1
|
||||
* Bit Rate Switch (BRS) 1
|
||||
* Error Status Indicator (ESI) 1
|
||||
* Data length code (DLC) 4
|
||||
*
|
||||
* including all fields preceding the data field, ignoring bitstuffing
|
||||
*/
|
||||
#define CANFD_FRAME_HEADER_EFF_BITS 41
|
||||
|
||||
/*
|
||||
* Size of a CAN CRC Field in bits
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* CRC sequence (CRC15) 15
|
||||
* CRC Delimiter 1
|
||||
*
|
||||
* ignoring bitstuffing
|
||||
*/
|
||||
#define CAN_FRAME_CRC_FIELD_BITS 16
|
||||
|
||||
/*
|
||||
* Size of a CAN-FD CRC17 Field in bits (length: 0..16)
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* Stuff Count 4
|
||||
* CRC Sequence (CRC17) 17
|
||||
* CRC Delimiter 1
|
||||
* Fixed stuff bits 6
|
||||
*/
|
||||
#define CANFD_FRAME_CRC17_FIELD_BITS 28
|
||||
|
||||
/*
|
||||
* Size of a CAN-FD CRC21 Field in bits (length: 20..64)
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* Stuff Count 4
|
||||
* CRC sequence (CRC21) 21
|
||||
* CRC Delimiter 1
|
||||
* Fixed stuff bits 7
|
||||
*/
|
||||
#define CANFD_FRAME_CRC21_FIELD_BITS 33
|
||||
|
||||
/*
|
||||
* Size of a CAN(-FD) Frame footer in bits
|
||||
*
|
||||
* Name of Field Bits
|
||||
* ---------------------------------------------------------
|
||||
* ACK slot 1
|
||||
* ACK delimiter 1
|
||||
* End Of Frame (EOF) 7
|
||||
*
|
||||
* including all fields following the CRC field
|
||||
*/
|
||||
#define CAN_FRAME_FOOTER_BITS 9
|
||||
|
||||
/*
|
||||
* First part of the Inter Frame Space
|
||||
* (a.k.a. IMF - intermission field)
|
||||
*/
|
||||
#define CAN_INTERMISSION_BITS 3
|
||||
|
||||
/**
|
||||
* can_bitstuffing_len() - Calculate the maximum length with bitstuffing
|
||||
* @destuffed_len: length of a destuffed bit stream
|
||||
*
|
||||
* The worst bit stuffing case is a sequence in which dominant and
|
||||
* recessive bits alternate every four bits:
|
||||
*
|
||||
* Destuffed: 1 1111 0000 1111 0000 1111
|
||||
* Stuffed: 1 1111o 0000i 1111o 0000i 1111o
|
||||
*
|
||||
* Nomenclature
|
||||
*
|
||||
* - "0": dominant bit
|
||||
* - "o": dominant stuff bit
|
||||
* - "1": recessive bit
|
||||
* - "i": recessive stuff bit
|
||||
*
|
||||
* Aside from the first bit, one stuff bit is added every four bits.
|
||||
*
|
||||
* Return: length of the stuffed bit stream in the worst case scenario.
|
||||
*/
|
||||
#define can_bitstuffing_len(destuffed_len) \
|
||||
(destuffed_len + (destuffed_len - 1) / 4)
|
||||
|
||||
#define __can_bitstuffing_len(bitstuffing, destuffed_len) \
|
||||
(bitstuffing ? can_bitstuffing_len(destuffed_len) : \
|
||||
destuffed_len)
|
||||
|
||||
#define __can_cc_frame_bits(is_eff, bitstuffing, \
|
||||
intermission, data_len) \
|
||||
( \
|
||||
__can_bitstuffing_len(bitstuffing, \
|
||||
(is_eff ? CAN_FRAME_HEADER_EFF_BITS : \
|
||||
CAN_FRAME_HEADER_SFF_BITS) + \
|
||||
(data_len) * BITS_PER_BYTE + \
|
||||
CAN_FRAME_CRC_FIELD_BITS) + \
|
||||
CAN_FRAME_FOOTER_BITS + \
|
||||
(intermission ? CAN_INTERMISSION_BITS : 0) \
|
||||
)
|
||||
|
||||
#define __can_fd_frame_bits(is_eff, bitstuffing, \
|
||||
intermission, data_len) \
|
||||
( \
|
||||
__can_bitstuffing_len(bitstuffing, \
|
||||
(is_eff ? CANFD_FRAME_HEADER_EFF_BITS : \
|
||||
CANFD_FRAME_HEADER_SFF_BITS) + \
|
||||
(data_len) * BITS_PER_BYTE) + \
|
||||
((data_len) <= 16 ? \
|
||||
CANFD_FRAME_CRC17_FIELD_BITS : \
|
||||
CANFD_FRAME_CRC21_FIELD_BITS) + \
|
||||
CAN_FRAME_FOOTER_BITS + \
|
||||
(intermission ? CAN_INTERMISSION_BITS : 0) \
|
||||
)
|
||||
|
||||
/**
|
||||
* can_frame_bits() - Calculate the number of bits on the wire in a
|
||||
* CAN frame
|
||||
* @is_fd: true: CAN-FD frame; false: Classical CAN frame.
|
||||
* @is_eff: true: Extended frame; false: Standard frame.
|
||||
* @bitstuffing: true: calculate the bitstuffing worst case; false:
|
||||
* calculate the bitstuffing best case (no dynamic
|
||||
* bitstuffing). CAN-FD's fixed stuff bits are always included.
|
||||
* @intermission: if and only if true, include the inter frame space
|
||||
* assuming no bus idle (i.e. only the intermission). Strictly
|
||||
* speaking, the inter frame space is not part of the
|
||||
* frame. However, it is needed when calculating the delay
|
||||
* between the Start Of Frame of two consecutive frames.
|
||||
* @data_len: length of the data field in bytes. Correspond to
|
||||
* can(fd)_frame->len. Should be zero for remote frames. No
|
||||
* sanitization is done on @data_len and it shall have no side
|
||||
* effects.
|
||||
*
|
||||
* Return: the numbers of bits on the wire of a CAN frame.
|
||||
*/
|
||||
#define can_frame_bits(is_fd, is_eff, bitstuffing, \
|
||||
intermission, data_len) \
|
||||
( \
|
||||
is_fd ? __can_fd_frame_bits(is_eff, bitstuffing, \
|
||||
intermission, data_len) : \
|
||||
__can_cc_frame_bits(is_eff, bitstuffing, \
|
||||
intermission, data_len) \
|
||||
)
|
||||
|
||||
/*
|
||||
* Number of bytes in a CAN frame
|
||||
* (rounded up, including intermission)
|
||||
*/
|
||||
#define can_frame_bytes(is_fd, is_eff, bitstuffing, data_len) \
|
||||
DIV_ROUND_UP(can_frame_bits(is_fd, is_eff, bitstuffing, \
|
||||
true, data_len), \
|
||||
BITS_PER_BYTE)
|
||||
|
||||
/*
|
||||
* Maximum size of a Classical CAN frame
|
||||
* (rounded up, ignoring bitstuffing but including intermission)
|
||||
*/
|
||||
#define CAN_FRAME_LEN_MAX can_frame_bytes(false, true, false, CAN_MAX_DLEN)
|
||||
|
||||
/*
|
||||
* Maximum size of a CAN-FD frame
|
||||
* (rounded up, ignoring dynamic bitstuffing but including intermission)
|
||||
*/
|
||||
#define CANFD_FRAME_LEN_MAX can_frame_bytes(true, true, false, CANFD_MAX_DLEN)
|
||||
|
||||
/*
|
||||
* can_cc_dlc2len(value) - convert a given data length code (dlc) of a
|
||||
* Classical CAN frame into a valid data length of max. 8 bytes.
|
||||
*
|
||||
* To be used in the CAN netdriver receive path to ensure conformance with
|
||||
* ISO 11898-1 Chapter 8.4.2.3 (DLC field)
|
||||
*/
|
||||
#define can_cc_dlc2len(dlc) (min_t(u8, (dlc), CAN_MAX_DLEN))
|
||||
|
||||
/* helper to get the data length code (DLC) for Classical CAN raw DLC access */
|
||||
static inline u8 can_get_cc_dlc(const struct can_frame *cf, const u32 ctrlmode)
|
||||
{
|
||||
/* return len8_dlc as dlc value only if all conditions apply */
|
||||
if ((ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC) &&
|
||||
(cf->len == CAN_MAX_DLEN) &&
|
||||
(cf->len8_dlc > CAN_MAX_DLEN && cf->len8_dlc <= CAN_MAX_RAW_DLC))
|
||||
return cf->len8_dlc;
|
||||
|
||||
/* return the payload length as dlc value */
|
||||
return cf->len;
|
||||
}
|
||||
|
||||
/* helper to set len and len8_dlc value for Classical CAN raw DLC access */
|
||||
static inline void can_frame_set_cc_len(struct can_frame *cf, const u8 dlc,
|
||||
const u32 ctrlmode)
|
||||
{
|
||||
/* the caller already ensured that dlc is a value from 0 .. 15 */
|
||||
if (ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC && dlc > CAN_MAX_DLEN)
|
||||
cf->len8_dlc = dlc;
|
||||
|
||||
/* limit the payload length 'len' to CAN_MAX_DLEN */
|
||||
cf->len = can_cc_dlc2len(dlc);
|
||||
}
|
||||
|
||||
/* get data length from raw data length code (DLC) */
|
||||
u8 can_fd_dlc2len(u8 dlc);
|
||||
|
||||
/* map the sanitized data length to an appropriate data length code */
|
||||
u8 can_fd_len2dlc(u8 len);
|
||||
|
||||
/* calculate the CAN Frame length in bytes of a given skb */
|
||||
unsigned int can_skb_get_frame_len(const struct sk_buff *skb);
|
||||
|
||||
/* map the data length to an appropriate data link layer length */
|
||||
static inline u8 canfd_sanitize_len(u8 len)
|
||||
{
|
||||
return can_fd_dlc2len(can_fd_len2dlc(len));
|
||||
}
|
||||
|
||||
#endif /* !_CAN_LENGTH_H */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _CAN_PLATFORM_CC770_H
|
||||
#define _CAN_PLATFORM_CC770_H
|
||||
|
||||
/* CPU Interface Register (0x02) */
|
||||
#define CPUIF_CEN 0x01 /* Clock Out Enable */
|
||||
#define CPUIF_MUX 0x04 /* Multiplex */
|
||||
#define CPUIF_SLP 0x08 /* Sleep */
|
||||
#define CPUIF_PWD 0x10 /* Power Down Mode */
|
||||
#define CPUIF_DMC 0x20 /* Divide Memory Clock */
|
||||
#define CPUIF_DSC 0x40 /* Divide System Clock */
|
||||
#define CPUIF_RST 0x80 /* Hardware Reset Status */
|
||||
|
||||
/* Clock Out Register (0x1f) */
|
||||
#define CLKOUT_CD_MASK 0x0f /* Clock Divider mask */
|
||||
#define CLKOUT_SL_MASK 0x30 /* Slew Rate mask */
|
||||
#define CLKOUT_SL_SHIFT 4
|
||||
|
||||
/* Bus Configuration Register (0x2f) */
|
||||
#define BUSCFG_DR0 0x01 /* Disconnect RX0 Input / Select RX input */
|
||||
#define BUSCFG_DR1 0x02 /* Disconnect RX1 Input / Silent mode */
|
||||
#define BUSCFG_DT1 0x08 /* Disconnect TX1 Output */
|
||||
#define BUSCFG_POL 0x20 /* Polarity dominant or recessive */
|
||||
#define BUSCFG_CBY 0x40 /* Input Comparator Bypass */
|
||||
|
||||
struct cc770_platform_data {
|
||||
u32 osc_freq; /* CAN bus oscillator frequency in Hz */
|
||||
|
||||
u8 cir; /* CPU Interface Register */
|
||||
u8 cor; /* Clock Out Register */
|
||||
u8 bcr; /* Bus Configuration Register */
|
||||
};
|
||||
|
||||
#endif /* !_CAN_PLATFORM_CC770_H */
|
||||
@@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2021 Angelo Dureghello <angelo@kernel-space.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _CAN_PLATFORM_FLEXCAN_H
|
||||
#define _CAN_PLATFORM_FLEXCAN_H
|
||||
|
||||
struct flexcan_platform_data {
|
||||
u32 clock_frequency;
|
||||
u8 clk_src;
|
||||
};
|
||||
|
||||
#endif /* _CAN_PLATFORM_FLEXCAN_H */
|
||||
@@ -0,0 +1,36 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _CAN_PLATFORM_SJA1000_H
|
||||
#define _CAN_PLATFORM_SJA1000_H
|
||||
|
||||
/* clock divider register */
|
||||
#define CDR_CLKOUT_MASK 0x07
|
||||
#define CDR_CLK_OFF 0x08 /* Clock off (CLKOUT pin) */
|
||||
#define CDR_RXINPEN 0x20 /* TX1 output is RX irq output */
|
||||
#define CDR_CBP 0x40 /* CAN input comparator bypass */
|
||||
#define CDR_PELICAN 0x80 /* PeliCAN mode */
|
||||
|
||||
/* output control register */
|
||||
#define OCR_MODE_BIPHASE 0x00
|
||||
#define OCR_MODE_TEST 0x01
|
||||
#define OCR_MODE_NORMAL 0x02
|
||||
#define OCR_MODE_CLOCK 0x03
|
||||
#define OCR_MODE_MASK 0x03
|
||||
#define OCR_TX0_INVERT 0x04
|
||||
#define OCR_TX0_PULLDOWN 0x08
|
||||
#define OCR_TX0_PULLUP 0x10
|
||||
#define OCR_TX0_PUSHPULL 0x18
|
||||
#define OCR_TX1_INVERT 0x20
|
||||
#define OCR_TX1_PULLDOWN 0x40
|
||||
#define OCR_TX1_PULLUP 0x80
|
||||
#define OCR_TX1_PUSHPULL 0xc0
|
||||
#define OCR_TX_MASK 0xfc
|
||||
#define OCR_TX_SHIFT 2
|
||||
|
||||
struct sja1000_platform_data {
|
||||
u32 osc_freq; /* CAN bus oscillator frequency in Hz */
|
||||
|
||||
u8 ocr; /* output control register */
|
||||
u8 cdr; /* clock divider register */
|
||||
};
|
||||
|
||||
#endif /* !_CAN_PLATFORM_SJA1000_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* linux/can/rx-offload.h
|
||||
*
|
||||
* Copyright (c) 2014 David Jander, Protonic Holland
|
||||
* Copyright (c) 2014-2017, 2023 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
|
||||
*/
|
||||
|
||||
#ifndef _CAN_RX_OFFLOAD_H
|
||||
#define _CAN_RX_OFFLOAD_H
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/can.h>
|
||||
|
||||
struct can_rx_offload {
|
||||
struct net_device *dev;
|
||||
|
||||
struct sk_buff *(*mailbox_read)(struct can_rx_offload *offload,
|
||||
unsigned int mb, u32 *timestamp,
|
||||
bool drop);
|
||||
|
||||
struct sk_buff_head skb_queue;
|
||||
struct sk_buff_head skb_irq_queue;
|
||||
u32 skb_queue_len_max;
|
||||
|
||||
unsigned int mb_first;
|
||||
unsigned int mb_last;
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
bool inc;
|
||||
};
|
||||
|
||||
int can_rx_offload_add_timestamp(struct net_device *dev,
|
||||
struct can_rx_offload *offload);
|
||||
int can_rx_offload_add_fifo(struct net_device *dev,
|
||||
struct can_rx_offload *offload,
|
||||
unsigned int weight);
|
||||
int can_rx_offload_add_manual(struct net_device *dev,
|
||||
struct can_rx_offload *offload,
|
||||
unsigned int weight);
|
||||
int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
|
||||
u64 reg);
|
||||
int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload);
|
||||
int can_rx_offload_queue_timestamp(struct can_rx_offload *offload,
|
||||
struct sk_buff *skb, u32 timestamp);
|
||||
unsigned int can_rx_offload_get_echo_skb_queue_timestamp(struct can_rx_offload *offload,
|
||||
unsigned int idx, u32 timestamp,
|
||||
unsigned int *frame_len_ptr);
|
||||
int can_rx_offload_queue_tail(struct can_rx_offload *offload,
|
||||
struct sk_buff *skb);
|
||||
unsigned int can_rx_offload_get_echo_skb_queue_tail(struct can_rx_offload *offload,
|
||||
unsigned int idx,
|
||||
unsigned int *frame_len_ptr);
|
||||
void can_rx_offload_irq_finish(struct can_rx_offload *offload);
|
||||
void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload);
|
||||
void can_rx_offload_del(struct can_rx_offload *offload);
|
||||
void can_rx_offload_enable(struct can_rx_offload *offload);
|
||||
|
||||
static inline void can_rx_offload_disable(struct can_rx_offload *offload)
|
||||
{
|
||||
napi_disable(&offload->napi);
|
||||
}
|
||||
|
||||
#endif /* !_CAN_RX_OFFLOAD_H */
|
||||
@@ -0,0 +1,143 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
|
||||
/*
|
||||
* linux/can/skb.h
|
||||
*
|
||||
* Definitions for the CAN network socket buffer
|
||||
*
|
||||
* Copyright (C) 2012 Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CAN_SKB_H
|
||||
#define _CAN_SKB_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/can.h>
|
||||
#include <net/can.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
void can_flush_echo_skb(struct net_device *dev);
|
||||
int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned int idx, unsigned int frame_len);
|
||||
struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
|
||||
unsigned int *len_ptr,
|
||||
unsigned int *frame_len_ptr);
|
||||
unsigned int __must_check can_get_echo_skb(struct net_device *dev,
|
||||
unsigned int idx,
|
||||
unsigned int *frame_len_ptr);
|
||||
void can_free_echo_skb(struct net_device *dev, unsigned int idx,
|
||||
unsigned int *frame_len_ptr);
|
||||
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
|
||||
struct sk_buff *alloc_canfd_skb(struct net_device *dev,
|
||||
struct canfd_frame **cfd);
|
||||
struct sk_buff *alloc_canxl_skb(struct net_device *dev,
|
||||
struct canxl_frame **cxl,
|
||||
unsigned int data_len);
|
||||
struct sk_buff *alloc_can_err_skb(struct net_device *dev,
|
||||
struct can_frame **cf);
|
||||
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb);
|
||||
|
||||
static inline struct can_skb_ext *can_skb_ext_add(struct sk_buff *skb)
|
||||
{
|
||||
struct can_skb_ext *csx = skb_ext_add(skb, SKB_EXT_CAN);
|
||||
|
||||
/* skb_ext_add() returns uninitialized space */
|
||||
if (csx)
|
||||
csx->can_gw_hops = 0;
|
||||
|
||||
return csx;
|
||||
}
|
||||
|
||||
static inline struct can_skb_ext *can_skb_ext_find(struct sk_buff *skb)
|
||||
{
|
||||
return skb_ext_find(skb, SKB_EXT_CAN);
|
||||
}
|
||||
|
||||
static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk)
|
||||
{
|
||||
/* If the socket has already been closed by user space, the
|
||||
* refcount may already be 0 (and the socket will be freed
|
||||
* after the last TX skb has been freed). So only increase
|
||||
* socket refcount if the refcount is > 0.
|
||||
*/
|
||||
if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) {
|
||||
skb->destructor = sock_efree;
|
||||
skb->sk = sk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* returns an unshared skb owned by the original sock to be echo'ed back
|
||||
*/
|
||||
static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
|
||||
nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (unlikely(!nskb)) {
|
||||
kfree_skb(skb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
can_skb_set_owner(nskb, skb->sk);
|
||||
consume_skb(skb);
|
||||
return nskb;
|
||||
}
|
||||
|
||||
static inline bool can_is_can_skb(const struct sk_buff *skb)
|
||||
{
|
||||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
|
||||
/* the CAN specific type of skb is identified by its data length */
|
||||
return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN);
|
||||
}
|
||||
|
||||
static inline bool can_is_canfd_skb(const struct sk_buff *skb)
|
||||
{
|
||||
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
|
||||
|
||||
/* the CAN specific type of skb is identified by its data length */
|
||||
return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN);
|
||||
}
|
||||
|
||||
static inline bool can_is_canxl_skb(const struct sk_buff *skb)
|
||||
{
|
||||
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
|
||||
|
||||
if (skb->len < CANXL_HDR_SIZE + CANXL_MIN_DLEN || skb->len > CANXL_MTU)
|
||||
return false;
|
||||
|
||||
/* this also checks valid CAN XL data length boundaries */
|
||||
if (skb->len != CANXL_HDR_SIZE + cxl->len)
|
||||
return false;
|
||||
|
||||
return cxl->flags & CANXL_XLF;
|
||||
}
|
||||
|
||||
/* get length element value from can[|fd|xl]_frame structure */
|
||||
static inline unsigned int can_skb_get_len_val(struct sk_buff *skb)
|
||||
{
|
||||
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
|
||||
const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
|
||||
|
||||
if (can_is_canxl_skb(skb))
|
||||
return cxl->len;
|
||||
|
||||
return cfd->len;
|
||||
}
|
||||
|
||||
/* get needed data length inside CAN frame for all frame types (RTR aware) */
|
||||
static inline unsigned int can_skb_get_data_len(struct sk_buff *skb)
|
||||
{
|
||||
unsigned int len = can_skb_get_len_val(skb);
|
||||
const struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
|
||||
/* RTR frames have an actual length of zero */
|
||||
if (can_is_can_skb(skb) && cf->can_id & CAN_RTR_FLAG)
|
||||
return 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif /* !_CAN_SKB_H */
|
||||
Reference in New Issue
Block a user