PageRenderTime 29ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/net/ethernet/chelsio/cxgb/vsc7326.c

https://bitbucket.org/advance38/linux
C | 730 lines | 582 code | 103 blank | 45 comment | 87 complexity | b02efcee598e0e6d03c07ea65c72df98 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */
  2. /* Driver for Vitesse VSC7326 (Schaumburg) MAC */
  3. #include "gmac.h"
  4. #include "elmer0.h"
  5. #include "vsc7326_reg.h"
  6. /* Update fast changing statistics every 15 seconds */
  7. #define STATS_TICK_SECS 15
  8. /* 30 minutes for full statistics update */
  9. #define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS)
  10. #define MAX_MTU 9600
  11. /* The egress WM value 0x01a01fff should be used only when the
  12. * interface is down (MAC port disabled). This is a workaround
  13. * for disabling the T2/MAC flow-control. When the interface is
  14. * enabled, the WM value should be set to 0x014a03F0.
  15. */
  16. #define WM_DISABLE 0x01a01fff
  17. #define WM_ENABLE 0x014a03F0
  18. struct init_table {
  19. u32 addr;
  20. u32 data;
  21. };
  22. struct _cmac_instance {
  23. u32 index;
  24. u32 ticks;
  25. };
  26. #define INITBLOCK_SLEEP 0xffffffff
  27. static void vsc_read(adapter_t *adapter, u32 addr, u32 *val)
  28. {
  29. u32 status, vlo, vhi;
  30. int i;
  31. spin_lock_bh(&adapter->mac_lock);
  32. t1_tpi_read(adapter, (addr << 2) + 4, &vlo);
  33. i = 0;
  34. do {
  35. t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
  36. t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
  37. status = (vhi << 16) | vlo;
  38. i++;
  39. } while (((status & 1) == 0) && (i < 50));
  40. if (i == 50)
  41. pr_err("Invalid tpi read from MAC, breaking loop.\n");
  42. t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo);
  43. t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi);
  44. *val = (vhi << 16) | vlo;
  45. /* pr_err("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
  46. ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
  47. ((addr&0x01fe)>>1), *val); */
  48. spin_unlock_bh(&adapter->mac_lock);
  49. }
  50. static void vsc_write(adapter_t *adapter, u32 addr, u32 data)
  51. {
  52. spin_lock_bh(&adapter->mac_lock);
  53. t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF);
  54. t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF);
  55. /* pr_err("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n",
  56. ((addr&0xe000)>>13), ((addr&0x1e00)>>9),
  57. ((addr&0x01fe)>>1), data); */
  58. spin_unlock_bh(&adapter->mac_lock);
  59. }
  60. /* Hard reset the MAC. This wipes out *all* configuration. */
  61. static void vsc7326_full_reset(adapter_t* adapter)
  62. {
  63. u32 val;
  64. u32 result = 0xffff;
  65. t1_tpi_read(adapter, A_ELMER0_GPO, &val);
  66. val &= ~1;
  67. t1_tpi_write(adapter, A_ELMER0_GPO, val);
  68. udelay(2);
  69. val |= 0x1; /* Enable mac MAC itself */
  70. val |= 0x800; /* Turn off the red LED */
  71. t1_tpi_write(adapter, A_ELMER0_GPO, val);
  72. mdelay(1);
  73. vsc_write(adapter, REG_SW_RESET, 0x80000001);
  74. do {
  75. mdelay(1);
  76. vsc_read(adapter, REG_SW_RESET, &result);
  77. } while (result != 0x0);
  78. }
  79. static struct init_table vsc7326_reset[] = {
  80. { REG_IFACE_MODE, 0x00000000 },
  81. { REG_CRC_CFG, 0x00000020 },
  82. { REG_PLL_CLK_SPEED, 0x00050c00 },
  83. { REG_PLL_CLK_SPEED, 0x00050c00 },
  84. { REG_MSCH, 0x00002f14 },
  85. { REG_SPI4_MISC, 0x00040409 },
  86. { REG_SPI4_DESKEW, 0x00080000 },
  87. { REG_SPI4_ING_SETUP2, 0x08080004 },
  88. { REG_SPI4_ING_SETUP0, 0x04111004 },
  89. { REG_SPI4_EGR_SETUP0, 0x80001a04 },
  90. { REG_SPI4_ING_SETUP1, 0x02010000 },
  91. { REG_AGE_INC(0), 0x00000000 },
  92. { REG_AGE_INC(1), 0x00000000 },
  93. { REG_ING_CONTROL, 0x0a200011 },
  94. { REG_EGR_CONTROL, 0xa0010091 },
  95. };
  96. static struct init_table vsc7326_portinit[4][22] = {
  97. { /* Port 0 */
  98. /* FIFO setup */
  99. { REG_DBG(0), 0x000004f0 },
  100. { REG_HDX(0), 0x00073101 },
  101. { REG_TEST(0,0), 0x00000022 },
  102. { REG_TEST(1,0), 0x00000022 },
  103. { REG_TOP_BOTTOM(0,0), 0x003f0000 },
  104. { REG_TOP_BOTTOM(1,0), 0x00120000 },
  105. { REG_HIGH_LOW_WM(0,0), 0x07460757 },
  106. { REG_HIGH_LOW_WM(1,0), WM_DISABLE },
  107. { REG_CT_THRHLD(0,0), 0x00000000 },
  108. { REG_CT_THRHLD(1,0), 0x00000000 },
  109. { REG_BUCKE(0), 0x0002ffff },
  110. { REG_BUCKI(0), 0x0002ffff },
  111. { REG_TEST(0,0), 0x00000020 },
  112. { REG_TEST(1,0), 0x00000020 },
  113. /* Port config */
  114. { REG_MAX_LEN(0), 0x00002710 },
  115. { REG_PORT_FAIL(0), 0x00000002 },
  116. { REG_NORMALIZER(0), 0x00000a64 },
  117. { REG_DENORM(0), 0x00000010 },
  118. { REG_STICK_BIT(0), 0x03baa370 },
  119. { REG_DEV_SETUP(0), 0x00000083 },
  120. { REG_DEV_SETUP(0), 0x00000082 },
  121. { REG_MODE_CFG(0), 0x0200259f },
  122. },
  123. { /* Port 1 */
  124. /* FIFO setup */
  125. { REG_DBG(1), 0x000004f0 },
  126. { REG_HDX(1), 0x00073101 },
  127. { REG_TEST(0,1), 0x00000022 },
  128. { REG_TEST(1,1), 0x00000022 },
  129. { REG_TOP_BOTTOM(0,1), 0x007e003f },
  130. { REG_TOP_BOTTOM(1,1), 0x00240012 },
  131. { REG_HIGH_LOW_WM(0,1), 0x07460757 },
  132. { REG_HIGH_LOW_WM(1,1), WM_DISABLE },
  133. { REG_CT_THRHLD(0,1), 0x00000000 },
  134. { REG_CT_THRHLD(1,1), 0x00000000 },
  135. { REG_BUCKE(1), 0x0002ffff },
  136. { REG_BUCKI(1), 0x0002ffff },
  137. { REG_TEST(0,1), 0x00000020 },
  138. { REG_TEST(1,1), 0x00000020 },
  139. /* Port config */
  140. { REG_MAX_LEN(1), 0x00002710 },
  141. { REG_PORT_FAIL(1), 0x00000002 },
  142. { REG_NORMALIZER(1), 0x00000a64 },
  143. { REG_DENORM(1), 0x00000010 },
  144. { REG_STICK_BIT(1), 0x03baa370 },
  145. { REG_DEV_SETUP(1), 0x00000083 },
  146. { REG_DEV_SETUP(1), 0x00000082 },
  147. { REG_MODE_CFG(1), 0x0200259f },
  148. },
  149. { /* Port 2 */
  150. /* FIFO setup */
  151. { REG_DBG(2), 0x000004f0 },
  152. { REG_HDX(2), 0x00073101 },
  153. { REG_TEST(0,2), 0x00000022 },
  154. { REG_TEST(1,2), 0x00000022 },
  155. { REG_TOP_BOTTOM(0,2), 0x00bd007e },
  156. { REG_TOP_BOTTOM(1,2), 0x00360024 },
  157. { REG_HIGH_LOW_WM(0,2), 0x07460757 },
  158. { REG_HIGH_LOW_WM(1,2), WM_DISABLE },
  159. { REG_CT_THRHLD(0,2), 0x00000000 },
  160. { REG_CT_THRHLD(1,2), 0x00000000 },
  161. { REG_BUCKE(2), 0x0002ffff },
  162. { REG_BUCKI(2), 0x0002ffff },
  163. { REG_TEST(0,2), 0x00000020 },
  164. { REG_TEST(1,2), 0x00000020 },
  165. /* Port config */
  166. { REG_MAX_LEN(2), 0x00002710 },
  167. { REG_PORT_FAIL(2), 0x00000002 },
  168. { REG_NORMALIZER(2), 0x00000a64 },
  169. { REG_DENORM(2), 0x00000010 },
  170. { REG_STICK_BIT(2), 0x03baa370 },
  171. { REG_DEV_SETUP(2), 0x00000083 },
  172. { REG_DEV_SETUP(2), 0x00000082 },
  173. { REG_MODE_CFG(2), 0x0200259f },
  174. },
  175. { /* Port 3 */
  176. /* FIFO setup */
  177. { REG_DBG(3), 0x000004f0 },
  178. { REG_HDX(3), 0x00073101 },
  179. { REG_TEST(0,3), 0x00000022 },
  180. { REG_TEST(1,3), 0x00000022 },
  181. { REG_TOP_BOTTOM(0,3), 0x00fc00bd },
  182. { REG_TOP_BOTTOM(1,3), 0x00480036 },
  183. { REG_HIGH_LOW_WM(0,3), 0x07460757 },
  184. { REG_HIGH_LOW_WM(1,3), WM_DISABLE },
  185. { REG_CT_THRHLD(0,3), 0x00000000 },
  186. { REG_CT_THRHLD(1,3), 0x00000000 },
  187. { REG_BUCKE(3), 0x0002ffff },
  188. { REG_BUCKI(3), 0x0002ffff },
  189. { REG_TEST(0,3), 0x00000020 },
  190. { REG_TEST(1,3), 0x00000020 },
  191. /* Port config */
  192. { REG_MAX_LEN(3), 0x00002710 },
  193. { REG_PORT_FAIL(3), 0x00000002 },
  194. { REG_NORMALIZER(3), 0x00000a64 },
  195. { REG_DENORM(3), 0x00000010 },
  196. { REG_STICK_BIT(3), 0x03baa370 },
  197. { REG_DEV_SETUP(3), 0x00000083 },
  198. { REG_DEV_SETUP(3), 0x00000082 },
  199. { REG_MODE_CFG(3), 0x0200259f },
  200. },
  201. };
  202. static void run_table(adapter_t *adapter, struct init_table *ib, int len)
  203. {
  204. int i;
  205. for (i = 0; i < len; i++) {
  206. if (ib[i].addr == INITBLOCK_SLEEP) {
  207. udelay( ib[i].data );
  208. pr_err("sleep %d us\n",ib[i].data);
  209. } else
  210. vsc_write( adapter, ib[i].addr, ib[i].data );
  211. }
  212. }
  213. static int bist_rd(adapter_t *adapter, int moduleid, int address)
  214. {
  215. int data = 0;
  216. u32 result = 0;
  217. if ((address != 0x0) &&
  218. (address != 0x1) &&
  219. (address != 0x2) &&
  220. (address != 0xd) &&
  221. (address != 0xe))
  222. pr_err("No bist address: 0x%x\n", address);
  223. data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) |
  224. ((moduleid & 0xff) << 0));
  225. vsc_write(adapter, REG_RAM_BIST_CMD, data);
  226. udelay(10);
  227. vsc_read(adapter, REG_RAM_BIST_RESULT, &result);
  228. if ((result & (1 << 9)) != 0x0)
  229. pr_err("Still in bist read: 0x%x\n", result);
  230. else if ((result & (1 << 8)) != 0x0)
  231. pr_err("bist read error: 0x%x\n", result);
  232. return result & 0xff;
  233. }
  234. static int bist_wr(adapter_t *adapter, int moduleid, int address, int value)
  235. {
  236. int data = 0;
  237. u32 result = 0;
  238. if ((address != 0x0) &&
  239. (address != 0x1) &&
  240. (address != 0x2) &&
  241. (address != 0xd) &&
  242. (address != 0xe))
  243. pr_err("No bist address: 0x%x\n", address);
  244. if (value > 255)
  245. pr_err("Suspicious write out of range value: 0x%x\n", value);
  246. data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) |
  247. ((moduleid & 0xff) << 0));
  248. vsc_write(adapter, REG_RAM_BIST_CMD, data);
  249. udelay(5);
  250. vsc_read(adapter, REG_RAM_BIST_CMD, &result);
  251. if ((result & (1 << 27)) != 0x0)
  252. pr_err("Still in bist write: 0x%x\n", result);
  253. else if ((result & (1 << 26)) != 0x0)
  254. pr_err("bist write error: 0x%x\n", result);
  255. return 0;
  256. }
  257. static int run_bist(adapter_t *adapter, int moduleid)
  258. {
  259. /*run bist*/
  260. (void) bist_wr(adapter,moduleid, 0x00, 0x02);
  261. (void) bist_wr(adapter,moduleid, 0x01, 0x01);
  262. return 0;
  263. }
  264. static int check_bist(adapter_t *adapter, int moduleid)
  265. {
  266. int result=0;
  267. int column=0;
  268. /*check bist*/
  269. result = bist_rd(adapter,moduleid, 0x02);
  270. column = ((bist_rd(adapter,moduleid, 0x0e)<<8) +
  271. (bist_rd(adapter,moduleid, 0x0d)));
  272. if ((result & 3) != 0x3)
  273. pr_err("Result: 0x%x BIST error in ram %d, column: 0x%04x\n",
  274. result, moduleid, column);
  275. return 0;
  276. }
  277. static int enable_mem(adapter_t *adapter, int moduleid)
  278. {
  279. /*enable mem*/
  280. (void) bist_wr(adapter,moduleid, 0x00, 0x00);
  281. return 0;
  282. }
  283. static int run_bist_all(adapter_t *adapter)
  284. {
  285. int port = 0;
  286. u32 val = 0;
  287. vsc_write(adapter, REG_MEM_BIST, 0x5);
  288. vsc_read(adapter, REG_MEM_BIST, &val);
  289. for (port = 0; port < 12; port++)
  290. vsc_write(adapter, REG_DEV_SETUP(port), 0x0);
  291. udelay(300);
  292. vsc_write(adapter, REG_SPI4_MISC, 0x00040409);
  293. udelay(300);
  294. (void) run_bist(adapter,13);
  295. (void) run_bist(adapter,14);
  296. (void) run_bist(adapter,20);
  297. (void) run_bist(adapter,21);
  298. mdelay(200);
  299. (void) check_bist(adapter,13);
  300. (void) check_bist(adapter,14);
  301. (void) check_bist(adapter,20);
  302. (void) check_bist(adapter,21);
  303. udelay(100);
  304. (void) enable_mem(adapter,13);
  305. (void) enable_mem(adapter,14);
  306. (void) enable_mem(adapter,20);
  307. (void) enable_mem(adapter,21);
  308. udelay(300);
  309. vsc_write(adapter, REG_SPI4_MISC, 0x60040400);
  310. udelay(300);
  311. for (port = 0; port < 12; port++)
  312. vsc_write(adapter, REG_DEV_SETUP(port), 0x1);
  313. udelay(300);
  314. vsc_write(adapter, REG_MEM_BIST, 0x0);
  315. mdelay(10);
  316. return 0;
  317. }
  318. static int mac_intr_handler(struct cmac *mac)
  319. {
  320. return 0;
  321. }
  322. static int mac_intr_enable(struct cmac *mac)
  323. {
  324. return 0;
  325. }
  326. static int mac_intr_disable(struct cmac *mac)
  327. {
  328. return 0;
  329. }
  330. static int mac_intr_clear(struct cmac *mac)
  331. {
  332. return 0;
  333. }
  334. /* Expect MAC address to be in network byte order. */
  335. static int mac_set_address(struct cmac* mac, u8 addr[6])
  336. {
  337. u32 val;
  338. int port = mac->instance->index;
  339. vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port),
  340. (addr[3] << 16) | (addr[4] << 8) | addr[5]);
  341. vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port),
  342. (addr[0] << 16) | (addr[1] << 8) | addr[2]);
  343. vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val);
  344. val &= ~0xf0000000;
  345. vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28));
  346. vsc_write(mac->adapter, REG_ING_FFILT_MASK0,
  347. 0xffff0000 | (addr[4] << 8) | addr[5]);
  348. vsc_write(mac->adapter, REG_ING_FFILT_MASK1,
  349. 0xffff0000 | (addr[2] << 8) | addr[3]);
  350. vsc_write(mac->adapter, REG_ING_FFILT_MASK2,
  351. 0xffff0000 | (addr[0] << 8) | addr[1]);
  352. return 0;
  353. }
  354. static int mac_get_address(struct cmac *mac, u8 addr[6])
  355. {
  356. u32 addr_lo, addr_hi;
  357. int port = mac->instance->index;
  358. vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo);
  359. vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi);
  360. addr[0] = (u8) (addr_hi >> 16);
  361. addr[1] = (u8) (addr_hi >> 8);
  362. addr[2] = (u8) addr_hi;
  363. addr[3] = (u8) (addr_lo >> 16);
  364. addr[4] = (u8) (addr_lo >> 8);
  365. addr[5] = (u8) addr_lo;
  366. return 0;
  367. }
  368. /* This is intended to reset a port, not the whole MAC */
  369. static int mac_reset(struct cmac *mac)
  370. {
  371. int index = mac->instance->index;
  372. run_table(mac->adapter, vsc7326_portinit[index],
  373. ARRAY_SIZE(vsc7326_portinit[index]));
  374. return 0;
  375. }
  376. static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm)
  377. {
  378. u32 v;
  379. int port = mac->instance->index;
  380. vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v);
  381. v |= 1 << 12;
  382. if (t1_rx_mode_promisc(rm))
  383. v &= ~(1 << (port + 16));
  384. else
  385. v |= 1 << (port + 16);
  386. vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v);
  387. return 0;
  388. }
  389. static int mac_set_mtu(struct cmac *mac, int mtu)
  390. {
  391. int port = mac->instance->index;
  392. if (mtu > MAX_MTU)
  393. return -EINVAL;
  394. /* max_len includes header and FCS */
  395. vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4);
  396. return 0;
  397. }
  398. static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex,
  399. int fc)
  400. {
  401. u32 v;
  402. int enable, port = mac->instance->index;
  403. if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 &&
  404. speed != SPEED_1000)
  405. return -1;
  406. if (duplex > 0 && duplex != DUPLEX_FULL)
  407. return -1;
  408. if (speed >= 0) {
  409. vsc_read(mac->adapter, REG_MODE_CFG(port), &v);
  410. enable = v & 3; /* save tx/rx enables */
  411. v &= ~0xf;
  412. v |= 4; /* full duplex */
  413. if (speed == SPEED_1000)
  414. v |= 8; /* GigE */
  415. enable |= v;
  416. vsc_write(mac->adapter, REG_MODE_CFG(port), v);
  417. if (speed == SPEED_1000)
  418. v = 0x82;
  419. else if (speed == SPEED_100)
  420. v = 0x84;
  421. else /* SPEED_10 */
  422. v = 0x86;
  423. vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1); /* reset */
  424. vsc_write(mac->adapter, REG_DEV_SETUP(port), v);
  425. vsc_read(mac->adapter, REG_DBG(port), &v);
  426. v &= ~0xff00;
  427. if (speed == SPEED_1000)
  428. v |= 0x400;
  429. else if (speed == SPEED_100)
  430. v |= 0x2000;
  431. else /* SPEED_10 */
  432. v |= 0xff00;
  433. vsc_write(mac->adapter, REG_DBG(port), v);
  434. vsc_write(mac->adapter, REG_TX_IFG(port),
  435. speed == SPEED_1000 ? 5 : 0x11);
  436. if (duplex == DUPLEX_HALF)
  437. enable = 0x0; /* 100 or 10 */
  438. else if (speed == SPEED_1000)
  439. enable = 0xc;
  440. else /* SPEED_100 or 10 */
  441. enable = 0x4;
  442. enable |= 0x9 << 10; /* IFG1 */
  443. enable |= 0x6 << 6; /* IFG2 */
  444. enable |= 0x1 << 4; /* VLAN */
  445. enable |= 0x3; /* RX/TX EN */
  446. vsc_write(mac->adapter, REG_MODE_CFG(port), enable);
  447. }
  448. vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v);
  449. v &= 0xfff0ffff;
  450. v |= 0x20000; /* xon/xoff */
  451. if (fc & PAUSE_RX)
  452. v |= 0x40000;
  453. if (fc & PAUSE_TX)
  454. v |= 0x80000;
  455. if (fc == (PAUSE_RX | PAUSE_TX))
  456. v |= 0x10000;
  457. vsc_write(mac->adapter, REG_PAUSE_CFG(port), v);
  458. return 0;
  459. }
  460. static int mac_enable(struct cmac *mac, int which)
  461. {
  462. u32 val;
  463. int port = mac->instance->index;
  464. /* Write the correct WM value when the port is enabled. */
  465. vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE);
  466. vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
  467. if (which & MAC_DIRECTION_RX)
  468. val |= 0x2;
  469. if (which & MAC_DIRECTION_TX)
  470. val |= 1;
  471. vsc_write(mac->adapter, REG_MODE_CFG(port), val);
  472. return 0;
  473. }
  474. static int mac_disable(struct cmac *mac, int which)
  475. {
  476. u32 val;
  477. int i, port = mac->instance->index;
  478. /* Reset the port, this also writes the correct WM value */
  479. mac_reset(mac);
  480. vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
  481. if (which & MAC_DIRECTION_RX)
  482. val &= ~0x2;
  483. if (which & MAC_DIRECTION_TX)
  484. val &= ~0x1;
  485. vsc_write(mac->adapter, REG_MODE_CFG(port), val);
  486. vsc_read(mac->adapter, REG_MODE_CFG(port), &val);
  487. /* Clear stats */
  488. for (i = 0; i <= 0x3a; ++i)
  489. vsc_write(mac->adapter, CRA(4, port, i), 0);
  490. /* Clear software counters */
  491. memset(&mac->stats, 0, sizeof(struct cmac_statistics));
  492. return 0;
  493. }
  494. static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat)
  495. {
  496. u32 v, lo;
  497. vsc_read(mac->adapter, addr, &v);
  498. lo = *stat;
  499. *stat = *stat - lo + v;
  500. if (v == 0)
  501. return;
  502. if (v < lo)
  503. *stat += (1ULL << 32);
  504. }
  505. static void port_stats_update(struct cmac *mac)
  506. {
  507. struct {
  508. unsigned int reg;
  509. unsigned int offset;
  510. } hw_stats[] = {
  511. #define HW_STAT(reg, stat_name) \
  512. { reg, (&((struct cmac_statistics *)NULL)->stat_name) - (u64 *)NULL }
  513. /* Rx stats */
  514. HW_STAT(RxUnicast, RxUnicastFramesOK),
  515. HW_STAT(RxMulticast, RxMulticastFramesOK),
  516. HW_STAT(RxBroadcast, RxBroadcastFramesOK),
  517. HW_STAT(Crc, RxFCSErrors),
  518. HW_STAT(RxAlignment, RxAlignErrors),
  519. HW_STAT(RxOversize, RxFrameTooLongErrors),
  520. HW_STAT(RxPause, RxPauseFrames),
  521. HW_STAT(RxJabbers, RxJabberErrors),
  522. HW_STAT(RxFragments, RxRuntErrors),
  523. HW_STAT(RxUndersize, RxRuntErrors),
  524. HW_STAT(RxSymbolCarrier, RxSymbolErrors),
  525. HW_STAT(RxSize1519ToMax, RxJumboFramesOK),
  526. /* Tx stats (skip collision stats as we are full-duplex only) */
  527. HW_STAT(TxUnicast, TxUnicastFramesOK),
  528. HW_STAT(TxMulticast, TxMulticastFramesOK),
  529. HW_STAT(TxBroadcast, TxBroadcastFramesOK),
  530. HW_STAT(TxPause, TxPauseFrames),
  531. HW_STAT(TxUnderrun, TxUnderrun),
  532. HW_STAT(TxSize1519ToMax, TxJumboFramesOK),
  533. }, *p = hw_stats;
  534. unsigned int port = mac->instance->index;
  535. u64 *stats = (u64 *)&mac->stats;
  536. unsigned int i;
  537. for (i = 0; i < ARRAY_SIZE(hw_stats); i++)
  538. rmon_update(mac, CRA(0x4, port, p->reg), stats + p->offset);
  539. rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK);
  540. rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK);
  541. rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad);
  542. }
  543. /*
  544. * This function is called periodically to accumulate the current values of the
  545. * RMON counters into the port statistics. Since the counters are only 32 bits
  546. * some of them can overflow in less than a minute at GigE speeds, so this
  547. * function should be called every 30 seconds or so.
  548. *
  549. * To cut down on reading costs we update only the octet counters at each tick
  550. * and do a full update at major ticks, which can be every 30 minutes or more.
  551. */
  552. static const struct cmac_statistics *mac_update_statistics(struct cmac *mac,
  553. int flag)
  554. {
  555. if (flag == MAC_STATS_UPDATE_FULL ||
  556. mac->instance->ticks >= MAJOR_UPDATE_TICKS) {
  557. port_stats_update(mac);
  558. mac->instance->ticks = 0;
  559. } else {
  560. int port = mac->instance->index;
  561. rmon_update(mac, REG_RX_OK_BYTES(port),
  562. &mac->stats.RxOctetsOK);
  563. rmon_update(mac, REG_RX_BAD_BYTES(port),
  564. &mac->stats.RxOctetsBad);
  565. rmon_update(mac, REG_TX_OK_BYTES(port),
  566. &mac->stats.TxOctetsOK);
  567. mac->instance->ticks++;
  568. }
  569. return &mac->stats;
  570. }
  571. static void mac_destroy(struct cmac *mac)
  572. {
  573. kfree(mac);
  574. }
  575. static struct cmac_ops vsc7326_ops = {
  576. .destroy = mac_destroy,
  577. .reset = mac_reset,
  578. .interrupt_handler = mac_intr_handler,
  579. .interrupt_enable = mac_intr_enable,
  580. .interrupt_disable = mac_intr_disable,
  581. .interrupt_clear = mac_intr_clear,
  582. .enable = mac_enable,
  583. .disable = mac_disable,
  584. .set_mtu = mac_set_mtu,
  585. .set_rx_mode = mac_set_rx_mode,
  586. .set_speed_duplex_fc = mac_set_speed_duplex_fc,
  587. .statistics_update = mac_update_statistics,
  588. .macaddress_get = mac_get_address,
  589. .macaddress_set = mac_set_address,
  590. };
  591. static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index)
  592. {
  593. struct cmac *mac;
  594. u32 val;
  595. int i;
  596. mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL);
  597. if (!mac)
  598. return NULL;
  599. mac->ops = &vsc7326_ops;
  600. mac->instance = (cmac_instance *)(mac + 1);
  601. mac->adapter = adapter;
  602. mac->instance->index = index;
  603. mac->instance->ticks = 0;
  604. i = 0;
  605. do {
  606. u32 vhi, vlo;
  607. vhi = vlo = 0;
  608. t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo);
  609. udelay(1);
  610. t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi);
  611. udelay(5);
  612. val = (vhi << 16) | vlo;
  613. } while ((++i < 10000) && (val == 0xffffffff));
  614. return mac;
  615. }
  616. static int vsc7326_mac_reset(adapter_t *adapter)
  617. {
  618. vsc7326_full_reset(adapter);
  619. (void) run_bist_all(adapter);
  620. run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset));
  621. return 0;
  622. }
  623. const struct gmac t1_vsc7326_ops = {
  624. .stats_update_period = STATS_TICK_SECS,
  625. .create = vsc7326_mac_create,
  626. .reset = vsc7326_mac_reset,
  627. };