aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/tulip/interrupt.c84
-rw-r--r--drivers/net/tulip/tulip.h32
2 files changed, 86 insertions, 30 deletions
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index 9f946d421088..c8d220cf2cce 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -140,6 +140,7 @@ int tulip_poll(struct napi_struct *napi, int budget)
140 /* If we own the next entry, it is a new packet. Send it up. */ 140 /* If we own the next entry, it is a new packet. Send it up. */
141 while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { 141 while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
142 s32 status = le32_to_cpu(tp->rx_ring[entry].status); 142 s32 status = le32_to_cpu(tp->rx_ring[entry].status);
143 short pkt_len;
143 144
144 if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx) 145 if (tp->dirty_rx + RX_RING_SIZE == tp->cur_rx)
145 break; 146 break;
@@ -151,8 +152,28 @@ int tulip_poll(struct napi_struct *napi, int budget)
151 if (++work_done >= budget) 152 if (++work_done >= budget)
152 goto not_done; 153 goto not_done;
153 154
154 if ((status & 0x38008300) != 0x0300) { 155 /*
155 if ((status & 0x38000300) != 0x0300) { 156 * Omit the four octet CRC from the length.
157 * (May not be considered valid until we have
158 * checked status for RxLengthOver2047 bits)
159 */
160 pkt_len = ((status >> 16) & 0x7ff) - 4;
161
162 /*
163 * Maximum pkt_len is 1518 (1514 + vlan header)
164 * Anything higher than this is always invalid
165 * regardless of RxLengthOver2047 bits
166 */
167
168 if ((status & (RxLengthOver2047 |
169 RxDescCRCError |
170 RxDescCollisionSeen |
171 RxDescRunt |
172 RxDescDescErr |
173 RxWholePkt)) != RxWholePkt
174 || pkt_len > 1518) {
175 if ((status & (RxLengthOver2047 |
176 RxWholePkt)) != RxWholePkt) {
156 /* Ingore earlier buffers. */ 177 /* Ingore earlier buffers. */
157 if ((status & 0xffff) != 0x7fff) { 178 if ((status & 0xffff) != 0x7fff) {
158 if (tulip_debug > 1) 179 if (tulip_debug > 1)
@@ -161,30 +182,23 @@ int tulip_poll(struct napi_struct *napi, int budget)
161 dev->name, status); 182 dev->name, status);
162 tp->stats.rx_length_errors++; 183 tp->stats.rx_length_errors++;
163 } 184 }
164 } else if (status & RxDescFatalErr) { 185 } else {
165 /* There was a fatal error. */ 186 /* There was a fatal error. */
166 if (tulip_debug > 2) 187 if (tulip_debug > 2)
167 printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", 188 printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
168 dev->name, status); 189 dev->name, status);
169 tp->stats.rx_errors++; /* end of a packet.*/ 190 tp->stats.rx_errors++; /* end of a packet.*/
170 if (status & 0x0890) tp->stats.rx_length_errors++; 191 if (pkt_len > 1518 ||
192 (status & RxDescRunt))
193 tp->stats.rx_length_errors++;
194
171 if (status & 0x0004) tp->stats.rx_frame_errors++; 195 if (status & 0x0004) tp->stats.rx_frame_errors++;
172 if (status & 0x0002) tp->stats.rx_crc_errors++; 196 if (status & 0x0002) tp->stats.rx_crc_errors++;
173 if (status & 0x0001) tp->stats.rx_fifo_errors++; 197 if (status & 0x0001) tp->stats.rx_fifo_errors++;
174 } 198 }
175 } else { 199 } else {
176 /* Omit the four octet CRC from the length. */
177 short pkt_len = ((status >> 16) & 0x7ff) - 4;
178 struct sk_buff *skb; 200 struct sk_buff *skb;
179 201
180#ifndef final_version
181 if (pkt_len > 1518) {
182 printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
183 dev->name, pkt_len, pkt_len);
184 pkt_len = 1518;
185 tp->stats.rx_length_errors++;
186 }
187#endif
188 /* Check if the packet is long enough to accept without copying 202 /* Check if the packet is long enough to accept without copying
189 to a minimally-sized skbuff. */ 203 to a minimally-sized skbuff. */
190 if (pkt_len < tulip_rx_copybreak 204 if (pkt_len < tulip_rx_copybreak
@@ -356,14 +370,35 @@ static int tulip_rx(struct net_device *dev)
356 /* If we own the next entry, it is a new packet. Send it up. */ 370 /* If we own the next entry, it is a new packet. Send it up. */
357 while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { 371 while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
358 s32 status = le32_to_cpu(tp->rx_ring[entry].status); 372 s32 status = le32_to_cpu(tp->rx_ring[entry].status);
373 short pkt_len;
359 374
360 if (tulip_debug > 5) 375 if (tulip_debug > 5)
361 printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", 376 printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
362 dev->name, entry, status); 377 dev->name, entry, status);
363 if (--rx_work_limit < 0) 378 if (--rx_work_limit < 0)
364 break; 379 break;
365 if ((status & 0x38008300) != 0x0300) { 380
366 if ((status & 0x38000300) != 0x0300) { 381 /*
382 Omit the four octet CRC from the length.
383 (May not be considered valid until we have
384 checked status for RxLengthOver2047 bits)
385 */
386 pkt_len = ((status >> 16) & 0x7ff) - 4;
387 /*
388 Maximum pkt_len is 1518 (1514 + vlan header)
389 Anything higher than this is always invalid
390 regardless of RxLengthOver2047 bits
391 */
392
393 if ((status & (RxLengthOver2047 |
394 RxDescCRCError |
395 RxDescCollisionSeen |
396 RxDescRunt |
397 RxDescDescErr |
398 RxWholePkt)) != RxWholePkt
399 || pkt_len > 1518) {
400 if ((status & (RxLengthOver2047 |
401 RxWholePkt)) != RxWholePkt) {
367 /* Ingore earlier buffers. */ 402 /* Ingore earlier buffers. */
368 if ((status & 0xffff) != 0x7fff) { 403 if ((status & 0xffff) != 0x7fff) {
369 if (tulip_debug > 1) 404 if (tulip_debug > 1)
@@ -372,31 +407,22 @@ static int tulip_rx(struct net_device *dev)
372 dev->name, status); 407 dev->name, status);
373 tp->stats.rx_length_errors++; 408 tp->stats.rx_length_errors++;
374 } 409 }
375 } else if (status & RxDescFatalErr) { 410 } else {
376 /* There was a fatal error. */ 411 /* There was a fatal error. */
377 if (tulip_debug > 2) 412 if (tulip_debug > 2)
378 printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", 413 printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
379 dev->name, status); 414 dev->name, status);
380 tp->stats.rx_errors++; /* end of a packet.*/ 415 tp->stats.rx_errors++; /* end of a packet.*/
381 if (status & 0x0890) tp->stats.rx_length_errors++; 416 if (pkt_len > 1518 ||
417 (status & RxDescRunt))
418 tp->stats.rx_length_errors++;
382 if (status & 0x0004) tp->stats.rx_frame_errors++; 419 if (status & 0x0004) tp->stats.rx_frame_errors++;
383 if (status & 0x0002) tp->stats.rx_crc_errors++; 420 if (status & 0x0002) tp->stats.rx_crc_errors++;
384 if (status & 0x0001) tp->stats.rx_fifo_errors++; 421 if (status & 0x0001) tp->stats.rx_fifo_errors++;
385 } 422 }
386 } else { 423 } else {
387 /* Omit the four octet CRC from the length. */
388 short pkt_len = ((status >> 16) & 0x7ff) - 4;
389 struct sk_buff *skb; 424 struct sk_buff *skb;
390 425
391#ifndef final_version
392 if (pkt_len > 1518) {
393 printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
394 dev->name, pkt_len, pkt_len);
395 pkt_len = 1518;
396 tp->stats.rx_length_errors++;
397 }
398#endif
399
400 /* Check if the packet is long enough to accept without copying 426 /* Check if the packet is long enough to accept without copying
401 to a minimally-sized skbuff. */ 427 to a minimally-sized skbuff. */
402 if (pkt_len < tulip_rx_copybreak 428 if (pkt_len < tulip_rx_copybreak
diff --git a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
index 19abbc36b60a..0afa2d4f9472 100644
--- a/drivers/net/tulip/tulip.h
+++ b/drivers/net/tulip/tulip.h
@@ -201,8 +201,38 @@ enum desc_status_bits {
201 DescStartPkt = 0x20000000, 201 DescStartPkt = 0x20000000,
202 DescEndRing = 0x02000000, 202 DescEndRing = 0x02000000,
203 DescUseLink = 0x01000000, 203 DescUseLink = 0x01000000,
204 RxDescFatalErr = 0x008000, 204
205 /*
206 * Error summary flag is logical or of 'CRC Error', 'Collision Seen',
207 * 'Frame Too Long', 'Runt' and 'Descriptor Error' flags generated
208 * within tulip chip.
209 */
210 RxDescErrorSummary = 0x8000,
211 RxDescCRCError = 0x0002,
212 RxDescCollisionSeen = 0x0040,
213
214 /*
215 * 'Frame Too Long' flag is set if packet length including CRC exceeds
216 * 1518. However, a full sized VLAN tagged frame is 1522 bytes
217 * including CRC.
218 *
219 * The tulip chip does not block oversized frames, and if this flag is
220 * set on a receive descriptor it does not indicate the frame has been
221 * truncated. The receive descriptor also includes the actual length.
222 * Therefore we can safety ignore this flag and check the length
223 * ourselves.
224 */
225 RxDescFrameTooLong = 0x0080,
226 RxDescRunt = 0x0800,
227 RxDescDescErr = 0x4000,
205 RxWholePkt = 0x00000300, 228 RxWholePkt = 0x00000300,
229 /*
230 * Top three bits of 14 bit frame length (status bits 27-29) should
231 * never be set as that would make frame over 2047 bytes. The Receive
232 * Watchdog flag (bit 4) may indicate the length is over 2048 and the
233 * length field is invalid.
234 */
235 RxLengthOver2047 = 0x38000010
206}; 236};
207 237
208 238