linux-can-fixes-for-6.1-20221107
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEBsvAIBsPu6mG7thcrX5LkNig010FAmNpAhcTHG1rbEBwZW5n dXRyb25peC5kZQAKCRCtfkuQ2KDTXeaNB/4om4cfVvLAgYVnoOrsQgUUXaWRQAxl nrIdRZGOB4LvL5p+Y9cO4tivAQI8plOx10zxex0jJcMujRsY+xWqBHBRRaWTKreh kVLSBd7TBAbiDyIyU5vJNUgjMrRwnymfxl2VcFARBF42z+/BcK2hQrLE8Mj+IqVr 8adtyuCHvfsBZEXk1o0RWbaeR/tbvV53x2cmRiHFukZh2MBliEf6j5a/KmRWJSck +UKdydssDhHoJi3Hv4MdUdo7NcjJVLbXbUYGLlaYz9RJmb7gTbUx/kPGRygCUikJ q/G0k0IgpcdjZjAgDjFGF/PEPIK449sOeMVpE+mzdDgYU+XCGASvDkCL =3x/D -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-6.1-20221107' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== can 2022-11-07 The first patch is by Chen Zhongjin and adds a missing dev_remove_pack() to the AF_CAN protocol. Zhengchao Shao's patch fixes a potential NULL pointer deref in AF_CAN's can_rx_register(). The next patch is by Oliver Hartkopp and targets the CAN ISO-TP protocol, and fixes the state handling for echo TX processing. Oliver Hartkopp's patch for the j1939 protocol adds a missing initialization of the CAN headers inside outgoing skbs. Another patch by Oliver Hartkopp fixes an out of bounds read in the check for invalid CAN frames in the xmit callback of virtual CAN devices. This touches all non virtual device drivers as we decided to rename the function requiring that netdev_priv points to a struct can_priv. (Note: This patch will create a merge conflict with net-next where the pch_can driver has removed.) The last patch is by Geert Uytterhoeven and adds the missing ECC error checks for the channels 2-7 in the rcar_canfd driver. * tag 'linux-can-fixes-for-6.1-20221107' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can: can: rcar_canfd: Add missing ECC error checks for channels 2-7 can: dev: fix skb drop check can: j1939: j1939_send_one(): fix missing CAN header initialization can: isotp: fix tx state handling for echo tx processing can: af_can: fix NULL pointer dereference in can_rx_register() can: af_can: can_exit(): add missing dev_remove_pack() of canxl_packet ==================== Link: https://lore.kernel.org/r/20221107133217.59861-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Коммит
2b01450328
|
@ -452,7 +452,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
unsigned int mb, prio;
|
||||
u32 reg_mid, reg_mcr;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
mb = get_tx_next_mb(priv);
|
||||
|
|
|
@ -457,7 +457,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
|
|||
struct c_can_tx_ring *tx_ring = &priv->tx;
|
||||
u32 idx, obj, cmd = IF_COMM_TX;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (c_can_tx_busy(priv, tx_ring))
|
||||
|
|
|
@ -813,7 +813,7 @@ static netdev_tx_t can327_netdev_start_xmit(struct sk_buff *skb,
|
|||
struct can327 *elm = netdev_priv(dev);
|
||||
struct can_frame *frame = (struct can_frame *)skb->data;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* We shouldn't get here after a hardware fault:
|
||||
|
|
|
@ -429,7 +429,7 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
struct cc770_priv *priv = netdev_priv(dev);
|
||||
unsigned int mo = obj2msgobj(CC770_OBJ_TX);
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
|
|
@ -600,7 +600,7 @@ static netdev_tx_t ctucan_start_xmit(struct sk_buff *skb, struct net_device *nde
|
|||
bool ok;
|
||||
unsigned long flags;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (unlikely(!CTU_CAN_FD_TXTNF(priv))) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
#include <linux/can/dev.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#define MOD_DESC "CAN device driver interface"
|
||||
|
@ -337,8 +336,6 @@ static bool can_skb_headroom_valid(struct net_device *dev, struct sk_buff *skb)
|
|||
/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
|
||||
bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
|
||||
{
|
||||
struct can_priv *priv = netdev_priv(dev);
|
||||
|
||||
switch (ntohs(skb->protocol)) {
|
||||
case ETH_P_CAN:
|
||||
if (!can_is_can_skb(skb))
|
||||
|
@ -359,13 +356,8 @@ bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
|
|||
goto inval_skb;
|
||||
}
|
||||
|
||||
if (!can_skb_headroom_valid(dev, skb)) {
|
||||
if (!can_skb_headroom_valid(dev, skb))
|
||||
goto inval_skb;
|
||||
} else if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
|
||||
netdev_info_once(dev,
|
||||
"interface in listen only mode, dropping skb\n");
|
||||
goto inval_skb;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
|
|
|
@ -742,7 +742,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
|
|||
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_fd_len2dlc(cfd->len)) << 16);
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
|
|
@ -1345,7 +1345,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
|
|||
unsigned long flags;
|
||||
u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* Trying to transmit in silent mode will generate error interrupts, but
|
||||
|
|
|
@ -860,7 +860,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb,
|
|||
u32 txst, txid, txdlc;
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* Check if the TX buffer is full */
|
||||
|
|
|
@ -1693,7 +1693,7 @@ static netdev_tx_t ican3_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
void __iomem *desc_addr;
|
||||
unsigned long flags;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
spin_lock_irqsave(&mod->lock, flags);
|
||||
|
|
|
@ -772,7 +772,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
|
|||
int nwords;
|
||||
u8 count;
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb);
|
||||
|
|
|
@ -1721,7 +1721,7 @@ static netdev_tx_t m_can_start_xmit(struct sk_buff *skb,
|
|||
{
|
||||
struct m_can_classdev *cdev = netdev_priv(dev);
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (cdev->is_peripheral) {
|
||||
|
|
|
@ -191,7 +191,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
int i, rtr, buf_id;
|
||||
u32 can_id;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
out_8(®s->cantier, 0);
|
||||
|
|
|
@ -882,7 +882,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
int i;
|
||||
u32 id2;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
tx_obj_no = priv->tx_obj;
|
||||
|
|
|
@ -651,7 +651,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
|
|||
int room_left;
|
||||
u8 len;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
msg_size = ALIGN(sizeof(*msg) + cf->len, 4);
|
||||
|
|
|
@ -590,7 +590,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
|
|||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
u32 data, i;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
|
||||
|
|
|
@ -81,8 +81,7 @@ enum rcanfd_chip_id {
|
|||
|
||||
/* RSCFDnCFDGERFL / RSCFDnGERFL */
|
||||
#define RCANFD_GERFL_EEF0_7 GENMASK(23, 16)
|
||||
#define RCANFD_GERFL_EEF1 BIT(17)
|
||||
#define RCANFD_GERFL_EEF0 BIT(16)
|
||||
#define RCANFD_GERFL_EEF(ch) BIT(16 + (ch))
|
||||
#define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */
|
||||
#define RCANFD_GERFL_THLES BIT(2)
|
||||
#define RCANFD_GERFL_MES BIT(1)
|
||||
|
@ -90,7 +89,7 @@ enum rcanfd_chip_id {
|
|||
|
||||
#define RCANFD_GERFL_ERR(gpriv, x) \
|
||||
((x) & (reg_v3u(gpriv, RCANFD_GERFL_EEF0_7, \
|
||||
RCANFD_GERFL_EEF0 | RCANFD_GERFL_EEF1) | \
|
||||
RCANFD_GERFL_EEF(0) | RCANFD_GERFL_EEF(1)) | \
|
||||
RCANFD_GERFL_MES | \
|
||||
((gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0)))
|
||||
|
||||
|
@ -936,12 +935,8 @@ static void rcar_canfd_global_error(struct net_device *ndev)
|
|||
u32 ridx = ch + RCANFD_RFFIFO_IDX;
|
||||
|
||||
gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL);
|
||||
if ((gerfl & RCANFD_GERFL_EEF0) && (ch == 0)) {
|
||||
netdev_dbg(ndev, "Ch0: ECC Error flag\n");
|
||||
stats->tx_dropped++;
|
||||
}
|
||||
if ((gerfl & RCANFD_GERFL_EEF1) && (ch == 1)) {
|
||||
netdev_dbg(ndev, "Ch1: ECC Error flag\n");
|
||||
if (gerfl & RCANFD_GERFL_EEF(ch)) {
|
||||
netdev_dbg(ndev, "Ch%u: ECC Error flag\n", ch);
|
||||
stats->tx_dropped++;
|
||||
}
|
||||
if (gerfl & RCANFD_GERFL_MES) {
|
||||
|
@ -1481,7 +1476,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
|
|||
unsigned long flags;
|
||||
u32 ch = priv->channel;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (cf->can_id & CAN_EFF_FLAG) {
|
||||
|
|
|
@ -291,7 +291,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
|
|||
u8 cmd_reg_val = 0x00;
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
|
|
@ -594,7 +594,7 @@ static netdev_tx_t slcan_netdev_xmit(struct sk_buff *skb,
|
|||
{
|
||||
struct slcan *sl = netdev_priv(dev);
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
spin_lock(&sl->lock);
|
||||
|
|
|
@ -60,7 +60,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
|
|||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
uint8_t buf[DPRAM_TX_SIZE];
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
spin_lock(&card->spin);
|
||||
|
|
|
@ -373,7 +373,7 @@ static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
|
|||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (can_dropped_invalid_skb(net, skb))
|
||||
if (can_dev_dropped_skb(net, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(net);
|
||||
|
|
|
@ -789,7 +789,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
|
|||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (can_dropped_invalid_skb(net, skb))
|
||||
if (can_dev_dropped_skb(net, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(net);
|
||||
|
|
|
@ -172,7 +172,7 @@ netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
|
|||
u8 tx_head;
|
||||
int err;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (mcp251xfd_tx_busy(priv, tx_ring))
|
||||
|
|
|
@ -429,7 +429,7 @@ static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *d
|
|||
canid_t id;
|
||||
int i;
|
||||
|
||||
if (can_dropped_invalid_skb(dev, skb))
|
||||
if (can_dev_dropped_skb(dev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
netif_stop_queue(dev);
|
||||
|
|
|
@ -470,7 +470,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
u32 mbxno, mbx_mask, data;
|
||||
unsigned long flags;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
mbxno = get_tx_head_mb(priv);
|
||||
|
|
|
@ -747,7 +747,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
|
|||
size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
|
||||
+ sizeof(struct cpc_can_msg);
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* create a URB, and a buffer for it, and copy the data to the URB */
|
||||
|
|
|
@ -725,7 +725,7 @@ static netdev_tx_t esd_usb_start_xmit(struct sk_buff *skb,
|
|||
int ret = NETDEV_TX_OK;
|
||||
size_t size = sizeof(struct esd_usb_msg);
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* create a URB, and a buffer for it, and copy the data to the URB */
|
||||
|
|
|
@ -1913,7 +1913,7 @@ static netdev_tx_t es58x_start_xmit(struct sk_buff *skb,
|
|||
unsigned int frame_len;
|
||||
int ret;
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb)) {
|
||||
if (can_dev_dropped_skb(netdev, skb)) {
|
||||
if (priv->tx_urb)
|
||||
goto xmit_commit;
|
||||
return NETDEV_TX_OK;
|
||||
|
|
|
@ -723,7 +723,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
|||
unsigned int idx;
|
||||
struct gs_tx_context *txc;
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* find an empty context to keep track of transmission */
|
||||
|
|
|
@ -570,7 +570,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
|
|||
unsigned int i;
|
||||
unsigned long flags;
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
|
|
|
@ -311,7 +311,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
|
|||
.cmd_id = MBCA_CMD_TRANSMIT_MESSAGE_EV
|
||||
};
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
ctx = mcba_usb_get_free_ctx(priv, cf);
|
||||
|
|
|
@ -351,7 +351,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb,
|
|||
int i, err;
|
||||
size_t size = dev->adapter->tx_buffer_size;
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++)
|
||||
|
|
|
@ -1120,7 +1120,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb,
|
|||
struct can_frame *cf = (struct can_frame *)skb->data;
|
||||
|
||||
/* check skb */
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* allocate a context and slow down tx path, if fifo state is low */
|
||||
|
|
|
@ -602,7 +602,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
|
|||
int i, err;
|
||||
size_t size = sizeof(struct usb_8dev_tx_msg);
|
||||
|
||||
if (can_dropped_invalid_skb(netdev, skb))
|
||||
if (can_dev_dropped_skb(netdev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
/* create a URB, and a buffer for it, and copy the data to the URB */
|
||||
|
|
|
@ -743,7 +743,7 @@ static netdev_tx_t xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
struct xcan_priv *priv = netdev_priv(ndev);
|
||||
int ret;
|
||||
|
||||
if (can_dropped_invalid_skb(ndev, skb))
|
||||
if (can_dev_dropped_skb(ndev, skb))
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
if (priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES)
|
||||
|
|
|
@ -152,6 +152,22 @@ static inline bool can_is_canxl_dev_mtu(unsigned int mtu)
|
|||
return (mtu >= CANXL_MIN_MTU && mtu <= CANXL_MAX_MTU);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
if (priv->ctrlmode & CAN_CTRLMODE_LISTENONLY) {
|
||||
netdev_info_once(dev,
|
||||
"interface in listen only mode, dropping skb\n");
|
||||
kfree_skb(skb);
|
||||
dev->stats.tx_dropped++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return can_dropped_invalid_skb(dev, skb);
|
||||
}
|
||||
|
||||
void can_setup(struct net_device *dev);
|
||||
|
||||
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
|
||||
|
|
|
@ -450,7 +450,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id,
|
|||
|
||||
/* insert new receiver (dev,canid,mask) -> (func,data) */
|
||||
|
||||
if (dev && dev->type != ARPHRD_CAN)
|
||||
if (dev && (dev->type != ARPHRD_CAN || !can_get_ml_priv(dev)))
|
||||
return -ENODEV;
|
||||
|
||||
if (dev && !net_eq(net, dev_net(dev)))
|
||||
|
@ -902,6 +902,7 @@ out_pernet:
|
|||
static __exit void can_exit(void)
|
||||
{
|
||||
/* protocol unregister */
|
||||
dev_remove_pack(&canxl_packet);
|
||||
dev_remove_pack(&canfd_packet);
|
||||
dev_remove_pack(&can_packet);
|
||||
sock_unregister(PF_CAN);
|
||||
|
|
|
@ -111,6 +111,9 @@ MODULE_ALIAS("can-proto-6");
|
|||
#define ISOTP_FC_WT 1 /* wait */
|
||||
#define ISOTP_FC_OVFLW 2 /* overflow */
|
||||
|
||||
#define ISOTP_FC_TIMEOUT 1 /* 1 sec */
|
||||
#define ISOTP_ECHO_TIMEOUT 2 /* 2 secs */
|
||||
|
||||
enum {
|
||||
ISOTP_IDLE = 0,
|
||||
ISOTP_WAIT_FIRST_FC,
|
||||
|
@ -258,7 +261,8 @@ static int isotp_send_fc(struct sock *sk, int ae, u8 flowstatus)
|
|||
so->lastrxcf_tstamp = ktime_set(0, 0);
|
||||
|
||||
/* start rx timeout watchdog */
|
||||
hrtimer_start(&so->rxtimer, ktime_set(1, 0), HRTIMER_MODE_REL_SOFT);
|
||||
hrtimer_start(&so->rxtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -344,6 +348,8 @@ static int check_pad(struct isotp_sock *so, struct canfd_frame *cf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void isotp_send_cframe(struct isotp_sock *so);
|
||||
|
||||
static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
|
||||
{
|
||||
struct sock *sk = &so->sk;
|
||||
|
@ -398,14 +404,15 @@ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
|
|||
case ISOTP_FC_CTS:
|
||||
so->tx.bs = 0;
|
||||
so->tx.state = ISOTP_SENDING;
|
||||
/* start cyclic timer for sending CF frame */
|
||||
hrtimer_start(&so->txtimer, so->tx_gap,
|
||||
/* send CF frame and enable echo timeout handling */
|
||||
hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
isotp_send_cframe(so);
|
||||
break;
|
||||
|
||||
case ISOTP_FC_WT:
|
||||
/* start timer to wait for next FC frame */
|
||||
hrtimer_start(&so->txtimer, ktime_set(1, 0),
|
||||
hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
break;
|
||||
|
||||
|
@ -600,7 +607,7 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
|
|||
/* perform blocksize handling, if enabled */
|
||||
if (!so->rxfc.bs || ++so->rx.bs < so->rxfc.bs) {
|
||||
/* start rx timeout watchdog */
|
||||
hrtimer_start(&so->rxtimer, ktime_set(1, 0),
|
||||
hrtimer_start(&so->rxtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
return 0;
|
||||
}
|
||||
|
@ -829,7 +836,7 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
|
|||
struct isotp_sock *so = isotp_sk(sk);
|
||||
struct canfd_frame *cf = (struct canfd_frame *)skb->data;
|
||||
|
||||
/* only handle my own local echo skb's */
|
||||
/* only handle my own local echo CF/SF skb's (no FF!) */
|
||||
if (skb->sk != sk || so->cfecho != *(u32 *)cf->data)
|
||||
return;
|
||||
|
||||
|
@ -849,13 +856,16 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
|
|||
if (so->txfc.bs && so->tx.bs >= so->txfc.bs) {
|
||||
/* stop and wait for FC with timeout */
|
||||
so->tx.state = ISOTP_WAIT_FC;
|
||||
hrtimer_start(&so->txtimer, ktime_set(1, 0),
|
||||
hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* no gap between data frames needed => use burst mode */
|
||||
if (!so->tx_gap) {
|
||||
/* enable echo timeout handling */
|
||||
hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
isotp_send_cframe(so);
|
||||
return;
|
||||
}
|
||||
|
@ -879,7 +889,7 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
|
|||
/* start timeout for unlikely lost echo skb */
|
||||
hrtimer_set_expires(&so->txtimer,
|
||||
ktime_add(ktime_get(),
|
||||
ktime_set(2, 0)));
|
||||
ktime_set(ISOTP_ECHO_TIMEOUT, 0)));
|
||||
restart = HRTIMER_RESTART;
|
||||
|
||||
/* push out the next consecutive frame */
|
||||
|
@ -907,7 +917,8 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
|
|||
break;
|
||||
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
WARN_ONCE(1, "can-isotp: tx timer state %08X cfecho %08X\n",
|
||||
so->tx.state, so->cfecho);
|
||||
}
|
||||
|
||||
return restart;
|
||||
|
@ -923,7 +934,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
|||
struct canfd_frame *cf;
|
||||
int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
|
||||
int wait_tx_done = (so->opt.flags & CAN_ISOTP_WAIT_TX_DONE) ? 1 : 0;
|
||||
s64 hrtimer_sec = 0;
|
||||
s64 hrtimer_sec = ISOTP_ECHO_TIMEOUT;
|
||||
int off;
|
||||
int err;
|
||||
|
||||
|
@ -942,6 +953,8 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
|||
err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
so->tx.state = ISOTP_SENDING;
|
||||
}
|
||||
|
||||
if (!size || size > MAX_MSG_LENGTH) {
|
||||
|
@ -986,6 +999,10 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
|||
cf = (struct canfd_frame *)skb->data;
|
||||
skb_put_zero(skb, so->ll.mtu);
|
||||
|
||||
/* cfecho should have been zero'ed by init / former isotp_rcv_echo() */
|
||||
if (so->cfecho)
|
||||
pr_notice_once("can-isotp: uninit cfecho %08X\n", so->cfecho);
|
||||
|
||||
/* check for single frame transmission depending on TX_DL */
|
||||
if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) {
|
||||
/* The message size generally fits into a SingleFrame - good.
|
||||
|
@ -1011,11 +1028,8 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
|||
else
|
||||
cf->data[ae] |= size;
|
||||
|
||||
so->tx.state = ISOTP_IDLE;
|
||||
wake_up_interruptible(&so->wait);
|
||||
|
||||
/* don't enable wait queue for a single frame transmission */
|
||||
wait_tx_done = 0;
|
||||
/* set CF echo tag for isotp_rcv_echo() (SF-mode) */
|
||||
so->cfecho = *(u32 *)cf->data;
|
||||
} else {
|
||||
/* send first frame */
|
||||
|
||||
|
@ -1031,31 +1045,23 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
|||
/* disable wait for FCs due to activated block size */
|
||||
so->txfc.bs = 0;
|
||||
|
||||
/* cfecho should have been zero'ed by init */
|
||||
if (so->cfecho)
|
||||
pr_notice_once("can-isotp: no fc cfecho %08X\n",
|
||||
so->cfecho);
|
||||
|
||||
/* set consecutive frame echo tag */
|
||||
/* set CF echo tag for isotp_rcv_echo() (CF-mode) */
|
||||
so->cfecho = *(u32 *)cf->data;
|
||||
|
||||
/* switch directly to ISOTP_SENDING state */
|
||||
so->tx.state = ISOTP_SENDING;
|
||||
|
||||
/* start timeout for unlikely lost echo skb */
|
||||
hrtimer_sec = 2;
|
||||
} else {
|
||||
/* standard flow control check */
|
||||
so->tx.state = ISOTP_WAIT_FIRST_FC;
|
||||
|
||||
/* start timeout for FC */
|
||||
hrtimer_sec = 1;
|
||||
}
|
||||
hrtimer_sec = ISOTP_FC_TIMEOUT;
|
||||
|
||||
hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
/* no CF echo tag for isotp_rcv_echo() (FF-mode) */
|
||||
so->cfecho = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0),
|
||||
HRTIMER_MODE_REL_SOFT);
|
||||
|
||||
/* send the first or only CAN frame */
|
||||
cf->flags = so->ll.tx_flags;
|
||||
|
||||
|
@ -1068,8 +1074,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
|
|||
__func__, ERR_PTR(err));
|
||||
|
||||
/* no transmission -> no timeout monitoring */
|
||||
if (hrtimer_sec)
|
||||
hrtimer_cancel(&so->txtimer);
|
||||
hrtimer_cancel(&so->txtimer);
|
||||
|
||||
/* reset consecutive frame echo tag */
|
||||
so->cfecho = 0;
|
||||
|
|
|
@ -336,6 +336,9 @@ int j1939_send_one(struct j1939_priv *priv, struct sk_buff *skb)
|
|||
/* re-claim the CAN_HDR from the SKB */
|
||||
cf = skb_push(skb, J1939_CAN_HDR);
|
||||
|
||||
/* initialize header structure */
|
||||
memset(cf, 0, J1939_CAN_HDR);
|
||||
|
||||
/* make it a full can frame again */
|
||||
skb_put(skb, J1939_CAN_FTR + (8 - dlc));
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче