From: Brad House <brad@mcve.com>
To: Francois Romieu <romieu@fr.zoreil.com>
Cc: Jeff Garzik <jgarzik@pobox.com>,
Brad House <brad_mssw@gentoo.org>,
netdev@oss.sgi.com
Subject: Re: [patches] 2.6.0-test9 - r8169 DMA API conversion
Date: Wed, 19 Nov 2003 19:08:27 -0500 [thread overview]
Message-ID: <3FBC05FB.2020409@mcve.com> (raw)
In-Reply-To: <20031120010056.A19444@electric-eye.fr.zoreil.com>
Just because I'm way to lazy to actually look, is this
against the original r8169, or my patch from the v1.6
driver ??
-Brad
Francois Romieu wrote:
> Jeff Garzik <jgarzik@pobox.com> :
> [...]
>
>>hehe. I certainly don't object... You probably want to look over the
>>r8169 v1.6 that Brad posted a link to, since it does have some improved
>>8169 hardware support (modulo bugs, of course).
>
>
> Ok, will do (hmmm... looks like a free ticket for "Whitespace attacks").
>
> I have attached the usual DMA rework for:
> - the Tx descriptors;
> - the Rx process (with the original big Rx buffer removed).
>
> Feel free to comment/review. Next patch tomorrow.
>
> --
> Ueimor
>
>
> ------------------------------------------------------------------------
>
>
> Conversion of Rx/Tx descriptors to consistent DMA:
> - use pci_alloc_consistent() for Rx/Tx descriptors in rtl8169_open()
> (balanced by pci_free_consistent() on error path as well as in
> rtl8169_close());
> - removal of the fields {Rx/Tx}DescArrays in struct rtl8169_private
> as there is no need to store a non-256 bytes aligned address any more;
> - fix for rtl8169_open() leak when RxBufferRings allocation fails.
> Said allocation is pushed to rtl8169_init_ring() as part of an evil
> cunning plan.
>
>
> drivers/net/r8169.c | 99 +++++++++++++++++++++++++++-------------------------
> 1 files changed, 52 insertions(+), 47 deletions(-)
>
> diff -puN drivers/net/r8169.c~r8169-dma-api-tx drivers/net/r8169.c
> --- linux-2.6.0-test9/drivers/net/r8169.c~r8169-dma-api-tx 2003-11-19 20:30:09.000000000 +0100
> +++ linux-2.6.0-test9-fr/drivers/net/r8169.c 2003-11-19 21:24:44.000000000 +0100
> @@ -89,6 +89,8 @@ static int multicast_filter_limit = 32;
> #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
> #define NUM_RX_DESC 64 /* Number of Rx descriptor registers */
> #define RX_BUF_SIZE 1536 /* Rx Buffer size */
> +#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc))
> +#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc))
>
> #define RTL_MIN_IO_SIZE 0x80
> #define TX_TIMEOUT (6*HZ)
> @@ -280,10 +282,10 @@ struct rtl8169_private {
> 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;
> - unsigned char *TxDescArrays; /* Index of Tx Descriptor buffer */
> - unsigned char *RxDescArrays; /* Index of Rx Descriptor buffer */
> struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */
> struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */
> + dma_addr_t TxPhyAddr;
> + dma_addr_t RxPhyAddr;
> 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 */
> @@ -297,7 +299,7 @@ static int rtl8169_open(struct net_devic
> static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
> static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance,
> struct pt_regs *regs);
> -static void rtl8169_init_ring(struct net_device *dev);
> +static int rtl8169_init_ring(struct net_device *dev);
> static void rtl8169_hw_start(struct net_device *dev);
> static int rtl8169_close(struct net_device *dev);
> static void rtl8169_set_rx_mode(struct net_device *dev);
> @@ -654,52 +656,48 @@ static int
> rtl8169_open(struct net_device *dev)
> {
> struct rtl8169_private *tp = dev->priv;
> + struct pci_dev *pdev = tp->pci_dev;
> int retval;
> - u8 diff;
> - u32 TxPhyAddr, RxPhyAddr;
>
> retval =
> request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev);
> - if (retval) {
> - return retval;
> - }
> + if (retval < 0)
> + goto out;
>
> - tp->TxDescArrays =
> - kmalloc(NUM_TX_DESC * sizeof (struct TxDesc) + 256, GFP_KERNEL);
> - // Tx Desscriptor needs 256 bytes alignment;
> - TxPhyAddr = virt_to_bus(tp->TxDescArrays);
> - diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8));
> - TxPhyAddr += diff;
> - tp->TxDescArray = (struct TxDesc *) (tp->TxDescArrays + diff);
> -
> - tp->RxDescArrays =
> - kmalloc(NUM_RX_DESC * sizeof (struct RxDesc) + 256, GFP_KERNEL);
> - // Rx Desscriptor needs 256 bytes alignment;
> - RxPhyAddr = virt_to_bus(tp->RxDescArrays);
> - diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8));
> - RxPhyAddr += diff;
> - tp->RxDescArray = (struct RxDesc *) (tp->RxDescArrays + diff);
> + retval = -ENOMEM;
>
> - if (tp->TxDescArrays == NULL || tp->RxDescArrays == NULL) {
> - printk(KERN_INFO
> - "Allocate RxDescArray or TxDescArray failed\n");
> - free_irq(dev->irq, dev);
> - if (tp->TxDescArrays)
> - kfree(tp->TxDescArrays);
> - if (tp->RxDescArrays)
> - kfree(tp->RxDescArrays);
> - return -ENOMEM;
> - }
> - tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
> - if (tp->RxBufferRings == NULL) {
> - printk(KERN_INFO "Allocate RxBufferRing failed\n");
> - }
> + /*
> + * Rx and Tx desscriptors needs 256 bytes alignment.
> + * pci_alloc_consistent provides more.
> + */
> + tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
> + &tp->TxPhyAddr);
> + if (!tp->TxDescArray)
> + goto err_free_irq;
> +
> + tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
> + &tp->RxPhyAddr);
> + if (!tp->RxDescArray)
> + goto err_free_tx;
> +
> + retval = rtl8169_init_ring(dev);
> + if (retval < 0)
> + goto err_free_rx;
>
> - rtl8169_init_ring(dev);
> rtl8169_hw_start(dev);
>
> - return 0;
> +out:
> + return retval;
>
> +err_free_rx:
> + pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
> + tp->RxPhyAddr);
> +err_free_tx:
> + pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
> + tp->TxPhyAddr);
> +err_free_irq:
> + free_irq(dev->irq, dev);
> + goto out;
> }
>
> static void
> @@ -739,8 +737,8 @@ rtl8169_hw_start(struct net_device *dev)
>
> tp->cur_rx = 0;
>
> - RTL_W32(TxDescStartAddr, virt_to_bus(tp->TxDescArray));
> - RTL_W32(RxDescStartAddr, virt_to_bus(tp->RxDescArray));
> + RTL_W32(TxDescStartAddr, tp->TxPhyAddr);
> + RTL_W32(RxDescStartAddr, tp->RxPhyAddr);
> RTL_W8(Cfg9346, Cfg9346_Lock);
> udelay(10);
>
> @@ -758,12 +756,17 @@ rtl8169_hw_start(struct net_device *dev)
>
> }
>
> -static void
> -rtl8169_init_ring(struct net_device *dev)
> +static int rtl8169_init_ring(struct net_device *dev)
> {
> struct rtl8169_private *tp = dev->priv;
> int i;
>
> + tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
> + if (tp->RxBufferRings == NULL) {
> + printk(KERN_INFO "Allocate RxBufferRing failed\n");
> + return -ENOMEM;
> + }
> +
> tp->cur_rx = 0;
> tp->cur_tx = 0;
> tp->dirty_tx = 0;
> @@ -783,6 +786,7 @@ rtl8169_init_ring(struct net_device *dev
> tp->RxBufferRing[i] = &(tp->RxBufferRings[i * RX_BUF_SIZE]);
> tp->RxDescArray[i].buf_addr = virt_to_bus(tp->RxBufferRing[i]);
> }
> + return 0;
> }
>
> static void
> @@ -1026,6 +1030,7 @@ static int
> rtl8169_close(struct net_device *dev)
> {
> struct rtl8169_private *tp = dev->priv;
> + struct pci_dev *pdev = tp->pci_dev;
> void *ioaddr = tp->mmio_addr;
> int i;
>
> @@ -1049,10 +1054,10 @@ rtl8169_close(struct net_device *dev)
> free_irq(dev->irq, dev);
>
> rtl8169_tx_clear(tp);
> - kfree(tp->TxDescArrays);
> - kfree(tp->RxDescArrays);
> - tp->TxDescArrays = NULL;
> - tp->RxDescArrays = NULL;
> + pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
> + tp->RxPhyAddr);
> + pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
> + tp->TxPhyAddr);
> tp->TxDescArray = NULL;
> tp->RxDescArray = NULL;
> kfree(tp->RxBufferRings);
>
> _
>
>
> ------------------------------------------------------------------------
>
>
> Conversion of Rx data buffers to PCI DMA
> - endianness is kept in a fscked state as it is in the original code
> (will be adressed in a later patch);
> - rtl8169_rx_clear() walks the buffer ring and releases the allocated
> data buffers. It needs to be used in two places:
> - rtl8169_init_ring() failure path;
> - normal device release (i.e. rtl8169_close);
> - rtl8169_free_rx_skb() releases a Rx data buffer. Mostly an helper
> for rtl8169_rx_clear(). As such it must:
> - unmap the memory area;
> - release the skb;
> - prevent the ring descriptor from being used again;
> - rtl8169_alloc_rx_skb() prepares a Rx data buffer for use.
> As such it must:
> - allocate an skb;
> - map the memory area;
> - reflect the changes in the ring descriptor.
> This function is balanced by rtl8169_free_rx_skb().
> - rtl8169_unmap_rx() simply helps with the 80-columns limit.
> - rtl8169_rx_fill() walks a given range of the buffer ring and
> try to turn any descriptor into a ready to use one. It returns the
> count of modified descriptors and exits if an allocation fails.
> It can be seen as balanced by rtl8169_rx_clear(). Motivation:
> - partially abstract the (usually big) piece of code for the refill
> logic at the end of the Rx interrupt;
> - factorize the refill logic and the initial ring setup.
> - simple conversion of rtl8169_rx_interrupt() without rx_copybreak
> (will be adressed in a later patch).
>
>
> drivers/net/r8169.c | 235 +++++++++++++++++++++++++++++++++++-----------------
> 1 files changed, 161 insertions(+), 74 deletions(-)
>
> diff -puN drivers/net/r8169.c~r8169-dma-api-data-buffers drivers/net/r8169.c
> --- linux-2.6.0-test9/drivers/net/r8169.c~r8169-dma-api-data-buffers 2003-11-19 21:26:45.000000000 +0100
> +++ linux-2.6.0-test9-fr/drivers/net/r8169.c 2003-11-20 00:45:00.000000000 +0100
> @@ -279,15 +279,15 @@ struct rtl8169_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 Rx pkt. */
> + u32 dirty_rx;
> + u32 dirty_tx;
> struct TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */
> struct RxDesc *RxDescArray; /* Index of 256-alignment Rx Descriptor buffer */
> dma_addr_t TxPhyAddr;
> dma_addr_t RxPhyAddr;
> - unsigned char *RxBufferRings; /* Index of Rx Buffer */
> - unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */
> + struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */
> struct sk_buff *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */
> };
>
> @@ -756,37 +756,119 @@ rtl8169_hw_start(struct net_device *dev)
>
> }
>
> -static int rtl8169_init_ring(struct net_device *dev)
> +static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc)
> +{
> + desc->buf_addr = 0xdeadbeef;
> + desc->status = EORbit;
> +}
> +
> +static void rtl8169_free_rx_skb(struct pci_dev *pdev, struct sk_buff **sk_buff,
> + struct RxDesc *desc)
> +{
> + pci_unmap_single(pdev, desc->buf_addr, RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
> + dev_kfree_skb(*sk_buff);
> + *sk_buff = NULL;
> + rtl8169_make_unusable_by_asic(desc);
> +}
> +
> +static inline void rtl8169_give_to_asic(struct RxDesc *desc, dma_addr_t mapping)
> +{
> + desc->buf_addr = mapping;
> + desc->status = OWNbit + RX_BUF_SIZE;
> +}
> +
> +static int rtl8169_alloc_rx_skb(struct pci_dev *pdev, struct net_device *dev,
> + struct sk_buff **sk_buff, struct RxDesc *desc)
> +{
> + struct sk_buff *skb;
> + dma_addr_t mapping;
> + int ret = 0;
> +
> + skb = dev_alloc_skb(RX_BUF_SIZE);
> + 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);
> +
> + rtl8169_give_to_asic(desc, mapping);
> +
> +out:
> + return ret;
> +
> +err_out:
> + ret = -ENOMEM;
> + rtl8169_make_unusable_by_asic(desc);
> + goto out;
> +}
> +
> +static void rtl8169_rx_clear(struct rtl8169_private *tp)
> {
> - struct rtl8169_private *tp = dev->priv;
> int i;
>
> - tp->RxBufferRings = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
> - if (tp->RxBufferRings == NULL) {
> - printk(KERN_INFO "Allocate RxBufferRing failed\n");
> - return -ENOMEM;
> + for (i = 0; i < NUM_RX_DESC; i++) {
> + if (tp->Rx_skbuff[i]) {
> + rtl8169_free_rx_skb(tp->pci_dev, tp->Rx_skbuff + i,
> + tp->RxDescArray + i);
> + }
> }
> +}
>
> - tp->cur_rx = 0;
> - tp->cur_tx = 0;
> - tp->dirty_tx = 0;
> +static u32 rtl8169_rx_fill(struct rtl8169_private *tp, struct net_device *dev,
> + u32 start, u32 end)
> +{
> + u32 cur;
> +
> + for (cur = start; end - start > 0; cur++) {
> + int ret, i = cur % NUM_RX_DESC;
> +
> + if (tp->Rx_skbuff[i])
> + continue;
> +
> + ret = rtl8169_alloc_rx_skb(tp->pci_dev, dev, tp->Rx_skbuff + i,
> + tp->RxDescArray + i);
> + if (ret < 0)
> + break;
> + }
> + return cur - start;
> +}
> +
> +static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc)
> +{
> + desc->status |= EORbit;
> +}
> +
> +static inline void rtl8169_unmark_as_last_descriptor(struct RxDesc *desc)
> +{
> + desc->status &= ~EORbit;
> +}
> +
> +static int rtl8169_init_ring(struct net_device *dev)
> +{
> + struct rtl8169_private *tp = dev->priv;
> +
> + 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));
>
> - for (i = 0; i < NUM_TX_DESC; i++) {
> - tp->Tx_skbuff[i] = NULL;
> - }
> - for (i = 0; i < NUM_RX_DESC; i++) {
> - if (i == (NUM_RX_DESC - 1))
> - tp->RxDescArray[i].status =
> - (OWNbit | EORbit) + RX_BUF_SIZE;
> - else
> - tp->RxDescArray[i].status = OWNbit + RX_BUF_SIZE;
> + memset(tp->Tx_skbuff, 0x0, NUM_TX_DESC * sizeof(struct sk_buff *));
> + memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *));
> +
> + if (rtl8169_rx_fill(tp, dev, 0, NUM_RX_DESC) != NUM_RX_DESC)
> + goto err_out;
> +
> + rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1);
>
> - tp->RxBufferRing[i] = &(tp->RxBufferRings[i * RX_BUF_SIZE]);
> - tp->RxDescArray[i].buf_addr = virt_to_bus(tp->RxBufferRing[i]);
> - }
> return 0;
> +
> +err_out:
> + rtl8169_rx_clear(tp);
> + return -ENOMEM;
> }
>
> static void
> @@ -906,70 +988,77 @@ rtl8169_tx_interrupt(struct net_device *
> }
> }
>
> +static inline void rtl8169_unmap_rx(struct pci_dev *pdev, struct RxDesc *desc)
> +{
> + pci_dma_sync_single(pdev, le32_to_cpu(desc->buf_addr), RX_BUF_SIZE,
> + PCI_DMA_FROMDEVICE);
> + pci_unmap_single(pdev, le32_to_cpu(desc->buf_addr), RX_BUF_SIZE,
> + PCI_DMA_FROMDEVICE);
> +}
> +
> static void
> rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
> void *ioaddr)
> {
> - int cur_rx;
> - struct sk_buff *skb;
> - int pkt_size = 0;
> + int cur_rx, delta;
>
> assert(dev != NULL);
> assert(tp != NULL);
> assert(ioaddr != NULL);
>
> - cur_rx = tp->cur_rx;
> + cur_rx = tp->cur_rx % RX_BUF_SIZE;
>
> while ((tp->RxDescArray[cur_rx].status & OWNbit) == 0) {
> + u32 status = tp->RxDescArray[cur_rx].status;
>
> - if (tp->RxDescArray[cur_rx].status & RxRES) {
> + if (status & RxRES) {
> printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
> tp->stats.rx_errors++;
> - if (tp->RxDescArray[cur_rx].status & (RxRWT | RxRUNT))
> + if (status & (RxRWT | RxRUNT))
> tp->stats.rx_length_errors++;
> - if (tp->RxDescArray[cur_rx].status & RxCRC)
> + if (status & RxCRC)
> tp->stats.rx_crc_errors++;
> } else {
> - pkt_size =
> - (int) (tp->RxDescArray[cur_rx].
> - status & 0x00001FFF) - 4;
> - skb = dev_alloc_skb(pkt_size + 2);
> - if (skb != NULL) {
> - skb->dev = dev;
> - skb_reserve(skb, 2); // 16 byte align the IP fields. //
> - eth_copy_and_sum(skb, tp->RxBufferRing[cur_rx],
> - pkt_size, 0);
> - skb_put(skb, pkt_size);
> - skb->protocol = eth_type_trans(skb, dev);
> - netif_rx(skb);
> -
> - if (cur_rx == (NUM_RX_DESC - 1))
> - tp->RxDescArray[cur_rx].status =
> - (OWNbit | EORbit) + RX_BUF_SIZE;
> - else
> - tp->RxDescArray[cur_rx].status =
> - OWNbit + RX_BUF_SIZE;
> -
> - tp->RxDescArray[cur_rx].buf_addr =
> - virt_to_bus(tp->RxBufferRing[cur_rx]);
> - dev->last_rx = jiffies;
> - tp->stats.rx_bytes += pkt_size;
> - tp->stats.rx_packets++;
> - } 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++;
> - }
> - }
> + struct sk_buff *skb = tp->Rx_skbuff[cur_rx];
> + int pkt_size = (status & 0x00001FFF) - 4;
> +
> + rtl8169_unmap_rx(tp->pci_dev, tp->RxDescArray + cur_rx);
> +
> + skb_put(skb, pkt_size);
> + skb->protocol = eth_type_trans(skb, dev);
> + netif_rx(skb);
>
> - cur_rx = (cur_rx + 1) % NUM_RX_DESC;
> + tp->Rx_skbuff[cur_rx] = NULL;
>
> + dev->last_rx = jiffies;
> + tp->stats.rx_bytes += pkt_size;
> + tp->stats.rx_packets++;
> + }
> +
> + tp->cur_rx++;
> + cur_rx = tp->cur_rx % NUM_RX_DESC;
> }
>
> - tp->cur_rx = cur_rx;
> + delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
> + if (delta > 0) {
> + u32 old_last = (tp->dirty_rx - 1) % NUM_RX_DESC;
> +
> + tp->dirty_rx += delta;
> + rtl8169_mark_as_last_descriptor(tp->RxDescArray +
> + (tp->dirty_rx - 1)%NUM_RX_DESC);
> + rtl8169_unmark_as_last_descriptor(tp->RxDescArray + old_last);
> + } else if (delta < 0)
> + printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
> +
> + /*
> + * FIXME: until there is periodic timer to try and refill the ring,
> + * a temporary shortage may definitely kill the Rx process.
> + * - disable the asic to try and avoid an overflow and kick it again
> + * after refill ?
> + * - how do others driver handle this condition (Uh oh...).
> + */
> + 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. */
> @@ -1032,7 +1121,6 @@ rtl8169_close(struct net_device *dev)
> struct rtl8169_private *tp = dev->priv;
> struct pci_dev *pdev = tp->pci_dev;
> void *ioaddr = tp->mmio_addr;
> - int i;
>
> netif_stop_queue(dev);
>
> @@ -1054,16 +1142,15 @@ rtl8169_close(struct net_device *dev)
> free_irq(dev->irq, dev);
>
> rtl8169_tx_clear(tp);
> +
> + rtl8169_rx_clear(tp);
> +
> pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
> tp->RxPhyAddr);
> pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
> tp->TxPhyAddr);
> tp->TxDescArray = NULL;
> tp->RxDescArray = NULL;
> - kfree(tp->RxBufferRings);
> - for (i = 0; i < NUM_RX_DESC; i++) {
> - tp->RxBufferRing[i] = NULL;
> - }
>
> return 0;
> }
>
> _
next prev parent reply other threads:[~2003-11-20 0:08 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-11-17 4:08 [PATCH 2.6.0-test9-bk6] r8169.c update for 8110S support from RTL 1.6 version Brad House
2003-11-18 4:39 ` r8169 and tg3 Jeff Garzik
2003-11-18 4:51 ` Brad House
2003-11-18 10:00 ` Jan Oravec
2003-11-18 11:01 ` David S. Miller
2003-11-18 12:58 ` Francois Romieu
2003-11-19 17:24 ` Jeff Garzik
2003-11-19 18:44 ` Robert Olsson
2003-11-20 0:00 ` [patches] 2.6.0-test9 - r8169 DMA API conversion Francois Romieu
2003-11-20 0:08 ` Brad House [this message]
2003-11-20 0:45 ` Francois Romieu
2003-11-20 0:59 ` Brad House
2003-11-20 1:34 ` Andre Tomt
2003-11-20 1:35 ` Brad House
2003-11-20 1:36 ` Brad House
2003-11-20 1:36 ` Jeff Garzik
2003-11-21 0:36 ` Francois Romieu
2003-11-21 1:38 ` Jeff Garzik
2003-11-21 23:20 ` Francois Romieu
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=3FBC05FB.2020409@mcve.com \
--to=brad@mcve.com \
--cc=brad_mssw@gentoo.org \
--cc=jgarzik@pobox.com \
--cc=netdev@oss.sgi.com \
--cc=romieu@fr.zoreil.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 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).