Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20b298f5 authored by Rasesh Mody's avatar Rasesh Mody Committed by David S. Miller
Browse files

bna: Fix Filter Add Del



Change Details:
 - bna_rx_mcast_listset() API first looks at free_q only and not at other
   pending Qs rendering it non-deterministic of giving an upper limit.
   Modify bna_rx_mcast_listset() implementation to not use only half of the
   limit.
 - Allocate and initialize queue for deleting
 - Segregate the adding and deleting process by using separate queues.
 - The filter framework in bna does not let adding addresses to its max capacity
   due to asynchronous operations involved.
   Provide a synchronous option to set a given list.

Signed-off-by: default avatarRasesh Mody <rmody@brocade.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 41ed903a
Loading
Loading
Loading
Loading
+10 −6
Original line number Original line Diff line number Diff line
@@ -354,6 +354,14 @@ do { \
	}								\
	}								\
} while (0)
} while (0)


#define bna_mcam_mod_free_q(_bna) (&(_bna)->mcam_mod.free_q)

#define bna_mcam_mod_del_q(_bna) (&(_bna)->mcam_mod.del_q)

#define bna_ucam_mod_free_q(_bna) (&(_bna)->ucam_mod.free_q)

#define bna_ucam_mod_del_q(_bna) (&(_bna)->ucam_mod.del_q)

/*  Inline functions  */
/*  Inline functions  */


static inline struct bna_mac *bna_mac_find(struct list_head *q, u8 *addr)
static inline struct bna_mac *bna_mac_find(struct list_head *q, u8 *addr)
@@ -391,12 +399,8 @@ int bna_num_rxp_set(struct bna *bna, int num_rxp);
void bna_hw_stats_get(struct bna *bna);
void bna_hw_stats_get(struct bna *bna);


/* APIs for RxF */
/* APIs for RxF */
struct bna_mac *bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod);
struct bna_mac *bna_cam_mod_mac_get(struct list_head *head);
void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod,
void bna_cam_mod_mac_put(struct list_head *tail, struct bna_mac *mac);
			  struct bna_mac *mac);
struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod);
void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod,
			  struct bna_mac *mac);
struct bna_mcam_handle *bna_mcam_mod_handle_get(struct bna_mcam_mod *mod);
struct bna_mcam_handle *bna_mcam_mod_handle_get(struct bna_mcam_mod *mod);
void bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod,
void bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod,
			  struct bna_mcam_handle *handle);
			  struct bna_mcam_handle *handle);
+21 −27
Original line number Original line Diff line number Diff line
@@ -1811,6 +1811,13 @@ bna_ucam_mod_init(struct bna_ucam_mod *ucam_mod, struct bna *bna,
		list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
		list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->free_q);
	}
	}


	/* A separate queue to allow synchronous setting of a list of MACs */
	INIT_LIST_HEAD(&ucam_mod->del_q);
	for (i = i; i < (bna->ioceth.attr.num_ucmac * 2); i++) {
		bfa_q_qe_init(&ucam_mod->ucmac[i].qe);
		list_add_tail(&ucam_mod->ucmac[i].qe, &ucam_mod->del_q);
	}

	ucam_mod->bna = bna;
	ucam_mod->bna = bna;
}
}


@@ -1851,6 +1858,13 @@ bna_mcam_mod_init(struct bna_mcam_mod *mcam_mod, struct bna *bna,
				&mcam_mod->free_handle_q);
				&mcam_mod->free_handle_q);
	}
	}


	/* A separate queue to allow synchronous setting of a list of MACs */
	INIT_LIST_HEAD(&mcam_mod->del_q);
	for (i = i; i < (bna->ioceth.attr.num_mcmac * 2); i++) {
		bfa_q_qe_init(&mcam_mod->mcmac[i].qe);
		list_add_tail(&mcam_mod->mcmac[i].qe, &mcam_mod->del_q);
	}

	mcam_mod->bna = bna;
	mcam_mod->bna = bna;
}
}


@@ -1976,7 +1990,7 @@ bna_mod_res_req(struct bna *bna, struct bna_res_info *res_info)
		BNA_MEM_T_KVA;
		BNA_MEM_T_KVA;
	res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
	res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.num = 1;
	res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
	res_info[BNA_MOD_RES_MEM_T_UCMAC_ARRAY].res_u.mem_info.len =
		attr->num_ucmac * sizeof(struct bna_mac);
		(attr->num_ucmac * 2) * sizeof(struct bna_mac);


	/* Virtual memory for Multicast MAC address - stored by mcam module */
	/* Virtual memory for Multicast MAC address - stored by mcam module */
	res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
	res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_type = BNA_RES_T_MEM;
