diff options
-rw-r--r-- | drivers/net/tulip/interrupt.c | 84 | ||||
-rw-r--r-- | drivers/net/tulip/tulip.h | 32 |
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 | ||