Commit 902f3218 authored by François Romieu's avatar François Romieu Committed by Jeff Garzik

[netdrvr r8169] 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.
parent 4576b4fa
...@@ -89,6 +89,8 @@ static int multicast_filter_limit = 32; ...@@ -89,6 +89,8 @@ static int multicast_filter_limit = 32;
#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ #define NUM_TX_DESC 64 /* Number of Tx descriptor registers */
#define NUM_RX_DESC 64 /* Number of Rx descriptor registers */ #define NUM_RX_DESC 64 /* Number of Rx descriptor registers */
#define RX_BUF_SIZE 1536 /* Rx Buffer size */ #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 RTL_MIN_IO_SIZE 0x80
#define TX_TIMEOUT (6*HZ) #define TX_TIMEOUT (6*HZ)
...@@ -280,10 +282,10 @@ struct rtl8169_private { ...@@ -280,10 +282,10 @@ struct rtl8169_private {
unsigned long cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ 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 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
unsigned long dirty_tx; 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 TxDesc *TxDescArray; /* Index of 256-alignment Tx Descriptor buffer */
struct RxDesc *RxDescArray; /* Index of 256-alignment Rx 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 *RxBufferRings; /* Index of Rx Buffer */
unsigned char *RxBufferRing[NUM_RX_DESC]; /* Index of Rx Buffer array */ 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 *Tx_skbuff[NUM_TX_DESC]; /* Index of Transmit data buffer */
...@@ -298,7 +300,7 @@ static int rtl8169_open(struct net_device *dev); ...@@ -298,7 +300,7 @@ static int rtl8169_open(struct net_device *dev);
static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev); static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance, static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance,
struct pt_regs *regs); 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 void rtl8169_hw_start(struct net_device *dev);
static int rtl8169_close(struct net_device *dev); static int rtl8169_close(struct net_device *dev);
static void rtl8169_set_rx_mode(struct net_device *dev); static void rtl8169_set_rx_mode(struct net_device *dev);
...@@ -651,52 +653,48 @@ static int ...@@ -651,52 +653,48 @@ static int
rtl8169_open(struct net_device *dev) rtl8169_open(struct net_device *dev)
{ {
struct rtl8169_private *tp = dev->priv; struct rtl8169_private *tp = dev->priv;
struct pci_dev *pdev = tp->pci_dev;
int retval; int retval;
u8 diff;
u32 TxPhyAddr, RxPhyAddr;
retval = retval =
request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev); request_irq(dev->irq, rtl8169_interrupt, SA_SHIRQ, dev->name, dev);
if (retval) { if (retval < 0)
return retval; goto out;
}
tp->TxDescArrays = retval = -ENOMEM;
kmalloc(NUM_TX_DESC * sizeof (struct TxDesc) + 256, GFP_KERNEL);
// Tx Desscriptor needs 256 bytes alignment; /*
TxPhyAddr = virt_to_bus(tp->TxDescArrays); * Rx and Tx desscriptors needs 256 bytes alignment.
diff = 256 - (TxPhyAddr - ((TxPhyAddr >> 8) << 8)); * pci_alloc_consistent provides more.
TxPhyAddr += diff; */
tp->TxDescArray = (struct TxDesc *) (tp->TxDescArrays + diff); tp->TxDescArray = pci_alloc_consistent(pdev, R8169_TX_RING_BYTES,
&tp->TxPhyAddr);
tp->RxDescArrays = if (!tp->TxDescArray)
kmalloc(NUM_RX_DESC * sizeof (struct RxDesc) + 256, GFP_KERNEL); goto err_free_irq;
// Rx Desscriptor needs 256 bytes alignment;
RxPhyAddr = virt_to_bus(tp->RxDescArrays); tp->RxDescArray = pci_alloc_consistent(pdev, R8169_RX_RING_BYTES,
diff = 256 - (RxPhyAddr - ((RxPhyAddr >> 8) << 8)); &tp->RxPhyAddr);
RxPhyAddr += diff; if (!tp->RxDescArray)
tp->RxDescArray = (struct RxDesc *) (tp->RxDescArrays + diff); goto err_free_tx;
if (tp->TxDescArrays == NULL || tp->RxDescArrays == NULL) { retval = rtl8169_init_ring(dev);
printk(KERN_INFO if (retval < 0)
"Allocate RxDescArray or TxDescArray failed\n"); goto err_free_rx;
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");
}
rtl8169_init_ring(dev);
rtl8169_hw_start(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 static void
...@@ -736,8 +734,8 @@ rtl8169_hw_start(struct net_device *dev) ...@@ -736,8 +734,8 @@ rtl8169_hw_start(struct net_device *dev)
tp->cur_rx = 0; tp->cur_rx = 0;
RTL_W32(TxDescStartAddr, virt_to_bus(tp->TxDescArray)); RTL_W32(TxDescStartAddr, tp->TxPhyAddr);
RTL_W32(RxDescStartAddr, virt_to_bus(tp->RxDescArray)); RTL_W32(RxDescStartAddr, tp->RxPhyAddr);
RTL_W8(Cfg9346, Cfg9346_Lock); RTL_W8(Cfg9346, Cfg9346_Lock);
udelay(10); udelay(10);
...@@ -755,12 +753,17 @@ rtl8169_hw_start(struct net_device *dev) ...@@ -755,12 +753,17 @@ rtl8169_hw_start(struct net_device *dev)
} }
static void static int rtl8169_init_ring(struct net_device *dev)
rtl8169_init_ring(struct net_device *dev)
{ {
struct rtl8169_private *tp = dev->priv; struct rtl8169_private *tp = dev->priv;
int i; 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_rx = 0;
tp->cur_tx = 0; tp->cur_tx = 0;
tp->dirty_tx = 0; tp->dirty_tx = 0;
...@@ -780,6 +783,7 @@ rtl8169_init_ring(struct net_device *dev) ...@@ -780,6 +783,7 @@ rtl8169_init_ring(struct net_device *dev)
tp->RxBufferRing[i] = &(tp->RxBufferRings[i * RX_BUF_SIZE]); tp->RxBufferRing[i] = &(tp->RxBufferRings[i * RX_BUF_SIZE]);
tp->RxDescArray[i].buf_addr = virt_to_bus(tp->RxBufferRing[i]); tp->RxDescArray[i].buf_addr = virt_to_bus(tp->RxBufferRing[i]);
} }
return 0;
} }
static void static void
...@@ -1023,6 +1027,7 @@ static int ...@@ -1023,6 +1027,7 @@ static int
rtl8169_close(struct net_device *dev) rtl8169_close(struct net_device *dev)
{ {
struct rtl8169_private *tp = dev->priv; struct rtl8169_private *tp = dev->priv;
struct pci_dev *pdev = tp->pci_dev;
void *ioaddr = tp->mmio_addr; void *ioaddr = tp->mmio_addr;
int i; int i;
...@@ -1046,10 +1051,10 @@ rtl8169_close(struct net_device *dev) ...@@ -1046,10 +1051,10 @@ rtl8169_close(struct net_device *dev)
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
rtl8169_tx_clear(tp); rtl8169_tx_clear(tp);
kfree(tp->TxDescArrays); pci_free_consistent(pdev, R8169_RX_RING_BYTES, tp->RxDescArray,
kfree(tp->RxDescArrays); tp->RxPhyAddr);
tp->TxDescArrays = NULL; pci_free_consistent(pdev, R8169_TX_RING_BYTES, tp->TxDescArray,
tp->RxDescArrays = NULL; tp->TxPhyAddr);
tp->TxDescArray = NULL; tp->TxDescArray = NULL;
tp->RxDescArray = NULL; tp->RxDescArray = NULL;
kfree(tp->RxBufferRings); kfree(tp->RxBufferRings);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment