Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 67056
b: refs/heads/master
c: 0d3031d
h: refs/heads/master
v: v3
  • Loading branch information
Matt Carlson authored and David S. Miller committed Oct 11, 2007
1 parent 7f17a27 commit 8de1bb1
Show file tree
Hide file tree
Showing 3 changed files with 275 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6b91fa02796292c322b20572188c74c1ef5bb02b
refs/heads/master: 0d3031d9e674cddd4c09731123ad252294cdf15f
232 changes: 228 additions & 4 deletions trunk/drivers/net/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,16 @@ static u32 tg3_read32(struct tg3 *tp, u32 off)
return (readl(tp->regs + off));
}

static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val)
{
writel(val, tp->aperegs + off);
}

static u32 tg3_ape_read32(struct tg3 *tp, u32 off)
{
return (readl(tp->aperegs + off));
}

static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
{
unsigned long flags;
Expand Down Expand Up @@ -500,6 +510,73 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
spin_unlock_irqrestore(&tp->indirect_lock, flags);
}

static void tg3_ape_lock_init(struct tg3 *tp)
{
int i;

/* Make sure the driver hasn't any stale locks. */
for (i = 0; i < 8; i++)
tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + 4 * i,
APE_LOCK_GRANT_DRIVER);
}

static int tg3_ape_lock(struct tg3 *tp, int locknum)
{
int i, off;
int ret = 0;
u32 status;

if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return 0;

switch (locknum) {
case TG3_APE_LOCK_MEM:
break;
default:
return -EINVAL;
}

off = 4 * locknum;

tg3_ape_write32(tp, TG3_APE_LOCK_REQ + off, APE_LOCK_REQ_DRIVER);

/* Wait for up to 1 millisecond to acquire lock. */
for (i = 0; i < 100; i++) {
status = tg3_ape_read32(tp, TG3_APE_LOCK_GRANT + off);
if (status == APE_LOCK_GRANT_DRIVER)
break;
udelay(10);
}

if (status != APE_LOCK_GRANT_DRIVER) {
/* Revoke the lock request. */
tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off,
APE_LOCK_GRANT_DRIVER);

ret = -EBUSY;
}

return ret;
}

static void tg3_ape_unlock(struct tg3 *tp, int locknum)
{
int off;

if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;

switch (locknum) {
case TG3_APE_LOCK_MEM:
break;
default:
return;
}

off = 4 * locknum;
tg3_ape_write32(tp, TG3_APE_LOCK_GRANT + off, APE_LOCK_GRANT_DRIVER);
}

static void tg3_disable_ints(struct tg3 *tp)
{
tw32(TG3PCI_MISC_HOST_CTRL,
Expand Down Expand Up @@ -1448,7 +1525,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
}

if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
tg3_power_down_phy(tp);

tg3_frob_aux_power(tp);
Expand Down Expand Up @@ -4726,6 +4804,80 @@ static void tg3_disable_nvram_access(struct tg3 *tp)
}
}

static void tg3_ape_send_event(struct tg3 *tp, u32 event)
{
int i;
u32 apedata;

apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
if (apedata != APE_SEG_SIG_MAGIC)
return;

apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
if (apedata != APE_FW_STATUS_READY)
return;

/* Wait for up to 1 millisecond for APE to service previous event. */
for (i = 0; i < 10; i++) {
if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
return;

apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);

if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
event | APE_EVENT_STATUS_EVENT_PENDING);

tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);

if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
break;

udelay(100);
}

if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
}

static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
{
u32 event;
u32 apedata;

if (!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
return;

switch (kind) {
case RESET_KIND_INIT:
tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
APE_HOST_SEG_SIG_MAGIC);
tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN,
APE_HOST_SEG_LEN_MAGIC);
apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT);
tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata);
tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID,
APE_HOST_DRIVER_ID_MAGIC);
tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
APE_HOST_BEHAV_NO_PHYLOCK);

event = APE_EVENT_STATUS_STATE_START;
break;
case RESET_KIND_SHUTDOWN:
event = APE_EVENT_STATUS_STATE_UNLOAD;
break;
case RESET_KIND_SUSPEND:
event = APE_EVENT_STATUS_STATE_SUSPEND;
break;
default:
return;
}

event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE;

tg3_ape_send_event(tp, event);
}

/* tp->lock is held. */
static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
{
Expand Down Expand Up @@ -4753,6 +4905,10 @@ static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
break;
};
}

