Skip to content

Commit

Permalink
Merge tag 'linux-can-fixes-for-5.10-20201127' of git://git.kernel.org…
Browse files Browse the repository at this point in the history
…/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2020-11-27

The first patch is by me and target the gs_usb driver and fixes the endianess
problem with candleLight firmware.

Another patch by me for the mcp251xfd driver add sanity checking to bail out if
no IRQ is configured.

The next three patches target the m_can driver. A patch by me removes the
hardcoded IRQF_TRIGGER_FALLING from the request_threaded_irq() as this clashes
with the trigger level specified in the DT. Further a patch by me fixes the
nominal bitiming tseg2 min value for modern m_can cores. Pankaj Sharma's patch
add support for cores version 3.3.x.

The last patch by Oliver Hartkopp is for af_can and converts a WARN() into a
pr_warn(), which is triggered by the syzkaller. It was able to create a
situation where the closing of a socket runs simultaneously to the notifier
call chain for removing the CAN network device in use.

* tag 'linux-can-fixes-for-5.10-20201127' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: af_can: can_rx_unregister(): remove WARN() statement from list operation sanity check
  can: m_can: m_can_dev_setup(): add support for bosch mcan version 3.3.0
  can: m_can: fix nominal bitiming tseg2 min for version >= 3.1
  can: m_can: m_can_open(): remove IRQF_TRIGGER_FALLING from request_threaded_irq()'s flags
  can: mcp251xfd: mcp251xfd_probe(): bail out if no IRQ was given
  can: gs_usb: fix endianess problem with candleLight firmware
====================

Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
kuba-moo committed Nov 27, 2020
2 parents 985f733 + d73ff9b commit d0742c4
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 65 deletions.
6 changes: 4 additions & 2 deletions drivers/net/can/m_can/m_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@ static const struct can_bittiming_const m_can_bittiming_const_31X = {
.name = KBUILD_MODNAME,
.tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */
.tseg1_max = 256,
.tseg2_min = 1, /* Time segment 2 = phase_seg2 */
.tseg2_min = 2, /* Time segment 2 = phase_seg2 */
.tseg2_max = 128,
.sjw_max = 128,
.brp_min = 1,
Expand Down Expand Up @@ -1385,6 +1385,8 @@ static int m_can_dev_setup(struct m_can_classdev *m_can_dev)
&m_can_data_bittiming_const_31X;
break;
case 32:
case 33:
/* Support both MCAN version v3.2.x and v3.3.0 */
m_can_dev->can.bittiming_const = m_can_dev->bit_timing ?
m_can_dev->bit_timing : &m_can_bittiming_const_31X;

Expand Down Expand Up @@ -1653,7 +1655,7 @@ static int m_can_open(struct net_device *dev)
INIT_WORK(&cdev->tx_work, m_can_tx_work_queue);

err = request_threaded_irq(dev->irq, NULL, m_can_isr,
IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
IRQF_ONESHOT,
dev->name, dev);
} else {
err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name,
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2738,6 +2738,10 @@ static int mcp251xfd_probe(struct spi_device *spi)
u32 freq;
int err;

if (!spi->irq)
return dev_err_probe(&spi->dev, -ENXIO,
"No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n");

rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int",
GPIOD_IN);
if (PTR_ERR(rx_int) == -EPROBE_DEFER)
Expand Down
131 changes: 70 additions & 61 deletions drivers/net/can/usb/gs_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,27 @@ enum gs_can_identify_mode {
};

/* data types passed between host and device */

/* The firmware on the original USB2CAN by Geschwister Schneider
* Technologie Entwicklungs- und Vertriebs UG exchanges all data
* between the host and the device in host byte order. This is done
* with the struct gs_host_config::byte_order member, which is sent
* first to indicate the desired byte order.
*
* The widely used open source firmware candleLight doesn't support
* this feature and exchanges the data in little endian byte order.
*/
struct gs_host_config {
u32 byte_order;
__le32 byte_order;
} __packed;
/* All data exchanged between host and device is exchanged in host byte order,
* thanks to the struct gs_host_config byte_order member, which is sent first
* to indicate the desired byte order.
*/

struct gs_device_config {
u8 reserved1;
u8 reserved2;
u8 reserved3;
u8 icount;
u32 sw_version;
u32 hw_version;
__le32 sw_version;
__le32 hw_version;
} __packed;

