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>
This commit is contained in:
Dimitris Michailidis 2010-08-23 17:20:59 +00:00 committed by David S. Miller
parent e46dab4d4b
commit 1478b3ee93
2 changed files with 32 additions and 9 deletions

View File

@ -1681,27 +1681,41 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
return 0; return 0;
} }
/* /**
* Translate a physical EEPROM address to virtual. The first 1K is accessed * eeprom_ptov - translate a physical EEPROM address to virtual
* through virtual addresses starting at 31K, the rest is accessed through * @phys_addr: the physical EEPROM address
* virtual addresses starting at 0. This mapping is correct only for PF0. * @fn: the PCI function number
* @sz: size of function-specific area
*
* Translate a physical EEPROM address to virtual. The first 1K is
* accessed through virtual addresses starting at 31K, the rest is
* accessed through virtual addresses starting at 0.
*
* The mapping is as follows:
* [0..1K) -> [31K..32K)
* [1K..1K+A) -> [31K-A..31K)
* [1K+A..ES) -> [0..ES-A-1K)
*
* where A = @fn * @sz, and ES = EEPROM size.
*/ */
static int eeprom_ptov(unsigned int phys_addr) static int eeprom_ptov(unsigned int phys_addr, unsigned int fn, unsigned int sz)
{ {
fn *= sz;
if (phys_addr < 1024) if (phys_addr < 1024)
return phys_addr + (31 << 10); return phys_addr + (31 << 10);
if (phys_addr < 1024 + fn)
return 31744 - fn + phys_addr - 1024;
if (phys_addr < EEPROMSIZE) if (phys_addr < EEPROMSIZE)
return phys_addr - 1024; return phys_addr - 1024 - fn;
return -EINVAL; return -EINVAL;
} }
/* /*
* The next two routines implement eeprom read/write from physical addresses. * The next two routines implement eeprom read/write from physical addresses.
* The physical->virtual translation is correct only for PF0.
*/ */
static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v) static int eeprom_rd_phys(struct adapter *adap, unsigned int phys_addr, u32 *v)
{ {
int vaddr = eeprom_ptov(phys_addr); int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
if (vaddr >= 0) if (vaddr >= 0)
vaddr = pci_read_vpd(adap->pdev, vaddr, sizeof(u32), v); 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)
static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v) static int eeprom_wr_phys(struct adapter *adap, unsigned int phys_addr, u32 v)
{ {
int vaddr = eeprom_ptov(phys_addr); int vaddr = eeprom_ptov(phys_addr, adap->fn, EEPROMPFSIZE);
if (vaddr >= 0) if (vaddr >= 0)
vaddr = pci_write_vpd(adap->pdev, vaddr, sizeof(u32), &v); 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,
aligned_offset = eeprom->offset & ~3; aligned_offset = eeprom->offset & ~3;
aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3; aligned_len = (eeprom->len + (eeprom->offset & 3) + 3) & ~3;
if (adapter->fn > 0) {
u32 start = 1024 + adapter->fn * EEPROMPFSIZE;
if (aligned_offset < start ||
aligned_offset + aligned_len > start + EEPROMPFSIZE)
return -EPERM;
}
if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) { if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
/* /*
* RMW possibly needed for first or last words. * RMW possibly needed for first or last words.

View File

@ -42,6 +42,7 @@ enum {
MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */ MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */
EEPROMSIZE = 17408, /* Serial EEPROM physical size */ EEPROMSIZE = 17408, /* Serial EEPROM physical size */
EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */ EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */
EEPROMPFSIZE = 1024, /* EEPROM writable area size for PFn, n>0 */
RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */ RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */
TCB_SIZE = 128, /* TCB size */ TCB_SIZE = 128, /* TCB size */
NMTUS = 16, /* size of MTU table */ NMTUS = 16, /* size of MTU table */