if (kind == RESET_KIND_INIT ||
kind == RESET_KIND_SUSPEND)
tg3_ape_driver_state_change(tp, kind);
}

/* tp->lock is held. */
Expand All @@ -4774,6 +4930,9 @@ static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
break;
};
}

if (kind == RESET_KIND_SHUTDOWN)
tg3_ape_driver_state_change(tp, kind);
}

/* tp->lock is held. */
Expand Down Expand Up @@ -4864,6 +5023,10 @@ static void tg3_restore_pci_state(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0 &&
(tp->tg3_flags & TG3_FLAG_PCIX_MODE))
val |= PCISTATE_RETRY_SAME_DMA;
/* Allow reads and writes to the APE register and memory space. */
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)
val |= PCISTATE_ALLOW_APE_CTLSPC_WR |
PCISTATE_ALLOW_APE_SHMEM_WR;
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, val);

pci_write_config_dword(tp->pdev, TG3PCI_COMMAND, tp->pci_cmd);
Expand Down Expand Up @@ -5092,7 +5255,8 @@ static int tg3_chip_reset(struct tg3 *tp)
/* tp->lock is held. */
static void tg3_stop_fw(struct tg3 *tp)
{
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
u32 val;
int i;

Expand Down Expand Up @@ -6173,6 +6337,16 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tw32(TG3PCI_PCISTATE, val);
}

if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
/* Allow reads and writes to the
* APE register and memory space.
*/
val = tr32(TG3PCI_PCISTATE);
val |= PCISTATE_ALLOW_APE_CTLSPC_WR |
PCISTATE_ALLOW_APE_SHMEM_WR;
tw32(TG3PCI_PCISTATE, val);
}

if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5704_BX) {
/* Enable some hw fixes. */
val = tr32(TG3PCI_MSI_DATA);
Expand Down Expand Up @@ -6780,6 +6954,10 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
break;
};

/* Write our heartbeat update interval to APE. */
tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS,
APE_HOST_HEARTBEAT_INT_DISABLE);

tg3_write_sig_post_reset(tp, RESET_KIND_INIT);

return 0;
Expand Down Expand Up @@ -10302,6 +10480,8 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
}
if (nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE)
tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE;
if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
!(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
Expand Down Expand Up @@ -10334,7 +10514,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
* firwmare access to the PHY hardware.
*/
err = 0;
if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) {
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) {
hw_phy_id = hw_phy_id_masked = PHY_ID_INVALID;
} else {
/* Now read the physical PHY_ID from the chip and verify
Expand Down Expand Up @@ -10381,6 +10562,7 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
}

if (!(tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) &&
!(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) &&
!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
u32 bmsr, adv_reg, tg3_ctrl, mask;

Expand Down Expand Up @@ -10972,6 +11154,16 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
*/
tg3_get_eeprom_hw_cfg(tp);

if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
/* Allow reads and writes to the
* APE register and memory space.
*/
pci_state_reg |= PCISTATE_ALLOW_APE_CTLSPC_WR |
PCISTATE_ALLOW_APE_SHMEM_WR;
pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE,
pci_state_reg);
}

if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784)
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;

Expand Down Expand Up @@ -12165,13 +12357,35 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,

tg3_init_coal(tp);

if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX "Cannot find proper PCI device "
"base address for APE, aborting.\n");
err = -ENODEV;
goto err_out_iounmap;
}

tg3reg_base = pci_resource_start(pdev, 2);
tg3reg_len = pci_resource_len(pdev, 2);

tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
if (tp->aperegs == 0UL) {
printk(KERN_ERR PFX "Cannot map APE registers, "
"aborting.\n");
err = -ENOMEM;
goto err_out_iounmap;
}

tg3_ape_lock_init(tp);
}

pci_set_drvdata(pdev, dev);

err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
"aborting.\n");
goto err_out_iounmap;
goto err_out_apeunmap;
}

printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ",
Expand Down Expand Up @@ -12204,6 +12418,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,

return 0;

err_out_apeunmap:
if (tp->aperegs) {
iounmap(tp->aperegs);
tp->aperegs = NULL;
}

err_out_iounmap:
if (tp->regs) {
iounmap(tp->regs);
Expand Down Expand Up @@ -12231,6 +12451,10 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)

flush_scheduled_work();
unregister_netdev(dev);
if (tp->aperegs) {
iounmap(tp->aperegs);
tp->aperegs = NULL;
}
if (tp->regs) {
iounmap(tp->regs);
tp->regs = NULL;
Expand Down
Loading

0 comments on commit 8de1bb1

Please sign in to comment.