diff options
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 143 |
1 files changed, 121 insertions, 22 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 27a7c20f64c..bb8645ab247 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: | ||
1656 | break; | ||
1657 | |||
1658 | case PHY_BJMPN: | ||
1659 | if (regno > index) { | ||
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 | } | ||
1646 | break; | 1680 | break; |
1647 | 1681 | ||
1648 | if ((action & 0xf0000000) != PHY_WRITE) { | 1682 | case PHY_READ_MAC_BYTE: |
1649 | netif_err(tp, probe, dev, | 1683 | case PHY_WRITE_MAC_BYTE: |
1650 | "unknown action 0x%08x\n", action); | 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++; | ||
1664 | break; | 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++; | ||
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 | } |
@@ -3069,15 +3167,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3069 | rtl8168_driver_start(tp); | 3167 | rtl8168_driver_start(tp); |
3070 | } | 3168 | } |
3071 | 3169 | ||
3072 | rtl8169_init_phy(dev, tp); | ||
3073 | |||
3074 | /* | ||
3075 | * Pretend we are using VLANs; This bypasses a nasty bug where | ||
3076 | * Interrupts stop flowing on high load on 8110SCd controllers. | ||
3077 | */ | ||
3078 | if (tp->mac_version == RTL_GIGA_MAC_VER_05) | ||
3079 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); | ||
3080 | |||
3081 | device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); | 3170 | device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); |
3082 | 3171 | ||
3083 | if (pci_dev_run_wake(pdev)) | 3172 | if (pci_dev_run_wake(pdev)) |
@@ -3127,6 +3216,7 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev) | |||
3127 | static int rtl8169_open(struct net_device *dev) | 3216 | static int rtl8169_open(struct net_device *dev) |
3128 | { | 3217 | { |
3129 | struct rtl8169_private *tp = netdev_priv(dev); | 3218 | struct rtl8169_private *tp = netdev_priv(dev); |
3219 | void __iomem *ioaddr = tp->mmio_addr; | ||
3130 | struct pci_dev *pdev = tp->pci_dev; | 3220 | struct pci_dev *pdev = tp->pci_dev; |
3131 | int retval = -ENOMEM; | 3221 | int retval = -ENOMEM; |
3132 | 3222 | ||
@@ -3162,6 +3252,15 @@ static int rtl8169_open(struct net_device *dev) | |||
3162 | 3252 | ||
3163 | napi_enable(&tp->napi); | 3253 | napi_enable(&tp->napi); |
3164 | 3254 | ||
3255 | rtl8169_init_phy(dev, tp); | ||
3256 | |||
3257 | /* | ||
3258 | * Pretend we are using VLANs; This bypasses a nasty bug where | ||
3259 | * Interrupts stop flowing on high load on 8110SCd controllers. | ||
3260 | */ | ||
3261 | if (tp->mac_version == RTL_GIGA_MAC_VER_05) | ||
3262 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan); | ||
3263 | |||
3165 | rtl_pll_power_up(tp); | 3264 | rtl_pll_power_up(tp); |
3166 | 3265 | ||
3167 | rtl_hw_start(dev); | 3266 | rtl_hw_start(dev); |
@@ -3171,7 +3270,7 @@ static int rtl8169_open(struct net_device *dev) | |||
3171 | tp->saved_wolopts = 0; | 3270 | tp->saved_wolopts = 0; |
3172 | pm_runtime_put_noidle(&pdev->dev); | 3271 | pm_runtime_put_noidle(&pdev->dev); |
3173 | 3272 | ||
3174 | rtl8169_check_link_status(dev, tp, tp->mmio_addr); | 3273 | rtl8169_check_link_status(dev, tp, ioaddr); |
3175 | out: | 3274 | out: |
3176 | return retval; | 3275 | return retval; |
3177 | 3276 | ||