Received: by 2002:a05:6358:11c7:b0:104:8066:f915 with SMTP id i7csp1297484rwl; Fri, 24 Mar 2023 08:43:11 -0700 (PDT) X-Google-Smtp-Source: AKy350ZxpO+bbZHmbeJtpTdRD66p0J8yXBqgvfAGOrc1b1W7uQrvqauIXvtYfYf1WLAoLlvF+ZpV X-Received: by 2002:aa7:dc10:0:b0:4bd:94b9:b8a8 with SMTP id b16-20020aa7dc10000000b004bd94b9b8a8mr3342015edu.26.1679672590600; Fri, 24 Mar 2023 08:43:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679672590; cv=none; d=google.com; s=arc-20160816; b=BeZW3x2WY2ncPdewFBde6eCb+gnU2XVHO6zTYRppAbAHHKPXAm6GShlbTC3gjZLUDE GkaT3uplkpRgRjNDdcB0aUSFU3l4ZxqrvGRRHD2ST7rXaxLM04tqTFBUyjiKKgmbEFMp Qy/pGYZwxPj8QBxbRX9lEQIgyj3rL0RhldqeUZjyTpoVbQj1GA2sc8W2zEF5/gNa98M2 tH+izOi8ei8aeFAgprbZDT3K9Xq/CenBv+doUQzI3VmuARE8mGZ6EqnIEiVvZsuLlqd/ gyu0eYivVMyDDiVdwhnXsPAlqkdpn7DOWXmxPLVMKNx99HIpTJRLRKM/05vRAJ67XHro k3XQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date; bh=U3lNECH70/PXGZQ2zPeK4H8uV+/5XFMtoLmT+QBipmI=; b=eR23keMqO4NliuEUWhy6YODTEuXbUFDtstVq+kuJ62sCRhvw7OjoUiBNJUbgh4GRPk YOY6W7GcR6ImQYKvTydqP4uCZZtvHO4DH3fZJ1bpscj7EyPE8QkmmvMaWs06VkZkP8Lw awasxT5r9kM8duKKaq0xS7um5PTSG9VX+2r1WLCYalrCUKh10TY9pJ8Z59Utg56NX/X2 9Gmshbujpxh6aJI/7VB0m+dEzQDVUDBdN3PY0abxvGuzJC3xC20p3y3CFBg6zCrzox6I aDlPTy5LLn7ZJ8kw6GDgQiBhqyURLBIf+yC15YNd01g1bPMu+ToCSFQ0Kjve4IRtz65c urMQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d25-20020aa7d699000000b004fc8943f1ffsi392781edr.211.2023.03.24.08.42.45; Fri, 24 Mar 2023 08:43:10 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232566AbjCXPll (ORCPT + 99 others); Fri, 24 Mar 2023 11:41:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232564AbjCXPlc (ORCPT ); Fri, 24 Mar 2023 11:41:32 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E16FA231E4 for ; Fri, 24 Mar 2023 08:41:02 -0700 (PDT) Received: from moin.white.stw.pengutronix.de ([2a0a:edc0:0:b01:1d::7b] helo=bjornoya.blackshift.org) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1pfjX0-00024Y-UF; Fri, 24 Mar 2023 16:40:43 +0100 Received: from pengutronix.de (unknown [IPv6:2a01:4f8:1c1c:29e9:22:41ff:fe00:1400]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (prime256v1) server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) (Authenticated sender: mkl-all@blackshift.org) by smtp.blackshift.org (Postfix) with ESMTPSA id B88F619B9AC; Fri, 24 Mar 2023 15:40:38 +0000 (UTC) Date: Fri, 24 Mar 2023 16:40:37 +0100 From: Marc Kleine-Budde To: Dario Binacchi Cc: linux-kernel@vger.kernel.org, Krzysztof Kozlowski , Amarula patchwork , Vincent Mailhol , Alexandre Torgue , michael@amarulasolutions.com, Rob Herring , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Wolfgang Grandegger , linux-can@vger.kernel.org, netdev@vger.kernel.org Subject: Re: [RESEND PATCH v7 5/5] can: bxcan: add support for ST bxCAN controller Message-ID: <20230324154037.xpqh65ehhdryagaf@pengutronix.de> References: <20230315211040.2455855-1-dario.binacchi@amarulasolutions.com> <20230315211040.2455855-6-dario.binacchi@amarulasolutions.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="hurynxunpy2fobxu" Content-Disposition: inline In-Reply-To: <20230315211040.2455855-6-dario.binacchi@amarulasolutions.com> X-SA-Exim-Connect-IP: 2a0a:edc0:0:b01:1d::7b X-SA-Exim-Mail-From: mkl@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org X-Spam-Status: No, score=-2.3 required=5.0 tests=RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --hurynxunpy2fobxu Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On 15.03.2023 22:10:40, Dario Binacchi wrote: > Add support for the basic extended CAN controller (bxCAN) found in many > low- to middle-end STM32 SoCs. It supports the Basic Extended CAN > protocol versions 2.0A and B with a maximum bit rate of 1 Mbit/s. >=20 > The controller supports two channels (CAN1 as master and CAN2 as slave) > and the driver can enable either or both of the channels. They share > some of the required logic (e. g. clocks and filters), and that means > you cannot use the slave CAN without enabling some hardware resources > managed by the master CAN. >=20 > Each channel has 3 transmit mailboxes, 2 receive FIFOs with 3 stages and > 28 scalable filter banks. > It also manages 4 dedicated interrupt vectors: > - transmit interrupt > - FIFO 0 receive interrupt > - FIFO 1 receive interrupt > - status change error interrupt >=20 > Driver uses all 3 available mailboxes for transmission and FIFO 0 for > reception. Rx filter rules are configured to the minimum. They accept > all messages and assign filter 0 to CAN1 and filter 14 to CAN2 in > identifier mask mode with 32 bits width. It enables and uses transmit, > receive buffers for FIFO 0 and error and status change interrupts. >=20 > Signed-off-by: Dario Binacchi > Reviewed-by: Vincent Mailhol [...] > diff --git a/drivers/net/can/bxcan.c b/drivers/net/can/bxcan.c > new file mode 100644 > index 000000000000..daf4d7ef00e7 > --- /dev/null > +++ b/drivers/net/can/bxcan.c [...] > + > +static inline void bxcan_rmw(struct bxcan_priv *priv, void __iomem *addr, > + u32 clear, u32 set) > +{ > + unsigned long flags; > + u32 old, val; > + > + spin_lock_irqsave(&priv->rmw_lock, flags); > + old =3D readl(addr); > + val =3D (old & ~clear) | set; > + if (val !=3D old) > + writel(val, addr); > + > + spin_unlock_irqrestore(&priv->rmw_lock, flags); > +} I think you don't need the spin_lock anymore, but it's not in the hot path, so leave it this way. > + [...] > +static irqreturn_t bxcan_rx_isr(int irq, void *dev_id) > +{ > + struct net_device *ndev =3D dev_id; > + struct bxcan_priv *priv =3D netdev_priv(ndev); > + > + can_rx_offload_irq_offload_fifo(&priv->offload); > + can_rx_offload_irq_finish(&priv->offload); > + > + return IRQ_HANDLED; This handler is not 100% shared IRQ safe, you have to return IRQ_NONE if no IRQ is active. > +} > + > +static irqreturn_t bxcan_tx_isr(int irq, void *dev_id) > +{ > + struct net_device *ndev =3D dev_id; > + struct bxcan_priv *priv =3D netdev_priv(ndev); > + struct bxcan_regs __iomem *regs =3D priv->regs; > + struct net_device_stats *stats =3D &ndev->stats; > + u32 tsr, rqcp_bit; > + int idx; > + > + tsr =3D readl(®s->tsr); > + if (!(tsr & (BXCAN_TSR_RQCP0 | BXCAN_TSR_RQCP1 | BXCAN_TSR_RQCP2))) > + return IRQ_HANDLED; Is this a check for no IRQ? Then return IRQ_NONE. > + > + while (priv->tx_head - priv->tx_tail > 0) { > + idx =3D bxcan_get_tx_tail(priv); > + rqcp_bit =3D BXCAN_TSR_RQCP0 << (idx << 3); > + if (!(tsr & rqcp_bit)) > + break; > + > + stats->tx_packets++; > + stats->tx_bytes +=3D can_get_echo_skb(ndev, idx, NULL); > + priv->tx_tail++; > + } > + > + writel(tsr, ®s->tsr); > + > + if (bxcan_get_tx_free(priv)) { > + /* Make sure that anybody stopping the queue after > + * this sees the new tx_ring->tail. > + */ > + smp_mb(); > + netif_wake_queue(ndev); > + } > + > + return IRQ_HANDLED; > +} > + > +static void bxcan_handle_state_change(struct net_device *ndev, u32 esr) > +{ > + struct bxcan_priv *priv =3D netdev_priv(ndev); > + enum can_state new_state =3D priv->can.state; > + struct can_berr_counter bec; > + enum can_state rx_state, tx_state; > + struct sk_buff *skb; > + struct can_frame *cf; > + > + /* Early exit if no error flag is set */ > + if (!(esr & (BXCAN_ESR_EWGF | BXCAN_ESR_EPVF | BXCAN_ESR_BOFF))) > + return; > + > + bec.txerr =3D FIELD_GET(BXCAN_ESR_TEC_MASK, esr); > + bec.rxerr =3D FIELD_GET(BXCAN_ESR_REC_MASK, esr); > + > + if (esr & BXCAN_ESR_BOFF) > + new_state =3D CAN_STATE_BUS_OFF; > + else if (esr & BXCAN_ESR_EPVF) > + new_state =3D CAN_STATE_ERROR_PASSIVE; > + else if (esr & BXCAN_ESR_EWGF) > + new_state =3D CAN_STATE_ERROR_WARNING; > + > + /* state hasn't changed */ > + if (unlikely(new_state =3D=3D priv->can.state)) > + return; > + > + skb =3D alloc_can_err_skb(ndev, &cf); > + > + tx_state =3D bec.txerr >=3D bec.rxerr ? new_state : 0; > + rx_state =3D bec.txerr <=3D bec.rxerr ? new_state : 0; > + can_change_state(ndev, cf, tx_state, rx_state); > + > + if (new_state =3D=3D CAN_STATE_BUS_OFF) { > + can_bus_off(ndev); > + } else if (skb) { > + cf->can_id |=3D CAN_ERR_CNT; > + cf->data[6] =3D bec.txerr; > + cf->data[7] =3D bec.rxerr; > + } > + > + if (skb) { > + int err; > + > + err =3D can_rx_offload_queue_timestamp(&priv->offload, skb, > + priv->timestamp); > + if (err) > + ndev->stats.rx_fifo_errors++; > + } > +} > + > +static void bxcan_handle_bus_err(struct net_device *ndev, u32 esr) > +{ > + struct bxcan_priv *priv =3D netdev_priv(ndev); > + enum bxcan_lec_code lec_code; > + struct can_frame *cf; > + struct sk_buff *skb; > + > + lec_code =3D FIELD_GET(BXCAN_ESR_LEC_MASK, esr); > + > + /* Early exit if no lec update or no error. > + * No lec update means that no CAN bus event has been detected > + * since CPU wrote BXCAN_LEC_UNUSED value to status reg. > + */ > + if (lec_code =3D=3D BXCAN_LEC_UNUSED || lec_code =3D=3D BXCAN_LEC_NO_ER= ROR) > + return; > + > + /* Common for all type of bus errors */ > + priv->can.can_stats.bus_error++; > + > + /* Propagate the error condition to the CAN stack */ > + skb =3D alloc_can_err_skb(ndev, &cf); > + if (skb) > + cf->can_id |=3D CAN_ERR_PROT | CAN_ERR_BUSERROR; > + > + switch (lec_code) { > + case BXCAN_LEC_STUFF_ERROR: > + netdev_dbg(ndev, "Stuff error\n"); > + ndev->stats.rx_errors++; > + if (skb) > + cf->data[2] |=3D CAN_ERR_PROT_STUFF; > + break; > + > + case BXCAN_LEC_FORM_ERROR: > + netdev_dbg(ndev, "Form error\n"); > + ndev->stats.rx_errors++; > + if (skb) > + cf->data[2] |=3D CAN_ERR_PROT_FORM; > + break; > + > + case BXCAN_LEC_ACK_ERROR: > + netdev_dbg(ndev, "Ack error\n"); > + ndev->stats.tx_errors++; > + if (skb) { > + cf->can_id |=3D CAN_ERR_ACK; > + cf->data[3] =3D CAN_ERR_PROT_LOC_ACK; > + } > + break; > + > + case BXCAN_LEC_BIT1_ERROR: > + netdev_dbg(ndev, "Bit error (recessive)\n"); > + ndev->stats.tx_errors++; > + if (skb) > + cf->data[2] |=3D CAN_ERR_PROT_BIT1; > + break; > + > + case BXCAN_LEC_BIT0_ERROR: > + netdev_dbg(ndev, "Bit error (dominant)\n"); > + ndev->stats.tx_errors++; > + if (skb) > + cf->data[2] |=3D CAN_ERR_PROT_BIT0; > + break; > + > + case BXCAN_LEC_CRC_ERROR: > + netdev_dbg(ndev, "CRC error\n"); > + ndev->stats.rx_errors++; > + if (skb) { > + cf->data[2] |=3D CAN_ERR_PROT_BIT; > + cf->data[3] =3D CAN_ERR_PROT_LOC_CRC_SEQ; > + } > + break; > + > + default: > + break; > + } > + > + if (skb) { > + int err; > + > + err =3D can_rx_offload_queue_timestamp(&priv->offload, skb, > + priv->timestamp); > + if (err) > + ndev->stats.rx_fifo_errors++; > + } > +} > + > +static irqreturn_t bxcan_state_change_isr(int irq, void *dev_id) > +{ > + struct net_device *ndev =3D dev_id; > + struct bxcan_priv *priv =3D netdev_priv(ndev); > + struct bxcan_regs __iomem *regs =3D priv->regs; > + u32 msr, esr; > + > + msr =3D readl(®s->msr); > + if (!(msr & BXCAN_MSR_ERRI)) > + return IRQ_NONE; No IRQ, the driver returns IRQ_NONE here? Looks good! > + > + esr =3D readl(®s->esr); > + bxcan_handle_state_change(ndev, esr); > + > + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) > + bxcan_handle_bus_err(ndev, esr); > + > + msr |=3D BXCAN_MSR_ERRI; > + writel(msr, ®s->msr); > + can_rx_offload_irq_finish(&priv->offload); > + > + return IRQ_HANDLED; > +} regards, Marc --=20 Pengutronix e.K. | Marc Kleine-Budde | Embedded Linux | https://www.pengutronix.de | Vertretung N=C3=BCrnberg | Phone: +49-5121-206917-129 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | --hurynxunpy2fobxu Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEDs2BvajyNKlf9TJQvlAcSiqKBOgFAmQdxHIACgkQvlAcSiqK BOgQMwgAhqpI0jAZ2dRqn5P/mLsnOX4aVIvI4E0PUfaZqZdPfrmRtYr2SDWkFrj3 LOHzYHnbYeBqELhwM3H+E5oRyPihf+rkBZg2WBoeRVKaCWXSFNm+QAuKpNkYGbDu kCd5HlvWWcVJUN8ORSyVB2jH0laBS9eyqmuBAcYtGURrUEIz7LEBAhd97gykKxKv m0PAQPbG6CPB43NTx06beGz8n6QIzDwiVs2EKju0/Ni4nlKWsE0u2GpKSf0PYkZz 5zdO20lWOc6OtEZ4uuQTdC4i8b3SvTo5fJq2416XSbaU0bRWR5RVCkKacdgHBiOs ulHzE9NkcPO1teCJGnZF1Zcs7ZUX0w== =5afL -----END PGP SIGNATURE----- --hurynxunpy2fobxu--