Commit 26394310 authored by Jeff Garzik's avatar Jeff Garzik

Add 64-bit DMA support to 8139cp net driver

parent f4aea019
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
TODO, in rough priority order: TODO, in rough priority order:
* Test Tx checksumming thoroughly * Test Tx checksumming thoroughly
* support 64-bit PCI DMA
* dev->tx_timeout * dev->tx_timeout
* LinkChg interrupt * LinkChg interrupt
* Support forcing media type with a module parameter, * Support forcing media type with a module parameter,
...@@ -50,7 +49,7 @@ ...@@ -50,7 +49,7 @@
*/ */
#define DRV_NAME "8139cp" #define DRV_NAME "8139cp"
#define DRV_VERSION "0.2.0" #define DRV_VERSION "0.2.1"
#define DRV_RELDATE "Aug 9, 2002" #define DRV_RELDATE "Aug 9, 2002"
...@@ -253,6 +252,7 @@ enum { ...@@ -253,6 +252,7 @@ enum {
/* C+ mode command register */ /* C+ mode command register */
RxVlanOn = (1 << 6), /* Rx VLAN de-tagging enable */ RxVlanOn = (1 << 6), /* Rx VLAN de-tagging enable */
RxChkSum = (1 << 5), /* Rx checksum offload enable */ RxChkSum = (1 << 5), /* Rx checksum offload enable */
PCIDAC = (1 << 4), /* PCI Dual Address Cycle (64-bit PCI) */
PCIMulRW = (1 << 3), /* Enable PCI read/write multiple */ PCIMulRW = (1 << 3), /* Enable PCI read/write multiple */
CpRxOn = (1 << 1), /* Rx mode enable */ CpRxOn = (1 << 1), /* Rx mode enable */
CpTxOn = (1 << 0), /* Tx mode enable */ CpTxOn = (1 << 0), /* Tx mode enable */
...@@ -309,7 +309,7 @@ struct cp_desc { ...@@ -309,7 +309,7 @@ struct cp_desc {
struct ring_info { struct ring_info {
struct sk_buff *skb; struct sk_buff *skb;
dma_addr_t mapping; dma64_addr_t mapping;
unsigned frag; unsigned frag;
}; };
...@@ -365,6 +365,7 @@ struct cp_private { ...@@ -365,6 +365,7 @@ struct cp_private {
struct sk_buff *frag_skb; struct sk_buff *frag_skb;
unsigned dropping_frag : 1; unsigned dropping_frag : 1;
unsigned pci_using_dac : 1;
unsigned int board_type; unsigned int board_type;
unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */ unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */
...@@ -578,7 +579,7 @@ static void cp_rx (struct cp_private *cp) ...@@ -578,7 +579,7 @@ static void cp_rx (struct cp_private *cp)
while (rx_work--) { while (rx_work--) {
u32 status, len; u32 status, len;
dma_addr_t mapping; dma64_addr_t mapping;
struct sk_buff *skb, *new_skb; struct sk_buff *skb, *new_skb;
struct cp_desc *desc; struct cp_desc *desc;
unsigned buflen; unsigned buflen;
...@@ -645,7 +646,8 @@ static void cp_rx (struct cp_private *cp) ...@@ -645,7 +646,8 @@ static void cp_rx (struct cp_private *cp)
else else
desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz); desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
cp->rx_ring[rx_tail].opts2 = 0; cp->rx_ring[rx_tail].opts2 = 0;
cp->rx_ring[rx_tail].addr_lo = cpu_to_le32(mapping); cp->rx_ring[rx_tail].addr_lo = cpu_to_le32(mapping & 0xffffffff);
cp->rx_ring[rx_tail].addr_hi = cpu_to_le32(mapping >> 32);
rx_tail = NEXT_RX(rx_tail); rx_tail = NEXT_RX(rx_tail);
} }
...@@ -776,13 +778,15 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -776,13 +778,15 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
if (skb_shinfo(skb)->nr_frags == 0) { if (skb_shinfo(skb)->nr_frags == 0) {
struct cp_desc *txd = &cp->tx_ring[entry]; struct cp_desc *txd = &cp->tx_ring[entry];
u32 mapping, len; u32 len;
dma64_addr_t mapping;
len = skb->len; len = skb->len;
mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE); mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
CP_VLAN_TX_TAG(txd, vlan_tag); CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping); txd->addr_lo = cpu_to_le32(mapping & 0xffffffff);
txd->addr_hi = cpu_to_le32(mapping >> 32);
wmb(); wmb();
#ifdef CP_TX_CHECKSUM #ifdef CP_TX_CHECKSUM
...@@ -810,7 +814,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -810,7 +814,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
entry = NEXT_TX(entry); entry = NEXT_TX(entry);
} else { } else {
struct cp_desc *txd; struct cp_desc *txd;
u32 first_len, first_mapping; u32 first_len;
dma64_addr_t first_mapping;
int frag, first_entry = entry; int frag, first_entry = entry;
#ifdef CP_TX_CHECKSUM #ifdef CP_TX_CHECKSUM
const struct iphdr *ip = skb->nh.iph; const struct iphdr *ip = skb->nh.iph;
...@@ -829,8 +834,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -829,8 +834,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
u32 len, mapping; u32 len;
u32 ctrl; u32 ctrl;
dma64_addr_t mapping;
len = this_frag->size; len = this_frag->size;
mapping = pci_map_single(cp->pdev, mapping = pci_map_single(cp->pdev,
...@@ -856,7 +862,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -856,7 +862,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
txd = &cp->tx_ring[entry]; txd = &cp->tx_ring[entry];
CP_VLAN_TX_TAG(txd, vlan_tag); CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(mapping); txd->addr_lo = cpu_to_le32(mapping & 0xffffffff);
txd->addr_hi = cpu_to_le32(mapping >> 32);
wmb(); wmb();
txd->opts1 = cpu_to_le32(ctrl); txd->opts1 = cpu_to_le32(ctrl);
...@@ -870,7 +877,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev) ...@@ -870,7 +877,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
txd = &cp->tx_ring[first_entry]; txd = &cp->tx_ring[first_entry];
CP_VLAN_TX_TAG(txd, vlan_tag); CP_VLAN_TX_TAG(txd, vlan_tag);
txd->addr_lo = cpu_to_le32(first_mapping); txd->addr_lo = cpu_to_le32(first_mapping & 0xffffffff);
txd->addr_hi = cpu_to_le32(first_mapping >> 32);
wmb(); wmb();
#ifdef CP_TX_CHECKSUM #ifdef CP_TX_CHECKSUM
...@@ -1015,10 +1023,11 @@ static void cp_reset_hw (struct cp_private *cp) ...@@ -1015,10 +1023,11 @@ static void cp_reset_hw (struct cp_private *cp)
static inline void cp_start_hw (struct cp_private *cp) static inline void cp_start_hw (struct cp_private *cp)
{ {
u16 pci_dac = cp->pci_using_dac ? PCIDAC : 0;
if (cp->board_type == RTL8169) if (cp->board_type == RTL8169)
cpw16(CpCmd, PCIMulRW | RxChkSum); cpw16(CpCmd, pci_dac | PCIMulRW | RxChkSum);
else else
cpw16(CpCmd, PCIMulRW | RxChkSum | CpRxOn | CpTxOn); cpw16(CpCmd, pci_dac | PCIMulRW | RxChkSum | CpRxOn | CpTxOn);
cpw8(Cmd, RxOn | TxOn); cpw8(Cmd, RxOn | TxOn);
} }
...@@ -1091,8 +1100,10 @@ static int cp_refill_rx (struct cp_private *cp) ...@@ -1091,8 +1100,10 @@ static int cp_refill_rx (struct cp_private *cp)
cp->rx_ring[i].opts1 = cp->rx_ring[i].opts1 =
cpu_to_le32(DescOwn | cp->rx_buf_sz); cpu_to_le32(DescOwn | cp->rx_buf_sz);
cp->rx_ring[i].opts2 = 0; cp->rx_ring[i].opts2 = 0;
cp->rx_ring[i].addr_lo = cpu_to_le32(cp->rx_skb[i].mapping); cp->rx_ring[i].addr_lo =
cp->rx_ring[i].addr_hi = 0; cpu_to_le32(cp->rx_skb[i].mapping & 0xffffffff);
cp->rx_ring[i].addr_hi =
cpu_to_le32(cp->rx_skb[i].mapping >> 32);
} }
return 0; return 0;
...@@ -1756,7 +1767,7 @@ static int __devinit cp_init_one (struct pci_dev *pdev, ...@@ -1756,7 +1767,7 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
int rc; int rc;
void *regs; void *regs;
long pciaddr; long pciaddr;
unsigned addr_len, i; unsigned int addr_len, i;
u8 pci_rev, cache_size; u8 pci_rev, cache_size;
u16 pci_command; u16 pci_command;
unsigned int board_type = (unsigned int) ent->driver_data; unsigned int board_type = (unsigned int) ent->driver_data;
...@@ -1821,6 +1832,19 @@ static int __devinit cp_init_one (struct pci_dev *pdev, ...@@ -1821,6 +1832,19 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
goto err_out_res; goto err_out_res;
} }
/* Configure DMA attributes. */
if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) {
cp->pci_using_dac = 1;
} else {
rc = pci_set_dma_mask(pdev, (u64) 0xffffffff);
if (rc) {
printk(KERN_ERR PFX "No usable DMA configuration, "
"aborting.\n");
goto err_out_res;
}
cp->pci_using_dac = 0;
}
regs = ioremap_nocache(pciaddr, CP_REGS_SIZE); regs = ioremap_nocache(pciaddr, CP_REGS_SIZE);
if (!regs) { if (!regs) {
rc = -EIO; rc = -EIO;
......
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