@@ -1984,7 +1998,7 @@ bna_mod_res_req(struct bna *bna, struct bna_res_info *res_info)
		BNA_MEM_T_KVA;
		BNA_MEM_T_KVA;
	res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
	res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.num = 1;
	res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
	res_info[BNA_MOD_RES_MEM_T_MCMAC_ARRAY].res_u.mem_info.len =
		attr->num_mcmac * sizeof(struct bna_mac);
		(attr->num_mcmac * 2) * sizeof(struct bna_mac);


	/* Virtual memory for Multicast handle - stored by mcam module */
	/* Virtual memory for Multicast handle - stored by mcam module */
	res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_type = BNA_RES_T_MEM;
	res_info[BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY].res_type = BNA_RES_T_MEM;
@@ -2080,41 +2094,21 @@ bna_num_rxp_set(struct bna *bna, int num_rxp)
}
}


struct bna_mac *
struct bna_mac *
bna_ucam_mod_mac_get(struct bna_ucam_mod *ucam_mod)
bna_cam_mod_mac_get(struct list_head *head)
{
{
	struct list_head *qe;
	struct list_head *qe;


	if (list_empty(&ucam_mod->free_q))
	if (list_empty(head))
		return NULL;
		return NULL;


	bfa_q_deq(&ucam_mod->free_q, &qe);
	bfa_q_deq(head, &qe);

	return (struct bna_mac *)qe;
}

void
bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *mac)
{
	list_add_tail(&mac->qe, &ucam_mod->free_q);
}

struct bna_mac *
bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod)
{
	struct list_head *qe;

	if (list_empty(&mcam_mod->free_q))
		return NULL;

	bfa_q_deq(&mcam_mod->free_q, &qe);

	return (struct bna_mac *)qe;
	return (struct bna_mac *)qe;
}
}


void
void
bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac)
bna_cam_mod_mac_put(struct list_head *tail, struct bna_mac *mac)
{
{
	list_add_tail(&mac->qe, &mcam_mod->free_q);
	list_add_tail(&mac->qe, tail);
}
}


struct bna_mcam_handle *
struct bna_mcam_handle *
+38 −29
Original line number Original line Diff line number Diff line
@@ -529,13 +529,13 @@ bna_rxf_mcast_cfg_apply(struct bna_rxf *rxf)
	struct list_head *qe;
	struct list_head *qe;
	int ret;
	int ret;


	/* Delete multicast entries previousely added */
	/* First delete multicast entries to maintain the count */
	while (!list_empty(&rxf->mcast_pending_del_q)) {
	while (!list_empty(&rxf->mcast_pending_del_q)) {
		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
		bfa_q_deq(&rxf->mcast_pending_del_q, &qe);
		bfa_q_qe_init(qe);
		bfa_q_qe_init(qe);
		mac = (struct bna_mac *)qe;
		mac = (struct bna_mac *)qe;
		ret = bna_rxf_mcast_del(rxf, mac, BNA_HARD_CLEANUP);
		ret = bna_rxf_mcast_del(rxf, mac, BNA_HARD_CLEANUP);
		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
		bna_cam_mod_mac_put(bna_mcam_mod_del_q(rxf->rx->bna), mac);
		if (ret)
		if (ret)
			return ret;
			return ret;
	}
	}
@@ -586,7 +586,7 @@ bna_rxf_mcast_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
		bfa_q_qe_init(qe);
		bfa_q_qe_init(qe);
		mac = (struct bna_mac *)qe;
		mac = (struct bna_mac *)qe;
		ret = bna_rxf_mcast_del(rxf, mac, cleanup);
		ret = bna_rxf_mcast_del(rxf, mac, cleanup);
		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
		bna_cam_mod_mac_put(bna_mcam_mod_del_q(rxf->rx->bna), mac);
		if (ret)
		if (ret)
			return ret;
			return ret;
	}
	}
@@ -796,12 +796,12 @@ bna_rxf_uninit(struct bna_rxf *rxf)
	while (!list_empty(&rxf->ucast_pending_add_q)) {
	while (!list_empty(&rxf->ucast_pending_add_q)) {
		bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
		bfa_q_deq(&rxf->ucast_pending_add_q, &mac);
		bfa_q_qe_init(&mac->qe);
		bfa_q_qe_init(&mac->qe);
		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
		bna_cam_mod_mac_put(bna_ucam_mod_free_q(rxf->rx->bna), mac);
	}
	}


	if (rxf->ucast_pending_mac) {
	if (rxf->ucast_pending_mac) {
		bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
		bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod,
		bna_cam_mod_mac_put(bna_ucam_mod_free_q(rxf->rx->bna),
				    rxf->ucast_pending_mac);
				    rxf->ucast_pending_mac);
		rxf->ucast_pending_mac = NULL;
		rxf->ucast_pending_mac = NULL;
	}
	}
@@ -809,7 +809,7 @@ bna_rxf_uninit(struct bna_rxf *rxf)
	while (!list_empty(&rxf->mcast_pending_add_q)) {
	while (!list_empty(&rxf->mcast_pending_add_q)) {
		bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
		bfa_q_deq(&rxf->mcast_pending_add_q, &mac);
		bfa_q_qe_init(&mac->qe);
		bfa_q_qe_init(&mac->qe);
		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
		bna_cam_mod_mac_put(bna_mcam_mod_free_q(rxf->rx->bna), mac);
	}
	}


	rxf->rxmode_pending = 0;
	rxf->rxmode_pending = 0;
@@ -869,7 +869,7 @@ bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac,


	if (rxf->ucast_pending_mac == NULL) {
	if (rxf->ucast_pending_mac == NULL) {
		rxf->ucast_pending_mac =
		rxf->ucast_pending_mac =
				bna_ucam_mod_mac_get(&rxf->rx->bna->ucam_mod);
			bna_cam_mod_mac_get(bna_ucam_mod_free_q(rxf->rx->bna));
		if (rxf->ucast_pending_mac == NULL)
		if (rxf->ucast_pending_mac == NULL)
			return BNA_CB_UCAST_CAM_FULL;
			return BNA_CB_UCAST_CAM_FULL;
		bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
		bfa_q_qe_init(&rxf->ucast_pending_mac->qe);
@@ -900,7 +900,7 @@ bna_rx_mcast_add(struct bna_rx *rx, u8 *addr,
		return BNA_CB_SUCCESS;
		return BNA_CB_SUCCESS;
	}
	}


	mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
	mac = bna_cam_mod_mac_get(bna_mcam_mod_free_q(rxf->rx->bna));
	if (mac == NULL)
	if (mac == NULL)
		return BNA_CB_MCAST_LIST_FULL;
		return BNA_CB_MCAST_LIST_FULL;
	bfa_q_qe_init(&mac->qe);
	bfa_q_qe_init(&mac->qe);
@@ -919,32 +919,20 @@ enum bna_cb_status
bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
		     void (*cbfn)(struct bnad *, struct bna_rx *))
		     void (*cbfn)(struct bnad *, struct bna_rx *))
{
{
	struct bna_mcam_mod *mcam_mod = &rx->bna->mcam_mod;
	struct bna_rxf *rxf = &rx->rxf;
	struct bna_rxf *rxf = &rx->rxf;
	struct list_head list_head;
	struct list_head list_head;
	struct list_head *qe;
	struct list_head *qe;
	u8 *mcaddr;
	u8 *mcaddr;
	struct bna_mac *mac;
	struct bna_mac *mac, *del_mac;
	int i;
	int i;


	/* Allocate nodes */
	INIT_LIST_HEAD(&list_head);
	for (i = 0, mcaddr = mclist; i < count; i++) {
		mac = bna_mcam_mod_mac_get(&rxf->rx->bna->mcam_mod);
		if (mac == NULL)
			goto err_return;
		bfa_q_qe_init(&mac->qe);
		memcpy(mac->addr, mcaddr, ETH_ALEN);
		list_add_tail(&mac->qe, &list_head);

		mcaddr += ETH_ALEN;
	}

	/* Purge the pending_add_q */
	/* Purge the pending_add_q */
	while (!list_empty(&rxf->mcast_pending_add_q)) {
	while (!list_empty(&rxf->mcast_pending_add_q)) {
		bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
		bfa_q_deq(&rxf->mcast_pending_add_q, &qe);
		bfa_q_qe_init(qe);
		bfa_q_qe_init(qe);
		mac = (struct bna_mac *)qe;
		mac = (struct bna_mac *)qe;
		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
		bna_cam_mod_mac_put(&mcam_mod->free_q, mac);
	}
	}


	/* Schedule active_q entries for deletion */
	/* Schedule active_q entries for deletion */
@@ -952,7 +940,26 @@ bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
		bfa_q_deq(&rxf->mcast_active_q, &qe);
		bfa_q_deq(&rxf->mcast_active_q, &qe);
		mac = (struct bna_mac *)qe;
		mac = (struct bna_mac *)qe;
		bfa_q_qe_init(&mac->qe);
		bfa_q_qe_init(&mac->qe);
		list_add_tail(&mac->qe, &rxf->mcast_pending_del_q);

		del_mac = bna_cam_mod_mac_get(&mcam_mod->del_q);

		memcpy(del_mac, mac, sizeof(*mac));
		list_add_tail(&del_mac->qe, &rxf->mcast_pending_del_q);
		mac->handle = NULL;
		bna_cam_mod_mac_put(&mcam_mod->free_q, mac);
	}

	/* Allocate nodes */
	INIT_LIST_HEAD(&list_head);
	for (i = 0, mcaddr = mclist; i < count; i++) {
		mac = bna_cam_mod_mac_get(&mcam_mod->free_q);
		if (mac == NULL)
			goto err_return;
		bfa_q_qe_init(&mac->qe);
		memcpy(mac->addr, mcaddr, ETH_ALEN);
		list_add_tail(&mac->qe, &list_head);

		mcaddr += ETH_ALEN;
	}
	}


	/* Add the new entries */
	/* Add the new entries */
