diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 2520cf2b7c..ceb23402a5 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -407,6 +407,7 @@ void sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
 int sfc_port_update_mac_stats(struct sfc_adapter *sa);
 int sfc_port_reset_mac_stats(struct sfc_adapter *sa);
 int sfc_set_rx_mode(struct sfc_adapter *sa);
+int sfc_set_rx_mode_unchecked(struct sfc_adapter *sa);
 
 
 #ifdef __cplusplus
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index f8867b0ec0..de490eb90d 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -393,8 +393,16 @@ sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode,
 		} else if ((sa->state == SFC_ADAPTER_STARTED) &&
 			   ((rc = sfc_set_rx_mode(sa)) != 0)) {
 			*toggle = !(enabled);
-			sfc_warn(sa, "Failed to %s %s mode",
-				 ((enabled) ? "enable" : "disable"), desc);
+			sfc_warn(sa, "Failed to %s %s mode, rc = %d",
+				 ((enabled) ? "enable" : "disable"), desc, rc);
+
+			/*
+			 * For promiscuous and all-multicast filters a
+			 * permission failure should be reported as an
+			 * unsupported filter.
+			 */
+			if (rc == EPERM)
+				rc = ENOTSUP;
 		}
 	}
 
@@ -1060,12 +1068,12 @@ sfc_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr)
 		 * has no effect on received traffic, therefore
 		 * we also need to update unicast filters
 		 */
-		rc = sfc_set_rx_mode(sa);
+		rc = sfc_set_rx_mode_unchecked(sa);
 		if (rc != 0) {
 			sfc_err(sa, "cannot set filter (rc = %u)", rc);
 			/* Rollback the old address */
 			(void)efx_mac_addr_set(sa->nic, old_addr->addr_bytes);
-			(void)sfc_set_rx_mode(sa);
+			(void)sfc_set_rx_mode_unchecked(sa);
 		}
 	} else {
 		sfc_warn(sa, "cannot set MAC address with filters installed");
diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c
index 23313e125f..0ddefdefe8 100644
--- a/drivers/net/sfc/sfc_port.c
+++ b/drivers/net/sfc/sfc_port.c
@@ -239,7 +239,7 @@ sfc_port_start(struct sfc_adapter *sa)
 				B_TRUE : B_FALSE;
 		port->allmulti = (sa->eth_dev->data->all_multicast != 0) ?
 				 B_TRUE : B_FALSE;
-		rc = sfc_set_rx_mode(sa);
+		rc = sfc_set_rx_mode_unchecked(sa);
 		if (rc != 0)
 			goto fail_mac_filter_set;
 
@@ -485,16 +485,70 @@ sfc_port_detach(struct sfc_adapter *sa)
 	sfc_log_init(sa, "done");
 }
 
+static boolean_t
+sfc_get_requested_all_ucast(struct sfc_port *port)
+{
+	return port->promisc;
+}
+
+static boolean_t
+sfc_get_requested_all_mcast(struct sfc_port *port)
+{
+	return port->promisc || port->allmulti;
+}
+
+int
+sfc_set_rx_mode_unchecked(struct sfc_adapter *sa)
+{
+	struct sfc_port *port = &sa->port;
+	boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port);
+	boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port);
+	int rc;
+
+	rc = efx_mac_filter_set(sa->nic, requested_all_ucast, B_TRUE,
+				requested_all_mcast, B_TRUE);
+	if (rc != 0)
+		return rc;
+
+	return 0;
+}
+
 int
 sfc_set_rx_mode(struct sfc_adapter *sa)
 {
 	struct sfc_port *port = &sa->port;
+	boolean_t old_all_ucast;
+	boolean_t old_all_mcast;
+	boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port);
+	boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port);
+	boolean_t actual_all_ucast;
+	boolean_t actual_all_mcast;
 	int rc;
 
-	rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE,
-				port->promisc || port->allmulti, B_TRUE);
+	efx_mac_filter_get_all_ucast_mcast(sa->nic, &old_all_ucast,
+					   &old_all_mcast);
 
-	return rc;
+	rc = sfc_set_rx_mode_unchecked(sa);
+	if (rc != 0)
+		return rc;
+
+	efx_mac_filter_get_all_ucast_mcast(sa->nic, &actual_all_ucast,
+					   &actual_all_mcast);
+
+	if (actual_all_ucast != requested_all_ucast ||
+	    actual_all_mcast != requested_all_mcast) {
+		/*
+		 * MAC filter set succeeded but not all requested modes
+		 * were applied. The rollback is necessary to bring back the
+		 * consistent old state.
+		 */
+		(void)efx_mac_filter_set(sa->nic, old_all_ucast, B_TRUE,
+					 old_all_mcast, B_TRUE);
+
+		return EPERM;
+	}
+
+	return 0;
 }
 
 void
diff --git a/drivers/net/sfc/sfc_rx.c b/drivers/net/sfc/sfc_rx.c
index 891709fd04..183589c639 100644
--- a/drivers/net/sfc/sfc_rx.c
+++ b/drivers/net/sfc/sfc_rx.c
@@ -720,7 +720,7 @@ sfc_rx_default_rxq_set_filter(struct sfc_adapter *sa, struct sfc_rxq *rxq)
 
 		port->promisc = B_FALSE;
 		sa->eth_dev->data->promiscuous = 0;
-		rc = sfc_set_rx_mode(sa);
+		rc = sfc_set_rx_mode_unchecked(sa);
 		if (rc != 0)
 			return rc;
 
@@ -734,7 +734,7 @@ sfc_rx_default_rxq_set_filter(struct sfc_adapter *sa, struct sfc_rxq *rxq)
 
 		port->allmulti = B_FALSE;
 		sa->eth_dev->data->all_multicast = 0;
-		rc = sfc_set_rx_mode(sa);
+		rc = sfc_set_rx_mode_unchecked(sa);
 		if (rc != 0)
 			return rc;
 
