mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-09 00:43:08 -04:00
ionic: better handling of RESET event
When IONIC_EVENT_RESET is received, we only need to start the
fw_down process if we aren't already down, and we need to be
sure to set the FW_STOPPING state on the way.
If this is how we noticed that FW was stopped, it is most
likely from a FW update, and we'll see a new FW generation.
The update happens quickly enough that we might not see
fw_status==0, so we need to be sure things get restarted when
we see the fw_generation change.
Fixes: d2662072c0 ("ionic: monitor fw status generation")
Signed-off-by: Shannon Nelson <snelson@pensando.io>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
398d1e37f9
commit
abd75d14fe
@@ -33,7 +33,8 @@ static void ionic_watchdog_cb(struct timer_list *t)
|
||||
!test_bit(IONIC_LIF_F_FW_RESET, lif->state))
|
||||
ionic_link_status_check_request(lif, CAN_NOT_SLEEP);
|
||||
|
||||
if (test_bit(IONIC_LIF_F_FILTER_SYNC_NEEDED, lif->state)) {
|
||||
if (test_bit(IONIC_LIF_F_FILTER_SYNC_NEEDED, lif->state) &&
|
||||
!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
|
||||
work = kzalloc(sizeof(*work), GFP_ATOMIC);
|
||||
if (!work) {
|
||||
netdev_err(lif->netdev, "rxmode change dropped\n");
|
||||
@@ -148,8 +149,9 @@ bool ionic_is_fw_running(struct ionic_dev *idev)
|
||||
|
||||
int ionic_heartbeat_check(struct ionic *ionic)
|
||||
{
|
||||
struct ionic_dev *idev = &ionic->idev;
|
||||
unsigned long check_time, last_check_time;
|
||||
struct ionic_dev *idev = &ionic->idev;
|
||||
struct ionic_lif *lif = ionic->lif;
|
||||
bool fw_status_ready = true;
|
||||
bool fw_hb_ready;
|
||||
u8 fw_generation;
|
||||
@@ -187,14 +189,21 @@ int ionic_heartbeat_check(struct ionic *ionic)
|
||||
* the down, the next watchdog will see the fw is up
|
||||
* and the generation value stable, so will trigger
|
||||
* the fw-up activity.
|
||||
*
|
||||
* If we had already moved to FW_RESET from a RESET event,
|
||||
* it is possible that we never saw the fw_status go to 0,
|
||||
* so we fake the current idev->fw_status_ready here to
|
||||
* force the transition and get FW up again.
|
||||
*/
|
||||
fw_status_ready = false;
|
||||
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
|
||||
idev->fw_status_ready = false; /* go to running */
|
||||
else
|
||||
fw_status_ready = false; /* go to down */
|
||||
}
|
||||
}
|
||||
|
||||
/* is this a transition? */
|
||||
if (fw_status_ready != idev->fw_status_ready) {
|
||||
struct ionic_lif *lif = ionic->lif;
|
||||
bool trigger = false;
|
||||
|
||||
if (!fw_status_ready && lif &&
|
||||
|
||||
@@ -1112,12 +1112,17 @@ static bool ionic_notifyq_service(struct ionic_cq *cq,
|
||||
ionic_link_status_check_request(lif, CAN_NOT_SLEEP);
|
||||
break;
|
||||
case IONIC_EVENT_RESET:
|
||||
work = kzalloc(sizeof(*work), GFP_ATOMIC);
|
||||
if (!work) {
|
||||
netdev_err(lif->netdev, "Reset event dropped\n");
|
||||
} else {
|
||||
work->type = IONIC_DW_TYPE_LIF_RESET;
|
||||
ionic_lif_deferred_enqueue(&lif->deferred, work);
|
||||
if (lif->ionic->idev.fw_status_ready &&
|
||||
!test_bit(IONIC_LIF_F_FW_RESET, lif->state) &&
|
||||
!test_and_set_bit(IONIC_LIF_F_FW_STOPPING, lif->state)) {
|
||||
work = kzalloc(sizeof(*work), GFP_ATOMIC);
|
||||
if (!work) {
|
||||
netdev_err(lif->netdev, "Reset event dropped\n");
|
||||
clear_bit(IONIC_LIF_F_FW_STOPPING, lif->state);
|
||||
} else {
|
||||
work->type = IONIC_DW_TYPE_LIF_RESET;
|
||||
ionic_lif_deferred_enqueue(&lif->deferred, work);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user