aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Cree <ecree@solarflare.com>2018-03-27 12:42:28 -0400
committerDavid S. Miller <davem@davemloft.net>2018-03-27 13:33:19 -0400
commitc2bebe37c6b686817f795b6b63599ed4472775fa (patch)
tree6609695bdc12aa7d21fd708dd922ba8c41c23858
parent3af0f34290f6192756ee1d9c2d5fe27222267035 (diff)
sfc: give ef10 its own rwsem in the filter table instead of filter_lock
efx->filter_lock remains in place for use on farch, but EF10 now ignores it. EFX_EF10_FILTER_FLAG_BUSY is no longer needed, hence it is removed. Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/sfc/ef10.c361
-rw-r--r--drivers/net/ethernet/sfc/efx.c1
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h2
3 files changed, 151 insertions, 213 deletions
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index bcbaba330fb5..9db1b9144e70 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -96,17 +96,15 @@ struct efx_ef10_filter_table {
96 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_MAXNUM * 2]; 96 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_MAXNUM * 2];
97 unsigned int rx_match_count; 97 unsigned int rx_match_count;
98 98
99 struct rw_semaphore lock; /* Protects entries */
99 struct { 100 struct {
100 unsigned long spec; /* pointer to spec plus flag bits */ 101 unsigned long spec; /* pointer to spec plus flag bits */
101/* BUSY flag indicates that an update is in progress. AUTO_OLD is 102/* AUTO_OLD is used to mark and sweep MAC filters for the device address lists. */
102 * used to mark and sweep MAC filters for the device address lists. 103/* unused flag 1UL */
103 */
104#define EFX_EF10_FILTER_FLAG_BUSY 1UL
105#define EFX_EF10_FILTER_FLAG_AUTO_OLD 2UL 104#define EFX_EF10_FILTER_FLAG_AUTO_OLD 2UL
106#define EFX_EF10_FILTER_FLAGS 3UL 105#define EFX_EF10_FILTER_FLAGS 3UL
107 u64 handle; /* firmware handle */ 106 u64 handle; /* firmware handle */
108 } *entry; 107 } *entry;
109 wait_queue_head_t waitq;
110/* Shadow of net_device address lists, guarded by mac_lock */ 108/* Shadow of net_device address lists, guarded by mac_lock */
111 struct efx_ef10_dev_addr dev_uc_list[EFX_EF10_FILTER_DEV_UC_MAX]; 109 struct efx_ef10_dev_addr dev_uc_list[EFX_EF10_FILTER_DEV_UC_MAX];
112 struct efx_ef10_dev_addr dev_mc_list[EFX_EF10_FILTER_DEV_MC_MAX]; 110 struct efx_ef10_dev_addr dev_mc_list[EFX_EF10_FILTER_DEV_MC_MAX];
@@ -4302,26 +4300,33 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
4302 struct efx_filter_spec *spec, 4300 struct efx_filter_spec *spec,
4303 bool replace_equal) 4301 bool replace_equal)
4304{ 4302{
4305 struct efx_ef10_filter_table *table = efx->filter_state;
4306 DECLARE_BITMAP(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT); 4303 DECLARE_BITMAP(mc_rem_map, EFX_EF10_FILTER_SEARCH_LIMIT);
4304 struct efx_ef10_filter_table *table;
4307 struct efx_filter_spec *saved_spec; 4305 struct efx_filter_spec *saved_spec;
4308 struct efx_rss_context *ctx = NULL; 4306 struct efx_rss_context *ctx = NULL;
4309 unsigned int match_pri, hash; 4307 unsigned int match_pri, hash;
4310 unsigned int priv_flags; 4308 unsigned int priv_flags;
4311 bool replacing = false; 4309 bool replacing = false;
4310 unsigned int depth, i;
4312 int ins_index = -1; 4311 int ins_index = -1;
4313 DEFINE_WAIT(wait); 4312 DEFINE_WAIT(wait);
4314 bool is_mc_recip; 4313 bool is_mc_recip;
4315 s32 rc; 4314 s32 rc;
4316 4315
4316 down_read(&efx->filter_sem);
4317 table = efx->filter_state;
4318 down_write(&table->lock);
4319
4317 /* For now, only support RX filters */ 4320 /* For now, only support RX filters */
4318 if ((spec->flags & (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)) != 4321 if ((spec->flags & (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)) !=
4319 EFX_FILTER_FLAG_RX) 4322 EFX_FILTER_FLAG_RX) {
4320 return -EINVAL; 4323 rc = -EINVAL;
4324 goto out_unlock;
4325 }
4321 4326
4322 rc = efx_ef10_filter_pri(table, spec); 4327 rc = efx_ef10_filter_pri(table, spec);
4323 if (rc < 0) 4328 if (rc < 0)
4324 return rc; 4329 goto out_unlock;
4325 match_pri = rc; 4330 match_pri = rc;
4326 4331
4327 hash = efx_ef10_filter_hash(spec); 4332 hash = efx_ef10_filter_hash(spec);
@@ -4335,86 +4340,64 @@ static s32 efx_ef10_filter_insert(struct efx_nic *efx,
4335 &efx->rss_context.list); 4340 &efx->rss_context.list);
4336 else 4341 else
4337 ctx = &efx->rss_context; 4342 ctx = &efx->rss_context;
4338 if (!ctx) 4343 if (!ctx) {
4339 return -ENOENT; 4344 rc = -ENOENT;
4340 if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) 4345 goto out_unlock;
4341 return -EOPNOTSUPP; 4346 }
4347 if (ctx->context_id == EFX_EF10_RSS_CONTEXT_INVALID) {
4348 rc = -EOPNOTSUPP;
4349 goto out_unlock;
4350 }
4342 } 4351 }
4343 4352
4344 /* Find any existing filters with the same match tuple or 4353 /* Find any existing filters with the same match tuple or
4345 * else a free slot to insert at. If any of them are busy, 4354 * else a free slot to insert at.
4346 * we have to wait and retry.
4347 */ 4355 */
4348 for (;;) { 4356 for (depth = 1; depth < EFX_EF10_FILTER_SEARCH_LIMIT; depth++) {
4349 unsigned int depth = 1; 4357 i = (hash + depth) & (HUNT_FILTER_TBL_ROWS - 1);
4350 unsigned int i; 4358 saved_spec = efx_ef10_filter_entry_spec(table, i);
4351
4352 spin_lock_bh(&efx->filter_lock);
4353 4359
4354 for (;;) { 4360 if (!saved_spec) {
4355 i = (hash + depth) & (HUNT_FILTER_TBL_ROWS - 1); 4361 if (ins_index < 0)
4356 saved_spec = efx_ef10_filter_entry_spec(table, i); 4362 ins_index = i;
4357 4363 } else if (efx_ef10_filter_equal(spec, saved_spec)) {
4358 if (!saved_spec) { 4364 if (spec->priority < saved_spec->priority &&
4359 if (ins_index < 0) 4365 spec->priority != EFX_FILTER_PRI_AUTO) {
4360 ins_index = i; 4366 rc = -EPERM;
4361 } else if (efx_ef10_filter_equal(spec, saved_spec)) { 4367 goto out_unlock;
4362 if (table->entry[i].spec &
4363 EFX_EF10_FILTER_FLAG_BUSY)
4364 break;
4365 if (spec->priority < saved_spec->priority &&
4366 spec->priority != EFX_FILTER_PRI_AUTO) {
4367 rc = -EPERM;
4368 goto out_unlock;
4369 }
4370 if (!is_mc_recip) {
4371 /* This is the only one */
4372 if (spec->priority ==
4373 saved_spec->priority &&
4374 !replace_equal) {
4375 rc = -EEXIST;
4376 goto out_unlock;
4377 }
4378 ins_index = i;
4379 goto found;
4380 } else if (spec->priority >
4381 saved_spec->priority ||
4382 (spec->priority ==
4383 saved_spec->priority &&
4384 replace_equal)) {
4385 if (ins_index < 0)
4386 ins_index = i;
4387 else
4388 __set_bit(depth, mc_rem_map);
4389 }
4390 } 4368 }
4391 4369 if (!is_mc_recip) {
4392 /* Once we reach the maximum search depth, use 4370 /* This is the only one */
4393 * the first suitable slot or return -EBUSY if 4371 if (spec->priority ==
4394 * there was none 4372 saved_spec->priority &&
4395 */ 4373 !replace_equal) {
4396 if (depth == EFX_EF10_FILTER_SEARCH_LIMIT) { 4374 rc = -EEXIST;
4397 if (ins_index < 0) {
4398 rc = -EBUSY;
4399 goto out_unlock; 4375 goto out_unlock;
4400 } 4376 }
4401 goto found; 4377 ins_index = i;
4378 break;
4379 } else if (spec->priority >
4380 saved_spec->priority ||
4381 (spec->priority ==
4382 saved_spec->priority &&
4383 replace_equal)) {
4384 if (ins_index < 0)
4385 ins_index = i;
4386 else
4387 __set_bit(depth, mc_rem_map);
4402 } 4388 }
4403
4404 ++depth;
4405 } 4389 }
4406
4407 prepare_to_wait(&table->waitq, &wait, TASK_UNINTERRUPTIBLE);
4408 spin_unlock_bh(&efx->filter_lock);
4409 schedule();
4410 } 4390 }
4411 4391
4412found: 4392 /* Once we reach the maximum search depth, use the first suitable
4413 /* Create a software table entry if necessary, and mark it 4393 * slot, or return -EBUSY if there was none
4414 * busy. We might yet fail to insert, but any attempt to
4415 * insert a conflicting filter while we're waiting for the
4416 * firmware must find the busy entry.
4417 */ 4394 */
4395 if (ins_index < 0) {
4396 rc = -EBUSY;
4397 goto out_unlock;
4398 }
4399
4400 /* Create a software table entry if necessary. */
4418 saved_spec = efx_ef10_filter_entry_spec(table, ins_index); 4401 saved_spec = efx_ef10_filter_entry_spec(table, ins_index);
4419 if (saved_spec) { 4402 if (saved_spec) {
4420 if (spec->priority == EFX_FILTER_PRI_AUTO && 4403 if (spec->priority == EFX_FILTER_PRI_AUTO &&
@@ -4438,28 +4421,13 @@ found:
4438 *saved_spec = *spec; 4421 *saved_spec = *spec;
4439 priv_flags = 0; 4422 priv_flags = 0;
4440 } 4423 }
4441 efx_ef10_filter_set_entry(table, ins_index, saved_spec, 4424 efx_ef10_filter_set_entry(table, ins_index, saved_spec, priv_flags);
4442 priv_flags | EFX_EF10_FILTER_FLAG_BUSY);
4443
4444 /* Mark lower-priority multicast recipients busy prior to removal */
4445 if (is_mc_recip) {
4446 unsigned int depth, i;
4447
4448 for (depth = 0; depth < EFX_EF10_FILTER_SEARCH_LIMIT; depth++) {
4449 i = (hash + depth) & (HUNT_FILTER_TBL_ROWS - 1);
4450 if (test_bit(depth, mc_rem_map))
4451 table->entry[i].spec |=
4452 EFX_EF10_FILTER_FLAG_BUSY;
4453 }
4454 }
4455
4456 spin_unlock_bh(&efx->filter_lock);
4457 4425
4426 /* Actually insert the filter on the HW */
4458 rc = efx_ef10_filter_push(efx, spec, &table->entry[ins_index].handle, 4427 rc = efx_ef10_filter_push(efx, spec, &table->entry[ins_index].handle,
4459 ctx, replacing); 4428 ctx, replacing);
4460 4429
4461 /* Finalise the software table entry */ 4430 /* Finalise the software table entry */
4462 spin_lock_bh(&efx->filter_lock);
4463 if (rc == 0) { 4431 if (rc == 0) {
4464 if (replacing) { 4432 if (replacing) {
4465 /* Update the fields that may differ */ 4433 /* Update the fields that may differ */
@@ -4475,6 +4443,12 @@ found:
4475 } else if (!replacing) { 4443 } else if (!replacing) {
4476 kfree(saved_spec); 4444 kfree(saved_spec);
4477 saved_spec = NULL; 4445 saved_spec = NULL;
4446 } else {
4447 /* We failed to replace, so the old filter is still present.
4448 * Roll back the software table to reflect this. In fact the
4449 * efx_ef10_filter_set_entry() call below will do the right
4450 * thing, so nothing extra is needed here.
4451 */
4478 } 4452 }
4479 efx_ef10_filter_set_entry(table, ins_index, saved_spec, priv_flags); 4453 efx_ef10_filter_set_entry(table, ins_index, saved_spec, priv_flags);
4480 4454
@@ -4496,7 +4470,6 @@ found:
4496 priv_flags = efx_ef10_filter_entry_flags(table, i); 4470 priv_flags = efx_ef10_filter_entry_flags(table, i);
4497 4471
4498 if (rc == 0) { 4472 if (rc == 0) {
4499 spin_unlock_bh(&efx->filter_lock);
4500 MCDI_SET_DWORD(inbuf, FILTER_OP_IN_OP, 4473 MCDI_SET_DWORD(inbuf, FILTER_OP_IN_OP,
4501 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE); 4474 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE);
4502 MCDI_SET_QWORD(inbuf, FILTER_OP_IN_HANDLE, 4475 MCDI_SET_QWORD(inbuf, FILTER_OP_IN_HANDLE,
@@ -4504,15 +4477,12 @@ found:
4504 rc = efx_mcdi_rpc(efx, MC_CMD_FILTER_OP, 4477 rc = efx_mcdi_rpc(efx, MC_CMD_FILTER_OP,
4505 inbuf, sizeof(inbuf), 4478 inbuf, sizeof(inbuf),
4506 NULL, 0, NULL); 4479 NULL, 0, NULL);
4507 spin_lock_bh(&efx->filter_lock);
4508 } 4480 }
4509 4481
4510 if (rc == 0) { 4482 if (rc == 0) {
4511 kfree(saved_spec); 4483 kfree(saved_spec);
4512 saved_spec = NULL; 4484 saved_spec = NULL;
4513 priv_flags = 0; 4485 priv_flags = 0;
4514 } else {
4515 priv_flags &= ~EFX_EF10_FILTER_FLAG_BUSY;
4516 } 4486 }
4517 efx_ef10_filter_set_entry(table, i, saved_spec, 4487 efx_ef10_filter_set_entry(table, i, saved_spec,
4518 priv_flags); 4488 priv_flags);
@@ -4523,10 +4493,9 @@ found:
4523 if (rc == 0) 4493 if (rc == 0)
4524 rc = efx_ef10_make_filter_id(match_pri, ins_index); 4494 rc = efx_ef10_make_filter_id(match_pri, ins_index);
4525 4495
4526 wake_up_all(&table->waitq);
4527out_unlock: 4496out_unlock:
4528 spin_unlock_bh(&efx->filter_lock); 4497 up_write(&table->lock);
4529 finish_wait(&table->waitq, &wait); 4498 up_read(&efx->filter_sem);
4530 return rc; 4499 return rc;
4531} 4500}
4532 4501
@@ -4539,6 +4508,8 @@ static void efx_ef10_filter_update_rx_scatter(struct efx_nic *efx)
4539 * If !by_index, remove by ID 4508 * If !by_index, remove by ID
4540 * If by_index, remove by index 4509 * If by_index, remove by index
4541 * Filter ID may come from userland and must be range-checked. 4510 * Filter ID may come from userland and must be range-checked.
4511 * Caller must hold efx->filter_sem for read, and efx->filter_state->lock
4512 * for write.
4542 */ 4513 */
4543static int efx_ef10_filter_remove_internal(struct efx_nic *efx, 4514static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
4544 unsigned int priority_mask, 4515 unsigned int priority_mask,
@@ -4553,45 +4524,23 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
4553 DEFINE_WAIT(wait); 4524 DEFINE_WAIT(wait);
4554 int rc; 4525 int rc;
4555 4526
4556 /* Find the software table entry and mark it busy. Don't
4557 * remove it yet; any attempt to update while we're waiting
4558 * for the firmware must find the busy entry.
4559 */
4560 for (;;) {
4561 spin_lock_bh(&efx->filter_lock);
4562 if (!(table->entry[filter_idx].spec &
4563 EFX_EF10_FILTER_FLAG_BUSY))
4564 break;
4565 prepare_to_wait(&table->waitq, &wait, TASK_UNINTERRUPTIBLE);
4566 spin_unlock_bh(&efx->filter_lock);
4567 schedule();
4568 }
4569
4570 spec = efx_ef10_filter_entry_spec(table, filter_idx); 4527 spec = efx_ef10_filter_entry_spec(table, filter_idx);
4571 if (!spec || 4528 if (!spec ||
4572 (!by_index && 4529 (!by_index &&
4573 efx_ef10_filter_pri(table, spec) != 4530 efx_ef10_filter_pri(table, spec) !=
4574 efx_ef10_filter_get_unsafe_pri(filter_id))) { 4531 efx_ef10_filter_get_unsafe_pri(filter_id)))
4575 rc = -ENOENT; 4532 return -ENOENT;
4576 goto out_unlock;
4577 }
4578 4533
4579 if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO && 4534 if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO &&
4580 priority_mask == (1U << EFX_FILTER_PRI_AUTO)) { 4535 priority_mask == (1U << EFX_FILTER_PRI_AUTO)) {
4581 /* Just remove flags */ 4536 /* Just remove flags */
4582 spec->flags &= ~EFX_FILTER_FLAG_RX_OVER_AUTO; 4537 spec->flags &= ~EFX_FILTER_FLAG_RX_OVER_AUTO;
4583 table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_AUTO_OLD; 4538 table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_AUTO_OLD;
4584 rc = 0; 4539 return 0;
4585 goto out_unlock;
4586 }
4587
4588 if (!(priority_mask & (1U << spec->priority))) {
4589 rc = -ENOENT;
4590 goto out_unlock;
4591 } 4540 }
4592 4541
4593 table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY; 4542 if (!(priority_mask & (1U << spec->priority)))
4594 spin_unlock_bh(&efx->filter_lock); 4543 return -ENOENT;
4595 4544
4596 if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) { 4545 if (spec->flags & EFX_FILTER_FLAG_RX_OVER_AUTO) {
4597 /* Reset to an automatic filter */ 4546 /* Reset to an automatic filter */
@@ -4609,7 +4558,6 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
4609 &efx->rss_context, 4558 &efx->rss_context,
4610 true); 4559 true);
4611 4560
4612 spin_lock_bh(&efx->filter_lock);
4613 if (rc == 0) 4561 if (rc == 0)
4614 *spec = new_spec; 4562 *spec = new_spec;
4615 } else { 4563 } else {
@@ -4624,7 +4572,6 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
4624 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FILTER_OP, 4572 rc = efx_mcdi_rpc_quiet(efx, MC_CMD_FILTER_OP,
4625 inbuf, sizeof(inbuf), NULL, 0, NULL); 4573 inbuf, sizeof(inbuf), NULL, 0, NULL);
4626 4574
4627 spin_lock_bh(&efx->filter_lock);
4628 if ((rc == 0) || (rc == -ENOENT)) { 4575 if ((rc == 0) || (rc == -ENOENT)) {
4629 /* Filter removed OK or didn't actually exist */ 4576 /* Filter removed OK or didn't actually exist */
4630 kfree(spec); 4577 kfree(spec);
@@ -4636,11 +4583,6 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
4636 } 4583 }
4637 } 4584 }
4638 4585
4639 table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_BUSY;
4640 wake_up_all(&table->waitq);
4641out_unlock:
4642 spin_unlock_bh(&efx->filter_lock);
4643 finish_wait(&table->waitq, &wait);
4644 return rc; 4586 return rc;
4645} 4587}
4646 4588
@@ -4648,17 +4590,33 @@ static int efx_ef10_filter_remove_safe(struct efx_nic *efx,
4648 enum efx_filter_priority priority, 4590 enum efx_filter_priority priority,
4649 u32 filter_id) 4591 u32 filter_id)
4650{ 4592{
4651 return efx_ef10_filter_remove_internal(efx, 1U << priority, 4593 struct efx_ef10_filter_table *table;
4652 filter_id, false); 4594 int rc;
4595
4596 down_read(&efx->filter_sem);
4597 table = efx->filter_state;
4598 down_write(&table->lock);
4599 rc = efx_ef10_filter_remove_internal(efx, 1U << priority, filter_id,
4600 false);
4601 up_write(&table->lock);
4602 up_read(&efx->filter_sem);
4603 return rc;
4653} 4604}
4654 4605
4606/* Caller must hold efx->filter_sem for read */
4655static void efx_ef10_filter_remove_unsafe(struct efx_nic *efx, 4607static void efx_ef10_filter_remove_unsafe(struct efx_nic *efx,
4656 enum efx_filter_priority priority, 4608 enum efx_filter_priority priority,
4657 u32 filter_id) 4609 u32 filter_id)
4658{ 4610{
4611 struct efx_ef10_filter_table *table = efx->filter_state;
4612
4659 if (filter_id == EFX_EF10_FILTER_ID_INVALID) 4613 if (filter_id == EFX_EF10_FILTER_ID_INVALID)
4660 return; 4614 return;
4661 efx_ef10_filter_remove_internal(efx, 1U << priority, filter_id, true); 4615
4616 down_write(&table->lock);
4617 efx_ef10_filter_remove_internal(efx, 1U << priority, filter_id,
4618 true);
4619 up_write(&table->lock);
4662} 4620}
4663 4621
4664static int efx_ef10_filter_get_safe(struct efx_nic *efx, 4622static int efx_ef10_filter_get_safe(struct efx_nic *efx,
@@ -4666,11 +4624,13 @@ static int efx_ef10_filter_get_safe(struct efx_nic *efx,
4666 u32 filter_id, struct efx_filter_spec *spec) 4624 u32 filter_id, struct efx_filter_spec *spec)
4667{ 4625{
4668 unsigned int filter_idx = efx_ef10_filter_get_unsafe_id(filter_id); 4626 unsigned int filter_idx = efx_ef10_filter_get_unsafe_id(filter_id);
4669 struct efx_ef10_filter_table *table = efx->filter_state;
4670 const struct efx_filter_spec *saved_spec; 4627 const struct efx_filter_spec *saved_spec;
4628 struct efx_ef10_filter_table *table;
4671 int rc; 4629 int rc;
4672 4630
4673 spin_lock_bh(&efx->filter_lock); 4631 down_read(&efx->filter_sem);
4632 table = efx->filter_state;
4633 down_read(&table->lock);
4674 saved_spec = efx_ef10_filter_entry_spec(table, filter_idx); 4634 saved_spec = efx_ef10_filter_entry_spec(table, filter_idx);
4675 if (saved_spec && saved_spec->priority == priority && 4635 if (saved_spec && saved_spec->priority == priority &&
4676 efx_ef10_filter_pri(table, saved_spec) == 4636 efx_ef10_filter_pri(table, saved_spec) ==
@@ -4680,13 +4640,15 @@ static int efx_ef10_filter_get_safe(struct efx_nic *efx,
4680 } else { 4640 } else {
4681 rc = -ENOENT; 4641 rc = -ENOENT;
4682 } 4642 }
4683 spin_unlock_bh(&efx->filter_lock); 4643 up_read(&table->lock);
4644 up_read(&efx->filter_sem);
4684 return rc; 4645 return rc;
4685} 4646}
4686 4647
4687static int efx_ef10_filter_clear_rx(struct efx_nic *efx, 4648static int efx_ef10_filter_clear_rx(struct efx_nic *efx,
4688 enum efx_filter_priority priority) 4649 enum efx_filter_priority priority)
4689{ 4650{
4651 struct efx_ef10_filter_table *table;
4690 unsigned int priority_mask; 4652 unsigned int priority_mask;
4691 unsigned int i; 4653 unsigned int i;
4692 int rc; 4654 int rc;
@@ -4694,31 +4656,40 @@ static int efx_ef10_filter_clear_rx(struct efx_nic *efx,
4694 priority_mask = (((1U << (priority + 1)) - 1) & 4656 priority_mask = (((1U << (priority + 1)) - 1) &
4695 ~(1U << EFX_FILTER_PRI_AUTO)); 4657 ~(1U << EFX_FILTER_PRI_AUTO));
4696 4658
4659 down_read(&efx->filter_sem);
4660 table = efx->filter_state;
4661 down_write(&table->lock);
4697 for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) { 4662 for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) {
4698 rc = efx_ef10_filter_remove_internal(efx, priority_mask, 4663 rc = efx_ef10_filter_remove_internal(efx, priority_mask,
4699 i, true); 4664 i, true);
4700 if (rc && rc != -ENOENT) 4665 if (rc && rc != -ENOENT)
4701 return rc; 4666 break;
4667 rc = 0;
4702 } 4668 }
4703 4669
4704 return 0; 4670 up_write(&table->lock);
4671 up_read(&efx->filter_sem);
4672 return rc;
4705} 4673}
4706 4674
4707static u32 efx_ef10_filter_count_rx_used(struct efx_nic *efx, 4675static u32 efx_ef10_filter_count_rx_used(struct efx_nic *efx,
4708 enum efx_filter_priority priority) 4676 enum efx_filter_priority priority)
4709{ 4677{
4710 struct efx_ef10_filter_table *table = efx->filter_state; 4678 struct efx_ef10_filter_table *table;
4711 unsigned int filter_idx; 4679 unsigned int filter_idx;
4712 s32 count = 0; 4680 s32 count = 0;
4713 4681
4714 spin_lock_bh(&efx->filter_lock); 4682 down_read(&efx->filter_sem);
4683 table = efx->filter_state;
4684 down_read(&table->lock);
4715 for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) { 4685 for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) {
4716 if (table->entry[filter_idx].spec && 4686 if (table->entry[filter_idx].spec &&
4717 efx_ef10_filter_entry_spec(table, filter_idx)->priority == 4687 efx_ef10_filter_entry_spec(table, filter_idx)->priority ==
4718 priority) 4688 priority)
4719 ++count; 4689 ++count;
4720 } 4690 }
4721 spin_unlock_bh(&efx->filter_lock); 4691 up_read(&table->lock);
4692 up_read(&efx->filter_sem);
4722 return count; 4693 return count;
4723} 4694}
4724 4695
@@ -4733,12 +4704,15 @@ static s32 efx_ef10_filter_get_rx_ids(struct efx_nic *efx,
4733 enum efx_filter_priority priority, 4704 enum efx_filter_priority priority,
4734 u32 *buf, u32 size) 4705 u32 *buf, u32 size)
4735{ 4706{
4736 struct efx_ef10_filter_table *table = efx->filter_state; 4707 struct efx_ef10_filter_table *table;
4737 struct efx_filter_spec *spec; 4708 struct efx_filter_spec *spec;
4738 unsigned int filter_idx; 4709 unsigned int filter_idx;
4739 s32 count = 0; 4710 s32 count = 0;
4740 4711
4741 spin_lock_bh(&efx->filter_lock); 4712 down_read(&efx->filter_sem);
4713 table = efx->filter_state;
4714 down_read(&table->lock);
4715
4742 for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) { 4716 for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) {
4743 spec = efx_ef10_filter_entry_spec(table, filter_idx); 4717 spec = efx_ef10_filter_entry_spec(table, filter_idx);
4744 if (spec && spec->priority == priority) { 4718 if (spec && spec->priority == priority) {
@@ -4752,73 +4726,44 @@ static s32 efx_ef10_filter_get_rx_ids(struct efx_nic *efx,
4752 filter_idx); 4726 filter_idx);
4753 } 4727 }
4754 } 4728 }
4755 spin_unlock_bh(&efx->filter_lock); 4729 up_read(&table->lock);
4730 up_read(&efx->filter_sem);
4756 return count; 4731 return count;
4757} 4732}
4758 4733
4759#ifdef CONFIG_RFS_ACCEL 4734#ifdef CONFIG_RFS_ACCEL
4760 4735
4761static void
4762efx_ef10_filter_rfs_expire_complete(struct efx_nic *efx,
4763 unsigned long filter_idx,
4764 int rc, efx_dword_t *outbuf,
4765 size_t outlen_actual);
4766
4767static bool efx_ef10_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id, 4736static bool efx_ef10_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
4768 unsigned int filter_idx) 4737 unsigned int filter_idx)
4769{ 4738{
4770 struct efx_ef10_filter_table *table = efx->filter_state; 4739 struct efx_ef10_filter_table *table;
4771 struct efx_filter_spec *spec; 4740 struct efx_filter_spec *spec;
4772 MCDI_DECLARE_BUF(inbuf, 4741 bool ret;
4773 MC_CMD_FILTER_OP_IN_HANDLE_OFST +
4774 MC_CMD_FILTER_OP_IN_HANDLE_LEN);
4775 bool ret = true;
4776 4742
4777 spin_lock_bh(&efx->filter_lock); 4743 down_read(&efx->filter_sem);
4744 table = efx->filter_state;
4745 down_write(&table->lock);
4778 spec = efx_ef10_filter_entry_spec(table, filter_idx); 4746 spec = efx_ef10_filter_entry_spec(table, filter_idx);
4779 if (!spec || 4747
4780 (table->entry[filter_idx].spec & EFX_EF10_FILTER_FLAG_BUSY) || 4748 if (!spec || spec->priority != EFX_FILTER_PRI_HINT) {
4781 spec->priority != EFX_FILTER_PRI_HINT || 4749 ret = true;
4782 !rps_may_expire_flow(efx->net_dev, spec->dmaq_id, 4750 goto out_unlock;
4751 }
4752
4753 if (!rps_may_expire_flow(efx->net_dev, spec->dmaq_id,
4783 flow_id, filter_idx)) { 4754 flow_id, filter_idx)) {
4784 ret = false; 4755 ret = false;
4785 goto out_unlock; 4756 goto out_unlock;
4786 } 4757 }
4787 4758
4788 MCDI_SET_DWORD(inbuf, FILTER_OP_IN_OP, 4759 ret = efx_ef10_filter_remove_internal(efx, 1U << spec->priority,
4789 MC_CMD_FILTER_OP_IN_OP_REMOVE); 4760 filter_idx, true) == 0;
4790 MCDI_SET_QWORD(inbuf, FILTER_OP_IN_HANDLE,
4791 table->entry[filter_idx].handle);
4792 if (efx_mcdi_rpc_async(efx, MC_CMD_FILTER_OP, inbuf, sizeof(inbuf), 0,
4793 efx_ef10_filter_rfs_expire_complete, filter_idx))
4794 ret = false;
4795 else
4796 table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY;
4797out_unlock: 4761out_unlock:
4798 spin_unlock_bh(&efx->filter_lock); 4762 up_write(&table->lock);
4763 up_read(&efx->filter_sem);
4799 return ret; 4764 return ret;
4800} 4765}
4801 4766
4802static void
4803efx_ef10_filter_rfs_expire_complete(struct efx_nic *efx,
4804 unsigned long filter_idx,
4805 int rc, efx_dword_t *outbuf,
4806 size_t outlen_actual)
4807{
4808 struct efx_ef10_filter_table *table = efx->filter_state;
4809 struct efx_filter_spec *spec =
4810 efx_ef10_filter_entry_spec(table, filter_idx);
4811
4812 spin_lock_bh(&efx->filter_lock);
4813 if (rc == 0) {
4814 kfree(spec);
4815 efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
4816 }
4817 table->entry[filter_idx].spec &= ~EFX_EF10_FILTER_FLAG_BUSY;
4818 wake_up_all(&table->waitq);
4819 spin_unlock_bh(&efx->filter_lock);
4820}
4821
4822#endif /* CONFIG_RFS_ACCEL */ 4767#endif /* CONFIG_RFS_ACCEL */
4823 4768
4824static int efx_ef10_filter_match_flags_from_mcdi(bool encap, u32 mcdi_flags) 4769static int efx_ef10_filter_match_flags_from_mcdi(bool encap, u32 mcdi_flags)
@@ -5011,9 +4956,9 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx)
5011 table->vlan_filter = 4956 table->vlan_filter =
5012 !!(efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_FILTER); 4957 !!(efx->net_dev->features & NETIF_F_HW_VLAN_CTAG_FILTER);
5013 INIT_LIST_HEAD(&table->vlan_list); 4958 INIT_LIST_HEAD(&table->vlan_list);
4959 init_rwsem(&table->lock);
5014 4960
5015 efx->filter_state = table; 4961 efx->filter_state = table;
5016 init_waitqueue_head(&table->waitq);
5017 4962
5018 list_for_each_entry(vlan, &nic_data->vlan_list, list) { 4963 list_for_each_entry(vlan, &nic_data->vlan_list, list) {
5019 rc = efx_ef10_filter_add_vlan(efx, vlan->vid); 4964 rc = efx_ef10_filter_add_vlan(efx, vlan->vid);
@@ -5055,7 +5000,7 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
5055 if (!table) 5000 if (!table)
5056 return; 5001 return;
5057 5002
5058 spin_lock_bh(&efx->filter_lock); 5003 down_write(&table->lock);
5059 5004
5060 for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) { 5005 for (filter_idx = 0; filter_idx < HUNT_FILTER_TBL_ROWS; filter_idx++) {
5061 spec = efx_ef10_filter_entry_spec(table, filter_idx); 5006 spec = efx_ef10_filter_entry_spec(table, filter_idx);
@@ -5093,15 +5038,11 @@ static void efx_ef10_filter_table_restore(struct efx_nic *efx)
5093 } 5038 }
5094 } 5039 }
5095 5040
5096 table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY;
5097 spin_unlock_bh(&efx->filter_lock);
5098
5099 rc = efx_ef10_filter_push(efx, spec, 5041 rc = efx_ef10_filter_push(efx, spec,
5100 &table->entry[filter_idx].handle, 5042 &table->entry[filter_idx].handle,
5101 ctx, false); 5043 ctx, false);
5102 if (rc) 5044 if (rc)
5103 failed++; 5045 failed++;
5104 spin_lock_bh(&efx->filter_lock);
5105 5046
5106 if (rc) { 5047 if (rc) {
5107not_restored: 5048not_restored:
@@ -5113,13 +5054,10 @@ not_restored:
5113 5054
5114 kfree(spec); 5055 kfree(spec);
5115 efx_ef10_filter_set_entry(table, filter_idx, NULL, 0); 5056 efx_ef10_filter_set_entry(table, filter_idx, NULL, 0);
5116 } else {
5117 table->entry[filter_idx].spec &=
5118 ~EFX_EF10_FILTER_FLAG_BUSY;
5119 } 5057 }
5120 } 5058 }
5121 5059
5122 spin_unlock_bh(&efx->filter_lock); 5060 up_write(&table->lock);
5123 5061
5124 /* This can happen validly if the MC's capabilities have changed, so 5062 /* This can happen validly if the MC's capabilities have changed, so
5125 * is not an error. 5063 * is not an error.
@@ -5187,6 +5125,8 @@ static void efx_ef10_filter_mark_one_old(struct efx_nic *efx, uint16_t *id)
5187 struct efx_ef10_filter_table *table = efx->filter_state; 5125 struct efx_ef10_filter_table *table = efx->filter_state;
5188 unsigned int filter_idx; 5126 unsigned int filter_idx;
5189 5127
5128 efx_rwsem_assert_write_locked(&table->lock);
5129
5190 if (*id != EFX_EF10_FILTER_ID_INVALID) { 5130 if (*id != EFX_EF10_FILTER_ID_INVALID) {
5191 filter_idx = efx_ef10_filter_get_unsafe_id(*id); 5131 filter_idx = efx_ef10_filter_get_unsafe_id(*id);
5192 if (!table->entry[filter_idx].spec) 5132 if (!table->entry[filter_idx].spec)
@@ -5222,10 +5162,10 @@ static void efx_ef10_filter_mark_old(struct efx_nic *efx)
5222 struct efx_ef10_filter_table *table = efx->filter_state; 5162 struct efx_ef10_filter_table *table = efx->filter_state;
5223 struct efx_ef10_filter_vlan *vlan; 5163 struct efx_ef10_filter_vlan *vlan;
5224 5164
5225 spin_lock_bh(&efx->filter_lock); 5165 down_write(&table->lock);
5226 list_for_each_entry(vlan, &table->vlan_list, list) 5166 list_for_each_entry(vlan, &table->vlan_list, list)
5227 _efx_ef10_filter_vlan_mark_old(efx, vlan); 5167 _efx_ef10_filter_vlan_mark_old(efx, vlan);
5228 spin_unlock_bh(&efx->filter_lock); 5168 up_write(&table->lock);
5229} 5169}
5230 5170
5231static void efx_ef10_filter_uc_addr_list(struct efx_nic *efx) 5171static void efx_ef10_filter_uc_addr_list(struct efx_nic *efx)
@@ -5502,10 +5442,7 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx,
5502 return rc; 5442 return rc;
5503} 5443}
5504 5444
5505/* Remove filters that weren't renewed. Since nothing else changes the AUTO_OLD 5445/* Remove filters that weren't renewed. */
5506 * flag or removes these filters, we don't need to hold the filter_lock while
5507 * scanning for these filters.
5508 */
5509static void efx_ef10_filter_remove_old(struct efx_nic *efx) 5446static void efx_ef10_filter_remove_old(struct efx_nic *efx)
5510{ 5447{
5511 struct efx_ef10_filter_table *table = efx->filter_state; 5448 struct efx_ef10_filter_table *table = efx->filter_state;
@@ -5514,6 +5451,7 @@ static void efx_ef10_filter_remove_old(struct efx_nic *efx)
5514 int rc; 5451 int rc;
5515 int i; 5452 int i;
5516 5453
5454 down_write(&table->lock);
5517 for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) { 5455 for (i = 0; i < HUNT_FILTER_TBL_ROWS; i++) {
5518 if (READ_ONCE(table->entry[i].spec) & 5456 if (READ_ONCE(table->entry[i].spec) &
5519 EFX_EF10_FILTER_FLAG_AUTO_OLD) { 5457 EFX_EF10_FILTER_FLAG_AUTO_OLD) {
@@ -5525,6 +5463,7 @@ static void efx_ef10_filter_remove_old(struct efx_nic *efx)
5525 remove_failed++; 5463 remove_failed++;
5526 } 5464 }
5527 } 5465 }
5466 up_write(&table->lock);
5528 5467
5529 if (remove_failed) 5468 if (remove_failed)
5530 netif_info(efx, drv, efx->net_dev, 5469 netif_info(efx, drv, efx->net_dev,
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 0be93abdb2ad..cb9273016916 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -1783,7 +1783,6 @@ static int efx_probe_filters(struct efx_nic *efx)
1783{ 1783{
1784 int rc; 1784 int rc;
1785 1785
1786 spin_lock_init(&efx->filter_lock);
1787 init_rwsem(&efx->filter_sem); 1786 init_rwsem(&efx->filter_sem);
1788 mutex_lock(&efx->mac_lock); 1787 mutex_lock(&efx->mac_lock);
1789 down_write(&efx->filter_sem); 1788 down_write(&efx->filter_sem);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index dad78e3dde70..e2901dda4e32 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -843,7 +843,7 @@ struct efx_rss_context {
843 * @loopback_mode: Loopback status 843 * @loopback_mode: Loopback status
844 * @loopback_modes: Supported loopback mode bitmask 844 * @loopback_modes: Supported loopback mode bitmask
845 * @loopback_selftest: Offline self-test private state 845 * @loopback_selftest: Offline self-test private state
846 * @filter_sem: Filter table rw_semaphore, for freeing the table 846 * @filter_sem: Filter table rw_semaphore, protects existence of @filter_state
847 * @filter_lock: Filter table lock, for mere content changes 847 * @filter_lock: Filter table lock, for mere content changes
848 * @filter_state: Architecture-dependent filter table state 848 * @filter_state: Architecture-dependent filter table state
849 * @rps_mutex: Protects RPS state of all channels 849 * @rps_mutex: Protects RPS state of all channels