Skip to content

Commit

Permalink
tg3: APE heartbeat changes
Browse files Browse the repository at this point in the history
In ungraceful host shutdown or driver crash case BMC connectivity is
lost. APE firmware is missing the driver state in this
case to keep the BMC connectivity alive.
This patch has below change to address this issue.

Heartbeat mechanism with APE firmware. This heartbeat mechanism
is needed to notify the APE firmware about driver state.

This patch also has the change in wait time for APE event from
1ms to 20ms as there can be some delay in getting response.

v2: Drop inline keyword as per David suggestion.

Signed-off-by: Prashant Sreedharan <[email protected]>
Signed-off-by: Satish Baddipadige <[email protected]>
Signed-off-by: Siva Reddy Kallam <[email protected]>
Acked-by: Michael Chan <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Prashant Sreedharan authored and davem330 committed Feb 19, 2018
1 parent d1c95af commit 506b0a3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 11 deletions.
35 changes: 24 additions & 11 deletions drivers/net/ethernet/broadcom/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,7 @@ static int tg3_ape_event_lock(struct tg3 *tp, u32 timeout_us)

tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);

udelay(10);
usleep_range(10, 20);
timeout_us -= (timeout_us > 10) ? 10 : timeout_us;
}

Expand Down Expand Up @@ -922,8 +922,8 @@ static int tg3_ape_send_event(struct tg3 *tp, u32 event)
if (!(apedata & APE_FW_STATUS_READY))
return -EAGAIN;

/* Wait for up to 1 millisecond for APE to service previous event. */
err = tg3_ape_event_lock(tp, 1000);
/* Wait for up to 20 millisecond for APE to service previous event. */
err = tg3_ape_event_lock(tp, 20000);
if (err)
return err;

Expand All @@ -946,6 +946,7 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)

switch (kind) {
case RESET_KIND_INIT:
tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_COUNT, tp->ape_hb++);
tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
APE_HOST_SEG_SIG_MAGIC);
tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN,
Expand All @@ -962,13 +963,6 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
event = APE_EVENT_STATUS_STATE_START;
break;
case RESET_KIND_SHUTDOWN:
/* With the interface we are currently using,
* APE does not track driver state. Wiping
* out the HOST SEGMENT SIGNATURE forces
* the APE to assume OS absent status.
*/
tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);

if (device_may_wakeup(&tp->pdev->dev) &&
tg3_flag(tp, WOL_ENABLE)) {
tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED,
Expand All @@ -990,6 +984,18 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
tg3_ape_send_event(tp, event);
}

static void tg3_send_ape_heartbeat(struct tg3 *tp,
unsigned long interval)
{
/* Check if hb interval has exceeded */
if (!tg3_flag(tp, ENABLE_APE) ||
time_before(jiffies, tp->ape_hb_jiffies + interval))
return;

tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_COUNT, tp->ape_hb++);
tp->ape_hb_jiffies = jiffies;
}

static void tg3_disable_ints(struct tg3 *tp)
{
int i;
Expand Down Expand Up @@ -7262,6 +7268,7 @@ static int tg3_poll_msix(struct napi_struct *napi, int budget)
}
}

tg3_send_ape_heartbeat(tp, TG3_APE_HB_INTERVAL << 1);
return work_done;

tx_recovery:
Expand Down Expand Up @@ -7344,6 +7351,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
}
}

tg3_send_ape_heartbeat(tp, TG3_APE_HB_INTERVAL << 1);
return work_done;

tx_recovery:
Expand Down Expand Up @@ -10732,7 +10740,7 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
if (tg3_flag(tp, ENABLE_APE))
/* Write our heartbeat update interval to APE. */
tg3_ape_write32(tp, TG3_APE_HOST_HEARTBEAT_INT_MS,
APE_HOST_HEARTBEAT_INT_DISABLE);
APE_HOST_HEARTBEAT_INT_5SEC);

tg3_write_sig_post_reset(tp, RESET_KIND_INIT);

Expand Down Expand Up @@ -11077,6 +11085,9 @@ static void tg3_timer(struct timer_list *t)
tp->asf_counter = tp->asf_multiplier;
}

/* Update the APE heartbeat every 5 seconds.*/
tg3_send_ape_heartbeat(tp, TG3_APE_HB_INTERVAL);

spin_unlock(&tp->lock);

restart_timer:
Expand Down Expand Up @@ -16653,6 +16664,8 @@ static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
pci_state_reg);

tg3_ape_lock_init(tp);
tp->ape_hb_interval =
msecs_to_jiffies(APE_HOST_HEARTBEAT_INT_5SEC);
}

/* Set up tp->grc_local_ctrl before calling
Expand Down
5 changes: 5 additions & 0 deletions drivers/net/ethernet/broadcom/tg3.h
Original file line number Diff line number Diff line change
Expand Up @@ -2508,6 +2508,7 @@
#define TG3_APE_LOCK_PHY3 5
#define TG3_APE_LOCK_GPIO 7

#define TG3_APE_HB_INTERVAL (tp->ape_hb_interval)
#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10


Expand Down Expand Up @@ -3423,6 +3424,10 @@ struct tg3 {
struct device *hwmon_dev;
bool link_up;
bool pcierr_recovery;

u32 ape_hb;
unsigned long ape_hb_interval;
unsigned long ape_hb_jiffies;
};

/* Accessor macros for chip and asic attributes
Expand Down

0 comments on commit 506b0a3

Please sign in to comment.