Skip to content

Commit 34ad937

Browse files
committed
Merge branch 'ionic-error-recovery'
Shannon Nelson says: ==================== ionic error recovery This set of patches comes mostly from error recovery path testing, as well as a couple of upstream review comments. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 7b419e6 + 9e15410 commit 34ad937

File tree

4 files changed

+134
-88
lines changed

4 files changed

+134
-88
lines changed

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
266266
dev_err(dev, "Cannot identify device: %d, aborting\n", err);
267267
goto err_out_teardown;
268268
}
269+
ionic_debugfs_add_ident(ionic);
269270

270271
err = ionic_init(ionic);
271272
if (err) {
@@ -286,14 +287,7 @@ static int ionic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
286287
goto err_out_reset;
287288
}
288289

289-
/* Configure LIFs */
290-
err = ionic_lif_identify(ionic, IONIC_LIF_TYPE_CLASSIC,
291-
&ionic->ident.lif);
292-
if (err) {
293-
dev_err(dev, "Cannot identify LIFs: %d, aborting\n", err);
294-
goto err_out_port_reset;
295-
}
296-
290+
/* Allocate and init the LIF */
297291
err = ionic_lif_size(ionic);
298292
if (err) {
299293
dev_err(dev, "Cannot size LIF: %d, aborting\n", err);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ enum ionic_status_code {
9696
IONIC_RC_ERROR = 29, /* Generic error */
9797
IONIC_RC_ERDMA = 30, /* Generic RDMA error */
9898
IONIC_RC_EVFID = 31, /* VF ID does not exist */
99+
IONIC_RC_EBAD_FW = 32, /* FW file is invalid or corrupted */
99100
};
100101

101102
enum ionic_notifyq_opcode {

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

Lines changed: 118 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,18 @@ static void ionic_lif_deferred_work(struct work_struct *work)
6262
struct ionic_deferred *def = &lif->deferred;
6363
struct ionic_deferred_work *w = NULL;
6464

65-
spin_lock_bh(&def->lock);
66-
if (!list_empty(&def->list)) {
67-
w = list_first_entry(&def->list,
68-
struct ionic_deferred_work, list);
69-
list_del(&w->list);
70-
}
71-
spin_unlock_bh(&def->lock);
65+
do {
66+
spin_lock_bh(&def->lock);
67+
if (!list_empty(&def->list)) {
68+
w = list_first_entry(&def->list,
69+
struct ionic_deferred_work, list);
70+
list_del(&w->list);
71+
}
72+
spin_unlock_bh(&def->lock);
73+
74+
if (!w)
75+
break;
7276

73-
if (w) {
7477
switch (w->type) {
7578
case IONIC_DW_TYPE_RX_MODE:
7679
ionic_lif_rx_mode(lif, w->rx_mode);
@@ -94,8 +97,8 @@ static void ionic_lif_deferred_work(struct work_struct *work)
9497
break;
9598
}
9699
kfree(w);
97-
schedule_work(&def->work);
98-
}
100+
w = NULL;
101+
} while (true);
99102
}
100103

101104
void ionic_lif_deferred_enqueue(struct ionic_deferred *def,
@@ -161,8 +164,10 @@ void ionic_link_status_check_request(struct ionic_lif *lif, bool can_sleep)
161164

162165
if (!can_sleep) {
163166
work = kzalloc(sizeof(*work), GFP_ATOMIC);
164-
if (!work)
167+
if (!work) {
168+
clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state);
165169
return;
170+
}
166171

167172
work->type = IONIC_DW_TYPE_LINK_STATUS;
168173
ionic_lif_deferred_enqueue(&lif->deferred, work);
@@ -259,31 +264,29 @@ static int ionic_qcq_enable(struct ionic_qcq *qcq)
259264
return ionic_adminq_post_wait(lif, &ctx);
260265
}
261266

262-
static int ionic_qcq_disable(struct ionic_qcq *qcq)
267+
static int ionic_qcq_disable(struct ionic_qcq *qcq, bool send_to_hw)
263268
{
264-
struct ionic_queue *q = &qcq->q;
265-
struct ionic_lif *lif = q->lif;
266-
struct ionic_dev *idev;
267-
struct device *dev;
269+
struct ionic_queue *q;
270+
struct ionic_lif *lif;
271+
int err = 0;
268272

269273
struct ionic_admin_ctx ctx = {
270274
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
271275
.cmd.q_control = {
272276
.opcode = IONIC_CMD_Q_CONTROL,
273-
.lif_index = cpu_to_le16(lif->index),
274-
.type = q->type,
275-
.index = cpu_to_le32(q->index),
276277
.oper = IONIC_Q_DISABLE,
277278
},
278279
};
279280

280-
idev = &lif->ionic->idev;
281-
dev = lif->ionic->dev;
281+
if (!qcq)
282+
return -ENXIO;
282283

283-
dev_dbg(dev, "q_disable.index %d q_disable.qtype %d\n",
284-
ctx.cmd.q_control.index, ctx.cmd.q_control.type);
284+
q = &qcq->q;
285+
lif = q->lif;
285286

286287
if (qcq->flags & IONIC_QCQ_F_INTR) {
288+
struct ionic_dev *idev = &lif->ionic->idev;
289+
287290
cancel_work_sync(&qcq->dim.work);
288291
ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
289292
IONIC_INTR_MASK_SET);
@@ -292,7 +295,17 @@ static int ionic_qcq_disable(struct ionic_qcq *qcq)
292295
napi_disable(&qcq->napi);
293296
}
294297

295-
return ionic_adminq_post_wait(lif, &ctx);
298+
if (send_to_hw) {
299+
ctx.cmd.q_control.lif_index = cpu_to_le16(lif->index);
300+
ctx.cmd.q_control.type = q->type;
301+
ctx.cmd.q_control.index = cpu_to_le32(q->index);
302+
dev_dbg(lif->ionic->dev, "q_disable.index %d q_disable.qtype %d\n",
303+
ctx.cmd.q_control.index, ctx.cmd.q_control.type);
304+
305+
err = ionic_adminq_post_wait(lif, &ctx);
306+
}
307+
308+
return err;
296309
}
297310

