Changeset e1e379b in freewrt
- Timestamp:
- Nov 16, 2006, 12:29:12 AM (19 years ago)
- Children:
- 6615be8
- Parents:
- 7a23d2e
- Location:
- target/linux/rb-2.4/patches
- Files:
-
- 4 added
- 2 deleted
- 2 moved
-
002-rb.patch (added)
-
002-rb500.patch (deleted)
-
004-net.patch (moved) (moved from target/linux/rb-2.4/patches/003-korina.patch ) (5 diffs)
-
004-via-rhine.patch (deleted)
-
005-cfmips.patch (moved) (moved from target/linux/rb-2.4/patches/005-cf-mips.patch ) (13 diffs)
-
007-yaffs2.patch (added)
-
008-pcmcia.patch (added)
-
009-usbserial.patch (added)
Legend:
- Unmodified
- Added
- Removed
-
target/linux/rb-2.4/patches/004-net.patch
r7a23d2e re1e379b 1 diff -NaurB linux-2.4.33.3/drivers/net/admtek.c linux-2.4.33.3.patched/drivers/net/admtek.c 2 --- linux-2.4.33.3/drivers/net/admtek.c 1970-01-01 01:00:00.000000000 +0100 3 +++ linux-2.4.33.3.patched/drivers/net/admtek.c 2006-11-15 10:34:04.000000000 +0100 4 @@ -0,0 +1,812 @@ 5 +#include <asm/unaligned.h> 6 +#include <linux/module.h> 7 +#include <linux/init.h> 8 +#include <linux/bitops.h> 9 +#include <linux/pci.h> 10 +#include <linux/netdevice.h> 11 +#include <linux/etherdevice.h> 12 +#include <linux/ethtool.h> 13 + 14 + 15 +#define ADMTEK_REG_BASE 0x12000000 16 + 17 +// register offsets 18 +#define SWReset_REG 0x000C 19 +#define PHY_st_REG 0x0014 20 +#define Port_st_REG 0x0018 21 +#define SW_conf_REG 0x0020 22 +#define CPUp_conf_REG 0x0024 23 +#define Port_conf0_REG 0x0028 24 +#define Port_conf1_REG 0x002C 25 +#define Port_conf2_REG 0x0030 26 +#define VLAN_G1_REG 0x0040 27 +#define VLAN_G2_REG 0x0044 28 +#define Send_trig_REG 0x0048 29 +#define MAC_wt0_REG 0x0058 30 +#define MAC_wt1_REG 0x005C 31 +#define PHY_cntl0_REG 0x0068 32 +#define PHY_cntl1_REG 0x006C 33 +#define PHY_cntl2_REG 0x007C 34 +#define PHY_cntl3_REG 0x0080 35 +#define SW_Int_st_REG 0x00B0 36 +#define SW_Int_mask_REG 0x00B4 37 +#define Send_HBaddr_REG 0x00D0 38 +#define Send_LBaddr_REG 0x00D4 39 +#define Recv_HBaddr_REG 0x00D8 40 +#define Recv_LBaddr_REG 0x00DC 41 +#define Send_HWaddr_REG 0x00E0 42 +#define Send_LWaddr_REG 0x00E4 43 +#define Recv_HWaddr_REG 0x00E8 44 +#define Recv_LWaddr_REG 0x00EC 45 + 46 +#define ADMTEK_REG(reg) \ 47 + (*((volatile unsigned long *)(KSEG1ADDR(ADMTEK_REG_BASE + (reg))))) 48 + 49 + 50 +/* CPUp_conf_REG */ 51 +#define SW_CPU_PORT_DISABLE 0x00000001 52 +#define SW_PADING_CRC 0x00000002 53 + 54 +#define SW_DIS_UN_SHIFT 9 55 +#define SW_DIS_UN_MASK (0x3F << SW_DIS_UN_SHIFT) 56 +#define SW_DIS_MC_SHIFT 16 57 +#define SW_DIS_MC_MASK (0x3F << SW_DIS_MC_SHIFT) 58 +#define SW_DIS_BC_SHIFT 24 59 +#define SW_DIS_BC_MASK (0x3F << SW_DIS_BC_SHIFT) 60 + 61 +/* Port_conf0_REG */ 62 +#define SW_DISABLE_PORT_MASK 0x0000003F 63 +#define SW_EN_MC_MASK 0x00003F00 64 +#define SW_EN_MC_SHIFT 8 65 +#define SW_EN_BP_MASK 0x003F0000 66 +#define SW_EN_BP_SHIFT 16 67 +#define SW_EN_FC_MASK 0x3F000000 68 +#define SW_EN_FC_SHIFT 24 69 + 70 +/* MAC_wt0_REG */ 71 +#define SW_MAC_WRITE 0x00000001 72 +#define SW_MAC_WRITE_DONE 0x00000002 73 +#define SW_MAC_VLANID_SHIFT 3 74 +#define SW_MAC_VLANID_MASK 0x00000038 75 +#define SW_MAC_VLANID_EN 0x00000040 76 + 77 +/* PHY_cntl0_REG */ 78 +#define SW_PHY_WRITE 0x00002000 79 +#define SW_PHY_READ 0x00004000 80 + 81 +/* PHY_cntl2_REG */ 82 +#define SW_PHY_AN_MASK 0x0000001F 83 +#define SW_PHY_NORMAL_MASK 0x01F00000 84 + 85 +/* SW_Int_st_REG & SW_Int_mask_REG */ 86 +#define TX_H_INT 0x0000001 87 +#define TX_L_INT 0x0000002 88 +#define RX_H_INT 0x0000004 89 +#define RX_L_INT 0x0000008 90 +#define RX_H_DESC_FULL_INT 0x0000010 91 +#define RX_L_DESC_FULL_INT 0x0000020 92 +#define PORT_STATUS_CHANGE_INT 0x0040000 93 +#define RX_DESC_ERR_INT 0x0400000 94 +#define TX_DESC_ERR_INT 0x0800000 95 +#define SWITCH_INT_MASK 0x1FDEFFF 96 + 97 + 98 + 99 +// descriptor bits 100 +#define DESC_OWN 0x80000000 101 +#define DESC_RING_END 0x10000000 102 +#define DESC_ADDR_MASK 0x00ffffff 103 +#define DESC_LEN_MASK 0x07ff0000 104 +#define DESC_LEN_SHIFT 16 105 + 106 +// rx descr status 107 +#define DESC_RX_PORT_MASK 0x00007000 108 +#define DESC_RX_PORT_SHIFT 12 109 +#define DESC_RX_FRAME_MASK 0x00000030 110 +#define DESC_RX_FRAME_UC 0x00000000 111 +#define DESC_RX_FRAME_MC 0x00000010 112 +#define DESC_RX_FRAME_BC 0x00000020 113 +#define DESC_RX_CSUM_ERR 0x00000008 114 +#define DESC_RX_VLAN_TAG 0x00000004 115 + 116 +// tx descr ctrl 117 +#define DESC_TX_CSUM 0x80000000 118 +#define DESC_TX_PORT_MASK 0x00003F00 119 +#define DESC_TX_VLAN_MASK 0x0000003F 120 + 121 + 122 +#define RX_BUF_SIZE 1550 123 + 124 +#define SW_IRQ 9 125 + 126 +#define VLAN_PORT_MASK 0x7f 127 + 128 + 129 +struct admtek_rx_desc { 130 + unsigned long buf1; 131 + unsigned long buf2; 132 + unsigned long len; 133 + unsigned long status; 134 +}; 135 + 136 +struct admtek_tx_desc { 137 + unsigned long buf1; 138 + unsigned long buf2; 139 + unsigned long len; 140 + unsigned long ctrl; 141 +}; 142 + 143 +#define RX_DESC_COUNT 128 144 +#define TX_DESC_PER_PORT 32 145 +#define PORT_COUNT 5 146 +#define TX_DESC_COUNT ((TX_DESC_PER_PORT + 1) * PORT_COUNT) 147 + 148 +struct admtek_dev_priv { 149 + struct net_device *dev; 150 + struct net_device_stats stats; 151 + 152 + unsigned port; 153 + 154 + int in_transmit; 155 +}; 156 + 157 + 158 +struct admtek_switch { 159 + struct admtek_rx_desc *rx_descs; 160 + struct admtek_tx_desc *tx_descs; 161 + dma_addr_t rx_descs_dma; 162 + dma_addr_t tx_descs_dma; 163 + 164 + struct sk_buff **rx_skbs; 165 + struct sk_buff **tx_skbs; 166 + 167 + unsigned cur_rx, dirty_rx; 168 + unsigned cur_tx, dirty_tx; 169 + 170 + struct net_device *devs[PORT_COUNT]; 171 + 172 + spinlock_t lock; 173 + 174 + struct tasklet_struct rx_tasklet; 175 + struct tasklet_struct tx_tasklet; 176 + 177 + unsigned link_status; 178 + 179 + unsigned irq; 180 +}; 181 + 182 +static struct admtek_switch sw; 183 + 184 +extern unsigned char mips_mac_address[6]; 185 + 186 + 187 +static void admtek_init_engine(void) { 188 + unsigned i; 189 + 190 + // initialize engine 191 + ADMTEK_REG(CPUp_conf_REG) = 192 + SW_CPU_PORT_DISABLE | SW_PADING_CRC | SW_DIS_UN_MASK; 193 + ADMTEK_REG(Port_conf0_REG) = 194 + SW_EN_BP_MASK | SW_EN_MC_MASK | SW_DISABLE_PORT_MASK; 195 + for (i = 0; i < 500000; i++); 196 + ADMTEK_REG(PHY_cntl2_REG) |= SW_PHY_AN_MASK | SW_PHY_NORMAL_MASK; 197 + ADMTEK_REG(PHY_cntl3_REG) |= 0x400; 198 + ADMTEK_REG(SW_Int_mask_REG) = SWITCH_INT_MASK; 199 + ADMTEK_REG(SW_Int_st_REG) = SWITCH_INT_MASK; 200 + ADMTEK_REG(Send_LBaddr_REG) = sw.tx_descs_dma; 201 + ADMTEK_REG(Send_HBaddr_REG) = sw.tx_descs_dma; 202 + ADMTEK_REG(Recv_LBaddr_REG) = sw.rx_descs_dma; 203 + ADMTEK_REG(Recv_HBaddr_REG) = sw.rx_descs_dma; 204 + ADMTEK_REG(VLAN_G1_REG) = 0; 205 + ADMTEK_REG(VLAN_G2_REG) = 0; 206 + ADMTEK_REG(CPUp_conf_REG) &= ~SW_CPU_PORT_DISABLE; 207 + 208 + // setup vlans 209 + for (i = 0; i < PORT_COUNT; ++i) { 210 + unsigned long reg, shiftcnt; 211 + if (i <= 3) { 212 + shiftcnt = 8 * i; 213 + reg = ADMTEK_REG(VLAN_G1_REG) & ~(VLAN_PORT_MASK << shiftcnt); 214 + reg |= (0x40 | (1 << i)) << shiftcnt; 215 + ADMTEK_REG(VLAN_G1_REG) = reg; 216 + } 217 + else { 218 + shiftcnt = 8 * (i - 4); 219 + reg = ADMTEK_REG(VLAN_G2_REG) & ~(VLAN_PORT_MASK << shiftcnt); 220 + reg |= (0x40 | (1 << i)) << shiftcnt; 221 + ADMTEK_REG(VLAN_G2_REG) = reg; 222 + } 223 + } 224 +} 225 + 226 +static void admtek_init_descs(void) { 227 + unsigned i; 228 + 229 + memset(sw.rx_descs, 0, sizeof(struct admtek_rx_desc) * RX_DESC_COUNT); 230 + for (i = 0; i < RX_DESC_COUNT; ++i) { 231 + sw.rx_descs[i].len = RX_BUF_SIZE; 232 + sw.rx_descs[i].buf1 = 233 + ((unsigned long)sw.rx_skbs[i]->data & DESC_ADDR_MASK) | DESC_OWN; 234 + } 235 + sw.rx_descs[RX_DESC_COUNT - 1].buf1 |= DESC_RING_END; 236 + 237 + memset(sw.tx_descs, 0, sizeof(struct admtek_tx_desc) * TX_DESC_COUNT); 238 + sw.tx_descs[TX_DESC_COUNT - 1].buf1 |= DESC_RING_END; 239 + 240 + memset(sw.tx_skbs, 0, sizeof(struct sk_buff *) * TX_DESC_COUNT); 241 +} 242 + 243 +static void admtek_rx_tasklet(unsigned long dum) { 244 + struct admtek_rx_desc *desc; 245 + unsigned port; 246 + struct net_device *dev; 247 + struct admtek_dev_priv *priv; 248 + unsigned len; 249 + struct sk_buff *skb; 250 + unsigned long flags; 251 + 252 + spin_lock_irqsave(&sw.lock, flags); 253 + 254 + while (1) { 255 + desc = sw.rx_descs + sw.cur_rx; 256 + if (desc->buf1 & DESC_OWN) break; 257 + 258 + port = (desc->status & DESC_RX_PORT_MASK) >> DESC_RX_PORT_SHIFT; 259 + 260 + dev = sw.devs[port]; 261 + priv = dev->priv; 262 + 263 + len = ((desc->status & DESC_LEN_MASK) >> DESC_LEN_SHIFT) - 4; 264 +// printk("rx status: %08lx, port: %u, len: %u, dev: %s\n", 265 +// desc->status, port, len, dev->name); 266 + if (!len || desc->status & DESC_RX_CSUM_ERR) { 267 + printk("admtek: rx error\n"); 268 + priv->stats.rx_errors++; 269 + priv->stats.rx_length_errors++; 270 + goto next; 271 + } 272 + 273 + if (netif_running(dev)) { 274 + skb = sw.rx_skbs[sw.cur_rx]; 275 + skb_put(skb, len); 276 + skb->dev = dev; 277 + skb->protocol = eth_type_trans(skb, dev); 278 + skb->ip_summed = CHECKSUM_UNNECESSARY; 279 + 280 + // only place we need to flush cache 281 + dma_cache_wback_inv((unsigned long)skb->head, len); 282 + 283 + dev->last_rx = jiffies; 284 + priv->stats.rx_packets++; 285 + priv->stats.rx_bytes += skb->len; 286 + netif_rx(skb); 287 + skb = dev_alloc_skb(RX_BUF_SIZE + 16); 288 + if (skb) skb_reserve(skb, 2); 289 + else { 290 + printk("admtek: alloc rx skb failed\n"); 291 + } 292 + sw.rx_skbs[sw.cur_rx] = skb; 293 + } 294 + 295 + if (sw.rx_skbs[sw.cur_rx]) { 296 + next: 297 + skb = sw.rx_skbs[sw.cur_rx]; 298 + desc->buf2 = 0; 299 + desc->status = 0; 300 + desc->len = RX_BUF_SIZE; 301 + desc->buf1 = (desc->buf1 & DESC_RING_END) | DESC_OWN 302 + | (((unsigned long)skb->data) & DESC_ADDR_MASK); 303 + } 304 + else { 305 + printk("admtek: not enough mem\n"); 306 + } 307 + 308 + ++sw.cur_rx; 309 + if (sw.cur_rx >= RX_DESC_COUNT) sw.cur_rx = 0; 310 + } 311 + ADMTEK_REG(SW_Int_mask_REG) = (ADMTEK_REG(SW_Int_mask_REG) & ~RX_L_INT); 312 + spin_unlock_irqrestore(&sw.lock, flags); 313 +} 314 + 315 +static void admtek_tx_tasklet(unsigned long dum) { 316 + struct admtek_tx_desc *desc; 317 + struct admtek_dev_priv *priv; 318 + unsigned long flags; 319 + 320 + spin_lock_irqsave(&sw.lock, flags); 321 + 322 + while (1) { 323 + desc = sw.tx_descs + sw.dirty_tx; 324 + if (desc->buf1 & DESC_OWN) break; 325 + if (sw.cur_tx == sw.dirty_tx) break; 326 + 327 + priv = sw.devs[ffs(desc->ctrl) - 1]->priv; 328 + if (priv->in_transmit >= TX_DESC_PER_PORT) { 329 +// printk("%lu: start queue: %s, %u\n", 330 +// jiffies, priv->dev->name, priv->in_transmit); 331 + netif_start_queue(priv->dev); 332 + } 333 + --priv->in_transmit; 334 + 335 + dev_kfree_skb_any(sw.tx_skbs[sw.dirty_tx]); 336 + sw.tx_skbs[sw.dirty_tx] = NULL; 337 + 338 + ++sw.dirty_tx; 339 + if (sw.dirty_tx >= TX_DESC_COUNT) sw.dirty_tx = 0; 340 + } 341 + 342 + ADMTEK_REG(SW_Int_mask_REG) = (ADMTEK_REG(SW_Int_mask_REG) & ~TX_L_INT); 343 + spin_unlock_irqrestore(&sw.lock, flags); 344 +} 345 + 346 +static void admtek_interrupt(int irq, void *dev_id, struct pt_regs *regs) { 347 + unsigned long status, mask; 348 +// printk("admtek_interrupt\n"); 349 + 350 + spin_lock(&sw.lock); 351 + 352 + mask = ADMTEK_REG(SW_Int_mask_REG); 353 + 354 + // get status 355 + status = ADMTEK_REG(SW_Int_st_REG); 356 +// if (status & ~(RX_L_INT | TX_L_INT | PORT_STATUS_CHANGE_INT)) { 357 +// printk("interrupt status: %08lx mask: %08lx\n", status, mask); 358 +// } 359 + 360 + // acknowledge 361 + ADMTEK_REG(SW_Int_st_REG ) = status; 362 + 363 + if (status & RX_L_INT) { 364 + mask |= RX_L_INT; 365 + tasklet_hi_schedule(&sw.rx_tasklet); 366 + } 367 + if (status & TX_L_INT) { 368 + mask |= TX_L_INT; 369 + tasklet_hi_schedule(&sw.tx_tasklet); 370 + } 371 + if (status & PORT_STATUS_CHANGE_INT) { 372 + unsigned new_status = ADMTEK_REG(PHY_st_REG); 373 + unsigned i; 374 + for (i = 0; i < PORT_COUNT; ++i) { 375 + if (!sw.devs[i] || !netif_running(sw.devs[i])) continue; 376 + if (((new_status & (1 << i))) != ((sw.link_status & (1 << i)))) { 377 + if ((new_status & (1 << i))) { 378 + printk("admtek: link up for %s\n", sw.devs[i]->name); 379 + netif_carrier_on(sw.devs[i]); 380 + } 381 + else { 382 + printk("admtek: link down for %s\n", sw.devs[i]->name); 383 + netif_carrier_off(sw.devs[i]); 384 + } 385 + } 386 + } 387 + sw.link_status = new_status; 388 + } 389 + 390 + ADMTEK_REG(SW_Int_mask_REG) = mask; 391 + spin_unlock(&sw.lock); 392 +} 393 + 394 + 395 +static int admtek_open(struct net_device *dev) { 396 + struct admtek_dev_priv *priv = dev->priv; 397 + unsigned long reg; 398 +// printk("admtek_open: %s\n", dev->name); 399 + 400 + // set mac 401 +// printk("port #%d mac = %02x:%02x:%02x:%02x:%02x:%02x\n", priv->port, 402 +// dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], 403 +// dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); 404 + 405 + reg = (dev->dev_addr[5] << 24) | (dev->dev_addr[4] << 16) | 406 + (dev->dev_addr[3] << 8) | dev->dev_addr[2]; 407 + ADMTEK_REG(MAC_wt1_REG) = reg; 408 + 409 + reg = (dev->dev_addr[1] << 24) | (dev->dev_addr[0] << 16) | 410 + (priv->port << SW_MAC_VLANID_SHIFT) | SW_MAC_WRITE | SW_MAC_VLANID_EN; 411 + ADMTEK_REG(MAC_wt0_REG) = reg; 412 + 413 + while (!(ADMTEK_REG(MAC_wt0_REG) & SW_MAC_WRITE_DONE)); 414 + 415 + reg = ADMTEK_REG(PHY_st_REG); 416 + if ((reg & (1 << priv->port))) { 417 + printk("admtek: initial link up for %s\n", dev->name); 418 + netif_carrier_on(dev); 419 + sw.link_status |= (1 << priv->port); 420 + } 421 + else { 422 + printk("admtek: initial link down for %s\n", dev->name); 423 + netif_carrier_off(dev); 424 + sw.link_status &= ~(1 << priv->port); 425 + } 426 + 427 + // enable port 428 + ADMTEK_REG(Port_conf0_REG) &= ~(1 << priv->port); 429 + 430 + netif_start_queue(dev); 431 + return 0; 432 +} 433 + 434 +static int admtek_stop(struct net_device *dev) { 435 + struct admtek_dev_priv *priv = dev->priv; 436 +// printk("admtek_stop: %s\n", dev->name); 437 + 438 + netif_stop_queue(dev); 439 + 440 + // disable port 441 + ADMTEK_REG(Port_conf0_REG) |= (1 << priv->port); 442 + 443 + return 0; 444 +} 445 + 446 +static void admtek_set_multicast_list(struct net_device *dev) { 447 + struct admtek_dev_priv *priv = dev->priv; 448 +// printk("admtek_set_multicast_list: %s\n", dev->name); 449 + 450 + if (dev->flags & IFF_PROMISC) { 451 + printk("admtek: enable promisc for %s\n", dev->name); 452 + ADMTEK_REG(CPUp_conf_REG) &= ~((1 << priv->port) << 9); 453 + } 454 + else { 455 + printk("admtek: disable promisc for %s\n", dev->name); 456 + ADMTEK_REG(CPUp_conf_REG) |= ((1 << priv->port) << 9); 457 + } 458 + 459 +} 460 + 461 +static int admtek_hard_start_xmit(struct sk_buff *skb, 462 + struct net_device *dev) { 463 + struct admtek_dev_priv *priv = dev->priv; 464 + struct admtek_tx_desc *desc; 465 + unsigned len; 466 + unsigned long flags; 467 +// printk("admtek_hard_start_xmit: %s\n", dev->name); 468 + 469 + spin_lock_irqsave(&sw.lock, flags); 470 + 471 + desc = sw.tx_descs + sw.cur_tx; 472 + if (desc->buf1 & DESC_OWN) { 473 + printk("admtek: queue not stopped when it should be\n"); 474 + dev_kfree_skb(skb); 475 + priv->stats.tx_dropped++; 476 + return 0; 477 + } 478 + 479 + sw.tx_skbs[sw.cur_tx] = skb; 480 + 481 + desc->buf1 = (desc->buf1 & DESC_RING_END) | 482 + ((unsigned long)skb->data & DESC_ADDR_MASK) | DESC_OWN; 483 + len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; 484 + desc->ctrl = (len << DESC_LEN_SHIFT) | (1 << priv->port); 485 + desc->len = len; 486 + 487 + ADMTEK_REG(Send_trig_REG) = 1; 488 + 489 + priv->stats.tx_packets++; 490 + priv->stats.tx_bytes += len; 491 + dev->trans_start = jiffies; 492 + 493 + ++sw.cur_tx; 494 + if (sw.cur_tx >= TX_DESC_COUNT) sw.cur_tx = 0; 495 + 496 + priv->in_transmit++; 497 + if (priv->in_transmit >= TX_DESC_PER_PORT) { 498 +// printk("%lu: stop queue: %s, %u\n", 499 +// jiffies, dev->name, priv->in_transmit); 500 + netif_stop_queue(dev); 501 + } 502 + 503 + spin_unlock_irqrestore(&sw.lock, flags); 504 + return 0; 505 +} 506 + 507 +static void admtek_get_drvinfo (struct net_device *dev, 508 + struct ethtool_drvinfo *info) { 509 + strcpy(info->driver, "admtek"); 510 + strcpy(info->version, "1.0"); 511 +} 512 + 513 +static int admtek_get_settings(struct net_device *dev, 514 + struct ethtool_cmd *cmd) { 515 + struct admtek_dev_priv *priv = dev->priv; 516 + unsigned long reg; 517 + spin_lock_irq(&sw.lock); 518 + 519 + // inspired from mii.c 520 + cmd->supported = 521 + (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | 522 + SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | 523 + SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); 524 + cmd->port = PORT_MII; 525 + cmd->transceiver = XCVR_INTERNAL; 526 + cmd->phy_address = 0; 527 + 528 + cmd->advertising = ADVERTISED_TP | ADVERTISED_MII; 529 + cmd->advertising |= ADVERTISED_10baseT_Half; 530 + cmd->advertising |= ADVERTISED_10baseT_Full; 531 + cmd->advertising |= ADVERTISED_100baseT_Half; 532 + cmd->advertising |= ADVERTISED_100baseT_Full; 533 + 534 + reg = ADMTEK_REG(PHY_cntl2_REG); 535 + if ((reg & (1 << priv->port))) { 536 + cmd->advertising |= ADVERTISED_Autoneg; 537 + cmd->autoneg = AUTONEG_ENABLE; 538 + } 539 + else cmd->autoneg = AUTONEG_DISABLE; 540 + 541 + reg = ADMTEK_REG(PHY_st_REG); 542 + if ((reg & ((1 << 8) << priv->port))) cmd->speed = SPEED_100; 543 + else cmd->speed = SPEED_10; 544 + if ((reg & ((1 << 16) << priv->port))) cmd->duplex = DUPLEX_FULL; 545 + else cmd->duplex = DUPLEX_HALF; 546 + 547 + spin_unlock_irq(&sw.lock); 548 + return 0; 549 +} 550 + 551 +static int admtek_set_settings(struct net_device *dev, 552 + struct ethtool_cmd *cmd) { 553 + struct admtek_dev_priv *priv = dev->priv; 554 + spin_lock_irq(&sw.lock); 555 + 556 + // inspired from mii.c 557 + if (cmd->speed != SPEED_10 && cmd->speed != SPEED_100) 558 + return -EINVAL; 559 + if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL) 560 + return -EINVAL; 561 + if (cmd->port != PORT_MII) 562 + return -EINVAL; 563 + if (cmd->transceiver != XCVR_INTERNAL) 564 + return -EINVAL; 565 + if (cmd->autoneg != AUTONEG_DISABLE && cmd->autoneg != AUTONEG_ENABLE) 566 + return -EINVAL; 567 + 568 + if (cmd->autoneg == AUTONEG_ENABLE) { 569 + ADMTEK_REG(PHY_cntl2_REG) |= (1 << priv->port); 570 + ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 5) << priv->port); 571 + ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 10) << priv->port); 572 + } else { 573 + ADMTEK_REG(PHY_cntl2_REG) &= ~(1 << priv->port); 574 + 575 + if (cmd->speed == SPEED_100) { 576 + ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 5) << priv->port); 577 + } 578 + else { 579 + ADMTEK_REG(PHY_cntl2_REG) &= ~((1 << 5) << priv->port); 580 + } 581 + 582 + if (cmd->duplex == DUPLEX_FULL) { 583 + ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 10) << priv->port); 584 + } 585 + else { 586 + ADMTEK_REG(PHY_cntl2_REG) &= ~((1 << 10) << priv->port); 587 + } 588 + } 589 + 590 + spin_unlock_irq(&sw.lock); 591 + return 0; 592 +} 593 + 594 +static u32 admtek_get_link(struct net_device *dev) { 595 + struct admtek_dev_priv *priv = dev->priv; 596 + 597 + return !!(sw.link_status & (1 << priv->port)); 598 +} 599 + 600 + 601 +static struct ethtool_ops admtek_ethtool_ops = { 602 + .get_drvinfo = admtek_get_drvinfo, 603 + .get_settings = admtek_get_settings, 604 + .set_settings = admtek_set_settings, 605 + .get_link = admtek_get_link, 606 +}; 607 + 608 +static int admtek_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { 609 + return -EINVAL; 610 +} 611 + 612 +static struct net_device_stats *admtek_get_stats(struct net_device *dev) { 613 + struct admtek_dev_priv *priv = dev->priv; 614 +// printk("admtek_get_stats: %s\n", dev->name); 615 + return &priv->stats; 616 +} 617 + 618 +static void admtek_tx_timeout(struct net_device *dev) { 619 + unsigned i; 620 + unsigned long flags; 621 + printk("admtek_tx_timeout: %s\n", dev->name); 622 + 623 + spin_lock_irqsave(&sw.lock, flags); 624 + 625 + // disable interrupts 626 + ADMTEK_REG(SW_Int_mask_REG) = SWITCH_INT_MASK; 627 + 628 + admtek_init_engine(); 629 + 630 + for (i = 0; i < TX_DESC_COUNT; ++i) { 631 + if (sw.tx_skbs[i]) dev_kfree_skb(sw.tx_skbs[i]); 632 + } 633 + 634 + admtek_init_descs(); 635 + 636 + // reenable ports 637 + for (i = 0; i < PORT_COUNT; ++i) { 638 + if (netif_running(sw.devs[i])) { 639 + ADMTEK_REG(Port_conf0_REG) &= ~(1 << i); 640 + } 641 + } 642 + 643 + // enable interrupts 644 + ADMTEK_REG(SW_Int_mask_REG) = ~(RX_L_INT | TX_L_INT | RX_DESC_ERR_INT | 645 + TX_DESC_ERR_INT | PORT_STATUS_CHANGE_INT); 646 + 647 + spin_unlock_irqrestore(&sw.lock, flags); 648 +} 649 + 650 + 651 +static int admtek_init_dev(struct net_device *dev, unsigned port) { 652 + struct admtek_dev_priv *priv = dev->priv; 653 + int ret = 0; 654 + 655 + SET_MODULE_OWNER(dev); 656 + memcpy(dev->dev_addr, mips_mac_address, 6); 657 + 658 + if (dev->dev_addr[5] + port > 255) ++dev->dev_addr[4]; 659 + dev->dev_addr[5] += port; 660 + 661 + dev->open = admtek_open; 662 + dev->stop = admtek_stop; 663 + dev->set_multicast_list = admtek_set_multicast_list; 664 + dev->hard_start_xmit = admtek_hard_start_xmit; 665 + dev->do_ioctl = admtek_ioctl; 666 + dev->get_stats = admtek_get_stats; 667 + dev->tx_timeout = admtek_tx_timeout; 668 + dev->watchdog_timeo = 2 * HZ; 669 + dev->irq = SW_IRQ; 670 + dev->ethtool_ops = &admtek_ethtool_ops; 671 + 672 + ret = register_netdev(dev); 673 + if (ret) { 674 + printk("admtek: register_netdev failed\n"); 675 + return ret; 676 + } 677 + 678 + priv->dev = dev; 679 + priv->port = port; 680 + 681 + return ret; 682 +} 683 + 684 +static void admtek_cleanup_dev(struct net_device *dev) { 685 + struct admtek_dev_priv *priv = dev->priv; 686 + 687 + if (priv->dev) unregister_netdevice(dev); 688 + 689 + kfree(dev); 690 +} 691 + 692 +static void admtek_cleanup(void) { 693 + unsigned i; 694 + unsigned c; 695 + 696 + // disable interrupts 697 + ADMTEK_REG(SW_Int_mask_REG) = SWITCH_INT_MASK; 698 + 699 + if (sw.irq) free_irq(SW_IRQ, &sw); 700 + 701 + for (i = 0; i < PORT_COUNT; ++i) { 702 + if (sw.devs[i]) admtek_cleanup_dev(sw.devs[i]); 703 + } 704 + if (sw.tx_skbs) { 705 + for (i = 0; i < TX_DESC_COUNT; ++i) { 706 + if (sw.tx_skbs[i]) dev_kfree_skb(sw.tx_skbs[i]); 707 + } 708 + kfree(sw.tx_skbs); 709 + } 710 + if (sw.tx_descs) { 711 + c = TX_DESC_COUNT; 712 + pci_free_consistent(NULL, sizeof(struct admtek_rx_desc) * c, 713 + sw.tx_descs, sw.tx_descs_dma); 714 + } 715 + if (sw.rx_skbs) { 716 + for (i = 0; i < RX_DESC_COUNT; ++i) { 717 + if (sw.rx_skbs[i]) dev_kfree_skb(sw.rx_skbs[i]); 718 + } 719 + kfree(sw.rx_skbs); 720 + } 721 + if (sw.rx_descs) { 722 + c = RX_DESC_COUNT; 723 + pci_free_consistent(NULL, sizeof(struct admtek_rx_desc) * c, 724 + sw.rx_descs, sw.rx_descs_dma); 725 + } 726 +} 727 + 728 +static int __init admtek_init(void) { 729 + unsigned i; 730 + 731 + if (!is_rb100()) return 1; 732 + 733 + printk("ADMTEK ethernet switch driver\n"); 734 + if (request_irq(SW_IRQ, admtek_interrupt, SA_SHIRQ, 735 + "ethernet switch", &sw)) { 736 + printk("admtek: request irq failed\n"); 737 + goto err_out; 738 + } 739 + sw.irq = 1; 740 + 741 + // alloc buffers 742 + sw.rx_descs = pci_alloc_consistent(NULL, sizeof(struct admtek_rx_desc) 743 + * RX_DESC_COUNT, &sw.rx_descs_dma); 744 + if (!sw.rx_descs) { 745 + printk("admtek: alloc rx descriptors failed\n"); 746 + goto err_out; 747 + } 748 + 749 + sw.rx_skbs = kmalloc(sizeof(struct sk_buff *) * RX_DESC_COUNT, GFP_KERNEL); 750 + if (!sw.rx_skbs) { 751 + printk("admtek: alloc rx skb ptr buf failed\n"); 752 + goto err_out; 753 + } 754 + memset(sw.rx_skbs, 0, sizeof(struct sk_buff *) * RX_DESC_COUNT); 755 + 756 + for (i = 0; i < RX_DESC_COUNT; ++i) { 757 + sw.rx_skbs[i] = dev_alloc_skb(RX_BUF_SIZE + 16); 758 + if (!sw.rx_skbs[i]) { 759 + printk("admtek: alloc rx skb failed\n"); 760 + goto err_out; 761 + } 762 + skb_reserve(sw.rx_skbs[i], 2); 763 + } 764 + 765 + sw.tx_descs = pci_alloc_consistent(NULL, sizeof(struct admtek_tx_desc) 766 + * TX_DESC_COUNT, &sw.tx_descs_dma); 767 + if (!sw.tx_descs) { 768 + printk("admtek: alloc tx descriptors failed\n"); 769 + goto err_out; 770 + } 771 + 772 + sw.tx_skbs = kmalloc(sizeof(struct sk_buff *) * TX_DESC_COUNT, GFP_KERNEL); 773 + if (!sw.tx_skbs) { 774 + printk("admtek: alloc tx skb ptr buf failed\n"); 775 + goto err_out; 776 + } 777 + 778 + tasklet_init(&sw.rx_tasklet, admtek_rx_tasklet, (unsigned long)&sw); 779 + tasklet_init(&sw.tx_tasklet, admtek_tx_tasklet, (unsigned long)&sw); 780 + spin_lock_init(&sw.lock); 781 + 782 + admtek_init_engine(); 783 + 784 + admtek_init_descs(); 785 + 786 + for (i = 0; i < PORT_COUNT; ++i) { 787 + sw.devs[i] = alloc_etherdev(sizeof(struct admtek_dev_priv)); 788 + if (sw.devs[i] == NULL) { 789 + printk("admtek: alloc_etherdev failed for port #%u\n", i); 790 + goto err_out; 791 + } 792 + 793 + /* TODO: check for 5 port version */ 794 + if (i == 1) break; 795 + 796 + if (admtek_init_dev(sw.devs[i], i)) { 797 + printk("admtek: init failed for port #%u\n", i); 798 + goto err_out; 799 + } 800 + } 801 + 802 + // enable interrupts 803 + ADMTEK_REG(SW_Int_mask_REG) = ~(RX_L_INT | TX_L_INT | RX_DESC_ERR_INT | 804 + TX_DESC_ERR_INT | PORT_STATUS_CHANGE_INT); 805 + return 0; 806 +err_out: 807 + admtek_cleanup(); 808 + return -ENODEV; 809 +} 810 + 811 +static void __exit admtek_uninit(void) { 812 + admtek_cleanup(); 813 +} 814 + 815 +module_init(admtek_init); 816 +module_exit(admtek_uninit); 1 817 diff -NaurB linux-2.4.33.3/drivers/net/Config.in linux-2.4.33.3.patched/drivers/net/Config.in 2 --- linux-2.4.33.3/drivers/net/Config.in 2006-11-1 2 21:17:50.000000000 +01003 +++ linux-2.4.33.3.patched/drivers/net/Config.in 2006-11-1 2 22:37:38.000000000 +0100818 --- linux-2.4.33.3/drivers/net/Config.in 2006-11-15 10:12:14.000000000 +0100 819 +++ linux-2.4.33.3.patched/drivers/net/Config.in 2006-11-15 10:34:48.000000000 +0100 4 820 @@ -30,6 +30,9 @@ 5 821 comment 'Ethernet (10 or 100Mbit)' … … 12 828 dep_bool ' ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110 13 829 tristate ' Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS 830 @@ -77,6 +80,12 @@ 831 bool ' Broadcom 5222 Dual Phy Support' CONFIG_BCM5222_DUAL_PHY 832 fi 833 fi 834 + if [ "$CONFIG_MIPS_MIKROTIK" = "y" ]; then 835 + tristate ' MIPS ADM5120 Ethernet Switch support' CONFIG_MIPS_AM5120_SW 836 + fi 837 + if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then 838 + tristate ' SB1250 Ethernet support' CONFIG_NET_SB1250_MAC 839 + fi 840 if [ "$CONFIG_SGI_IP27" = "y" ]; then 841 bool ' SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH 842 fi 14 843 diff -NaurB linux-2.4.33.3/drivers/net/korina.c linux-2.4.33.3.patched/drivers/net/korina.c 15 844 --- linux-2.4.33.3/drivers/net/korina.c 1970-01-01 01:00:00.000000000 +0100 16 +++ linux-2.4.33.3.patched/drivers/net/korina.c 2006-11-1 2 22:33:45.000000000 +010017 @@ -0,0 +1,172 5@@845 +++ linux-2.4.33.3.patched/drivers/net/korina.c 2006-11-15 10:34:48.000000000 +0100 846 @@ -0,0 +1,1727 @@ 18 847 +/* 19 848 +************************************************************************************ … … 1563 2392 + int i, retval=0; 1564 2393 + 2394 + if (!is_rb500()) return 1; 2395 + 1565 2396 + for (i = 0; korina_iflist[i].iobase; i++) { 1566 2397 + retval |= korina_probe(i); … … 1742 2573 +module_exit(korina_cleanup_module); 1743 2574 diff -NaurB linux-2.4.33.3/drivers/net/Makefile linux-2.4.33.3.patched/drivers/net/Makefile 1744 --- linux-2.4.33.3/drivers/net/Makefile 2006-11-1 2 21:17:50.000000000 +01001745 +++ linux-2.4.33.3.patched/drivers/net/Makefile 2006-11-1 2 22:38:07.000000000 +01001746 @@ -244,6 +244, 7@@2575 --- linux-2.4.33.3/drivers/net/Makefile 2006-11-15 10:12:14.000000000 +0100 2576 +++ linux-2.4.33.3.patched/drivers/net/Makefile 2006-11-15 10:34:48.000000000 +0100 2577 @@ -244,6 +244,8 @@ 1747 2578 obj-$(CONFIG_DL2K) += dl2k.o 1748 2579 obj-$(CONFIG_R8169) += r8169.o 1749 2580 obj-$(CONFIG_AMD8111_ETH) += amd8111e.o mii.o 1750 2581 +obj-$(CONFIG_KORINA) += korina.o mii.o 2582 +obj-$(CONFIG_MIPS_AM5120_SW) += admtek.o 1751 2583 1752 2584 # non-drivers/net drivers who want mii lib 1753 2585 obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o 2586 diff -NaurB linux-2.4.33.3/drivers/net/natsemi.c linux-2.4.33.3.patched/drivers/net/natsemi.c 2587 --- linux-2.4.33.3/drivers/net/natsemi.c 2006-08-31 19:03:20.000000000 +0200 2588 +++ linux-2.4.33.3.patched/drivers/net/natsemi.c 2006-11-15 10:34:10.000000000 +0100 2589 @@ -190,8 +190,8 @@ 2590 static int debug = -1; 2591 2592 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ 2593 -static int max_interrupt_work = 20; 2594 -static int mtu; 2595 +static int max_interrupt_work = 40; 2596 +static int mtu = 0; 2597 2598 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). 2599 This chip uses a 512 element hash table based on the Ethernet CRC. */ 2600 @@ -199,7 +199,10 @@ 2601 2602 /* Set the copy breakpoint for the copy-only-tiny-frames scheme. 2603 Setting to > 1518 effectively disables this feature. */ 2604 -static int rx_copybreak; 2605 +static int rx_copybreak = 0; 2606 + 2607 +/* Set the interrupt holdoff value in usec. */ 2608 +static int intr_holdoff_value = 1000; 2609 2610 /* Used to pass the media type, etc. 2611 Both 'options[]' and 'full_duplex[]' should exist for driver 2612 @@ -217,9 +220,9 @@ 2613 Making the Tx ring too large decreases the effectiveness of channel 2614 bonding and packet priority. 2615 There are no ill effects from too-large receive rings. */ 2616 -#define TX_RING_SIZE 16 2617 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used, min 4. */ 2618 -#define RX_RING_SIZE 32 2619 +#define TX_RING_SIZE 32 2620 +#define TX_QUEUE_LEN 28 /* Limit ring entries actually used, min 4. */ 2621 +#define RX_RING_SIZE 64 2622 2623 /* Operational parameters that usually are not changed. */ 2624 /* Time in jiffies before concluding the transmitter is hung. */ 2625 @@ -236,7 +239,8 @@ 2626 #define NATSEMI_REGS_SIZE (NATSEMI_NREGS * sizeof(u32)) 2627 #define NATSEMI_EEPROM_SIZE 24 /* 12 16-bit values */ 2628 2629 -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ 2630 +//#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ 2631 +#define PKT_BUF_SZ 4036 /* Size of each temporary Rx buffer. */ 2632 2633 /* These identify the driver base version and may not be removed. */ 2634 static char version[] __devinitdata = 2635 @@ -254,6 +258,7 @@ 2636 MODULE_PARM(mtu, "i"); 2637 MODULE_PARM(debug, "i"); 2638 MODULE_PARM(rx_copybreak, "i"); 2639 +MODULE_PARM(intr_holdoff_value, "i"); 2640 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); 2641 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); 2642 MODULE_PARM_DESC(max_interrupt_work, 2643 @@ -262,6 +267,8 @@ 2644 MODULE_PARM_DESC(debug, "DP8381x default debug level"); 2645 MODULE_PARM_DESC(rx_copybreak, 2646 "DP8381x copy breakpoint for copy-only-tiny-frames"); 2647 +MODULE_PARM_DESC(intr_holdoff_value, 2648 + "DP83816 interrupt holdoff in usec (DP83816 only)"); 2649 MODULE_PARM_DESC(options, 2650 "DP8381x: Bits 0-3: media type, bit 17: full duplex"); 2651 MODULE_PARM_DESC(full_duplex, "DP8381x full duplex setting(s) (1)"); 2652 @@ -597,6 +604,11 @@ 2653 PhyAddrMask = 0xf, 2654 }; 2655 2656 +enum IntrHoldoff_bits { 2657 + InteHoldoffTime = 0xff, 2658 + InteHoldoffControl = 0x100, 2659 +}; 2660 + 2661 /* values we might find in the silicon revision register */ 2662 #define SRR_DP83815_C 0x0302 2663 #define SRR_DP83815_D 0x0403 2664 @@ -674,6 +686,9 @@ 2665 unsigned int iosize; 2666 spinlock_t lock; 2667 u32 msg_enable; 2668 + 2669 + int long_cable; 2670 + int cable_magic_done; 2671 }; 2672 2673 static int eeprom_read(long ioaddr, int location); 2674 @@ -1131,9 +1146,12 @@ 2675 { 2676 struct netdev_private *np = dev->priv; 2677 2678 - if (np->srr >= SRR_DP83816_A5) 2679 + if (np->srr > SRR_DP83816_A5 || np->long_cable) 2680 return; 2681 2682 + np->cable_magic_done = 1; 2683 + printk("natsemi: do cable magic\n"); 2684 + 2685 /* 2686 * 100 MBit links with short cables can trip an issue with the chip. 2687 * The problem manifests as lots of CRC errors and/or flickering 2688 @@ -1172,9 +1190,12 @@ 2689 u16 data; 2690 struct netdev_private *np = dev->priv; 2691 2692 - if (np->srr >= SRR_DP83816_A5) 2693 + if (np->srr > SRR_DP83816_A5 || !np->cable_magic_done) 2694 return; 2695 2696 + np->cable_magic_done = 0; 2697 + printk("natsemi: undo cable magic\n"); 2698 + 2699 writew(1, dev->base_addr + PGSEL); 2700 /* make sure the lock bit is clear */ 2701 data = readw(dev->base_addr + DSPCFG); 2702 @@ -1294,7 +1315,8 @@ 2703 /* DRTH 0x10: start copying to memory if 128 bytes are in the fifo 2704 * MXDMA 0: up to 256 byte bursts 2705 */ 2706 - np->rx_config = RxMxdma_256 | 0x20; 2707 +// np->rx_config = RxMxdma_256 | 0x20; 2708 + np->rx_config = RxAcceptLong | RxMxdma_256 | 0x20; 2709 writel(np->rx_config, ioaddr + RxConfig); 2710 2711 /* Disable PME: 2712 @@ -1506,7 +1528,8 @@ 2713 /* 2) RX ring */ 2714 np->dirty_rx = 0; 2715 np->cur_rx = RX_RING_SIZE; 2716 - np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); 2717 + np->rx_buf_sz = PKT_BUF_SZ; 2718 +// np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); 2719 np->oom = 0; 2720 np->rx_head_desc = &np->rx_ring[0]; 2721 2722 @@ -1691,6 +1714,7 @@ 2723 struct netdev_private *np = dev->priv; 2724 long ioaddr = dev->base_addr; 2725 int boguscnt = max_interrupt_work; 2726 + int was_rx = 0; 2727 unsigned int handled = 0; 2728 2729 if (np->hands_off) 2730 @@ -1712,6 +1736,7 @@ 2731 if (intr_status & 2732 (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | 2733 IntrRxErr | IntrRxOverrun)) { 2734 + was_rx++; 2735 netdev_rx(dev); 2736 } 2737 2738 @@ -1736,6 +1761,13 @@ 2739 } 2740 } while (1); 2741 2742 + if (was_rx && (np->srr >= SRR_DP83816_A4)) 2743 + { 2744 + /* set interrupt hold off. (only in DP83816) */ 2745 + writel(((intr_holdoff_value/100) & InteHoldoffTime), 2746 + dev->base_addr + IntrHoldoff); 2747 + } 2748 + 2749 if (netif_msg_intr(np)) 2750 printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name); 2751 2752 @@ -2122,6 +2154,20 @@ 2753 return 0; 2754 } 2755 2756 + case 0x12345678: { 2757 + struct ethtool_value edata; 2758 + if (copy_from_user(&edata, useraddr, sizeof(edata))) 2759 + return -EFAULT; 2760 + 2761 + spin_lock_irq(&np->lock); 2762 + undo_cable_magic(dev); 2763 + np->long_cable = edata.data; 2764 + do_cable_magic(dev); 2765 + spin_unlock_irq(&np->lock); 2766 + 2767 + return 0; 2768 + } 2769 + 2770 } 2771 2772 return -EOPNOTSUPP; 2773 diff -NaurB linux-2.4.33.3/drivers/net/sundance.c linux-2.4.33.3.patched/drivers/net/sundance.c 2774 --- linux-2.4.33.3/drivers/net/sundance.c 2006-08-31 19:03:20.000000000 +0200 2775 +++ linux-2.4.33.3.patched/drivers/net/sundance.c 2006-11-15 10:34:16.000000000 +0100 2776 @@ -188,6 +188,8 @@ 2777 #include "compat.h" 2778 #endif 2779 2780 +#define USE_IO_OPS 1 2781 + 2782 /* These identify the driver base version and may not be removed. */ 2783 static char version[] __devinitdata = 2784 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" 2785 diff -NaurB linux-2.4.33.3/drivers/net/tulip/interrupt.c linux-2.4.33.3.patched/drivers/net/tulip/interrupt.c 2786 --- linux-2.4.33.3/drivers/net/tulip/interrupt.c 2006-08-31 19:03:20.000000000 +0200 2787 +++ linux-2.4.33.3.patched/drivers/net/tulip/interrupt.c 2006-11-15 10:34:19.000000000 +0100 2788 @@ -122,14 +122,36 @@ 2789 /* If we own the next entry, it is a new packet. Send it up. */ 2790 while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { 2791 s32 status = le32_to_cpu(tp->rx_ring[entry].status); 2792 + short pkt_len; 2793 2794 if (tulip_debug > 5) 2795 printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", 2796 dev->name, entry, status); 2797 if (--rx_work_limit < 0) 2798 break; 2799 - if ((status & 0x38008300) != 0x0300) { 2800 - if ((status & 0x38000300) != 0x0300) { 2801 + 2802 + /* 2803 + Omit the four octet CRC from the length. 2804 + (May not be considered valid until we have 2805 + checked status for RxLengthOver2047 bits) 2806 + */ 2807 + pkt_len = ((status >> 16) & 0x7ff) - 4; 2808 + 2809 + /* 2810 + Maximum pkt_len is 1518 (1514 + vlan header) 2811 + Anything higher than this is always invalid 2812 + regardless of RxLengthOver2047 bits 2813 + */ 2814 + 2815 + if ((status & (RxLengthOver2047 | 2816 + RxDescCRCError | 2817 + RxDescCollisionSeen | 2818 + RxDescRunt | 2819 + RxDescDescErr | 2820 + RxWholePkt)) != RxWholePkt 2821 + || pkt_len > 1518 ) { 2822 + if ((status & (RxLengthOver2047 | 2823 + RxWholePkt)) != RxWholePkt) { 2824 /* Ingore earlier buffers. */ 2825 if ((status & 0xffff) != 0x7fff) { 2826 if (tulip_debug > 1) 2827 @@ -138,31 +160,21 @@ 2828 dev->name, status); 2829 tp->stats.rx_length_errors++; 2830 } 2831 - } else if (status & RxDescFatalErr) { 2832 + } else { 2833 /* There was a fatal error. */ 2834 if (tulip_debug > 2) 2835 printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", 2836 dev->name, status); 2837 tp->stats.rx_errors++; /* end of a packet.*/ 2838 - if (status & 0x0890) tp->stats.rx_length_errors++; 2839 + if (pkt_len > 1518 || 2840 + status & RxDescRunt) tp->stats.rx_length_errors++; 2841 if (status & 0x0004) tp->stats.rx_frame_errors++; 2842 if (status & 0x0002) tp->stats.rx_crc_errors++; 2843 if (status & 0x0001) tp->stats.rx_fifo_errors++; 2844 } 2845 } else { 2846 - /* Omit the four octet CRC from the length. */ 2847 - short pkt_len = ((status >> 16) & 0x7ff) - 4; 2848 struct sk_buff *skb; 2849 2850 -#ifndef final_version 2851 - if (pkt_len > 1518) { 2852 - printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n", 2853 - dev->name, pkt_len, pkt_len); 2854 - pkt_len = 1518; 2855 - tp->stats.rx_length_errors++; 2856 - } 2857 -#endif 2858 - 2859 #ifdef CONFIG_NET_HW_FLOWCONTROL 2860 drop = atomic_read(&netdev_dropping); 2861 if (drop) 2862 diff -NaurB linux-2.4.33.3/drivers/net/tulip/tulip.h linux-2.4.33.3.patched/drivers/net/tulip/tulip.h 2863 --- linux-2.4.33.3/drivers/net/tulip/tulip.h 2006-08-31 19:03:20.000000000 +0200 2864 +++ linux-2.4.33.3.patched/drivers/net/tulip/tulip.h 2006-11-15 10:34:19.000000000 +0100 2865 @@ -191,8 +191,40 @@ 2866 2867 enum desc_status_bits { 2868 DescOwned = 0x80000000, 2869 - RxDescFatalErr = 0x8000, 2870 + 2871 + /* 2872 + Error summary flag is logical or of 'CRC Error', 2873 + 'Collision Seen', 'Frame Too Long', 'Runt' and 2874 + 'Descriptor Error' flags generated within tulip chip. 2875 + */ 2876 + RxDescErrorSummary = 0x8000, 2877 + 2878 + RxDescCRCError = 0x0002, 2879 + RxDescCollisionSeen = 0x0040, 2880 + 2881 + /* 2882 + 'Frame Too Long' flag is set if packet length including CRC 2883 + exceeds 1518. However, a full sized VLAN tagged frame is 2884 + 1522 bytes including CRC. 2885 + 2886 + The tulip chip does not block oversized frames, and if this 2887 + flag is set on a receive descriptor it does not indicate 2888 + the frame has been truncated. The receive descriptor also 2889 + includes the actual length. Therefore we can safety ignore 2890 + this flag and check the length ourselves. 2891 + */ 2892 + RxDescFrameTooLong = 0x0080, 2893 + RxDescRunt = 0x0800, 2894 + RxDescDescErr = 0x4000, 2895 RxWholePkt = 0x0300, 2896 + 2897 + /* 2898 + Top three bits of 14 bit frame length (status bits 27-29) 2899 + should never be set as that would make frame over 2047 bytes. 2900 + The Receive Watchdog flag (bit 4) may indicate the length is 2901 + over 2048 and the length field is invalid. 2902 + */ 2903 + RxLengthOver2047 = 0x38000010 2904 }; 2905 2906 2907 diff -NaurB linux-2.4.33.3/drivers/net/via-rhine.c linux-2.4.33.3.patched/drivers/net/via-rhine.c 2908 --- linux-2.4.33.3/drivers/net/via-rhine.c 2006-08-31 19:03:20.000000000 +0200 2909 +++ linux-2.4.33.3.patched/drivers/net/via-rhine.c 2006-11-15 10:33:56.000000000 +0100 2910 @@ -172,9 +172,9 @@ 2911 Making the Tx ring too large decreases the effectiveness of channel 2912 bonding and packet priority. 2913 There are no ill effects from too-large receive rings. */ 2914 -#define TX_RING_SIZE 16 2915 -#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ 2916 -#define RX_RING_SIZE 16 2917 +#define TX_RING_SIZE 128 2918 +#define TX_QUEUE_LEN 120 /* Limit ring entries actually used. */ 2919 +#define RX_RING_SIZE 128 2920 2921 2922 /* Operational parameters that usually are not changed. */ 2923 @@ -258,6 +258,31 @@ 2924 MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex"); 2925 MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)"); 2926 2927 +#ifdef CONFIG_MIPS_MIKROTIK 2928 +#undef USE_MEM 2929 +#undef USE_IO 2930 +#define USE_IO 2931 + 2932 +#undef readb 2933 +#undef readw 2934 +#undef readl 2935 +#undef writeb 2936 +#undef writew 2937 +#undef writel 2938 + 2939 +#include <asm/rb/pci.h> 2940 +#include <asm/io.h> 2941 + 2942 +#define readb(addr) pci_readb((unsigned long) (addr) + mips_io_port_base) 2943 +#define readw(addr) pci_readw((unsigned long) (addr) + mips_io_port_base) 2944 +#define readl(addr) pci_readl((unsigned long) (addr) + mips_io_port_base) 2945 + 2946 +#define writeb(b,addr) pci_writeb(b, (unsigned long) (addr) + mips_io_port_base) 2947 +#define writew(b,addr) pci_writew(b, (unsigned long) (addr) + mips_io_port_base) 2948 +#define writel(b,addr) pci_writel(b, (unsigned long) (addr) + mips_io_port_base) 2949 + 2950 +#endif 2951 + 2952 /* 2953 Theory of Operation 2954 2955 @@ -510,6 +535,9 @@ 2956 unsigned char *tx_bufs; 2957 dma_addr_t tx_bufs_dma; 2958 2959 + struct tasklet_struct *rx_tasklet; 2960 + struct tasklet_struct *tx_tasklet; 2961 + 2962 struct pci_dev *pdev; 2963 struct net_device_stats stats; 2964 struct timer_list timer; /* Media monitoring timer. */ 2965 @@ -543,7 +571,9 @@ 2966 static int via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev); 2967 static irqreturn_t via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); 2968 static void via_rhine_tx(struct net_device *dev); 2969 +static void via_rhine_tx_tasklet(unsigned long tx_data_dev); 2970 static void via_rhine_rx(struct net_device *dev); 2971 +static void via_rhine_rx_tasklet(unsigned long rx_data_dev); 2972 static void via_rhine_error(struct net_device *dev, int intr_status); 2973 static void via_rhine_set_rx_mode(struct net_device *dev); 2974 static struct net_device_stats *via_rhine_get_stats(struct net_device *dev); 2975 @@ -567,7 +597,7 @@ 2976 static void wait_for_reset(struct net_device *dev, int chip_id, char *name) 2977 { 2978 long ioaddr = dev->base_addr; 2979 - int boguscnt = 20; 2980 + int boguscnt = 2000; 2981 2982 IOSYNC; 2983 2984 @@ -611,7 +641,7 @@ 2985 int i; 2986 outb(0x20, ioaddr + MACRegEEcsr); 2987 /* Typically 2 cycles to reload. */ 2988 - for (i = 0; i < 150; i++) 2989 + for (i = 0; i < 3000; i++) 2990 if (! (inb(ioaddr + MACRegEEcsr) & 0x20)) 2991 break; 2992 } 2993 @@ -735,6 +765,7 @@ 2994 dev->base_addr = ioaddr; 2995 wait_for_reset(dev, chip_id, shortname); 2996 2997 +#ifndef CONFIG_MIPS_MIKROTIK 2998 /* Reload the station address from the EEPROM. */ 2999 #ifdef USE_IO 3000 reload_eeprom(ioaddr); 3001 @@ -745,6 +776,7 @@ 3002 not known if that still works with the "win98-reboot" problem. */ 3003 enable_mmio(ioaddr0, chip_id); 3004 #endif 3005 +#endif 3006 3007 for (i = 0; i < 6; i++) 3008 dev->dev_addr[i] = readb(ioaddr + StationAddr + i); 3009 @@ -874,6 +906,17 @@ 3010 } 3011 } 3012 3013 + np->rx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL); 3014 + tasklet_init(np->rx_tasklet, via_rhine_rx_tasklet, (unsigned long)dev); 3015 + tasklet_disable_nosync(np->rx_tasklet); 3016 + np->tx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL); 3017 + tasklet_init(np->tx_tasklet, via_rhine_tx_tasklet, (unsigned long)dev); 3018 + tasklet_disable_nosync(np->tx_tasklet); 3019 + 3020 + // shut down until somebody really needs it 3021 + writeb(0x80, ioaddr + 0xa1); 3022 + pci_set_power_state(np->pdev, 3); 3023 + 3024 return 0; 3025 3026 err_out_unmap: 3027 @@ -1091,9 +1134,11 @@ 3028 3029 static int mdio_read(struct net_device *dev, int phy_id, int regnum) 3030 { 3031 + struct netdev_private *np = dev->priv; 3032 long ioaddr = dev->base_addr; 3033 int boguscnt = 1024; 3034 3035 + if (np->pdev->current_state) return 0; 3036 /* Wait for a previous command to complete. */ 3037 while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0) 3038 ; 3039 @@ -1113,6 +1158,7 @@ 3040 long ioaddr = dev->base_addr; 3041 int boguscnt = 1024; 3042 3043 + if (np->pdev->current_state) return; 3044 if (phy_id == np->phys[0]) { 3045 switch (regnum) { 3046 case MII_BMCR: /* Is user forcing speed/duplex? */ 3047 @@ -1144,6 +1190,8 @@ 3048 long ioaddr = dev->base_addr; 3049 int i; 3050 3051 + pci_enable_device(np->pdev); 3052 + 3053 /* Reset the chip. */ 3054 writew(CmdReset, ioaddr + ChipCmd); 3055 3056 @@ -1168,6 +1216,9 @@ 3057 dev->name, readw(ioaddr + ChipCmd), 3058 mdio_read(dev, np->phys[0], MII_BMSR)); 3059 3060 + tasklet_enable(np->rx_tasklet); 3061 + tasklet_enable(np->tx_tasklet); 3062 + 3063 netif_start_queue(dev); 3064 3065 /* Set the timer to check for link beat. */ 3066 @@ -1367,7 +1418,6 @@ 3067 struct net_device *dev = dev_instance; 3068 long ioaddr; 3069 u32 intr_status; 3070 - int boguscnt = max_interrupt_work; 3071 int handled = 0; 3072 3073 ioaddr = dev->base_addr; 3074 @@ -1409,13 +1459,11 @@ 3075 IntrTxUnderrun | IntrTxDescRace)) 3076 via_rhine_error(dev, intr_status); 3077 3078 - if (--boguscnt < 0) { 3079 - printk(KERN_WARNING "%s: Too much work at interrupt, " 3080 - "status=%#8.8x.\n", 3081 - dev->name, intr_status); 3082 + if (debug > 3) 3083 + printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n", 3084 + dev->name, readw(ioaddr + IntrStatus)); 3085 break; 3086 } 3087 - } 3088 3089 if (debug > 3) 3090 printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n", 3091 @@ -1428,9 +1476,28 @@ 3092 static void via_rhine_tx(struct net_device *dev) 3093 { 3094 struct netdev_private *np = dev->priv; 3095 + long ioaddr = dev->base_addr; 3096 + 3097 + spin_lock(&np->lock); 3098 + 3099 + /* Disable TX interrupts by setting the interrupt mask */ 3100 + writew(readw(ioaddr + IntrEnable) & ~(IntrTxDone | IntrTxErrSummary), 3101 + ioaddr + IntrEnable); 3102 + 3103 + tasklet_hi_schedule(np->tx_tasklet); 3104 + 3105 + spin_unlock(&np->lock); 3106 +} 3107 + 3108 +static void via_rhine_tx_tasklet(unsigned long tx_data_dev) 3109 +{ 3110 + struct net_device *dev = (struct net_device *)tx_data_dev; 3111 + struct netdev_private *np = dev->priv; 3112 + long ioaddr = dev->base_addr; 3113 + 3114 int txstatus = 0, entry = np->dirty_tx % TX_RING_SIZE; 3115 3116 - spin_lock (&np->lock); 3117 + spin_lock_irq(&np->lock); 3118 3119 /* find and cleanup dirty tx descriptors */ 3120 while (np->dirty_tx != np->cur_tx) { 3121 @@ -1474,14 +1541,19 @@ 3122 np->tx_skbuff_dma[entry], 3123 np->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); 3124 } 3125 - dev_kfree_skb_irq(np->tx_skbuff[entry]); 3126 + dev_kfree_skb_any(np->tx_skbuff[entry]); 3127 np->tx_skbuff[entry] = NULL; 3128 entry = (++np->dirty_tx) % TX_RING_SIZE; 3129 } 3130 if ((np->cur_tx - np->dirty_tx) < TX_QUEUE_LEN - 4) 3131 netif_wake_queue (dev); 3132 3133 - spin_unlock (&np->lock); 3134 + spin_unlock_irq(&np->lock); 3135 + 3136 + // Enable TX interrupts by setting the interrupt mask 3137 + writew(readw(ioaddr + IntrEnable) | 3138 + (IntrTxDone | IntrTxErrSummary), 3139 + ioaddr + IntrEnable); 3140 } 3141 3142 /* This routine is logically part of the interrupt handler, but isolated 3143 @@ -1489,6 +1561,28 @@ 3144 static void via_rhine_rx(struct net_device *dev) 3145 { 3146 struct netdev_private *np = dev->priv; 3147 + long ioaddr = dev->base_addr; 3148 + 3149 + spin_lock(&np->lock); 3150 + 3151 + /* Disable RX interrupts by setting the interrupt mask */ 3152 + writew(readw(ioaddr + IntrEnable) & 3153 + ~(IntrRxDone | IntrRxErr | IntrRxDropped | IntrRxWakeUp | 3154 + IntrRxEmpty | IntrRxNoBuf), 3155 + ioaddr + IntrEnable); 3156 + 3157 + tasklet_hi_schedule(np->rx_tasklet); 3158 + 3159 + spin_unlock(&np->lock); 3160 +} 3161 + 3162 +static void via_rhine_rx_tasklet(unsigned long rx_data_dev) 3163 +{ 3164 + struct net_device *dev = (struct net_device *)rx_data_dev; 3165 + struct netdev_private *np = dev->priv; 3166 + long ioaddr = dev->base_addr; 3167 + u32 desc_status; 3168 + 3169 int entry = np->cur_rx % RX_RING_SIZE; 3170 int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx; 3171 3172 @@ -1498,10 +1592,11 @@ 3173 } 3174 3175 /* If EOP is set on the next entry, it's a new packet. Send it up. */ 3176 - while ( ! (np->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) { 3177 - struct rx_desc *desc = np->rx_head_desc; 3178 - u32 desc_status = le32_to_cpu(desc->rx_status); 3179 - int data_size = desc_status >> 16; 3180 + while (1) { 3181 + int data_size; 3182 + desc_status = le32_to_cpu(np->rx_head_desc->rx_status); 3183 + if (desc_status & DescOwn) break; 3184 + data_size = desc_status >> 16; 3185 3186 if (debug > 4) 3187 printk(KERN_DEBUG " via_rhine_rx() status is %8.8x.\n", 3188 @@ -1527,9 +1622,9 @@ 3189 if (desc_status & 0x0004) np->stats.rx_frame_errors++; 3190 if (desc_status & 0x0002) { 3191 /* this can also be updated outside the interrupt handler */ 3192 - spin_lock (&np->lock); 3193 + spin_lock_irq(&np->lock); 3194 np->stats.rx_crc_errors++; 3195 - spin_unlock (&np->lock); 3196 + spin_unlock_irq(&np->lock); 3197 } 3198 } 3199 } else { 3200 @@ -1566,7 +1661,7 @@ 3201 np->rx_skbuff[entry] = NULL; 3202 skb_put(skb, pkt_len); 3203 pci_unmap_single(np->pdev, np->rx_skbuff_dma[entry], 3204 - np->rx_buf_sz, PCI_DMA_FROMDEVICE); 3205 + pkt_len, PCI_DMA_FROMDEVICE); 3206 } 3207 skb->protocol = eth_type_trans(skb, dev); 3208 netif_rx(skb); 3209 @@ -1596,6 +1691,12 @@ 3210 np->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); 3211 } 3212 3213 + // Enable RX interrupts by setting the interrupt mask 3214 + writew(readw(ioaddr + IntrEnable) | 3215 + (IntrRxDone | IntrRxErr | IntrRxDropped | IntrRxWakeUp | 3216 + IntrRxEmpty | IntrRxNoBuf), 3217 + ioaddr + IntrEnable); 3218 + 3219 /* Pre-emptively restart Rx engine. */ 3220 writew(readw(dev->base_addr + ChipCmd) | CmdRxOn | CmdRxDemand, 3221 dev->base_addr + ChipCmd); 3222 @@ -1866,6 +1967,9 @@ 3223 3224 del_timer_sync(&np->timer); 3225 3226 + tasklet_disable(np->rx_tasklet); 3227 + tasklet_disable(np->tx_tasklet); 3228 + 3229 spin_lock_irq(&np->lock); 3230 3231 netif_stop_queue(dev); 3232 @@ -1890,6 +1994,9 @@ 3233 free_tbufs(dev); 3234 free_ring(dev); 3235 3236 + writeb(0x80, ioaddr + 0xa1); 3237 + pci_set_power_state(np->pdev, 3); 3238 + 3239 return 0; 3240 } 3241 3242 @@ -1897,6 +2004,7 @@ 3243 static void __devexit via_rhine_remove_one (struct pci_dev *pdev) 3244 { 3245 struct net_device *dev = pci_get_drvdata(pdev); 3246 + struct netdev_private *np = dev->priv; 3247 3248 unregister_netdev(dev); 3249 3250 @@ -1906,6 +2014,9 @@ 3251 iounmap((char *)(dev->base_addr)); 3252 #endif 3253 3254 + kfree(np->rx_tasklet); 3255 + kfree(np->tx_tasklet); 3256 + 3257 free_netdev(dev); 3258 pci_disable_device(pdev); 3259 pci_set_drvdata(pdev, NULL); 1754 3260 diff -NaurB linux-2.4.33.3/include/asm-mips/rb/rb500_korina.h linux-2.4.33.3.patched/include/asm-mips/rb/rb500_korina.h 1755 3261 --- linux-2.4.33.3/include/asm-mips/rb/rb500_korina.h 1970-01-01 01:00:00.000000000 +0100 1756 +++ linux-2.4.33.3.patched/include/asm-mips/rb/rb500_korina.h 2006-11-1 2 21:20:23.000000000 +01003262 +++ linux-2.4.33.3.patched/include/asm-mips/rb/rb500_korina.h 2006-11-15 10:33:51.000000000 +0100 1757 3263 @@ -0,0 +1,209 @@ 1758 3264 +/* $Id: pciacacia.h,v 1.5 2001/05/01 10:09:17 carstenl Exp $ … … 1965 3471 + 1966 3472 + 3473 diff -NaurB linux-2.4.33.3/net/ipv4/tcp_input.c linux-2.4.33.3.patched/net/ipv4/tcp_input.c 3474 --- linux-2.4.33.3/net/ipv4/tcp_input.c 2006-08-31 19:03:20.000000000 +0200 3475 +++ linux-2.4.33.3.patched/net/ipv4/tcp_input.c 2006-11-15 10:23:06.000000000 +0100 3476 @@ -70,6 +70,7 @@ 3477 #include <net/tcp.h> 3478 #include <net/inet_common.h> 3479 #include <linux/ipsec.h> 3480 +#include <asm/unaligned.h> 3481 3482 int sysctl_tcp_timestamps = 1; 3483 int sysctl_tcp_window_scaling = 1; 3484 @@ -2896,7 +2897,7 @@ 3485 switch(opcode) { 3486 case TCPOPT_MSS: 3487 if(opsize==TCPOLEN_MSS && th->syn && !estab) { 3488 - u16 in_mss = ntohs(*(__u16 *)ptr); 3489 + u16 in_mss = ntohs(get_unaligned((__u16 *)ptr)); 3490 if (in_mss) { 3491 if (tp->user_mss && tp->user_mss < in_mss) 3492 in_mss = tp->user_mss; 3493 @@ -2923,8 +2924,8 @@ 3494 if ((estab && tp->tstamp_ok) || 3495 (!estab && sysctl_tcp_timestamps)) { 3496 tp->saw_tstamp = 1; 3497 - tp->rcv_tsval = ntohl(*(__u32 *)ptr); 3498 - tp->rcv_tsecr = ntohl(*(__u32 *)(ptr+4)); 3499 + tp->rcv_tsval = ntohl(get_unaligned((__u32 *)ptr)); 3500 + tp->rcv_tsecr = ntohl(get_unaligned((__u32 *)(ptr+4))); 3501 } 3502 } 3503 break; 3504 @@ -2961,13 +2962,13 @@ 3505 } else if (tp->tstamp_ok && 3506 th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) { 3507 __u32 *ptr = (__u32 *)(th + 1); 3508 - if (*ptr == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) 3509 + if (get_unaligned(ptr) == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) 3510 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { 3511 tp->saw_tstamp = 1; 3512 ++ptr; 3513 - tp->rcv_tsval = ntohl(*ptr); 3514 + tp->rcv_tsval = ntohl(get_unaligned(ptr)); 3515 ++ptr; 3516 - tp->rcv_tsecr = ntohl(*ptr); 3517 + tp->rcv_tsecr = ntohl(get_unaligned(ptr)); 3518 return 1; 3519 } 3520 } 3521 @@ -4131,15 +4132,15 @@ 3522 __u32 *ptr = (__u32 *)(th + 1); 3523 3524 /* No? Slow path! */ 3525 - if (*ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) 3526 + if (get_unaligned(ptr) != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) 3527 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) 3528 goto slow_path; 3529 3530 tp->saw_tstamp = 1; 3531 ++ptr; 3532 - tp->rcv_tsval = ntohl(*ptr); 3533 + tp->rcv_tsval = ntohl(get_unaligned(ptr)); 3534 ++ptr; 3535 - tp->rcv_tsecr = ntohl(*ptr); 3536 + tp->rcv_tsecr = ntohl(get_unaligned(ptr)); 3537 3538 /* If PAWS failed, check it more carefully in slow path */ 3539 if ((s32)(tp->rcv_tsval - tp->ts_recent) < 0) -
target/linux/rb-2.4/patches/005-cfmips.patch
r7a23d2e re1e379b 1 1 diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/ata.c linux-2.4.33.3.patched/drivers/block/cf-mips/ata.c 2 2 --- linux-2.4.33.3/drivers/block/cf-mips/ata.c 1970-01-01 01:00:00.000000000 +0100 3 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.c 2006-11-1 2 23:46:19.000000000 +01004 @@ -0,0 +1,8 02 @@3 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.c 2006-11-15 10:42:47.000000000 +0100 4 @@ -0,0 +1,862 @@ 5 5 +#include <linux/kernel.h> /* printk() */ 6 6 +#include <linux/module.h> /* module to be loadable */ … … 14 14 +#include <asm/rc32434/dev.h> 15 15 +#include <asm/rc32434/gpio.h> 16 +#include <asm/rb/rb100.h> 16 17 + 17 18 +#include "ata.h" … … 31 32 +#define RC32434_IRQ_CFRDY (8 + 4 * 32 + RC32434_CF_GPIO_NUM) /* 149 */ 32 33 +static GPIO_t rcgpio = (GPIO_t)GPIO_VirtualAddress; 34 + 35 +/* CFRDY is connected to GPIO4/INTX_1 */ 36 +#define ADM5120_CF_GPIO_NUM 4 37 +#define ADM5120_CF_IRQ_LEVEL_BIT 0x20 /* GPIO4 = 0x20, GPIO2 = 0x10 */ 38 +#define ADM5120_IRQ_CFRDY INT_LVL_EXTIO_1 33 39 + 34 40 +static unsigned irq_cfrdy = 0; … … 104 110 +} 105 111 + 112 +static int 113 +adm5120_cfrdy(void) 114 +{ 115 + return ADM5120_SW_REG(GPIO_conf0_REG) & GPIO4_INPUT_MASK; 116 +} 117 + 106 118 +static void 107 119 +rc32434_prepare_cf_irq(void) … … 113 125 +} 114 126 + 127 +static void 128 +adm5120_prepare_cf_irq(void) 129 +{ 130 + /* interrupt on cf ready (not busy) */ 131 + ADM5120_INTC_REG(IRQ_LEVEL_REG) |= ADM5120_CF_IRQ_LEVEL_BIT; 132 + // FIXME: how to clear interrupt status? 133 +} 134 + 115 135 +static int 116 136 +init_cfdev_base(void) 117 137 +{ 118 + printk("RB500 CF\n"); 119 + DEV_t devt = (DEV_t)DEV_VirtualAddress; 120 + 121 + if (devt->dev[1].devmask == 0) { 122 + printk(KERN_ERR 123 + "DEV1 in Device Controller" 124 + " is not mapped anywhere!\n"); 138 + if (is_rb500()) { 139 + printk("RB500 CF\n"); 140 + DEV_t devt = (DEV_t)DEV_VirtualAddress; 141 + 142 + if (devt->dev[1].devmask == 0) { 143 + printk(KERN_ERR 144 + "DEV1 in Device Controller" 145 + " is not mapped anywhere!\n"); 146 + return 0; 147 + } 148 + /* setup CFRDY GPIO as input */ 149 + rcgpio->gpiofunc &= ~RC32434_CF_GPIO_BIT; 150 + rcgpio->gpiocfg &= ~RC32434_CF_GPIO_BIT; 151 + 152 + cfdev_base = devt->dev[1].devbase; 153 + cfrdy = &rc32434_cfrdy; 154 + prepare_cf_irq = &rc32434_prepare_cf_irq; 155 + irq_cfrdy = RC32434_IRQ_CFRDY; 156 + ilevel_addr = &rcgpio->gpioilevel; 157 + ilevel_bit = RC32434_CF_GPIO_BIT; 158 + 159 + printk(KERN_INFO 160 + "DC DEV1 base 0x%08lx ctrl 0x%08x tctrl 0x%08x" 161 + " cfrdy %d\n", 162 + cfdev_base, 163 + devt->dev[1].devc, 164 + devt->dev[1].devtc, 165 + (*cfrdy)()); 166 + } 167 + else if (is_rb100()) { 168 + printk("RB100 CF\n"); 169 + 170 + /* FIXME: enabling of EXTIO will be done by BIOS in future */ 171 + unsigned cmd = EXTIO_CS0_INT0_EN; 172 + /* on RB100 WAIT is LOW all the time => read will hang */ 173 + if (ADM5120_SW_REG(GPIO_conf0_REG) & GPIO0_INPUT_MASK) { 174 + cmd |= EXTIO_WAIT_EN; 175 + } 176 + ADM5120_SW_REG(GPIO_conf2_REG) = cmd; 177 + ADM5120_SW_REG(GPIO_conf0_REG) &= ~(1 << 178 + (16 + ADM5120_CF_GPIO_NUM)); 179 + 180 + /* FIXME: timings will be set by BIOS in future - remove this */ 181 + writel(0x88, KSEG1ADDR(MPMC_BASE) | MPMC_SM_CONFIG2_REG); 182 + writel(0x02, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITWEN2_REG); 183 + writel(0x03, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITOEN2_REG); 184 + writel(0x1a, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITRD2_REG); 185 + writel(0x1d, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITPAGE2_REG); 186 + writel(0x14, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITWR2_REG); 187 + writel(0x09, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITTURN2_REG); 188 + 189 + cfdev_base = EXTIO0_BASE; 190 + cfrdy = &adm5120_cfrdy; 191 + prepare_cf_irq = &adm5120_prepare_cf_irq; 192 + irq_cfrdy = ADM5120_IRQ_CFRDY; 193 + ilevel_addr = (volatile U32 *)(KSEG1ADDR(INTC_BASE + IRQ_LEVEL_REG)); 194 + ilevel_bit = ADM5120_CF_IRQ_LEVEL_BIT; 195 + 196 + printk(KERN_INFO 197 + "CF DEV base 0x%08lx cfrdy %d\n", 198 + cfdev_base, 199 + (*cfrdy)()); 200 + } 201 + else { 202 + printk(KERN_ERR "CF ERROR: unknown RouterBOARD type!\n"); 125 203 + return 0; 126 204 + } 127 + /* setup CFRDY GPIO as input */128 + rcgpio->gpiofunc &= ~RC32434_CF_GPIO_BIT;129 + rcgpio->gpiocfg &= ~RC32434_CF_GPIO_BIT;130 +131 + cfdev_base = devt->dev[1].devbase;132 + cfrdy = &rc32434_cfrdy;133 + prepare_cf_irq = &rc32434_prepare_cf_irq;134 + irq_cfrdy = RC32434_IRQ_CFRDY;135 + ilevel_addr = &rcgpio->gpioilevel;136 + ilevel_bit = RC32434_CF_GPIO_BIT;137 +138 + printk(KERN_INFO139 + "DC DEV1 base 0x%08lx ctrl 0x%08x tctrl 0x%08x"140 + " cfrdy %d\n",141 + cfdev_base,142 + devt->dev[1].devc,143 + devt->dev[1].devtc,144 + (*cfrdy)());145 205 + return 1; 146 206 +} … … 807 867 diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/ata.h linux-2.4.33.3.patched/drivers/block/cf-mips/ata.h 808 868 --- linux-2.4.33.3/drivers/block/cf-mips/ata.h 1970-01-01 01:00:00.000000000 +0100 809 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.h 2006-11-1 2 23:44:49.000000000 +0100869 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.h 2006-11-15 10:42:38.000000000 +0100 810 870 @@ -0,0 +1,70 @@ 811 871 +#ifndef __CFMIPS_ATA_H__ … … 881 941 diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/bdev.c linux-2.4.33.3.patched/drivers/block/cf-mips/bdev.c 882 942 --- linux-2.4.33.3/drivers/block/cf-mips/bdev.c 1970-01-01 01:00:00.000000000 +0100 883 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/bdev.c 2006-11-1 2 23:44:49.000000000 +0100884 @@ -0,0 +1,29 4@@943 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/bdev.c 2006-11-15 10:42:47.000000000 +0100 944 @@ -0,0 +1,298 @@ 885 945 +#include <linux/kernel.h> /* printk() */ 886 946 +#include <linux/module.h> /* module to be loadable */ … … 1064 1124 + DEBUGP(KERN_INFO "cf-mips module opened, minor %d\n", minor); 1065 1125 + MOD_INC_USE_COUNT; 1066 + GPIO_t gpiot = (GPIO_t)GPIO_VirtualAddress; 1067 + /* dirty workaround to set CFRDY GPIO as an input 1068 + * when some other program sets it as an output 1069 + */ 1070 + gpiot->gpiocfg &= ~(1 << 13); 1126 + if (is_rb500()) { 1127 + GPIO_t gpiot = (GPIO_t)GPIO_VirtualAddress; 1128 + /* dirty workaround to set CFRDY GPIO as an input 1129 + * when some other program sets it as an output 1130 + */ 1131 + gpiot->gpiocfg &= ~(1 << 13); 1132 + } 1071 1133 + return 0; /* success */ 1072 1134 +} … … 1107 1169 + int i; 1108 1170 + 1171 + if (!is_rb500() && !is_rb100()) return -1; 1172 + 1109 1173 + result = register_blkdev(MAJOR_NR, "cf-mips", &cf_bdops); 1110 1174 + if (result < 0) { … … 1179 1243 diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/Makefile linux-2.4.33.3.patched/drivers/block/cf-mips/Makefile 1180 1244 --- linux-2.4.33.3/drivers/block/cf-mips/Makefile 1970-01-01 01:00:00.000000000 +0100 1181 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/Makefile 2006-11-1 2 23:44:49.000000000 +01001245 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/Makefile 2006-11-15 10:42:38.000000000 +0100 1182 1246 @@ -0,0 +1,5 @@ 1183 1247 +O_TARGET := cf-mips.o … … 1188 1252 diff -NaurB linux-2.4.33.3/drivers/block/ll_rw_blk.c linux-2.4.33.3.patched/drivers/block/ll_rw_blk.c 1189 1253 --- linux-2.4.33.3/drivers/block/ll_rw_blk.c 2006-08-31 19:03:20.000000000 +0200 1190 +++ linux-2.4.33.3.patched/drivers/block/ll_rw_blk.c 2006-11-1 2 23:44:49.000000000 +01001254 +++ linux-2.4.33.3.patched/drivers/block/ll_rw_blk.c 2006-11-15 10:42:38.000000000 +0100 1191 1255 @@ -32,6 +32,8 @@ 1192 1256 #include <linux/slab.h> … … 1211 1275 diff -NaurB linux-2.4.33.3/drivers/block/Makefile linux-2.4.33.3.patched/drivers/block/Makefile 1212 1276 --- linux-2.4.33.3/drivers/block/Makefile 2006-08-31 19:03:20.000000000 +0200 1213 +++ linux-2.4.33.3.patched/drivers/block/Makefile 2006-11-1 2 23:44:49.000000000 +01001277 +++ linux-2.4.33.3.patched/drivers/block/Makefile 2006-11-15 10:42:38.000000000 +0100 1214 1278 @@ -32,7 +32,9 @@ 1215 1279 obj-$(CONFIG_BLK_DEV_UMEM) += umem.o … … 1223 1287 include $(TOPDIR)/Rules.make 1224 1288 diff -NaurB linux-2.4.33.3/init/do_mounts.c linux-2.4.33.3.patched/init/do_mounts.c 1225 --- linux-2.4.33.3/init/do_mounts.c 2006-11-1 2 23:43:16.000000000 +01001226 +++ linux-2.4.33.3.patched/init/do_mounts.c 2006-11-1 2 23:44:49.000000000 +01001289 --- linux-2.4.33.3/init/do_mounts.c 2006-11-15 10:12:12.000000000 +0100 1290 +++ linux-2.4.33.3.patched/init/do_mounts.c 2006-11-15 10:42:38.000000000 +0100 1227 1291 @@ -256,6 +256,7 @@ 1228 1292 { "ftld", 0x2c18 },
Note:
See TracChangeset
for help on using the changeset viewer.
