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:
Jakub Kicinski 2022-11-08 15:22:33 -08:00
Родитель ce9e57feee 8b043dfb3d
Коммит 2b01450328
39 изменённых файлов: 98 добавлений и 86 удалений

Просмотреть файл

@ -452,7 +452,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned int mb, prio; unsigned int mb, prio;
u32 reg_mid, reg_mcr; u32 reg_mid, reg_mcr;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
mb = get_tx_next_mb(priv); 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; struct c_can_tx_ring *tx_ring = &priv->tx;
u32 idx, obj, cmd = IF_COMM_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; return NETDEV_TX_OK;
if (c_can_tx_busy(priv, tx_ring)) 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 can327 *elm = netdev_priv(dev);
struct can_frame *frame = (struct can_frame *)skb->data; 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; return NETDEV_TX_OK;
/* We shouldn't get here after a hardware fault: /* 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); struct cc770_priv *priv = netdev_priv(dev);
unsigned int mo = obj2msgobj(CC770_OBJ_TX); 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; return NETDEV_TX_OK;
netif_stop_queue(dev); 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; bool ok;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (unlikely(!CTU_CAN_FD_TXTNF(priv))) { if (unlikely(!CTU_CAN_FD_TXTNF(priv))) {

Просмотреть файл

@ -5,7 +5,6 @@
*/ */
#include <linux/can/dev.h> #include <linux/can/dev.h>
#include <linux/can/netlink.h>
#include <linux/module.h> #include <linux/module.h>
#define MOD_DESC "CAN device driver interface" #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. */ /* 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) bool can_dropped_invalid_skb(struct net_device *dev, struct sk_buff *skb)
{ {
struct can_priv *priv = netdev_priv(dev);
switch (ntohs(skb->protocol)) { switch (ntohs(skb->protocol)) {
case ETH_P_CAN: case ETH_P_CAN:
if (!can_is_can_skb(skb)) 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; goto inval_skb;
} }
if (!can_skb_headroom_valid(dev, skb)) { if (!can_skb_headroom_valid(dev, skb))
goto inval_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; 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); u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | ((can_fd_len2dlc(cfd->len)) << 16);
int i; int i;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(dev); netif_stop_queue(dev);

Просмотреть файл

@ -1345,7 +1345,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
unsigned long flags; unsigned long flags;
u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT; 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; return NETDEV_TX_OK;
/* Trying to transmit in silent mode will generate error interrupts, but /* 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; u32 txst, txid, txdlc;
int i; int i;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* Check if the TX buffer is full */ /* 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; void __iomem *desc_addr;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
spin_lock_irqsave(&mod->lock, flags); spin_lock_irqsave(&mod->lock, flags);

Просмотреть файл

@ -772,7 +772,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
int nwords; int nwords;
u8 count; u8 count;
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
nwords = kvaser_pciefd_prepare_tx_packet(&packet, can, skb); 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); 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; return NETDEV_TX_OK;
if (cdev->is_peripheral) { 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; int i, rtr, buf_id;
u32 can_id; u32 can_id;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
out_8(&regs->cantier, 0); out_8(&regs->cantier, 0);

Просмотреть файл

@ -882,7 +882,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
int i; int i;
u32 id2; u32 id2;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
tx_obj_no = priv->tx_obj; 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; int room_left;
u8 len; u8 len;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
msg_size = ALIGN(sizeof(*msg) + cf->len, 4); 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; struct can_frame *cf = (struct can_frame *)skb->data;
u32 data, i; u32 data, i;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */ if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */

Просмотреть файл

@ -81,8 +81,7 @@ enum rcanfd_chip_id {
/* RSCFDnCFDGERFL / RSCFDnGERFL */ /* RSCFDnCFDGERFL / RSCFDnGERFL */
#define RCANFD_GERFL_EEF0_7 GENMASK(23, 16) #define RCANFD_GERFL_EEF0_7 GENMASK(23, 16)
#define RCANFD_GERFL_EEF1 BIT(17) #define RCANFD_GERFL_EEF(ch) BIT(16 + (ch))
#define RCANFD_GERFL_EEF0 BIT(16)
#define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */ #define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */
#define RCANFD_GERFL_THLES BIT(2) #define RCANFD_GERFL_THLES BIT(2)
#define RCANFD_GERFL_MES BIT(1) #define RCANFD_GERFL_MES BIT(1)
@ -90,7 +89,7 @@ enum rcanfd_chip_id {
#define RCANFD_GERFL_ERR(gpriv, x) \ #define RCANFD_GERFL_ERR(gpriv, x) \
((x) & (reg_v3u(gpriv, RCANFD_GERFL_EEF0_7, \ ((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 | \ RCANFD_GERFL_MES | \
((gpriv)->fdmode ? RCANFD_GERFL_CMPOF : 0))) ((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; u32 ridx = ch + RCANFD_RFFIFO_IDX;
gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL); gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL);
if ((gerfl & RCANFD_GERFL_EEF0) && (ch == 0)) { if (gerfl & RCANFD_GERFL_EEF(ch)) {
netdev_dbg(ndev, "Ch0: ECC Error flag\n"); netdev_dbg(ndev, "Ch%u: ECC Error flag\n", ch);
stats->tx_dropped++;
}
if ((gerfl & RCANFD_GERFL_EEF1) && (ch == 1)) {
netdev_dbg(ndev, "Ch1: ECC Error flag\n");
stats->tx_dropped++; stats->tx_dropped++;
} }
if (gerfl & RCANFD_GERFL_MES) { if (gerfl & RCANFD_GERFL_MES) {
@ -1481,7 +1476,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
unsigned long flags; unsigned long flags;
u32 ch = priv->channel; u32 ch = priv->channel;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (cf->can_id & CAN_EFF_FLAG) { 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; u8 cmd_reg_val = 0x00;
int i; int i;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(dev); 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); struct slcan *sl = netdev_priv(dev);
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
spin_lock(&sl->lock); 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; struct can_frame *cf = (struct can_frame *)skb->data;
uint8_t buf[DPRAM_TX_SIZE]; uint8_t buf[DPRAM_TX_SIZE];
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
spin_lock(&card->spin); spin_lock(&card->spin);

Просмотреть файл

@ -373,7 +373,7 @@ static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
if (can_dropped_invalid_skb(net, skb)) if (can_dev_dropped_skb(net, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(net); netif_stop_queue(net);

Просмотреть файл

@ -789,7 +789,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
if (can_dropped_invalid_skb(net, skb)) if (can_dev_dropped_skb(net, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(net); netif_stop_queue(net);

Просмотреть файл

@ -172,7 +172,7 @@ netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
u8 tx_head; u8 tx_head;
int err; int err;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (mcp251xfd_tx_busy(priv, tx_ring)) 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; canid_t id;
int i; int i;
if (can_dropped_invalid_skb(dev, skb)) if (can_dev_dropped_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
netif_stop_queue(dev); 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; u32 mbxno, mbx_mask, data;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
mbxno = get_tx_head_mb(priv); 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 size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
+ sizeof(struct cpc_can_msg); + sizeof(struct cpc_can_msg);
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* create a URB, and a buffer for it, and copy the data to the URB */ /* 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; int ret = NETDEV_TX_OK;
size_t size = sizeof(struct esd_usb_msg); 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; return NETDEV_TX_OK;
/* create a URB, and a buffer for it, and copy the data to the URB */ /* 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; unsigned int frame_len;
int ret; int ret;
if (can_dropped_invalid_skb(netdev, skb)) { if (can_dev_dropped_skb(netdev, skb)) {
if (priv->tx_urb) if (priv->tx_urb)
goto xmit_commit; goto xmit_commit;
return NETDEV_TX_OK; return NETDEV_TX_OK;

Просмотреть файл

@ -723,7 +723,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
unsigned int idx; unsigned int idx;
struct gs_tx_context *txc; struct gs_tx_context *txc;
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* find an empty context to keep track of transmission */ /* 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 int i;
unsigned long flags; unsigned long flags;
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
urb = usb_alloc_urb(0, GFP_ATOMIC); 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 .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; return NETDEV_TX_OK;
ctx = mcba_usb_get_free_ctx(priv, cf); 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; int i, err;
size_t size = dev->adapter->tx_buffer_size; 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; return NETDEV_TX_OK;
for (i = 0; i < PCAN_USB_MAX_TX_URBS; i++) 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; struct can_frame *cf = (struct can_frame *)skb->data;
/* check skb */ /* check skb */
if (can_dropped_invalid_skb(netdev, skb)) if (can_dev_dropped_skb(netdev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
/* allocate a context and slow down tx path, if fifo state is low */ /* 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; int i, err;
size_t size = sizeof(struct usb_8dev_tx_msg); 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; return NETDEV_TX_OK;
/* create a URB, and a buffer for it, and copy the data to the URB */ /* 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); struct xcan_priv *priv = netdev_priv(ndev);
int ret; int ret;
if (can_dropped_invalid_skb(ndev, skb)) if (can_dev_dropped_skb(ndev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
if (priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) 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); 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); void can_setup(struct net_device *dev);
struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, 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) */ /* 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; return -ENODEV;
if (dev && !net_eq(net, dev_net(dev))) if (dev && !net_eq(net, dev_net(dev)))
@ -902,6 +902,7 @@ out_pernet:
static __exit void can_exit(void) static __exit void can_exit(void)
{ {
/* protocol unregister */ /* protocol unregister */
dev_remove_pack(&canxl_packet);
dev_remove_pack(&canfd_packet); dev_remove_pack(&canfd_packet);
dev_remove_pack(&can_packet); dev_remove_pack(&can_packet);
sock_unregister(PF_CAN); sock_unregister(PF_CAN);

Просмотреть файл

@ -111,6 +111,9 @@ MODULE_ALIAS("can-proto-6");
#define ISOTP_FC_WT 1 /* wait */ #define ISOTP_FC_WT 1 /* wait */
#define ISOTP_FC_OVFLW 2 /* overflow */ #define ISOTP_FC_OVFLW 2 /* overflow */
#define ISOTP_FC_TIMEOUT 1 /* 1 sec */
#define ISOTP_ECHO_TIMEOUT 2 /* 2 secs */
enum { enum {
ISOTP_IDLE = 0, ISOTP_IDLE = 0,
ISOTP_WAIT_FIRST_FC, 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); so->lastrxcf_tstamp = ktime_set(0, 0);
/* start rx timeout watchdog */ /* 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; return 0;
} }
@ -344,6 +348,8 @@ static int check_pad(struct isotp_sock *so, struct canfd_frame *cf,
return 0; 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) static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
{ {
struct sock *sk = &so->sk; 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: case ISOTP_FC_CTS:
so->tx.bs = 0; so->tx.bs = 0;
so->tx.state = ISOTP_SENDING; so->tx.state = ISOTP_SENDING;
/* start cyclic timer for sending CF frame */ /* send CF frame and enable echo timeout handling */
hrtimer_start(&so->txtimer, so->tx_gap, hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT); HRTIMER_MODE_REL_SOFT);
isotp_send_cframe(so);
break; break;
case ISOTP_FC_WT: case ISOTP_FC_WT:
/* start timer to wait for next FC frame */ /* 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); HRTIMER_MODE_REL_SOFT);
break; break;
@ -600,7 +607,7 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
/* perform blocksize handling, if enabled */ /* perform blocksize handling, if enabled */
if (!so->rxfc.bs || ++so->rx.bs < so->rxfc.bs) { if (!so->rxfc.bs || ++so->rx.bs < so->rxfc.bs) {
/* start rx timeout watchdog */ /* 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); HRTIMER_MODE_REL_SOFT);
return 0; 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 isotp_sock *so = isotp_sk(sk);
struct canfd_frame *cf = (struct canfd_frame *)skb->data; 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) if (skb->sk != sk || so->cfecho != *(u32 *)cf->data)
return; 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) { if (so->txfc.bs && so->tx.bs >= so->txfc.bs) {
/* stop and wait for FC with timeout */ /* stop and wait for FC with timeout */
so->tx.state = ISOTP_WAIT_FC; 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); HRTIMER_MODE_REL_SOFT);
return; return;
} }
/* no gap between data frames needed => use burst mode */ /* no gap between data frames needed => use burst mode */
if (!so->tx_gap) { 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); isotp_send_cframe(so);
return; return;
} }
@ -879,7 +889,7 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
/* start timeout for unlikely lost echo skb */ /* start timeout for unlikely lost echo skb */
hrtimer_set_expires(&so->txtimer, hrtimer_set_expires(&so->txtimer,
ktime_add(ktime_get(), ktime_add(ktime_get(),
ktime_set(2, 0))); ktime_set(ISOTP_ECHO_TIMEOUT, 0)));
restart = HRTIMER_RESTART; restart = HRTIMER_RESTART;
/* push out the next consecutive frame */ /* push out the next consecutive frame */
@ -907,7 +917,8 @@ static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
break; break;
default: default:
WARN_ON_ONCE(1); WARN_ONCE(1, "can-isotp: tx timer state %08X cfecho %08X\n",
so->tx.state, so->cfecho);
} }
return restart; return restart;
@ -923,7 +934,7 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
struct canfd_frame *cf; struct canfd_frame *cf;
int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; 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; 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 off;
int err; 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); err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
if (err) if (err)
goto err_out; goto err_out;
so->tx.state = ISOTP_SENDING;
} }
if (!size || size > MAX_MSG_LENGTH) { 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; cf = (struct canfd_frame *)skb->data;
skb_put_zero(skb, so->ll.mtu); 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 */ /* check for single frame transmission depending on TX_DL */
if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) { if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) {
/* The message size generally fits into a SingleFrame - good. /* 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 else
cf->data[ae] |= size; cf->data[ae] |= size;
so->tx.state = ISOTP_IDLE; /* set CF echo tag for isotp_rcv_echo() (SF-mode) */
wake_up_interruptible(&so->wait); so->cfecho = *(u32 *)cf->data;
/* don't enable wait queue for a single frame transmission */
wait_tx_done = 0;
} else { } else {
/* send first frame */ /* 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 */ /* disable wait for FCs due to activated block size */
so->txfc.bs = 0; so->txfc.bs = 0;
/* cfecho should have been zero'ed by init */ /* set CF echo tag for isotp_rcv_echo() (CF-mode) */
if (so->cfecho)
pr_notice_once("can-isotp: no fc cfecho %08X\n",
so->cfecho);
/* set consecutive frame echo tag */
so->cfecho = *(u32 *)cf->data; 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 { } else {
/* standard flow control check */ /* standard flow control check */
so->tx.state = ISOTP_WAIT_FIRST_FC; so->tx.state = ISOTP_WAIT_FIRST_FC;
/* start timeout for FC */ /* start timeout for FC */
hrtimer_sec = 1; hrtimer_sec = ISOTP_FC_TIMEOUT;
}
hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0), /* no CF echo tag for isotp_rcv_echo() (FF-mode) */
HRTIMER_MODE_REL_SOFT); so->cfecho = 0;
}
} }
hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0),
HRTIMER_MODE_REL_SOFT);
/* send the first or only CAN frame */ /* send the first or only CAN frame */
cf->flags = so->ll.tx_flags; 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)); __func__, ERR_PTR(err));
/* no transmission -> no timeout monitoring */ /* no transmission -> no timeout monitoring */
if (hrtimer_sec) hrtimer_cancel(&so->txtimer);
hrtimer_cancel(&so->txtimer);
/* reset consecutive frame echo tag */ /* reset consecutive frame echo tag */
so->cfecho = 0; 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 */ /* re-claim the CAN_HDR from the SKB */
cf = skb_push(skb, J1939_CAN_HDR); cf = skb_push(skb, J1939_CAN_HDR);
/* initialize header structure */
memset(cf, 0, J1939_CAN_HDR);
/* make it a full can frame again */ /* make it a full can frame again */
skb_put(skb, J1939_CAN_FTR + (8 - dlc)); skb_put(skb, J1939_CAN_FTR + (8 - dlc));