diff options
author | Dimitris Michailidis <dm@chelsio.com> | 2010-08-23 13:20:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-08-23 23:38:14 -0400 |
commit | 1478b3ee931e83c7a94f61376e962574b28d23d6 (patch) | |
tree | e22cb1de6256301f2e5cf5476b5219977af66dc9 /drivers/net/cxgb4 | |
parent | e46dab4d4be87769b09404135bc34f89e2e155d8 (diff) |
cxgb4: support eeprom read/write on functions other than 0
Extend the address translation for eeprom read/write (code used by
ethtool -[eE]) to functions other than 0.
Signed-off-by: Dimitris Michailidis <dm@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/cxgb4')
-rw-r--r-- | drivers/net/cxgb4/cxgb4_main.c | 40 | ||||
-rw-r--r-- | drivers/net/cxgb4/t4_hw.h | 1 |
2 files changed, 32 insertions, 9 deletions
diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 6e08e2d8eb3e..7552d8df55ed 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c | |||
@@ -1681,27 +1681,41 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) | |||
1681 | return 0; | 1681 | return 0; |
1682 | } | 1682 | } |
1683 | 1683 | ||
1684 | /* | 1684 | /** |
1685 | * Translate a physical EEPROM address to virtual. The first 1K is accessed | 1685 | * eeprom_ptov - translate a physical EEPROM address to virtual |
1686 | * through virtual addresses starting at 31K, the rest is accessed through | 1686 | * @phys_addr: the physical EEPROM address |
1687 | * virtual addresses starting at 0. This mapping is correct only for PF0. | 1687 | * @fn: the PCI function number |
1688 | * @sz: size of function-specific area | ||
1689 | * | ||
1690 | * Translate a physical EEPROM address to virtual. The first 1K is | ||
1691 | * accessed through virtual addresses starting at 31K, the rest is | ||
1692 | * accessed through virtual addresses starting at 0. | ||
1693 | * | ||
1694 | * The mapping is as follows: | ||
1695 | * [0..1K) -> [31K..32K) | ||
1696 | * [1K..1K+A) -> [31K-A..31K) | ||
1697 | * [1K+A..ES) -> [0..ES-A-1K) | ||
1698 | * | ||
1699 | * where A = @fn * @sz, and ES = EEPROM size. | ||
1688 | */ | 1700 | */ |
1689 | static int eeprom_ptov(unsigned int phys_addr) | 1701 | static int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz) |
1690 | { | 1702 | { |
1703 | fn *= sz; | ||
1691 | if (phys_addr < 1024) | 1704 | if (phys_addr < 1024) |
1692 | return phys_addr + (31 << 10); | 1705 | return phys_addr + (31 << 10); |
1706 | if (phys_addr < 1024 + fn) | ||
1707 | return 31744 - fn + phys_addr - 1024; | ||
1693 | if (phys_addr < EEPROMSIZE) | 1708 | if (phys_addr < EEPROMSIZE) |
1694 | return phys_addr - 1024; | 1709 | return phys_addr - 1024 - fn; |
1695 | return -EINVAL; | 1710 | return -EINVAL; |
1696 | } | 1711 | } |
1697 | 1712 | ||
1698 | /* | 1713 | /* |
1699 | * The next two routines implement eeprom read/write from physical addresses. | 1714 | * The next two routines implement eeprom read/write from physical addresses. |
1700 | * The physical->virtual translation is correct only for PF0. | ||
1701 | */ | 1715 | */ |
1702 | static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v) | 1716 | static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v) |
1703 | { | 1717 | { |
1704 | int vaddr = eeprom_ptov(phys_addr); | 1718 | int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE); |
1705 | 1719 | ||
1706 | if (vaddr >= 0) | 1720 | if (vaddr >= 0) |
1707 | vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v); | 1721 | vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v); |
@@ -1710,7 +1724,7 @@ static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v) | |||
1710 | 1724 | ||
1711 | static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v) | 1725 | static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v) |
1712 | { | 1726 | { |
1713 | int vaddr = eeprom_ptov(phys_addr); | 1727 | int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE); |
1714 | 1728 | ||
1715 | if (vaddr >= 0) | 1729 | if (vaddr >= 0) |
1716 | vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v); | 1730 | vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v); |
@@ -1753,6 +1767,14 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | |||
1753 | aligned_offset = eeprom->offset & ~3; | 1767 | aligned_offset = eeprom->offset & ~3; |
1754 | aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3; | 1768 | aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3; |
1755 | 1769 | ||
1770 | if (adapter->fn > 0) { | ||
1771 | u32 start = 1024 + adapter->fn * EEPROMPFSIZE; | ||
1772 | |||
1773 | if (aligned_offset < start || | ||
1774 | aligned_offset + aligned_len > start + EEPROMPFSIZE) | ||
1775 | return -EPERM; | ||
1776 | } | ||
1777 | |||
1756 | if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) { | 1778 | if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) { |
1757 | /* | 1779 | /* |
1758 | * RMW possibly needed for first or last words. | 1780 | * RMW possibly needed for first or last words. |
diff --git a/drivers/net/cxgb4/t4_hw.h b/drivers/net/cxgb4/t4_hw.h index 10a055565776..c26b455f37de 100644 --- a/drivers/net/cxgb4/t4_hw.h +++ b/drivers/net/cxgb4/t4_hw.h | |||
@@ -42,6 +42,7 @@ enum { | |||
42 | MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */ | 42 | MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */ |
43 | EEPROMSIZE = 17408, /* Serial EEPROM physical size */ | 43 | EEPROMSIZE = 17408, /* Serial EEPROM physical size */ |
44 | EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */ | 44 | EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */ |
45 | EEPROMPFSIZE = 1024, /* EEPROM writable area size for PFn, n>0 */ | ||
45 | RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */ | 46 | RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */ |
46 | TCB_SIZE = 128, /* TCB size */ | 47 | TCB_SIZE = 128, /* TCB size */ |
47 | NMTUS = 16, /* size of MTU table */ | 48 | NMTUS = 16, /* size of MTU table */ |