Skip to content

Commit c672412

Browse files
emuslndavem330
authored andcommitted
ionic: remove lifs on fw reset
When the FW RESET event comes to the driver from the firmware, or the fw_status goes to 0 (stopped) or to 0xff (no PCI connection), then shut down the driver activity. This event signals a FW upgrade where we need to quiesce all operations and wait for the FW to restart. The FW will continue the update process once it sees all the LIFs are reset. When the update process is done it will set the fw_status back to RUNNING. Meanwhile, the heartbeat check continues and when the fw_status is seen as set to running we can restart the driver operations. Signed-off-by: Shannon Nelson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 49d3b49 commit c672412

File tree

5 files changed

+158
-25
lines changed

5 files changed

+158
-25
lines changed

drivers/net/ethernet/pensando/ionic/ionic_dev.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ int ionic_dev_setup(struct ionic *ionic)
8686
return -EFAULT;
8787
}
8888

89+
idev->last_fw_status = 0xff;
8990
timer_setup(&ionic->watchdog_timer, ionic_watchdog_cb, 0);
9091
ionic->watchdog_period = IONIC_WATCHDOG_SECS * HZ;
9192
mod_timer(&ionic->watchdog_timer,
@@ -119,8 +120,43 @@ int ionic_heartbeat_check(struct ionic *ionic)
119120
* fw_status != 0xff (bad PCI read)
120121
*/
121122
fw_status = ioread8(&idev->dev_info_regs->fw_status);
122-
if (fw_status == 0xff ||
123-
!(fw_status & IONIC_FW_STS_F_RUNNING))
123+
if (fw_status != 0xff)
124+
fw_status &= IONIC_FW_STS_F_RUNNING; /* use only the run bit */
125+
126+
/* is this a transition? */
127+
if (fw_status != idev->last_fw_status &&
128+
idev->last_fw_status != 0xff) {
129+
struct ionic_lif *lif = ionic->master_lif;
130+
bool trigger = false;
131+
132+
if (!fw_status || fw_status == 0xff) {
133+
dev_info(ionic->dev, "FW stopped %u\n", fw_status);
134+
if (lif && !test_bit(IONIC_LIF_F_FW_RESET, lif->state))
135+
trigger = true;
136+
} else {
137+
dev_info(ionic->dev, "FW running %u\n", fw_status);
138+
if (lif && test_bit(IONIC_LIF_F_FW_RESET, lif->state))
139+
trigger = true;
140+
}
141+
142+
if (trigger) {
143+
struct ionic_deferred_work *work;
144+
145+
work = kzalloc(sizeof(*work), GFP_ATOMIC);
146+
if (!work) {
147+
dev_err(ionic->dev, "%s OOM\n", __func__);
148+
} else {
149+
work->type = IONIC_DW_TYPE_LIF_RESET;
150+
if (fw_status & IONIC_FW_STS_F_RUNNING &&
151+
fw_status != 0xff)
152+
work->fw_status = 1;
153+
ionic_lif_deferred_enqueue(&lif->deferred, work);
154+
}
155+
}
156+
}
157+
idev->last_fw_status = fw_status;
158+
159+
if (!fw_status || fw_status == 0xff)
124160
return -ENXIO;
125161

126162
/* early FW has no heartbeat, else FW will return non-zero */

drivers/net/ethernet/pensando/ionic/ionic_dev.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ struct ionic_dev {
132132

133133
unsigned long last_hb_time;
134134
u32 last_hb;
135+
u8 last_fw_status;
135136

136137
u64 __iomem *db_pages;
137138
dma_addr_t phy_db_pages;

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 110 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ static void ionic_lif_rx_mode(struct ionic_lif *lif, unsigned int rx_mode);
2121
static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr);
2222
static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr);
2323
static void ionic_link_status_check(struct ionic_lif *lif);
24+
static void ionic_lif_handle_fw_down(struct ionic_lif *lif);
25+
static void ionic_lif_handle_fw_up(struct ionic_lif *lif);
26+
static void ionic_lif_set_netdev_info(struct ionic_lif *lif);
2427

2528
static int ionic_start_queues(struct ionic_lif *lif);
2629
static void ionic_stop_queues(struct ionic_lif *lif);
@@ -53,6 +56,12 @@ static void ionic_lif_deferred_work(struct work_struct *work)
5356
case IONIC_DW_TYPE_LINK_STATUS:
5457
ionic_link_status_check(lif);
5558
break;
59+
case IONIC_DW_TYPE_LIF_RESET:
60+
if (w->fw_status)
61+
ionic_lif_handle_fw_up(lif);
62+
else
63+
ionic_lif_handle_fw_down(lif);
64+
break;
5665
default:
5766
break;
5867
}
@@ -61,8 +70,8 @@ static void ionic_lif_deferred_work(struct work_struct *work)
6170
}
6271
}
6372

64-
static void ionic_lif_deferred_enqueue(struct ionic_deferred *def,
65-
struct ionic_deferred_work *work)
73+
void ionic_lif_deferred_enqueue(struct ionic_deferred *def,
74+
struct ionic_deferred_work *work)
6675
{
6776
spin_lock_bh(&def->lock);
6877
list_add_tail(&work->list, &def->list);
@@ -682,6 +691,7 @@ static bool ionic_notifyq_service(struct ionic_cq *cq,
682691
struct ionic_cq_info *cq_info)
683692
{
684693
union ionic_notifyq_comp *comp = cq_info->cq_desc;
694+
struct ionic_deferred_work *work;
685695
struct net_device *netdev;
686696
struct ionic_queue *q;
687697
struct ionic_lif *lif;
@@ -707,11 +717,13 @@ static bool ionic_notifyq_service(struct ionic_cq *cq,
707717
ionic_link_status_check_request(lif);
708718
break;
709719
case IONIC_EVENT_RESET:
710-
netdev_info(netdev, "Notifyq IONIC_EVENT_RESET eid=%lld\n",
711-
eid);
712-
netdev_info(netdev, " reset_code=%d state=%d\n",
713-
comp->reset.reset_code,
714-
comp->reset.state);
720+
work = kzalloc(sizeof(*work), GFP_ATOMIC);
721+
if (!work) {
722+
netdev_err(lif->netdev, "%s OOM\n", __func__);
723+
} else {
724+
work->type = IONIC_DW_TYPE_LIF_RESET;
725+
ionic_lif_deferred_enqueue(&lif->deferred, work);
726+
}
715727
break;
716728
default:
717729
netdev_warn(netdev, "Notifyq unknown event ecode=%d eid=%lld\n",
@@ -1224,7 +1236,8 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
12241236
netdev->hw_features |= netdev->hw_enc_features;
12251237
netdev->features |= netdev->hw_features;
12261238

1227-
netdev->priv_flags |= IFF_UNICAST_FLT;
1239+
netdev->priv_flags |= IFF_UNICAST_FLT |
1240+
IFF_LIVE_ADDR_CHANGE;
12281241

12291242
return 0;
12301243
}
@@ -1669,6 +1682,9 @@ int ionic_stop(struct net_device *netdev)
16691682
{
16701683
struct ionic_lif *lif = netdev_priv(netdev);
16711684

1685+
if (test_bit(IONIC_LIF_F_FW_RESET, lif->state))
1686+
return 0;
1687+
16721688
ionic_stop_queues(lif);
16731689
ionic_txrx_deinit(lif);
16741690
ionic_txrx_free(lif);
@@ -2064,6 +2080,80 @@ static void ionic_lif_reset(struct ionic_lif *lif)
20642080
mutex_unlock(&lif->ionic->dev_cmd_lock);
20652081
}
20662082

2083+
static void ionic_lif_handle_fw_down(struct ionic_lif *lif)
2084+
{
2085+
struct ionic *ionic = lif->ionic;
2086+
2087+
if (test_and_set_bit(IONIC_LIF_F_FW_RESET, lif->state))
2088+
return;
2089+
2090+
dev_info(ionic->dev, "FW Down: Stopping LIFs\n");
2091+
2092+
netif_device_detach(lif->netdev);
2093+
2094+
if (test_bit(IONIC_LIF_F_UP, lif->state)) {
2095+
dev_info(ionic->dev, "Surprise FW stop, stopping queues\n");
2096+
ionic_stop_queues(lif);
2097+
}
2098+
2099+
if (netif_running(lif->netdev)) {
2100+
ionic_txrx_deinit(lif);
2101+
ionic_txrx_free(lif);
2102+
}
2103+
ionic_lifs_deinit(ionic);
2104+
ionic_qcqs_free(lif);
2105+
2106+
dev_info(ionic->dev, "FW Down: LIFs stopped\n");
2107+
}
2108+
2109+
static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
2110+
{
2111+
struct ionic *ionic = lif->ionic;
2112+
int err;
2113+
2114+
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state))
2115+
return;
2116+
2117+
dev_info(ionic->dev, "FW Up: restarting LIFs\n");
2118+
2119+
err = ionic_qcqs_alloc(lif);
2120+
if (err)
2121+
goto err_out;
2122+
2123+
err = ionic_lifs_init(ionic);
2124+
if (err)
2125+
goto err_qcqs_free;
2126+
2127+
if (lif->registered)
2128+
ionic_lif_set_netdev_info(lif);
2129+
2130+
if (netif_running(lif->netdev)) {
2131+
err = ionic_txrx_alloc(lif);
2132+
if (err)
2133+
goto err_lifs_deinit;
2134+
2135+
err = ionic_txrx_init(lif);
2136+
if (err)
2137+
goto err_txrx_free;
2138+
}
2139+
2140+
clear_bit(IONIC_LIF_F_FW_RESET, lif->state);
2141+
ionic_link_status_check_request(lif);
2142+
netif_device_attach(lif->netdev);
2143+
dev_info(ionic->dev, "FW Up: LIFs restarted\n");
2144+
2145+
return;
2146+
2147+
err_txrx_free:
2148+
ionic_txrx_free(lif);
2149+
err_lifs_deinit:
2150+
ionic_lifs_deinit(ionic);
2151+
err_qcqs_free:
2152+
ionic_qcqs_free(lif);
2153+
err_out:
2154+
dev_err(ionic->dev, "FW Up: LIFs restart failed - err %d\n", err);
2155+
}
2156+
20672157
static void ionic_lif_free(struct ionic_lif *lif)
20682158
{
20692159
struct device *dev = lif->ionic->dev;
@@ -2076,7 +2166,8 @@ static void ionic_lif_free(struct ionic_lif *lif)
20762166

20772167
/* free queues */
20782168
ionic_qcqs_free(lif);
2079-
ionic_lif_reset(lif);
2169+
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state))
2170+
ionic_lif_reset(lif);
20802171

