diff options
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 122 |
1 files changed, 110 insertions, 12 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index dd758cdb55c4..bb8645ab247c 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -1632,36 +1632,134 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw) | |||
1632 | { | 1632 | { |
1633 | __le32 *phytable = (__le32 *)fw->data; | 1633 | __le32 *phytable = (__le32 *)fw->data; |
1634 | struct net_device *dev = tp->dev; | 1634 | struct net_device *dev = tp->dev; |
1635 | size_t i; | 1635 | size_t index, fw_size = fw->size / sizeof(*phytable); |
1636 | u32 predata, count; | ||
1636 | 1637 | ||
1637 | if (fw->size % sizeof(*phytable)) { | 1638 | if (fw->size % sizeof(*phytable)) { |
1638 | netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size); | 1639 | netif_err(tp, probe, dev, "odd sized firmware %zd\n", fw->size); |
1639 | return; | 1640 | return; |
1640 | } | 1641 | } |
1641 | 1642 | ||
1642 | for (i = 0; i < fw->size / sizeof(*phytable); i++) { | 1643 | for (index = 0; index < fw_size; index++) { |
1643 | u32 action = le32_to_cpu(phytable[i]); | 1644 | u32 action = le32_to_cpu(phytable[index]); |
1645 | u32 regno = (action & 0x0fff0000) >> 16; | ||
1644 | 1646 | ||
1645 | if (!action) | 1647 | switch(action & 0xf0000000) { |
1648 | case PHY_READ: | ||
1649 | case PHY_DATA_OR: | ||
1650 | case PHY_DATA_AND: | ||
1651 | case PHY_READ_EFUSE: | ||
1652 | case PHY_CLEAR_READCOUNT: | ||
1653 | case PHY_WRITE: | ||
1654 | case PHY_WRITE_PREVIOUS: | ||
1655 | case PHY_DELAY_MS: | ||
1646 | break; | 1656 | break; |
1647 | 1657 | ||
1648 | if ((action & 0xf0000000) != PHY_WRITE) { | 1658 | case PHY_BJMPN: |
1649 | netif_err(tp, probe, dev, | 1659 | if (regno > index) { |
1650 | "unknown action 0x%08x\n", action); | 1660 | netif_err(tp, probe, tp->dev, |
1661 | "Out of range of firmware\n"); | ||
1662 | return; | ||
1663 | } | ||
1664 | break; | ||
1665 | case PHY_READCOUNT_EQ_SKIP: | ||
1666 | if (index + 2 >= fw_size) { | ||
1667 | netif_err(tp, probe, tp->dev, | ||
1668 | "Out of range of firmware\n"); | ||
1669 | return; | ||
1670 | } | ||
1671 | break; | ||
1672 | case PHY_COMP_EQ_SKIPN: | ||
1673 | case PHY_COMP_NEQ_SKIPN: | ||
1674 | case PHY_SKIPN: | ||
1675 | if (index + 1 + regno >= fw_size) { | ||
1676 | netif_err(tp, probe, tp->dev, | ||
1677 | "Out of range of firmware\n"); | ||
1678 | return; | ||
1679 | } | ||
1680 | break; | ||
1681 | |||
1682 | case PHY_READ_MAC_BYTE: | ||
1683 | case PHY_WRITE_MAC_BYTE: | ||
1684 | case PHY_WRITE_ERI_WORD: | ||
1685 | default: | ||
1686 | netif_err(tp, probe, tp->dev, | ||
1687 | "Invalid action 0x%08x\n", action); | ||
1651 | return; | 1688 | return; |
1652 | } | 1689 | } |
1653 | } | 1690 | } |
1654 | 1691 | ||
1655 | while (i-- != 0) { | 1692 | predata = 0; |
1656 | u32 action = le32_to_cpu(*phytable); | 1693 | count = 0; |
1694 | |||
1695 | for (index = 0; index < fw_size; ) { | ||
1696 | u32 action = le32_to_cpu(phytable[index]); | ||
1657 | u32 data = action & 0x0000ffff; | 1697 | u32 data = action & 0x0000ffff; |
1658 | u32 reg = (action & 0x0fff0000) >> 16; | 1698 | u32 regno = (action & 0x0fff0000) >> 16; |
1699 | |||
1700 | if (!action) | ||
1701 | break; | ||
1659 | 1702 | ||
1660 | switch(action & 0xf0000000) { | 1703 | switch(action & 0xf0000000) { |
1704 | case PHY_READ: | ||
1705 | predata = rtl_readphy(tp, regno); | ||
1706 | count++; | ||
1707 | index++; | ||
1708 | break; | ||
1709 | case PHY_DATA_OR: | ||
1710 | predata |= data; | ||
1711 | index++; | ||
1712 | break; | ||
1713 | case PHY_DATA_AND: | ||
1714 | predata &= data; | ||
1715 | index++; | ||
1716 | break; | ||
1717 | case PHY_BJMPN: | ||
1718 | index -= regno; | ||
1719 | break; | ||
1720 | case PHY_READ_EFUSE: | ||
1721 | predata = rtl8168d_efuse_read(tp->mmio_addr, regno); | ||
1722 | index++; | ||
1723 | break; | ||
1724 | case PHY_CLEAR_READCOUNT: | ||
1725 | count = 0; | ||
1726 | index++; | ||
1727 | break; | ||
1661 | case PHY_WRITE: | 1728 | case PHY_WRITE: |
1662 | rtl_writephy(tp, reg, data); | 1729 | rtl_writephy(tp, regno, data); |
1663 | phytable++; | 1730 | index++; |
1731 | break; | ||
1732 | case PHY_READCOUNT_EQ_SKIP: | ||
1733 | if (count == data) | ||
1734 | index += 2; | ||
1735 | else | ||
1736 | index += 1; | ||
1737 | break; | ||
1738 | case PHY_COMP_EQ_SKIPN: | ||
1739 | if (predata == data) | ||
1740 | index += regno; | ||
1741 | index++; | ||
1742 | break; | ||
1743 | case PHY_COMP_NEQ_SKIPN: | ||
1744 | if (predata != data) | ||
1745 | index += regno; | ||
1746 | index++; | ||
1747 | break; | ||
1748 | case PHY_WRITE_PREVIOUS: | ||
1749 | rtl_writephy(tp, regno, predata); | ||
1750 | index++; | ||
1664 | break; | 1751 | break; |
1752 | case PHY_SKIPN: | ||
1753 | index += regno + 1; | ||
1754 | break; | ||
1755 | case PHY_DELAY_MS: | ||
1756 | mdelay(data); | ||
1757 | index++; | ||
1758 | break; | ||
1759 | |||
1760 | case PHY_READ_MAC_BYTE: | ||
1761 | case PHY_WRITE_MAC_BYTE: | ||
1762 | case PHY_WRITE_ERI_WORD: | ||
1665 | default: | 1763 | default: |
1666 | BUG(); | 1764 | BUG(); |
1667 | } | 1765 | } |