0001
0002
0003
0004
0005
0006 #include "gmac.h"
0007 #include "elmer0.h"
0008 #include "vsc7326_reg.h"
0009
0010
0011 #define STATS_TICK_SECS 15
0012
0013 #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
0014
0015
0016
0017
0018
0019
0020 #define WM_DISABLE 0x01a01fff
0021 #define WM_ENABLE 0x014a03F0
0022
0023 struct init_table {
0024 u32 addr;
0025 u32 data;
0026 };
0027
0028 struct _cmac_instance {
0029 u32 index;
0030 u32 ticks;
0031 };
0032
0033 #define INITBLOCK_SLEEP 0xffffffff
0034
0035 static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
0036 {
0037 u32 status, vlo, vhi;
0038 int i;
0039
0040 spin_lock_bh(&adapter->mac_lock);
0041 t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
0042 i = 0;
0043 do {
0044 t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
0045 t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
0046 status = (vhi << 16) | vlo;
0047 i++;
0048 } while (((status & 1) == 0) && (i < 50));
0049 if (i == 50)
0050 pr_err("Invalid tpi read from MAC, breaking loop.\n");
0051
0052 t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
0053 t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
0054
0055 *val = (vhi << 16) | vlo;
0056
0057
0058
0059
0060 spin_unlock_bh(&adapter->mac_lock);
0061 }
0062
0063 static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
0064 {
0065 spin_lock_bh(&adapter->mac_lock);
0066 t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF);
0067 t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF);
0068
0069
0070
0071 spin_unlock_bh(&adapter->mac_lock);
0072 }
0073
0074
0075 static void vsc7326_full_reset(adapter_t* adapter)
0076 {
0077 u32 val;
0078 u32 result = 0xffff;
0079
0080 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
0081 val &= ~1;
0082 t1_tpi_write(adapter, A_ELMER0_GPO, val);
0083 udelay(2);
0084 val |= 0x1;
0085 val |= 0x800;
0086 t1_tpi_write(adapter, A_ELMER0_GPO, val);
0087 mdelay(1);
0088 vsc_write(adapter, REG_SW_RESET, 0x80000001);
0089 do {
0090 mdelay(1);
0091 vsc_read(adapter, REG_SW_RESET, &result);
0092 } while (result != 0x0);
0093 }
0094
0095 static struct init_table vsc7326_reset[] = {
0096 { REG_IFACE_MODE, 0x00000000 },
0097 { REG_CRC_CFG, 0x00000020 },
0098 { REG_PLL_CLK_SPEED, 0x00050c00 },
0099 { REG_PLL_CLK_SPEED, 0x00050c00 },
0100 { REG_MSCH, 0x00002f14 },
0101 { REG_SPI4_MISC, 0x00040409 },
0102 { REG_SPI4_DESKEW, 0x00080000 },
0103 { REG_SPI4_ING_SETUP2, 0x08080004 },
0104 { REG_SPI4_ING_SETUP0, 0x04111004 },
0105 { REG_SPI4_EGR_SETUP0, 0x80001a04 },
0106 { REG_SPI4_ING_SETUP1, 0x02010000 },
0107 { REG_AGE_INC(0), 0x00000000 },
0108 { REG_AGE_INC(1), 0x00000000 },
0109 { REG_ING_CONTROL, 0x0a200011 },
0110 { REG_EGR_CONTROL, 0xa0010091 },
0111 };
0112
0113 static struct init_table vsc7326_portinit[4][22] = {
0114 {
0115
0116 { REG_DBG(0), 0x000004f0 },
0117 { REG_HDX(0), 0x00073101 },
0118 { REG_TEST(0,0), 0x00000022 },
0119 { REG_TEST(1,0), 0x00000022 },
0120 { REG_TOP_BOTTOM(0,0), 0x003f0000 },
0121 { REG_TOP_BOTTOM(1,0), 0x00120000 },
0122 { REG_HIGH_LOW_WM(0,0), 0x07460757 },
0123 { REG_HIGH_LOW_WM(1,0), WM_DISABLE },
0124 { REG_CT_THRHLD(0,0), 0x00000000 },
0125 { REG_CT_THRHLD(1,0), 0x00000000 },
0126 { REG_BUCKE(0), 0x0002ffff },
0127 { REG_BUCKI(0), 0x0002ffff },
0128 { REG_TEST(0,0), 0x00000020 },
0129 { REG_TEST(1,0), 0x00000020 },
0130
0131 { REG_MAX_LEN(0), 0x00002710 },
0132 { REG_PORT_FAIL(0), 0x00000002 },
0133 { REG_NORMALIZER(0), 0x00000a64 },
0134 { REG_DENORM(0), 0x00000010 },
0135 { REG_STICK_BIT(0), 0x03baa370 },
0136 { REG_DEV_SETUP(0), 0x00000083 },
0137 { REG_DEV_SETUP(0), 0x00000082 },
0138 { REG_MODE_CFG(0), 0x0200259f },
0139 },
0140 {
0141
0142 { REG_DBG(1), 0x000004f0 },
0143 { REG_HDX(1), 0x00073101 },
0144 { REG_TEST(0,1), 0x00000022 },
0145 { REG_TEST(1,1), 0x00000022 },
0146 { REG_TOP_BOTTOM(0,1), 0x007e003f },
0147 { REG_TOP_BOTTOM(1,1), 0x00240012 },
0148 { REG_HIGH_LOW_WM(0,1), 0x07460757 },
0149 { REG_HIGH_LOW_WM(1,1), WM_DISABLE },
0150 { REG_CT_THRHLD(0,1), 0x00000000 },
0151 { REG_CT_THRHLD(1,1), 0x00000000 },
0152 { REG_BUCKE(1), 0x0002ffff },
0153 { REG_BUCKI(1), 0x0002ffff },
0154 { REG_TEST(0,1), 0x00000020 },
0155 { REG_TEST(1,1), 0x00000020 },
0156
0157 { REG_MAX_LEN(1), 0x00002710 },
0158 { REG_PORT_FAIL(1), 0x00000002 },
0159 { REG_NORMALIZER(1), 0x00000a64 },
0160 { REG_DENORM(1), 0x00000010 },
0161 { REG_STICK_BIT(1), 0x03baa370 },
0162 { REG_DEV_SETUP(1), 0x00000083 },
0163 { REG_DEV_SETUP(1), 0x00000082 },
0164 { REG_MODE_CFG(1), 0x0200259f },
0165 },
0166 {
0167
0168 { REG_DBG(2), 0x000004f0 },
0169 { REG_HDX(2), 0x00073101 },
0170 { REG_TEST(0,2), 0x00000022 },
0171 { REG_TEST(1,2), 0x00000022 },
0172 { REG_TOP_BOTTOM(0,2), 0x00bd007e },
0173 { REG_TOP_BOTTOM(1,2), 0x00360024 },
0174 { REG_HIGH_LOW_WM(0,2), 0x07460757 },
0175 { REG_HIGH_LOW_WM(1,2), WM_DISABLE },
0176 { REG_CT_THRHLD(0,2), 0x00000000 },
0177 { REG_CT_THRHLD(1,2), 0x00000000 },
0178 { REG_BUCKE(2), 0x0002ffff },
0179 { REG_BUCKI(2), 0x0002ffff },
0180 { REG_TEST(0,2), 0x00000020 },
0181 { REG_TEST(1,2), 0x00000020 },
0182
0183 { REG_MAX_LEN(2), 0x00002710 },
0184 { REG_PORT_FAIL(2), 0x00000002 },
0185 { REG_NORMALIZER(2), 0x00000a64 },
0186 { REG_DENORM(2), 0x00000010 },
0187 { REG_STICK_BIT(2), 0x03baa370 },
0188 { REG_DEV_SETUP(2), 0x00000083 },
0189 { REG_DEV_SETUP(2), 0x00000082 },
0190 { REG_MODE_CFG(2), 0x0200259f },
0191 },
0192 {
0193
0194 { REG_DBG(3), 0x000004f0 },
0195 { REG_HDX(3), 0x00073101 },
0196 { REG_TEST(0,3), 0x00000022 },
0197 { REG_TEST(1,3), 0x00000022 },
0198 { REG_TOP_BOTTOM(0,3), 0x00fc00bd },
0199 { REG_TOP_BOTTOM(1,3), 0x00480036 },
0200 { REG_HIGH_LOW_WM(0,3), 0x07460757 },
0201 { REG_HIGH_LOW_WM(1,3), WM_DISABLE },
0202 { REG_CT_THRHLD(0,3), 0x00000000 },
0203 { REG_CT_THRHLD(1,3), 0x00000000 },
0204 { REG_BUCKE(3), 0x0002ffff },
0205 { REG_BUCKI(3), 0x0002ffff },
0206 { REG_TEST(0,3), 0x00000020 },
0207 { REG_TEST(1,3), 0x00000020 },
0208
0209 { REG_MAX_LEN(3), 0x00002710 },
0210 { REG_PORT_FAIL(3), 0x00000002 },
0211 { REG_NORMALIZER(3), 0x00000a64 },
0212 { REG_DENORM(3), 0x00000010 },
0213 { REG_STICK_BIT(3), 0x03baa370 },
0214 { REG_DEV_SETUP(3), 0x00000083 },
0215 { REG_DEV_SETUP(3), 0x00000082 },
0216 { REG_MODE_CFG(3), 0x0200259f },
0217 },
0218 };
0219
0220 static void run_table(adapter_t *adapter, struct init_table *ib, int len)
0221 {
0222 int i;
0223
0224 for (i = 0; i < len; i++) {
0225 if (ib[i].addr == INITBLOCK_SLEEP) {
0226 udelay( ib[i].data );
0227 pr_err("sleep %d us\n",ib[i].data);
0228 } else
0229 vsc_write( adapter, ib[i].addr, ib[i].data );
0230 }
0231 }
0232
0233 static int bist_rd(adapter_t *adapter, int moduleid, int address)
0234 {
0235 int data = 0;
0236 u32 result = 0;
0237
0238 if ((address != 0x0) &&
0239 (address != 0x1) &&
0240 (address != 0x2) &&
0241 (address != 0xd) &&
0242 (address != 0xe))
0243 pr_err("No bist address: 0x%x\n", address);
0244
0245 data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
0246 ((moduleid & 0xff) << 0));
0247 vsc_write(adapter, REG_RAM_BIST_CMD, data);
0248
0249 udelay(10);
0250
0251 vsc_read(adapter, REG_RAM_BIST_RESULT, &result);
0252 if ((result & (1 << 9)) != 0x0)
0253 pr_err("Still in bist read: 0x%x\n", result);
0254 else if ((result & (1 << 8)) != 0x0)
0255 pr_err("bist read error: 0x%x\n", result);
0256
0257 return result & 0xff;
0258 }
0259
0260 static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
0261 {
0262 int data = 0;
0263 u32 result = 0;
0264
0265 if ((address != 0x0) &&
0266 (address != 0x1) &&
0267 (address != 0x2) &&
0268 (address != 0xd) &&
0269 (address != 0xe))
0270 pr_err("No bist address: 0x%x\n", address);
0271
0272 if (value > 255)
0273 pr_err("Suspicious write out of range value: 0x%x\n", value);
0274
0275 data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
0276 ((moduleid & 0xff) << 0));
0277 vsc_write(adapter, REG_RAM_BIST_CMD, data);
0278
0279 udelay(5);
0280
0281 vsc_read(adapter, REG_RAM_BIST_CMD, &result);
0282 if ((result & (1 << 27)) != 0x0)
0283 pr_err("Still in bist write: 0x%x\n", result);
0284 else if ((result & (1 << 26)) != 0x0)
0285 pr_err("bist write error: 0x%x\n", result);
0286
0287 return 0;
0288 }
0289
0290 static int run_bist(adapter_t *adapter, int moduleid)
0291 {
0292
0293 (void) bist_wr(adapter,moduleid, 0x00, 0x02);
0294 (void) bist_wr(adapter,moduleid, 0x01, 0x01);
0295
0296 return 0;
0297 }
0298
0299 static int check_bist(adapter_t *adapter, int moduleid)
0300 {
0301 int result=0;
0302 int column=0;
0303
0304 result = bist_rd(adapter,moduleid, 0x02);
0305 column = ((bist_rd(adapter,moduleid, 0x0e)<<8) +
0306 (bist_rd(adapter,moduleid, 0x0d)));
0307 if ((result & 3) != 0x3)
0308 pr_err("Result: 0x%x BIST error in ram %d, column: 0x%04x\n",
0309 result, moduleid, column);
0310 return 0;
0311 }
0312
0313 static int enable_mem(adapter_t *adapter, int moduleid)
0314 {
0315
0316 (void) bist_wr(adapter,moduleid, 0x00, 0x00);
0317 return 0;
0318 }
0319
0320 static int run_bist_all(adapter_t *adapter)
0321 {
0322 int port = 0;
0323 u32 val = 0;
0324
0325 vsc_write(adapter, REG_MEM_BIST, 0x5);
0326 vsc_read(adapter, REG_MEM_BIST, &val);
0327
0328 for (port = 0; port < 12; port++)
0329 vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
0330
0331 udelay(300);
0332 vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
0333 udelay(300);
0334
0335 (void) run_bist(adapter,13);
0336 (void) run_bist(adapter,14);
0337 (void) run_bist(adapter,20);
0338 (void) run_bist(adapter,21);
0339 mdelay(200);
0340 (void) check_bist(adapter,13);
0341 (void) check_bist(adapter,14);
0342 (void) check_bist(adapter,20);
0343 (void) check_bist(adapter,21);
0344 udelay(100);
0345 (void) enable_mem(adapter,13);
0346 (void) enable_mem(adapter,14);
0347 (void) enable_mem(adapter,20);
0348 (void) enable_mem(adapter,21);
0349 udelay(300);
0350 vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
0351 udelay(300);
0352 for (port = 0; port < 12; port++)
0353 vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
0354
0355 udelay(300);
0356 vsc_write(adapter, REG_MEM_BIST, 0x0);
0357 mdelay(10);
0358 return 0;
0359 }
0360
0361 static int mac_intr_handler(struct cmac *mac)
0362 {
0363 return 0;
0364 }
0365
0366 static int mac_intr_enable(struct cmac *mac)
0367 {
0368 return 0;
0369 }
0370
0371 static int mac_intr_disable(struct cmac *mac)
0372 {
0373 return 0;
0374 }
0375
0376 static int mac_intr_clear(struct cmac *mac)
0377 {
0378 return 0;
0379 }
0380
0381
0382 static int mac_set_address(struct cmac* mac, const u8 addr[6])
0383 {
0384 u32 val;
0385 int port = mac->instance->index;
0386
0387 vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port),
0388 (addr[3] << 16) | (addr[4] << 8) | addr[5]);
0389 vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port),
0390 (addr[0] << 16) | (addr[1] << 8) | addr[2]);
0391
0392 vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
0393 val &= ~0xf0000000;
0394 vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
0395
0396 vsc_write(mac->adapter, REG_ING_FFILT_MASK0,
0397 0xffff0000 | (addr[4] << 8) | addr[5]);
0398 vsc_write(mac->adapter, REG_ING_FFILT_MASK1,
0399 0xffff0000 | (addr[2] << 8) | addr[3]);
0400 vsc_write(mac->adapter, REG_ING_FFILT_MASK2,
0401 0xffff0000 | (addr[0] << 8) | addr[1]);
0402 return 0;
0403 }
0404
0405 static int mac_get_address(struct cmac *mac, u8 addr[6])
0406 {
0407 u32 addr_lo, addr_hi;
0408 int port = mac->instance->index;
0409
0410 vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
0411 vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
0412
0413 addr[0] = (u8) (addr_hi >> 16);
0414 addr[1] = (u8) (addr_hi >> 8);
0415 addr[2] = (u8) addr_hi;
0416 addr[3] = (u8) (addr_lo >> 16);
0417 addr[4] = (u8) (addr_lo >> 8);
0418 addr[5] = (u8) addr_lo;
0419 return 0;
0420 }
0421
0422
0423 static int mac_reset(struct cmac *mac)
0424 {
0425 int index = mac->instance->index;
0426
0427 run_table(mac->adapter, vsc7326_portinit[index],
0428 ARRAY_SIZE(vsc7326_portinit[index]));
0429
0430 return 0;
0431 }
0432
0433 static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
0434 {
0435 u32 v;
0436 int port = mac->instance->index;
0437
0438 vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
0439 v |= 1 << 12;
0440
0441 if (t1_rx_mode_promisc(rm))
0442 v &= ~(1 << (port + 16));
0443 else
0444 v |= 1 << (port + 16);
0445
0446 vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
0447 return 0;
0448 }
0449
0450 static int mac_set_mtu(struct cmac *mac, int mtu)
0451 {
0452 int port = mac->instance->index;
0453
0454
0455 vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
0456 return 0;
0457 }
0458
0459 static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
0460 int fc)
0461 {
0462 u32 v;
0463 int enable, port = mac->instance->index;
0464
0465 if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 &&
0466 speed != SPEED_1000)
0467 return -1;
0468 if (duplex > 0 && duplex != DUPLEX_FULL)
0469 return -1;
0470
0471 if (speed >= 0) {
0472 vsc_read(mac->adapter, REG_MODE_CFG(port), &v);
0473 enable = v & 3;
0474 v &= ~0xf;
0475 v |= 4;
0476 if (speed == SPEED_1000)
0477 v |= 8;
0478 enable |= v;
0479 vsc_write(mac->adapter, REG_MODE_CFG(port), v);
0480
0481 if (speed == SPEED_1000)
0482 v = 0x82;
0483 else if (speed == SPEED_100)
0484 v = 0x84;
0485 else
0486 v = 0x86;
0487 vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1);
0488 vsc_write(mac->adapter, REG_DEV_SETUP(port), v);
0489 vsc_read(mac->adapter, REG_DBG(port), &v);
0490 v &= ~0xff00;
0491 if (speed == SPEED_1000)
0492 v |= 0x400;
0493 else if (speed == SPEED_100)
0494 v |= 0x2000;
0495 else
0496 v |= 0xff00;
0497 vsc_write(mac->adapter, REG_DBG(port), v);
0498
0499 vsc_write(mac->adapter, REG_TX_IFG(port),
0500 speed == SPEED_1000 ? 5 : 0x11);
0501 if (duplex == DUPLEX_HALF)
0502 enable = 0x0;
0503 else if (speed == SPEED_1000)
0504 enable = 0xc;
0505 else
0506 enable = 0x4;
0507 enable |= 0x9 << 10;
0508 enable |= 0x6 << 6;
0509 enable |= 0x1 << 4;
0510 enable |= 0x3;
0511 vsc_write(mac->adapter, REG_MODE_CFG(port), enable);
0512
0513 }
0514
0515 vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
0516 v &= 0xfff0ffff;
0517 v |= 0x20000;
0518 if (fc & PAUSE_RX)
0519 v |= 0x40000;
0520 if (fc & PAUSE_TX)
0521 v |= 0x80000;
0522 if (fc == (PAUSE_RX | PAUSE_TX))
0523 v |= 0x10000;
0524 vsc_write(mac->adapter, REG_PAUSE_CFG(port), v);
0525 return 0;
0526 }
0527
0528 static int mac_enable(struct cmac *mac, int which)
0529 {
0530 u32 val;
0531 int port = mac->instance->index;
0532
0533
0534 vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE);
0535
0536 vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
0537 if (which & MAC_DIRECTION_RX)
0538 val |= 0x2;
0539 if (which & MAC_DIRECTION_TX)
0540 val |= 1;
0541 vsc_write(mac->adapter, REG_MODE_CFG(port), val);
0542 return 0;
0543 }
0544
0545 static int mac_disable(struct cmac *mac, int which)
0546 {
0547 u32 val;
0548 int i, port = mac->instance->index;
0549
0550
0551 mac_reset(mac);
0552
0553 vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
0554 if (which & MAC_DIRECTION_RX)
0555 val &= ~0x2;
0556 if (which & MAC_DIRECTION_TX)
0557 val &= ~0x1;
0558 vsc_write(mac->adapter, REG_MODE_CFG(port), val);
0559 vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
0560
0561
0562 for (i = 0; i <= 0x3a; ++i)
0563 vsc_write(mac->adapter, CRA(4, port, i), 0);
0564
0565
0566 memset(&mac->stats, 0, sizeof(struct cmac_statistics));
0567
0568 return 0;
0569 }
0570
0571 static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat)
0572 {
0573 u32 v, lo;
0574
0575 vsc_read(mac->adapter, addr, &v);
0576 lo = *stat;
0577 *stat = *stat - lo + v;
0578
0579 if (v == 0)
0580 return;
0581
0582 if (v < lo)
0583 *stat += (1ULL << 32);
0584 }
0585
0586 static void port_stats_update(struct cmac *mac)
0587 {
0588 struct {
0589 unsigned int reg;
0590 unsigned int offset;
0591 } hw_stats[] = {
0592
0593 #define HW_STAT(reg, stat_name) \
0594 { reg, offsetof(struct cmac_statistics, stat_name) / sizeof(u64) }
0595
0596
0597 HW_STAT(RxUnicast, RxUnicastFramesOK),
0598 HW_STAT(RxMulticast, RxMulticastFramesOK),
0599 HW_STAT(RxBroadcast, RxBroadcastFramesOK),
0600 HW_STAT(Crc, RxFCSErrors),
0601 HW_STAT(RxAlignment, RxAlignErrors),
0602 HW_STAT(RxOversize, RxFrameTooLongErrors),
0603 HW_STAT(RxPause, RxPauseFrames),
0604 HW_STAT(RxJabbers, RxJabberErrors),
0605 HW_STAT(RxFragments, RxRuntErrors),
0606 HW_STAT(RxUndersize, RxRuntErrors),
0607 HW_STAT(RxSymbolCarrier, RxSymbolErrors),
0608 HW_STAT(RxSize1519ToMax, RxJumboFramesOK),
0609
0610
0611 HW_STAT(TxUnicast, TxUnicastFramesOK),
0612 HW_STAT(TxMulticast, TxMulticastFramesOK),
0613 HW_STAT(TxBroadcast, TxBroadcastFramesOK),
0614 HW_STAT(TxPause, TxPauseFrames),
0615 HW_STAT(TxUnderrun, TxUnderrun),
0616 HW_STAT(TxSize1519ToMax, TxJumboFramesOK),
0617 }, *p = hw_stats;
0618 unsigned int port = mac->instance->index;
0619 u64 *stats = (u64 *)&mac->stats;
0620 unsigned int i;
0621
0622 for (i = 0; i < ARRAY_SIZE(hw_stats); i++)
0623 rmon_update(mac, CRA(0x4, port, p->reg), stats + p->offset);
0624
0625 rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK);
0626 rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK);
0627 rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad);
0628 }
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639 static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
0640 int flag)
0641 {
0642 if (flag == MAC_STATS_UPDATE_FULL ||
0643 mac->instance->ticks >= MAJOR_UPDATE_TICKS) {
0644 port_stats_update(mac);
0645 mac->instance->ticks = 0;
0646 } else {
0647 int port = mac->instance->index;
0648
0649 rmon_update(mac, REG_RX_OK_BYTES(port),
0650 &mac->stats.RxOctetsOK);
0651 rmon_update(mac, REG_RX_BAD_BYTES(port),
0652 &mac->stats.RxOctetsBad);
0653 rmon_update(mac, REG_TX_OK_BYTES(port),
0654 &mac->stats.TxOctetsOK);
0655 mac->instance->ticks++;
0656 }
0657 return &mac->stats;
0658 }
0659
0660 static void mac_destroy(struct cmac *mac)
0661 {
0662 kfree(mac);
0663 }
0664
0665 static const struct cmac_ops vsc7326_ops = {
0666 .destroy = mac_destroy,
0667 .reset = mac_reset,
0668 .interrupt_handler = mac_intr_handler,
0669 .interrupt_enable = mac_intr_enable,
0670 .interrupt_disable = mac_intr_disable,
0671 .interrupt_clear = mac_intr_clear,
0672 .enable = mac_enable,
0673 .disable = mac_disable,
0674 .set_mtu = mac_set_mtu,
0675 .set_rx_mode = mac_set_rx_mode,
0676 .set_speed_duplex_fc = mac_set_speed_duplex_fc,
0677 .statistics_update = mac_update_statistics,
0678 .macaddress_get = mac_get_address,
0679 .macaddress_set = mac_set_address,
0680 };
0681
0682 static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index)
0683 {
0684 struct cmac *mac;
0685 u32 val;
0686 int i;
0687
0688 mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
0689 if (!mac)
0690 return NULL;
0691
0692 mac->ops = &vsc7326_ops;
0693 mac->instance = (cmac_instance *)(mac + 1);
0694 mac->adapter = adapter;
0695
0696 mac->instance->index = index;
0697 mac->instance->ticks = 0;
0698
0699 i = 0;
0700 do {
0701 u32 vhi, vlo;
0702
0703 vhi = vlo = 0;
0704 t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
0705 udelay(1);
0706 t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
0707 udelay(5);
0708 val = (vhi << 16) | vlo;
0709 } while ((++i < 10000) && (val == 0xffffffff));
0710
0711 return mac;
0712 }
0713
0714 static int vsc7326_mac_reset(adapter_t *adapter)
0715 {
0716 vsc7326_full_reset(adapter);
0717 (void) run_bist_all(adapter);
0718 run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset));
0719 return 0;
0720 }
0721
0722 const struct gmac t1_vsc7326_ops = {
0723 .stats_update_period = STATS_TICK_SECS,
0724 .create = vsc7326_mac_create,
0725 .reset = vsc7326_mac_reset,
0726 };