* [PATCH] [RFT] 2.6.5-rc2 - sis190 update
@ 2004-03-27 2:08 Francois Romieu
2004-03-27 2:11 ` [PATCH 1/8] " Francois Romieu
0 siblings, 1 reply; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:08 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
The recent changes to the r8169 driver turned it into something quite
different from the sis190 driver whence it (apparently) originated.
The following serie of patches resyncs the sis190 driver with the r8169
one while making it compliant (?) wrt the DMA API.
I'll review it more closely once I have got some sleep but if some happy
tester wants to contribute, he will be welcome.
The patches compile, they are untested and should apply to nearly anything
2.6.x as -mm does not include patches to the sis190.c.
--
Ueimor
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:08 [PATCH] [RFT] 2.6.5-rc2 - sis190 update Francois Romieu
@ 2004-03-27 2:11 ` Francois Romieu
2004-03-27 2:12 ` [PATCH 2/8] " Francois Romieu
2004-03-27 2:37 ` [PATCH 1/8] " Jeff Garzik
0 siblings, 2 replies; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:11 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
Endianness issues.
Use of le32_to_cpu/cpu_to_le32 in the code which handles the different
components of the Rx descriptors (PSize/status/buf_addr/buf_Len).
drivers/net/sis190.c | 45 +++++++++++++++++++++------------------------
1 files changed, 21 insertions(+), 24 deletions(-)
diff -puN drivers/net/sis190.c~sis190-rx-path-le32_to_cpu drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-rx-path-le32_to_cpu 2004-03-26 23:12:05.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-26 23:13:10.000000000 +0100
@@ -824,18 +824,19 @@ SiS190_init_ring(struct net_device *dev)
}
for (i = 0; i < NUM_RX_DESC; i++) {
struct RxDesc *desc = tp->RxDescArray + i;
+ dma_addr_t mapping;
+ u32 len;
desc->PSize = 0x0;
- if (i == (NUM_RX_DESC - 1))
- desc->buf_Len = BIT_31 + RX_BUF_SIZE; //bit 31 is End bit
- else
- desc->buf_Len = RX_BUF_SIZE;
+ len = RX_BUF_SIZE + ENDbit * !((i + 1) % NUM_RX_DESC);
tp->RxBufferRing[i] = tp->RxBufferRings + i * RX_BUF_SIZE;
- desc->buf_addr = pci_map_single(tp->pci_dev,
+ mapping = pci_map_single(tp->pci_dev,
tp->RxBufferRing[i], RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- desc->status = OWNbit | INTbit;
+ desc->buf_addr = cpu_to_le32(mapping);
+ desc->buf_Len = cpu_to_le32(len);
+ desc->status = cpu_to_le32(OWNbit | INTbit);
}
}
@@ -1001,13 +1002,13 @@ SiS190_rx_interrupt(struct net_device *d
assert(tp != NULL);
assert(ioaddr != NULL);
- while ((desc->status & OWNbit) == 0) {
+ while ((le32_to_cpu(desc->status) & OWNbit) == 0) {
- if (desc->PSize & 0x0080000) {
+ if (cpu_to_le32(desc->PSize) & RxCRC) {
printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
tp->stats.rx_errors++;
tp->stats.rx_length_errors++;
- } else if (!(desc->PSize & 0x0010000)) {
+ } else if (!(cpu_to_le32(desc->PSize) & 0x0010000)) {
printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
tp->stats.rx_errors++;
tp->stats.rx_crc_errors++;
@@ -1015,37 +1016,32 @@ SiS190_rx_interrupt(struct net_device *d
struct sk_buff *skb;
int pkt_size;
- pkt_size = (int) (desc->PSize & 0x0000FFFF) - 4;
+ pkt_size = (cpu_to_le32(desc->PSize) & 0x0000FFFF) - 4;
skb = dev_alloc_skb(pkt_size + 2);
if (skb != NULL) {
skb->dev = dev;
skb_reserve(skb, 2); // 16 byte align the IP fields. //
pci_dma_sync_single_for_cpu(tp->pci_dev,
- desc->buf_addr,
- RX_BUF_SIZE,
- PCI_DMA_FROMDEVICE);
+ le32_to_cpu(desc->buf_addr),
+ RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
eth_copy_and_sum(skb, tp->RxBufferRing[cur_rx],
pkt_size, 0);
pci_dma_sync_single_for_device(tp->pci_dev,
- desc->buf_addr,
- RX_BUF_SIZE,
- PCI_DMA_FROMDEVICE);
+ le32_to_cpu(desc->buf_addr),
+ RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
skb_put(skb, pkt_size);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
desc->PSize = 0x0;
- if (cur_rx == (NUM_RX_DESC - 1))
- desc->buf_Len = ENDbit + RX_BUF_SIZE;
- else
- desc->buf_Len = RX_BUF_SIZE;
-
+ desc->buf_Len = cpu_to_le32(RX_BUF_SIZE +
+ ENDbit * !((cur_rx + 1) % NUM_RX_DESC));
dev->last_rx = jiffies;
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
- desc->status = OWNbit | INTbit;
+ desc->status = cpu_to_le32(OWNbit | INTbit);
} else {
printk(KERN_WARNING
"%s: Memory squeeze, deferring packet.\n",
@@ -1142,8 +1138,9 @@ SiS190_close(struct net_device *dev)
tp->rx_dma);
tp->TxDescArray = NULL;
for (i = 0; i < NUM_RX_DESC; i++) {
- pci_unmap_single(tp->pci_dev, tp->RxDescArray[i].buf_addr,
- RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(tp->pci_dev,
+ le32_to_cpu(tp->RxDescArray[i].buf_addr), RX_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
tp->RxBufferRing[i] = NULL;
}
tp->RxDescArray = NULL;
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:11 ` [PATCH 1/8] " Francois Romieu
@ 2004-03-27 2:12 ` Francois Romieu
2004-03-27 2:13 ` [PATCH 3/8] " Francois Romieu
2004-03-27 2:37 ` [PATCH 1/8] " Jeff Garzik
1 sibling, 1 reply; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:12 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
Balance the call to pci_enable_device() in SiS190_init_one() with a call
to pci_disable_device() in SiS190_remove_one().
drivers/net/sis190.c | 24 +++++++++++++++---------
1 files changed, 15 insertions(+), 9 deletions(-)
diff -puN drivers/net/sis190.c~sis190-missing-pci-disable-device drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-missing-pci-disable-device 2004-03-26 23:16:58.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-26 23:16:58.000000000 +0100
@@ -435,6 +435,18 @@ ReadEEprom(void *ioaddr, u32 RegAddr)
return data;
}
+static void SiS190_release_board(struct pci_dev *pdev, struct net_device *dev)
+{
+ struct sis190_private *tp = dev->priv;
+
+ assert(tp != NULL);
+
+ iounmap(tp->mmio_addr);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ free_netdev(dev);
+}
+
static int __devinit
SiS190_init_board(struct pci_dev *pdev, struct net_device **dev_out,
void **ioaddr_out)
@@ -599,10 +611,7 @@ SiS190_init_one(struct pci_dev *pdev, co
spin_lock_init(&tp->lock);
rc = register_netdev(dev);
if (rc) {
- iounmap(ioaddr);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- free_netdev(dev);
+ SiS190_release_board(pdev, dev);
return rc;
}
@@ -694,16 +703,13 @@ static void __devexit
SiS190_remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct sis190_private *tp = (struct sis190_private *) (dev->priv);
assert(dev != NULL);
- assert(tp != NULL);
unregister_netdev(dev);
- iounmap(tp->mmio_addr);
- pci_release_regions(pdev);
- free_netdev(dev);
+ SiS190_release_board(pdev, dev);
+
pci_set_drvdata(pdev, NULL);
}
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 3/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:12 ` [PATCH 2/8] " Francois Romieu
@ 2004-03-27 2:13 ` Francois Romieu
2004-03-27 2:13 ` [PATCH 4/8] " Francois Romieu
0 siblings, 1 reply; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:13 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
- make sis190_open() look like r8169_open() as they do the same thing;
- ready sis190_init_ring for incoming DMA api changes;
- trade a "for" loop against a single line, idiomatic, memset().
drivers/net/sis190.c | 57 +++++++++++++++++++++++++--------------------------
1 files changed, 29 insertions(+), 28 deletions(-)
diff -puN drivers/net/sis190.c~sis190-rework-open drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-rework-open 2004-03-26 23:29:27.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-26 23:47:11.000000000 +0100
@@ -331,7 +331,7 @@ static int SiS190_open(struct net_device
static int SiS190_start_xmit(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t SiS190_interrupt(int irq, void *dev_instance,
struct pt_regs *regs);
-static void SiS190_init_ring(struct net_device *dev);
+static int SiS190_init_ring(struct net_device *dev);
static void SiS190_hw_start(struct net_device *dev);
static int SiS190_close(struct net_device *dev);
static void SiS190_set_rx_mode(struct net_device *dev);
@@ -720,50 +720,43 @@ SiS190_open(struct net_device *dev)
int rc;
rc = request_irq(dev->irq, SiS190_interrupt, SA_SHIRQ, dev->name, dev);
- if (rc)
+ if (rc < 0)
goto out;
+ rc = -ENOMEM;
+
/*
* Rx and Tx descriptors need 256 bytes alignment.
* pci_alloc_consistent() guarantees a stronger alignment.
*/
tp->TxDescArray = pci_alloc_consistent(tp->pci_dev, TX_DESC_TOTAL_SIZE,
&tp->tx_dma);
- if (!tp->TxDescArray) {
- rc = -ENOMEM;
- goto err_out;
- }
+ if (!tp->TxDescArray)
+ goto err_free_irq;
tp->RxDescArray = pci_alloc_consistent(tp->pci_dev, RX_DESC_TOTAL_SIZE,
&tp->rx_dma);
- if (!tp->RxDescArray) {
- rc = -ENOMEM;
- goto err_out_free_tx;
- }
+ if (!tp->RxDescArray)
+ goto err_free_tx;
- tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
- if (tp->RxBufferRings == NULL) {
- printk(KERN_INFO "%s: allocate RxBufferRing failed\n",
- dev->name);
- rc = -ENOMEM;
- goto err_out_free_rx;
- }
+ rc = SiS190_init_ring(dev);
+ if (rc < 0)
+ goto err_free_rx;
- SiS190_init_ring(dev);
SiS190_hw_start(dev);
out:
return rc;
-err_out_free_rx:
+err_free_rx:
pci_free_consistent(tp->pci_dev, RX_DESC_TOTAL_SIZE, tp->RxDescArray,
tp->rx_dma);
-err_out_free_tx:
+err_free_tx:
pci_free_consistent(tp->pci_dev, TX_DESC_TOTAL_SIZE, tp->TxDescArray,
tp->tx_dma);
-err_out:
+err_free_irq:
free_irq(dev->irq, dev);
- return rc;
+ goto out;
}
static void
@@ -813,21 +806,25 @@ SiS190_hw_start(struct net_device *dev)
}
-static void
-SiS190_init_ring(struct net_device *dev)
+static int SiS190_init_ring(struct net_device *dev)
{
struct sis190_private *tp = dev->priv;
int i;
tp->cur_rx = 0;
- tp->cur_tx = 0;
- tp->dirty_tx = 0;
+ tp->cur_tx = tp->dirty_tx = 0;
memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc));
memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc));
- for (i = 0; i < NUM_TX_DESC; i++) {
- tp->Tx_skbuff[i] = NULL;
+ memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
+
+ tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
+ if (tp->RxBufferRings == NULL) {
+ printk(KERN_INFO "%s: allocate RxBufferRing failed\n",
+ dev->name);
+ goto err_out;
}
+
for (i = 0; i < NUM_RX_DESC; i++) {
struct RxDesc *desc = tp->RxDescArray + i;
dma_addr_t mapping;
@@ -845,6 +842,10 @@ SiS190_init_ring(struct net_device *dev)
desc->status = cpu_to_le32(OWNbit | INTbit);
}
+ return 0;
+
+err_out:
+ return -ENOMEM;
}
static void
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 4/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:13 ` [PATCH 3/8] " Francois Romieu
@ 2004-03-27 2:13 ` Francois Romieu
2004-03-27 2:14 ` [PATCH 5/8] " Francois Romieu
0 siblings, 1 reply; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:13 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
New helpers (shamelessly stolen from r8169 driver):
- sis190_mark_as_last_descriptor;
- sis190_give_to_asic.
drivers/net/sis190.c | 20 ++++++++++++++------
1 files changed, 14 insertions(+), 6 deletions(-)
diff -puN drivers/net/sis190.c~sis190-dma-api-rx-buffers-00 drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-dma-api-rx-buffers-00 2004-03-27 02:35:56.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-27 02:36:46.000000000 +0100
@@ -806,6 +806,17 @@ SiS190_hw_start(struct net_device *dev)
}
+static inline void sis190_mark_as_last_descriptor(struct RxDesc *desc)
+{
+ desc->buf_Len |= cpu_to_le32(ENDbit);
+}
+
+static inline void sis190_give_to_asic(struct RxDesc *desc, dma_addr_t mapping)
+{
+ desc->buf_addr = cpu_to_le32(mapping);
+ desc->status |= cpu_to_le32(OWNbit | INTbit);
+}
+
static int SiS190_init_ring(struct net_device *dev)
{
struct sis190_private *tp = dev->priv;
@@ -828,19 +839,16 @@ static int SiS190_init_ring(struct net_d
for (i = 0; i < NUM_RX_DESC; i++) {
struct RxDesc *desc = tp->RxDescArray + i;
dma_addr_t mapping;
- u32 len;
desc->PSize = 0x0;
-
- len = RX_BUF_SIZE + ENDbit * !((i + 1) % NUM_RX_DESC);
+ desc->buf_Len = cpu_to_le32(RX_BUF_SIZE);
tp->RxBufferRing[i] = tp->RxBufferRings + i * RX_BUF_SIZE;
mapping = pci_map_single(tp->pci_dev,
tp->RxBufferRing[i], RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- desc->buf_addr = cpu_to_le32(mapping);
- desc->buf_Len = cpu_to_le32(len);
- desc->status = cpu_to_le32(OWNbit | INTbit);
+ sis190_give_to_asic(desc, mapping);
}
+ sis190_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
return 0;
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 5/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:13 ` [PATCH 4/8] " Francois Romieu
@ 2004-03-27 2:14 ` Francois Romieu
2004-03-27 2:15 ` [PATCH 6/8] " Francois Romieu
0 siblings, 1 reply; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:14 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
Still no functionnal change. See r8169 driver for details.
drivers/net/sis190.c | 49 +++++++++++++++++++++++++++++++++++++------------
1 files changed, 37 insertions(+), 12 deletions(-)
diff -puN drivers/net/sis190.c~sis190-dma-api-rx-buffers-10 drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-dma-api-rx-buffers-10 2004-03-27 02:37:12.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-27 02:37:12.000000000 +0100
@@ -817,10 +817,42 @@ static inline void sis190_give_to_asic(s
desc->status |= cpu_to_le32(OWNbit | INTbit);
}
+static int sis190_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev,
+ char *tail, struct RxDesc *desc)
+{
+ dma_addr_t mapping;
+ int ret = 0;
+
+ mapping = pci_map_single(pdev, tail, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+ desc->PSize = 0x0;
+ desc->buf_Len |= cpu_to_le32(RX_BUF_SIZE);
+
+ sis190_give_to_asic(desc, mapping);
+
+ return ret;
+}
+
+static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
+ u32 start, u32 end)
+{
+ u32 cur;
+
+ for (cur = start; end - cur > 0; cur++) {
+ int ret, i = cur % NUM_RX_DESC;
+
+ ret = sis190_alloc_rx_skb(tp->pci_dev, dev,
+ tp->RxBufferRings + i * RX_BUF_SIZE,
+ tp->RxDescArray + i);
+ if (ret < 0)
+ break;
+ }
+ return cur - start;
+}
+
static int SiS190_init_ring(struct net_device *dev)
{
struct sis190_private *tp = dev->priv;
- int i;
tp->cur_rx = 0;
tp->cur_tx = tp->dirty_tx = 0;
@@ -836,22 +868,15 @@ static int SiS190_init_ring(struct net_d
goto err_out;
}
- for (i = 0; i < NUM_RX_DESC; i++) {
- struct RxDesc *desc = tp->RxDescArray + i;
- dma_addr_t mapping;
-
- desc->PSize = 0x0;
- desc->buf_Len = cpu_to_le32(RX_BUF_SIZE);
+ if (sis190_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
+ goto err_out_free;
- tp->RxBufferRing[i] = tp->RxBufferRings + i * RX_BUF_SIZE;
- mapping = pci_map_single(tp->pci_dev,
- tp->RxBufferRing[i], RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- sis190_give_to_asic(desc, mapping);
- }
sis190_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
return 0;
+err_out_free:
+ kfree(tp->RxBufferRings);
err_out:
return -ENOMEM;
}
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 6/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:14 ` [PATCH 5/8] " Francois Romieu
@ 2004-03-27 2:15 ` Francois Romieu
2004-03-27 2:16 ` [PATCH 7/8] " Francois Romieu
0 siblings, 1 reply; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:15 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
Add dirty_rx (unused so far).
drivers/net/sis190.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
diff -puN drivers/net/sis190.c~sis190-dma-api-rx-buffers-20 drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-dma-api-rx-buffers-20 2004-03-27 02:37:25.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-27 02:37:25.000000000 +0100
@@ -310,9 +310,10 @@ struct sis190_private {
struct net_device_stats stats; /* statistics of net device */
spinlock_t lock; /* spin lock flag */
int chipset;
- unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
- unsigned long cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
- unsigned long dirty_tx;
+ u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
+ u32 cur_tx; /* Index into the Tx descriptor buffer of next Tx pkt. */
+ u32 dirty_rx;
+ u32 dirty_tx;
dma_addr_t tx_dma;
dma_addr_t rx_dma;
struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */
@@ -854,7 +855,7 @@ static int SiS190_init_ring(struct net_d
{
struct sis190_private *tp = dev->priv;
- tp->cur_rx = 0;
+ tp->cur_rx = tp->dirty_rx = 0;
tp->cur_tx = tp->dirty_tx = 0;
memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof (struct TxDesc));
memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc));
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 7/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:15 ` [PATCH 6/8] " Francois Romieu
@ 2004-03-27 2:16 ` Francois Romieu
2004-03-27 2:17 ` [PATCH 8/8] " Francois Romieu
0 siblings, 1 reply; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:16 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
Replace the giant receive buffer with individually allocated skb.
drivers/net/sis190.c | 86 +++++++++++++++++++++++++++++++++++----------------
1 files changed, 60 insertions(+), 26 deletions(-)
diff -puN drivers/net/sis190.c~sis190-dma-api-rx-buffers-30 drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-dma-api-rx-buffers-30 2004-03-27 02:37:47.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-27 02:37:47.000000000 +0100
@@ -290,6 +290,9 @@ enum _DescStatusBit {
ENDbit = 0x80000000,
};
+/* FIXME: datasheet, anyone ? */
+#define RsvdMask 0x00000000
+
struct TxDesc {
u32 PSize;
u32 status;
@@ -318,9 +321,8 @@ struct sis190_private {
dma_addr_t rx_dma;
struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */
struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */
- unsigned char *RxBufferRings; /* Index of Rx Buffer */
- unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */
- struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */
+ struct sk_buff *Rx_skbuff[NUM_TX_DESC]; /* Rx data buffer */
+ struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Tx data buffer */
};
MODULE_AUTHOR("K.M. Liu <kmliu@sis.com>");
@@ -812,6 +814,22 @@ static inline void sis190_mark_as_last_d
desc->buf_Len |= cpu_to_le32(ENDbit);
}
+static inline void sis190_make_unusable_by_asic(struct RxDesc *desc)
+{
+ desc->buf_addr = 0xdeadbeef;
+ desc->status &= ~cpu_to_le32(OWNbit | RsvdMask);
+}
+
+static void sis190_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
+ struct RxDesc *desc)
+{
+ pci_unmap_single(pdev, le32_to_cpu(desc->buf_addr), RX_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(*sk_buff);
+ *sk_buff = NULL;
+ sis190_make_unusable_by_asic(desc);
+}
+
static inline void sis190_give_to_asic(struct RxDesc *desc, dma_addr_t mapping)
{
desc->buf_addr = cpu_to_le32(mapping);
@@ -819,19 +837,47 @@ static inline void sis190_give_to_asic(s
}
static int sis190_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev,
- char *tail, struct RxDesc *desc)
+ struct sk_buff **sk_buff, struct RxDesc *desc)
{
+ struct sk_buff *skb;
dma_addr_t mapping;
int ret = 0;
- mapping = pci_map_single(pdev, tail, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ skb = dev_alloc_skb(RX_BUF_SIZE + 2);
+ if (!skb)
+ goto err_out;
+
+ skb->dev = dev;
+ skb_reserve(skb, 2);
+ *sk_buff = skb;
+
+ mapping = pci_map_single(pdev, skb->tail, RX_BUF_SIZE,
+ PCI_DMA_FROMDEVICE);
desc->PSize = 0x0;
desc->buf_Len |= cpu_to_le32(RX_BUF_SIZE);
sis190_give_to_asic(desc, mapping);
+out:
return ret;
+
+err_out:
+ ret = -ENOMEM;
+ sis190_make_unusable_by_asic(desc);
+ goto out;
+}
+
+static void sis190_rx_clear(struct sis190_private *tp)
+{
+ int i;
+
+ for (i = 0; i < NUM_RX_DESC; i++) {
+ if (tp->Rx_skbuff[i]) {
+ sis190_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
+ tp->RxDescArray + i);
+ }
+ }
}
static u32 sis190_rx_fill(struct sis190_private *tp, struct net_device *dev,
@@ -842,8 +888,10 @@ static u32 sis190_rx_fill(struct sis190_
for (cur = start; end - cur > 0; cur++) {
int ret, i = cur % NUM_RX_DESC;
- ret = sis190_alloc_rx_skb(tp->pci_dev, dev,
- tp->RxBufferRings + i * RX_BUF_SIZE,
+ if (tp->Rx_skbuff[i])
+ continue;
+
+ ret = sis190_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i,
tp->RxDescArray + i);
if (ret < 0)
break;
@@ -861,24 +909,17 @@ static int SiS190_init_ring(struct net_d
memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof (struct RxDesc));
memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
-
- tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
- if (tp->RxBufferRings == NULL) {
- printk(KERN_INFO "%s: allocate RxBufferRing failed\n",
- dev->name);
- goto err_out;
- }
+ memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
if (sis190_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
- goto err_out_free;
+ goto err_out;
sis190_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
return 0;
-err_out_free:
- kfree(tp->RxBufferRings);
err_out:
+ sis190_rx_clear(tp);
return -ENOMEM;
}
@@ -1065,7 +1106,7 @@ SiS190_rx_interrupt(struct net_device *d
pci_dma_sync_single_for_cpu(tp->pci_dev,
le32_to_cpu(desc->buf_addr),
RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, tp->RxBufferRing[cur_rx],
+ eth_copy_and_sum(skb, tp->Rx_skbuff[cur_rx]->tail,
pkt_size, 0);
pci_dma_sync_single_for_device(tp->pci_dev,
le32_to_cpu(desc->buf_addr),
@@ -1150,7 +1191,6 @@ SiS190_close(struct net_device *dev)
{
struct sis190_private *tp = dev->priv;
void *ioaddr = tp->mmio_addr;
- int i;
netif_stop_queue(dev);
@@ -1173,19 +1213,13 @@ SiS190_close(struct net_device *dev)
free_irq(dev->irq, dev);
SiS190_tx_clear(tp);
+ sis190_rx_clear(tp);
pci_free_consistent(tp->pci_dev, TX_DESC_TOTAL_SIZE, tp->TxDescArray,
tp->tx_dma);
pci_free_consistent(tp->pci_dev, RX_DESC_TOTAL_SIZE, tp->RxDescArray,
tp->rx_dma);
tp->TxDescArray = NULL;
- for (i = 0; i < NUM_RX_DESC; i++) {
- pci_unmap_single(tp->pci_dev,
- le32_to_cpu(tp->RxDescArray[i].buf_addr), RX_BUF_SIZE,
- PCI_DMA_FROMDEVICE);
- tp->RxBufferRing[i] = NULL;
- }
tp->RxDescArray = NULL;
- kfree(tp->RxBufferRings);
return 0;
}
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 8/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:16 ` [PATCH 7/8] " Francois Romieu
@ 2004-03-27 2:17 ` Francois Romieu
0 siblings, 0 replies; 10+ messages in thread
From: Francois Romieu @ 2004-03-27 2:17 UTC (permalink / raw)
To: netdev; +Cc: Jeff Garzik
- sis190_rx_interrupt converted to classical Rx skb handling;
- rx_copybreak *new.
Some similarity with the r8169 driver can not be excluded.
drivers/net/sis190.c | 116 ++++++++++++++++++++++++++++++++++-----------------
1 files changed, 78 insertions(+), 38 deletions(-)
diff -puN drivers/net/sis190.c~sis190-dma-api-rx-buffers-40 drivers/net/sis190.c
--- linux-2.6.5-rc2/drivers/net/sis190.c~sis190-dma-api-rx-buffers-40 2004-03-27 02:38:14.000000000 +0100
+++ linux-2.6.5-rc2-fr/drivers/net/sis190.c 2004-03-27 02:42:39.000000000 +0100
@@ -149,6 +149,8 @@ static struct pci_device_id sis190_pci_t
MODULE_DEVICE_TABLE(pci, sis190_pci_tbl);
+static int rx_copybreak = 200;
+
enum SiS190_registers {
TxControl = 0x0,
TxDescStartAddr = 0x4,
@@ -329,6 +331,7 @@ MODULE_AUTHOR("K.M. Liu <kmliu@sis.com>"
MODULE_DESCRIPTION("SiS SiS190 Gigabit Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(rx_copybreak, "i");
static int SiS190_open(struct net_device *dev);
static int SiS190_start_xmit(struct sk_buff *skb, struct net_device *dev);
@@ -830,6 +833,13 @@ static void sis190_free_rx_skb(struct pc
sis190_make_unusable_by_asic(desc);
}
+
+static inline void sis190_return_to_asic(struct RxDesc *desc)
+{
+ desc->PSize = 0x0;
+ desc->status |= cpu_to_le32(OWNbit | INTbit);
+}
+
static inline void sis190_give_to_asic(struct RxDesc *desc, dma_addr_t mapping)
{
desc->buf_addr = cpu_to_le32(mapping);
@@ -1073,18 +1083,49 @@ SiS190_tx_interrupt(struct net_device *d
}
}
+static inline int sis190_try_rx_copy(struct sk_buff **sk_buff, int pkt_size,
+ struct RxDesc *desc,
+ struct net_device *dev)
+{
+ int ret = -1;
+
+ if (pkt_size < rx_copybreak) {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(pkt_size + 2);
+ if (skb) {
+ skb->dev = dev;
+ skb_reserve(skb, 2);
+ eth_copy_and_sum(skb, sk_buff[0]->tail, pkt_size, 0);
+ *sk_buff = skb;
+ sis190_return_to_asic(desc);
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
static void
SiS190_rx_interrupt(struct net_device *dev, struct sis190_private *tp,
void *ioaddr)
{
- int cur_rx = tp->cur_rx;
- struct RxDesc *desc = tp->RxDescArray + cur_rx;
+ unsigned long cur_rx, rx_left;
+ int delta;
assert(dev != NULL);
assert(tp != NULL);
assert(ioaddr != NULL);
- while ((le32_to_cpu(desc->status) & OWNbit) == 0) {
+ cur_rx = tp->cur_rx;
+ rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
+
+ while (rx_left > 0) {
+ int entry = cur_rx % NUM_RX_DESC;
+ struct RxDesc *desc = tp->RxDescArray + entry;
+ u32 status = le32_to_cpu(desc->status);
+
+ if (status & OWNbit)
+ break;
if (cpu_to_le32(desc->PSize) & RxCRC) {
printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
@@ -1095,43 +1136,33 @@ SiS190_rx_interrupt(struct net_device *d
tp->stats.rx_errors++;
tp->stats.rx_crc_errors++;
} else {
- struct sk_buff *skb;
- int pkt_size;
+ struct sk_buff *skb = tp->Rx_skbuff[entry];
+ void (*dma_op)(struct pci_dev *, dma_addr_t, size_t,
+ int);
+ int pkt_size;
pkt_size = (cpu_to_le32(desc->PSize) & 0x0000FFFF) - 4;
- skb = dev_alloc_skb(pkt_size + 2);
- if (skb != NULL) {
- skb->dev = dev;
- skb_reserve(skb, 2); // 16 byte align the IP fields. //
- pci_dma_sync_single_for_cpu(tp->pci_dev,
- le32_to_cpu(desc->buf_addr),
- RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- eth_copy_and_sum(skb, tp->Rx_skbuff[cur_rx]->tail,
- pkt_size, 0);
- pci_dma_sync_single_for_device(tp->pci_dev,
- le32_to_cpu(desc->buf_addr),
- RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- skb_put(skb, pkt_size);
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
-
- desc->PSize = 0x0;
-
- desc->buf_Len = cpu_to_le32(RX_BUF_SIZE +
- ENDbit * !((cur_rx + 1) % NUM_RX_DESC));
- dev->last_rx = jiffies;
- tp->stats.rx_bytes += pkt_size;
- tp->stats.rx_packets++;
-
- desc->status = cpu_to_le32(OWNbit | INTbit);
- } else {
- printk(KERN_WARNING
- "%s: Memory squeeze, deferring packet.\n",
- dev->name);
- /* We should check that some rx space is free.
- If not, free one and mark stats->rx_dropped++. */
- tp->stats.rx_dropped++;
- }
+
+ dma_op = pci_dma_sync_single_for_cpu;
+ dma_op(tp->pci_dev, le32_to_cpu(desc->buf_addr),
+ RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+ if (sis190_try_rx_copy(&skb, pkt_size, desc, dev) < 0) {
+ tp->Rx_skbuff[entry] = NULL;
+ dma_op = pci_unmap_single;
+ } else
+ dma_op = pci_dma_sync_single_for_device;
+
+ dma_op(tp->pci_dev, le32_to_cpu(desc->buf_addr),
+ RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+
+ skb_put(skb, pkt_size);
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+
+ dev->last_rx = jiffies;
+ tp->stats.rx_bytes += pkt_size;
+ tp->stats.rx_packets++;
}
cur_rx = (cur_rx + 1) % NUM_RX_DESC;
@@ -1139,6 +1170,15 @@ SiS190_rx_interrupt(struct net_device *d
}
tp->cur_rx = cur_rx;
+
+ delta = sis190_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
+ if (delta > 0)
+ tp->dirty_rx += delta;
+ else if (delta < 0)
+ printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
+
+ if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
+ printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
}
/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */
_
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/8] 2.6.5-rc2 - sis190 update
2004-03-27 2:11 ` [PATCH 1/8] " Francois Romieu
2004-03-27 2:12 ` [PATCH 2/8] " Francois Romieu
@ 2004-03-27 2:37 ` Jeff Garzik
1 sibling, 0 replies; 10+ messages in thread
From: Jeff Garzik @ 2004-03-27 2:37 UTC (permalink / raw)
To: Francois Romieu; +Cc: netdev
applied to netdev-2.6 queue, so they will show up in -mm soon.
We need to be careful, I have not seen any users or hardware for this
driver yet. We might just remove it...
Jeff
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2004-03-27 2:37 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-03-27 2:08 [PATCH] [RFT] 2.6.5-rc2 - sis190 update Francois Romieu
2004-03-27 2:11 ` [PATCH 1/8] " Francois Romieu
2004-03-27 2:12 ` [PATCH 2/8] " Francois Romieu
2004-03-27 2:13 ` [PATCH 3/8] " Francois Romieu
2004-03-27 2:13 ` [PATCH 4/8] " Francois Romieu
2004-03-27 2:14 ` [PATCH 5/8] " Francois Romieu
2004-03-27 2:15 ` [PATCH 6/8] " Francois Romieu
2004-03-27 2:16 ` [PATCH 7/8] " Francois Romieu
2004-03-27 2:17 ` [PATCH 8/8] " Francois Romieu
2004-03-27 2:37 ` [PATCH 1/8] " Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).