aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/sky2.c97
1 files changed, 55 insertions, 42 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index e24b25ca1c69..4e3e2a37c3d1 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -3732,27 +3732,63 @@ static int sky2_get_eeprom_len(struct net_device *dev)
3732 return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); 3732 return 1 << ( ((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8);
3733} 3733}
3734 3734
3735static u32 sky2_vpd_read(struct sky2_hw *hw, int cap, u16 offset) 3735static int sky2_vpd_wait(const struct sky2_hw *hw, int cap, u16 busy)
3736{ 3736{
3737 u32 val; 3737 unsigned long start = jiffies;
3738 3738
3739 sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset); 3739 while ( (sky2_pci_read16(hw, cap + PCI_VPD_ADDR) & PCI_VPD_ADDR_F) == busy) {
3740 /* Can take up to 10.6 ms for write */
3741 if (time_after(jiffies, start + HZ/4)) {
3742 dev_err(&hw->pdev->dev, PFX "VPD cycle timed out");
3743 return -ETIMEDOUT;
3744 }
3745 mdelay(1);
3746 }
3740 3747
3741 do { 3748 return 0;
3742 offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR); 3749}
3743 } while (!(offset & PCI_VPD_ADDR_F));
3744 3750
3745 val = sky2_pci_read32(hw, cap + PCI_VPD_DATA); 3751static int sky2_vpd_read(struct sky2_hw *hw, int cap, void *data,
3746 return val; 3752 u16 offset, size_t length)
3753{
3754 int rc = 0;
3755
3756 while (length > 0) {
3757 u32 val;
3758
3759 sky2_pci_write16(hw, cap + PCI_VPD_ADDR, offset);
3760 rc = sky2_vpd_wait(hw, cap, 0);
3761 if (rc)
3762 break;
3763
3764 val = sky2_pci_read32(hw, cap + PCI_VPD_DATA);
3765
3766 memcpy(data, &val, min(sizeof(val), length));
3767 offset += sizeof(u32);
3768 data += sizeof(u32);
3769 length -= sizeof(u32);
3770 }
3771
3772 return rc;
3747} 3773}
3748 3774
3749static void sky2_vpd_write(struct sky2_hw *hw, int cap, u16 offset, u32 val) 3775static int sky2_vpd_write(struct sky2_hw *hw, int cap, const void *data,
3776 u16 offset, unsigned int length)
3750{ 3777{
3751 sky2_pci_write16(hw, cap + PCI_VPD_DATA, val); 3778 unsigned int i;
3752 sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F); 3779 int rc = 0;
3753 do { 3780
3754 offset = sky2_pci_read16(hw, cap + PCI_VPD_ADDR); 3781 for (i = 0; i < length; i += sizeof(u32)) {
3755 } while (offset & PCI_VPD_ADDR_F); 3782 u32 val = *(u32 *)(data + i);
3783
3784 sky2_pci_write32(hw, cap + PCI_VPD_DATA, val);
3785 sky2_pci_write32(hw, cap + PCI_VPD_ADDR, offset | PCI_VPD_ADDR_F);
3786
3787 rc = sky2_vpd_wait(hw, cap, PCI_VPD_ADDR_F);
3788 if (rc)
3789 break;
3790 }
3791 return rc;
3756} 3792}
3757 3793
3758static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, 3794static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
@@ -3760,24 +3796,13 @@ static int sky2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
3760{ 3796{
3761 struct sky2_port *sky2 = netdev_priv(dev); 3797 struct sky2_port *sky2 = netdev_priv(dev);
3762 int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); 3798 int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
3763 int length = eeprom->len;
3764 u16 offset = eeprom->offset;
3765 3799
3766 if (!cap) 3800 if (!cap)
3767 return -EINVAL; 3801 return -EINVAL;
3768 3802
3769 eeprom->magic = SKY2_EEPROM_MAGIC; 3803 eeprom->magic = SKY2_EEPROM_MAGIC;
3770 3804
3771 while (length > 0) { 3805 return sky2_vpd_read(sky2->hw, cap, data, eeprom->offset, eeprom->len);
3772 u32 val = sky2_vpd_read(sky2->hw, cap, offset);
3773 int n = min_t(int, length, sizeof(val));
3774
3775 memcpy(data, &val, n);
3776 length -= n;
3777 data += n;
3778 offset += n;
3779 }
3780 return 0;
3781} 3806}
3782 3807
3783static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, 3808static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
@@ -3785,8 +3810,6 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
3785{ 3810{
3786 struct sky2_port *sky2 = netdev_priv(dev); 3811 struct sky2_port *sky2 = netdev_priv(dev);
3787 int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD); 3812 int cap = pci_find_capability(sky2->hw->pdev, PCI_CAP_ID_VPD);
3788 int length = eeprom->len;
3789 u16 offset = eeprom->offset;
3790 3813
3791 if (!cap) 3814 if (!cap)
3792 return -EINVAL; 3815 return -EINVAL;
@@ -3794,21 +3817,11 @@ static int sky2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom
3794 if (eeprom->magic != SKY2_EEPROM_MAGIC) 3817 if (eeprom->magic != SKY2_EEPROM_MAGIC)
3795 return -EINVAL; 3818 return -EINVAL;
3796 3819
3797 while (length > 0) { 3820 /* Partial writes not supported */
3798 u32 val; 3821 if ((eeprom->offset & 3) || (eeprom->len & 3))
3799 int n = min_t(int, length, sizeof(val)); 3822 return -EINVAL;
3800
3801 if (n < sizeof(val))
3802 val = sky2_vpd_read(sky2->hw, cap, offset);
3803 memcpy(&val, data, n);
3804
3805 sky2_vpd_write(sky2->hw, cap, offset, val);
3806 3823
3807 length -= n; 3824 return sky2_vpd_write(sky2->hw, cap, data, eeprom->offset, eeprom->len);
3808 data += n;
3809 offset += n;
3810 }
3811 return 0;
3812} 3825}
3813 3826
3814 3827