From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
Cc: Wolfgang Grandegger <wg@grandegger.com>,
Wolfram Sang <w.sang@pengutronix.de>,
Christian Pellegrin <chripell@fsfe.org>,
Barry Song <21cnbao@gmail.com>,
Samuel Ortiz <sameo@linux.intel.com>,
socketcan-core@lists.berlios.de, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org,
"David S. Miller" <davem@davemloft.net>,
andrew.chih.howe.khor@intel.com, qi.wang@intel.com,
margie.foster@intel.com, yong.y.wang@intel.com,
kok.howg.ewe@intel.com, joel.clark@intel.com
Subject: Re: [PATCH net-next-2.6 06/19 v5] can: EG20T PCH: Fix endianness issue
Date: Fri, 26 Nov 2010 10:52:28 +0100 [thread overview]
Message-ID: <4CEF835C.7000304@pengutronix.de> (raw)
In-Reply-To: <4CEF178C.2050506@dsn.okisemi.com>
[-- Attachment #1: Type: text/plain, Size: 15560 bytes --]
On 11/26/2010 03:12 AM, Tomoya MORINAGA wrote:
> Fix endianness issue.
> there is endianness issue both Tx and Rx.
> Currently, data is set like below.
> Register:
> MSB--LSB
> x x D0 D1
> x x D2 D3
> x x D4 D5
> x x D6 D7
>
> But Data to be sent must be set like below.
> Register:
> MSB--LSB
> x x D1 D0
> x x D3 D2
> x x D5 D4
> x x D7 D6 (x means reserved area.)
I whish you just fix the endianess issue in this patch. Makes it more
readable.
> For easy to read, some sub-functions are created.
>
> Modify complex "goto" to do~while.
This should go into a separate patch. Please don't introduce the
next_flag variable that you remove in a later patch.
>
> Signed-off-by: Tomoya MORINAGA <tomoya-linux@dsn.okisemi.com>
> ---
> drivers/net/can/pch_can.c | 304 +++++++++++++++++++++++----------------------
> 1 files changed, 155 insertions(+), 149 deletions(-)
>
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index 6437e60..0ac2a75 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> @@ -134,10 +134,7 @@ struct pch_can_if_regs {
> u32 id1;
> u32 id2;
> u32 mcont;
> - u32 dataa1;
> - u32 dataa2;
> - u32 datab1;
> - u32 datab2;
> + u32 data[4];
> u32 rsv[13];
> };
>
> @@ -420,10 +417,10 @@ static void pch_can_clear_buffers(struct pch_can_priv *priv)
> iowrite32(0x0, &priv->regs->ifregs[0].id1);
> iowrite32(0x0, &priv->regs->ifregs[0].id2);
> iowrite32(0x0, &priv->regs->ifregs[0].mcont);
> - iowrite32(0x0, &priv->regs->ifregs[0].dataa1);
> - iowrite32(0x0, &priv->regs->ifregs[0].dataa2);
> - iowrite32(0x0, &priv->regs->ifregs[0].datab1);
> - iowrite32(0x0, &priv->regs->ifregs[0].datab2);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[0]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[1]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[2]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[3]);
> iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK |
> PCH_CMASK_ARB | PCH_CMASK_CTRL,
> &priv->regs->ifregs[0].cmask);
> @@ -437,10 +434,10 @@ static void pch_can_clear_buffers(struct pch_can_priv *priv)
> iowrite32(0x0, &priv->regs->ifregs[1].id1);
> iowrite32(0x0, &priv->regs->ifregs[1].id2);
> iowrite32(0x0, &priv->regs->ifregs[1].mcont);
> - iowrite32(0x0, &priv->regs->ifregs[1].dataa1);
> - iowrite32(0x0, &priv->regs->ifregs[1].dataa2);
> - iowrite32(0x0, &priv->regs->ifregs[1].datab1);
> - iowrite32(0x0, &priv->regs->ifregs[1].datab2);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[0]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[1]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[2]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[3]);
> iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK |
> PCH_CMASK_ARB | PCH_CMASK_CTRL,
> &priv->regs->ifregs[1].cmask);
> @@ -697,190 +694,202 @@ static irqreturn_t pch_can_interrupt(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> -static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat)
> +static void pch_fifo_thresh(struct pch_can_priv *priv, int obj_id)
> +{
> + if (obj_id < PCH_FIFO_THRESH) {
> + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL |
> + PCH_CMASK_ARB, &priv->regs->ifregs[0].cmask);
> +
> + /* Clearing the Dir bit. */
> + pch_can_bit_clear(&priv->regs->ifregs[0].id2, PCH_ID2_DIR);
> +
> + /* Clearing NewDat & IntPnd */
> + pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> + PCH_IF_MCONT_INTPND);
> + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, obj_id);
> + } else if (obj_id > PCH_FIFO_THRESH) {
> + pch_can_int_clr(priv, obj_id);
> + } else if (obj_id == PCH_FIFO_THRESH) {
> + int cnt;
> + for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
> + pch_can_int_clr(priv, cnt + 1);
> + }
> +}
> +
> +static int pch_can_rx_msg_lost(struct net_device *ndev, int obj_id)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &(priv->ndev->stats);
> + struct sk_buff *skb;
> + struct can_frame *cf;
> +
> + netdev_dbg(priv->ndev, "Msg Obj is overwritten.\n");
> + pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> + PCH_IF_MCONT_MSGLOST);
> + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL,
> + &priv->regs->ifregs[0].cmask);
> + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, obj_id);
> +
> + skb = alloc_can_err_skb(ndev, &cf);
> + if (!skb)
> + return -ENOMEM;
> +
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> + stats->rx_over_errors++;
> + stats->rx_errors++;
> +
> + netif_receive_skb(skb);
> +
> + return 0;
> +}
> +
> +static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota)
> {
> u32 reg;
> canid_t id;
> - u32 ide;
> - u32 rtr;
> - int i, j, k;
> int rcv_pkts = 0;
> + int rtn;
> + int next_flag = 0;
> struct sk_buff *skb;
> struct can_frame *cf;
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct net_device_stats *stats = &(priv->ndev->stats);
> + int i;
> + u32 id2;
> + u16 data_reg;
>
> - /* Reading the messsage object from the Message RAM */
> - iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, int_stat);
> + do {
> + /* Reading the messsage object from the Message RAM */
> + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
> + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, obj_num);
>
> - /* Reading the MCONT register. */
> - reg = ioread32(&priv->regs->ifregs[0].mcont);
> - reg &= 0xffff;
> + /* Reading the MCONT register. */
> + reg = ioread32(&priv->regs->ifregs[0].mcont);
> +
> + if (reg & PCH_IF_MCONT_EOB)
> + break;
>
> - for (k = int_stat; !(reg & PCH_IF_MCONT_EOB); k++) {
> /* If MsgLost bit set. */
> if (reg & PCH_IF_MCONT_MSGLOST) {
> - dev_err(&priv->ndev->dev, "Msg Obj is overwritten.\n");
> - pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> - PCH_IF_MCONT_MSGLOST);
> - iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL,
> - &priv->regs->ifregs[0].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k);
> -
> - skb = alloc_can_err_skb(ndev, &cf);
> + rtn = pch_can_rx_msg_lost(ndev, obj_num);
> + if (!rtn)
> + netdev_err(ndev, "Can't get memory\n");
Your logic is broken, the function returns 0 on success, which makes it
print a error message.
In an OOM situation the system is under pressure anyway. On low end
systems it not good to print a message to the log. AFAICS no other can
driver does this.
> + rcv_pkts++;
> + quota--;
> + next_flag = 1;
> + } else if (!(reg & PCH_IF_MCONT_NEWDAT))
> + next_flag = 1;
Please don't introduce the next_flag, that is removed in a later patch.
> +
> + if (!next_flag) {
> + skb = alloc_can_skb(priv->ndev, &cf);
> if (!skb)
> return -ENOMEM;
>
> - priv->can.can_stats.error_passive++;
> - priv->can.state = CAN_STATE_ERROR_PASSIVE;
> - cf->can_id |= CAN_ERR_CRTL;
> - cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
> - cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
> - stats->rx_packets++;
> - stats->rx_bytes += cf->can_dlc;
> + /* Get Received data */
> + id2 = ioread32(&priv->regs->ifregs[0].id2);
> + if (id2 & PCH_ID2_XTD) {
> + id = (ioread32(&priv->regs->ifregs[0].id1) &
> + 0xffff);
> + id |= (((id2) & 0x1fff) << 16);
> + cf->can_id = id | CAN_EFF_FLAG;
> + } else {
> + id = ((id2 & (CAN_SFF_MASK << 2)) >> 2);
id = (id2 >> 2) & CAN_SFF_MASK;
this is IMHO more readable.
> + cf->can_id = id;
> + }
> +
> + if (id2 & PCH_ID2_DIR)
> + cf->can_id |= CAN_RTR_FLAG;
> +
> + cf->can_dlc = get_can_dlc((ioread32(&priv->regs->
> + ifregs[0].mcont)) & 0xF);
> +
> + for (i = 0; i < cf->can_dlc; i += 2) {
> + data_reg = ioread16(&priv->regs->ifregs[0].
> + data[i / 2]);
> + cf->data[i] = data_reg & 0xff;
& 0xff isn't needed, as cf->data is 8 bit wide.
> + cf->data[i + 1] = data_reg >> 8;
> + }
>
> netif_receive_skb(skb);
> rcv_pkts++;
> - goto RX_NEXT;
> - }
> - if (!(reg & PCH_IF_MCONT_NEWDAT))
> - goto RX_NEXT;
> -
> - skb = alloc_can_skb(priv->ndev, &cf);
> - if (!skb)
> - return -ENOMEM;
> -
> - /* Get Received data */
> - ide = ((ioread32(&priv->regs->ifregs[0].id2)) & PCH_ID2_XTD) >>
> - 14;
> - if (ide) {
> - id = (ioread32(&priv->regs->ifregs[0].id1) & 0xffff);
> - id |= (((ioread32(&priv->regs->ifregs[0].id2)) &
> - 0x1fff) << 16);
> - cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
> - } else {
> - id = (((ioread32(&priv->regs->ifregs[0].id2)) &
> - (CAN_SFF_MASK << 2)) >> 2);
> - cf->can_id = (id & CAN_SFF_MASK);
> - }
> + stats->rx_packets++;
> + quota--;
> + stats->rx_bytes += cf->can_dlc;
>
> - rtr = (ioread32(&priv->regs->ifregs[0].id2) & PCH_ID2_DIR);
> - if (rtr) {
> - cf->can_dlc = 0;
> - cf->can_id |= CAN_RTR_FLAG;
> - } else {
> - cf->can_dlc =
> - ((ioread32(&priv->regs->ifregs[0].mcont)) & 0x0f);
> + pch_fifo_thresh(priv, obj_num);
> }
> + obj_num++;
> + next_flag = 0;
> + } while (quota > 0);
>
> - for (i = 0, j = 0; i < cf->can_dlc; j++) {
> - reg = ioread32(&priv->regs->ifregs[0].dataa1 + j*4);
> - cf->data[i++] = cpu_to_le32(reg & 0xff);
> - if (i == cf->can_dlc)
> - break;
> - cf->data[i++] = cpu_to_le32((reg >> 8) & 0xff);
> - }
> + return rcv_pkts;
> +}
>
> - netif_receive_skb(skb);
> - rcv_pkts++;
> - stats->rx_packets++;
> - stats->rx_bytes += cf->can_dlc;
> -
> - if (k < PCH_FIFO_THRESH) {
> - iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL |
> - PCH_CMASK_ARB, &priv->regs->ifregs[0].cmask);
> -
> - /* Clearing the Dir bit. */
> - pch_can_bit_clear(&priv->regs->ifregs[0].id2,
> - PCH_ID2_DIR);
> -
> - /* Clearing NewDat & IntPnd */
> - pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> - PCH_IF_MCONT_INTPND);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k);
> - } else if (k > PCH_FIFO_THRESH) {
> - pch_can_int_clr(priv, k);
> - } else if (k == PCH_FIFO_THRESH) {
> - int cnt;
> - for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
> - pch_can_int_clr(priv, cnt+1);
> - }
> -RX_NEXT:
> - /* Reading the messsage object from the Message RAM */
> - iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k);
> - reg = ioread32(&priv->regs->ifregs[0].mcont);
> - }
> +static void pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &(priv->ndev->stats);
> + u32 dlc;
>
> - return rcv_pkts;
> + can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
> + iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
> + &priv->regs->ifregs[1].cmask);
> + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, int_stat);
> + dlc = get_can_dlc(ioread32(&priv->regs->ifregs[1].mcont) &
> + PCH_IF_MCONT_DLC);
> + stats->tx_bytes += dlc;
> + stats->tx_packets++;
> + if (int_stat == PCH_TX_OBJ_END)
> + netif_wake_queue(ndev);
> }
> +
> static int pch_can_rx_poll(struct napi_struct *napi, int quota)
> {
> struct net_device *ndev = napi->dev;
> struct pch_can_priv *priv = netdev_priv(ndev);
> - struct net_device_stats *stats = &(priv->ndev->stats);
> - u32 dlc;
> u32 int_stat;
> int rcv_pkts = 0;
> u32 reg_stat;
>
> int_stat = pch_can_int_pending(priv);
> if (!int_stat)
> - return 0;
> + goto end;
>
> -INT_STAT:
> - if (int_stat == PCH_STATUS_INT) {
> + if ((int_stat == PCH_STATUS_INT) && (quota > 0)) {
> reg_stat = ioread32(&priv->regs->stat);
> if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) {
> - if ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL)
> + if (reg_stat & PCH_BUS_OFF ||
> + (reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL) {
> pch_can_error(ndev, reg_stat);
> + quota--;
> + }
> }
>
> - if (reg_stat & PCH_TX_OK) {
> - iowrite32(PCH_CMASK_RX_TX_GET,
> - &priv->regs->ifregs[1].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[1].creq,
> - ioread32(&priv->regs->intr));
> + if (reg_stat & PCH_TX_OK)
> pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK);
> - }
>
> if (reg_stat & PCH_RX_OK)
> pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK);
>
> int_stat = pch_can_int_pending(priv);
> - if (int_stat == PCH_STATUS_INT)
> - goto INT_STAT;
> }
>
> -MSG_OBJ:
> + if (quota == 0)
> + goto end;
> +
> if ((int_stat >= PCH_RX_OBJ_START) && (int_stat <= PCH_RX_OBJ_END)) {
> - rcv_pkts = pch_can_rx_normal(ndev, int_stat);
> - if (rcv_pkts < 0)
> - return 0;
> + rcv_pkts += pch_can_rx_normal(ndev, int_stat, quota);
> + quota -= rcv_pkts;
> + if (quota < 0)
> + goto end;
> } else if ((int_stat >= PCH_TX_OBJ_START) &&
> (int_stat <= PCH_TX_OBJ_END)) {
> /* Handle transmission interrupt */
> - can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
> - iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
> - &priv->regs->ifregs[1].cmask);
> - dlc = ioread32(&priv->regs->ifregs[1].mcont) &
> - PCH_IF_MCONT_DLC;
> - pch_can_check_if_busy(&priv->regs->ifregs[1].creq, int_stat);
> - if (dlc > 8)
> - dlc = 8;
> - stats->tx_bytes += dlc;
> - stats->tx_packets++;
> - if (int_stat == PCH_TX_OBJ_END)
> - netif_wake_queue(ndev);
> + pch_can_tx_complete(ndev, int_stat);
> }
>
> - int_stat = pch_can_int_pending(priv);
> - if (int_stat == PCH_STATUS_INT)
> - goto INT_STAT;
> - else if (int_stat >= 1 && int_stat <= 32)
> - goto MSG_OBJ;
> -
> +end:
> napi_complete(napi);
> pch_can_set_int_enables(priv, PCH_CAN_ALL);
>
The following hunk is a nice and clean patch. It fixes the endianess
issue, nothing more.
> @@ -1013,10 +1022,10 @@ static int pch_close(struct net_device *ndev)
>
> static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> {
> - int i, j;
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct can_frame *cf = (struct can_frame *)skb->data;
> int tx_buffer_avail = 0;
> + int i;
>
> if (can_dropped_invalid_skb(ndev, skb))
> return NETDEV_TX_OK;
> @@ -1057,13 +1066,10 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> if (cf->can_id & CAN_RTR_FLAG)
> pch_can_bit_clear(&priv->regs->ifregs[1].id2, PCH_ID2_DIR);
>
> - for (i = 0, j = 0; i < cf->can_dlc; j++) {
> - iowrite32(le32_to_cpu(cf->data[i++]),
> - (&priv->regs->ifregs[1].dataa1) + j*4);
> - if (i == cf->can_dlc)
> - break;
> - iowrite32(le32_to_cpu(cf->data[i++] << 8),
> - (&priv->regs->ifregs[1].dataa1) + j*4);
> + /* Copy data to register */
> + for (i = 0; i < cf->can_dlc; i += 2) {
> + iowrite16(cf->data[i] | (cf->data[i + 1] << 8),
> + &priv->regs->ifregs[1].data[i / 2]);
> }
>
> can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_END - 1);
cheers, Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
WARNING: multiple messages have this Message-ID (diff)
From: Marc Kleine-Budde <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
To: Tomoya MORINAGA <tomoya-linux-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
Samuel Ortiz <sameo-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>,
margie.foster-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org,
yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
kok.howg.ewe-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>,
joel.clark-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org,
"David S. Miller" <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>,
Christian Pellegrin <chripell-VaTbYqLCNhc@public.gmane.org>,
qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Subject: Re: [PATCH net-next-2.6 06/19 v5] can: EG20T PCH: Fix endianness issue
Date: Fri, 26 Nov 2010 10:52:28 +0100 [thread overview]
Message-ID: <4CEF835C.7000304@pengutronix.de> (raw)
In-Reply-To: <4CEF178C.2050506-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
[-- Attachment #1.1: Type: text/plain, Size: 15584 bytes --]
On 11/26/2010 03:12 AM, Tomoya MORINAGA wrote:
> Fix endianness issue.
> there is endianness issue both Tx and Rx.
> Currently, data is set like below.
> Register:
> MSB--LSB
> x x D0 D1
> x x D2 D3
> x x D4 D5
> x x D6 D7
>
> But Data to be sent must be set like below.
> Register:
> MSB--LSB
> x x D1 D0
> x x D3 D2
> x x D5 D4
> x x D7 D6 (x means reserved area.)
I whish you just fix the endianess issue in this patch. Makes it more
readable.
> For easy to read, some sub-functions are created.
>
> Modify complex "goto" to do~while.
This should go into a separate patch. Please don't introduce the
next_flag variable that you remove in a later patch.
>
> Signed-off-by: Tomoya MORINAGA <tomoya-linux-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
> ---
> drivers/net/can/pch_can.c | 304 +++++++++++++++++++++++----------------------
> 1 files changed, 155 insertions(+), 149 deletions(-)
>
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index 6437e60..0ac2a75 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> @@ -134,10 +134,7 @@ struct pch_can_if_regs {
> u32 id1;
> u32 id2;
> u32 mcont;
> - u32 dataa1;
> - u32 dataa2;
> - u32 datab1;
> - u32 datab2;
> + u32 data[4];
> u32 rsv[13];
> };
>
> @@ -420,10 +417,10 @@ static void pch_can_clear_buffers(struct pch_can_priv *priv)
> iowrite32(0x0, &priv->regs->ifregs[0].id1);
> iowrite32(0x0, &priv->regs->ifregs[0].id2);
> iowrite32(0x0, &priv->regs->ifregs[0].mcont);
> - iowrite32(0x0, &priv->regs->ifregs[0].dataa1);
> - iowrite32(0x0, &priv->regs->ifregs[0].dataa2);
> - iowrite32(0x0, &priv->regs->ifregs[0].datab1);
> - iowrite32(0x0, &priv->regs->ifregs[0].datab2);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[0]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[1]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[2]);
> + iowrite32(0x0, &priv->regs->ifregs[0].data[3]);
> iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK |
> PCH_CMASK_ARB | PCH_CMASK_CTRL,
> &priv->regs->ifregs[0].cmask);
> @@ -437,10 +434,10 @@ static void pch_can_clear_buffers(struct pch_can_priv *priv)
> iowrite32(0x0, &priv->regs->ifregs[1].id1);
> iowrite32(0x0, &priv->regs->ifregs[1].id2);
> iowrite32(0x0, &priv->regs->ifregs[1].mcont);
> - iowrite32(0x0, &priv->regs->ifregs[1].dataa1);
> - iowrite32(0x0, &priv->regs->ifregs[1].dataa2);
> - iowrite32(0x0, &priv->regs->ifregs[1].datab1);
> - iowrite32(0x0, &priv->regs->ifregs[1].datab2);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[0]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[1]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[2]);
> + iowrite32(0x0, &priv->regs->ifregs[1].data[3]);
> iowrite32(PCH_CMASK_RDWR | PCH_CMASK_MASK |
> PCH_CMASK_ARB | PCH_CMASK_CTRL,
> &priv->regs->ifregs[1].cmask);
> @@ -697,190 +694,202 @@ static irqreturn_t pch_can_interrupt(int irq, void *dev_id)
> return IRQ_HANDLED;
> }
>
> -static int pch_can_rx_normal(struct net_device *ndev, u32 int_stat)
> +static void pch_fifo_thresh(struct pch_can_priv *priv, int obj_id)
> +{
> + if (obj_id < PCH_FIFO_THRESH) {
> + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL |
> + PCH_CMASK_ARB, &priv->regs->ifregs[0].cmask);
> +
> + /* Clearing the Dir bit. */
> + pch_can_bit_clear(&priv->regs->ifregs[0].id2, PCH_ID2_DIR);
> +
> + /* Clearing NewDat & IntPnd */
> + pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> + PCH_IF_MCONT_INTPND);
> + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, obj_id);
> + } else if (obj_id > PCH_FIFO_THRESH) {
> + pch_can_int_clr(priv, obj_id);
> + } else if (obj_id == PCH_FIFO_THRESH) {
> + int cnt;
> + for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
> + pch_can_int_clr(priv, cnt + 1);
> + }
> +}
> +
> +static int pch_can_rx_msg_lost(struct net_device *ndev, int obj_id)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &(priv->ndev->stats);
> + struct sk_buff *skb;
> + struct can_frame *cf;
> +
> + netdev_dbg(priv->ndev, "Msg Obj is overwritten.\n");
> + pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> + PCH_IF_MCONT_MSGLOST);
> + iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL,
> + &priv->regs->ifregs[0].cmask);
> + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, obj_id);
> +
> + skb = alloc_can_err_skb(ndev, &cf);
> + if (!skb)
> + return -ENOMEM;
> +
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> + stats->rx_over_errors++;
> + stats->rx_errors++;
> +
> + netif_receive_skb(skb);
> +
> + return 0;
> +}
> +
> +static int pch_can_rx_normal(struct net_device *ndev, u32 obj_num, int quota)
> {
> u32 reg;
> canid_t id;
> - u32 ide;
> - u32 rtr;
> - int i, j, k;
> int rcv_pkts = 0;
> + int rtn;
> + int next_flag = 0;
> struct sk_buff *skb;
> struct can_frame *cf;
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct net_device_stats *stats = &(priv->ndev->stats);
> + int i;
> + u32 id2;
> + u16 data_reg;
>
> - /* Reading the messsage object from the Message RAM */
> - iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, int_stat);
> + do {
> + /* Reading the messsage object from the Message RAM */
> + iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
> + pch_can_check_if_busy(&priv->regs->ifregs[0].creq, obj_num);
>
> - /* Reading the MCONT register. */
> - reg = ioread32(&priv->regs->ifregs[0].mcont);
> - reg &= 0xffff;
> + /* Reading the MCONT register. */
> + reg = ioread32(&priv->regs->ifregs[0].mcont);
> +
> + if (reg & PCH_IF_MCONT_EOB)
> + break;
>
> - for (k = int_stat; !(reg & PCH_IF_MCONT_EOB); k++) {
> /* If MsgLost bit set. */
> if (reg & PCH_IF_MCONT_MSGLOST) {
> - dev_err(&priv->ndev->dev, "Msg Obj is overwritten.\n");
> - pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> - PCH_IF_MCONT_MSGLOST);
> - iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL,
> - &priv->regs->ifregs[0].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k);
> -
> - skb = alloc_can_err_skb(ndev, &cf);
> + rtn = pch_can_rx_msg_lost(ndev, obj_num);
> + if (!rtn)
> + netdev_err(ndev, "Can't get memory\n");
Your logic is broken, the function returns 0 on success, which makes it
print a error message.
In an OOM situation the system is under pressure anyway. On low end
systems it not good to print a message to the log. AFAICS no other can
driver does this.
> + rcv_pkts++;
> + quota--;
> + next_flag = 1;
> + } else if (!(reg & PCH_IF_MCONT_NEWDAT))
> + next_flag = 1;
Please don't introduce the next_flag, that is removed in a later patch.
> +
> + if (!next_flag) {
> + skb = alloc_can_skb(priv->ndev, &cf);
> if (!skb)
> return -ENOMEM;
>
> - priv->can.can_stats.error_passive++;
> - priv->can.state = CAN_STATE_ERROR_PASSIVE;
> - cf->can_id |= CAN_ERR_CRTL;
> - cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
> - cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
> - stats->rx_packets++;
> - stats->rx_bytes += cf->can_dlc;
> + /* Get Received data */
> + id2 = ioread32(&priv->regs->ifregs[0].id2);
> + if (id2 & PCH_ID2_XTD) {
> + id = (ioread32(&priv->regs->ifregs[0].id1) &
> + 0xffff);
> + id |= (((id2) & 0x1fff) << 16);
> + cf->can_id = id | CAN_EFF_FLAG;
> + } else {
> + id = ((id2 & (CAN_SFF_MASK << 2)) >> 2);
id = (id2 >> 2) & CAN_SFF_MASK;
this is IMHO more readable.
> + cf->can_id = id;
> + }
> +
> + if (id2 & PCH_ID2_DIR)
> + cf->can_id |= CAN_RTR_FLAG;
> +
> + cf->can_dlc = get_can_dlc((ioread32(&priv->regs->
> + ifregs[0].mcont)) & 0xF);
> +
> + for (i = 0; i < cf->can_dlc; i += 2) {
> + data_reg = ioread16(&priv->regs->ifregs[0].
> + data[i / 2]);
> + cf->data[i] = data_reg & 0xff;
& 0xff isn't needed, as cf->data is 8 bit wide.
> + cf->data[i + 1] = data_reg >> 8;
> + }
>
> netif_receive_skb(skb);
> rcv_pkts++;
> - goto RX_NEXT;
> - }
> - if (!(reg & PCH_IF_MCONT_NEWDAT))
> - goto RX_NEXT;
> -
> - skb = alloc_can_skb(priv->ndev, &cf);
> - if (!skb)
> - return -ENOMEM;
> -
> - /* Get Received data */
> - ide = ((ioread32(&priv->regs->ifregs[0].id2)) & PCH_ID2_XTD) >>
> - 14;
> - if (ide) {
> - id = (ioread32(&priv->regs->ifregs[0].id1) & 0xffff);
> - id |= (((ioread32(&priv->regs->ifregs[0].id2)) &
> - 0x1fff) << 16);
> - cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG;
> - } else {
> - id = (((ioread32(&priv->regs->ifregs[0].id2)) &
> - (CAN_SFF_MASK << 2)) >> 2);
> - cf->can_id = (id & CAN_SFF_MASK);
> - }
> + stats->rx_packets++;
> + quota--;
> + stats->rx_bytes += cf->can_dlc;
>
> - rtr = (ioread32(&priv->regs->ifregs[0].id2) & PCH_ID2_DIR);
> - if (rtr) {
> - cf->can_dlc = 0;
> - cf->can_id |= CAN_RTR_FLAG;
> - } else {
> - cf->can_dlc =
> - ((ioread32(&priv->regs->ifregs[0].mcont)) & 0x0f);
> + pch_fifo_thresh(priv, obj_num);
> }
> + obj_num++;
> + next_flag = 0;
> + } while (quota > 0);
>
> - for (i = 0, j = 0; i < cf->can_dlc; j++) {
> - reg = ioread32(&priv->regs->ifregs[0].dataa1 + j*4);
> - cf->data[i++] = cpu_to_le32(reg & 0xff);
> - if (i == cf->can_dlc)
> - break;
> - cf->data[i++] = cpu_to_le32((reg >> 8) & 0xff);
> - }
> + return rcv_pkts;
> +}
>
> - netif_receive_skb(skb);
> - rcv_pkts++;
> - stats->rx_packets++;
> - stats->rx_bytes += cf->can_dlc;
> -
> - if (k < PCH_FIFO_THRESH) {
> - iowrite32(PCH_CMASK_RDWR | PCH_CMASK_CTRL |
> - PCH_CMASK_ARB, &priv->regs->ifregs[0].cmask);
> -
> - /* Clearing the Dir bit. */
> - pch_can_bit_clear(&priv->regs->ifregs[0].id2,
> - PCH_ID2_DIR);
> -
> - /* Clearing NewDat & IntPnd */
> - pch_can_bit_clear(&priv->regs->ifregs[0].mcont,
> - PCH_IF_MCONT_INTPND);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k);
> - } else if (k > PCH_FIFO_THRESH) {
> - pch_can_int_clr(priv, k);
> - } else if (k == PCH_FIFO_THRESH) {
> - int cnt;
> - for (cnt = 0; cnt < PCH_FIFO_THRESH; cnt++)
> - pch_can_int_clr(priv, cnt+1);
> - }
> -RX_NEXT:
> - /* Reading the messsage object from the Message RAM */
> - iowrite32(PCH_CMASK_RX_TX_GET, &priv->regs->ifregs[0].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[0].creq, k);
> - reg = ioread32(&priv->regs->ifregs[0].mcont);
> - }
> +static void pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct net_device_stats *stats = &(priv->ndev->stats);
> + u32 dlc;
>
> - return rcv_pkts;
> + can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
> + iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
> + &priv->regs->ifregs[1].cmask);
> + pch_can_check_if_busy(&priv->regs->ifregs[1].creq, int_stat);
> + dlc = get_can_dlc(ioread32(&priv->regs->ifregs[1].mcont) &
> + PCH_IF_MCONT_DLC);
> + stats->tx_bytes += dlc;
> + stats->tx_packets++;
> + if (int_stat == PCH_TX_OBJ_END)
> + netif_wake_queue(ndev);
> }
> +
> static int pch_can_rx_poll(struct napi_struct *napi, int quota)
> {
> struct net_device *ndev = napi->dev;
> struct pch_can_priv *priv = netdev_priv(ndev);
> - struct net_device_stats *stats = &(priv->ndev->stats);
> - u32 dlc;
> u32 int_stat;
> int rcv_pkts = 0;
> u32 reg_stat;
>
> int_stat = pch_can_int_pending(priv);
> if (!int_stat)
> - return 0;
> + goto end;
>
> -INT_STAT:
> - if (int_stat == PCH_STATUS_INT) {
> + if ((int_stat == PCH_STATUS_INT) && (quota > 0)) {
> reg_stat = ioread32(&priv->regs->stat);
> if (reg_stat & (PCH_BUS_OFF | PCH_LEC_ALL)) {
> - if ((reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL)
> + if (reg_stat & PCH_BUS_OFF ||
> + (reg_stat & PCH_LEC_ALL) != PCH_LEC_ALL) {
> pch_can_error(ndev, reg_stat);
> + quota--;
> + }
> }
>
> - if (reg_stat & PCH_TX_OK) {
> - iowrite32(PCH_CMASK_RX_TX_GET,
> - &priv->regs->ifregs[1].cmask);
> - pch_can_check_if_busy(&priv->regs->ifregs[1].creq,
> - ioread32(&priv->regs->intr));
> + if (reg_stat & PCH_TX_OK)
> pch_can_bit_clear(&priv->regs->stat, PCH_TX_OK);
> - }
>
> if (reg_stat & PCH_RX_OK)
> pch_can_bit_clear(&priv->regs->stat, PCH_RX_OK);
>
> int_stat = pch_can_int_pending(priv);
> - if (int_stat == PCH_STATUS_INT)
> - goto INT_STAT;
> }
>
> -MSG_OBJ:
> + if (quota == 0)
> + goto end;
> +
> if ((int_stat >= PCH_RX_OBJ_START) && (int_stat <= PCH_RX_OBJ_END)) {
> - rcv_pkts = pch_can_rx_normal(ndev, int_stat);
> - if (rcv_pkts < 0)
> - return 0;
> + rcv_pkts += pch_can_rx_normal(ndev, int_stat, quota);
> + quota -= rcv_pkts;
> + if (quota < 0)
> + goto end;
> } else if ((int_stat >= PCH_TX_OBJ_START) &&
> (int_stat <= PCH_TX_OBJ_END)) {
> /* Handle transmission interrupt */
> - can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
> - iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
> - &priv->regs->ifregs[1].cmask);
> - dlc = ioread32(&priv->regs->ifregs[1].mcont) &
> - PCH_IF_MCONT_DLC;
> - pch_can_check_if_busy(&priv->regs->ifregs[1].creq, int_stat);
> - if (dlc > 8)
> - dlc = 8;
> - stats->tx_bytes += dlc;
> - stats->tx_packets++;
> - if (int_stat == PCH_TX_OBJ_END)
> - netif_wake_queue(ndev);
> + pch_can_tx_complete(ndev, int_stat);
> }
>
> - int_stat = pch_can_int_pending(priv);
> - if (int_stat == PCH_STATUS_INT)
> - goto INT_STAT;
> - else if (int_stat >= 1 && int_stat <= 32)
> - goto MSG_OBJ;
> -
> +end:
> napi_complete(napi);
> pch_can_set_int_enables(priv, PCH_CAN_ALL);
>
The following hunk is a nice and clean patch. It fixes the endianess
issue, nothing more.
> @@ -1013,10 +1022,10 @@ static int pch_close(struct net_device *ndev)
>
> static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> {
> - int i, j;
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct can_frame *cf = (struct can_frame *)skb->data;
> int tx_buffer_avail = 0;
> + int i;
>
> if (can_dropped_invalid_skb(ndev, skb))
> return NETDEV_TX_OK;
> @@ -1057,13 +1066,10 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> if (cf->can_id & CAN_RTR_FLAG)
> pch_can_bit_clear(&priv->regs->ifregs[1].id2, PCH_ID2_DIR);
>
> - for (i = 0, j = 0; i < cf->can_dlc; j++) {
> - iowrite32(le32_to_cpu(cf->data[i++]),
> - (&priv->regs->ifregs[1].dataa1) + j*4);
> - if (i == cf->can_dlc)
> - break;
> - iowrite32(le32_to_cpu(cf->data[i++] << 8),
> - (&priv->regs->ifregs[1].dataa1) + j*4);
> + /* Copy data to register */
> + for (i = 0; i < cf->can_dlc; i += 2) {
> + iowrite16(cf->data[i] | (cf->data[i + 1] << 8),
> + &priv->regs->ifregs[1].data[i / 2]);
> }
>
> can_put_echo_skb(skb, ndev, tx_buffer_avail - PCH_RX_OBJ_END - 1);
cheers, Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
[-- Attachment #2: Type: text/plain, Size: 188 bytes --]
_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core
next prev parent reply other threads:[~2010-11-26 9:52 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-26 2:12 [PATCH net-next-2.6 06/19 v5] can: EG20T PCH: Fix endianness issue Tomoya MORINAGA
2010-11-26 9:52 ` Marc Kleine-Budde [this message]
2010-11-26 9:52 ` Marc Kleine-Budde
2010-11-29 0:19 ` Tomoya MORINAGA
2010-11-29 0:19 ` Tomoya MORINAGA
-- strict thread matches above, loose matches on Subject: below --
2010-11-26 2:12 Tomoya MORINAGA
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4CEF835C.7000304@pengutronix.de \
--to=mkl@pengutronix.de \
--cc=21cnbao@gmail.com \
--cc=andrew.chih.howe.khor@intel.com \
--cc=chripell@fsfe.org \
--cc=davem@davemloft.net \
--cc=joel.clark@intel.com \
--cc=kok.howg.ewe@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=margie.foster@intel.com \
--cc=netdev@vger.kernel.org \
--cc=qi.wang@intel.com \
--cc=sameo@linux.intel.com \
--cc=socketcan-core@lists.berlios.de \
--cc=tomoya-linux@dsn.okisemi.com \
--cc=w.sang@pengutronix.de \
--cc=wg@grandegger.com \
--cc=yong.y.wang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.