diff options
author | David S. Miller <davem@davemloft.net> | 2021-07-27 20:15:31 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-07-27 20:15:31 +0100 |
commit | 2f21be447bf0eed63a5c8999a6c449b37e2c6180 (patch) | |
tree | 0d5004f7bb679806520fa46c3f7234b37a425e50 | |
parent | 7c57706b4be5cf85ded0721c0619a2122b846c18 (diff) | |
parent | 18d6426402deaac0f748bd4476c977ea4bca3b12 (diff) | |
download | linux-2f21be447bf0eed63a5c8999a6c449b37e2c6180.tar.bz2 |
Merge branch 'ionic-next'
Shannon Nelson says:
====================
ionic: driver updates 27-July-2021
This is a collection of small driver updates for adding a couple of
small features and for a bit of code cleaning.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_dev.c | 28 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_dev.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_ethtool.c | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_if.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_lif.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_phc.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/pensando/ionic/ionic_txrx.c | 27 |
9 files changed, 100 insertions, 30 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c index 505f605fa40b..7e296fa71b36 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c @@ -165,10 +165,10 @@ static int ionic_vf_alloc(struct ionic *ionic, int num_vfs) goto out; } + ionic->num_vfs++; /* ignore failures from older FW, we just won't get stats */ (void)ionic_set_vf_config(ionic, i, IONIC_VF_ATTR_STATSADDR, (u8 *)&v->stats_pa); - ionic->num_vfs++; } out: diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c index 1dfe962e22e0..9aac647290f7 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c @@ -106,6 +106,8 @@ int ionic_dev_setup(struct ionic *ionic) idev->last_fw_hb = 0; idev->fw_hb_ready = true; idev->fw_status_ready = true; + idev->fw_generation = IONIC_FW_STS_F_GENERATION & + ioread8(&idev->dev_info_regs->fw_status); mod_timer(&ionic->watchdog_timer, round_jiffies(jiffies + ionic->watchdog_period)); @@ -121,7 +123,9 @@ int ionic_heartbeat_check(struct ionic *ionic) { struct ionic_dev *idev = &ionic->idev; unsigned long check_time, last_check_time; - bool fw_status_ready, fw_hb_ready; + bool fw_status_ready = true; + bool fw_hb_ready; + u8 fw_generation; u8 fw_status; u32 fw_hb; @@ -140,9 +144,29 @@ do_check_time: /* firmware is useful only if the running bit is set and * fw_status != 0xff (bad PCI read) + * If fw_status is not ready don't bother with the generation. */ fw_status = ioread8(&idev->dev_info_regs->fw_status); - fw_status_ready = (fw_status != 0xff) && (fw_status & IONIC_FW_STS_F_RUNNING); + + if (fw_status == 0xff || !(fw_status & IONIC_FW_STS_F_RUNNING)) { + fw_status_ready = false; + } else { + fw_generation = fw_status & IONIC_FW_STS_F_GENERATION; + if (idev->fw_generation != fw_generation) { + dev_info(ionic->dev, "FW generation 0x%02x -> 0x%02x\n", + idev->fw_generation, fw_generation); + + idev->fw_generation = fw_generation; + + /* If the generation changed, the fw status is not + * ready so we need to trigger a fw-down cycle. After + * the down, the next watchdog will see the fw is up + * and the generation value stable, so will trigger + * the fw-up activity. + */ + fw_status_ready = false; + } + } /* is this a transition? */ if (fw_status_ready != idev->fw_status_ready) { diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h index c25cf9b744c5..8311086fb1f4 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h @@ -143,6 +143,7 @@ struct ionic_dev { u32 last_fw_hb; bool fw_hb_ready; bool fw_status_ready; + u8 fw_generation; u64 __iomem *db_pages; dma_addr_t phy_db_pages; @@ -160,8 +161,6 @@ struct ionic_dev { struct ionic_cq_info { union { void *cq_desc; - struct ionic_txq_comp *txcq; - struct ionic_rxq_comp *rxcq; struct ionic_admin_comp *admincq; struct ionic_notifyq_event *notifyq; }; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c index 6583be570e45..adc9fdb03e86 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -32,6 +32,9 @@ static void ionic_get_stats(struct net_device *netdev, struct ionic_lif *lif = netdev_priv(netdev); u32 i; + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return; + memset(buf, 0, stats->n_stats * sizeof(*buf)); for (i = 0; i < ionic_num_stats_grps; i++) ionic_stats_groups[i].get_values(lif, &buf); @@ -274,6 +277,9 @@ static int ionic_set_link_ksettings(struct net_device *netdev, struct ionic *ionic = lif->ionic; int err = 0; + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return -EBUSY; + /* set autoneg */ if (ks->base.autoneg != idev->port_info->config.an_enable) { mutex_lock(&ionic->dev_cmd_lock); @@ -320,6 +326,9 @@ static int ionic_set_pauseparam(struct net_device *netdev, u32 requested_pause; int err; + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return -EBUSY; + if (pause->autoneg) return -EOPNOTSUPP; @@ -372,6 +381,9 @@ static int ionic_set_fecparam(struct net_device *netdev, u8 fec_type; int ret = 0; + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return -EBUSY; + if (lif->ionic->idev.port_info->config.an_enable) { netdev_err(netdev, "FEC request not allowed while autoneg is enabled\n"); return -EINVAL; @@ -528,6 +540,9 @@ static int ionic_set_ringparam(struct net_device *netdev, struct ionic_queue_params qparam; int err; + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return -EBUSY; + ionic_init_queue_params(lif, &qparam); if (ring->rx_mini_pending || ring->rx_jumbo_pending) { @@ -597,6 +612,9 @@ static int ionic_set_channels(struct net_device *netdev, int max_cnt; int err; + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return -EBUSY; + ionic_init_queue_params(lif, &qparam); if (ch->rx_count != ch->tx_count) { @@ -947,6 +965,9 @@ static int ionic_nway_reset(struct net_device *netdev) struct ionic *ionic = lif->ionic; int err = 0; + if (test_bit(IONIC_LIF_F_FW_RESET, lif->state)) + return -EBUSY; + /* flap the link to force auto-negotiation */ mutex_lock(&ionic->dev_cmd_lock); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h index 0478b48d9895..278610ed7227 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_if.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h @@ -2936,6 +2936,8 @@ struct ionic_hwstamp_regs { * @asic_type: Asic type * @asic_rev: Asic revision * @fw_status: Firmware status + * bit 0 - 1 = fw running + * bit 4-7 - 4 bit generation number, changes on fw restart * @fw_heartbeat: Firmware heartbeat counter * @serial_num: Serial number * @fw_version: Firmware version @@ -2949,7 +2951,8 @@ union ionic_dev_info_regs { u8 version; u8 asic_type; u8 asic_rev; -#define IONIC_FW_STS_F_RUNNING 0x1 +#define IONIC_FW_STS_F_RUNNING 0x01 +#define IONIC_FW_STS_F_GENERATION 0xF0 u8 fw_status; u32 fw_heartbeat; char fw_version[IONIC_DEVINFO_FWVERS_BUFLEN]; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 537c2907b91e..f21f80cee188 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -11,6 +11,7 @@ #include <linux/interrupt.h> #include <linux/pci.h> #include <linux/cpumask.h> +#include <linux/crash_dump.h> #include "ionic.h" #include "ionic_bus.h" @@ -1606,7 +1607,6 @@ static int ionic_init_nic_features(struct ionic_lif *lif) features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER | - NETIF_F_RXHASH | NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM | @@ -1614,6 +1614,9 @@ static int ionic_init_nic_features(struct ionic_lif *lif) NETIF_F_TSO6 | NETIF_F_TSO_ECN; + if (lif->nxqs > 1) + features |= NETIF_F_RXHASH; + err = ionic_set_nic_features(lif, features); if (err) return err; @@ -2587,22 +2590,26 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, struct ionic_qcq **tx_qcqs = NULL; struct ionic_qcq **rx_qcqs = NULL; unsigned int flags, i; - int err = -ENOMEM; + int err = 0; /* allocate temporary qcq arrays to hold new queue structs */ if (qparam->nxqs != lif->nxqs || qparam->ntxq_descs != lif->ntxq_descs) { tx_qcqs = devm_kcalloc(lif->ionic->dev, lif->ionic->ntxqs_per_lif, sizeof(struct ionic_qcq *), GFP_KERNEL); - if (!tx_qcqs) + if (!tx_qcqs) { + err = -ENOMEM; goto err_out; + } } if (qparam->nxqs != lif->nxqs || qparam->nrxq_descs != lif->nrxq_descs || qparam->rxq_features != lif->rxq_features) { rx_qcqs = devm_kcalloc(lif->ionic->dev, lif->ionic->nrxqs_per_lif, sizeof(struct ionic_qcq *), GFP_KERNEL); - if (!rx_qcqs) + if (!rx_qcqs) { + err = -ENOMEM; goto err_out; + } } /* allocate new desc_info and rings, but leave the interrupt setup @@ -2781,6 +2788,9 @@ err_out: ionic_qcq_free(lif, lif->rxqcqs[i]); } + if (err) + netdev_info(lif->netdev, "%s: failed %d\n", __func__, err); + return err; } @@ -2834,8 +2844,14 @@ int ionic_lif_alloc(struct ionic *ionic) lif->ionic = ionic; lif->index = 0; - lif->ntxq_descs = IONIC_DEF_TXRX_DESC; - lif->nrxq_descs = IONIC_DEF_TXRX_DESC; + + if (is_kdump_kernel()) { + lif->ntxq_descs = IONIC_MIN_TXRX_DESC; + lif->nrxq_descs = IONIC_MIN_TXRX_DESC; + } else { + lif->ntxq_descs = IONIC_DEF_TXRX_DESC; + lif->nrxq_descs = IONIC_DEF_TXRX_DESC; + } /* Convert the default coalesce value to actual hw resolution */ lif->rx_coalesce_usecs = IONIC_ITR_COAL_USEC_DEFAULT; @@ -3519,6 +3535,7 @@ int ionic_lif_size(struct ionic *ionic) unsigned int min_intrs; int err; + /* retrieve basic values from FW */ lc = &ident->lif.eth.config; dev_nintrs = le32_to_cpu(ident->dev.nintrs); neqs_per_lif = le32_to_cpu(ident->lif.rdma.eq_qtype.qid_count); @@ -3526,6 +3543,15 @@ int ionic_lif_size(struct ionic *ionic) ntxqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_TXQ]); nrxqs_per_lif = le32_to_cpu(lc->queue_count[IONIC_QTYPE_RXQ]); + /* limit values to play nice with kdump */ + if (is_kdump_kernel()) { + dev_nintrs = 2; + neqs_per_lif = 0; + nnqs_per_lif = 0; + ntxqs_per_lif = 1; + nrxqs_per_lif = 1; + } + /* reserve last queue id for hardware timestamping */ if (lc->features & cpu_to_le64(IONIC_ETH_HW_TIMESTAMP)) { if (ntxqs_per_lif <= 1 || nrxqs_per_lif <= 1) { diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c index 61cfe2120817..5f1e5b6e85c3 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_main.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c @@ -450,6 +450,8 @@ int ionic_identify(struct ionic *ionic) } mutex_unlock(&ionic->dev_cmd_lock); + dev_info(ionic->dev, "FW: %s\n", idev->dev_info.fw_version); + if (err) { dev_err(ionic->dev, "Cannot identify ionic: %dn", err); goto err_out; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_phc.c b/drivers/net/ethernet/pensando/ionic/ionic_phc.c index a87c87e86aef..736ebc5da0f7 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_phc.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_phc.c @@ -119,8 +119,8 @@ static int ionic_lif_hwstamp_set_ts_config(struct ionic_lif *lif, config->rx_filter = HWTSTAMP_FILTER_ALL; } - dev_dbg(ionic->dev, "config_rx_filter %d rx_filt %#llx rx_all %d\n", - config->rx_filter, rx_filt, rx_all); + dev_dbg(ionic->dev, "%s: config_rx_filter %d rx_filt %#llx rx_all %d\n", + __func__, config->rx_filter, rx_filt, rx_all); if (tx_mode) { err = ionic_lif_create_hwstamp_txq(lif); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c index 08934888575c..2ba19246d763 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c @@ -32,19 +32,13 @@ static inline struct netdev_queue *q_to_ndq(struct ionic_queue *q) return netdev_get_tx_queue(q->lif->netdev, q->index); } -static void ionic_rx_buf_reset(struct ionic_buf_info *buf_info) -{ - buf_info->page = NULL; - buf_info->page_offset = 0; - buf_info->dma_addr = 0; -} - static int ionic_rx_page_alloc(struct ionic_queue *q, struct ionic_buf_info *buf_info) { struct net_device *netdev = q->lif->netdev; struct ionic_rx_stats *stats; struct device *dev; + struct page *page; dev = q->dev; stats = q_to_rx_stats(q); @@ -55,26 +49,27 @@ static int ionic_rx_page_alloc(struct ionic_queue *q, return -EINVAL; } - buf_info->page = alloc_pages(IONIC_PAGE_GFP_MASK, 0); - if (unlikely(!buf_info->page)) { + page = alloc_pages(IONIC_PAGE_GFP_MASK, 0); + if (unlikely(!page)) { net_err_ratelimited("%s: %s page alloc failed\n", netdev->name, q->name); stats->alloc_err++; return -ENOMEM; } - buf_info->page_offset = 0; - buf_info->dma_addr = dma_map_page(dev, buf_info->page, buf_info->page_offset, + buf_info->dma_addr = dma_map_page(dev, page, 0, IONIC_PAGE_SIZE, DMA_FROM_DEVICE); if (unlikely(dma_mapping_error(dev, buf_info->dma_addr))) { - __free_pages(buf_info->page, 0); - ionic_rx_buf_reset(buf_info); + __free_pages(page, 0); net_err_ratelimited("%s: %s dma map failed\n", netdev->name, q->name); stats->dma_map_err++; return -EIO; } + buf_info->page = page; + buf_info->page_offset = 0; + return 0; } @@ -95,7 +90,7 @@ static void ionic_rx_page_free(struct ionic_queue *q, dma_unmap_page(dev, buf_info->dma_addr, IONIC_PAGE_SIZE, DMA_FROM_DEVICE); __free_pages(buf_info->page, 0); - ionic_rx_buf_reset(buf_info); + buf_info->page = NULL; } static bool ionic_rx_buf_recycle(struct ionic_queue *q, @@ -139,7 +134,7 @@ static struct sk_buff *ionic_rx_frags(struct ionic_queue *q, buf_info = &desc_info->bufs[0]; len = le16_to_cpu(comp->len); - prefetch(buf_info->page); + prefetchw(buf_info->page); skb = napi_get_frags(&q_to_qcq(q)->napi); if (unlikely(!skb)) { @@ -170,7 +165,7 @@ static struct sk_buff *ionic_rx_frags(struct ionic_queue *q, if (!ionic_rx_buf_recycle(q, buf_info, frag_len)) { dma_unmap_page(dev, buf_info->dma_addr, IONIC_PAGE_SIZE, DMA_FROM_DEVICE); - ionic_rx_buf_reset(buf_info); + buf_info->page = NULL; } buf_info++; |