npcm7xx-emc: diorite c0 workaround
Remove garbage byte sent by c0 and re-calculate checksum.
This assumes that there are always 1 byte garbage, which is the case
based on current testing.
Change-Id: I92465e3350ce606e288853ea040ba2be88a99e8f
Signed-off-by: Yuxiao Zhang <yuxiaozhang@google.com>
(cherry picked from commit 90f2cffc710aafb6ceec75bf0d7503506fbaaed5)
(cherry picked from commit 141daea52e9e3ffad6db25bac24f404d1726fcfa)
diff --git a/recipes-kernel/linux/5.15/0001-Diorite-workaround-for-c0-card.patch b/recipes-kernel/linux/5.15/0001-Diorite-workaround-for-c0-card.patch
new file mode 100644
index 0000000..d87ea97
--- /dev/null
+++ b/recipes-kernel/linux/5.15/0001-Diorite-workaround-for-c0-card.patch
@@ -0,0 +1,110 @@
+From 6394781fddc8bb2d48f08994595fff4e77c238e5 Mon Sep 17 00:00:00 2001
+From: invalid_git config <unknown@unknown>
+Date: Tue, 29 Aug 2023 20:48:42 +0000
+Subject: [PATCH] Diorite workaround for c0 card
+
+Diorite c0 card has one dribble bytes at the end of the packet, this
+patch is a workaround of removing it and redo the checksum.
+---
+ drivers/net/ethernet/nuvoton/npcm7xx_emc.c | 50 ++++++++++++++++++++--
+ 1 file changed, 47 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/nuvoton/npcm7xx_emc.c b/drivers/net/ethernet/nuvoton/npcm7xx_emc.c
+index 2c58a82a56fd..a2ce9d976d18 100644
+--- a/drivers/net/ethernet/nuvoton/npcm7xx_emc.c
++++ b/drivers/net/ethernet/nuvoton/npcm7xx_emc.c
+@@ -92,6 +92,7 @@ static struct dentry *npcm7xx_fs_dir;
+ #define MCMDR_RXON BIT(0)
+ #define MCMDR_ALP BIT(1)
+ #define MCMDR_ACP BIT(3)
++#define MCMDR_AEP BIT(4)
+ #define MCMDR_SPCRC BIT(5)
+ #define MCMDR_TXON BIT(8)
+ #define MCMDR_NDEF BIT(9)
+@@ -1059,6 +1060,12 @@ static void npcm7xx_rx_enable(struct net_device *netdev)
+ struct npcm7xx_ether *ether = netdev_priv(netdev);
+
+ /* enable RX */
++ writel(readl((ether->reg + REG_MCMDR)) & ~(MCMDR_SPCRC),
++ (ether->reg + REG_MCMDR));
++
++ writel(readl((ether->reg + REG_MCMDR)) | (MCMDR_AEP),
++ (ether->reg + REG_MCMDR));
++
+ writel(readl((ether->reg + REG_MCMDR)) | MCMDR_RXON,
+ (ether->reg + REG_MCMDR));
+ }
+@@ -1585,18 +1592,18 @@ static int npcm7xx_poll(struct napi_struct *napi, int budget)
+ */
+ if (likely((status & (RXDS_RXGD | RXDS_CRCE | RXDS_ALIE |
+ RXDS_RP | (IS_VLAN ? 0 : RXDS_PTLE))) ==
+- RXDS_RXGD) && likely(length <= MAX_PACKET_SIZE)) {
++ RXDS_RXGD) && likely(length <= MAX_PACKET_SIZE_W_CRC)) {
+ if (s) {
+ dma_unmap_single(&pdev->dev,
+ (dma_addr_t)le32_to_cpu(rxbd->buffer),
+ roundup(MAX_PACKET_SIZE_W_CRC, 4),
+ DMA_FROM_DEVICE);
+
+- skb_put(s, length);
++ skb_put(s, length - 4);
+ s->protocol = eth_type_trans(s, netdev);
+ netif_receive_skb(s);
+ ether->stats.rx_packets++;
+- ether->stats.rx_bytes += length;
++ ether->stats.rx_bytes += (length - 4);
+ } else
+ ether->stats.rx_dropped++;
+ rx_cnt++;
+@@ -1605,6 +1609,40 @@ static int npcm7xx_poll(struct napi_struct *napi, int budget)
+ /* now we allocate new skb instead if the used one. */
+ get_new_skb(netdev, ether->cur_rx);
+ } else {
++ if (likely((status & (RXDS_RXGD | RXDS_RP | RXDS_CRCE)) == (RXDS_RXGD | RXDS_CRCE))) {
++ if (s) {
++ dma_unmap_single(&pdev->dev,
++ (dma_addr_t)le32_to_cpu(rxbd->buffer),
++ roundup(MAX_PACKET_SIZE_W_CRC, 4),
++ DMA_FROM_DEVICE);
++ skb_put(s, length - 1);
++ uint8_t dribble = 1;
++ for (dribble = 1; dribble <= 2; ++dribble) {
++ uint32_t crc = ether_crc_le(length - 4 - dribble, s->data) ^ 0xFFFFFFFF;
++ if (likely(crc == get_unaligned_le32(s->data + length - 4 - dribble))) {
++ break;
++ }
++ }
++ if (likely(dribble <= 2)) {
++ skb_trim(s, length - 4 - dribble);
++ s->protocol = eth_type_trans(s, netdev);
++ netif_receive_skb(s);
++ ether->stats.rx_packets++;
++ ether->stats.rx_bytes += (length - 4 - dribble);
++ } else {
++ dev_kfree_skb_any(s);
++ get_new_skb(netdev, ether->cur_rx);
++ goto rx_error;
++ }
++ } else {
++ ether->stats.rx_dropped++;
++ }
++ rx_cnt++;
++ ether->rx_count_pool++;
++ get_new_skb(netdev, ether->cur_rx);
++ goto rx_poll_done;
++ }
++rx_error:
+ ether->rx_err_count++;
+ ether->stats.rx_errors++;
+ dev_dbg(&pdev->dev, "rx_errors = %lu status = 0x%08X\n",
+@@ -1630,6 +1671,7 @@ static int npcm7xx_poll(struct napi_struct *napi, int budget)
+ }
+ }
+
++rx_poll_done:
+ /* make sure other values are set before we set owner */
+ wmb();
+
+--
+2.42.0.459.ge4e396fd5e-goog
+
diff --git a/recipes-kernel/linux/linux-gbmc_5.15.bb b/recipes-kernel/linux/linux-gbmc_5.15.bb
index 2e2d4a0..6be0306 100644
--- a/recipes-kernel/linux/linux-gbmc_5.15.bb
+++ b/recipes-kernel/linux/linux-gbmc_5.15.bb
@@ -5,11 +5,17 @@
SRCREV = "1720a480503b8bcf69419c11af5fdaf54fa43d03"
LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
+PACKAGECONFIG[diorite_c0] = ""
+
FILESEXTRAPATHS:prepend := "${THISDIR}/5.15:"
SRC_URI += " \
file://DOWNSTREAM_0002-mtd-spi-nor-macronix-Add-google-compatible-flash-IDs.patch \
"
+SRC_URI:append:npcm7xx = "\
+ ${@bb.utils.contains('PACKAGECONFIG', 'diorite_c0', 'file://0001-Diorite-workaround-for-c0-card.patch', '', d)} \
+ "
+
SRC_URI:append:aspeed-g6 = " \
file://0001-net-ftgmac100-Support-for-fixed-PHYs.patch \
file://DOWNSTREAM_0002-kernel-Ensure-only-3-byte-read-command-can-be-sent.patch \