diff options
| author | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
| commit | 1ac731c529cd4d6adbce134754b51ff7d822b145 (patch) | |
| tree | 143ab3f35ca5f3b69f583c84e6964b17139c2ec1 /drivers/net/ethernet/microchip/vcap/vcap_api.c | |
| parent | 07b4c950f27bef0362dc6ad7ee713aab61d58149 (diff) | |
| parent | 54116d442e001e1b6bd482122043b1870998a1f3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.6 merge window.
Diffstat (limited to 'drivers/net/ethernet/microchip/vcap/vcap_api.c')
| -rw-r--r-- | drivers/net/ethernet/microchip/vcap/vcap_api.c | 61 | 
1 files changed, 61 insertions, 0 deletions
diff --git a/drivers/net/ethernet/microchip/vcap/vcap_api.c b/drivers/net/ethernet/microchip/vcap/vcap_api.c index 4847d0d99ec9..5675b0962bc3 100644 --- a/drivers/net/ethernet/microchip/vcap/vcap_api.c +++ b/drivers/net/ethernet/microchip/vcap/vcap_api.c @@ -976,6 +976,25 @@ int vcap_lookup_rule_by_cookie(struct vcap_control *vctrl, u64 cookie)  }  EXPORT_SYMBOL_GPL(vcap_lookup_rule_by_cookie); +/* Get number of rules in a vcap instance lookup chain id range */ +int vcap_admin_rule_count(struct vcap_admin *admin, int cid) +{ +	int max_cid = roundup(cid + 1, VCAP_CID_LOOKUP_SIZE); +	int min_cid = rounddown(cid, VCAP_CID_LOOKUP_SIZE); +	struct vcap_rule_internal *elem; +	int count = 0; + +	list_for_each_entry(elem, &admin->rules, list) { +		mutex_lock(&admin->lock); +		if (elem->data.vcap_chain_id >= min_cid && +		    elem->data.vcap_chain_id < max_cid) +			++count; +		mutex_unlock(&admin->lock); +	} +	return count; +} +EXPORT_SYMBOL_GPL(vcap_admin_rule_count); +  /* Make a copy of the rule, shallow or full */  static struct vcap_rule_internal *vcap_dup_rule(struct vcap_rule_internal *ri,  						bool full) @@ -3403,6 +3422,25 @@ int vcap_rule_mod_key_u32(struct vcap_rule *rule, enum vcap_key_field key,  }  EXPORT_SYMBOL_GPL(vcap_rule_mod_key_u32); +/* Remove a key field with value and mask in the rule */ +int vcap_rule_rem_key(struct vcap_rule *rule, enum vcap_key_field key) +{ +	struct vcap_rule_internal *ri = to_intrule(rule); +	struct vcap_client_keyfield *field; + +	field = vcap_find_keyfield(rule, key); +	if (!field) { +		pr_err("%s:%d: key %s is not in the rule\n", +		       __func__, __LINE__, vcap_keyfield_name(ri->vctrl, key)); +		return -EINVAL; +	} +	/* Deallocate the key field */ +	list_del(&field->ctrl.list); +	kfree(field); +	return 0; +} +EXPORT_SYMBOL_GPL(vcap_rule_rem_key); +  static int vcap_rule_mod_action(struct vcap_rule *rule,  				enum vcap_action_field action,  				enum vcap_field_type ftype, @@ -3475,6 +3513,29 @@ int vcap_filter_rule_keys(struct vcap_rule *rule,  }  EXPORT_SYMBOL_GPL(vcap_filter_rule_keys); +/* Select the keyset from the list that results in the smallest rule size */ +enum vcap_keyfield_set +vcap_select_min_rule_keyset(struct vcap_control *vctrl, +			    enum vcap_type vtype, +			    struct vcap_keyset_list *kslist) +{ +	enum vcap_keyfield_set ret = VCAP_KFS_NO_VALUE; +	const struct vcap_set *kset; +	int max = 100, idx; + +	for (idx = 0; idx < kslist->cnt; ++idx) { +		kset = vcap_keyfieldset(vctrl, vtype, kslist->keysets[idx]); +		if (!kset) +			continue; +		if (kset->sw_per_item >= max) +			continue; +		max = kset->sw_per_item; +		ret = kslist->keysets[idx]; +	} +	return ret; +} +EXPORT_SYMBOL_GPL(vcap_select_min_rule_keyset); +  /* Make a full copy of an existing rule with a new rule id */  struct vcap_rule *vcap_copy_rule(struct vcap_rule *erule)  {  |