#define GS_CAN_MODE_NORMAL 0
Expand All @@ -87,26 +93,26 @@ struct gs_device_config {
#define GS_CAN_MODE_ONE_SHOT BIT(3)

struct gs_device_mode {
u32 mode;
u32 flags;
__le32 mode;
__le32 flags;
} __packed;

struct gs_device_state {
u32 state;
u32 rxerr;
u32 txerr;
__le32 state;
__le32 rxerr;
__le32 txerr;
} __packed;

struct gs_device_bittiming {
u32 prop_seg;
u32 phase_seg1;
u32 phase_seg2;
u32 sjw;
u32 brp;
__le32 prop_seg;
__le32 phase_seg1;
__le32 phase_seg2;
__le32 sjw;
__le32 brp;
} __packed;

struct gs_identify_mode {
u32 mode;
__le32 mode;
} __packed;

#define GS_CAN_FEATURE_LISTEN_ONLY BIT(0)
Expand All @@ -117,23 +123,23 @@ struct gs_identify_mode {
#define GS_CAN_FEATURE_IDENTIFY BIT(5)

struct gs_device_bt_const {
u32 feature;
u32 fclk_can;
u32 tseg1_min;
u32 tseg1_max;
u32 tseg2_min;
u32 tseg2_max;
u32 sjw_max;
u32 brp_min;
u32 brp_max;
u32 brp_inc;
__le32 feature;
__le32 fclk_can;
__le32 tseg1_min;
__le32 tseg1_max;
__le32 tseg2_min;
__le32 tseg2_max;
__le32 sjw_max;
__le32 brp_min;
__le32 brp_max;
__le32 brp_inc;
} __packed;

#define GS_CAN_FLAG_OVERFLOW 1

struct gs_host_frame {
u32 echo_id;
u32 can_id;
__le32 can_id;

u8 can_dlc;
u8 channel;
Expand Down Expand Up @@ -329,13 +335,13 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
if (!skb)
return;

cf->can_id = hf->can_id;
cf->can_id = le32_to_cpu(hf->can_id);

cf->can_dlc = get_can_dlc(hf->can_dlc);
memcpy(cf->data, hf->data, 8);

/* ERROR frames tell us information about the controller */
if (hf->can_id & CAN_ERR_FLAG)
if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG)
gs_update_state(dev, cf);

netdev->stats.rx_packets++;
Expand Down Expand Up @@ -418,11 +424,11 @@ static int gs_usb_set_bittiming(struct net_device *netdev)
if (!dbt)
return -ENOMEM;

dbt->prop_seg = bt->prop_seg;
dbt->phase_seg1 = bt->phase_seg1;
dbt->phase_seg2 = bt->phase_seg2;
dbt->sjw = bt->sjw;
dbt->brp = bt->brp;
dbt->prop_seg = cpu_to_le32(bt->prop_seg);
dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1);
dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2);
dbt->sjw = cpu_to_le32(bt->sjw);
dbt->brp = cpu_to_le32(bt->brp);

/* request bit timings */
rc = usb_control_msg(interface_to_usbdev(intf),
Expand Down Expand Up @@ -503,7 +509,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,

cf = (struct can_frame *)skb->data;

hf->can_id = cf->can_id;
hf->can_id = cpu_to_le32(cf->can_id);
hf->can_dlc = cf->can_dlc;
memcpy(hf->data, cf->data, cf->can_dlc);

Expand Down Expand Up @@ -573,6 +579,7 @@ static int gs_can_open(struct net_device *netdev)
int rc, i;
struct gs_device_mode *dm;
u32 ctrlmode;
u32 flags = 0;

rc = open_candev(netdev);
if (rc)
Expand Down Expand Up @@ -640,24 +647,24 @@ static int gs_can_open(struct net_device *netdev)

/* flags */
ctrlmode = dev->can.ctrlmode;
dm->flags = 0;

if (ctrlmode & CAN_CTRLMODE_LOOPBACK)
dm->flags |= GS_CAN_MODE_LOOP_BACK;
flags |= GS_CAN_MODE_LOOP_BACK;
else if (ctrlmode & CAN_CTRLMODE_LISTENONLY)
dm->flags |= GS_CAN_MODE_LISTEN_ONLY;
flags |= GS_CAN_MODE_LISTEN_ONLY;

/* Controller is not allowed to retry TX
* this mode is unavailable on atmels uc3c hardware
*/
if (ctrlmode & CAN_CTRLMODE_ONE_SHOT)
dm->flags |= GS_CAN_MODE_ONE_SHOT;
flags |= GS_CAN_MODE_ONE_SHOT;

if (ctrlmode & CAN_CTRLMODE_3_SAMPLES)
dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE;
flags |= GS_CAN_MODE_TRIPLE_SAMPLE;

/* finally start device */
dm->mode = GS_CAN_MODE_START;
dm->mode = cpu_to_le32(GS_CAN_MODE_START);
dm->flags = cpu_to_le32(flags);
rc = usb_control_msg(interface_to_usbdev(dev->iface),
usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0),
GS_USB_BREQ_MODE,
Expand Down Expand Up @@ -737,9 +744,9 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
return -ENOMEM;

if (do_identify)
imode->mode = GS_CAN_IDENTIFY_ON;
imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON);
else
imode->mode = GS_CAN_IDENTIFY_OFF;
imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF);

