aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tulip/interrupt.c
diff options
context:
space:
mode:
authorTomasz Lemiech <szpajder@staszic.waw.pl>2009-03-13 18:43:38 -0400
committerDavid S. Miller <davem@davemloft.net>2009-03-13 18:43:38 -0400
commit1f8ae0a21d83f43006d7f6d2862e921dbf2eeddd (patch)
tree36f744e3dda465f67d4bf5e2faab45ab14b791f4 /drivers/net/tulip/interrupt.c
parenta390d1f379cf821248b735f43d2e1147ebb8241d (diff)
tulip: Fix for MTU problems with 802.1q tagged frames
The original patch was submitted last year but wasn't discussed or applied because of missing maintainer's CCs. I only fixed some formatting errors, but as I saw tulip is very badly formatted and needs further work. Original description: This patch fixes MTU problem, which occurs when using 802.1q VLANs. We should allow receiving frames of up to 1518 bytes in length, instead of 1514. Based on patch written by Ben McKeegan for 2.4.x kernels. It is archived at http://www.candelatech.com/~greear/vlan/howto.html#tulip I've adjusted a few things to make it apply on 2.6.x kernels. Tested on D-Link DFE-570TX quad-fastethernet card. Signed-off-by: Tomasz Lemiech <szpajder@staszic.waw.pl> Signed-off-by: Ivan Vecera <ivecera@redhat.com> Signed-off-by: Ben McKeegan <ben@netservers.co.uk> Acked-by: Grant Grundler <grundler@parisc-linux.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tulip/interrupt.c')
-rw-r--r--drivers/net/tulip/interrupt.c84
1 files changed, 55 insertions, 29 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