update 2.6.27 patches with upstream fixes from git repository and mailing-lists. via-rhine is still broken, thus not switching to 2.6.27 as default.

SVN-Revision: 14173
This commit is contained in:
Florian Fainelli 2009-01-25 13:36:27 +00:00
parent c198a51398
commit 3d2066526c
20 changed files with 794 additions and 250 deletions

View file

@ -8,6 +8,7 @@ CONFIG_ARCH_REQUIRE_GPIOLIB=y
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_ARCH_SUPPORTS_OPROFILE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
# CONFIG_ATA_PIIX is not set
CONFIG_ATA_SFF=y
@ -67,7 +68,6 @@ CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_GPIOLIB=y
# CONFIG_GPIO_BT8XX is not set
CONFIG_GPIO_SYSFS=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
@ -108,7 +108,6 @@ CONFIG_KORINA=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_TMIO is not set
CONFIG_MIKROTIK_RB532=y
CONFIG_MINI_FO=y
CONFIG_MIPS=y
# CONFIG_MIPS_COBALT is not set
CONFIG_MIPS_L1_CACHE_SHIFT=4
@ -140,8 +139,6 @@ CONFIG_MTD_CHAR=y
# CONFIG_MTD_CMDLINE_PARTS is not set
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
@ -177,12 +174,15 @@ CONFIG_MTD_PHYSMAP_START=0x8000000
# CONFIG_NATSEMI is not set
# CONFIG_NET_SCH_ESFQ_NFCT is not set
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CT_ACCT=y
# CONFIG_NO_IOPORT is not set
CONFIG_PAGEFLAGS_EXTENDED=y
# CONFIG_PAGE_SIZE_16KB is not set
CONFIG_PAGE_SIZE_4KB=y
# CONFIG_PAGE_SIZE_64KB is not set
# CONFIG_PAGE_SIZE_8KB is not set
CONFIG_PATA_PLATFORM=y
CONFIG_PATA_RB532=y
# CONFIG_PATA_SCH is not set
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
@ -192,12 +192,15 @@ CONFIG_PCSPKR_PLATFORM=y
# CONFIG_PNX8550_JBS is not set
# CONFIG_PNX8550_STB810 is not set
# CONFIG_PROBE_INITRD_HEADER is not set
# CONFIG_PROM_EMU is not set
# CONFIG_R6040 is not set
CONFIG_RC32434_WDT=y
CONFIG_RFKILL_LEDS=y
CONFIG_RTC_LIB=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_SCSI=y
CONFIG_SCSI_WAIT_SCAN=m
# CONFIG_SERIAL_8250_EXTENDED is not set
# CONFIG_SGI_IP22 is not set
# CONFIG_SGI_IP27 is not set
@ -227,8 +230,18 @@ CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
CONFIG_TRAD_SIGNALS=y
# CONFIG_VGASTATE is not set
CONFIG_VIA_RHINE=y
# CONFIG_VIA_RHINE_MMIO is not set
CONFIG_VIA_RHINE_MMIO=y
CONFIG_VIDEO_MEDIA=m
CONFIG_VIDEO_V4L2=m
CONFIG_VIDEO_V4L2_COMMON=m
CONFIG_YAFFS_9BYTE_TAGS=y
# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
CONFIG_YAFFS_AUTO_YAFFS2=y
CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=0
# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
CONFIG_YAFFS_FS=y
CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
CONFIG_YAFFS_YAFFS1=y
CONFIG_YAFFS_YAFFS2=y
CONFIG_ZONE_DMA_FLAG=0

View file