rc = usb_control_msg(interface_to_usbdev(dev->iface),
usb_sndctrlpipe(interface_to_usbdev(dev->iface),
Expand Down Expand Up @@ -790,6 +797,7 @@ static struct gs_can *gs_make_candev(unsigned int channel,
struct net_device *netdev;
int rc;
struct gs_device_bt_const *bt_const;
u32 feature;

bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL);
if (!bt_const)
Expand Down Expand Up @@ -830,14 +838,14 @@ static struct gs_can *gs_make_candev(unsigned int channel,

/* dev setup */
strcpy(dev->bt_const.name, "gs_usb");
dev->bt_const.tseg1_min = bt_const->tseg1_min;
dev->bt_const.tseg1_max = bt_const->tseg1_max;
dev->bt_const.tseg2_min = bt_const->tseg2_min;
dev->bt_const.tseg2_max = bt_const->tseg2_max;
dev->bt_const.sjw_max = bt_const->sjw_max;
dev->bt_const.brp_min = bt_const->brp_min;
dev->bt_const.brp_max = bt_const->brp_max;
dev->bt_const.brp_inc = bt_const->brp_inc;
dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min);
dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max);
dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min);
dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max);
dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max);
dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min);
dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max);
dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc);

dev->udev = interface_to_usbdev(intf);
dev->iface = intf;
Expand All @@ -854,28 +862,29 @@ static struct gs_can *gs_make_candev(unsigned int channel,

/* can setup */
dev->can.state = CAN_STATE_STOPPED;
dev->can.clock.freq = bt_const->fclk_can;
dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can);
dev->can.bittiming_const = &dev->bt_const;
dev->can.do_set_bittiming = gs_usb_set_bittiming;

dev->can.ctrlmode_supported = 0;

if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY)
feature = le32_to_cpu(bt_const->feature);
if (feature & GS_CAN_FEATURE_LISTEN_ONLY)
dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;

if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK)
if (feature & GS_CAN_FEATURE_LOOP_BACK)
dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK;

if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE)
dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;

if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT)
if (feature & GS_CAN_FEATURE_ONE_SHOT)
dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT;

SET_NETDEV_DEV(netdev, &intf->dev);

if (dconf->sw_version > 1)
if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY)
if (le32_to_cpu(dconf->sw_version) > 1)
if (feature & GS_CAN_FEATURE_IDENTIFY)
netdev->ethtool_ops = &gs_usb_ethtool_ops;

kfree(bt_const);
Expand Down Expand Up @@ -910,7 +919,7 @@ static int gs_usb_probe(struct usb_interface *intf,
if (!hconf)
return -ENOMEM;

hconf->byte_order = 0x0000beef;
hconf->byte_order = cpu_to_le32(0x0000beef);

/* send host config */
rc = usb_control_msg(interface_to_usbdev(intf),
Expand Down
7 changes: 5 additions & 2 deletions net/can/af_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,10 +541,13 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id,

/* Check for bugs in CAN protocol implementations using af_can.c:
* 'rcv' will be NULL if no matching list item was found for removal.
* As this case may potentially happen when closing a socket while
* the notifier for removing the CAN netdev is running we just print
* a warning here.
*/
if (!rcv) {
WARN(1, "BUG: receive list entry not found for dev %s, id %03X, mask %03X\n",
DNAME(dev), can_id, mask);
pr_warn("can: receive list entry not found for dev %s, id %03X, mask %03X\n",
DNAME(dev), can_id, mask);
goto out;
}

Expand Down

0 comments on commit d0742c4

Please sign in to comment.