aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/sfc.h24
-rw-r--r--drivers/net/sfc/sfc_ef10_rx.c4
-rw-r--r--drivers/net/sfc/sfc_ethdev.c19
-rw-r--r--drivers/net/sfc/sfc_ev.c27
-rw-r--r--drivers/net/sfc/sfc_flow.c6
-rw-r--r--drivers/net/sfc/sfc_intr.c5
-rw-r--r--drivers/net/sfc/sfc_port.c19
7 files changed, 80 insertions, 24 deletions
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 7f11bf22..ef980a40 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -158,6 +158,8 @@ struct sfc_port {
boolean_t promisc;
boolean_t allmulti;
+ struct ether_addr default_mac_addr;
+
unsigned int max_mcast_addrs;
unsigned int nb_mcast_addrs;
uint8_t *mcast_addrs;
@@ -210,7 +212,29 @@ struct sfc_adapter {
unsigned int evq_count;
unsigned int mgmt_evq_index;
+ /*
+ * The lock is used to serialise management event queue polling
+ * which can be done from different context. Also the lock
+ * guarantees that mgmt_evq_running is preserved while the lock
+ * is held. It is used to serialise polling and start/stop
+ * operations.
+ *
+ * Locks which may be held when the lock is acquired:
+ * - adapter lock, when:
+ * - device start/stop to change mgmt_evq_running
+ * - any control operations in client side MCDI proxy handling to
+ * poll management event queue waiting for proxy response
+ * - MCDI lock, when:
+ * - any control operations in client side MCDI proxy handling to
+ * poll management event queue waiting for proxy response
+ *
+ * Locks which are acquired with the lock held:
+ * - nic_lock, when:
+ * - MC event processing on management event queue polling
+ * (e.g. MC REBOOT or BADASSERT events)
+ */
rte_spinlock_t mgmt_evq_lock;
+ bool mgmt_evq_running;
struct sfc_evq *mgmt_evq;
unsigned int rxq_count;
diff --git a/drivers/net/sfc/sfc_ef10_rx.c b/drivers/net/sfc/sfc_ef10_rx.c
index 18d60c69..4c76f747 100644
--- a/drivers/net/sfc/sfc_ef10_rx.c
+++ b/drivers/net/sfc/sfc_ef10_rx.c
@@ -286,10 +286,10 @@ sfc_ef10_rx_ev_to_offloads(struct sfc_ef10_rxq *rxq, const efx_qword_t rx_ev,
PKT_RX_IP_CKSUM_BAD : PKT_RX_IP_CKSUM_GOOD);
break;
case ESE_DZ_L3_CLASS_IP6_FRAG:
- l4_ptype |= RTE_PTYPE_L4_FRAG;
+ l4_ptype = RTE_PTYPE_L4_FRAG;
/* FALLTHROUGH */
case ESE_DZ_L3_CLASS_IP6:
- l3_ptype |= RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
+ l3_ptype = RTE_PTYPE_L3_IPV6_EXT_UNKNOWN;
ol_flags |= PKT_RX_RSS_HASH;
break;
case ESE_DZ_L3_CLASS_ARP:
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 2f5f86f8..fabcc329 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -926,6 +926,12 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
sfc_adapter_lock(sa);
+ /*
+ * Copy the address to the device private data so that
+ * it could be recalled in the case of adapter restart.
+ */
+ ether_addr_copy(mac_addr, &port->default_mac_addr);
+
if (port->isolated) {
sfc_err(sa, "isolated mode is active on the port");
sfc_err(sa, "will not set MAC address");
@@ -961,9 +967,9 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
/*
* Since setting MAC address with filters installed is not
- * allowed on the adapter, one needs to simply restart adapter
- * so that the new MAC address will be taken from an outer
- * storage and set flawlessly by means of sfc_start() call
+ * allowed on the adapter, the new MAC address will be set
+ * by means of adapter restart. sfc_start() shall retrieve
+ * the new address from the device private data and set it.
*/
sfc_stop(sa);
rc = sfc_start(sa);
@@ -972,6 +978,13 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr)
}
unlock:
+ /*
+ * In the case of failure sa->port->default_mac_addr does not
+ * need rollback since no error code is returned, and the upper
+ * API will anyway update the external MAC address storage.
+ * To be consistent with that new value it is better to keep
+ * the device private value the same.
+ */
sfc_adapter_unlock(sa);
}
diff --git a/drivers/net/sfc/sfc_ev.c b/drivers/net/sfc/sfc_ev.c
index a16dc27b..5fbebbf1 100644
--- a/drivers/net/sfc/sfc_ev.c
+++ b/drivers/net/sfc/sfc_ev.c
@@ -565,10 +565,8 @@ void
sfc_ev_mgmt_qpoll(struct sfc_adapter *sa)
{
if (rte_spinlock_trylock(&sa->mgmt_evq_lock)) {
- struct sfc_evq *mgmt_evq = sa->mgmt_evq;
-
- if (mgmt_evq->init_state == SFC_EVQ_STARTED)
- sfc_ev_qpoll(mgmt_evq);
+ if (sa->mgmt_evq_running)
+ sfc_ev_qpoll(sa->mgmt_evq);
rte_spinlock_unlock(&sa->mgmt_evq_lock);
}
@@ -734,20 +732,26 @@ sfc_ev_start(struct sfc_adapter *sa)
goto fail_ev_init;
/* Start management EVQ used for global events */
- rte_spinlock_lock(&sa->mgmt_evq_lock);
+ /*
+ * Management event queue start polls the queue, but it cannot
+ * interfere with other polling contexts since mgmt_evq_running
+ * is false yet.
+ */
rc = sfc_ev_qstart(sa->mgmt_evq, sa->mgmt_evq_index);
if (rc != 0)
goto fail_mgmt_evq_start;
+ rte_spinlock_lock(&sa->mgmt_evq_lock);
+ sa->mgmt_evq_running = true;
+ rte_spinlock_unlock(&sa->mgmt_evq_lock);
+
if (sa->intr.lsc_intr) {
rc = sfc_ev_qprime(sa->mgmt_evq);
if (rc != 0)
- goto fail_evq0_prime;
+ goto fail_mgmt_evq_prime;
}
- rte_spinlock_unlock(&sa->mgmt_evq_lock);
-
/*
* Start management EVQ polling. If interrupts are disabled
* (not used), it is required to process link status change
@@ -763,11 +767,10 @@ sfc_ev_start(struct sfc_adapter *sa)
return 0;
-fail_evq0_prime:
+fail_mgmt_evq_prime:
sfc_ev_qstop(sa->mgmt_evq);
fail_mgmt_evq_start:
- rte_spinlock_unlock(&sa->mgmt_evq_lock);
efx_ev_fini(sa->nic);
fail_ev_init:
@@ -783,9 +786,11 @@ sfc_ev_stop(struct sfc_adapter *sa)
sfc_ev_mgmt_periodic_qpoll_stop(sa);
rte_spinlock_lock(&sa->mgmt_evq_lock);
- sfc_ev_qstop(sa->mgmt_evq);
+ sa->mgmt_evq_running = false;
rte_spinlock_unlock(&sa->mgmt_evq_lock);
+ sfc_ev_qstop(sa->mgmt_evq);
+
efx_ev_fini(sa->nic);
}
diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c
index f2050f65..e770b98e 100644
--- a/drivers/net/sfc/sfc_flow.c
+++ b/drivers/net/sfc/sfc_flow.c
@@ -1021,7 +1021,7 @@ fail_scale_tbl_set:
fail_filter_insert:
fail_scale_key_set:
fail_scale_mode_set:
- if (rss != NULL)
+ if (flow->rss)
efx_rx_scale_context_free(sa->nic, spec->efs_rss_context);
fail_scale_context_alloc:
@@ -1126,8 +1126,6 @@ sfc_flow_parse(struct rte_eth_dev *dev,
struct sfc_adapter *sa = dev->data->dev_private;
int rc;
- memset(&flow->spec, 0, sizeof(flow->spec));
-
rc = sfc_flow_parse_attr(attr, flow, error);
if (rc != 0)
goto fail_bad_value;
@@ -1160,6 +1158,8 @@ sfc_flow_validate(struct rte_eth_dev *dev,
{
struct rte_flow flow;
+ memset(&flow, 0, sizeof(flow));
+
return sfc_flow_parse(dev, attr, pattern, actions, &flow, error);
}
diff --git a/drivers/net/sfc/sfc_intr.c b/drivers/net/sfc/sfc_intr.c
index ee59cb1c..de65f8c0 100644
--- a/drivers/net/sfc/sfc_intr.c
+++ b/drivers/net/sfc/sfc_intr.c
@@ -57,8 +57,9 @@ sfc_intr_handle_mgmt_evq(struct sfc_adapter *sa)
evq = sa->mgmt_evq;
- if (evq->init_state != SFC_EVQ_STARTED) {
- sfc_log_init(sa, "interrupt on stopped EVQ %u", evq->evq_index);
+ if (!sa->mgmt_evq_running) {
+ sfc_log_init(sa, "interrupt on not running management EVQ %u",
+ evq->evq_index);
} else {
sfc_ev_qpoll(evq);
diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c
index c1466a77..5254394c 100644
--- a/drivers/net/sfc/sfc_port.c
+++ b/drivers/net/sfc/sfc_port.c
@@ -188,10 +188,10 @@ sfc_port_start(struct sfc_adapter *sa)
goto fail_mac_pdu_set;
if (!port->isolated) {
- struct ether_addr *mac_addrs = sa->eth_dev->data->mac_addrs;
+ struct ether_addr *addr = &port->default_mac_addr;
sfc_log_init(sa, "set MAC address");
- rc = efx_mac_addr_set(sa->nic, mac_addrs[0].addr_bytes);
+ rc = efx_mac_addr_set(sa->nic, addr->addr_bytes);
if (rc != 0)
goto fail_mac_addr_set;
@@ -279,10 +279,10 @@ fail_port_init_dev_link:
(void)efx_mac_drain(sa->nic, B_TRUE);
fail_mac_drain:
+fail_mac_stats_upload:
(void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
0, B_FALSE);
-fail_mac_stats_upload:
fail_mac_stats_periodic:
fail_mcast_address_list_set:
fail_mac_filter_set:
@@ -342,6 +342,8 @@ int
sfc_port_attach(struct sfc_adapter *sa)
{
struct sfc_port *port = &sa->port;
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+ const struct ether_addr *from;
long kvarg_stats_update_period_ms;
int rc;
@@ -353,6 +355,10 @@ sfc_port_attach(struct sfc_adapter *sa)
port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
port->flow_ctrl_autoneg = B_TRUE;
+ RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from));
+ from = (const struct ether_addr *)(encp->enc_mac_addr);
+ ether_addr_copy(from, &port->default_mac_addr);
+
port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX;
port->nb_mcast_addrs = 0;
port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf",
@@ -404,9 +410,14 @@ sfc_port_attach(struct sfc_adapter *sa)
return 0;
fail_kvarg_stats_update_period_ms:
+ sfc_dma_free(sa, &port->mac_stats_dma_mem);
+
fail_mac_stats_dma_alloc:
rte_free(port->mac_stats_buf);
+
fail_mac_stats_buf_alloc:
+ rte_free(port->mcast_addrs);
+
fail_mcast_addr_list_buf_alloc:
sfc_log_init(sa, "failed %d", rc);
return rc;
@@ -422,6 +433,8 @@ sfc_port_detach(struct sfc_adapter *sa)
sfc_dma_free(sa, &port->mac_stats_dma_mem);
rte_free(port->mac_stats_buf);
+ rte_free(port->mcast_addrs);
+
sfc_log_init(sa, "done");
}