@ -1,245 +0,0 @@
--- linux-2.6.27.5/drivers/net/korina.c 2008-11-07 18:55:34.000000000 +0100
+++ ../build_dir/linux-rb532/linux-2.6.27.5/drivers/net/korina.c 2008-11-16 00:38:19.000000000 +0100
@@ -327,12 +327,11 @@
dmas = readl(&lp->rx_dma_regs->dmas);
if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
- netif_rx_schedule_prep(dev, &lp->napi);
-
dmasm = readl(&lp->rx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_DONE |
DMA_STAT_HALT | DMA_STAT_ERR),
&lp->rx_dma_regs->dmasm);
+ netif_rx_schedule(dev, &lp->napi);
if (dmas & DMA_STAT_ERR)
printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
@@ -350,14 +349,24 @@
struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done];
struct sk_buff *skb, *skb_new;
u8 *pkt_buf;
- u32 devcs, pkt_len, dmas, rx_free_desc;
+ u32 devcs, pkt_len, dmas, pktuncrc_len;
int count;
dma_cache_inv((u32)rd, sizeof(*rd));
for (count = 0; count < limit; count++) {
-
+ skb_new = NULL;
devcs = rd->devcs;
+ pkt_len = RCVPKT_LENGTH(devcs);
+ skb = lp->rx_skb[lp->rx_next_done];
+
+ if ((devcs & ETH_RX_LD) != ETH_RX_LD) {
+ /* check that this is a whole packet
+ * WARNING: DMA_FD bit incorrectly set
+ * in Rc32434 (errata ref #077) */
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+ }
/* Update statistics counters */
if (devcs & ETH_RX_CRC)
@@ -375,75 +384,79 @@
if (devcs & ETH_RX_MP)
dev->stats.multicast++;
- if ((devcs & ETH_RX_LD) != ETH_RX_LD) {
- /* check that this is a whole packet
- * WARNING: DMA_FD bit incorrectly set
- * in Rc32434 (errata ref #077) */
- dev->stats.rx_errors++;
- dev->stats.rx_dropped++;
- }
-
- while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
- /* init the var. used for the later
- * operations within the while loop */
- skb_new = NULL;
- pkt_len = RCVPKT_LENGTH(devcs);
- skb = lp->rx_skb[lp->rx_next_done];
-
- if ((devcs & ETH_RX_ROK)) {
- /* must be the (first and) last
- * descriptor then */
- pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
+ else if ((devcs & ETH_RX_ROK)) {
+ /* must be the (first and) last
+ * descriptor then */
+ pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
+ pktuncrc_len = pkt_len - 4;
- /* invalidate the cache */
- dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
+ /* invalidate the cache */
+ dma_cache_inv((unsigned long)pkt_buf, pktuncrc_len);
- /* Malloc up new buffer. */
- skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
+ /* Malloc up new buffer. */
+ skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
- if (!skb_new)
- break;
+ if (skb_new) {
/* Do not count the CRC */
- skb_put(skb, pkt_len - 4);
+ skb_put(skb, pktuncrc_len);
skb->protocol = eth_type_trans(skb, dev);
/* Pass the packet to upper layers */
netif_receive_skb(skb);
+
dev->last_rx = jiffies;
dev->stats.rx_packets++;
- dev->stats.rx_bytes += pkt_len;
-
- /* Update the mcast stats */
- if (devcs & ETH_RX_MP)
- dev->stats.multicast++;
-
+ dev->stats.rx_bytes += pktuncrc_len;
+
lp->rx_skb[lp->rx_next_done] = skb_new;
+ } else {
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
}
+ } else {
+ dev->stats.rx_errors++;
+ dev->stats.rx_dropped++;
+
+ /* Update statistics counters */
+ if (devcs & ETH_RX_CRC)
+ dev->stats.rx_crc_errors++;
+ else if (devcs & ETH_RX_LOR)
+ dev->stats.rx_length_errors++;
+ else if (devcs & ETH_RX_LE)
+ dev->stats.rx_length_errors++;
+ else if (devcs & ETH_RX_OVR)
+ dev->stats.rx_over_errors++;
+ else if (devcs & ETH_RX_CV)
+ dev->stats.rx_frame_errors++;
+ else if (devcs & ETH_RX_CES)
+ dev->stats.rx_length_errors++;
+ else if (devcs & ETH_RX_MP)
+ dev->stats.multicast++;
+ }
- rd->devcs = 0;
+ rd->devcs = 0;
- /* Restore descriptor's curr_addr */
- if (skb_new)
- rd->ca = CPHYSADDR(skb_new->data);
- else
- rd->ca = CPHYSADDR(skb->data);
+ /* Restore descriptor's curr_addr */
+ if (skb_new)
+ rd->ca = CPHYSADDR(skb_new->data);
+ else
+ rd->ca = CPHYSADDR(skb->data);
- rd->control = DMA_COUNT(KORINA_RBSIZE) |
+ rd->control = DMA_COUNT(KORINA_RBSIZE) |
DMA_DESC_COD | DMA_DESC_IOD;
- lp->rd_ring[(lp->rx_next_done - 1) &
- KORINA_RDS_MASK].control &=
- ~DMA_DESC_COD;
-
- lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
- dma_cache_wback((u32)rd, sizeof(*rd));
- rd = &lp->rd_ring[lp->rx_next_done];
- writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
- }
+ lp->rd_ring[(lp->rx_next_done - 1) &
+ KORINA_RDS_MASK].control &= ~DMA_DESC_COD;
+
+ lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
+ dma_cache_wback((u32)rd, sizeof(*rd));
+ rd = &lp->rd_ring[lp->rx_next_done];
+ writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
}
dmas = readl(&lp->rx_dma_regs->dmas);
if (dmas & DMA_STAT_HALT) {
+ /* Mask off halt and errors bits */
writel(~(DMA_STAT_HALT | DMA_STAT_ERR),
&lp->rx_dma_regs->dmas);
@@ -469,8 +482,9 @@
if (work_done < budget) {
netif_rx_complete(dev, napi);
+ /* Mask off interrupts */
writel(readl(&lp->rx_dma_regs->dmasm) &
- ~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
+ (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
&lp->rx_dma_regs->dmasm);
}
return work_done;
@@ -534,10 +548,11 @@
{
struct korina_private *lp = netdev_priv(dev);
struct dma_desc *td = &lp->td_ring[lp->tx_next_done];
+ unsigned long flags;
u32 devcs;
u32 dmas;
- spin_lock(&lp->lock);
+ spin_lock_irqsave(&lp->lock, flags);
/* Process all desc that are done */
while (IS_DMA_FINISHED(td->control)) {
@@ -610,7 +625,7 @@
~(DMA_STAT_FINI | DMA_STAT_ERR),
&lp->tx_dma_regs->dmasm);
- spin_unlock(&lp->lock);
+ spin_unlock_irqrestore(&lp->lock, flags);
}
static irqreturn_t
@@ -624,11 +639,10 @@
dmas = readl(&lp->tx_dma_regs->dmas);
if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
- korina_tx(dev);
-
dmasm = readl(&lp->tx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
&lp->tx_dma_regs->dmasm);
+ korina_tx(dev);
if (lp->tx_chain_status == desc_filled &&
(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {
@@ -1078,11 +1092,18 @@
static int korina_probe(struct platform_device *pdev)
{
- struct korina_device *bif = platform_get_drvdata(pdev);
+ struct korina_device *bif;
struct korina_private *lp;
struct net_device *dev;
struct resource *r;
int rc;
+ DECLARE_MAC_BUF(mac);
+
+ bif = (struct korina_device *)pdev->dev.platform_data;
+ if (!bif) {
+ printk(KERN_ERR DRV_NAME ": missing platform_data\n");
+ return -ENODEV;
+ }
dev = alloc_etherdev(sizeof(struct korina_private));
if (!dev) {
@@ -1172,6 +1193,7 @@
": cannot register net device %d\n", rc);
goto probe_err_register;
}
+ printk(KERN_INFO DRV_NAME ": registered %s, IRQ %d MAC %s\n", dev->name, dev->irq, print_mac(mac, dev->dev_addr));
out:
return rc;

View file

@ -0,0 +1,31 @@
The new value is the one used in the external patch before and allows at
least a standard MTU of 1500 to be handled correctly. Impact of this
change gets visible when bigger packets are to be received, issuing:
| ping -s 492 <IP>
and bigger payload sized led to 100% packet loss.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index fefb33d..e30c2f4 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -84,7 +84,10 @@
#define KORINA_NUM_RDS 64 /* number of receive descriptors */
#define KORINA_NUM_TDS 64 /* number of transmit descriptors */
-#define KORINA_RBSIZE 536 /* size of one resource buffer = Ether MTU */
+/* KORINA_RBSIZE is the hardware's default maximum receive
+ * frame size in bytes. Having this hardcoded means that there
+ * is no support for MTU sizes greater than 1500. */
+#define KORINA_RBSIZE 1536 /* size of one resource buffer = Ether MTU */
#define KORINA_RDS_MASK (KORINA_NUM_RDS - 1)
#define KORINA_TDS_MASK (KORINA_NUM_TDS - 1)
#define RD_RING_SIZE (KORINA_NUM_RDS * sizeof(struct dma_desc))
--
1.5.6.4

View file

@ -0,0 +1,33 @@
Without this the driver will crash when the NIC is being restarted.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index e30c2f4..65b8487 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -904,6 +904,8 @@ static int korina_restart(struct net_device *dev)
korina_free_ring(dev);
+ napi_disable(&lp->napi);
+
ret = korina_init(dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: cannot restart device\n",
@@ -1070,6 +1072,8 @@ static int korina_close(struct net_device *dev)
korina_free_ring(dev);
+ napi_disable(&lp->napi);
+
free_irq(lp->rx_irq, dev);
free_irq(lp->tx_irq, dev);
free_irq(lp->ovr_irq, dev);
--
1.5.6.4

View file

@ -0,0 +1,138 @@
This function needs an early exit condition to function properly, or
else caller assumes napi workload wasn't enough to handle all received
packets and korina_rx is called again (and again and again and ...).
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
--- a/drivers/net/korina.c 2009-01-19 23:19:10.000000000 +0100
+++ b/drivers/net/korina.c 2009-01-19 23:25:31.000000000 +0100
@@ -353,15 +353,20 @@
struct dma_desc *rd = &lp->rd_ring[lp->rx_next_done];
struct sk_buff *skb, *skb_new;
u8 *pkt_buf;
- u32 devcs, pkt_len, dmas, rx_free_desc;
+ u32 devcs, pkt_len, dmas;
int count;
dma_cache_inv((u32)rd, sizeof(*rd));
for (count = 0; count < limit; count++) {
+ skb = lp->rx_skb[lp->rx_next_done];
+ skb_new = NULL;
devcs = rd->devcs;
+ if ((KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) == 0)
+ break;
+
/* Update statistics counters */
if (devcs & ETH_RX_CRC)
dev->stats.rx_crc_errors++;
@@ -384,64 +389,53 @@
* in Rc32434 (errata ref #077) */
dev->stats.rx_errors++;
dev->stats.rx_dropped++;
- }
-
- while ((rx_free_desc = KORINA_RBSIZE - (u32)DMA_COUNT(rd->control)) != 0) {
- /* init the var. used for the later
- * operations within the while loop */
- skb_new = NULL;
+ } else if ((devcs & ETH_RX_ROK)) {
pkt_len = RCVPKT_LENGTH(devcs);
- skb = lp->rx_skb[lp->rx_next_done];
+ /* must be the (first and) last
+ * descriptor then */
+ pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
+
+ /* invalidate the cache */
+ dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
+
+ /* Malloc up new buffer. */
+ skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
+
+ if (!skb_new)
+ break;
+ /* Do not count the CRC */
+ skb_put(skb, pkt_len - 4);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ /* Pass the packet to upper layers */
+ netif_receive_skb(skb);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += pkt_len;
+
+ /* Update the mcast stats */
+ if (devcs & ETH_RX_MP)
+ dev->stats.multicast++;
- if ((devcs & ETH_RX_ROK)) {
- /* must be the (first and) last
- * descriptor then */
- pkt_buf = (u8 *)lp->rx_skb[lp->rx_next_done]->data;
-
- /* invalidate the cache */
- dma_cache_inv((unsigned long)pkt_buf, pkt_len - 4);
-
- /* Malloc up new buffer. */
- skb_new = netdev_alloc_skb(dev, KORINA_RBSIZE + 2);
-
- if (!skb_new)
- break;
- /* Do not count the CRC */
- skb_put(skb, pkt_len - 4);
- skb->protocol = eth_type_trans(skb, dev);
-
- /* Pass the packet to upper layers */
- netif_receive_skb(skb);
- dev->last_rx = jiffies;
- dev->stats.rx_packets++;
- dev->stats.rx_bytes += pkt_len;
-
- /* Update the mcast stats */
- if (devcs & ETH_RX_MP)
- dev->stats.multicast++;
-
- lp->rx_skb[lp->rx_next_done] = skb_new;
- }
-
- rd->devcs = 0;
-
- /* Restore descriptor's curr_addr */
- if (skb_new)
- rd->ca = CPHYSADDR(skb_new->data);
- else
- rd->ca = CPHYSADDR(skb->data);
+ lp->rx_skb[lp->rx_next_done] = skb_new;
+ }
+ rd->devcs = 0;
+
+ /* Restore descriptor's curr_addr */
+ if (skb_new)
+ rd->ca = CPHYSADDR(skb_new->data);
+ else
+ rd->ca = CPHYSADDR(skb->data);
- rd->control = DMA_COUNT(KORINA_RBSIZE) |
+ rd->control = DMA_COUNT(KORINA_RBSIZE) |
DMA_DESC_COD | DMA_DESC_IOD;
- lp->rd_ring[(lp->rx_next_done - 1) &
- KORINA_RDS_MASK].control &=
- ~DMA_DESC_COD;
-
- lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
- dma_cache_wback((u32)rd, sizeof(*rd));
- rd = &lp->rd_ring[lp->rx_next_done];
- writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
- }
+ lp->rd_ring[(lp->rx_next_done - 1) &
+ KORINA_RDS_MASK].control &=
+ ~DMA_DESC_COD;
+
+ lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK;
+ dma_cache_wback((u32)rd, sizeof(*rd));
+ rd = &lp->rd_ring[lp->rx_next_done];
+ writel(~DMA_STAT_DONE, &lp->rx_dma_regs->dmas);
}
dmas = readl(&lp->rx_dma_regs->dmas);

View file

@ -0,0 +1,18 @@
The called netif_rx_schedule() does all the work for us:
- it checks the return value of netif_rx_schedule_prep() and
- if everything is ok calls __netif_rx_schedule().
Before this change, the driver received absolutely nothing.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
--- a/drivers/net/korina.c 2009-01-19 23:26:19.000000000 +0100
+++ b/drivers/net/korina.c 2009-01-19 23:27:06.000000000 +0100
@@ -330,7 +330,7 @@
dmas = readl(&lp->rx_dma_regs->dmas);
if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
- netif_rx_schedule_prep(dev, &lp->napi);
+ netif_rx_schedule(dev, &lp->napi);
dmasm = readl(&lp->rx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_DONE |

View file

@ -0,0 +1,40 @@
Triggering TX before the write to the DMA status mask register leads to
transferring packets with maximum payload no matter what the actual
packet size is.
While here, also trigger RX scheduling after writing the DMA status mask
register, like it was in the original driver before it was sent
upstream.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
--- a/drivers/net/korina.c 2009-01-19 23:27:41.000000000 +0100
+++ b/drivers/net/korina.c 2009-01-19 23:29:08.000000000 +0100
@@ -330,12 +330,12 @@
dmas = readl(&lp->rx_dma_regs->dmas);
if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
- netif_rx_schedule(dev, &lp->napi);
-
dmasm = readl(&lp->rx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_DONE |
DMA_STAT_HALT | DMA_STAT_ERR),
&lp->rx_dma_regs->dmasm);
+
+ netif_rx_schedule(dev, &lp->napi);
if (dmas & DMA_STAT_ERR)
printk(KERN_ERR DRV_NAME "%s: DMA error\n", dev->name);
@@ -621,11 +621,11 @@
dmas = readl(&lp->tx_dma_regs->dmas);
if (dmas & (DMA_STAT_FINI | DMA_STAT_ERR)) {
- korina_tx(dev);
-
dmasm = readl(&lp->tx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_FINI | DMA_STAT_ERR),
&lp->tx_dma_regs->dmasm);
+
+ korina_tx(dev);
if (lp->tx_chain_status == desc_filled &&
(readl(&(lp->tx_dma_regs->dmandptr)) == 0)) {

View file

@ -0,0 +1,87 @@
Originally this must have been a rewrite error when introducing
'chain_index'. But the original driver did not use the previous chain
item everywhere: when altering the address tx_chain_tail points to, it
should move forward, not backwards.
Also this is not an "index" but rather the penultimate element in the
chain, so rename it accordingly.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 22 +++++++++++-----------
1 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index dced5e7..f200175 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -199,7 +199,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
struct korina_private *lp = netdev_priv(dev);
unsigned long flags;
u32 length;
- u32 chain_index;
+ u32 chain_prev, chain_next;
struct dma_desc *td;
spin_lock_irqsave(&lp->lock, flags);
@@ -231,8 +231,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
/* Setup the transmit descriptor. */
dma_cache_inv((u32) td, sizeof(*td));
td->ca = CPHYSADDR(skb->data);
- chain_index = (lp->tx_chain_tail - 1) &
- KORINA_TDS_MASK;
+ chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK;
+ chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK;
if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) {
if (lp->tx_chain_status == desc_empty) {
@@ -240,7 +240,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
/* Write to NDPTR */
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
&lp->tx_dma_regs->dmandptr);
@@ -251,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Link to prev */
- lp->td_ring[chain_index].control &=
+ lp->td_ring[chain_prev].control &=
~DMA_DESC_COF;
/* Link to prev */
- lp->td_ring[chain_index].link = CPHYSADDR(td);
+ lp->td_ring[chain_prev].link = CPHYSADDR(td);
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
/* Write to NDPTR */
writel(CPHYSADDR(&lp->td_ring[lp->tx_chain_head]),
&(lp->tx_dma_regs->dmandptr));
@@ -270,17 +270,17 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
/* Move tail */
- lp->tx_chain_tail = chain_index;
+ lp->tx_chain_tail = chain_next;
lp->tx_chain_status = desc_filled;
netif_stop_queue(dev);
} else {
/* Update tail */
td->control = DMA_COUNT(length) |
DMA_DESC_COF | DMA_DESC_IOF;
- lp->td_ring[chain_index].control &=
+ lp->td_ring[chain_prev].control &=
~DMA_DESC_COF;
- lp->td_ring[chain_index].link = CPHYSADDR(td);
- lp->tx_chain_tail = chain_index;
+ lp->td_ring[chain_prev].link = CPHYSADDR(td);
+ lp->tx_chain_tail = chain_next;
}
}
dma_cache_wback((u32) td, sizeof(*td));
--
1.5.6.4

View file

@ -0,0 +1,25 @@
Apparently this doesn't make sense. Otherwise the queue gets disabled as
soon as it's getting empty and can only be resurrected by a driver
restart.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index f200175..bd33fa9 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -272,7 +272,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev)
/* Move tail */
lp->tx_chain_tail = chain_next;
lp->tx_chain_status = desc_filled;
- netif_stop_queue(dev);
} else {
/* Update tail */
td->control = DMA_COUNT(length) |
--
1.5.6.4

View file

@ -0,0 +1,53 @@
As the kernel warning states: "IRQF_DISABLED is not guaranteed on shared
IRQs". Since these IRQs' values are hardcoded and my test system doesn't
show any shared use of IRQs at all, rather make them non-shared than
non-disabled.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index bd33fa9..1d6e48e 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -1000,14 +1000,14 @@ static int korina_open(struct net_device *dev)
* that handles the Done Finished
* Ovr and Und Events */
ret = request_irq(lp->rx_irq, &korina_rx_dma_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Rx", dev);
+ IRQF_DISABLED, "Korina ethernet Rx", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get Rx DMA IRQ %d\n",
dev->name, lp->rx_irq);
goto err_release;
}
ret = request_irq(lp->tx_irq, &korina_tx_dma_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Korina ethernet Tx", dev);
+ IRQF_DISABLED, "Korina ethernet Tx", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get Tx DMA IRQ %d\n",
dev->name, lp->tx_irq);
@@ -1016,7 +1016,7 @@ static int korina_open(struct net_device *dev)
/* Install handler for overrun error. */
ret = request_irq(lp->ovr_irq, &korina_ovr_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Ethernet Overflow", dev);
+ IRQF_DISABLED, "Ethernet Overflow", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME"%s: unable to get OVR IRQ %d\n",
dev->name, lp->ovr_irq);
@@ -1025,7 +1025,7 @@ static int korina_open(struct net_device *dev)
/* Install handler for underflow error. */
ret = request_irq(lp->und_irq, &korina_und_interrupt,
- IRQF_SHARED | IRQF_DISABLED, "Ethernet Underflow", dev);
+ IRQF_DISABLED, "Ethernet Underflow", dev);
if (ret < 0) {
printk(KERN_ERR DRV_NAME "%s: unable to get UND IRQ %d\n",
dev->name, lp->und_irq);
--
1.5.6.4

View file

@ -0,0 +1,34 @@
As the assigned value is being overwritten shortly after, it can be
dropped and so the whole variable definition moved to the start of the
function.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 60ae7bf..75010ca 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -743,6 +743,7 @@ static struct ethtool_ops netdev_ethtool_ops = {
static void korina_alloc_ring(struct net_device *dev)
{
struct korina_private *lp = netdev_priv(dev);
+ struct sk_buff *skb;
int i;
/* Initialize the transmit descriptors */
@@ -758,8 +759,6 @@ static void korina_alloc_ring(struct net_device *dev)
/* Initialize the receive descriptors */
for (i = 0; i < KORINA_NUM_RDS; i++) {
- struct sk_buff *skb = lp->rx_skb[i];
-
skb = dev_alloc_skb(KORINA_RBSIZE + 2);
if (!skb)
break;
--
1.5.6.4

View file

@ -0,0 +1,36 @@
After the last loop iteration, i has the value RC32434_NUM_RDS and
therefore leads to an index overflow when used afterwards to address the
last element. This is yet another another bug introduced when rewriting
parts of the driver for upstream preparation, as the original driver
used 'RC32434_NUM_RDS - 1' instead.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 1d6e48e..67fbdf4 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -769,11 +769,12 @@ static void korina_alloc_ring(struct net_device *dev)
lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[i+1]);
}
- /* loop back */
- lp->rd_ring[i].link = CPHYSADDR(&lp->rd_ring[0]);
- lp->rx_next_done = 0;
+ /* loop back receive descriptors, so the last
+ * descriptor points to the first one */
+ lp->rd_ring[i - 1].link = CPHYSADDR(&lp->rd_ring[0]);
+ lp->rd_ring[i - 1].control |= DMA_DESC_COD;
- lp->rd_ring[i].control |= DMA_DESC_COD;
+ lp->rx_next_done = 0;
lp->rx_chain_head = 0;
lp->rx_chain_tail = 0;
lp->rx_chain_status = desc_empty;
--
1.5.6.4

View file

@ -0,0 +1,28 @@
This is copy and paste from the original driver. As skb_reserve() is
also called within korina_alloc_ring() when initially allocating the
receive descriptors, the same should be done when allocating new space
after passing an skb to upper layers.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 67fbdf4..60ae7bf 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -416,6 +416,9 @@ static int korina_rx(struct net_device *dev, int limit)
if (devcs & ETH_RX_MP)
dev->stats.multicast++;
+ /* 16 bit align */
+ skb_reserve(skb_new, 2);
+
lp->rx_skb[lp->rx_next_done] = skb_new;
}
--
1.5.6.4

View file

@ -0,0 +1,33 @@
I'm not sure if this is necessary, but the original driver did it and
apparently also many other drivers do it, so it should not be completely
wrong to do it.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
drivers/net/korina.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index 75010ca..56b4db2 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -419,6 +419,7 @@ static int korina_rx(struct net_device *dev, int limit)
/* 16 bit align */
skb_reserve(skb_new, 2);
+ skb_new->dev = dev;
lp->rx_skb[lp->rx_next_done] = skb_new;
}
@@ -763,6 +764,7 @@ static void korina_alloc_ring(struct net_device *dev)
if (!skb)
break;
skb_reserve(skb, 2);
+ skb->dev = dev;
lp->rx_skb[i] = skb;
lp->rd_ring[i].control = DMA_DESC_IOD |
DMA_COUNT(KORINA_RBSIZE);
--
1.5.6.4

View file

@ -0,0 +1,26 @@
As the korina ethernet driver uses platform_get_drvdata() to extract the
driver specific data from the platform device, driver_data has to be
used here.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
arch/mips/rb532/devices.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index 9b6b744..3c74561 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -89,7 +89,7 @@ static struct korina_device korina_dev0_data = {
static struct platform_device korina_dev0 = {
.id = -1,
.name = "korina",
- .dev.platform_data = &korina_dev0_data,
+ .dev.driver_data = &korina_dev0_data,
.resource = korina_dev0_res,
.num_resources = ARRAY_SIZE(korina_dev0_res),
};
--
1.5.6.4

View file

@ -0,0 +1,91 @@
Auto-detection works just fine, so use it instead of specifying the type
manually. Also define a platform device for the uart, as suggested by
David Daney.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
arch/mips/rb532/devices.c | 26 ++++++++++++++++++++++++++
arch/mips/rb532/serial.c | 2 +-
2 files changed, 27 insertions(+), 1 deletions(-)
diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c
index c1c2918..9b6b744 100644
--- a/arch/mips/rb532/devices.c
+++ b/arch/mips/rb532/devices.c
@@ -24,6 +24,7 @@
#include <linux/mtd/partitions.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
+#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
@@ -39,6 +40,8 @@
#define ETH0_RX_DMA_ADDR (DMA0_BASE_ADDR + 0 * DMA_CHAN_OFFSET)
#define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET)
+extern unsigned int idt_cpu_freq;
+
static struct resource korina_dev0_res[] = {
{
.name = "korina_regs",
@@ -214,12 +217,32 @@ static struct platform_device rb532_wdt = {
.num_resources = ARRAY_SIZE(rb532_wdt_res),
};
+static struct plat_serial8250_port rb532_uart_res[] = {
+ {
+ .membase = (char *)KSEG1ADDR(REGBASE + UART0BASE),
+ .irq = UART0_IRQ,
+ .regshift = 2,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF,
+ },
+ {
+ .flags = 0,
+ }
+};
+
+static struct platform_device rb532_uart = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev.platform_data = &rb532_uart_res,
+};
+
static struct platform_device *rb532_devs[] = {
&korina_dev0,
&nand_slot0,
&cf_slot0,
&rb532_led,
&rb532_button,
+ &rb532_uart,
&rb532_wdt
};
@@ -294,6 +317,9 @@ static int __init plat_setup_devices(void)
/* Initialise the NAND device */
rb532_nand_setup();
+ /* set the uart clock to the current cpu frequency */
+ rb532_uart_res[0].uartclk = idt_cpu_freq;
+
return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));
}
diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c
index 3e0d7ec..00ed19f 100644
--- a/arch/mips/rb532/serial.c
+++ b/arch/mips/rb532/serial.c
@@ -36,7 +36,7 @@
extern unsigned int idt_cpu_freq;
static struct uart_port rb532_uart = {
- .type = PORT_16550A,
+ .flags = UPF_BOOT_AUTOCONF,
.line = 0,
.irq = UART0_IRQ,
.iotype = UPIO_MEM,
--
1.5.6.4

View file

@ -0,0 +1,32 @@
This register just contains the address of the actual resource, so
initialisation has to be the same as cf_slot0_res and nand_slot0_res.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c
index d75eb19..40deb11 100644
--- a/arch/mips/rb532/gpio.c
+++ b/arch/mips/rb532/gpio.c
@@ -55,8 +55,6 @@ static struct resource rb532_gpio_reg0_res[] = {
static struct resource rb532_dev3_ctl_res[] = {
{
.name = "dev3_ctl",
- .start = REGBASE + DEV3BASE,
- .end = REGBASE + DEV3BASE + sizeof(struct dev_reg) - 1,
.flags = IORESOURCE_MEM,
}
};
@@ -243,6 +241,9 @@ int __init rb532_gpio_init(void)
/* Register our GPIO chip */
gpiochip_add(&rb532_gpio_chip->chip);
+ rb532_dev3_ctl_res[0].start = readl(IDT434_REG_BASE + DEV3BASE);
+ rb532_dev3_ctl_res[0].end = rb532_dev3_ctl_res[0].start + 0x1000;
+
r = rb532_dev3_ctl_res;
dev3.base = ioremap_nocache(r->start, r->end - r->start);
--
1.5.6.4

View file

@ -0,0 +1,23 @@
The data to be written is just a byte, so use writeb instead of writel.
Also, dev3.base contains the address, not the data so referencing here
is wrong.
Signed-off-by: Phil Sutter <n0-1@freewrt.org>
---
diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c
index 40deb11..7e0cb4f 100644
--- a/arch/mips/rb532/gpio.c
+++ b/arch/mips/rb532/gpio.c
@@ -93,7 +93,7 @@ void set_latch_u5(unsigned char or_mask, unsigned char nand_mask)
spin_lock_irqsave(&dev3.lock, flags);
dev3.state = (dev3.state | or_mask) & ~nand_mask;
- writel(dev3.state, &dev3.base);
+ writeb(dev3.state, dev3.base);
spin_unlock_irqrestore(&dev3.lock, flags);
}
--
1.5.6.4

View file

@ -0,0 +1,48 @@
--- a/arch/mips/rb532/devices.c 2009-01-25 13:36:15.000000000 +0100
+++ b/arch/mips/rb532/devices.c 2009-01-25 14:00:56.000000000 +0100
@@ -119,6 +119,19 @@
};
/* Resources and device for NAND */
+
+/*
+ * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader
+ * will not be able to find the kernel that we load. So set the oobinfo
+ * when creating the partitions
+ */
+static struct nand_ecclayout rb532_nand_ecclayout = {
+ .eccbytes = 6,
+ .eccpos = { 8, 9, 10, 13, 14, 15 },
+ .oobavail = 9,
+ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } }
+};
+
static int rb532_dev_ready(struct mtd_info *mtd)
{
return gpio_get_value(GPIO_RDY);
@@ -277,6 +290,16 @@
/* NAND definitions */
#define NAND_CHIP_DELAY 25
+static int rb532_nand_fixup(struct mtd_info *mtd)
+{
+ struct nand_chip *chip = mtd->priv;
+
+ if (mtd->writesize == 512)
+ chip->ecc.layout = &rb532_nand_ecclayout;
+
+ return 0;
+}
+
static void __init rb532_nand_setup(void)
{
switch (mips_machtype) {
@@ -296,6 +319,8 @@
rb532_nand_data.chip.partitions = rb532_partition_info;
rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY;
rb532_nand_data.chip.options = NAND_NO_AUTOINCR;
+
+ rb532_nand_data.chip.chip_fixup = &rb532_nand_fixup;
}