diff options
author | Don Fry <brazilnut@us.ibm.com> | 2006-09-13 13:16:38 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-13 13:23:52 -0400 |
commit | 3904c324148930bad5d9b97fdf66c63e7682b546 (patch) | |
tree | 92241080690303c39bd1f254906d71a6c214abd5 /drivers/net | |
parent | 9691edd26cfae0484367a6b8e3d46f3a5179e663 (diff) |
[PATCH] pcnet32: break receive routine into two pieces.
Breaking the receive frame processing into two routines for greater clarity.
Tested ia32 and ppc64.
Signed-off-by: Don Fry <brazilnut@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/pcnet32.c | 302 |
1 files changed, 141 insertions, 161 deletions
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 16b9538370cc..bf72aa80ccb6 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c | |||
@@ -1124,161 +1124,140 @@ static int pcnet32_suspend(struct net_device *dev, unsigned long *flags, | |||
1124 | return 1; | 1124 | return 1; |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | /* | ||
1128 | * process one receive descriptor entry | ||
1129 | */ | ||
1130 | |||
1131 | static void pcnet32_rx_entry(struct net_device *dev, | ||
1132 | struct pcnet32_private *lp, | ||
1133 | struct pcnet32_rx_head *rxp, | ||
1134 | int entry) | ||
1135 | { | ||
1136 | int status = (short)le16_to_cpu(rxp->status) >> 8; | ||
1137 | int rx_in_place = 0; | ||
1138 | struct sk_buff *skb; | ||
1139 | short pkt_len; | ||
1140 | |||
1141 | if (status != 0x03) { /* There was an error. */ | ||
1142 | /* | ||
1143 | * There is a tricky error noted by John Murphy, | ||
1144 | * <murf@perftech.com> to Russ Nelson: Even with full-sized | ||
1145 | * buffers it's possible for a jabber packet to use two | ||
1146 | * buffers, with only the last correctly noting the error. | ||
1147 | */ | ||
1148 | if (status & 0x01) /* Only count a general error at the */ | ||
1149 | lp->stats.rx_errors++; /* end of a packet. */ | ||
1150 | if (status & 0x20) | ||
1151 | lp->stats.rx_frame_errors++; | ||
1152 | if (status & 0x10) | ||
1153 | lp->stats.rx_over_errors++; | ||
1154 | if (status & 0x08) | ||
1155 | lp->stats.rx_crc_errors++; | ||
1156 | if (status & 0x04) | ||
1157 | lp->stats.rx_fifo_errors++; | ||
1158 | return; | ||
1159 | } | ||
1160 | |||
1161 | pkt_len = (le32_to_cpu(rxp->msg_length) & 0xfff) - 4; | ||
1162 | |||
1163 | /* Discard oversize frames. */ | ||
1164 | if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { | ||
1165 | if (netif_msg_drv(lp)) | ||
1166 | printk(KERN_ERR "%s: Impossible packet size %d!\n", | ||
1167 | dev->name, pkt_len); | ||
1168 | lp->stats.rx_errors++; | ||
1169 | return; | ||
1170 | } | ||
1171 | if (pkt_len < 60) { | ||
1172 | if (netif_msg_rx_err(lp)) | ||
1173 | printk(KERN_ERR "%s: Runt packet!\n", dev->name); | ||
1174 | lp->stats.rx_errors++; | ||
1175 | return; | ||
1176 | } | ||
1177 | |||
1178 | if (pkt_len > rx_copybreak) { | ||
1179 | struct sk_buff *newskb; | ||
1180 | |||
1181 | if ((newskb = dev_alloc_skb(PKT_BUF_SZ))) { | ||
1182 | skb_reserve(newskb, 2); | ||
1183 | skb = lp->rx_skbuff[entry]; | ||
1184 | pci_unmap_single(lp->pci_dev, | ||
1185 | lp->rx_dma_addr[entry], | ||
1186 | PKT_BUF_SZ - 2, | ||
1187 | PCI_DMA_FROMDEVICE); | ||
1188 | skb_put(skb, pkt_len); | ||
1189 | lp->rx_skbuff[entry] = newskb; | ||
1190 | newskb->dev = dev; | ||
1191 | lp->rx_dma_addr[entry] = | ||
1192 | pci_map_single(lp->pci_dev, | ||
1193 | newskb->data, | ||
1194 | PKT_BUF_SZ - 2, | ||
1195 | PCI_DMA_FROMDEVICE); | ||
1196 | rxp->base = le32_to_cpu(lp->rx_dma_addr[entry]); | ||
1197 | rx_in_place = 1; | ||
1198 | } else | ||
1199 | skb = NULL; | ||
1200 | } else { | ||
1201 | skb = dev_alloc_skb(pkt_len + 2); | ||
1202 | } | ||
1203 | |||
1204 | if (skb == NULL) { | ||
1205 | if (netif_msg_drv(lp)) | ||
1206 | printk(KERN_ERR | ||
1207 | "%s: Memory squeeze, dropping packet.\n", | ||
1208 | dev->name); | ||
1209 | lp->stats.rx_dropped++; | ||
1210 | return; | ||
1211 | } | ||
1212 | skb->dev = dev; | ||
1213 | if (!rx_in_place) { | ||
1214 | skb_reserve(skb, 2); /* 16 byte align */ | ||
1215 | skb_put(skb, pkt_len); /* Make room */ | ||
1216 | pci_dma_sync_single_for_cpu(lp->pci_dev, | ||
1217 | lp->rx_dma_addr[entry], | ||
1218 | PKT_BUF_SZ - 2, | ||
1219 | PCI_DMA_FROMDEVICE); | ||
1220 | eth_copy_and_sum(skb, | ||
1221 | (unsigned char *)(lp->rx_skbuff[entry]->data), | ||
1222 | pkt_len, 0); | ||
1223 | pci_dma_sync_single_for_device(lp->pci_dev, | ||
1224 | lp->rx_dma_addr[entry], | ||
1225 | PKT_BUF_SZ - 2, | ||
1226 | PCI_DMA_FROMDEVICE); | ||
1227 | } | ||
1228 | lp->stats.rx_bytes += skb->len; | ||
1229 | skb->protocol = eth_type_trans(skb, dev); | ||
1230 | netif_rx(skb); | ||
1231 | dev->last_rx = jiffies; | ||
1232 | lp->stats.rx_packets++; | ||
1233 | return; | ||
1234 | } | ||
1235 | |||
1127 | 1236 | ||
1128 | static int pcnet32_rx(struct net_device *dev) | 1237 | static void pcnet32_rx(struct net_device *dev) |
1129 | { | 1238 | { |
1130 | struct pcnet32_private *lp = dev->priv; | 1239 | struct pcnet32_private *lp = dev->priv; |
1131 | int entry = lp->cur_rx & lp->rx_mod_mask; | 1240 | int entry = lp->cur_rx & lp->rx_mod_mask; |
1241 | struct pcnet32_rx_head *rxp = &lp->rx_ring[entry]; | ||
1242 | int npackets = 0; | ||
1132 | int boguscnt = lp->rx_ring_size / 2; | 1243 | int boguscnt = lp->rx_ring_size / 2; |
1133 | 1244 | ||
1134 | /* If we own the next entry, it's a new packet. Send it up. */ | 1245 | /* If we own the next entry, it's a new packet. Send it up. */ |
1135 | while ((short)le16_to_cpu(lp->rx_ring[entry].status) >= 0) { | 1246 | while (boguscnt > npackets && (short)le16_to_cpu(rxp->status) >= 0) { |
1136 | int status = (short)le16_to_cpu(lp->rx_ring[entry].status) >> 8; | 1247 | pcnet32_rx_entry(dev, lp, rxp, entry); |
1137 | 1248 | npackets += 1; | |
1138 | if (status != 0x03) { /* There was an error. */ | ||
1139 | /* | ||
1140 | * There is a tricky error noted by John Murphy, | ||
1141 | * <murf@perftech.com> to Russ Nelson: Even with full-sized | ||
1142 | * buffers it's possible for a jabber packet to use two | ||
1143 | * buffers, with only the last correctly noting the error. | ||
1144 | */ | ||
1145 | if (status & 0x01) /* Only count a general error at the */ | ||
1146 | lp->stats.rx_errors++; /* end of a packet. */ | ||
1147 | if (status & 0x20) | ||
1148 | lp->stats.rx_frame_errors++; | ||
1149 | if (status & 0x10) | ||
1150 | lp->stats.rx_over_errors++; | ||
1151 | if (status & 0x08) | ||
1152 | lp->stats.rx_crc_errors++; | ||
1153 | if (status & 0x04) | ||
1154 | lp->stats.rx_fifo_errors++; | ||
1155 | lp->rx_ring[entry].status &= le16_to_cpu(0x03ff); | ||
1156 | } else { | ||
1157 | /* Malloc up new buffer, compatible with net-2e. */ | ||
1158 | short pkt_len = | ||
1159 | (le32_to_cpu(lp->rx_ring[entry].msg_length) & 0xfff) | ||
1160 | - 4; | ||
1161 | struct sk_buff *skb; | ||
1162 | |||
1163 | /* Discard oversize frames. */ | ||
1164 | if (unlikely(pkt_len > PKT_BUF_SZ - 2)) { | ||
1165 | if (netif_msg_drv(lp)) | ||
1166 | printk(KERN_ERR | ||
1167 | "%s: Impossible packet size %d!\n", | ||
1168 | dev->name, pkt_len); | ||
1169 | lp->stats.rx_errors++; | ||
1170 | } else if (pkt_len < 60) { | ||
1171 | if (netif_msg_rx_err(lp)) | ||
1172 | printk(KERN_ERR "%s: Runt packet!\n", | ||
1173 | dev->name); | ||
1174 | lp->stats.rx_errors++; | ||
1175 | } else { | ||
1176 | int rx_in_place = 0; | ||
1177 | |||
1178 | if (pkt_len > rx_copybreak) { | ||
1179 | struct sk_buff *newskb; | ||
1180 | |||
1181 | if ((newskb = | ||
1182 | dev_alloc_skb(PKT_BUF_SZ))) { | ||
1183 | skb_reserve(newskb, 2); | ||
1184 | skb = lp->rx_skbuff[entry]; | ||
1185 | pci_unmap_single(lp->pci_dev, | ||
1186 | lp-> | ||
1187 | rx_dma_addr | ||
1188 | [entry], | ||
1189 | PKT_BUF_SZ - 2, | ||
1190 | PCI_DMA_FROMDEVICE); | ||
1191 | skb_put(skb, pkt_len); | ||
1192 | lp->rx_skbuff[entry] = newskb; | ||
1193 | newskb->dev = dev; | ||
1194 | lp->rx_dma_addr[entry] = | ||
1195 | pci_map_single(lp->pci_dev, | ||
1196 | newskb->data, | ||
1197 | PKT_BUF_SZ - | ||
1198 | 2, | ||
1199 | PCI_DMA_FROMDEVICE); | ||
1200 | lp->rx_ring[entry].base = | ||
1201 | le32_to_cpu(lp-> | ||
1202 | rx_dma_addr | ||
1203 | [entry]); | ||
1204 | rx_in_place = 1; | ||
1205 | } else | ||
1206 | skb = NULL; | ||
1207 | } else { | ||
1208 | skb = dev_alloc_skb(pkt_len + 2); | ||
1209 | } | ||
1210 | |||
1211 | if (skb == NULL) { | ||
1212 | int i; | ||
1213 | if (netif_msg_drv(lp)) | ||
1214 | printk(KERN_ERR | ||
1215 | "%s: Memory squeeze, deferring packet.\n", | ||
1216 | dev->name); | ||
1217 | for (i = 0; i < lp->rx_ring_size; i++) | ||
1218 | if ((short) | ||
1219 | le16_to_cpu(lp-> | ||
1220 | rx_ring[(entry + | ||
1221 | i) | ||
1222 | & lp-> | ||
1223 | rx_mod_mask]. | ||
1224 | status) < 0) | ||
1225 | break; | ||
1226 | |||
1227 | if (i > lp->rx_ring_size - 2) { | ||
1228 | lp->stats.rx_dropped++; | ||
1229 | lp->rx_ring[entry].status |= | ||
1230 | le16_to_cpu(0x8000); | ||
1231 | wmb(); /* Make sure adapter sees owner change */ | ||
1232 | lp->cur_rx++; | ||
1233 | } | ||
1234 | break; | ||
1235 | } | ||
1236 | skb->dev = dev; | ||
1237 | if (!rx_in_place) { | ||
1238 | skb_reserve(skb, 2); /* 16 byte align */ | ||
1239 | skb_put(skb, pkt_len); /* Make room */ | ||
1240 | pci_dma_sync_single_for_cpu(lp->pci_dev, | ||
1241 | lp-> | ||
1242 | rx_dma_addr | ||
1243 | [entry], | ||
1244 | PKT_BUF_SZ - | ||
1245 | 2, | ||
1246 | PCI_DMA_FROMDEVICE); | ||
1247 | eth_copy_and_sum(skb, | ||
1248 | (unsigned char *)(lp-> | ||
1249 | rx_skbuff | ||
1250 | [entry]-> | ||
1251 | data), | ||
1252 | pkt_len, 0); | ||
1253 | pci_dma_sync_single_for_device(lp-> | ||
1254 | pci_dev, | ||
1255 | lp-> | ||
1256 | rx_dma_addr | ||
1257 | [entry], | ||
1258 | PKT_BUF_SZ | ||
1259 | - 2, | ||
1260 | PCI_DMA_FROMDEVICE); | ||
1261 | } | ||
1262 | lp->stats.rx_bytes += skb->len; | ||
1263 | skb->protocol = eth_type_trans(skb, dev); | ||
1264 | netif_rx(skb); | ||
1265 | dev->last_rx = jiffies; | ||
1266 | lp->stats.rx_packets++; | ||
1267 | } | ||
1268 | } | ||
1269 | /* | 1249 | /* |
1270 | * The docs say that the buffer length isn't touched, but Andrew Boyd | 1250 | * The docs say that the buffer length isn't touched, but Andrew |
1271 | * of QNX reports that some revs of the 79C965 clear it. | 1251 | * Boyd of QNX reports that some revs of the 79C965 clear it. |
1272 | */ | 1252 | */ |
1273 | lp->rx_ring[entry].buf_length = le16_to_cpu(2 - PKT_BUF_SZ); | 1253 | rxp->buf_length = le16_to_cpu(2 - PKT_BUF_SZ); |
1274 | wmb(); /* Make sure owner changes after all others are visible */ | 1254 | wmb(); /* Make sure owner changes after others are visible */ |
1275 | lp->rx_ring[entry].status |= le16_to_cpu(0x8000); | 1255 | rxp->status = le16_to_cpu(0x8000); |
1276 | entry = (++lp->cur_rx) & lp->rx_mod_mask; | 1256 | entry = (++lp->cur_rx) & lp->rx_mod_mask; |
1277 | if (--boguscnt <= 0) | 1257 | rxp = &lp->rx_ring[entry]; |
1278 | break; /* don't stay in loop forever */ | ||
1279 | } | 1258 | } |
1280 | 1259 | ||
1281 | return 0; | 1260 | return; |
1282 | } | 1261 | } |
1283 | 1262 | ||
1284 | static int pcnet32_tx(struct net_device *dev, u16 csr0) | 1263 | static int pcnet32_tx(struct net_device *dev, u16 csr0) |
@@ -1298,7 +1277,7 @@ static int pcnet32_tx(struct net_device *dev, u16 csr0) | |||
1298 | lp->tx_ring[entry].base = 0; | 1277 | lp->tx_ring[entry].base = 0; |
1299 | 1278 | ||
1300 | if (status & 0x4000) { | 1279 | if (status & 0x4000) { |
1301 | /* There was an major error, log it. */ | 1280 | /* There was a major error, log it. */ |
1302 | int err_status = le32_to_cpu(lp->tx_ring[entry].misc); | 1281 | int err_status = le32_to_cpu(lp->tx_ring[entry].misc); |
1303 | lp->stats.tx_errors++; | 1282 | lp->stats.tx_errors++; |
1304 | if (netif_msg_tx_err(lp)) | 1283 | if (netif_msg_tx_err(lp)) |
@@ -1329,8 +1308,7 @@ static int pcnet32_tx(struct net_device *dev, u16 csr0) | |||
1329 | if (!lp->dxsuflo) { /* If controller doesn't recover ... */ | 1308 | if (!lp->dxsuflo) { /* If controller doesn't recover ... */ |
1330 | /* Ackk! On FIFO errors the Tx unit is turned off! */ | 1309 | /* Ackk! On FIFO errors the Tx unit is turned off! */ |
1331 | /* Remove this verbosity later! */ | 1310 | /* Remove this verbosity later! */ |
1332 | if (netif_msg_tx_err | 1311 | if (netif_msg_tx_err(lp)) |
1333 | (lp)) | ||
1334 | printk(KERN_ERR | 1312 | printk(KERN_ERR |
1335 | "%s: Tx FIFO error! CSR0=%4.4x\n", | 1313 | "%s: Tx FIFO error! CSR0=%4.4x\n", |
1336 | dev->name, csr0); | 1314 | dev->name, csr0); |
@@ -1350,16 +1328,14 @@ static int pcnet32_tx(struct net_device *dev, u16 csr0) | |||
1350 | lp->tx_dma_addr[entry], | 1328 | lp->tx_dma_addr[entry], |
1351 | lp->tx_skbuff[entry]-> | 1329 | lp->tx_skbuff[entry]-> |
1352 | len, PCI_DMA_TODEVICE); | 1330 | len, PCI_DMA_TODEVICE); |
1353 | dev_kfree_skb_irq(lp->tx_skbuff[entry]); | 1331 | dev_kfree_skb_any(lp->tx_skbuff[entry]); |
1354 | lp->tx_skbuff[entry] = NULL; | 1332 | lp->tx_skbuff[entry] = NULL; |
1355 | lp->tx_dma_addr[entry] = 0; | 1333 | lp->tx_dma_addr[entry] = 0; |
1356 | } | 1334 | } |
1357 | dirty_tx++; | 1335 | dirty_tx++; |
1358 | } | 1336 | } |
1359 | 1337 | ||
1360 | delta = | 1338 | delta = (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + lp->tx_ring_size); |
1361 | (lp->cur_tx - dirty_tx) & (lp->tx_mod_mask + | ||
1362 | lp->tx_ring_size); | ||
1363 | if (delta > lp->tx_ring_size) { | 1339 | if (delta > lp->tx_ring_size) { |
1364 | if (netif_msg_drv(lp)) | 1340 | if (netif_msg_drv(lp)) |
1365 | printk(KERN_ERR | 1341 | printk(KERN_ERR |
@@ -2535,19 +2511,20 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2535 | 2511 | ||
2536 | spin_lock(&lp->lock); | 2512 | spin_lock(&lp->lock); |
2537 | 2513 | ||
2538 | while ((csr0 = lp->a.read_csr(ioaddr, 0)) & 0x8f00 && --boguscnt >= 0) { | 2514 | csr0 = lp->a.read_csr(ioaddr, CSR0); |
2515 | while ((csr0 & 0x8f00) && --boguscnt >= 0) { | ||
2539 | if (csr0 == 0xffff) { | 2516 | if (csr0 == 0xffff) { |
2540 | break; /* PCMCIA remove happened */ | 2517 | break; /* PCMCIA remove happened */ |
2541 | } | 2518 | } |
2542 | /* Acknowledge all of the current interrupt sources ASAP. */ | 2519 | /* Acknowledge all of the current interrupt sources ASAP. */ |
2543 | lp->a.write_csr(ioaddr, 0, csr0 & ~0x004f); | 2520 | lp->a.write_csr(ioaddr, CSR0, csr0 & ~0x004f); |
2544 | 2521 | ||
2545 | must_restart = 0; | 2522 | must_restart = 0; |
2546 | 2523 | ||
2547 | if (netif_msg_intr(lp)) | 2524 | if (netif_msg_intr(lp)) |
2548 | printk(KERN_DEBUG | 2525 | printk(KERN_DEBUG |
2549 | "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", | 2526 | "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", |
2550 | dev->name, csr0, lp->a.read_csr(ioaddr, 0)); | 2527 | dev->name, csr0, lp->a.read_csr(ioaddr, CSR0)); |
2551 | 2528 | ||
2552 | if (csr0 & 0x0400) /* Rx interrupt */ | 2529 | if (csr0 & 0x0400) /* Rx interrupt */ |
2553 | pcnet32_rx(dev); | 2530 | pcnet32_rx(dev); |
@@ -2561,14 +2538,16 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2561 | lp->stats.tx_errors++; /* Tx babble. */ | 2538 | lp->stats.tx_errors++; /* Tx babble. */ |
2562 | if (csr0 & 0x1000) { | 2539 | if (csr0 & 0x1000) { |
2563 | /* | 2540 | /* |
2564 | * this happens when our receive ring is full. This shouldn't | 2541 | * This happens when our receive ring is full. This |
2565 | * be a problem as we will see normal rx interrupts for the frames | 2542 | * shouldn't be a problem as we will see normal rx |
2566 | * in the receive ring. But there are some PCI chipsets (I can | 2543 | * interrupts for the frames in the receive ring. But |
2567 | * reproduce this on SP3G with Intel saturn chipset) which have | 2544 | * there are some PCI chipsets (I can reproduce this |
2568 | * sometimes problems and will fill up the receive ring with | 2545 | * on SP3G with Intel saturn chipset) which have |
2569 | * error descriptors. In this situation we don't get a rx | 2546 | * sometimes problems and will fill up the receive |
2570 | * interrupt, but a missed frame interrupt sooner or later. | 2547 | * ring with error descriptors. In this situation we |
2571 | * So we try to clean up our receive ring here. | 2548 | * don't get a rx interrupt, but a missed frame |
2549 | * interrupt sooner or later. So we try to clean up | ||
2550 | * our receive ring here. | ||
2572 | */ | 2551 | */ |
2573 | pcnet32_rx(dev); | 2552 | pcnet32_rx(dev); |
2574 | lp->stats.rx_errors++; /* Missed a Rx frame. */ | 2553 | lp->stats.rx_errors++; /* Missed a Rx frame. */ |
@@ -2588,6 +2567,7 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2588 | pcnet32_restart(dev, CSR0_START); | 2567 | pcnet32_restart(dev, CSR0_START); |
2589 | netif_wake_queue(dev); | 2568 | netif_wake_queue(dev); |
2590 | } | 2569 | } |
2570 | csr0 = lp->a.read_csr(ioaddr, CSR0); | ||
2591 | } | 2571 | } |
2592 | 2572 | ||
2593 | /* Set interrupt enable. */ | 2573 | /* Set interrupt enable. */ |