Commit 0629d245 authored by David S. Miller's avatar David S. Miller

Merge branch 'ionic-updates'

Shannon Nelson says:

====================
ionic updates

These are a few of the driver updates we've been working on internally.
These clean up a few mismatched struct comments, add checking for dead
firmware, fix an initialization bug, and change the Rx buffer management.

These are based on net-next v5.4-rc3-709-g985fd98a.

v2: clear napi->skb in the error case in ionic_rx_frags()
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e4b5c7a5 63ad1cd6
...@@ -12,7 +12,7 @@ struct ionic_lif; ...@@ -12,7 +12,7 @@ struct ionic_lif;
#define IONIC_DRV_NAME "ionic" #define IONIC_DRV_NAME "ionic"
#define IONIC_DRV_DESCRIPTION "Pensando Ethernet NIC Driver" #define IONIC_DRV_DESCRIPTION "Pensando Ethernet NIC Driver"
#define IONIC_DRV_VERSION "0.15.0-k" #define IONIC_DRV_VERSION "0.18.0-k"
#define PCI_VENDOR_ID_PENSANDO 0x1dd8 #define PCI_VENDOR_ID_PENSANDO 0x1dd8
...@@ -46,6 +46,8 @@ struct ionic { ...@@ -46,6 +46,8 @@ struct ionic {
DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX); DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX);
struct work_struct nb_work; struct work_struct nb_work;
struct notifier_block nb; struct notifier_block nb;
struct timer_list watchdog_timer;
int watchdog_period;
}; };
struct ionic_admin_ctx { struct ionic_admin_ctx {
......
...@@ -11,6 +11,16 @@ ...@@ -11,6 +11,16 @@
#include "ionic_dev.h" #include "ionic_dev.h"
#include "ionic_lif.h" #include "ionic_lif.h"
static void ionic_watchdog_cb(struct timer_list *t)
{
struct ionic *ionic = from_timer(ionic, t, watchdog_timer);
mod_timer(&ionic->watchdog_timer,
round_jiffies(jiffies + ionic->watchdog_period));
ionic_heartbeat_check(ionic);
}
void ionic_init_devinfo(struct ionic *ionic) void ionic_init_devinfo(struct ionic *ionic)
{ {
struct ionic_dev *idev = &ionic->idev; struct ionic_dev *idev = &ionic->idev;
...@@ -72,6 +82,11 @@ int ionic_dev_setup(struct ionic *ionic) ...@@ -72,6 +82,11 @@ int ionic_dev_setup(struct ionic *ionic)
return -EFAULT; return -EFAULT;
} }
timer_setup(&ionic->watchdog_timer, ionic_watchdog_cb, 0);
ionic->watchdog_period = IONIC_WATCHDOG_SECS * HZ;
mod_timer(&ionic->watchdog_timer,
round_jiffies(jiffies + ionic->watchdog_period));
idev->db_pages = bar->vaddr; idev->db_pages = bar->vaddr;
idev->phy_db_pages = bar->bus_addr; idev->phy_db_pages = bar->bus_addr;
...@@ -80,10 +95,53 @@ int ionic_dev_setup(struct ionic *ionic) ...@@ -80,10 +95,53 @@ int ionic_dev_setup(struct ionic *ionic)
void ionic_dev_teardown(struct ionic *ionic) void ionic_dev_teardown(struct ionic *ionic)
{ {
/* place holder */ del_timer_sync(&ionic->watchdog_timer);
} }
/* Devcmd Interface */ /* Devcmd Interface */
int ionic_heartbeat_check(struct ionic *ionic)
{
struct ionic_dev *idev = &ionic->idev;
unsigned long hb_time;
u32 fw_status;
u32 hb;
/* wait a little more than one second before testing again */
hb_time = jiffies;
if (time_before(hb_time, (idev->last_hb_time + ionic->watchdog_period)))
return 0;
/* firmware is useful only if fw_status is non-zero */
fw_status = ioread32(&idev->dev_info_regs->fw_status);
if (!fw_status)
return -ENXIO;
/* early FW has no heartbeat, else FW will return non-zero */
hb = ioread32(&idev->dev_info_regs->fw_heartbeat);
if (!hb)
return 0;
/* are we stalled? */
if (hb == idev->last_hb) {
/* only complain once for each stall seen */
if (idev->last_hb_time != 1) {
dev_info(ionic->dev, "FW heartbeat stalled at %d\n",
idev->last_hb);
idev->last_hb_time = 1;
}
return -ENXIO;
}
if (idev->last_hb_time == 1)
dev_info(ionic->dev, "FW heartbeat restored at %d\n", hb);
idev->last_hb = hb;
idev->last_hb_time = hb_time;
return 0;
}
u8 ionic_dev_cmd_status(struct ionic_dev *idev) u8 ionic_dev_cmd_status(struct ionic_dev *idev)
{ {
return ioread8(&idev->dev_cmd_regs->comp.comp.status); return ioread8(&idev->dev_cmd_regs->comp.comp.status);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#define IONIC_MIN_TXRX_DESC 16 #define IONIC_MIN_TXRX_DESC 16
#define IONIC_DEF_TXRX_DESC 4096 #define IONIC_DEF_TXRX_DESC 4096
#define IONIC_LIFS_MAX 1024 #define IONIC_LIFS_MAX 1024
#define IONIC_WATCHDOG_SECS 5
#define IONIC_ITR_COAL_USEC_DEFAULT 64 #define IONIC_ITR_COAL_USEC_DEFAULT 64
#define IONIC_DEV_CMD_REG_VERSION 1 #define IONIC_DEV_CMD_REG_VERSION 1
...@@ -123,6 +124,9 @@ struct ionic_dev { ...@@ -123,6 +124,9 @@ struct ionic_dev {
union ionic_dev_info_regs __iomem *dev_info_regs; union ionic_dev_info_regs __iomem *dev_info_regs;
union ionic_dev_cmd_regs __iomem *dev_cmd_regs; union ionic_dev_cmd_regs __iomem *dev_cmd_regs;
unsigned long last_hb_time;
u32 last_hb;
u64 __iomem *db_pages; u64 __iomem *db_pages;
dma_addr_t phy_db_pages; dma_addr_t phy_db_pages;
...@@ -151,12 +155,19 @@ typedef void (*ionic_desc_cb)(struct ionic_queue *q, ...@@ -151,12 +155,19 @@ typedef void (*ionic_desc_cb)(struct ionic_queue *q,
struct ionic_desc_info *desc_info, struct ionic_desc_info *desc_info,
struct ionic_cq_info *cq_info, void *cb_arg); struct ionic_cq_info *cq_info, void *cb_arg);
struct ionic_page_info {
struct page *page;
dma_addr_t dma_addr;
};
struct ionic_desc_info { struct ionic_desc_info {
void *desc; void *desc;
void *sg_desc; void *sg_desc;
struct ionic_desc_info *next; struct ionic_desc_info *next;
unsigned int index; unsigned int index;
unsigned int left; unsigned int left;
unsigned int npages;
struct ionic_page_info pages[IONIC_RX_MAX_SG_ELEMS + 1];
ionic_desc_cb cb; ionic_desc_cb cb;
void *cb_arg; void *cb_arg;
}; };
...@@ -295,5 +306,6 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb, ...@@ -295,5 +306,6 @@ void ionic_q_post(struct ionic_queue *q, bool ring_doorbell, ionic_desc_cb cb,
void ionic_q_rewind(struct ionic_queue *q, struct ionic_desc_info *start); void ionic_q_rewind(struct ionic_queue *q, struct ionic_desc_info *start);
void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info, void ionic_q_service(struct ionic_queue *q, struct ionic_cq_info *cq_info,
unsigned int stop_index); unsigned int stop_index);
int ionic_heartbeat_check(struct ionic *ionic);
#endif /* _IONIC_DEV_H_ */ #endif /* _IONIC_DEV_H_ */
...@@ -622,12 +622,14 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq) ...@@ -622,12 +622,14 @@ static int ionic_lif_rxq_init(struct ionic_lif *lif, struct ionic_qcq *qcq)
.lif_index = cpu_to_le16(lif->index), .lif_index = cpu_to_le16(lif->index),
.type = q->type, .type = q->type,
.index = cpu_to_le32(q->index), .index = cpu_to_le32(q->index),
.flags = cpu_to_le16(IONIC_QINIT_F_IRQ), .flags = cpu_to_le16(IONIC_QINIT_F_IRQ |
IONIC_QINIT_F_SG),
.intr_index = cpu_to_le16(cq->bound_intr->index), .intr_index = cpu_to_le16(cq->bound_intr->index),
.pid = cpu_to_le16(q->pid), .pid = cpu_to_le16(q->pid),
.ring_size = ilog2(q->num_descs), .ring_size = ilog2(q->num_descs),
.ring_base = cpu_to_le64(q->base_pa), .ring_base = cpu_to_le64(q->base_pa),
.cq_ring_base = cpu_to_le64(cq->base_pa), .cq_ring_base = cpu_to_le64(cq->base_pa),
.sg_ring_base = cpu_to_le64(q->sg_base_pa),
}, },
}; };
int err; int err;
...@@ -1460,13 +1462,14 @@ static int ionic_txrx_alloc(struct ionic_lif *lif) ...@@ -1460,13 +1462,14 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
lif->txqcqs[i].qcq->stats = lif->txqcqs[i].stats; lif->txqcqs[i].qcq->stats = lif->txqcqs[i].stats;
} }
flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_INTR; flags = IONIC_QCQ_F_RX_STATS | IONIC_QCQ_F_SG | IONIC_QCQ_F_INTR;
for (i = 0; i < lif->nxqs; i++) { for (i = 0; i < lif->nxqs; i++) {
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
lif->nrxq_descs, lif->nrxq_descs,
sizeof(struct ionic_rxq_desc), sizeof(struct ionic_rxq_desc),
sizeof(struct ionic_rxq_comp), sizeof(struct ionic_rxq_comp),
0, lif->kern_pid, &lif->rxqcqs[i].qcq); sizeof(struct ionic_rxq_sg_desc),
lif->kern_pid, &lif->rxqcqs[i].qcq);
if (err) if (err)
goto err_out; goto err_out;
...@@ -1686,7 +1689,7 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index ...@@ -1686,7 +1689,7 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
/* Convert the default coalesce value to actual hw resolution */ /* Convert the default coalesce value to actual hw resolution */
lif->rx_coalesce_usecs = IONIC_ITR_COAL_USEC_DEFAULT; lif->rx_coalesce_usecs = IONIC_ITR_COAL_USEC_DEFAULT;
lif->rx_coalesce_hw = ionic_coal_hw_to_usec(lif->ionic, lif->rx_coalesce_hw = ionic_coal_usec_to_hw(lif->ionic,
lif->rx_coalesce_usecs); lif->rx_coalesce_usecs);
snprintf(lif->name, sizeof(lif->name), "lif%u", index); snprintf(lif->name, sizeof(lif->name), "lif%u", index);
......
...@@ -245,6 +245,10 @@ static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx) ...@@ -245,6 +245,10 @@ static int ionic_adminq_post(struct ionic_lif *lif, struct ionic_admin_ctx *ctx)
goto err_out; goto err_out;
} }
err = ionic_heartbeat_check(lif->ionic);
if (err)
goto err_out;
memcpy(adminq->head->desc, &ctx->cmd, sizeof(ctx->cmd)); memcpy(adminq->head->desc, &ctx->cmd, sizeof(ctx->cmd));
dev_dbg(&lif->netdev->dev, "post admin queue command:\n"); dev_dbg(&lif->netdev->dev, "post admin queue command:\n");
...@@ -305,6 +309,14 @@ int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb, ...@@ -305,6 +309,14 @@ int ionic_napi(struct napi_struct *napi, int budget, ionic_cq_cb cb,
return work_done; return work_done;
} }
static void ionic_dev_cmd_clean(struct ionic *ionic)
{
union ionic_dev_cmd_regs *regs = ionic->idev.dev_cmd_regs;
iowrite32(0, &regs->doorbell);
memset_io(&regs->cmd, 0, sizeof(regs->cmd));
}
int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
{ {
struct ionic_dev *idev = &ionic->idev; struct ionic_dev *idev = &ionic->idev;
...@@ -314,6 +326,7 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) ...@@ -314,6 +326,7 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
int opcode; int opcode;
int done; int done;
int err; int err;
int hb;
WARN_ON(in_interrupt()); WARN_ON(in_interrupt());
...@@ -328,7 +341,8 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) ...@@ -328,7 +341,8 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
if (done) if (done)
break; break;
msleep(20); msleep(20);
} while (!done && time_before(jiffies, max_wait)); hb = ionic_heartbeat_check(ionic);
} while (!done && !hb && time_before(jiffies, max_wait));
duration = jiffies - start_time; duration = jiffies - start_time;
opcode = idev->dev_cmd_regs->cmd.cmd.opcode; opcode = idev->dev_cmd_regs->cmd.cmd.opcode;
...@@ -336,7 +350,15 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds) ...@@ -336,7 +350,15 @@ int ionic_dev_cmd_wait(struct ionic *ionic, unsigned long max_seconds)
ionic_opcode_to_str(opcode), opcode, ionic_opcode_to_str(opcode), opcode,
done, duration / HZ, duration); done, duration / HZ, duration);
if (!done && hb) {
ionic_dev_cmd_clean(ionic);
dev_warn(ionic->dev, "DEVCMD %s (%d) failed - FW halted\n",
ionic_opcode_to_str(opcode), opcode);
return -ENXIO;
}
if (!done && !time_before(jiffies, max_wait)) { if (!done && !time_before(jiffies, max_wait)) {
ionic_dev_cmd_clean(ionic);
dev_warn(ionic->dev, "DEVCMD %s (%d) timeout after %ld secs\n", dev_warn(ionic->dev, "DEVCMD %s (%d) timeout after %ld secs\n",
ionic_opcode_to_str(opcode), opcode, max_seconds); ionic_opcode_to_str(opcode), opcode, max_seconds);
return -ETIMEDOUT; return -ETIMEDOUT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment