Skip to content

Commit 3af0f34

Browse files
ecree-solarflaredavem330
authored andcommitted
sfc: replace asynchronous filter operations
Instead of having an efx->type->filter_rfs_insert() method, just use workitems with a worker function that calls efx->type->filter_insert(). The only user of this is efx_filter_rfs(), which now queues a call to efx_filter_rfs_work(). Similarly, efx_filter_rfs_expire() is now a worker function called on a new channel->filter_work work_struct, so the method efx->type->filter_rfs_expire_one() is no longer called in atomic context. We also add a new mutex efx->rps_mutex to protect the RPS state (efx-> rps_expire_channel, efx->rps_expire_index, and channel->rps_flow_id) so that the taking of efx->filter_lock can be moved to efx->type->filter_rfs_expire_one(). Thus, all filter table functions are now called in a sleepable context, allowing them to use sleeping locks in a future patch. Signed-off-by: Edward Cree <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c709002 commit 3af0f34

File tree

8 files changed

+124
-208
lines changed

8 files changed

+124
-208
lines changed

drivers/net/ethernet/sfc/ef10.c

Lines changed: 14 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -4758,143 +4758,6 @@ static s32 efx_ef10_filter_get_rx_ids(struct efx_nic *efx,
47584758

47594759
#ifdef CONFIG_RFS_ACCEL
47604760

4761-
static efx_mcdi_async_completer efx_ef10_filter_rfs_insert_complete;
4762-
4763-
static s32 efx_ef10_filter_rfs_insert(struct efx_nic *efx,
4764-
struct efx_filter_spec *spec)
4765-
{
4766-
struct efx_ef10_filter_table *table = efx->filter_state;
4767-
MCDI_DECLARE_BUF(inbuf, MC_CMD_FILTER_OP_EXT_IN_LEN);
4768-
struct efx_filter_spec *saved_spec;
4769-
unsigned int hash, i, depth = 1;
4770-
bool replacing = false;
4771-
int ins_index = -1;
4772-
u64 cookie;
4773-
s32 rc;
4774-
4775-
/* Must be an RX filter without RSS and not for a multicast
4776-
* destination address (RFS only works for connected sockets).
4777-
* These restrictions allow us to pass only a tiny amount of
4778-
* data through to the completion function.
4779-
*/
4780-
EFX_WARN_ON_PARANOID(spec->flags !=
4781-
(EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_SCATTER));
4782-
EFX_WARN_ON_PARANOID(spec->priority != EFX_FILTER_PRI_HINT);
4783-
EFX_WARN_ON_PARANOID(efx_filter_is_mc_recipient(spec));
4784-
4785-
hash = efx_ef10_filter_hash(spec);
4786-
4787-
spin_lock_bh(&efx->filter_lock);
4788-
4789-
/* Find any existing filter with the same match tuple or else
4790-
* a free slot to insert at. If an existing filter is busy,
4791-
* we have to give up.
4792-
*/
4793-
for (;;) {
4794-
i = (hash + depth) & (HUNT_FILTER_TBL_ROWS - 1);
4795-
saved_spec = efx_ef10_filter_entry_spec(table, i);
4796-
4797-
if (!saved_spec) {
4798-
if (ins_index < 0)
4799-
ins_index = i;
4800-
} else if (efx_ef10_filter_equal(spec, saved_spec)) {
4801-
if (table->entry[i].spec & EFX_EF10_FILTER_FLAG_BUSY) {
4802-
rc = -EBUSY;
4803-
goto fail_unlock;
4804-
}
4805-
if (spec->priority < saved_spec->priority) {
4806-
rc = -EPERM;
4807-
goto fail_unlock;
4808-
}
4809-
ins_index = i;
4810-
break;
4811-
}
4812-
4813-
/* Once we reach the maximum search depth, use the
4814-
* first suitable slot or return -EBUSY if there was
4815-
* none
4816-
*/
4817-
if (depth == EFX_EF10_FILTER_SEARCH_LIMIT) {
4818-
if (ins_index < 0) {
4819-
rc = -EBUSY;
4820-
goto fail_unlock;
4821-
}
4822-
break;
4823-
}
4824-
4825-
++depth;
4826-
}
4827-
4828-
/* Create a software table entry if necessary, and mark it
4829-
* busy. We might yet fail to insert, but any attempt to
4830-
* insert a conflicting filter while we're waiting for the
4831-
* firmware must find the busy entry.
4832-
*/
4833-
saved_spec = efx_ef10_filter_entry_spec(table, ins_index);
4834-
if (saved_spec) {
4835-
replacing = true;
4836-
} else {
4837-
saved_spec = kmalloc(sizeof(*spec), GFP_ATOMIC);
4838-
if (!saved_spec) {
4839-
rc = -ENOMEM;
4840-
goto fail_unlock;
4841-
}
4842-
*saved_spec = *spec;
4843-
}
4844-
efx_ef10_filter_set_entry(table, ins_index, saved_spec,
4845-
EFX_EF10_FILTER_FLAG_BUSY);
4846-
4847-
spin_unlock_bh(&efx->filter_lock);
4848-
4849-
/* Pack up the variables needed on completion */
4850-
cookie = replacing << 31 | ins_index << 16 | spec->dmaq_id;
4851-
4852-
efx_ef10_filter_push_prep(efx, spec, inbuf,
4853-
table->entry[ins_index].handle, NULL,
4854-
replacing);
4855-
efx_mcdi_rpc_async(efx, MC_CMD_FILTER_OP, inbuf, sizeof(inbuf),
4856-
MC_CMD_FILTER_OP_OUT_LEN,
4857-
efx_ef10_filter_rfs_insert_complete, cookie);
4858-
4859-
return ins_index;
4860-
4861-
fail_unlock:
4862-
spin_unlock_bh(&efx->filter_lock);
4863-
return rc;
4864-
}
4865-
4866-
static void
4867-
efx_ef10_filter_rfs_insert_complete(struct efx_nic *efx, unsigned long cookie,
4868-
int rc, efx_dword_t *outbuf,
4869-
size_t outlen_actual)
4870-
{
4871-
struct efx_ef10_filter_table *table = efx->filter_state;
4872-
unsigned int ins_index, dmaq_id;
4873-
struct efx_filter_spec *spec;
4874-
bool replacing;
4875-
4876-
/* Unpack the cookie */
4877-
replacing = cookie >> 31;
4878-
ins_index = (cookie >> 16) & (HUNT_FILTER_TBL_ROWS - 1);
4879-
dmaq_id = cookie & 0xffff;
4880-
4881-
spin_lock_bh(&efx->filter_lock);
4882-
spec = efx_ef10_filter_entry_spec(table, ins_index);
4883-
if (rc == 0) {
4884-
table->entry[ins_index].handle =
4885-
MCDI_QWORD(outbuf, FILTER_OP_OUT_HANDLE);
4886-
if (replacing)
4887-
spec->dmaq_id = dmaq_id;
4888-
} else if (!replacing) {
4889-
kfree(spec);
4890-
spec = NULL;
4891-
}
4892-
efx_ef10_filter_set_entry(table, ins_index, spec, 0);
4893-
spin_unlock_bh(&efx->filter_lock);
4894-
4895-
wake_up_all(&table->waitq);
4896-
}
4897-
48984761
static void
48994762
efx_ef10_filter_rfs_expire_complete(struct efx_nic *efx,
49004763
unsigned long filter_idx,
@@ -4905,29 +4768,35 @@ static bool efx_ef10_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
49054768
unsigned int filter_idx)
49064769
{
49074770
struct efx_ef10_filter_table *table = efx->filter_state;
4908-
struct efx_filter_spec *spec =
4909-
efx_ef10_filter_entry_spec(table, filter_idx);
4771+
struct efx_filter_spec *spec;
49104772
MCDI_DECLARE_BUF(inbuf,
49114773
MC_CMD_FILTER_OP_IN_HANDLE_OFST +
49124774
MC_CMD_FILTER_OP_IN_HANDLE_LEN);
4775+
bool ret = true;
49134776

4777+
spin_lock_bh(&efx->filter_lock);
4778+
spec = efx_ef10_filter_entry_spec(table, filter_idx);
49144779
if (!spec ||
49154780
(table->entry[filter_idx].spec & EFX_EF10_FILTER_FLAG_BUSY) ||
49164781
spec->priority != EFX_FILTER_PRI_HINT ||
49174782
!rps_may_expire_flow(efx->net_dev, spec->dmaq_id,
4918-
flow_id, filter_idx))
4919-
return false;
4783+
flow_id, filter_idx)) {
4784+
ret = false;
4785+
goto out_unlock;
4786+
}
49204787

49214788
MCDI_SET_DWORD(inbuf, FILTER_OP_IN_OP,
49224789
MC_CMD_FILTER_OP_IN_OP_REMOVE);
49234790
MCDI_SET_QWORD(inbuf, FILTER_OP_IN_HANDLE,
49244791
table->entry[filter_idx].handle);
49254792
if (efx_mcdi_rpc_async(efx, MC_CMD_FILTER_OP, inbuf, sizeof(inbuf), 0,
49264793
efx_ef10_filter_rfs_expire_complete, filter_idx))
4927-
return false;
4928-
4929-
table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY;
4930-
return true;
4794+
ret = false;
4795+
else
4796+
table->entry[filter_idx].spec |= EFX_EF10_FILTER_FLAG_BUSY;
4797+
out_unlock:
4798+
spin_unlock_bh(&efx->filter_lock);
4799+
return ret;
49314800
}
49324801

49334802
static void
@@ -6784,7 +6653,6 @@ const struct efx_nic_type efx_hunt_a0_vf_nic_type = {
67846653
.filter_get_rx_id_limit = efx_ef10_filter_get_rx_id_limit,
67856654
.filter_get_rx_ids = efx_ef10_filter_get_rx_ids,
67866655
#ifdef CONFIG_RFS_ACCEL
6787-
.filter_rfs_insert = efx_ef10_filter_rfs_insert,
67886656
.filter_rfs_expire_one = efx_ef10_filter_rfs_expire_one,
67896657
#endif
67906658
#ifdef CONFIG_SFC_MTD
@@ -6897,7 +6765,6 @@ const struct efx_nic_type efx_hunt_a0_nic_type = {
68976765
.filter_get_rx_id_limit = efx_ef10_filter_get_rx_id_limit,
68986766
.filter_get_rx_ids = efx_ef10_filter_get_rx_ids,
68996767
#ifdef CONFIG_RFS_ACCEL
6900-
.filter_rfs_insert = efx_ef10_filter_rfs_insert,
69016768
.filter_rfs_expire_one = efx_ef10_filter_rfs_expire_one,
69026769
#endif
69036770
#ifdef CONFIG_SFC_MTD

drivers/net/ethernet/sfc/efx.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,10 @@ static int efx_poll(struct napi_struct *napi, int budget)
340340
efx_update_irq_mod(efx, channel);
341341
}
342342

343-
efx_filter_rfs_expire(channel);
343+
#ifdef CONFIG_RFS_ACCEL
344+
/* Perhaps expire some ARFS filters */
345+
schedule_work(&channel->filter_work);
346+
#endif
344347

345348
/* There is no race here; although napi_disable() will
346349
* only wait for napi_complete(), this isn't a problem
@@ -470,6 +473,10 @@ efx_alloc_channel(struct efx_nic *efx, int i, struct efx_channel *old_channel)
470473
tx_queue->channel = channel;
471474
}
472475

476+
#ifdef CONFIG_RFS_ACCEL
477+
INIT_WORK(&channel->filter_work, efx_filter_rfs_expire);
478+
#endif
479+
473480
rx_queue = &channel->rx_queue;
474481
rx_queue->efx = efx;
475482
timer_setup(&rx_queue->slow_fill, efx_rx_slow_fill, 0);
@@ -512,6 +519,9 @@ efx_copy_channel(const struct efx_channel *old_channel)
512519
rx_queue->buffer = NULL;
513520
memset(&rx_queue->rxd, 0, sizeof(rx_queue->rxd));
514521
timer_setup(&rx_queue->slow_fill, efx_rx_slow_fill, 0);
522+
#ifdef CONFIG_RFS_ACCEL
523+
INIT_WORK(&channel->filter_work, efx_filter_rfs_expire);
524+
#endif
515525

516526
return channel;
517527
}
@@ -3012,6 +3022,9 @@ static int efx_init_struct(struct efx_nic *efx,
30123022
efx->num_mac_stats = MC_CMD_MAC_NSTATS;
30133023
BUILD_BUG_ON(MC_CMD_MAC_NSTATS - 1 != MC_CMD_MAC_GENERATION_END);
30143024
mutex_init(&efx->mac_lock);
3025+
#ifdef CONFIG_RFS_ACCEL
3026+
mutex_init(&efx->rps_mutex);
3027+
#endif
30153028
efx->phy_op = &efx_dummy_phy_operations;
30163029
efx->mdio.dev = net_dev;
30173030
INIT_WORK(&efx->mac_work, efx_mac_work);

drivers/net/ethernet/sfc/efx.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,18 @@ static inline s32 efx_filter_get_rx_ids(struct efx_nic *efx,
170170
int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
171171
u16 rxq_index, u32 flow_id);
172172
bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota);
173-
static inline void efx_filter_rfs_expire(struct efx_channel *channel)
173+
static inline void efx_filter_rfs_expire(struct work_struct *data)
174174
{
175+
struct efx_channel *channel = container_of(data, struct efx_channel,
176+
filter_work);
177+
175178
if (channel->rfs_filters_added >= 60 &&
176179
__efx_filter_rfs_expire(channel->efx, 100))
177180
channel->rfs_filters_added -= 60;
178181
}
179182
#define efx_filter_rfs_enabled() 1
180183
#else
181-
static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
184+
static inline void efx_filter_rfs_expire(struct work_struct *data) {}
182185
#define efx_filter_rfs_enabled() 0
183186
#endif
184187
bool efx_filter_is_mc_recipient(const struct efx_filter_spec *spec);

drivers/net/ethernet/sfc/farch.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2901,28 +2901,25 @@ void efx_farch_filter_update_rx_scatter(struct efx_nic *efx)
29012901

29022902
#ifdef CONFIG_RFS_ACCEL
29032903

2904-
s32 efx_farch_filter_rfs_insert(struct efx_nic *efx,
2905-
struct efx_filter_spec *gen_spec)
2906-
{
2907-
return efx_farch_filter_insert(efx, gen_spec, true);
2908-
}
2909-
29102904
bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
29112905
unsigned int index)
29122906
{
29132907
struct efx_farch_filter_state *state = efx->filter_state;
2914-
struct efx_farch_filter_table *table =
2915-
&state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
2908+
struct efx_farch_filter_table *table;
2909+
bool ret = false;
29162910

2911+
spin_lock_bh(&efx->filter_lock);
2912+
table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
29172913
if (test_bit(index, table->used_bitmap) &&
29182914
table->spec[index].priority == EFX_FILTER_PRI_HINT &&
29192915
rps_may_expire_flow(efx->net_dev, table->spec[index].dmaq_id,
29202916
flow_id, index)) {
29212917
efx_farch_filter_table_clear_entry(efx, table, index);
2922-
return true;
2918+
ret = true;
29232919
}
29242920

2925-
return false;
2921+
spin_unlock_bh(&efx->filter_lock);
2922+
return ret;
29262923
}
29272924

29282925
#endif /* CONFIG_RFS_ACCEL */

drivers/net/ethernet/sfc/net_driver.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ enum efx_sync_events_state {
430430
* @event_test_cpu: Last CPU to handle interrupt or test event for this channel
431431
* @irq_count: Number of IRQs since last adaptive moderation decision
432432
* @irq_mod_score: IRQ moderation score
433+
* @filter_work: Work item for efx_filter_rfs_expire()
433434
* @rps_flow_id: Flow IDs of filters allocated for accelerated RFS,
434435
* indexed by filter ID
435436
* @n_rx_tobe_disc: Count of RX_TOBE_DISC errors
@@ -475,6 +476,7 @@ struct efx_channel {
475476
unsigned int irq_mod_score;
476477
#ifdef CONFIG_RFS_ACCEL
477478
unsigned int rfs_filters_added;
479+
struct work_struct filter_work;
478480
#define RPS_FLOW_ID_INVALID 0xFFFFFFFF
479481
u32 *rps_flow_id;
480482
#endif
@@ -844,6 +846,7 @@ struct efx_rss_context {
844846
* @filter_sem: Filter table rw_semaphore, for freeing the table
845847
* @filter_lock: Filter table lock, for mere content changes
846848
* @filter_state: Architecture-dependent filter table state
849+
* @rps_mutex: Protects RPS state of all channels
847850
* @rps_expire_channel: Next channel to check for expiry
848851
* @rps_expire_index: Next index to check for expiry in
849852
* @rps_expire_channel's @rps_flow_id
@@ -998,6 +1001,7 @@ struct efx_nic {
9981001
spinlock_t filter_lock;
9991002
void *filter_state;
10001003
#ifdef CONFIG_RFS_ACCEL
1004+
struct mutex rps_mutex;
10011005
unsigned int rps_expire_channel;
10021006
unsigned int rps_expire_index;
10031007
#endif
@@ -1152,10 +1156,6 @@ struct efx_udp_tunnel {
11521156
* @filter_count_rx_used: Get the number of filters in use at a given priority
11531157
* @filter_get_rx_id_limit: Get maximum value of a filter id, plus 1
11541158
* @filter_get_rx_ids: Get list of RX filters at a given priority
1155-
* @filter_rfs_insert: Add or replace a filter for RFS. This must be
1156-
* atomic. The hardware change may be asynchronous but should
1157-
* not be delayed for long. It may fail if this can't be done
1158-
* atomically.
11591159
* @filter_rfs_expire_one: Consider expiring a filter inserted for RFS.
11601160
* This must check whether the specified table entry is used by RFS
11611161
* and that rps_may_expire_flow() returns true for it.
@@ -1306,8 +1306,6 @@ struct efx_nic_type {
13061306
enum efx_filter_priority priority,
13071307
u32 *buf, u32 size);
13081308
#ifdef CONFIG_RFS_ACCEL
1309-
s32 (*filter_rfs_insert)(struct efx_nic *efx,
1310-
struct efx_filter_spec *spec);
13111309
bool (*filter_rfs_expire_one)(struct efx_nic *efx, u32 flow_id,
13121310
unsigned int index);
13131311
#endif

drivers/net/ethernet/sfc/nic.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -601,8 +601,6 @@ s32 efx_farch_filter_get_rx_ids(struct efx_nic *efx,
601601
enum efx_filter_priority priority, u32 *buf,
602602
u32 size);
603603
#ifdef CONFIG_RFS_ACCEL
604-
s32 efx_farch_filter_rfs_insert(struct efx_nic *efx,
605-
struct efx_filter_spec *spec);
606604
bool efx_farch_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id,
607605
unsigned int index);
608606
#endif

0 commit comments

Comments
 (0)