@@ -974,7 +981,7 @@ bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mclist,
		bfa_q_deq(&list_head, &qe);
		bfa_q_deq(&list_head, &qe);
		mac = (struct bna_mac *)qe;
		mac = (struct bna_mac *)qe;
		bfa_q_qe_init(&mac->qe);
		bfa_q_qe_init(&mac->qe);
		bna_mcam_mod_mac_put(&rxf->rx->bna->mcam_mod, mac);
		bna_cam_mod_mac_put(&mcam_mod->free_q, mac);
	}
	}


	return BNA_CB_MCAST_LIST_FULL;
	return BNA_CB_MCAST_LIST_FULL;
@@ -1022,7 +1029,7 @@ bna_rxf_ucast_cfg_apply(struct bna_rxf *rxf)
		bfa_q_qe_init(qe);
		bfa_q_qe_init(qe);
		mac = (struct bna_mac *)qe;
		mac = (struct bna_mac *)qe;
		bna_bfi_ucast_req(rxf, mac, BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
		bna_bfi_ucast_req(rxf, mac, BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
		bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
		bna_cam_mod_mac_put(bna_ucam_mod_del_q(rxf->rx->bna), mac);
		return 1;
		return 1;
	}
	}


@@ -1062,11 +1069,13 @@ bna_rxf_ucast_cfg_reset(struct bna_rxf *rxf, enum bna_cleanup_type cleanup)
		bfa_q_qe_init(qe);
		bfa_q_qe_init(qe);
		mac = (struct bna_mac *)qe;
		mac = (struct bna_mac *)qe;
		if (cleanup == BNA_SOFT_CLEANUP)
		if (cleanup == BNA_SOFT_CLEANUP)
			bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
			bna_cam_mod_mac_put(bna_ucam_mod_del_q(rxf->rx->bna),
					    mac);
		else {
		else {
			bna_bfi_ucast_req(rxf, mac,
			bna_bfi_ucast_req(rxf, mac,
				BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
				BFI_ENET_H2I_MAC_UCAST_DEL_REQ);
			bna_ucam_mod_mac_put(&rxf->rx->bna->ucam_mod, mac);
			bna_cam_mod_mac_put(bna_ucam_mod_del_q(rxf->rx->bna),
					    mac);
			return 1;
			return 1;
		}
		}
	}
	}
+5 −3
Original line number Original line Diff line number Diff line
@@ -866,8 +866,9 @@ struct bna_rx_mod {
/* CAM */
/* CAM */


struct bna_ucam_mod {
struct bna_ucam_mod {
	struct bna_mac *ucmac;		/* BFI_MAX_UCMAC entries */
	struct bna_mac *ucmac;		/* num_ucmac * 2 entries */
	struct list_head			free_q;
	struct list_head			free_q;
	struct list_head			del_q;


	struct bna *bna;
	struct bna *bna;
};
};
@@ -880,9 +881,10 @@ struct bna_mcam_handle {
};
};


struct bna_mcam_mod {
struct bna_mcam_mod {
	struct bna_mac *mcmac;		/* BFI_MAX_MCMAC entries */
	struct bna_mac *mcmac;		/* num_mcmac * 2 entries */
	struct bna_mcam_handle *mchandle;	/* BFI_MAX_MCMAC entries */
	struct bna_mcam_handle *mchandle;	/* num_mcmac entries */
	struct list_head			free_q;
	struct list_head			free_q;
	struct list_head			del_q;
	struct list_head			free_handle_q;
	struct list_head			free_handle_q;


	struct bna *bna;
	struct bna *bna;