298311
static void ionic_lif_qcq_deinit(struct ionic_lif *lif, struct ionic_qcq *qcq)
@@ -518,30 +531,55 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
518531
goto err_out_free_cq_info;
519532
}
520533

521-
new->q_size = PAGE_SIZE + (num_descs * desc_size);
522-
new->q_base = dma_alloc_coherent(dev, new->q_size, &new->q_base_pa,
523-
GFP_KERNEL);
524-
if (!new->q_base) {
525-
netdev_err(lif->netdev, "Cannot allocate queue DMA memory\n");
526-
err = -ENOMEM;
527-
goto err_out_free_cq_info;
528-
}
529-
q_base = PTR_ALIGN(new->q_base, PAGE_SIZE);
530-
q_base_pa = ALIGN(new->q_base_pa, PAGE_SIZE);
531-
ionic_q_map(&new->q, q_base, q_base_pa);
534+
if (flags & IONIC_QCQ_F_NOTIFYQ) {
535+
int q_size, cq_size;
532536

533-
new->cq_size = PAGE_SIZE + (num_descs * cq_desc_size);
534-
new->cq_base = dma_alloc_coherent(dev, new->cq_size, &new->cq_base_pa,
535-
GFP_KERNEL);
536-
if (!new->cq_base) {
537-
netdev_err(lif->netdev, "Cannot allocate cq DMA memory\n");
538-
err = -ENOMEM;
539-
goto err_out_free_q;
537+
/* q & cq need to be contiguous in case of notifyq */
538+
q_size = ALIGN(num_descs * desc_size, PAGE_SIZE);
539+
cq_size = ALIGN(num_descs * cq_desc_size, PAGE_SIZE);
540+
541+
new->q_size = PAGE_SIZE + q_size + cq_size;
542+
new->q_base = dma_alloc_coherent(dev, new->q_size,
543+
&new->q_base_pa, GFP_KERNEL);
544+
if (!new->q_base) {
545+
netdev_err(lif->netdev, "Cannot allocate qcq DMA memory\n");
546+
err = -ENOMEM;
547+
goto err_out_free_cq_info;
548+
}
549+
q_base = PTR_ALIGN(new->q_base, PAGE_SIZE);
550+
q_base_pa = ALIGN(new->q_base_pa, PAGE_SIZE);
551+
ionic_q_map(&new->q, q_base, q_base_pa);
552+
553+
cq_base = PTR_ALIGN(q_base + q_size, PAGE_SIZE);
554+
cq_base_pa = ALIGN(new->q_base_pa + q_size, PAGE_SIZE);
555+
ionic_cq_map(&new->cq, cq_base, cq_base_pa);
556+
ionic_cq_bind(&new->cq, &new->q);
557+
} else {
558+
new->q_size = PAGE_SIZE + (num_descs * desc_size);
559+
new->q_base = dma_alloc_coherent(dev, new->q_size, &new->q_base_pa,
560+
GFP_KERNEL);
561+
if (!new->q_base) {
562+
netdev_err(lif->netdev, "Cannot allocate queue DMA memory\n");
563+
err = -ENOMEM;
564+
goto err_out_free_cq_info;
565+
}
566+
q_base = PTR_ALIGN(new->q_base, PAGE_SIZE);
567+
q_base_pa = ALIGN(new->q_base_pa, PAGE_SIZE);
568+
ionic_q_map(&new->q, q_base, q_base_pa);
569+
570+
new->cq_size = PAGE_SIZE + (num_descs * cq_desc_size);
571+
new->cq_base = dma_alloc_coherent(dev, new->cq_size, &new->cq_base_pa,
572+
GFP_KERNEL);
573+
if (!new->cq_base) {
574+
netdev_err(lif->netdev, "Cannot allocate cq DMA memory\n");
575+
err = -ENOMEM;
576+
goto err_out_free_q;
577+
}
578+
cq_base = PTR_ALIGN(new->cq_base, PAGE_SIZE);
579+
cq_base_pa = ALIGN(new->cq_base_pa, PAGE_SIZE);
580+
ionic_cq_map(&new->cq, cq_base, cq_base_pa);
581+
ionic_cq_bind(&new->cq, &new->q);
540582
}
541-
cq_base = PTR_ALIGN(new->cq_base, PAGE_SIZE);
542-
cq_base_pa = ALIGN(new->cq_base_pa, PAGE_SIZE);
543-
ionic_cq_map(&new->cq, cq_base, cq_base_pa);
544-
ionic_cq_bind(&new->cq, &new->q);
545583

546584
if (flags & IONIC_QCQ_F_SG) {
547585
new->sg_size = PAGE_SIZE + (num_descs * sg_desc_size);
@@ -984,7 +1022,6 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr)
9841022
static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add,
9851023
bool can_sleep)
9861024
{
987-
struct ionic *ionic = lif->ionic;
9881025
struct ionic_deferred_work *work;
9891026
unsigned int nmfilters;
9901027
unsigned int nufilters;
@@ -994,8 +1031,8 @@ static int ionic_lif_addr(struct ionic_lif *lif, const u8 *addr, bool add,
9941031
* here before checking the need for deferral so that we
9951032
* can return an overflow error to the stack.
9961033
*/
997-
nmfilters = le32_to_cpu(ionic->ident.lif.eth.max_mcast_filters);
998-
nufilters = le32_to_cpu(ionic->ident.lif.eth.max_ucast_filters);
1034+
nmfilters = le32_to_cpu(lif->identity->eth.max_mcast_filters);
1035+
nufilters = le32_to_cpu(lif->identity->eth.max_ucast_filters);
9991036

10001037
if ((is_multicast_ether_addr(addr) && lif->nmcast < nmfilters))
10011038
lif->nmcast++;
@@ -1124,12 +1161,9 @@ static void ionic_dev_uc_sync(struct net_device *netdev, bool from_ndo)
11241161
static void ionic_set_rx_mode(struct net_device *netdev, bool from_ndo)
11251162
{
11261163
struct ionic_lif *lif = netdev_priv(netdev);
1127-
struct ionic_identity *ident;
11281164
unsigned int nfilters;
11291165
unsigned int rx_mode;
11301166

1131-
ident = &lif->ionic->ident;
1132-
11331167
rx_mode = IONIC_RX_MODE_F_UNICAST;
11341168
rx_mode |= (netdev->flags & IFF_MULTICAST) ? IONIC_RX_MODE_F_MULTICAST : 0;
11351169
rx_mode |= (netdev->flags & IFF_BROADCAST) ? IONIC_RX_MODE_F_BROADCAST : 0;
@@ -1144,7 +1178,7 @@ static void ionic_set_rx_mode(struct net_device *netdev, bool from_ndo)
11441178
* to see if we can disable NIC PROMISC
11451179
*/
11461180
ionic_dev_uc_sync(netdev, from_ndo);
1147-
nfilters = le32_to_cpu(ident->lif.eth.max_ucast_filters);
1181+
nfilters = le32_to_cpu(lif->identity->eth.max_ucast_filters);
11481182
if (netdev_uc_count(netdev) + 1 > nfilters) {
11491183
rx_mode |= IONIC_RX_MODE_F_PROMISC;
11501184
lif->uc_overflow = true;
@@ -1156,7 +1190,7 @@ static void ionic_set_rx_mode(struct net_device *netdev, bool from_ndo)
11561190

11571191
/* same for multicast */
11581192
ionic_dev_uc_sync(netdev, from_ndo);
1159-
nfilters = le32_to_cpu(ident->lif.eth.max_mcast_filters);
1193+
nfilters = le32_to_cpu(lif->identity->eth.max_mcast_filters);
11601194
if (netdev_mc_count(netdev) > nfilters) {
11611195
rx_mode |= IONIC_RX_MODE_F_ALLMULTI;
11621196
lif->mc_overflow = true;
@@ -1594,22 +1628,16 @@ static void ionic_lif_rss_deinit(struct ionic_lif *lif)
15941628
static void ionic_txrx_disable(struct ionic_lif *lif)
15951629
{
15961630
unsigned int i;
1597-
int err;
1631+
int err = 0;
15981632

15991633
if (lif->txqcqs) {
1600-
for (i = 0; i < lif->nxqs; i++) {
1601-
err = ionic_qcq_disable(lif->txqcqs[i]);
1602-
if (err == -ETIMEDOUT)
1603-
break;
1604-
}
1634+
for (i = 0; i < lif->nxqs; i++)
1635+
err = ionic_qcq_disable(lif->txqcqs[i], (err != -ETIMEDOUT));
16051636
}
16061637

16071638
if (lif->rxqcqs) {
1608-
for (i = 0; i < lif->nxqs; i++) {
1609-
err = ionic_qcq_disable(lif->rxqcqs[i]);
1610-
if (err == -ETIMEDOUT)
1611-
break;
1612-
}
1639+
for (i = 0; i < lif->nxqs; i++)
1640+
err = ionic_qcq_disable(lif->rxqcqs[i], (err != -ETIMEDOUT));
16131641
}
16141642
}
16151643

@@ -1761,18 +1789,24 @@ static int ionic_txrx_init(struct ionic_lif *lif)
17611789

17621790
static int ionic_txrx_enable(struct ionic_lif *lif)
17631791
{
1792+
int derr = 0;
17641793
int i, err;
17651794

17661795
for (i = 0; i < lif->nxqs; i++) {
1796+
if (!(lif->rxqcqs[i] && lif->txqcqs[i])) {
1797+
dev_err(lif->ionic->dev, "%s: bad qcq %d\n", __func__, i);
1798+
err = -ENXIO;
1799+
goto err_out;
1800+
}
1801+
17671802
ionic_rx_fill(&lif->rxqcqs[i]->q);
17681803
err = ionic_qcq_enable(lif->rxqcqs[i]);
17691804
if (err)
17701805
goto err_out;
17711806

17721807
err = ionic_qcq_enable(lif->txqcqs[i]);
17731808
if (err) {
1774-
if (err != -ETIMEDOUT)
1775-
ionic_qcq_disable(lif->rxqcqs[i]);
1809+
derr = ionic_qcq_disable(lif->rxqcqs[i], (err != -ETIMEDOUT));
17761810
goto err_out;
17771811
}
17781812
}
@@ -1781,12 +1815,8 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
17811815

17821816
err_out:
17831817
while (i--) {
1784-
err = ionic_qcq_disable(lif->txqcqs[i]);
1785-
if (err == -ETIMEDOUT)
1786-
break;
1787-
err = ionic_qcq_disable(lif->rxqcqs[i]);
1788-
if (err == -ETIMEDOUT)
1789-
break;
1818+
derr = ionic_qcq_disable(lif->txqcqs[i], (derr != -ETIMEDOUT));
1819+
derr = ionic_qcq_disable(lif->rxqcqs[i], (derr != -ETIMEDOUT));
17901820
}
17911821

17921822
return err;
@@ -2391,7 +2421,12 @@ int ionic_lif_alloc(struct ionic *ionic)
23912421

23922422
lif->identity = lid;
23932423
lif->lif_type = IONIC_LIF_TYPE_CLASSIC;
2394-
ionic_lif_identify(ionic, lif->lif_type, lif->identity);
2424+
err = ionic_lif_identify(ionic, lif->lif_type, lif->identity);
2425+
if (err) {
2426+
dev_err(ionic->dev, "Cannot identify type %d: %d\n",
2427+
lif->lif_type, err);
2428+
goto err_out_free_netdev;
2429+
}
23952430
lif->netdev->min_mtu = max_t(unsigned int, ETH_MIN_MTU,
23962431
le32_to_cpu(lif->identity->eth.min_frame_size));
23972432
lif->netdev->max_mtu =
@@ -2522,7 +2557,15 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
25222557
dev_info(ionic->dev, "FW Up: restarting LIFs\n");
25232558

25242559
ionic_init_devinfo(ionic);
2525-
ionic_port_init(ionic);
2560+
err = ionic_identify(ionic);
2561+
if (err)
2562+
goto err_out;
2563+
err = ionic_port_identify(ionic);
2564+
if (err)
2565+
goto err_out;
2566+
err = ionic_port_init(ionic);
2567+
if (err)
2568+
goto err_out;
25262569
err = ionic_qcqs_alloc(lif);
25272570
if (err)
25282571
goto err_out;

0 commit comments

Comments
 (0)