Commit 578b46b9 authored by Rahul Lakkireddy's avatar Rahul Lakkireddy Committed by David S. Miller

cxgb4: add common api support for configuring filters

Enable filters for non-offload configuration and add common api support
for setting and deleting filters in LE-TCAM region of the hardware.

IPv4 filters occupy one slot.  IPv6 filters occupy 4 slots and must
be on a 4-slot boundary.  IPv4 filters can not occupy a slot belonging
to IPv6 and the vice-versa is also true.

Filters are set and deleted asynchronously.  Use completion to wait
for reply from firmware in order to allow for synchronization if needed.
Signed-off-by: default avatarRahul Lakkireddy <rahul.lakkireddy@chelsio.com>
Signed-off-by: default avatarHariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d57fd6ca
...@@ -1038,7 +1038,10 @@ struct filter_entry { ...@@ -1038,7 +1038,10 @@ struct filter_entry {
u32 pending:1; /* filter action is pending firmware reply */ u32 pending:1; /* filter action is pending firmware reply */
u32 smtidx:8; /* Source MAC Table index for smac */ u32 smtidx:8; /* Source MAC Table index for smac */
struct filter_ctx *ctx; /* Caller's completion hook */
struct l2t_entry *l2t; /* Layer Two Table entry for dmac */ struct l2t_entry *l2t; /* Layer Two Table entry for dmac */
struct net_device *dev; /* Associated net device */
u32 tid; /* This will store the actual tid */
/* The filter itself. Most of this is a straight copy of information /* The filter itself. Most of this is a straight copy of information
* provided by the extended ioctl(). Some fields are translated to * provided by the extended ioctl(). Some fields are translated to
......
...@@ -44,4 +44,5 @@ int set_filter_wr(struct adapter *adapter, int fidx); ...@@ -44,4 +44,5 @@ int set_filter_wr(struct adapter *adapter, int fidx);
int delete_filter(struct adapter *adapter, unsigned int fidx); int delete_filter(struct adapter *adapter, unsigned int fidx);
int writable_filter(struct filter_entry *f); int writable_filter(struct filter_entry *f);
void clear_all_filters(struct adapter *adapter);
#endif /* __CXGB4_FILTER_H */ #endif /* __CXGB4_FILTER_H */
...@@ -1324,19 +1324,22 @@ EXPORT_SYMBOL(cxgb4_remove_tid); ...@@ -1324,19 +1324,22 @@ EXPORT_SYMBOL(cxgb4_remove_tid);
*/ */
static int tid_init(struct tid_info *t) static int tid_init(struct tid_info *t)
{ {
size_t size;
unsigned int stid_bmap_size;
unsigned int natids = t->natids;
struct adapter *adap = container_of(t, struct adapter, tids); struct adapter *adap = container_of(t, struct adapter, tids);
unsigned int max_ftids = t->nftids + t->nsftids;
unsigned int natids = t->natids;
unsigned int stid_bmap_size;
unsigned int ftid_bmap_size;
size_t size;
stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids); stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
ftid_bmap_size = BITS_TO_LONGS(t->nftids);
size = t->ntids * sizeof(*t->tid_tab) + size = t->ntids * sizeof(*t->tid_tab) +
natids * sizeof(*t->atid_tab) + natids * sizeof(*t->atid_tab) +
t->nstids * sizeof(*t->stid_tab) + t->nstids * sizeof(*t->stid_tab) +
t->nsftids * sizeof(*t->stid_tab) + t->nsftids * sizeof(*t->stid_tab) +
stid_bmap_size * sizeof(long) + stid_bmap_size * sizeof(long) +
t->nftids * sizeof(*t->ftid_tab) + max_ftids * sizeof(*t->ftid_tab) +
t->nsftids * sizeof(*t->ftid_tab); ftid_bmap_size * sizeof(long);
t->tid_tab = t4_alloc_mem(size); t->tid_tab = t4_alloc_mem(size);
if (!t->tid_tab) if (!t->tid_tab)
...@@ -1346,8 +1349,10 @@ static int tid_init(struct tid_info *t) ...@@ -1346,8 +1349,10 @@ static int tid_init(struct tid_info *t)
t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; t->stid_tab = (struct serv_entry *)&t->atid_tab[natids];
t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids]; t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids];
t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size]; t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size];
t->ftid_bmap = (unsigned long *)&t->ftid_tab[max_ftids];
spin_lock_init(&t->stid_lock); spin_lock_init(&t->stid_lock);
spin_lock_init(&t->atid_lock); spin_lock_init(&t->atid_lock);
spin_lock_init(&t->ftid_lock);
t->stids_in_use = 0; t->stids_in_use = 0;
t->sftids_in_use = 0; t->sftids_in_use = 0;
...@@ -1362,12 +1367,16 @@ static int tid_init(struct tid_info *t) ...@@ -1362,12 +1367,16 @@ static int tid_init(struct tid_info *t)
t->atid_tab[natids - 1].next = &t->atid_tab[natids]; t->atid_tab[natids - 1].next = &t->atid_tab[natids];
t->afree = t->atid_tab; t->afree = t->atid_tab;
} }
bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
/* Reserve stid 0 for T4/T5 adapters */
if (!t->stid_base &&
(CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5))
__set_bit(0, t->stid_bmap);
if (is_offload(adap)) {
bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
/* Reserve stid 0 for T4/T5 adapters */
if (!t->stid_base &&
CHELSIO_CHIP_VERSION(adap->params.chip) <= CHELSIO_T5)
__set_bit(0, t->stid_bmap);
}
bitmap_zero(t->ftid_bmap, t->nftids);
return 0; return 0;
} }
...@@ -4825,7 +4834,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -4825,7 +4834,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
i); i);
} }
if (is_offload(adapter) && tid_init(&adapter->tids) < 0) { if (tid_init(&adapter->tids) < 0) {
dev_warn(&pdev->dev, "could not allocate TID table, " dev_warn(&pdev->dev, "could not allocate TID table, "
"continuing\n"); "continuing\n");
adapter->params.offload = 0; adapter->params.offload = 0;
...@@ -5012,13 +5021,7 @@ static void remove_one(struct pci_dev *pdev) ...@@ -5012,13 +5021,7 @@ static void remove_one(struct pci_dev *pdev)
/* If we allocated filters, free up state associated with any /* If we allocated filters, free up state associated with any
* valid filters ... * valid filters ...
*/ */
if (adapter->tids.ftid_tab) { clear_all_filters(adapter);
struct filter_entry *f = &adapter->tids.ftid_tab[0];
for (i = 0; i < (adapter->tids.nftids +
adapter->tids.nsftids); i++, f++)
if (f->valid)
clear_filter(adapter, f);
}
if (adapter->flags & FULL_INIT_DONE) if (adapter->flags & FULL_INIT_DONE)
cxgb_down(adapter); cxgb_down(adapter);
......
/* /*
* This file is part of the Chelsio T4 Ethernet driver for Linux. * This file is part of the Chelsio T4 Ethernet driver for Linux.
* *
* Copyright (c) 2003-2014 Chelsio Communications, Inc. All rights reserved. * Copyright (c) 2003-2016 Chelsio Communications, Inc. All rights reserved.
* *
* This software is available to you under a choice of one of two * This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU * licenses. You may choose to be licensed under the terms of the GNU
...@@ -106,6 +106,7 @@ struct tid_info { ...@@ -106,6 +106,7 @@ struct tid_info {
unsigned int atid_base; unsigned int atid_base;
struct filter_entry *ftid_tab; struct filter_entry *ftid_tab;
unsigned long *ftid_bmap;
unsigned int nftids; unsigned int nftids;
unsigned int ftid_base; unsigned int ftid_base;
unsigned int aftid_base; unsigned int aftid_base;
...@@ -126,6 +127,8 @@ struct tid_info { ...@@ -126,6 +127,8 @@ struct tid_info {
atomic_t tids_in_use; atomic_t tids_in_use;
/* TIDs in the HASH */ /* TIDs in the HASH */
atomic_t hash_tids_in_use; atomic_t hash_tids_in_use;
/* lock for setting/clearing filter bitmap */
spinlock_t ftid_lock;
}; };
static inline void *lookup_tid(const struct tid_info *t, unsigned int tid) static inline void *lookup_tid(const struct tid_info *t, unsigned int tid)
...@@ -185,6 +188,27 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid, ...@@ -185,6 +188,27 @@ int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid, int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
unsigned int queue, bool ipv6); unsigned int queue, bool ipv6);
/* Filter operation context to allow callers of cxgb4_set_filter() and
* cxgb4_del_filter() to wait for an asynchronous completion.
*/
struct filter_ctx {
struct completion completion; /* completion rendezvous */
void *closure; /* caller's opaque information */
int result; /* result of operation */
u32 tid; /* to store tid */
};
struct ch_filter_specification;
int __cxgb4_set_filter(struct net_device *dev, int filter_id,
struct ch_filter_specification *fs,
struct filter_ctx *ctx);
int __cxgb4_del_filter(struct net_device *dev, int filter_id,
struct filter_ctx *ctx);
int cxgb4_set_filter(struct net_device *dev, int filter_id,
struct ch_filter_specification *fs);
int cxgb4_del_filter(struct net_device *dev, int filter_id);
static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
{ {
skb_set_queue_mapping(skb, (queue << 1) | prio); skb_set_queue_mapping(skb, (queue << 1) | prio);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment