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 @@
TODO, in rough priority order:
* Test Tx checksumming thoroughly
* support 64-bit PCI DMA
* dev->tx_timeout
* LinkChg interrupt
* Support forcing media type with a module parameter,
......@@ -50,7 +49,7 @@
*/
#define DRV_NAME "8139cp"
#define DRV_VERSION "0.2.0"
#define DRV_VERSION "0.2.1"
#define DRV_RELDATE "Aug 9, 2002"
......@@ -253,6 +252,7 @@ enum {
/* C+ mode command register */
RxVlanOn = (1 << 6), /* Rx VLAN de-tagging 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 */
CpRxOn = (1 << 1), /* Rx mode enable */
CpTxOn = (1 << 0), /* Tx mode enable */
......@@ -309,7 +309,7 @@ struct cp_desc {
struct ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
dma64_addr_t mapping;
unsigned frag;
};
......@@ -365,6 +365,7 @@ struct cp_private {
struct sk_buff *frag_skb;
unsigned dropping_frag : 1;
unsigned pci_using_dac : 1;
unsigned int board_type;
unsigned int wol_enabled : 1; /* Is Wake-on-LAN enabled? */
......@@ -578,7 +579,7 @@ static void cp_rx (struct cp_private *cp)
while (rx_work--) {
u32 status, len;
dma_addr_t mapping;
dma64_addr_t mapping;
struct sk_buff *skb, *new_skb;
struct cp_desc *desc;
unsigned buflen;
......@@ -645,7 +646,8 @@ static void cp_rx (struct cp_private *cp)
else
desc->opts1 = cpu_to_le32(DescOwn | cp->rx_buf_sz);
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);
}
......@@ -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;
if (skb_shinfo(skb)->nr_frags == 0) {
struct cp_desc *txd = &cp->tx_ring[entry];
u32 mapping, len;
u32 len;
dma64_addr_t mapping;
len = skb->len;
mapping = pci_map_single(cp->pdev, skb->data, len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
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();
#ifdef CP_TX_CHECKSUM
......@@ -810,7 +814,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
entry = NEXT_TX(entry);
} else {
struct cp_desc *txd;
u32 first_len, first_mapping;
u32 first_len;
dma64_addr_t first_mapping;
int frag, first_entry = entry;
#ifdef CP_TX_CHECKSUM
const struct iphdr *ip = skb->nh.iph;
......@@ -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++) {
skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
u32 len, mapping;
u32 len;
u32 ctrl;
dma64_addr_t mapping;
len = this_frag->size;
mapping = pci_map_single(cp->pdev,
......@@ -856,7 +862,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
txd = &cp->tx_ring[entry];
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();
txd->opts1 = cpu_to_le32(ctrl);
......@@ -870,7 +877,8 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
txd = &cp->tx_ring[first_entry];
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();
#ifdef CP_TX_CHECKSUM
......@@ -1015,10 +1023,11 @@ static void cp_reset_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)
cpw16(CpCmd, PCIMulRW | RxChkSum);
cpw16(CpCmd, pci_dac | PCIMulRW | RxChkSum);
else
cpw16(CpCmd, PCIMulRW | RxChkSum | CpRxOn | CpTxOn);
cpw16(CpCmd, pci_dac | PCIMulRW | RxChkSum | CpRxOn | CpTxOn);
cpw8(Cmd, RxOn | TxOn);
}
......@@ -1091,8 +1100,10 @@ static int cp_refill_rx (struct cp_private *cp)
cp->rx_ring[i].opts1 =
cpu_to_le32(DescOwn | cp->rx_buf_sz);
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_hi = 0;
cp->rx_ring[i].addr_lo =
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;
......@@ -1756,7 +1767,7 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
int rc;
void *regs;
long pciaddr;
unsigned addr_len, i;
unsigned int addr_len, i;
u8 pci_rev, cache_size;
u16 pci_command;
unsigned int board_type = (unsigned int) ent->driver_data;
......@@ -1821,6 +1832,19 @@ static int __devinit cp_init_one (struct pci_dev *pdev,
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);
if (!regs) {
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