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

drivers: net: phy: xgene: Add lock to protect mac access

This patch,

- refactors mac access routine
- adds lock to protect mac indirect access

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

authored by

Quan Nguyen and committed by
David S. Miller
8ec7074a ae1aed95

+40 -37
+37 -37
drivers/net/phy/mdio-xgene.c
··· 34 34 35 35 static bool xgene_mdio_status; 36 36 37 - static u32 xgene_enet_rd_mac(void __iomem *base_addr, u32 rd_addr) 37 + u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr) 38 38 { 39 39 void __iomem *addr, *rd, *cmd, *cmd_done; 40 40 u32 done, rd_data = BUSY_MASK; 41 41 u8 wait = 10; 42 42 43 - addr = base_addr + MAC_ADDR_REG_OFFSET; 44 - rd = base_addr + MAC_READ_REG_OFFSET; 45 - cmd = base_addr + MAC_COMMAND_REG_OFFSET; 46 - cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET; 43 + addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET; 44 + rd = pdata->mac_csr_addr + MAC_READ_REG_OFFSET; 45 + cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET; 46 + cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET; 47 47 48 + spin_lock(&pdata->mac_lock); 48 49 iowrite32(rd_addr, addr); 49 50 iowrite32(XGENE_ENET_RD_CMD, cmd); 50 51 51 - while (wait--) { 52 - done = ioread32(cmd_done); 53 - if (done) 54 - break; 52 + while (!(done = ioread32(cmd_done)) && wait--) 55 53 udelay(1); 56 - } 57 54 58 - if (!done) 59 - return rd_data; 55 + if (done) 56 + rd_data = ioread32(rd); 60 57 61 - rd_data = ioread32(rd); 62 58 iowrite32(0, cmd); 59 + spin_unlock(&pdata->mac_lock); 63 60 64 61 return rd_data; 65 62 } 63 + EXPORT_SYMBOL(xgene_mdio_rd_mac); 66 64 67 - static void xgene_enet_wr_mac(void __iomem *base_addr, u32 wr_addr, u32 wr_data) 65 + void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data) 68 66 { 69 67 void __iomem *addr, *wr, *cmd, *cmd_done; 70 68 u8 wait = 10; 71 69 u32 done; 72 70 73 - addr = base_addr + MAC_ADDR_REG_OFFSET; 74 - wr = base_addr + MAC_WRITE_REG_OFFSET; 75 - cmd = base_addr + MAC_COMMAND_REG_OFFSET; 76 - cmd_done = base_addr + MAC_COMMAND_DONE_REG_OFFSET; 71 + addr = pdata->mac_csr_addr + MAC_ADDR_REG_OFFSET; 72 + wr = pdata->mac_csr_addr + MAC_WRITE_REG_OFFSET; 73 + cmd = pdata->mac_csr_addr + MAC_COMMAND_REG_OFFSET; 74 + cmd_done = pdata->mac_csr_addr + MAC_COMMAND_DONE_REG_OFFSET; 77 75 76 + spin_lock(&pdata->mac_lock); 78 77 iowrite32(wr_addr, addr); 79 - iowrite32(wr_data, wr); 78 + iowrite32(data, wr); 80 79 iowrite32(XGENE_ENET_WR_CMD, cmd); 81 80 82 - while (wait--) { 83 - done = ioread32(cmd_done); 84 - if (done) 85 - break; 81 + while (!(done = ioread32(cmd_done)) && wait--) 86 82 udelay(1); 87 - } 88 83 89 84 if (!done) 90 85 pr_err("MCX mac write failed, addr: 0x%04x\n", wr_addr); 91 86 92 87 iowrite32(0, cmd); 88 + spin_unlock(&pdata->mac_lock); 93 89 } 90 + EXPORT_SYMBOL(xgene_mdio_wr_mac); 94 91 95 92 int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg) 96 93 { 97 - void __iomem *addr = (void __iomem *)bus->priv; 94 + struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; 98 95 u32 data, done; 99 96 u8 wait = 10; 100 97 101 98 data = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); 102 - xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, data); 103 - xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); 99 + xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, data); 100 + xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); 104 101 do { 105 102 usleep_range(5, 10); 106 - done = xgene_enet_rd_mac(addr, MII_MGMT_INDICATORS_ADDR); 103 + done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR); 107 104 } while ((done & BUSY_MASK) && wait--); 108 105 109 106 if (done & BUSY_MASK) { ··· 108 111 return -EBUSY; 109 112 } 110 113 111 - data = xgene_enet_rd_mac(addr, MII_MGMT_STATUS_ADDR); 112 - xgene_enet_wr_mac(addr, MII_MGMT_COMMAND_ADDR, 0); 114 + data = xgene_mdio_rd_mac(pdata, MII_MGMT_STATUS_ADDR); 115 + xgene_mdio_wr_mac(pdata, MII_MGMT_COMMAND_ADDR, 0); 113 116 114 117 return data; 115 118 } ··· 117 120 118 121 int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data) 119 122 { 120 - void __iomem *addr = (void __iomem *)bus->priv; 123 + struct xgene_mdio_pdata *pdata = (struct xgene_mdio_pdata *)bus->priv; 121 124 u32 val, done; 122 125 u8 wait = 10; 123 126 124 127 val = SET_VAL(PHY_ADDR, phy_id) | SET_VAL(REG_ADDR, reg); 125 - xgene_enet_wr_mac(addr, MII_MGMT_ADDRESS_ADDR, val); 128 + xgene_mdio_wr_mac(pdata, MII_MGMT_ADDRESS_ADDR, val); 126 129 127 - xgene_enet_wr_mac(addr, MII_MGMT_CONTROL_ADDR, data); 130 + xgene_mdio_wr_mac(pdata, MII_MGMT_CONTROL_ADDR, data); 128 131 do { 129 132 usleep_range(5, 10); 130 - done = xgene_enet_rd_mac(addr, MII_MGMT_INDICATORS_ADDR); 133 + done = xgene_mdio_rd_mac(pdata, MII_MGMT_INDICATORS_ADDR); 131 134 } while ((done & BUSY_MASK) && wait--); 132 135 133 136 if (done & BUSY_MASK) { ··· 171 174 172 175 static void xgene_gmac_reset(struct xgene_mdio_pdata *pdata) 173 176 { 174 - xgene_enet_wr_mac(pdata->mac_csr_addr, MAC_CONFIG_1_ADDR, SOFT_RESET); 175 - xgene_enet_wr_mac(pdata->mac_csr_addr, MAC_CONFIG_1_ADDR, 0); 177 + xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET); 178 + xgene_mdio_wr_mac(pdata, MAC_CONFIG_1_ADDR, 0); 176 179 } 177 180 178 181 static int xgene_mdio_reset(struct xgene_mdio_pdata *pdata) ··· 372 375 pdata->mdio_csr_addr = csr_base + BLOCK_XG_MDIO_CSR_OFFSET; 373 376 pdata->diag_csr_addr = csr_base + BLOCK_DIAG_CSR_OFFSET; 374 377 378 + if (mdio_id == XGENE_MDIO_RGMII) 379 + spin_lock_init(&pdata->mac_lock); 380 + 375 381 if (dev->of_node) { 376 382 pdata->clk = devm_clk_get(dev, NULL); 377 383 if (IS_ERR(pdata->clk)) { ··· 396 396 if (mdio_id == XGENE_MDIO_RGMII) { 397 397 mdio_bus->read = xgene_mdio_rgmii_read; 398 398 mdio_bus->write = xgene_mdio_rgmii_write; 399 - mdio_bus->priv = (void __force *)pdata->mac_csr_addr; 399 + mdio_bus->priv = (void __force *)pdata; 400 400 snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s", 401 401 "xgene-mii-rgmii"); 402 402 } else {
+3
drivers/net/phy/mdio-xgene.h
··· 102 102 void __iomem *mdio_csr_addr; 103 103 struct mii_bus *mdio_bus; 104 104 int mdio_id; 105 + spinlock_t mac_lock; /* mac lock */ 105 106 }; 106 107 107 108 /* Set the specified value into a bit-field defined by its starting position ··· 133 132 #define GET_BIT(field, src) \ 134 133 xgene_enet_get_field_value(field ## _POS, 1, src) 135 134 135 + u32 xgene_mdio_rd_mac(struct xgene_mdio_pdata *pdata, u32 rd_addr); 136 + void xgene_mdio_wr_mac(struct xgene_mdio_pdata *pdata, u32 wr_addr, u32 data); 136 137 int xgene_mdio_rgmii_read(struct mii_bus *bus, int phy_id, int reg); 137 138 int xgene_mdio_rgmii_write(struct mii_bus *bus, int phy_id, int reg, u16 data); 138 139 struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr);