Commit 328e765c authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-fixes-for-5.17-20220225' of...

Merge tag 'linux-can-fixes-for-5.17-20220225' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2022-02-25

The first 2 patches are by Vincent Mailhol and fix the error handling
of the ndo_open callbacks of the etas_es58x and the gs_usb CAN USB
drivers.

The last patch is by Lad Prabhakar and fixes a small race condition in
the rcar_canfd's rcar_canfd_channel_probe() function.

* tag 'linux-can-fixes-for-5.17-20220225' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  can: rcar_canfd: rcar_canfd_channel_probe(): register the CAN device when fully ready
  can: gs_usb: change active_channels's type from atomic_t to u8
  can: etas_es58x: change opened_channel_cnt's type from atomic_t to u8
====================

Link: https://lore.kernel.org/r/20220225165622.3231809-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents e01b042e c5048a7b
...@@ -1715,15 +1715,15 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, ...@@ -1715,15 +1715,15 @@ static int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch,
netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll, netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll,
RCANFD_NAPI_WEIGHT); RCANFD_NAPI_WEIGHT);
spin_lock_init(&priv->tx_lock);
devm_can_led_init(ndev);
gpriv->ch[priv->channel] = priv;
err = register_candev(ndev); err = register_candev(ndev);
if (err) { if (err) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"register_candev() failed, error %d\n", err); "register_candev() failed, error %d\n", err);
goto fail_candev; goto fail_candev;
} }
spin_lock_init(&priv->tx_lock);
devm_can_led_init(ndev);
gpriv->ch[priv->channel] = priv;
dev_info(&pdev->dev, "device registered (channel %u)\n", priv->channel); dev_info(&pdev->dev, "device registered (channel %u)\n", priv->channel);
return 0; return 0;
......
...@@ -1787,7 +1787,7 @@ static int es58x_open(struct net_device *netdev) ...@@ -1787,7 +1787,7 @@ static int es58x_open(struct net_device *netdev)
struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev; struct es58x_device *es58x_dev = es58x_priv(netdev)->es58x_dev;
int ret; int ret;
if (atomic_inc_return(&es58x_dev->opened_channel_cnt) == 1) { if (!es58x_dev->opened_channel_cnt) {
ret = es58x_alloc_rx_urbs(es58x_dev); ret = es58x_alloc_rx_urbs(es58x_dev);
if (ret) if (ret)
return ret; return ret;
...@@ -1805,12 +1805,13 @@ static int es58x_open(struct net_device *netdev) ...@@ -1805,12 +1805,13 @@ static int es58x_open(struct net_device *netdev)
if (ret) if (ret)
goto free_urbs; goto free_urbs;
es58x_dev->opened_channel_cnt++;
netif_start_queue(netdev); netif_start_queue(netdev);
return ret; return ret;
free_urbs: free_urbs:
if (atomic_dec_and_test(&es58x_dev->opened_channel_cnt)) if (!es58x_dev->opened_channel_cnt)
es58x_free_urbs(es58x_dev); es58x_free_urbs(es58x_dev);
netdev_err(netdev, "%s: Could not open the network device: %pe\n", netdev_err(netdev, "%s: Could not open the network device: %pe\n",
__func__, ERR_PTR(ret)); __func__, ERR_PTR(ret));
...@@ -1845,7 +1846,8 @@ static int es58x_stop(struct net_device *netdev) ...@@ -1845,7 +1846,8 @@ static int es58x_stop(struct net_device *netdev)
es58x_flush_pending_tx_msg(netdev); es58x_flush_pending_tx_msg(netdev);
if (atomic_dec_and_test(&es58x_dev->opened_channel_cnt)) es58x_dev->opened_channel_cnt--;
if (!es58x_dev->opened_channel_cnt)
es58x_free_urbs(es58x_dev); es58x_free_urbs(es58x_dev);
return 0; return 0;
...@@ -2215,7 +2217,6 @@ static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf, ...@@ -2215,7 +2217,6 @@ static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf,
init_usb_anchor(&es58x_dev->tx_urbs_idle); init_usb_anchor(&es58x_dev->tx_urbs_idle);
init_usb_anchor(&es58x_dev->tx_urbs_busy); init_usb_anchor(&es58x_dev->tx_urbs_busy);
atomic_set(&es58x_dev->tx_urbs_idle_cnt, 0); atomic_set(&es58x_dev->tx_urbs_idle_cnt, 0);
atomic_set(&es58x_dev->opened_channel_cnt, 0);
usb_set_intfdata(intf, es58x_dev); usb_set_intfdata(intf, es58x_dev);
es58x_dev->rx_pipe = usb_rcvbulkpipe(es58x_dev->udev, es58x_dev->rx_pipe = usb_rcvbulkpipe(es58x_dev->udev,
......
...@@ -373,8 +373,6 @@ struct es58x_operators { ...@@ -373,8 +373,6 @@ struct es58x_operators {
* queue wake/stop logic should prevent this URB from getting * queue wake/stop logic should prevent this URB from getting
* empty. Please refer to es58x_get_tx_urb() for more details. * empty. Please refer to es58x_get_tx_urb() for more details.
* @tx_urbs_idle_cnt: number of urbs in @tx_urbs_idle. * @tx_urbs_idle_cnt: number of urbs in @tx_urbs_idle.
* @opened_channel_cnt: number of channels opened (c.f. es58x_open()
* and es58x_stop()).
* @ktime_req_ns: kernel timestamp when es58x_set_realtime_diff_ns() * @ktime_req_ns: kernel timestamp when es58x_set_realtime_diff_ns()
* was called. * was called.
* @realtime_diff_ns: difference in nanoseconds between the clocks of * @realtime_diff_ns: difference in nanoseconds between the clocks of
...@@ -384,6 +382,10 @@ struct es58x_operators { ...@@ -384,6 +382,10 @@ struct es58x_operators {
* in RX branches. * in RX branches.
* @rx_max_packet_size: Maximum length of bulk-in URB. * @rx_max_packet_size: Maximum length of bulk-in URB.
* @num_can_ch: Number of CAN channel (i.e. number of elements of @netdev). * @num_can_ch: Number of CAN channel (i.e. number of elements of @netdev).
* @opened_channel_cnt: number of channels opened. Free of race
* conditions because its two users (net_device_ops:ndo_open()
* and net_device_ops:ndo_close()) guarantee that the network
* stack big kernel lock (a.k.a. rtnl_mutex) is being hold.
* @rx_cmd_buf_len: Length of @rx_cmd_buf. * @rx_cmd_buf_len: Length of @rx_cmd_buf.
* @rx_cmd_buf: The device might split the URB commands in an * @rx_cmd_buf: The device might split the URB commands in an
* arbitrary amount of pieces. This buffer is used to concatenate * arbitrary amount of pieces. This buffer is used to concatenate
...@@ -406,7 +408,6 @@ struct es58x_device { ...@@ -406,7 +408,6 @@ struct es58x_device {
struct usb_anchor tx_urbs_busy; struct usb_anchor tx_urbs_busy;
struct usb_anchor tx_urbs_idle; struct usb_anchor tx_urbs_idle;
atomic_t tx_urbs_idle_cnt; atomic_t tx_urbs_idle_cnt;
atomic_t opened_channel_cnt;
u64 ktime_req_ns; u64 ktime_req_ns;
s64 realtime_diff_ns; s64 realtime_diff_ns;
...@@ -415,6 +416,7 @@ struct es58x_device { ...@@ -415,6 +416,7 @@ struct es58x_device {
u16 rx_max_packet_size; u16 rx_max_packet_size;
u8 num_can_ch; u8 num_can_ch;
u8 opened_channel_cnt;
u16 rx_cmd_buf_len; u16 rx_cmd_buf_len;
union es58x_urb_cmd rx_cmd_buf; union es58x_urb_cmd rx_cmd_buf;
......
...@@ -191,8 +191,8 @@ struct gs_can { ...@@ -191,8 +191,8 @@ struct gs_can {
struct gs_usb { struct gs_usb {
struct gs_can *canch[GS_MAX_INTF]; struct gs_can *canch[GS_MAX_INTF];
struct usb_anchor rx_submitted; struct usb_anchor rx_submitted;
atomic_t active_channels;
struct usb_device *udev; struct usb_device *udev;
u8 active_channels;
}; };
/* 'allocate' a tx context. /* 'allocate' a tx context.
...@@ -589,7 +589,7 @@ static int gs_can_open(struct net_device *netdev) ...@@ -589,7 +589,7 @@ static int gs_can_open(struct net_device *netdev)
if (rc) if (rc)
return rc; return rc;
if (atomic_add_return(1, &parent->active_channels) == 1) { if (!parent->active_channels) {
for (i = 0; i < GS_MAX_RX_URBS; i++) { for (i = 0; i < GS_MAX_RX_URBS; i++) {
struct urb *urb; struct urb *urb;
u8 *buf; u8 *buf;
...@@ -690,6 +690,7 @@ static int gs_can_open(struct net_device *netdev) ...@@ -690,6 +690,7 @@ static int gs_can_open(struct net_device *netdev)
dev->can.state = CAN_STATE_ERROR_ACTIVE; dev->can.state = CAN_STATE_ERROR_ACTIVE;
parent->active_channels++;
if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) if (!(dev->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
netif_start_queue(netdev); netif_start_queue(netdev);
...@@ -705,7 +706,8 @@ static int gs_can_close(struct net_device *netdev) ...@@ -705,7 +706,8 @@ static int gs_can_close(struct net_device *netdev)
netif_stop_queue(netdev); netif_stop_queue(netdev);
/* Stop polling */ /* Stop polling */
if (atomic_dec_and_test(&parent->active_channels)) parent->active_channels--;
if (!parent->active_channels)
usb_kill_anchored_urbs(&parent->rx_submitted); usb_kill_anchored_urbs(&parent->rx_submitted);
/* Stop sending URBs */ /* Stop sending URBs */
...@@ -984,8 +986,6 @@ static int gs_usb_probe(struct usb_interface *intf, ...@@ -984,8 +986,6 @@ static int gs_usb_probe(struct usb_interface *intf,
init_usb_anchor(&dev->rx_submitted); init_usb_anchor(&dev->rx_submitted);
atomic_set(&dev->active_channels, 0);
usb_set_intfdata(intf, dev); usb_set_intfdata(intf, dev);
dev->udev = interface_to_usbdev(intf); dev->udev = interface_to_usbdev(intf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment