Browse Source

sfc: use a semaphore to lock farch filters too

With this change, the spinlock efx->filter_lock is no longer used and is
 thus removed.

Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Edward Cree 7 years ago
parent
commit
fc7a6c287f
2 changed files with 33 additions and 36 deletions
  1. 33 34
      drivers/net/ethernet/sfc/farch.c
  2. 0 2
      drivers/net/ethernet/sfc/net_driver.h

+ 33 - 34
drivers/net/ethernet/sfc/farch.c

@@ -1878,6 +1878,7 @@ struct efx_farch_filter_table {
 };
 };
 
 
 struct efx_farch_filter_state {
 struct efx_farch_filter_state {
+	struct rw_semaphore lock; /* Protects table contents */
 	struct efx_farch_filter_table table[EFX_FARCH_FILTER_TABLE_COUNT];
 	struct efx_farch_filter_table table[EFX_FARCH_FILTER_TABLE_COUNT];
 };
 };
 
 
@@ -2397,9 +2398,13 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
 	if (rc)
 	if (rc)
 		return rc;
 		return rc;
 
 
+	down_write(&state->lock);
+
 	table = &state->table[efx_farch_filter_spec_table_id(&spec)];
 	table = &state->table[efx_farch_filter_spec_table_id(&spec)];
-	if (table->size == 0)
-		return -EINVAL;
+	if (table->size == 0) {
+		rc = -EINVAL;
+		goto out_unlock;
+	}
 
 
 	netif_vdbg(efx, hw, efx->net_dev,
 	netif_vdbg(efx, hw, efx->net_dev,
 		   "%s: type %d search_limit=%d", __func__, spec.type,
 		   "%s: type %d search_limit=%d", __func__, spec.type,
@@ -2412,8 +2417,6 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
 			     EFX_FARCH_FILTER_MC_DEF - EFX_FARCH_FILTER_UC_DEF);
 			     EFX_FARCH_FILTER_MC_DEF - EFX_FARCH_FILTER_UC_DEF);
 		rep_index = spec.type - EFX_FARCH_FILTER_UC_DEF;
 		rep_index = spec.type - EFX_FARCH_FILTER_UC_DEF;
 		ins_index = rep_index;
 		ins_index = rep_index;
-
-		spin_lock_bh(&efx->filter_lock);
 	} else {
 	} else {
 		/* Search concurrently for
 		/* Search concurrently for
 		 * (1) a filter to be replaced (rep_index): any filter
 		 * (1) a filter to be replaced (rep_index): any filter
@@ -2443,8 +2446,6 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
 		ins_index = -1;
 		ins_index = -1;
 		depth = 1;
 		depth = 1;
 
 
-		spin_lock_bh(&efx->filter_lock);
-
 		for (;;) {
 		for (;;) {
 			if (!test_bit(i, table->used_bitmap)) {
 			if (!test_bit(i, table->used_bitmap)) {
 				if (ins_index < 0)
 				if (ins_index < 0)
@@ -2463,7 +2464,7 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
 				/* Case (b) */
 				/* Case (b) */
 				if (ins_index < 0) {
 				if (ins_index < 0) {
 					rc = -EBUSY;
 					rc = -EBUSY;
-					goto out;
+					goto out_unlock;
 				}
 				}
 				rep_index = -1;
 				rep_index = -1;
 				break;
 				break;
@@ -2483,11 +2484,11 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
 
 
 		if (spec.priority == saved_spec->priority && !replace_equal) {
 		if (spec.priority == saved_spec->priority && !replace_equal) {
 			rc = -EEXIST;
 			rc = -EEXIST;
-			goto out;
+			goto out_unlock;
 		}
 		}
 		if (spec.priority < saved_spec->priority) {
 		if (spec.priority < saved_spec->priority) {
 			rc = -EPERM;
 			rc = -EPERM;
-			goto out;
+			goto out_unlock;
 		}
 		}
 		if (saved_spec->priority == EFX_FILTER_PRI_AUTO ||
 		if (saved_spec->priority == EFX_FILTER_PRI_AUTO ||
 		    saved_spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO)
 		    saved_spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO)
@@ -2528,8 +2529,8 @@ s32 efx_farch_filter_insert(struct efx_nic *efx,
 		   __func__, spec.type, ins_index, spec.dmaq_id);
 		   __func__, spec.type, ins_index, spec.dmaq_id);
 	rc = efx_farch_filter_make_id(&spec, ins_index);
 	rc = efx_farch_filter_make_id(&spec, ins_index);
 
 
-out:
-	spin_unlock_bh(&efx->filter_lock);
+out_unlock:
+	up_write(&state->lock);
 	return rc;
 	return rc;
 }
 }
 
 
