linux-can-next-for-5.15-20210804
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmEKaBUTHG1rbEBwZW5n dXRyb25peC5kZQAKCRCpyVqK+u3vqSvgCACpR64hydl7/qt9QGnm9Ym6/v/L9y9v aBfZMQsedP1GSuev5PpxghXU4GF0LXiDr6ryr0hhu7w2ojjlLNl9sVHCF9qdAJKz x2D4YTlxct2KuPBdhWllQr/KWFbJh2IzarHEWzdo+QoU5A8jDlsK2kLeeikFECzT fVUe3mu1k66/DvHsetsfzIvbUkuHk2SPpK/pwrUC6Siw6wQZBHlSoUEtBNwEPlyH 8+ZQJPqtrjr2v3mZUOkgHrlXEOZRu6OM3i1Yv2bn2x4VI+3KQHEw/cA1WNE2AOzN CfMp4sS98QdCrAboX4VJZpGAbziTFHedqFjjIP9ultCfH9ROHhQj4Zsl =37wt -----END PGP SIGNATURE----- Merge tag 'linux-can-next-for-5.15-20210804' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next Marc Kleine-Budde says: ==================== pull-request: can-next 2021-08-04 this is a pull request of 5 patches for net-next/master. The first patch is by me and fixes a typo in a comment in the CAN J1939 protocol. The next 2 patches are by Oleksij Rempel and update the CAN J1939 protocol to send RX status updates via the error queue mechanism. The next patch is by me and adds a missing variable initialization to the flexcan driver (the problem was introduced in the current net-next cycle). The last patch is by Aswath Govindraju and adds power-domains to the Bosch m_can DT binding documentation. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9c0532f9cc
|
@ -104,6 +104,12 @@ properties:
|
||||||
maximum: 32
|
maximum: 32
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
description:
|
||||||
|
Power domain provider node and an args specifier containing
|
||||||
|
the can device id value.
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
can-transceiver:
|
can-transceiver:
|
||||||
$ref: can-transceiver.yaml#
|
$ref: can-transceiver.yaml#
|
||||||
|
|
||||||
|
|
|
@ -649,7 +649,7 @@ static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv)
|
||||||
|
|
||||||
static int flexcan_clks_enable(const struct flexcan_priv *priv)
|
static int flexcan_clks_enable(const struct flexcan_priv *priv)
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
|
|
||||||
if (priv->clk_ipg) {
|
if (priv->clk_ipg) {
|
||||||
err = clk_prepare_enable(priv->clk_ipg);
|
err = clk_prepare_enable(priv->clk_ipg);
|
||||||
|
|
|
@ -78,11 +78,20 @@ enum {
|
||||||
enum {
|
enum {
|
||||||
J1939_NLA_PAD,
|
J1939_NLA_PAD,
|
||||||
J1939_NLA_BYTES_ACKED,
|
J1939_NLA_BYTES_ACKED,
|
||||||
|
J1939_NLA_TOTAL_SIZE,
|
||||||
|
J1939_NLA_PGN,
|
||||||
|
J1939_NLA_SRC_NAME,
|
||||||
|
J1939_NLA_DEST_NAME,
|
||||||
|
J1939_NLA_SRC_ADDR,
|
||||||
|
J1939_NLA_DEST_ADDR,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
J1939_EE_INFO_NONE,
|
J1939_EE_INFO_NONE,
|
||||||
J1939_EE_INFO_TX_ABORT,
|
J1939_EE_INFO_TX_ABORT,
|
||||||
|
J1939_EE_INFO_RX_RTS,
|
||||||
|
J1939_EE_INFO_RX_DPO,
|
||||||
|
J1939_EE_INFO_RX_ABORT,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct j1939_filter {
|
struct j1939_filter {
|
||||||
|
|
|
@ -20,9 +20,12 @@
|
||||||
|
|
||||||
struct j1939_session;
|
struct j1939_session;
|
||||||
enum j1939_sk_errqueue_type {
|
enum j1939_sk_errqueue_type {
|
||||||
J1939_ERRQUEUE_ACK,
|
J1939_ERRQUEUE_TX_ACK,
|
||||||
J1939_ERRQUEUE_SCHED,
|
J1939_ERRQUEUE_TX_SCHED,
|
||||||
J1939_ERRQUEUE_ABORT,
|
J1939_ERRQUEUE_TX_ABORT,
|
||||||
|
J1939_ERRQUEUE_RX_RTS,
|
||||||
|
J1939_ERRQUEUE_RX_DPO,
|
||||||
|
J1939_ERRQUEUE_RX_ABORT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* j1939 devices */
|
/* j1939 devices */
|
||||||
|
@ -87,6 +90,7 @@ struct j1939_priv {
|
||||||
struct list_head j1939_socks;
|
struct list_head j1939_socks;
|
||||||
|
|
||||||
struct kref rx_kref;
|
struct kref rx_kref;
|
||||||
|
u32 rx_tskey;
|
||||||
};
|
};
|
||||||
|
|
||||||
void j1939_ecu_put(struct j1939_ecu *ecu);
|
void j1939_ecu_put(struct j1939_ecu *ecu);
|
||||||
|
|
|
@ -905,20 +905,33 @@ failure:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t j1939_sk_opt_stats_get_size(void)
|
static size_t j1939_sk_opt_stats_get_size(enum j1939_sk_errqueue_type type)
|
||||||
{
|
{
|
||||||
return
|
switch (type) {
|
||||||
nla_total_size(sizeof(u32)) + /* J1939_NLA_BYTES_ACKED */
|
case J1939_ERRQUEUE_RX_RTS:
|
||||||
0;
|
return
|
||||||
|
nla_total_size(sizeof(u32)) + /* J1939_NLA_TOTAL_SIZE */
|
||||||
|
nla_total_size(sizeof(u32)) + /* J1939_NLA_PGN */
|
||||||
|
nla_total_size(sizeof(u64)) + /* J1939_NLA_SRC_NAME */
|
||||||
|
nla_total_size(sizeof(u64)) + /* J1939_NLA_DEST_NAME */
|
||||||
|
nla_total_size(sizeof(u8)) + /* J1939_NLA_SRC_ADDR */
|
||||||
|
nla_total_size(sizeof(u8)) + /* J1939_NLA_DEST_ADDR */
|
||||||
|
0;
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
nla_total_size(sizeof(u32)) + /* J1939_NLA_BYTES_ACKED */
|
||||||
|
0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct sk_buff *
|
static struct sk_buff *
|
||||||
j1939_sk_get_timestamping_opt_stats(struct j1939_session *session)
|
j1939_sk_get_timestamping_opt_stats(struct j1939_session *session,
|
||||||
|
enum j1939_sk_errqueue_type type)
|
||||||
{
|
{
|
||||||
struct sk_buff *stats;
|
struct sk_buff *stats;
|
||||||
u32 size;
|
u32 size;
|
||||||
|
|
||||||
stats = alloc_skb(j1939_sk_opt_stats_get_size(), GFP_ATOMIC);
|
stats = alloc_skb(j1939_sk_opt_stats_get_size(type), GFP_ATOMIC);
|
||||||
if (!stats)
|
if (!stats)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -928,32 +941,67 @@ j1939_sk_get_timestamping_opt_stats(struct j1939_session *session)
|
||||||
size = min(session->pkt.tx_acked * 7,
|
size = min(session->pkt.tx_acked * 7,
|
||||||
session->total_message_size);
|
session->total_message_size);
|
||||||
|
|
||||||
nla_put_u32(stats, J1939_NLA_BYTES_ACKED, size);
|
switch (type) {
|
||||||
|
case J1939_ERRQUEUE_RX_RTS:
|
||||||
|
nla_put_u32(stats, J1939_NLA_TOTAL_SIZE,
|
||||||
|
session->total_message_size);
|
||||||
|
nla_put_u32(stats, J1939_NLA_PGN,
|
||||||
|
session->skcb.addr.pgn);
|
||||||
|
nla_put_u64_64bit(stats, J1939_NLA_SRC_NAME,
|
||||||
|
session->skcb.addr.src_name, J1939_NLA_PAD);
|
||||||
|
nla_put_u64_64bit(stats, J1939_NLA_DEST_NAME,
|
||||||
|
session->skcb.addr.dst_name, J1939_NLA_PAD);
|
||||||
|
nla_put_u8(stats, J1939_NLA_SRC_ADDR,
|
||||||
|
session->skcb.addr.sa);
|
||||||
|
nla_put_u8(stats, J1939_NLA_DEST_ADDR,
|
||||||
|
session->skcb.addr.da);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
nla_put_u32(stats, J1939_NLA_BYTES_ACKED, size);
|
||||||
|
}
|
||||||
|
|
||||||
return stats;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
void j1939_sk_errqueue(struct j1939_session *session,
|
static void __j1939_sk_errqueue(struct j1939_session *session, struct sock *sk,
|
||||||
enum j1939_sk_errqueue_type type)
|
enum j1939_sk_errqueue_type type)
|
||||||
{
|
{
|
||||||
struct j1939_priv *priv = session->priv;
|
struct j1939_priv *priv = session->priv;
|
||||||
struct sock *sk = session->sk;
|
|
||||||
struct j1939_sock *jsk;
|
struct j1939_sock *jsk;
|
||||||
struct sock_exterr_skb *serr;
|
struct sock_exterr_skb *serr;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
char *state = "UNK";
|
char *state = "UNK";
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* currently we have no sk for the RX session */
|
|
||||||
if (!sk)
|
|
||||||
return;
|
|
||||||
|
|
||||||
jsk = j1939_sk(sk);
|
jsk = j1939_sk(sk);
|
||||||
|
|
||||||
if (!(jsk->state & J1939_SOCK_ERRQUEUE))
|
if (!(jsk->state & J1939_SOCK_ERRQUEUE))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
skb = j1939_sk_get_timestamping_opt_stats(session);
|
switch (type) {
|
||||||
|
case J1939_ERRQUEUE_TX_ACK:
|
||||||
|
if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK))
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case J1939_ERRQUEUE_TX_SCHED:
|
||||||
|
if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED))
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
case J1939_ERRQUEUE_TX_ABORT:
|
||||||
|
break;
|
||||||
|
case J1939_ERRQUEUE_RX_RTS:
|
||||||
|
fallthrough;
|
||||||
|
case J1939_ERRQUEUE_RX_DPO:
|
||||||
|
fallthrough;
|
||||||
|
case J1939_ERRQUEUE_RX_ABORT:
|
||||||
|
if (!(sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE))
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
netdev_err(priv->ndev, "Unknown errqueue type %i\n", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
skb = j1939_sk_get_timestamping_opt_stats(session, type);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -964,36 +1012,42 @@ void j1939_sk_errqueue(struct j1939_session *session,
|
||||||
serr = SKB_EXT_ERR(skb);
|
serr = SKB_EXT_ERR(skb);
|
||||||
memset(serr, 0, sizeof(*serr));
|
memset(serr, 0, sizeof(*serr));
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case J1939_ERRQUEUE_ACK:
|
case J1939_ERRQUEUE_TX_ACK:
|
||||||
if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK)) {
|
|
||||||
kfree_skb(skb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
serr->ee.ee_errno = ENOMSG;
|
serr->ee.ee_errno = ENOMSG;
|
||||||
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
|
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
|
||||||
serr->ee.ee_info = SCM_TSTAMP_ACK;
|
serr->ee.ee_info = SCM_TSTAMP_ACK;
|
||||||
state = "ACK";
|
state = "TX ACK";
|
||||||
break;
|
break;
|
||||||
case J1939_ERRQUEUE_SCHED:
|
case J1939_ERRQUEUE_TX_SCHED:
|
||||||
if (!(sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED)) {
|
|
||||||
kfree_skb(skb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
serr->ee.ee_errno = ENOMSG;
|
serr->ee.ee_errno = ENOMSG;
|
||||||
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
|
serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING;
|
||||||
serr->ee.ee_info = SCM_TSTAMP_SCHED;
|
serr->ee.ee_info = SCM_TSTAMP_SCHED;
|
||||||
state = "SCH";
|
state = "TX SCH";
|
||||||
break;
|
break;
|
||||||
case J1939_ERRQUEUE_ABORT:
|
case J1939_ERRQUEUE_TX_ABORT:
|
||||||
serr->ee.ee_errno = session->err;
|
serr->ee.ee_errno = session->err;
|
||||||
serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
|
serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
|
||||||
serr->ee.ee_info = J1939_EE_INFO_TX_ABORT;
|
serr->ee.ee_info = J1939_EE_INFO_TX_ABORT;
|
||||||
state = "ABT";
|
state = "TX ABT";
|
||||||
|
break;
|
||||||
|
case J1939_ERRQUEUE_RX_RTS:
|
||||||
|
serr->ee.ee_errno = ENOMSG;
|
||||||
|
serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
|
||||||
|
serr->ee.ee_info = J1939_EE_INFO_RX_RTS;
|
||||||
|
state = "RX RTS";
|
||||||
|
break;
|
||||||
|
case J1939_ERRQUEUE_RX_DPO:
|
||||||
|
serr->ee.ee_errno = ENOMSG;
|
||||||
|
serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
|
||||||
|
serr->ee.ee_info = J1939_EE_INFO_RX_DPO;
|
||||||
|
state = "RX DPO";
|
||||||
|
break;
|
||||||
|
case J1939_ERRQUEUE_RX_ABORT:
|
||||||
|
serr->ee.ee_errno = session->err;
|
||||||
|
serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
|
||||||
|
serr->ee.ee_info = J1939_EE_INFO_RX_ABORT;
|
||||||
|
state = "RX ABT";
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
netdev_err(priv->ndev, "Unknown errqueue type %i\n", type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serr->opt_stats = true;
|
serr->opt_stats = true;
|
||||||
|
@ -1008,6 +1062,27 @@ void j1939_sk_errqueue(struct j1939_session *session,
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void j1939_sk_errqueue(struct j1939_session *session,
|
||||||
|
enum j1939_sk_errqueue_type type)
|
||||||
|
{
|
||||||
|
struct j1939_priv *priv = session->priv;
|
||||||
|
struct j1939_sock *jsk;
|
||||||
|
|
||||||
|
if (session->sk) {
|
||||||
|
/* send TX notifications to the socket of origin */
|
||||||
|
__j1939_sk_errqueue(session, session->sk, type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* spread RX notifications to all sockets subscribed to this session */
|
||||||
|
spin_lock_bh(&priv->j1939_socks_lock);
|
||||||
|
list_for_each_entry(jsk, &priv->j1939_socks, list) {
|
||||||
|
if (j1939_sk_recv_match_one(jsk, &session->skcb))
|
||||||
|
__j1939_sk_errqueue(session, &jsk->sk, type);
|
||||||
|
}
|
||||||
|
spin_unlock_bh(&priv->j1939_socks_lock);
|
||||||
|
};
|
||||||
|
|
||||||
void j1939_sk_send_loop_abort(struct sock *sk, int err)
|
void j1939_sk_send_loop_abort(struct sock *sk, int err)
|
||||||
{
|
{
|
||||||
sk->sk_err = err;
|
sk->sk_err = err;
|
||||||
|
|
|
@ -260,10 +260,14 @@ static void __j1939_session_drop(struct j1939_session *session)
|
||||||
|
|
||||||
static void j1939_session_destroy(struct j1939_session *session)
|
static void j1939_session_destroy(struct j1939_session *session)
|
||||||
{
|
{
|
||||||
if (session->err)
|
if (session->transmission) {
|
||||||
j1939_sk_errqueue(session, J1939_ERRQUEUE_ABORT);
|
if (session->err)
|
||||||
else
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_TX_ABORT);
|
||||||
j1939_sk_errqueue(session, J1939_ERRQUEUE_ACK);
|
else
|
||||||
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_TX_ACK);
|
||||||
|
} else if (session->err) {
|
||||||
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_ABORT);
|
||||||
|
}
|
||||||
|
|
||||||
netdev_dbg(session->priv->ndev, "%s: 0x%p\n", __func__, session);
|
netdev_dbg(session->priv->ndev, "%s: 0x%p\n", __func__, session);
|
||||||
|
|
||||||
|
@ -822,7 +826,7 @@ static int j1939_session_tx_dat(struct j1939_session *session)
|
||||||
memcpy(&dat[1], &tpdat[offset], len);
|
memcpy(&dat[1], &tpdat[offset], len);
|
||||||
ret = j1939_tp_tx_dat(session, dat, len + 1);
|
ret = j1939_tp_tx_dat(session, dat, len + 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
/* ENOBUS == CAN interface TX queue is full */
|
/* ENOBUFS == CAN interface TX queue is full */
|
||||||
if (ret != -ENOBUFS)
|
if (ret != -ENOBUFS)
|
||||||
netdev_alert(priv->ndev,
|
netdev_alert(priv->ndev,
|
||||||
"%s: 0x%p: queue data error: %i\n",
|
"%s: 0x%p: queue data error: %i\n",
|
||||||
|
@ -1044,7 +1048,7 @@ static int j1939_simple_txnext(struct j1939_session *session)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_free;
|
goto out_free;
|
||||||
|
|
||||||
j1939_sk_errqueue(session, J1939_ERRQUEUE_SCHED);
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_TX_SCHED);
|
||||||
j1939_sk_queue_activate_next(session);
|
j1939_sk_queue_activate_next(session);
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -1116,6 +1120,8 @@ static void __j1939_session_cancel(struct j1939_session *session,
|
||||||
|
|
||||||
if (session->sk)
|
if (session->sk)
|
||||||
j1939_sk_send_loop_abort(session->sk, session->err);
|
j1939_sk_send_loop_abort(session->sk, session->err);
|
||||||
|
else
|
||||||
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void j1939_session_cancel(struct j1939_session *session,
|
static void j1939_session_cancel(struct j1939_session *session,
|
||||||
|
@ -1330,6 +1336,8 @@ static void j1939_xtp_rx_abort_one(struct j1939_priv *priv, struct sk_buff *skb,
|
||||||
session->err = j1939_xtp_abort_to_errno(priv, abort);
|
session->err = j1939_xtp_abort_to_errno(priv, abort);
|
||||||
if (session->sk)
|
if (session->sk)
|
||||||
j1939_sk_send_loop_abort(session->sk, session->err);
|
j1939_sk_send_loop_abort(session->sk, session->err);
|
||||||
|
else
|
||||||
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_ABORT);
|
||||||
j1939_session_deactivate_activate_next(session);
|
j1939_session_deactivate_activate_next(session);
|
||||||
|
|
||||||
abort_put:
|
abort_put:
|
||||||
|
@ -1438,7 +1446,7 @@ j1939_xtp_rx_cts_one(struct j1939_session *session, struct sk_buff *skb)
|
||||||
if (session->transmission) {
|
if (session->transmission) {
|
||||||
if (session->pkt.tx_acked)
|
if (session->pkt.tx_acked)
|
||||||
j1939_sk_errqueue(session,
|
j1939_sk_errqueue(session,
|
||||||
J1939_ERRQUEUE_SCHED);
|
J1939_ERRQUEUE_TX_SCHED);
|
||||||
j1939_session_txtimer_cancel(session);
|
j1939_session_txtimer_cancel(session);
|
||||||
j1939_tp_schedule_txtimer(session, 0);
|
j1939_tp_schedule_txtimer(session, 0);
|
||||||
}
|
}
|
||||||
|
@ -1630,6 +1638,9 @@ j1939_session *j1939_xtp_rx_rts_session_new(struct j1939_priv *priv,
|
||||||
session->pkt.rx = 0;
|
session->pkt.rx = 0;
|
||||||
session->pkt.tx = 0;
|
session->pkt.tx = 0;
|
||||||
|
|
||||||
|
session->tskey = priv->rx_tskey++;
|
||||||
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_RTS);
|
||||||
|
|
||||||
WARN_ON_ONCE(j1939_session_activate(session));
|
WARN_ON_ONCE(j1939_session_activate(session));
|
||||||
|
|
||||||
return session;
|
return session;
|
||||||
|
@ -1752,6 +1763,9 @@ static void j1939_xtp_rx_dpo_one(struct j1939_session *session,
|
||||||
session->pkt.dpo = j1939_etp_ctl_to_packet(skb->data);
|
session->pkt.dpo = j1939_etp_ctl_to_packet(skb->data);
|
||||||
session->last_cmd = dat[0];
|
session->last_cmd = dat[0];
|
||||||
j1939_tp_set_rxtimeout(session, 750);
|
j1939_tp_set_rxtimeout(session, 750);
|
||||||
|
|
||||||
|
if (!session->transmission)
|
||||||
|
j1939_sk_errqueue(session, J1939_ERRQUEUE_RX_DPO);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void j1939_xtp_rx_dpo(struct j1939_priv *priv, struct sk_buff *skb,
|
static void j1939_xtp_rx_dpo(struct j1939_priv *priv, struct sk_buff *skb,
|
||||||
|
|
Loading…
Reference in New Issue