mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 14:44:10 +08:00
linux-can-next-for-5.12-20210127
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmARLD8THG1rbEBwZW5n dXRyb25peC5kZQAKCRCpyVqK+u3vqdlXB/48nQ5I+Z1wnhPvbtvyH4tk9XSbJaTt 4HH+i3R5RUAzHcOmfm2PQHe9/DxiogOQAFv9Lo0t7HN449bM3LMHrhTCcJIrIRf9 VxFSk4H97wjHR0Zj6TlEe++CTUPUalCpkCluERwqYP9WXRRklXL1mju+WNKnMMl0 9fl4CvQDWjB2wNXXoZ1SVuoFxyeqiKQHJy9n3Wez8sQTIlguOZvm8glDQlyb4v+q rSxpCUrlpOVv6/11NqxQ7CfGdfTgLUi1a4greriwf1PjEXvDArXMjpDG3bo0kbgy 7Iv0U9GsvtzOPB+6XKxEFeYTKFaixyLugYBAadfvs0lVEIFP1mtlYvQs =pHI/ -----END PGP SIGNATURE----- Merge tag 'linux-can-next-for-5.12-20210127' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next Marc Kleine-Budde says: ==================== pull-request: can-next 2021-01-27 The first two patches are by me and fix typos on the CAN gw protocol and the flexcan driver. The next patch is by Vincent Mailhol and targets the CAN driver infrastructure, it exports the function that converts the CAN state into a human readable string. A patch by me, which target the CAN driver infrastructure, too, makes the calculation in can_fd_len2dlc() more readable. A patch by Tom Rix fixes a checkpatch warning in the mcba_usb driver. The next seven patches target the mcp251xfd driver. Su Yanjun's patch replaces several hardcoded assumptions when calling regmap, by using regmap_get_val_bytes(). The remaining patches are by me. First an open coded check is replaced by an existing helper function, then in the TX path the padding for CAN-FD frames is cleaned up. The next two patches clean up the RTR frame handling in the RX and TX path. Then support for len8_dlc is added. The last patch adds BQL support. * tag 'linux-can-next-for-5.12-20210127' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next: can: mcp251xfd: add BQL support can: mcp251xfd: add len8_dlc support can: mcp251xfd: mcp251xfd_tx_obj_from_skb(): don't copy data for RTR CAN frames in TX-path can: mcp251xfd: mcp251xfd_hw_rx_obj_to_skb(): don't copy data for RTR CAN frames in RX-path can: mcp251xfd: mcp251xfd_tx_obj_from_skb(): clean up padding of CAN-FD frames can: mcp251xfd: mcp251xfd_start_xmit(): use mcp251xfd_get_tx_free() to check TX is is full can: mcp251xfd: replace sizeof(u32) with val_bytes in regmap can: mcba_usb: remove h from printk format specifier can: length: can_fd_len2dlc(): make legnth calculation readable again can: dev: export can_get_state_str() function can: flexcan: fix typos can: gw: fix typo ==================== Link: https://lore.kernel.org/r/20210127092227.2775573-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
df9d80470a
@ -74,7 +74,7 @@ static int can_rx_state_to_frame(struct net_device *dev, enum can_state state)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *can_get_state_str(const enum can_state state)
|
||||
const char *can_get_state_str(const enum can_state state)
|
||||
{
|
||||
switch (state) {
|
||||
case CAN_STATE_ERROR_ACTIVE:
|
||||
@ -95,6 +95,7 @@ static const char *can_get_state_str(const enum can_state state)
|
||||
|
||||
return "<unknown>";
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(can_get_state_str);
|
||||
|
||||
void can_change_state(struct net_device *dev, struct can_frame *cf,
|
||||
enum can_state tx_state, enum can_state rx_state)
|
||||
|
@ -27,12 +27,17 @@ static const u8 len2dlc[] = {
|
||||
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
|
||||
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
|
||||
15, 15, 15, 15, 15, 15, 15, 15 /* 57 - 64 */
|
||||
};
|
||||
|
||||
/* map the sanitized data length to an appropriate data length code */
|
||||
u8 can_fd_len2dlc(u8 len)
|
||||
{
|
||||
if (len >= ARRAY_SIZE(len2dlc))
|
||||
/* check for length mapping table size at build time */
|
||||
BUILD_BUG_ON(ARRAY_SIZE(len2dlc) != CANFD_MAX_DLEN + 1);
|
||||
|
||||
if (unlikely(len > CANFD_MAX_DLEN))
|
||||
return CANFD_MAX_DLC;
|
||||
|
||||
return len2dlc[len];
|
||||
|
@ -1975,14 +1975,14 @@ static int flexcan_setup_stop_mode_scfw(struct platform_device *pdev)
|
||||
priv = netdev_priv(dev);
|
||||
priv->scu_idx = scu_idx;
|
||||
|
||||
/* this function could be defered probe, return -EPROBE_DEFER */
|
||||
/* this function could be deferred probe, return -EPROBE_DEFER */
|
||||
return imx_scu_get_handle(&priv->sc_ipc_handle);
|
||||
}
|
||||
|
||||
/* flexcan_setup_stop_mode - Setup stop mode for wakeup
|
||||
*
|
||||
* Return: = 0 setup stop mode successfully or doesn't support this feature
|
||||
* < 0 fail to setup stop mode (could be defered probe)
|
||||
* < 0 fail to setup stop mode (could be deferred probe)
|
||||
*/
|
||||
static int flexcan_setup_stop_mode(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -335,6 +335,8 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
|
||||
u8 len;
|
||||
int i, j;
|
||||
|
||||
netdev_reset_queue(priv->ndev);
|
||||
|
||||
/* TEF */
|
||||
tef_ring = priv->tef;
|
||||
tef_ring->head = 0;
|
||||
@ -1249,7 +1251,8 @@ mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
|
||||
|
||||
static int
|
||||
mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
|
||||
const struct mcp251xfd_hw_tef_obj *hw_tef_obj)
|
||||
const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
|
||||
unsigned int *frame_len_ptr)
|
||||
{
|
||||
struct net_device_stats *stats = &priv->ndev->stats;
|
||||
u32 seq, seq_masked, tef_tail_masked;
|
||||
@ -1271,7 +1274,8 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
|
||||
stats->tx_bytes +=
|
||||
can_rx_offload_get_echo_skb(&priv->offload,
|
||||
mcp251xfd_get_tef_tail(priv),
|
||||
hw_tef_obj->ts, NULL);
|
||||
hw_tef_obj->ts,
|
||||
frame_len_ptr);
|
||||
stats->tx_packets++;
|
||||
priv->tef->tail++;
|
||||
|
||||
@ -1308,6 +1312,7 @@ mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
|
||||
const u8 offset, const u8 len)
|
||||
{
|
||||
const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
|
||||
const int val_bytes = regmap_get_val_bytes(priv->map_rx);
|
||||
|
||||
if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
|
||||
(offset > tx_ring->obj_num ||
|
||||
@ -1322,12 +1327,13 @@ mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
|
||||
return regmap_bulk_read(priv->map_rx,
|
||||
mcp251xfd_get_tef_obj_addr(offset),
|
||||
hw_tef_obj,
|
||||
sizeof(*hw_tef_obj) / sizeof(u32) * len);
|
||||
sizeof(*hw_tef_obj) / val_bytes * len);
|
||||
}
|
||||
|
||||
static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
|
||||
{
|
||||
struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX];
|
||||
unsigned int total_frame_len = 0;
|
||||
u8 tef_tail, len, l;
|
||||
int err, i;
|
||||
|
||||
@ -1349,7 +1355,9 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i]);
|
||||
unsigned int frame_len;
|
||||
|
||||
err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
|
||||
/* -EAGAIN means the Sequence Number in the TEF
|
||||
* doesn't match our tef_tail. This can happen if we
|
||||
* read the TEF objects too early. Leave loop let the
|
||||
@ -1359,6 +1367,8 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
|
||||
goto out_netif_wake_queue;
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
total_frame_len += frame_len;
|
||||
}
|
||||
|
||||
out_netif_wake_queue:
|
||||
@ -1389,6 +1399,7 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
|
||||
return err;
|
||||
|
||||
tx_ring->tail += len;
|
||||
netdev_completed_queue(priv->ndev, len, total_frame_len);
|
||||
|
||||
err = mcp251xfd_check_tef_tail(priv);
|
||||
if (err)
|
||||
@ -1438,6 +1449,7 @@ mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
|
||||
u8 dlc;
|
||||
|
||||
if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) {
|
||||
u32 sid, eid;
|
||||
@ -1453,9 +1465,10 @@ mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
|
||||
hw_rx_obj->id);
|
||||
}
|
||||
|
||||
dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, hw_rx_obj->flags);
|
||||
|
||||
/* CANFD */
|
||||
if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) {
|
||||
u8 dlc;
|
||||
|
||||
if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI)
|
||||
cfd->flags |= CANFD_ESI;
|
||||
@ -1463,17 +1476,17 @@ mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
|
||||
if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS)
|
||||
cfd->flags |= CANFD_BRS;
|
||||
|
||||
dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, hw_rx_obj->flags);
|
||||
cfd->len = can_fd_dlc2len(dlc);
|
||||
} else {
|
||||
if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR)
|
||||
cfd->can_id |= CAN_RTR_FLAG;
|
||||
|
||||
cfd->len = can_cc_dlc2len(FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC,
|
||||
hw_rx_obj->flags));
|
||||
can_frame_set_cc_len((struct can_frame *)cfd, dlc,
|
||||
priv->can.ctrlmode);
|
||||
}
|
||||
|
||||
memcpy(cfd->data, hw_rx_obj->data, cfd->len);
|
||||
if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR))
|
||||
memcpy(cfd->data, hw_rx_obj->data, cfd->len);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1510,12 +1523,13 @@ mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv,
|
||||
struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
|
||||
const u8 offset, const u8 len)
|
||||
{
|
||||
const int val_bytes = regmap_get_val_bytes(priv->map_rx);
|
||||
int err;
|
||||
|
||||
err = regmap_bulk_read(priv->map_rx,
|
||||
mcp251xfd_get_rx_obj_addr(ring, offset),
|
||||
hw_rx_obj,
|
||||
len * ring->obj_size / sizeof(u32));
|
||||
len * ring->obj_size / val_bytes);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -2137,6 +2151,7 @@ static int mcp251xfd_handle_spicrcif(struct mcp251xfd_priv *priv)
|
||||
static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct mcp251xfd_priv *priv = dev_id;
|
||||
const int val_bytes = regmap_get_val_bytes(priv->map_reg);
|
||||
irqreturn_t handled = IRQ_NONE;
|
||||
int err;
|
||||
|
||||
@ -2162,7 +2177,7 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
|
||||
err = regmap_bulk_read(priv->map_reg, MCP251XFD_REG_INT,
|
||||
&priv->regs_status,
|
||||
sizeof(priv->regs_status) /
|
||||
sizeof(u32));
|
||||
val_bytes);
|
||||
if (err)
|
||||
goto out_fail;
|
||||
|
||||
@ -2300,7 +2315,7 @@ mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv,
|
||||
union mcp251xfd_tx_obj_load_buf *load_buf;
|
||||
u8 dlc;
|
||||
u32 id, flags;
|
||||
int offset, len;
|
||||
int len_sanitized = 0, len;
|
||||
|
||||
if (cfd->can_id & CAN_EFF_FLAG) {
|
||||
u32 sid, eid;
|
||||
@ -2321,12 +2336,12 @@ mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv,
|
||||
* harm, only the lower 7 bits will be transferred into the
|
||||
* TEF object.
|
||||
*/
|
||||
dlc = can_fd_len2dlc(cfd->len);
|
||||
flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq) |
|
||||
FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC, dlc);
|
||||
flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq);
|
||||
|
||||
if (cfd->can_id & CAN_RTR_FLAG)
|
||||
flags |= MCP251XFD_OBJ_FLAGS_RTR;
|
||||
else
|
||||
len_sanitized = canfd_sanitize_len(cfd->len);
|
||||
|
||||
/* CANFD */
|
||||
if (can_is_canfd_skb(skb)) {
|
||||
@ -2337,8 +2352,15 @@ mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv,
|
||||
|
||||
if (cfd->flags & CANFD_BRS)
|
||||
flags |= MCP251XFD_OBJ_FLAGS_BRS;
|
||||
|
||||
dlc = can_fd_len2dlc(cfd->len);
|
||||
} else {
|
||||
dlc = can_get_cc_dlc((struct can_frame *)cfd,
|
||||
priv->can.ctrlmode);
|
||||
}
|
||||
|
||||
flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC, dlc);
|
||||
|
||||
load_buf = &tx_obj->buf;
|
||||
if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
|
||||
hw_tx_obj = &load_buf->crc.hw_tx_obj;
|
||||
@ -2348,17 +2370,22 @@ mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv,
|
||||
put_unaligned_le32(id, &hw_tx_obj->id);
|
||||
put_unaligned_le32(flags, &hw_tx_obj->flags);
|
||||
|
||||
/* Clear data at end of CAN frame */
|
||||
offset = round_down(cfd->len, sizeof(u32));
|
||||
len = round_up(can_fd_dlc2len(dlc), sizeof(u32)) - offset;
|
||||
if (MCP251XFD_SANITIZE_CAN && len)
|
||||
memset(hw_tx_obj->data + offset, 0x0, len);
|
||||
/* Copy data */
|
||||
memcpy(hw_tx_obj->data, cfd->data, cfd->len);
|
||||
|
||||
/* Clear unused data at end of CAN frame */
|
||||
if (MCP251XFD_SANITIZE_CAN && len_sanitized) {
|
||||
int pad_len;
|
||||
|
||||
pad_len = len_sanitized - cfd->len;
|
||||
if (pad_len)
|
||||
memset(hw_tx_obj->data + cfd->len, 0x0, pad_len);
|
||||
}
|
||||
|
||||
/* Number of bytes to be written into the RAM of the controller */
|
||||
len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags);
|
||||
if (MCP251XFD_SANITIZE_CAN)
|
||||
len += round_up(can_fd_dlc2len(dlc), sizeof(u32));
|
||||
len += round_up(len_sanitized, sizeof(u32));
|
||||
else
|
||||
len += round_up(cfd->len, sizeof(u32));
|
||||
|
||||
@ -2418,6 +2445,7 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
|
||||
struct mcp251xfd_priv *priv = netdev_priv(ndev);
|
||||
struct mcp251xfd_tx_ring *tx_ring = priv->tx;
|
||||
struct mcp251xfd_tx_obj *tx_obj;
|
||||
unsigned int frame_len;
|
||||
u8 tx_head;
|
||||
int err;
|
||||
|
||||
@ -2433,10 +2461,12 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
|
||||
/* Stop queue if we occupy the complete TX FIFO */
|
||||
tx_head = mcp251xfd_get_tx_head(tx_ring);
|
||||
tx_ring->head++;
|
||||
if (tx_ring->head - tx_ring->tail >= tx_ring->obj_num)
|
||||
if (mcp251xfd_get_tx_free(tx_ring) == 0)
|
||||
netif_stop_queue(ndev);
|
||||
|
||||
can_put_echo_skb(skb, ndev, tx_head, 0);
|
||||
frame_len = can_skb_get_frame_len(skb);
|
||||
can_put_echo_skb(skb, ndev, tx_head, frame_len);
|
||||
netdev_sent_queue(priv->ndev, frame_len);
|
||||
|
||||
err = mcp251xfd_tx_obj_write(priv, tx_obj);
|
||||
if (err)
|
||||
@ -2885,7 +2915,8 @@ static int mcp251xfd_probe(struct spi_device *spi)
|
||||
priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const;
|
||||
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
|
||||
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
|
||||
CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO;
|
||||
CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
|
||||
CAN_CTRLMODE_CC_LEN8_DLC;
|
||||
priv->ndev = ndev;
|
||||
priv->spi = spi;
|
||||
priv->rx_int = rx_int;
|
||||
|
@ -466,7 +466,7 @@ static void mcba_usb_process_ka_usb(struct mcba_priv *priv,
|
||||
struct mcba_usb_msg_ka_usb *msg)
|
||||
{
|
||||
if (unlikely(priv->usb_ka_first_pass)) {
|
||||
netdev_info(priv->netdev, "PIC USB version %hhu.%hhu\n",
|
||||
netdev_info(priv->netdev, "PIC USB version %u.%u\n",
|
||||
msg->soft_ver_major, msg->soft_ver_minor);
|
||||
|
||||
priv->usb_ka_first_pass = false;
|
||||
@ -492,7 +492,7 @@ static void mcba_usb_process_ka_can(struct mcba_priv *priv,
|
||||
struct mcba_usb_msg_ka_can *msg)
|
||||
{
|
||||
if (unlikely(priv->can_ka_first_pass)) {
|
||||
netdev_info(priv->netdev, "PIC CAN version %hhu.%hhu\n",
|
||||
netdev_info(priv->netdev, "PIC CAN version %u.%u\n",
|
||||
msg->soft_ver_major, msg->soft_ver_minor);
|
||||
|
||||
priv->can_ka_first_pass = false;
|
||||
@ -554,7 +554,7 @@ static void mcba_usb_process_rx(struct mcba_priv *priv,
|
||||
break;
|
||||
|
||||
default:
|
||||
netdev_warn(priv->netdev, "Unsupported msg (0x%hhX)",
|
||||
netdev_warn(priv->netdev, "Unsupported msg (0x%X)",
|
||||
msg->cmd_id);
|
||||
break;
|
||||
}
|
||||
|
@ -123,6 +123,7 @@ 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);
|
||||
void can_change_state(struct net_device *dev, struct can_frame *cf,
|
||||
enum can_state tx_state, enum can_state rx_state);
|
||||
|
||||
|
@ -225,7 +225,7 @@ static void mod_store_ccdlc(struct canfd_frame *cf)
|
||||
if (ccf->len <= CAN_MAX_DLEN)
|
||||
return;
|
||||
|
||||
/* potentially broken values are catched in can_can_gw_rcv() */
|
||||
/* potentially broken values are caught in can_can_gw_rcv() */
|
||||
if (ccf->len > CAN_MAX_RAW_DLC)
|
||||
return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user