aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/b44.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/b44.c')
-rw-r--r--drivers/net/b44.c164
1 files changed, 143 insertions, 21 deletions
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 94939f570f78..0ee3e27969c6 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -19,6 +19,7 @@
19#include <linux/delay.h> 19#include <linux/delay.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/version.h> 21#include <linux/version.h>
22#include <linux/dma-mapping.h>
22 23
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24#include <asm/io.h> 25#include <asm/io.h>
@@ -106,6 +107,29 @@ static int b44_poll(struct net_device *dev, int *budget);
106static void b44_poll_controller(struct net_device *dev); 107static void b44_poll_controller(struct net_device *dev);
107#endif 108#endif
108 109
110static int dma_desc_align_mask;
111static int dma_desc_sync_size;
112
113static inline void b44_sync_dma_desc_for_device(struct pci_dev *pdev,
114 dma_addr_t dma_base,
115 unsigned long offset,
116 enum dma_data_direction dir)
117{
118 dma_sync_single_range_for_device(&pdev->dev, dma_base,
119 offset & dma_desc_align_mask,
120 dma_desc_sync_size, dir);
121}
122
123static inline void b44_sync_dma_desc_for_cpu(struct pci_dev *pdev,
124 dma_addr_t dma_base,
125 unsigned long offset,
126 enum dma_data_direction dir)
127{
128 dma_sync_single_range_for_cpu(&pdev->dev, dma_base,
129 offset & dma_desc_align_mask,
130 dma_desc_sync_size, dir);
131}
132
109static inline unsigned long br32(const struct b44 *bp, unsigned long reg) 133static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
110{ 134{
111 return readl(bp->regs + reg); 135 return readl(bp->regs + reg);
@@ -668,6 +692,11 @@ static int b44_alloc_rx_skb(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
668 dp->ctrl = cpu_to_le32(ctrl); 692 dp->ctrl = cpu_to_le32(ctrl);
669 dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset); 693 dp->addr = cpu_to_le32((u32) mapping + bp->rx_offset + bp->dma_offset);
670 694
695 if (bp->flags & B44_FLAG_RX_RING_HACK)
696 b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
697 dest_idx * sizeof(dp),
698 DMA_BIDIRECTIONAL);
699
671 return RX_PKT_BUF_SZ; 700 return RX_PKT_BUF_SZ;
672} 701}
673 702
@@ -692,6 +721,11 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
692 pci_unmap_addr_set(dest_map, mapping, 721 pci_unmap_addr_set(dest_map, mapping,
693 pci_unmap_addr(src_map, mapping)); 722 pci_unmap_addr(src_map, mapping));
694 723
724 if (bp->flags & B44_FLAG_RX_RING_HACK)
725 b44_sync_dma_desc_for_cpu(bp->pdev, bp->rx_ring_dma,
726 src_idx * sizeof(src_desc),
727 DMA_BIDIRECTIONAL);
728
695 ctrl = src_desc->ctrl; 729 ctrl = src_desc->ctrl;
696 if (dest_idx == (B44_RX_RING_SIZE - 1)) 730 if (dest_idx == (B44_RX_RING_SIZE - 1))
697 ctrl |= cpu_to_le32(DESC_CTRL_EOT); 731 ctrl |= cpu_to_le32(DESC_CTRL_EOT);
@@ -700,8 +734,14 @@ static void b44_recycle_rx(struct b44 *bp, int src_idx, u32 dest_idx_unmasked)
700 734
701 dest_desc->ctrl = ctrl; 735 dest_desc->ctrl = ctrl;
702 dest_desc->addr = src_desc->addr; 736 dest_desc->addr = src_desc->addr;
737
703 src_map->skb = NULL; 738 src_map->skb = NULL;
704 739
740 if (bp->flags & B44_FLAG_RX_RING_HACK)
741 b44_sync_dma_desc_for_device(bp->pdev, bp->rx_ring_dma,
742 dest_idx * sizeof(dest_desc),
743 DMA_BIDIRECTIONAL);
744
705 pci_dma_sync_single_for_device(bp->pdev, src_desc->addr, 745 pci_dma_sync_single_for_device(bp->pdev, src_desc->addr,
706 RX_PKT_BUF_SZ, 746 RX_PKT_BUF_SZ,
707 PCI_DMA_FROMDEVICE); 747 PCI_DMA_FROMDEVICE);
@@ -959,6 +999,11 @@ static int b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
959 bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl); 999 bp->tx_ring[entry].ctrl = cpu_to_le32(ctrl);
960 bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset); 1000 bp->tx_ring[entry].addr = cpu_to_le32((u32) mapping+bp->dma_offset);
961 1001
1002 if (bp->flags & B44_FLAG_TX_RING_HACK)
1003 b44_sync_dma_desc_for_device(bp->pdev, bp->tx_ring_dma,
1004 entry * sizeof(bp->tx_ring[0]),
1005 DMA_TO_DEVICE);
1006
962 entry = NEXT_TX(entry); 1007 entry = NEXT_TX(entry);
963 1008
964 bp->tx_prod = entry; 1009 bp->tx_prod = entry;
@@ -1064,6 +1109,16 @@ static void b44_init_rings(struct b44 *bp)
1064 memset(bp->rx_ring, 0, B44_RX_RING_BYTES); 1109 memset(bp->rx_ring, 0, B44_RX_RING_BYTES);
1065 memset(bp->tx_ring, 0, B44_TX_RING_BYTES); 1110 memset(bp->tx_ring, 0, B44_TX_RING_BYTES);
1066 1111
1112 if (bp->flags & B44_FLAG_RX_RING_HACK)
1113 dma_sync_single_for_device(&bp->pdev->dev, bp->rx_ring_dma,
1114 DMA_TABLE_BYTES,
1115 PCI_DMA_BIDIRECTIONAL);
1116
1117 if (bp->flags & B44_FLAG_TX_RING_HACK)
1118 dma_sync_single_for_device(&bp->pdev->dev, bp->tx_ring_dma,
1119 DMA_TABLE_BYTES,
1120 PCI_DMA_TODEVICE);
1121
1067 for (i = 0; i < bp->rx_pending; i++) { 1122 for (i = 0; i < bp->rx_pending; i++) {
1068 if (b44_alloc_rx_skb(bp, -1, i) < 0) 1123 if (b44_alloc_rx_skb(bp, -1, i) < 0)
1069 break; 1124 break;
@@ -1076,23 +1131,33 @@ static void b44_init_rings(struct b44 *bp)
1076 */ 1131 */
1077static void b44_free_consistent(struct b44 *bp) 1132static void b44_free_consistent(struct b44 *bp)
1078{ 1133{
1079 if (bp->rx_buffers) { 1134 kfree(bp->rx_buffers);
1080 kfree(bp->rx_buffers); 1135 bp->rx_buffers = NULL;
1081 bp->rx_buffers = NULL; 1136 kfree(bp->tx_buffers);
1082 } 1137 bp->tx_buffers = NULL;
1083 if (bp->tx_buffers) {
1084 kfree(bp->tx_buffers);
1085 bp->tx_buffers = NULL;
1086 }
1087 if (bp->rx_ring) { 1138 if (bp->rx_ring) {
1088 pci_free_consistent(bp->pdev, DMA_TABLE_BYTES, 1139 if (bp->flags & B44_FLAG_RX_RING_HACK) {
1089 bp->rx_ring, bp->rx_ring_dma); 1140 dma_unmap_single(&bp->pdev->dev, bp->rx_ring_dma,
1141 DMA_TABLE_BYTES,
1142 DMA_BIDIRECTIONAL);
1143 kfree(bp->rx_ring);
1144 } else
1145 pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
1146 bp->rx_ring, bp->rx_ring_dma);
1090 bp->rx_ring = NULL; 1147 bp->rx_ring = NULL;
1148 bp->flags &= ~B44_FLAG_RX_RING_HACK;
1091 } 1149 }
1092 if (bp->tx_ring) { 1150 if (bp->tx_ring) {
1093 pci_free_consistent(bp->pdev, DMA_TABLE_BYTES, 1151 if (bp->flags & B44_FLAG_TX_RING_HACK) {
1094 bp->tx_ring, bp->tx_ring_dma); 1152 dma_unmap_single(&bp->pdev->dev, bp->tx_ring_dma,
1153 DMA_TABLE_BYTES,
1154 DMA_TO_DEVICE);
1155 kfree(bp->tx_ring);
1156 } else
1157 pci_free_consistent(bp->pdev, DMA_TABLE_BYTES,
1158 bp->tx_ring, bp->tx_ring_dma);
1095 bp->tx_ring = NULL; 1159 bp->tx_ring = NULL;
1160 bp->flags &= ~B44_FLAG_TX_RING_HACK;
1096 } 1161 }
1097} 1162}
1098 1163
@@ -1118,12 +1183,56 @@ static int b44_alloc_consistent(struct b44 *bp)
1118 1183
1119 size = DMA_TABLE_BYTES; 1184 size = DMA_TABLE_BYTES;
1120 bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma); 1185 bp->rx_ring = pci_alloc_consistent(bp->pdev, size, &bp->rx_ring_dma);
1121 if (!bp->rx_ring) 1186 if (!bp->rx_ring) {
1122 goto out_err; 1187 /* Allocation may have failed due to pci_alloc_consistent
1188 insisting on use of GFP_DMA, which is more restrictive
1189 than necessary... */
1190 struct dma_desc *rx_ring;
1191 dma_addr_t rx_ring_dma;
1192
1193 if (!(rx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
1194 goto out_err;
1195
1196 memset(rx_ring, 0, size);
1197 rx_ring_dma = dma_map_single(&bp->pdev->dev, rx_ring,
1198 DMA_TABLE_BYTES,
1199 DMA_BIDIRECTIONAL);
1200
1201 if (rx_ring_dma + size > B44_DMA_MASK) {
1202 kfree(rx_ring);
1203 goto out_err;
1204 }
1205
1206 bp->rx_ring = rx_ring;
1207 bp->rx_ring_dma = rx_ring_dma;
1208 bp->flags |= B44_FLAG_RX_RING_HACK;
1209 }
1123 1210
1124 bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma); 1211 bp->tx_ring = pci_alloc_consistent(bp->pdev, size, &bp->tx_ring_dma);
1125 if (!bp->tx_ring) 1212 if (!bp->tx_ring) {
1126 goto out_err; 1213 /* Allocation may have failed due to pci_alloc_consistent
1214 insisting on use of GFP_DMA, which is more restrictive
1215 than necessary... */
1216 struct dma_desc *tx_ring;
1217 dma_addr_t tx_ring_dma;
1218
1219 if (!(tx_ring = (struct dma_desc *)kmalloc(size, GFP_KERNEL)))
1220 goto out_err;
1221
1222 memset(tx_ring, 0, size);
1223 tx_ring_dma = dma_map_single(&bp->pdev->dev, tx_ring,
1224 DMA_TABLE_BYTES,
1225 DMA_TO_DEVICE);
1226
1227 if (tx_ring_dma + size > B44_DMA_MASK) {
1228 kfree(tx_ring);
1229 goto out_err;
1230 }
1231
1232 bp->tx_ring = tx_ring;
1233 bp->tx_ring_dma = tx_ring_dma;
1234 bp->flags |= B44_FLAG_TX_RING_HACK;
1235 }
1127 1236
1128 return 0; 1237 return 0;
1129 1238
@@ -1507,14 +1616,14 @@ static int b44_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
1507 1616
1508 cmd->advertising = 0; 1617 cmd->advertising = 0;
1509 if (bp->flags & B44_FLAG_ADV_10HALF) 1618 if (bp->flags & B44_FLAG_ADV_10HALF)
1510 cmd->advertising |= ADVERTISE_10HALF; 1619 cmd->advertising |= ADVERTISED_10baseT_Half;
1511 if (bp->flags & B44_FLAG_ADV_10FULL) 1620 if (bp->flags & B44_FLAG_ADV_10FULL)
1512 cmd->advertising |= ADVERTISE_10FULL; 1621 cmd->advertising |= ADVERTISED_10baseT_Full;
1513 if (bp->flags & B44_FLAG_ADV_100HALF) 1622 if (bp->flags & B44_FLAG_ADV_100HALF)
1514 cmd->advertising |= ADVERTISE_100HALF; 1623 cmd->advertising |= ADVERTISED_100baseT_Half;
1515 if (bp->flags & B44_FLAG_ADV_100FULL) 1624 if (bp->flags & B44_FLAG_ADV_100FULL)
1516 cmd->advertising |= ADVERTISE_100FULL; 1625 cmd->advertising |= ADVERTISED_100baseT_Full;
1517 cmd->advertising |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; 1626 cmd->advertising |= ADVERTISED_Pause | ADVERTISED_Asym_Pause;
1518 cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ? 1627 cmd->speed = (bp->flags & B44_FLAG_100_BASE_T) ?
1519 SPEED_100 : SPEED_10; 1628 SPEED_100 : SPEED_10;
1520 cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ? 1629 cmd->duplex = (bp->flags & B44_FLAG_FULL_DUPLEX) ?
@@ -1676,6 +1785,7 @@ static struct ethtool_ops b44_ethtool_ops = {
1676 .set_pauseparam = b44_set_pauseparam, 1785 .set_pauseparam = b44_set_pauseparam,
1677 .get_msglevel = b44_get_msglevel, 1786 .get_msglevel = b44_get_msglevel,
1678 .set_msglevel = b44_set_msglevel, 1787 .set_msglevel = b44_set_msglevel,
1788 .get_perm_addr = ethtool_op_get_perm_addr,
1679}; 1789};
1680 1790
1681static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 1791static int b44_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -1718,6 +1828,7 @@ static int __devinit b44_get_invariants(struct b44 *bp)
1718 bp->dev->dev_addr[3] = eeprom[80]; 1828 bp->dev->dev_addr[3] = eeprom[80];
1719 bp->dev->dev_addr[4] = eeprom[83]; 1829 bp->dev->dev_addr[4] = eeprom[83];
1720 bp->dev->dev_addr[5] = eeprom[82]; 1830 bp->dev->dev_addr[5] = eeprom[82];
1831 memcpy(bp->dev->perm_addr, bp->dev->dev_addr, bp->dev->addr_len);
1721 1832
1722 bp->phy_addr = eeprom[90] & 0x1f; 1833 bp->phy_addr = eeprom[90] & 0x1f;
1723 1834
@@ -1930,6 +2041,8 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
1930 b44_free_rings(bp); 2041 b44_free_rings(bp);
1931 2042
1932 spin_unlock_irq(&bp->lock); 2043 spin_unlock_irq(&bp->lock);
2044
2045 free_irq(dev->irq, dev);
1933 pci_disable_device(pdev); 2046 pci_disable_device(pdev);
1934 return 0; 2047 return 0;
1935} 2048}
@@ -1946,6 +2059,9 @@ static int b44_resume(struct pci_dev *pdev)
1946 if (!netif_running(dev)) 2059 if (!netif_running(dev))
1947 return 0; 2060 return 0;
1948 2061
2062 if (request_irq(dev->irq, b44_interrupt, SA_SHIRQ, dev->name, dev))
2063 printk(KERN_ERR PFX "%s: request_irq failed\n", dev->name);
2064
1949 spin_lock_irq(&bp->lock); 2065 spin_lock_irq(&bp->lock);
1950 2066
1951 b44_init_rings(bp); 2067 b44_init_rings(bp);
@@ -1971,6 +2087,12 @@ static struct pci_driver b44_driver = {
1971 2087
1972static int __init b44_init(void) 2088static int __init b44_init(void)
1973{ 2089{
2090 unsigned int dma_desc_align_size = dma_get_cache_alignment();
2091
2092 /* Setup paramaters for syncing RX/TX DMA descriptors */
2093 dma_desc_align_mask = ~(dma_desc_align_size - 1);
2094 dma_desc_sync_size = max(dma_desc_align_size, sizeof(struct dma_desc));
2095
1974 return pci_module_init(&b44_driver); 2096 return pci_module_init(&b44_driver);
1975} 2097}
1976 2098