20812172
/* free lif info */
20822173
dma_free_coherent(dev, lif->info_sz, lif->info, lif->info_pa);
@@ -2109,17 +2200,19 @@ void ionic_lifs_free(struct ionic *ionic)
21092200

21102201
static void ionic_lif_deinit(struct ionic_lif *lif)
21112202
{
2112-
if (!test_bit(IONIC_LIF_F_INITED, lif->state))
2203+
if (!test_and_clear_bit(IONIC_LIF_F_INITED, lif->state))
21132204
return;
21142205

2115-
clear_bit(IONIC_LIF_F_INITED, lif->state);
2206+
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
2207+
cancel_work_sync(&lif->deferred.work);
2208+
cancel_work_sync(&lif->tx_timeout_work);
2209+
}
21162210

21172211
ionic_rx_filters_deinit(lif);
21182212
if (lif->netdev->features & NETIF_F_RXHASH)
21192213
ionic_lif_rss_deinit(lif);
21202214

21212215
napi_disable(&lif->adminqcq->napi);
2122-
netif_napi_del(&lif->adminqcq->napi);
21232216
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
21242217
ionic_lif_qcq_deinit(lif, lif->adminqcq);
21252218

@@ -2213,6 +2306,7 @@ static int ionic_lif_notifyq_init(struct ionic_lif *lif)
22132306
if (err)
22142307
return err;
22152308

