Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers: net: xgene: Protect indirect MAC access

This patch,

- refactors mac read/write functions
- adds lock to protect indirect mac access

Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Signed-off-by: Quan Nguyen <qnguyen@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Iyappan Subramanian and committed by
David S. Miller
ae1aed95 a95cfad9

+71 -186
+59 -78
drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
··· 270 270 iowrite32(val, addr); 271 271 } 272 272 273 - static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, 274 - void __iomem *cmd, void __iomem *cmd_done, 275 - u32 wr_addr, u32 wr_data) 276 - { 277 - u32 done; 278 - u8 wait = 10; 279 - 280 - iowrite32(wr_addr, addr); 281 - iowrite32(wr_data, wr); 282 - iowrite32(XGENE_ENET_WR_CMD, cmd); 283 - 284 - /* wait for write command to complete */ 285 - while (!(done = ioread32(cmd_done)) && wait--) 286 - udelay(1); 287 - 288 - if (!done) 289 - return false; 290 - 291 - iowrite32(0, cmd); 292 - 293 - return true; 294 - } 295 - 296 - static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata, 297 - u32 wr_addr, u32 wr_data) 273 + void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, u32 wr_data) 298 274 { 299 275 void __iomem *addr, *wr, *cmd, *cmd_done; 276 + struct net_device *ndev = pdata->ndev; 277 + u8 wait = 10; 278 + u32 done; 300 279 301 280 addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; 302 281 wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET; 303 282 cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; 304 283 cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; 305 284 306 - if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data)) 307 - netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n", 308 - wr_addr); 285 + spin_lock(&pdata->mac_lock); 286 + iowrite32(wr_addr, addr); 287 + iowrite32(wr_data, wr); 288 + iowrite32(XGENE_ENET_WR_CMD, cmd); 289 + 290 + while (!(done = ioread32(cmd_done)) && wait--) 291 + udelay(1); 292 + 293 + if (!done) 294 + netdev_err(ndev, "mac write failed, addr: %04x data: %08x\n", 295 + wr_addr, wr_data); 296 + 297 + iowrite32(0, cmd); 298 + spin_unlock(&pdata->mac_lock); 309 299 } 310 300 311 301 static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata, ··· 322 332 *val = ioread32(addr); 323 333 } 324 334 325 - static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, 326 - void __iomem *cmd, void __iomem *cmd_done, 327 - u32 rd_addr, u32 *rd_data) 328 - { 329 - u32 done; 330 - u8 wait = 10; 331 - 332 - iowrite32(rd_addr, addr); 333 - iowrite32(XGENE_ENET_RD_CMD, cmd); 334 - 335 - /* wait for read command to complete */ 336 - while (!(done = ioread32(cmd_done)) && wait--) 337 - udelay(1); 338 - 339 - if (!done) 340 - return false; 341 - 342 - *rd_data = ioread32(rd); 343 - iowrite32(0, cmd); 344 - 345 - return true; 346 - } 347 - 348 - static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata, 349 - u32 rd_addr, u32 *rd_data) 335 + u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr) 350 336 { 351 337 void __iomem *addr, *rd, *cmd, *cmd_done; 338 + u32 done, rd_data; 339 + u8 wait = 10; 352 340 353 341 addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; 354 342 rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; 355 343 cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; 356 344 cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; 357 345 358 - if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) 359 - netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", 346 + spin_lock(&pdata->mac_lock); 347 + iowrite32(rd_addr, addr); 348 + iowrite32(XGENE_ENET_RD_CMD, cmd); 349 + 350 + while (!(done = ioread32(cmd_done)) && wait--) 351 + udelay(1); 352 + 353 + if (!done) 354 + netdev_err(pdata->ndev, "mac read failed, addr: %04x\n", 360 355 rd_addr); 356 + 357 + rd_data = ioread32(rd); 358 + iowrite32(0, cmd); 359 + spin_unlock(&pdata->mac_lock); 360 + 361 + return rd_data; 361 362 } 362 363 363 364 static void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata) ··· 360 379 (dev_addr[1] << 8) | dev_addr[0]; 361 380 addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16); 362 381 363 - xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0); 364 - xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1); 382 + xgene_enet_wr_mac(pdata, STATION_ADDR0_ADDR, addr0); 383 + xgene_enet_wr_mac(pdata, STATION_ADDR1_ADDR, addr1); 365 384 } 366 385 367 386 static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) ··· 386 405 387 406 static void xgene_gmac_reset(struct xgene_enet_pdata *pdata) 388 407 { 389 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1); 390 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0); 408 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1); 409 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0); 391 410 } 392 411 393 412 static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata) ··· 437 456 438 457 xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0); 439 458 xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2); 440 - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2); 441 - xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl); 459 + mc2 = xgene_enet_rd_mac(pdata, MAC_CONFIG_2_ADDR); 460 + intf_ctl = xgene_enet_rd_mac(pdata, INTERFACE_CONTROL_ADDR); 442 461 xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii); 443 462 444 463 switch (pdata->phy_speed) { ··· 476 495 } 477 496 478 497 mc2 |= FULL_DUPLEX2 | PAD_CRC | LENGTH_CHK; 479 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2); 480 - xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); 498 + xgene_enet_wr_mac(pdata, MAC_CONFIG_2_ADDR, mc2); 499 + xgene_enet_wr_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); 481 500 xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii); 482 501 xgene_enet_configure_clock(pdata); 483 502 ··· 487 506 488 507 static void xgene_enet_set_frame_size(struct xgene_enet_pdata *pdata, int size) 489 508 { 490 - xgene_enet_wr_mcx_mac(pdata, MAX_FRAME_LEN_ADDR, size); 509 + xgene_enet_wr_mac(pdata, MAX_FRAME_LEN_ADDR, size); 491 510 } 492 511 493 512 static void xgene_gmac_enable_tx_pause(struct xgene_enet_pdata *pdata, ··· 509 528 { 510 529 u32 data; 511 530 512 - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); 531 + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); 513 532 514 533 if (enable) 515 534 data |= TX_FLOW_EN; 516 535 else 517 536 data &= ~TX_FLOW_EN; 518 537 519 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data); 538 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data); 520 539 521 540 pdata->mac_ops->enable_tx_pause(pdata, enable); 522 541 } ··· 525 544 { 526 545 u32 data; 527 546 528 - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); 547 + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); 529 548 530 549 if (enable) 531 550 data |= RX_FLOW_EN; 532 551 else 533 552 data &= ~RX_FLOW_EN; 534 553 535 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data); 554 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data); 536 555 } 537 556 538 557 static void xgene_gmac_init(struct xgene_enet_pdata *pdata) ··· 546 565 xgene_gmac_set_mac_addr(pdata); 547 566 548 567 /* Adjust MDC clock frequency */ 549 - xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value); 568 + value = xgene_enet_rd_mac(pdata, MII_MGMT_CONFIG_ADDR); 550 569 MGMT_CLOCK_SEL_SET(&value, 7); 551 - xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value); 570 + xgene_enet_wr_mac(pdata, MII_MGMT_CONFIG_ADDR, value); 552 571 553 572 /* Enable drop if bufpool not available */ 554 573 xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value); ··· 618 637 { 619 638 u32 data; 620 639 621 - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); 622 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN); 640 + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); 641 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN); 623 642 } 624 643 625 644 static void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata) 626 645 { 627 646 u32 data; 628 647 629 - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); 630 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN); 648 + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); 649 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN); 631 650 } 632 651 633 652 static void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata) 634 653 { 635 654 u32 data; 636 655 637 - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); 638 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN); 656 + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); 657 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN); 639 658 } 640 659 641 660 static void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata) 642 661 { 643 662 u32 data; 644 663 645 - xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); 646 - xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN); 664 + data = xgene_enet_rd_mac(pdata, MAC_CONFIG_1_ADDR); 665 + xgene_enet_wr_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN); 647 666 } 648 667 649 668 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p)
+3
drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
··· 388 388 bool xgene_ring_mgr_init(struct xgene_enet_pdata *p); 389 389 int xgene_enet_phy_connect(struct net_device *ndev); 390 390 void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata); 391 + u32 xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, u32 rd_addr); 392 + void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, u32 wr_addr, 393 + u32 wr_data); 391 394 392 395 extern const struct xgene_mac_ops xgene_gmac_ops; 393 396 extern const struct xgene_port_ops xgene_gport_ops;
+1
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
··· 2055 2055 goto err; 2056 2056 2057 2057 xgene_enet_setup_ops(pdata); 2058 + spin_lock_init(&pdata->mac_lock); 2058 2059 2059 2060 if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) { 2060 2061 ndev->features |= NETIF_F_TSO | NETIF_F_RXCSUM;
+1
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
··· 221 221 struct xgene_enet_cle cle; 222 222 struct rtnl_link_stats64 stats; 223 223 const struct xgene_mac_ops *mac_ops; 224 + spinlock_t mac_lock; /* mac lock */ 224 225 const struct xgene_port_ops *port_ops; 225 226 struct xgene_ring_ops *ring_ops; 226 227 const struct xgene_cle_ops *cle_ops;
-71
drivers/net/ethernet/apm/xgene/xgene_enet_sgmac.c
··· 54 54 iowrite32(val, addr); 55 55 } 56 56 57 - static bool xgene_enet_wr_indirect(struct xgene_indirect_ctl *ctl, 58 - u32 wr_addr, u32 wr_data) 59 - { 60 - int i; 61 - 62 - iowrite32(wr_addr, ctl->addr); 63 - iowrite32(wr_data, ctl->ctl); 64 - iowrite32(XGENE_ENET_WR_CMD, ctl->cmd); 65 - 66 - /* wait for write command to complete */ 67 - for (i = 0; i < 10; i++) { 68 - if (ioread32(ctl->cmd_done)) { 69 - iowrite32(0, ctl->cmd); 70 - return true; 71 - } 72 - udelay(1); 73 - } 74 - 75 - return false; 76 - } 77 - 78 - static void xgene_enet_wr_mac(struct xgene_enet_pdata *p, 79 - u32 wr_addr, u32 wr_data) 80 - { 81 - struct xgene_indirect_ctl ctl = { 82 - .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET, 83 - .ctl = p->mcx_mac_addr + MAC_WRITE_REG_OFFSET, 84 - .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET, 85 - .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET 86 - }; 87 - 88 - if (!xgene_enet_wr_indirect(&ctl, wr_addr, wr_data)) 89 - netdev_err(p->ndev, "mac write failed, addr: %04x\n", wr_addr); 90 - } 91 - 92 57 static u32 xgene_enet_rd_csr(struct xgene_enet_pdata *p, u32 offset) 93 58 { 94 59 return ioread32(p->eth_csr_addr + offset); ··· 67 102 static u32 xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *p, u32 offset) 68 103 { 69 104 return ioread32(p->mcx_mac_csr_addr + offset); 70 - } 71 - 72 - static u32 xgene_enet_rd_indirect(struct xgene_indirect_ctl *ctl, u32 rd_addr) 73 - { 74 - u32 rd_data; 75 - int i; 76 - 77 - iowrite32(rd_addr, ctl->addr); 78 - iowrite32(XGENE_ENET_RD_CMD, ctl->cmd); 79 - 80 - /* wait for read command to complete */ 81 - for (i = 0; i < 10; i++) { 82 - if (ioread32(ctl->cmd_done)) { 83 - rd_data = ioread32(ctl->ctl); 84 - iowrite32(0, ctl->cmd); 85 - 86 - return rd_data; 87 - } 88 - udelay(1); 89 - } 90 - 91 - pr_err("%s: mac read failed, addr: %04x\n", __func__, rd_addr); 92 - 93 - return 0; 94 - } 95 - 96 - static u32 xgene_enet_rd_mac(struct xgene_enet_pdata *p, u32 rd_addr) 97 - { 98 - struct xgene_indirect_ctl ctl = { 99 - .addr = p->mcx_mac_addr + MAC_ADDR_REG_OFFSET, 100 - .ctl = p->mcx_mac_addr + MAC_READ_REG_OFFSET, 101 - .cmd = p->mcx_mac_addr + MAC_COMMAND_REG_OFFSET, 102 - .cmd_done = p->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET 103 - }; 104 - 105 - return xgene_enet_rd_indirect(&ctl, rd_addr); 106 105 } 107 106 108 107 static int xgene_enet_ecc_init(struct xgene_enet_pdata *p)
+7 -37
drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
··· 71 71 return true; 72 72 } 73 73 74 - static void xgene_enet_wr_mac(struct xgene_enet_pdata *pdata, 75 - u32 wr_addr, u32 wr_data) 76 - { 77 - void __iomem *addr, *wr, *cmd, *cmd_done; 78 - 79 - addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; 80 - wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET; 81 - cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; 82 - cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; 83 - 84 - if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data)) 85 - netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n", 86 - wr_addr); 87 - } 88 - 89 74 static void xgene_enet_wr_pcs(struct xgene_enet_pdata *pdata, 90 75 u32 wr_addr, u32 wr_data) 91 76 { ··· 131 146 iowrite32(0, cmd); 132 147 133 148 return true; 134 - } 135 - 136 - static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata, 137 - u32 rd_addr, u32 *rd_data) 138 - { 139 - void __iomem *addr, *rd, *cmd, *cmd_done; 140 - 141 - addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; 142 - rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; 143 - cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; 144 - cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; 145 - 146 - if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) 147 - netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", 148 - rd_addr); 149 149 } 150 150 151 151 static bool xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata, ··· 270 300 { 271 301 u32 data; 272 302 273 - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); 303 + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); 274 304 275 305 if (enable) 276 306 data |= HSTTCTLEN; ··· 286 316 { 287 317 u32 data; 288 318 289 - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); 319 + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); 290 320 291 321 if (enable) 292 322 data |= HSTRCTLEN; ··· 302 332 303 333 xgene_xgmac_reset(pdata); 304 334 305 - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); 335 + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); 306 336 data |= HSTPPEN; 307 337 data &= ~HSTLENCHK; 308 338 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data); ··· 349 379 { 350 380 u32 data; 351 381 352 - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); 382 + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); 353 383 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTRFEN); 354 384 } 355 385 ··· 357 387 { 358 388 u32 data; 359 389 360 - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); 390 + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); 361 391 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data | HSTTFEN); 362 392 } 363 393 ··· 365 395 { 366 396 u32 data; 367 397 368 - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); 398 + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); 369 399 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTRFEN); 370 400 } 371 401 ··· 373 403 { 374 404 u32 data; 375 405 376 - xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1, &data); 406 + data = xgene_enet_rd_mac(pdata, AXGMAC_CONFIG_1); 377 407 xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data & ~HSTTFEN); 378 408 } 379 409