@@ -2604,11 +2605,11 @@ int efx_farch_filter_remove_safe(struct efx_nic *efx,
 	filter_idx = efx_farch_filter_id_index(filter_id);
 	filter_idx = efx_farch_filter_id_index(filter_id);
 	if (filter_idx >= table->size)
 	if (filter_idx >= table->size)
 		return -ENOENT;
 		return -ENOENT;
+	down_write(&state->lock);
 	spec = &table->spec[filter_idx];
 	spec = &table->spec[filter_idx];
 
 
-	spin_lock_bh(&efx->filter_lock);
 	rc = efx_farch_filter_remove(efx, table, filter_idx, priority);
 	rc = efx_farch_filter_remove(efx, table, filter_idx, priority);
-	spin_unlock_bh(&efx->filter_lock);
+	up_write(&state->lock);
 
 
 	return rc;
 	return rc;
 }
 }
@@ -2622,30 +2623,28 @@ int efx_farch_filter_get_safe(struct efx_nic *efx,
 	struct efx_farch_filter_table *table;
 	struct efx_farch_filter_table *table;
 	struct efx_farch_filter_spec *spec;
 	struct efx_farch_filter_spec *spec;
 	unsigned int filter_idx;
 	unsigned int filter_idx;
-	int rc;
+	int rc = -ENOENT;
+
+	down_read(&state->lock);
 
 
 	table_id = efx_farch_filter_id_table_id(filter_id);
 	table_id = efx_farch_filter_id_table_id(filter_id);
 	if ((unsigned int)table_id >= EFX_FARCH_FILTER_TABLE_COUNT)
 	if ((unsigned int)table_id >= EFX_FARCH_FILTER_TABLE_COUNT)
-		return -ENOENT;
+		goto out_unlock;
 	table = &state->table[table_id];
 	table = &state->table[table_id];
 
 
 	filter_idx = efx_farch_filter_id_index(filter_id);
 	filter_idx = efx_farch_filter_id_index(filter_id);
 	if (filter_idx >= table->size)
 	if (filter_idx >= table->size)
-		return -ENOENT;
+		goto out_unlock;
 	spec = &table->spec[filter_idx];
 	spec = &table->spec[filter_idx];
 
 
-	spin_lock_bh(&efx->filter_lock);
-
 	if (test_bit(filter_idx, table->used_bitmap) &&
 	if (test_bit(filter_idx, table->used_bitmap) &&
 	    spec->priority == priority) {
 	    spec->priority == priority) {
 		efx_farch_filter_to_gen_spec(spec_buf, spec);
 		efx_farch_filter_to_gen_spec(spec_buf, spec);
 		rc = 0;
 		rc = 0;
-	} else {
-		rc = -ENOENT;
 	}
 	}
 
 
-	spin_unlock_bh(&efx->filter_lock);
-
+out_unlock:
+	up_read(&state->lock);
 	return rc;
 	return rc;
 }
 }
 
 
@@ -2658,13 +2657,13 @@ efx_farch_filter_table_clear(struct efx_nic *efx,
 	struct efx_farch_filter_table *table = &state->table[table_id];
 	struct efx_farch_filter_table *table = &state->table[table_id];
 	unsigned int filter_idx;
 	unsigned int filter_idx;
 
 
-	spin_lock_bh(&efx->filter_lock);
+	down_write(&state->lock);
 	for (filter_idx = 0; filter_idx < table->size; ++filter_idx) {
 	for (filter_idx = 0; filter_idx < table->size; ++filter_idx) {
 		if (table->spec[filter_idx].priority != EFX_FILTER_PRI_AUTO)
 		if (table->spec[filter_idx].priority != EFX_FILTER_PRI_AUTO)
 			efx_farch_filter_remove(efx, table,
 			efx_farch_filter_remove(efx, table,
 						filter_idx, priority);
 						filter_idx, priority);
 	}
 	}
-	spin_unlock_bh(&efx->filter_lock);
+	up_write(&state->lock);
 }
 }
 
 
 int efx_farch_filter_clear_rx(struct efx_nic *efx,
 int efx_farch_filter_clear_rx(struct efx_nic *efx,
@@ -2688,7 +2687,7 @@ u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
 	unsigned int filter_idx;
 	unsigned int filter_idx;
 	u32 count = 0;
 	u32 count = 0;
 
 
-	spin_lock_bh(&efx->filter_lock);
+	down_read(&state->lock);
 
 
 	for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
 	for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
 	     table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
 	     table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
@@ -2701,7 +2700,7 @@ u32 efx_farch_filter_count_rx_used(struct efx_nic *efx,
 		}
 		}
 	}
 	}
 
 
-	spin_unlock_bh(&efx->filter_lock);
+	up_read(&state->lock);
 
 
 	return count;
 	return count;
 }
 }
@@ -2716,7 +2715,7 @@ s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx,
 	unsigned int filter_idx;
 	unsigned int filter_idx;
 	s32 count = 0;
 	s32 count = 0;
 
 