2309+
lif->last_eid = 0;
22162310
q->hw_type = ctx.comp.q_init.hw_type;
22172311
q->hw_index = le32_to_cpu(ctx.comp.q_init.hw_index);
22182312
q->dbval = IONIC_DBELL_QID(q->hw_index);
@@ -2253,8 +2347,8 @@ static int ionic_station_set(struct ionic_lif *lif)
22532347
addr.sa_family = AF_INET;
22542348
err = eth_prepare_mac_addr_change(netdev, &addr);
22552349
if (err) {
2256-
netdev_warn(lif->netdev, "ignoring bad MAC addr from NIC %pM\n",
2257-
addr.sa_data);
2350+
netdev_warn(lif->netdev, "ignoring bad MAC addr from NIC %pM - err %d\n",
2351+
addr.sa_data, err);
22582352
return 0;
22592353
}
22602354

@@ -2464,12 +2558,8 @@ void ionic_lifs_unregister(struct ionic *ionic)
24642558
* current model, so don't bother searching the
24652559
* ionic->lif for candidates to unregister
24662560
*/
2467-
if (!ionic->master_lif)
2468-
return;
2469-
2470-
cancel_work_sync(&ionic->master_lif->deferred.work);
2471-
cancel_work_sync(&ionic->master_lif->tx_timeout_work);
2472-
if (ionic->master_lif->netdev->reg_state == NETREG_REGISTERED)
2561+
if (ionic->master_lif &&
2562+
ionic->master_lif->netdev->reg_state == NETREG_REGISTERED)
24732563
unregister_netdev(ionic->master_lif->netdev);
24742564
}
24752565

drivers/net/ethernet/pensando/ionic/ionic_lif.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ struct ionic_deferred_work {
9898
union {
9999
unsigned int rx_mode;
100100
u8 addr[ETH_ALEN];
101+
u8 fw_status;
101102
};
102103
};
103104

@@ -126,6 +127,7 @@ enum ionic_lif_state_flags {
126127
IONIC_LIF_F_UP,
127128
IONIC_LIF_F_LINK_CHECK_REQUESTED,
128129
IONIC_LIF_F_QUEUE_RESET,
130+
IONIC_LIF_F_FW_RESET,
129131

130132
/* leave this as last */
131133
IONIC_LIF_F_STATE_SIZE
@@ -225,6 +227,8 @@ static inline u32 ionic_coal_hw_to_usec(struct ionic *ionic, u32 units)
225227
}
226228

227229
void ionic_link_status_check_request(struct ionic_lif *lif);
230+
void ionic_lif_deferred_enqueue(struct ionic_deferred *def,
231+
struct ionic_deferred_work *work);
228232
int ionic_lifs_alloc(struct ionic *ionic);
229233
void ionic_lifs_free(struct ionic *ionic);
230234
void ionic_lifs_deinit(struct ionic *ionic);

drivers/net/ethernet/pensando/ionic/ionic_main.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,11 @@ int ionic_adminq_post_wait(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
286286

287287
err = ionic_adminq_post(lif, ctx);
288288
if (err) {
289-
name = ionic_opcode_to_str(ctx->cmd.cmd.opcode);
290-
netdev_err(netdev, "Posting of %s (%d) failed: %d\n",
291-
name, ctx->cmd.cmd.opcode, err);
289+
if (!test_bit(IONIC_LIF_F_FW_RESET, lif->state)) {
290+
name = ionic_opcode_to_str(ctx->cmd.cmd.opcode);
291+
netdev_err(netdev, "Posting of %s (%d) failed: %d\n",
292+
name, ctx->cmd.cmd.opcode, err);
293+
}
292294
return err;
293295
}
294296

0 commit comments

Comments
 (0)