linux-can-fixes-for-5.18-20220429
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEBsvAIBsPu6mG7thcrX5LkNig010FAmJruWQTHG1rbEBwZW5n dXRyb25peC5kZQAKCRCtfkuQ2KDTXekLCACB+A9hMgX3swUDJ5vqBuvWjOZIgcgC 7sCOjIuO479IgeEhztXNOdAwQ+7BEg6UOOAeqXqSbqVcs/1mLgCHBaUlj7ENGsaI 7QSqmbf//1is6tqrujOpcKwd45w92ys96xX1TEbohFvjGvVE18DSt5pWuH0fEWs3 Qw3t+AfqP9aW1l7JwxN5fo6ktWnwXItCcB4fjeWjcV3AR2RG8HD7JXTq8vQrMA+3 suEvdEbh9nPTw0ll3N+RLyRHq69sGb1EmOi8OxE5UBu1WT7QytzS1a+oZkowg2bt Xp2ULRtf66imf+9P5ojYA9j1Pd+FtMJRcn07jEyD+EoDQD7oFzVVg/wO =R5GF -----END PGP SIGNATURE----- Merge tag 'linux-can-fixes-for-5.18-20220429' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can Marc Kleine-Budde says: ==================== pull-request: can 2022-04-29 The first patch is by Oliver Hartkopp and removes the ability to re-binding bounds sockets from the ISOTP. It turned out to be not needed and brings unnecessary complexity. The last 4 patches all target the grcan driver. Duoming Zhou's patch fixes a potential dead lock in the grcan_close() function. Daniel Hellstrom's patch fixes the dma_alloc_coherent() to use the correct device. Andreas Larsson's 1st patch fixes a broken system id check, the 2nd patch fixes the NAPI poll budget usage. * tag 'linux-can-fixes-for-5.18-20220429' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can: can: grcan: only use the NAPI poll budget for RX can: grcan: grcan_probe(): fix broken system id check for errata workaround needs can: grcan: use ofdev->dev when allocating DMA memory can: grcan: grcan_close(): fix deadlock can: isotp: remove re-binding of bound socket ==================== Link: https://lore.kernel.org/r/20220429125612.1792561-1-mkl@pengutronix.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Коммит
4f159a7c4d
|
@ -241,13 +241,14 @@ struct grcan_device_config {
|
|||
.rxsize = GRCAN_DEFAULT_BUFFER_SIZE, \
|
||||
}
|
||||
|
||||
#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 0x4100
|
||||
#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 4100
|
||||
#define GRLIB_VERSION_MASK 0xffff
|
||||
|
||||
/* GRCAN private data structure */
|
||||
struct grcan_priv {
|
||||
struct can_priv can; /* must be the first member */
|
||||
struct net_device *dev;
|
||||
struct device *ofdev_dev;
|
||||
struct napi_struct napi;
|
||||
|
||||
struct grcan_registers __iomem *regs; /* ioremap'ed registers */
|
||||
|
@ -921,7 +922,7 @@ static void grcan_free_dma_buffers(struct net_device *dev)
|
|||
struct grcan_priv *priv = netdev_priv(dev);
|
||||
struct grcan_dma *dma = &priv->dma;
|
||||
|
||||
dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf,
|
||||
dma_free_coherent(priv->ofdev_dev, dma->base_size, dma->base_buf,
|
||||
dma->base_handle);
|
||||
memset(dma, 0, sizeof(*dma));
|
||||
}
|
||||
|
@ -946,7 +947,7 @@ static int grcan_allocate_dma_buffers(struct net_device *dev,
|
|||
|
||||
/* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */
|
||||
dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT;
|
||||
dma->base_buf = dma_alloc_coherent(&dev->dev,
|
||||
dma->base_buf = dma_alloc_coherent(priv->ofdev_dev,
|
||||
dma->base_size,
|
||||
&dma->base_handle,
|
||||
GFP_KERNEL);
|
||||
|
@ -1102,8 +1103,10 @@ static int grcan_close(struct net_device *dev)
|
|||
|
||||
priv->closing = true;
|
||||
if (priv->need_txbug_workaround) {
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
del_timer_sync(&priv->hang_timer);
|
||||
del_timer_sync(&priv->rr_timer);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
}
|
||||
netif_stop_queue(dev);
|
||||
grcan_stop_hardware(dev);
|
||||
|
@ -1122,7 +1125,7 @@ static int grcan_close(struct net_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int grcan_transmit_catch_up(struct net_device *dev, int budget)
|
||||
static void grcan_transmit_catch_up(struct net_device *dev)
|
||||
{
|
||||
struct grcan_priv *priv = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
|
@ -1130,7 +1133,7 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget)
|
|||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
work_done = catch_up_echo_skb(dev, budget, true);
|
||||
work_done = catch_up_echo_skb(dev, -1, true);
|
||||
if (work_done) {
|
||||
if (!priv->resetting && !priv->closing &&
|
||||
!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
|
||||
|
@ -1144,8 +1147,6 @@ static int grcan_transmit_catch_up(struct net_device *dev, int budget)
|
|||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static int grcan_receive(struct net_device *dev, int budget)
|
||||
|
@ -1227,19 +1228,13 @@ static int grcan_poll(struct napi_struct *napi, int budget)
|
|||
struct net_device *dev = priv->dev;
|
||||
struct grcan_registers __iomem *regs = priv->regs;
|
||||
unsigned long flags;
|
||||
int tx_work_done, rx_work_done;
|
||||
int rx_budget = budget / 2;
|
||||
int tx_budget = budget - rx_budget;
|
||||
int work_done;
|
||||
|
||||
/* Half of the budget for receiving messages */
|
||||
rx_work_done = grcan_receive(dev, rx_budget);
|
||||
work_done = grcan_receive(dev, budget);
|
||||
|
||||
/* Half of the budget for transmitting messages as that can trigger echo
|
||||
* frames being received
|
||||
*/
|
||||
tx_work_done = grcan_transmit_catch_up(dev, tx_budget);
|
||||
grcan_transmit_catch_up(dev);
|
||||
|
||||
if (rx_work_done < rx_budget && tx_work_done < tx_budget) {
|
||||
if (work_done < budget) {
|
||||
napi_complete(napi);
|
||||
|
||||
/* Guarantee no interference with a running reset that otherwise
|
||||
|
@ -1256,7 +1251,7 @@ static int grcan_poll(struct napi_struct *napi, int budget)
|
|||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
return rx_work_done + tx_work_done;
|
||||
return work_done;
|
||||
}
|
||||
|
||||
/* Work tx bug by waiting while for the risky situation to clear. If that fails,
|
||||
|
@ -1587,6 +1582,7 @@ static int grcan_setup_netdev(struct platform_device *ofdev,
|
|||
memcpy(&priv->config, &grcan_module_config,
|
||||
sizeof(struct grcan_device_config));
|
||||
priv->dev = dev;
|
||||
priv->ofdev_dev = &ofdev->dev;
|
||||
priv->regs = base;
|
||||
priv->can.bittiming_const = &grcan_bittiming_const;
|
||||
priv->can.do_set_bittiming = grcan_set_bittiming;
|
||||
|
@ -1639,6 +1635,7 @@ exit_free_candev:
|
|||
static int grcan_probe(struct platform_device *ofdev)
|
||||
{
|
||||
struct device_node *np = ofdev->dev.of_node;
|
||||
struct device_node *sysid_parent;
|
||||
u32 sysid, ambafreq;
|
||||
int irq, err;
|
||||
void __iomem *base;
|
||||
|
@ -1647,10 +1644,15 @@ static int grcan_probe(struct platform_device *ofdev)
|
|||
/* Compare GRLIB version number with the first that does not
|
||||
* have the tx bug (see start_xmit)
|
||||
*/
|
||||
err = of_property_read_u32(np, "systemid", &sysid);
|
||||
if (!err && ((sysid & GRLIB_VERSION_MASK)
|
||||
>= GRCAN_TXBUG_SAFE_GRLIB_VERSION))
|
||||
txbug = false;
|
||||
sysid_parent = of_find_node_by_path("/ambapp0");
|
||||
if (sysid_parent) {
|
||||
of_node_get(sysid_parent);
|
||||
err = of_property_read_u32(sysid_parent, "systemid", &sysid);
|
||||
if (!err && ((sysid & GRLIB_VERSION_MASK) >=
|
||||
GRCAN_TXBUG_SAFE_GRLIB_VERSION))
|
||||
txbug = false;
|
||||
of_node_put(sysid_parent);
|
||||
}
|
||||
|
||||
err = of_property_read_u32(np, "freq", &ambafreq);
|
||||
if (err) {
|
||||
|
|
|
@ -1189,6 +1189,11 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
|
|||
|
||||
lock_sock(sk);
|
||||
|
||||
if (so->bound) {
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* do not register frame reception for functional addressing */
|
||||
if (so->opt.flags & CAN_ISOTP_SF_BROADCAST)
|
||||
do_rx_reg = 0;
|
||||
|
@ -1199,10 +1204,6 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (so->bound && addr->can_ifindex == so->ifindex &&
|
||||
rx_id == so->rxid && tx_id == so->txid)
|
||||
goto out;
|
||||
|
||||
dev = dev_get_by_index(net, addr->can_ifindex);
|
||||
if (!dev) {
|
||||
err = -ENODEV;
|
||||
|
@ -1237,22 +1238,6 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
|
|||
|
||||
dev_put(dev);
|
||||
|
||||
if (so->bound && do_rx_reg) {
|
||||
/* unregister old filter */
|
||||
if (so->ifindex) {
|
||||
dev = dev_get_by_index(net, so->ifindex);
|
||||
if (dev) {
|
||||
can_rx_unregister(net, dev, so->rxid,
|
||||
SINGLE_MASK(so->rxid),
|
||||
isotp_rcv, sk);
|
||||
can_rx_unregister(net, dev, so->txid,
|
||||
SINGLE_MASK(so->txid),
|
||||
isotp_rcv_echo, sk);
|
||||
dev_put(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* switch to new settings */
|
||||
so->ifindex = ifindex;
|
||||
so->rxid = rx_id;
|
||||
|
|
Загрузка…
Ссылка в новой задаче