-	spin_lock_bh(&efx->filter_lock);
+	down_read(&state->lock);
 
 
 	for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
 	for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
 	     table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
 	     table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
@@ -2735,7 +2734,7 @@ s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx,
 		}
 		}
 	}
 	}
 out:
 out:
-	spin_unlock_bh(&efx->filter_lock);
+	up_read(&state->lock);
 
 
 	return count;
 	return count;
 }
 }
@@ -2749,7 +2748,7 @@ void efx_farch_filter_table_restore(struct efx_nic *efx)
 	efx_oword_t filter;
 	efx_oword_t filter;
 	unsigned int filter_idx;
 	unsigned int filter_idx;
 
 
-	spin_lock_bh(&efx->filter_lock);
+	down_write(&state->lock);
 
 
 	for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
 	for (table_id = 0; table_id < EFX_FARCH_FILTER_TABLE_COUNT; table_id++) {
 		table = &state->table[table_id];
 		table = &state->table[table_id];
@@ -2770,7 +2769,7 @@ void efx_farch_filter_table_restore(struct efx_nic *efx)
 	efx_farch_filter_push_rx_config(efx);
 	efx_farch_filter_push_rx_config(efx);
 	efx_farch_filter_push_tx_limits(efx);
 	efx_farch_filter_push_tx_limits(efx);
 
 
-	spin_unlock_bh(&efx->filter_lock);
+	up_write(&state->lock);
 }
 }
 
 
 void efx_farch_filter_table_remove(struct efx_nic *efx)
 void efx_farch_filter_table_remove(struct efx_nic *efx)
@@ -2864,7 +2863,7 @@ void efx_farch_filter_update_rx_scatter(struct efx_nic *efx)
 	efx_oword_t filter;
 	efx_oword_t filter;
 	unsigned int filter_idx;
 	unsigned int filter_idx;
 
 
-	spin_lock_bh(&efx->filter_lock);
+	down_write(&state->lock);
 
 
 	for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
 	for (table_id = EFX_FARCH_FILTER_TABLE_RX_IP;
 	     table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
 	     table_id <= EFX_FARCH_FILTER_TABLE_RX_DEF;
@@ -2896,7 +2895,7 @@ void efx_farch_filter_update_rx_scatter(struct efx_nic *efx)
 
 
 	efx_farch_filter_push_rx_config(efx);
 	efx_farch_filter_push_rx_config(efx);
 
 
-	spin_unlock_bh(&efx->filter_lock);
+	up_write(&state->lock);
 }
 }
 
 
 #ifdef CONFIG_RFS_ACCEL
 #ifdef CONFIG_RFS_ACCEL
@@ -2908,7 +2907,7 @@ bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
 	struct efx_farch_filter_table *table;
 	struct efx_farch_filter_table *table;
 	bool ret = false;
 	bool ret = false;
 
 
-	spin_lock_bh(&efx->filter_lock);
+	down_write(&state->lock);
 	table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
 	table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
 	if (test_bit(index, table->used_bitmap) &&
 	if (test_bit(index, table->used_bitmap) &&
 	    table->spec[index].priority == EFX_FILTER_PRI_HINT &&
 	    table->spec[index].priority == EFX_FILTER_PRI_HINT &&
@@ -2918,7 +2917,7 @@ bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
 		ret = true;
 		ret = true;
 	}
 	}
 
 
-	spin_unlock_bh(&efx->filter_lock);
+	up_write(&state->lock);
 	return ret;
 	return ret;
 }
 }
 
 

+ 0 - 2
drivers/net/ethernet/sfc/net_driver.h

@@ -844,7 +844,6 @@ struct efx_rss_context {
  * @loopback_modes: Supported loopback mode bitmask
  * @loopback_modes: Supported loopback mode bitmask
  * @loopback_selftest: Offline self-test private state
  * @loopback_selftest: Offline self-test private state
  * @filter_sem: Filter table rw_semaphore, protects existence of @filter_state
  * @filter_sem: Filter table rw_semaphore, protects existence of @filter_state
- * @filter_lock: Filter table lock, for mere content changes
  * @filter_state: Architecture-dependent filter table state
  * @filter_state: Architecture-dependent filter table state
  * @rps_mutex: Protects RPS state of all channels
  * @rps_mutex: Protects RPS state of all channels
  * @rps_expire_channel: Next channel to check for expiry
  * @rps_expire_channel: Next channel to check for expiry
@@ -998,7 +997,6 @@ struct efx_nic {
 	void *loopback_selftest;
 	void *loopback_selftest;
 
 
 	struct rw_semaphore filter_sem;
 	struct rw_semaphore filter_sem;
-	spinlock_t filter_lock;
 	void *filter_state;
 	void *filter_state;
 #ifdef CONFIG_RFS_ACCEL
 #ifdef CONFIG_RFS_ACCEL
 	struct mutex rps_mutex;
 	struct mutex rps_mutex;