diff options
| -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 | } |
