diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2007-12-10 13:39:29 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-12-14 15:26:15 -0500 |
commit | 8e9859184031ac1b0a0234b8671a90cfcd333666 (patch) | |
tree | af153b9b74f3833b01175504b8359063bfe24d5f /drivers/net | |
parent | 8543da6672b0994921f014f2250e27ae81645580 (diff) |
hamachi endianness fixes
badly broken on big-endian
* passing little-endian to pci_unmap_single() et.al.
* cpu_to_le32() before passing value to writel()
* worse, cpu_to_le64() and shifting/masking result before the same
* hmp->tx_ring[i].status_n_length = cpu_to_le32(
DescEndRing |
(hmp->tx_ring[i].status_n_length & 0x0000FFFF));
is obviously bogus on big-endian. Not hard to untangle, fortunately...
* poisoning addresses in rx_ring is better done after we'd done
pci_unmap_single() on them, not before that. [this one affects little-endian
as well, obviously, provided that pci_unmap_single() is not a no-op on target
in question]
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/hamachi.c | 70 |
1 files changed, 37 insertions, 33 deletions
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c index ed407c85708f..b53f6b6491b3 100644 --- a/drivers/net/hamachi.c +++ b/drivers/net/hamachi.c | |||
@@ -204,8 +204,10 @@ KERN_INFO " Further modifications by Keith Underwood <keithu@parl.clemson.edu> | |||
204 | /* Condensed bus+endian portability operations. */ | 204 | /* Condensed bus+endian portability operations. */ |
205 | #if ADDRLEN == 64 | 205 | #if ADDRLEN == 64 |
206 | #define cpu_to_leXX(addr) cpu_to_le64(addr) | 206 | #define cpu_to_leXX(addr) cpu_to_le64(addr) |
207 | #define leXX_to_cpu(addr) le64_to_cpu(addr) | ||
207 | #else | 208 | #else |
208 | #define cpu_to_leXX(addr) cpu_to_le32(addr) | 209 | #define cpu_to_leXX(addr) cpu_to_le32(addr) |
210 | #define leXX_to_cpu(addr) le32_to_cpu(addr) | ||
209 | #endif | 211 | #endif |
210 | 212 | ||
211 | 213 | ||
@@ -465,12 +467,12 @@ enum intr_status_bits { | |||
465 | 467 | ||
466 | /* The Hamachi Rx and Tx buffer descriptors. */ | 468 | /* The Hamachi Rx and Tx buffer descriptors. */ |
467 | struct hamachi_desc { | 469 | struct hamachi_desc { |
468 | u32 status_n_length; | 470 | __le32 status_n_length; |
469 | #if ADDRLEN == 64 | 471 | #if ADDRLEN == 64 |
470 | u32 pad; | 472 | u32 pad; |
471 | u64 addr; | 473 | __le64 addr; |
472 | #else | 474 | #else |
473 | u32 addr; | 475 | __le32 addr; |
474 | #endif | 476 | #endif |
475 | }; | 477 | }; |
476 | 478 | ||
@@ -874,13 +876,13 @@ static int hamachi_open(struct net_device *dev) | |||
874 | 876 | ||
875 | #if ADDRLEN == 64 | 877 | #if ADDRLEN == 64 |
876 | /* writellll anyone ? */ | 878 | /* writellll anyone ? */ |
877 | writel(cpu_to_le64(hmp->rx_ring_dma), ioaddr + RxPtr); | 879 | writel(hmp->rx_ring_dma, ioaddr + RxPtr); |
878 | writel(cpu_to_le64(hmp->rx_ring_dma) >> 32, ioaddr + RxPtr + 4); | 880 | writel(hmp->rx_ring_dma >> 32, ioaddr + RxPtr + 4); |
879 | writel(cpu_to_le64(hmp->tx_ring_dma), ioaddr + TxPtr); | 881 | writel(hmp->tx_ring_dma, ioaddr + TxPtr); |
880 | writel(cpu_to_le64(hmp->tx_ring_dma) >> 32, ioaddr + TxPtr + 4); | 882 | writel(hmp->tx_ring_dma >> 32, ioaddr + TxPtr + 4); |
881 | #else | 883 | #else |
882 | writel(cpu_to_le32(hmp->rx_ring_dma), ioaddr + RxPtr); | 884 | writel(hmp->rx_ring_dma, ioaddr + RxPtr); |
883 | writel(cpu_to_le32(hmp->tx_ring_dma), ioaddr + TxPtr); | 885 | writel(hmp->tx_ring_dma, ioaddr + TxPtr); |
884 | #endif | 886 | #endif |
885 | 887 | ||
886 | /* TODO: It would make sense to organize this as words since the card | 888 | /* TODO: It would make sense to organize this as words since the card |
@@ -1019,8 +1021,8 @@ static inline int hamachi_tx(struct net_device *dev) | |||
1019 | skb = hmp->tx_skbuff[entry]; | 1021 | skb = hmp->tx_skbuff[entry]; |
1020 | if (skb) { | 1022 | if (skb) { |
1021 | pci_unmap_single(hmp->pci_dev, | 1023 | pci_unmap_single(hmp->pci_dev, |
1022 | hmp->tx_ring[entry].addr, skb->len, | 1024 | leXX_to_cpu(hmp->tx_ring[entry].addr), |
1023 | PCI_DMA_TODEVICE); | 1025 | skb->len, PCI_DMA_TODEVICE); |
1024 | dev_kfree_skb(skb); | 1026 | dev_kfree_skb(skb); |
1025 | hmp->tx_skbuff[entry] = NULL; | 1027 | hmp->tx_skbuff[entry] = NULL; |
1026 | } | 1028 | } |
@@ -1071,10 +1073,10 @@ static void hamachi_tx_timeout(struct net_device *dev) | |||
1071 | { | 1073 | { |
1072 | printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring); | 1074 | printk(KERN_DEBUG " Rx ring %p: ", hmp->rx_ring); |
1073 | for (i = 0; i < RX_RING_SIZE; i++) | 1075 | for (i = 0; i < RX_RING_SIZE; i++) |
1074 | printk(" %8.8x", (unsigned int)hmp->rx_ring[i].status_n_length); | 1076 | printk(" %8.8x", le32_to_cpu(hmp->rx_ring[i].status_n_length)); |
1075 | printk("\n"KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); | 1077 | printk("\n"KERN_DEBUG" Tx ring %p: ", hmp->tx_ring); |
1076 | for (i = 0; i < TX_RING_SIZE; i++) | 1078 | for (i = 0; i < TX_RING_SIZE; i++) |
1077 | printk(" %4.4x", hmp->tx_ring[i].status_n_length); | 1079 | printk(" %4.4x", le32_to_cpu(hmp->tx_ring[i].status_n_length)); |
1078 | printk("\n"); | 1080 | printk("\n"); |
1079 | } | 1081 | } |
1080 | 1082 | ||
@@ -1099,14 +1101,15 @@ static void hamachi_tx_timeout(struct net_device *dev) | |||
1099 | struct sk_buff *skb; | 1101 | struct sk_buff *skb; |
1100 | 1102 | ||
1101 | if (i >= TX_RING_SIZE - 1) | 1103 | if (i >= TX_RING_SIZE - 1) |
1102 | hmp->tx_ring[i].status_n_length = cpu_to_le32( | 1104 | hmp->tx_ring[i].status_n_length = |
1103 | DescEndRing | | 1105 | cpu_to_le32(DescEndRing) | |
1104 | (hmp->tx_ring[i].status_n_length & 0x0000FFFF)); | 1106 | (hmp->tx_ring[i].status_n_length & |
1107 | cpu_to_le32(0x0000ffff)); | ||
1105 | else | 1108 | else |
1106 | hmp->tx_ring[i].status_n_length &= 0x0000ffff; | 1109 | hmp->tx_ring[i].status_n_length &= cpu_to_le32(0x0000ffff); |
1107 | skb = hmp->tx_skbuff[i]; | 1110 | skb = hmp->tx_skbuff[i]; |
1108 | if (skb){ | 1111 | if (skb){ |
1109 | pci_unmap_single(hmp->pci_dev, hmp->tx_ring[i].addr, | 1112 | pci_unmap_single(hmp->pci_dev, leXX_to_cpu(hmp->tx_ring[i].addr), |
1110 | skb->len, PCI_DMA_TODEVICE); | 1113 | skb->len, PCI_DMA_TODEVICE); |
1111 | dev_kfree_skb(skb); | 1114 | dev_kfree_skb(skb); |
1112 | hmp->tx_skbuff[i] = NULL; | 1115 | hmp->tx_skbuff[i] = NULL; |
@@ -1128,7 +1131,8 @@ static void hamachi_tx_timeout(struct net_device *dev) | |||
1128 | struct sk_buff *skb = hmp->rx_skbuff[i]; | 1131 | struct sk_buff *skb = hmp->rx_skbuff[i]; |
1129 | 1132 | ||
1130 | if (skb){ | 1133 | if (skb){ |
1131 | pci_unmap_single(hmp->pci_dev, hmp->rx_ring[i].addr, | 1134 | pci_unmap_single(hmp->pci_dev, |
1135 | leXX_to_cpu(hmp->rx_ring[i].addr), | ||
1132 | hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); | 1136 | hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); |
1133 | dev_kfree_skb(skb); | 1137 | dev_kfree_skb(skb); |
1134 | hmp->rx_skbuff[i] = NULL; | 1138 | hmp->rx_skbuff[i] = NULL; |
@@ -1420,7 +1424,7 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance) | |||
1420 | /* Free the original skb. */ | 1424 | /* Free the original skb. */ |
1421 | if (skb){ | 1425 | if (skb){ |
1422 | pci_unmap_single(hmp->pci_dev, | 1426 | pci_unmap_single(hmp->pci_dev, |
1423 | hmp->tx_ring[entry].addr, | 1427 | leXX_to_cpu(hmp->tx_ring[entry].addr), |
1424 | skb->len, | 1428 | skb->len, |
1425 | PCI_DMA_TODEVICE); | 1429 | PCI_DMA_TODEVICE); |
1426 | dev_kfree_skb_irq(skb); | 1430 | dev_kfree_skb_irq(skb); |
@@ -1500,11 +1504,11 @@ static int hamachi_rx(struct net_device *dev) | |||
1500 | if (desc_status & DescOwn) | 1504 | if (desc_status & DescOwn) |
1501 | break; | 1505 | break; |
1502 | pci_dma_sync_single_for_cpu(hmp->pci_dev, | 1506 | pci_dma_sync_single_for_cpu(hmp->pci_dev, |
1503 | desc->addr, | 1507 | leXX_to_cpu(desc->addr), |
1504 | hmp->rx_buf_sz, | 1508 | hmp->rx_buf_sz, |
1505 | PCI_DMA_FROMDEVICE); | 1509 | PCI_DMA_FROMDEVICE); |
1506 | buf_addr = (u8 *) hmp->rx_skbuff[entry]->data; | 1510 | buf_addr = (u8 *) hmp->rx_skbuff[entry]->data; |
1507 | frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12]))); | 1511 | frame_status = le32_to_cpu(get_unaligned((__le32*)&(buf_addr[data_size - 12]))); |
1508 | if (hamachi_debug > 4) | 1512 | if (hamachi_debug > 4) |
1509 | printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n", | 1513 | printk(KERN_DEBUG " hamachi_rx() status was %8.8x.\n", |
1510 | frame_status); | 1514 | frame_status); |
@@ -1518,9 +1522,9 @@ static int hamachi_rx(struct net_device *dev) | |||
1518 | dev->name, desc, &hmp->rx_ring[hmp->cur_rx % RX_RING_SIZE]); | 1522 | dev->name, desc, &hmp->rx_ring[hmp->cur_rx % RX_RING_SIZE]); |
1519 | printk(KERN_WARNING "%s: Oversized Ethernet frame -- next status %x/%x last status %x.\n", | 1523 | printk(KERN_WARNING "%s: Oversized Ethernet frame -- next status %x/%x last status %x.\n", |
1520 | dev->name, | 1524 | dev->name, |
1521 | hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length & 0xffff0000, | 1525 | le32_to_cpu(hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length) & 0xffff0000, |
1522 | hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length & 0x0000ffff, | 1526 | le32_to_cpu(hmp->rx_ring[(hmp->cur_rx+1) % RX_RING_SIZE].status_n_length) & 0x0000ffff, |
1523 | hmp->rx_ring[(hmp->cur_rx-1) % RX_RING_SIZE].status_n_length); | 1527 | le32_to_cpu(hmp->rx_ring[(hmp->cur_rx-1) % RX_RING_SIZE].status_n_length)); |
1524 | hmp->stats.rx_length_errors++; | 1528 | hmp->stats.rx_length_errors++; |
1525 | } /* else Omit for prototype errata??? */ | 1529 | } /* else Omit for prototype errata??? */ |
1526 | if (frame_status & 0x00380000) { | 1530 | if (frame_status & 0x00380000) { |
@@ -1566,7 +1570,7 @@ static int hamachi_rx(struct net_device *dev) | |||
1566 | #endif | 1570 | #endif |
1567 | skb_reserve(skb, 2); /* 16 byte align the IP header */ | 1571 | skb_reserve(skb, 2); /* 16 byte align the IP header */ |
1568 | pci_dma_sync_single_for_cpu(hmp->pci_dev, | 1572 | pci_dma_sync_single_for_cpu(hmp->pci_dev, |
1569 | hmp->rx_ring[entry].addr, | 1573 | leXX_to_cpu(hmp->rx_ring[entry].addr), |
1570 | hmp->rx_buf_sz, | 1574 | hmp->rx_buf_sz, |
1571 | PCI_DMA_FROMDEVICE); | 1575 | PCI_DMA_FROMDEVICE); |
1572 | /* Call copy + cksum if available. */ | 1576 | /* Call copy + cksum if available. */ |
@@ -1579,12 +1583,12 @@ static int hamachi_rx(struct net_device *dev) | |||
1579 | + entry*sizeof(*desc), pkt_len); | 1583 | + entry*sizeof(*desc), pkt_len); |
1580 | #endif | 1584 | #endif |
1581 | pci_dma_sync_single_for_device(hmp->pci_dev, | 1585 | pci_dma_sync_single_for_device(hmp->pci_dev, |
1582 | hmp->rx_ring[entry].addr, | 1586 | leXX_to_cpu(hmp->rx_ring[entry].addr), |
1583 | hmp->rx_buf_sz, | 1587 | hmp->rx_buf_sz, |
1584 | PCI_DMA_FROMDEVICE); | 1588 | PCI_DMA_FROMDEVICE); |
1585 | } else { | 1589 | } else { |
1586 | pci_unmap_single(hmp->pci_dev, | 1590 | pci_unmap_single(hmp->pci_dev, |
1587 | hmp->rx_ring[entry].addr, | 1591 | leXX_to_cpu(hmp->rx_ring[entry].addr), |
1588 | hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); | 1592 | hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); |
1589 | skb_put(skb = hmp->rx_skbuff[entry], pkt_len); | 1593 | skb_put(skb = hmp->rx_skbuff[entry], pkt_len); |
1590 | hmp->rx_skbuff[entry] = NULL; | 1594 | hmp->rx_skbuff[entry] = NULL; |
@@ -1787,21 +1791,21 @@ static int hamachi_close(struct net_device *dev) | |||
1787 | for (i = 0; i < RX_RING_SIZE; i++) { | 1791 | for (i = 0; i < RX_RING_SIZE; i++) { |
1788 | skb = hmp->rx_skbuff[i]; | 1792 | skb = hmp->rx_skbuff[i]; |
1789 | hmp->rx_ring[i].status_n_length = 0; | 1793 | hmp->rx_ring[i].status_n_length = 0; |
1790 | hmp->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ | ||
1791 | if (skb) { | 1794 | if (skb) { |
1792 | pci_unmap_single(hmp->pci_dev, | 1795 | pci_unmap_single(hmp->pci_dev, |
1793 | hmp->rx_ring[i].addr, hmp->rx_buf_sz, | 1796 | leXX_to_cpu(hmp->rx_ring[i].addr), |
1794 | PCI_DMA_FROMDEVICE); | 1797 | hmp->rx_buf_sz, PCI_DMA_FROMDEVICE); |
1795 | dev_kfree_skb(skb); | 1798 | dev_kfree_skb(skb); |
1796 | hmp->rx_skbuff[i] = NULL; | 1799 | hmp->rx_skbuff[i] = NULL; |
1797 | } | 1800 | } |
1801 | hmp->rx_ring[i].addr = cpu_to_leXX(0xBADF00D0); /* An invalid address. */ | ||
1798 | } | 1802 | } |
1799 | for (i = 0; i < TX_RING_SIZE; i++) { | 1803 | for (i = 0; i < TX_RING_SIZE; i++) { |
1800 | skb = hmp->tx_skbuff[i]; | 1804 | skb = hmp->tx_skbuff[i]; |
1801 | if (skb) { | 1805 | if (skb) { |
1802 | pci_unmap_single(hmp->pci_dev, | 1806 | pci_unmap_single(hmp->pci_dev, |
1803 | hmp->tx_ring[i].addr, skb->len, | 1807 | leXX_to_cpu(hmp->tx_ring[i].addr), |
1804 | PCI_DMA_TODEVICE); | 1808 | skb->len, PCI_DMA_TODEVICE); |
1805 | dev_kfree_skb(skb); | 1809 | dev_kfree_skb(skb); |
1806 | hmp->tx_skbuff[i] = NULL; | 1810 | hmp->tx_skbuff[i] = NULL; |
1807 | } | 1811 | } |