/*-
* BSD LICENSE
*
- * Copyright(c) 2017 Semihalf. All rights reserved.
+ * Copyright(c) 2017 Marvell International Ltd.
+ * Copyright(c) 2017 Semihalf.
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include <rte_kvargs.h>
#include <rte_log.h>
#include <rte_malloc.h>
-#include <rte_vdev.h>
+#include <rte_bus_vdev.h>
/* Unluckily, container_of is defined by both DPDK and MUSDK,
* we'll declare only one version.
#undef container_of
#endif
-#include <drivers/mv_pp2.h>
-#include <drivers/mv_pp2_bpool.h>
-#include <drivers/mv_pp2_hif.h>
-
#include <fcntl.h>
#include <linux/ethtool.h>
#include <linux/sockios.h>
#define MRVL_COOKIE_HIGH_ADDR_SHIFT (sizeof(pp2_cookie_t) * 8)
#define MRVL_COOKIE_HIGH_ADDR_MASK (~0ULL << MRVL_COOKIE_HIGH_ADDR_SHIFT)
+/* Memory size (in bytes) for MUSDK dma buffers */
+#define MRVL_MUSDK_DMA_MEMSIZE 41943040
+
static const char * const valid_args[] = {
MRVL_IFACE_NAME_ARG,
MRVL_CFG_ARG,
if (mtu < ETHER_MIN_MTU || mru > MRVL_PKT_SIZE_MAX)
return -EINVAL;
+ if (!priv->ppio)
+ return -EPERM;
+
ret = pp2_ppio_set_mru(priv->ppio, mru);
if (ret)
return ret;
struct mrvl_priv *priv = dev->data->dev_private;
int ret;
+ if (!priv->ppio)
+ return -EPERM;
+
ret = pp2_ppio_enable(priv->ppio);
if (ret)
return ret;
if (ret)
pp2_ppio_disable(priv->ppio);
- dev->data->dev_link.link_status = ETH_LINK_UP;
-
return ret;
}
mrvl_dev_set_link_down(struct rte_eth_dev *dev)
{
struct mrvl_priv *priv = dev->data->dev_private;
- int ret;
- ret = pp2_ppio_disable(priv->ppio);
- if (ret)
- return ret;
-
- dev->data->dev_link.link_status = ETH_LINK_DOWN;
+ if (!priv->ppio)
+ return -EPERM;
- return ret;
+ return pp2_ppio_disable(priv->ppio);
}
/**
* TODO
* once MUSDK provides necessary API use it here
*/
+ struct mrvl_priv *priv = dev->data->dev_private;
struct ethtool_cmd edata;
struct ifreq req;
- int ret, fd;
+ int ret, fd, link_up;
+
+ if (!priv->ppio)
+ return -EPERM;
edata.cmd = ETHTOOL_GSET;
ETH_LINK_HALF_DUPLEX;
dev->data->dev_link.link_autoneg = edata.autoneg ? ETH_LINK_AUTONEG :
ETH_LINK_FIXED;
+ pp2_ppio_get_link_state(priv->ppio, &link_up);
+ dev->data->dev_link.link_status = link_up ? ETH_LINK_UP : ETH_LINK_DOWN;
return 0;
}
struct mrvl_priv *priv = dev->data->dev_private;
int ret;
- ret = pp2_ppio_set_uc_promisc(priv->ppio, 1);
+ if (!priv->ppio)
+ return;
+
+ ret = pp2_ppio_set_promisc(priv->ppio, 1);
if (ret)
RTE_LOG(ERR, PMD, "Failed to enable promiscuous mode\n");
}
struct mrvl_priv *priv = dev->data->dev_private;
int ret;
+ if (!priv->ppio)
+ return;
+
ret = pp2_ppio_set_mc_promisc(priv->ppio, 1);
if (ret)
RTE_LOG(ERR, PMD, "Failed enable all-multicast mode\n");
struct mrvl_priv *priv = dev->data->dev_private;
int ret;
- ret = pp2_ppio_set_uc_promisc(priv->ppio, 0);
+ if (!priv->ppio)
+ return;
+
+ ret = pp2_ppio_set_promisc(priv->ppio, 0);
if (ret)
RTE_LOG(ERR, PMD, "Failed to disable promiscuous mode\n");
}
struct mrvl_priv *priv = dev->data->dev_private;
int ret;
+ if (!priv->ppio)
+ return;
+
ret = pp2_ppio_set_mc_promisc(priv->ppio, 0);
if (ret)
RTE_LOG(ERR, PMD, "Failed to disable all-multicast mode\n");
char buf[ETHER_ADDR_FMT_SIZE];
int ret;
+ if (!priv->ppio)
+ return;
+
ret = pp2_ppio_remove_mac_addr(priv->ppio,
dev->data->mac_addrs[index].addr_bytes);
if (ret) {
/* For setting index 0, mrvl_mac_addr_set() should be used.*/
return -1;
+ if (!priv->ppio)
+ return -EPERM;
+
/*
* Maximum number of uc addresses can be tuned via kernel module mvpp2x
* parameter uc_filter_max. Maximum number of mc addresses is then
mrvl_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
{
struct mrvl_priv *priv = dev->data->dev_private;
+ int ret;
- pp2_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes);
- /*
- * TODO
- * Port stops sending packets if pp2_ppio_set_mac_addr()
- * was called after pp2_ppio_enable(). As a quick fix issue
- * enable port once again.
- */
- pp2_ppio_enable(priv->ppio);
+ if (!priv->ppio)
+ return;
+
+ ret = pp2_ppio_set_mac_addr(priv->ppio, mac_addr->addr_bytes);
+ if (ret) {
+ char buf[ETHER_ADDR_FMT_SIZE];
+ ether_format_addr(buf, sizeof(buf), mac_addr);
+ RTE_LOG(ERR, PMD, "Failed to set mac to %s\n", buf);
+ }
}
/**
* Pointer to Ethernet device structure.
* @param stats
* Stats structure output buffer.
+ *
+ * @return
+ * 0 on success, negative error value otherwise.
*/
-static void
+static int
mrvl_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
struct mrvl_priv *priv = dev->data->dev_private;
uint64_t drop_mac = 0;
unsigned int i, idx, ret;
+ if (!priv->ppio)
+ return -EPERM;
+
for (i = 0; i < dev->data->nb_rx_queues; i++) {
struct mrvl_rxq *rxq = dev->data->rx_queues[i];
struct pp2_ppio_inq_statistics rx_stats;
ret = pp2_ppio_get_statistics(priv->ppio, &ppio_stats, 0);
if (unlikely(ret)) {
RTE_LOG(ERR, PMD, "Failed to update port statistics\n");
- return;
+ return ret;
}
stats->ipackets += ppio_stats.rx_packets - drop_mac;
ppio_stats.rx_fifo_dropped +
ppio_stats.rx_cls_dropped;
stats->ierrors = drop_mac;
+
+ return 0;
}
/**
struct mrvl_priv *priv = dev->data->dev_private;
int i;
+ if (!priv->ppio)
+ return;
+
for (i = 0; i < dev->data->nb_rx_queues; i++) {
struct mrvl_rxq *rxq = dev->data->rx_queues[i];
{
struct mrvl_priv *priv = dev->data->dev_private;
+ if (!priv->ppio)
+ return -EPERM;
+
return on ? pp2_ppio_add_vlan(priv->ppio, vlan_id) :
pp2_ppio_remove_vlan(priv->ppio, vlan_id);
}
}
entries[i].buff.addr =
- rte_mbuf_data_dma_addr_default(mbufs[i]);
+ rte_mbuf_data_iova_default(mbufs[i]);
entries[i].buff.cookie = (pp2_cookie_t)(uint64_t)mbufs[i];
entries[i].bpool = bpool;
}
status = pp2_ppio_inq_desc_get_l2_pkt_error(&descs[i]);
if (unlikely(status != PP2_DESC_ERR_OK)) {
struct pp2_buff_inf binf = {
- .addr = rte_mbuf_data_dma_addr_default(mbuf),
+ .addr = rte_mbuf_data_iova_default(mbuf),
.cookie = (pp2_cookie_t)(uint64_t)mbuf,
};
sq->ent[sq->head].buff.cookie = (pp2_cookie_t)(uint64_t)mbuf;
sq->ent[sq->head].buff.addr =
- rte_mbuf_data_dma_addr_default(mbuf);
+ rte_mbuf_data_iova_default(mbuf);
sq->ent[sq->head].bpool =
(unlikely(mbuf->port == 0xff || mbuf->refcnt > 1)) ?
NULL : mrvl_port_to_bpool_lookup[mbuf->port];
pp2_ppio_outq_desc_reset(&descs[i]);
pp2_ppio_outq_desc_set_phys_addr(&descs[i],
- rte_pktmbuf_mtophys(mbuf));
+ rte_pktmbuf_iova(mbuf));
pp2_ppio_outq_desc_set_pkt_offset(&descs[i], 0);
pp2_ppio_outq_desc_set_pkt_len(&descs[i],
rte_pktmbuf_pkt_len(mbuf));
* ret == -EEXIST is correct, it means DMA
* has been already initialized (by another PMD).
*/
- ret = mv_sys_dma_mem_init(RTE_MRVL_MUSDK_DMA_MEMSIZE);
- if (ret < 0 && ret != -EEXIST)
- goto out_free_kvlist;
+ ret = mv_sys_dma_mem_init(MRVL_MUSDK_DMA_MEMSIZE);
+ if (ret < 0) {
+ if (ret != -EEXIST)
+ goto out_free_kvlist;
+ else
+ RTE_LOG(INFO, PMD,
+ "DMA memory has been already initialized by a different driver.\n");
+ }
ret = mrvl_init_pp2();
if (ret) {