aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorVipul Pandya <vipul@chelsio.com>2012-12-10 04:30:53 -0500
committerRoland Dreier <roland@purestorage.com>2012-12-19 12:28:19 -0500
commitdca4faeb812f665dab0607d8e0660ae564387186 (patch)
tree5fd3def8d745eb588f7dc2f65833bc711371ea6f /drivers/net
parentf2b7e78dbc79e09fc1164b226adc03ed91a326cb (diff)
cxgb4: Add LE hash collision bug fix path in LLD driver
It supports establishing passive open connection through firmware filter work request. Passive open connection will go through this path as now instead of listening server we create a server filter which will redirect the incoming SYN packet to the offload queue. It divides filter region into regular filters and server filter portion. It introduces new server filter region which will be exclusively used for creating server filters. This region will not overlap with regular filter region. It provides new API cxgb4_alloc_sftid in LLD for getting stid in case of LE hash collision path. This new stid will be used to open server filter in the filter region. Signed-off-by: Vipul Pandya <vipul@chelsio.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c151
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h15
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_regs.h33
4 files changed, 193 insertions, 10 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 24ce797ddbbd..46ddd432cdf2 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -35,6 +35,8 @@
35#ifndef __CXGB4_H__ 35#ifndef __CXGB4_H__
36#define __CXGB4_H__ 36#define __CXGB4_H__
37 37
38#include "t4_hw.h"
39
38#include <linux/bitops.h> 40#include <linux/bitops.h>
39#include <linux/cache.h> 41#include <linux/cache.h>
40#include <linux/interrupt.h> 42#include <linux/interrupt.h>
@@ -212,6 +214,8 @@ struct tp_err_stats {
212struct tp_params { 214struct tp_params {
213 unsigned int ntxchan; /* # of Tx channels */ 215 unsigned int ntxchan; /* # of Tx channels */
214 unsigned int tre; /* log2 of core clocks per TP tick */ 216 unsigned int tre; /* log2 of core clocks per TP tick */
217 unsigned short tx_modq_map; /* TX modulation scheduler queue to */
218 /* channel map */
215 219
216 uint32_t dack_re; /* DACK timer resolution */ 220 uint32_t dack_re; /* DACK timer resolution */
217 unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */ 221 unsigned short tx_modq[NCHAN]; /* channel to modulation queue map */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 41537a403eef..888bc7fc7a38 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2481,8 +2481,34 @@ int cxgb4_alloc_stid(struct tid_info *t, int family, void *data)
2481} 2481}
2482EXPORT_SYMBOL(cxgb4_alloc_stid); 2482EXPORT_SYMBOL(cxgb4_alloc_stid);
2483 2483
2484/* 2484/* Allocate a server filter TID and set it to the supplied value.
2485 * Release a server TID. 2485 */
2486int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data)
2487{
2488 int stid;
2489
2490 spin_lock_bh(&t->stid_lock);
2491 if (family == PF_INET) {
2492 stid = find_next_zero_bit(t->stid_bmap,
2493 t->nstids + t->nsftids, t->nstids);
2494 if (stid < (t->nstids + t->nsftids))
2495 __set_bit(stid, t->stid_bmap);
2496 else
2497 stid = -1;
2498 } else {
2499 stid = -1;
2500 }
2501 if (stid >= 0) {
2502 t->stid_tab[stid].data = data;
2503 stid += t->stid_base;
2504 t->stids_in_use++;
2505 }
2506 spin_unlock_bh(&t->stid_lock);
2507 return stid;
2508}
2509EXPORT_SYMBOL(cxgb4_alloc_sftid);
2510
2511/* Release a server TID.
2486 */ 2512 */
2487void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family) 2513void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family)
2488{ 2514{
@@ -2597,12 +2623,14 @@ static int tid_init(struct tid_info *t)
2597 unsigned int stid_bmap_size; 2623 unsigned int stid_bmap_size;
2598 unsigned int natids = t->natids; 2624 unsigned int natids = t->natids;
2599 2625
2600 stid_bmap_size = BITS_TO_LONGS(t->nstids); 2626 stid_bmap_size = BITS_TO_LONGS(t->nstids + t->nsftids);
2601 size = t->ntids * sizeof(*t->tid_tab) + 2627 size = t->ntids * sizeof(*t->tid_tab) +
2602 natids * sizeof(*t->atid_tab) + 2628 natids * sizeof(*t->atid_tab) +
2603 t->nstids * sizeof(*t->stid_tab) + 2629 t->nstids * sizeof(*t->stid_tab) +
2630 t->nsftids * sizeof(*t->stid_tab) +
2604 stid_bmap_size * sizeof(long) + 2631 stid_bmap_size * sizeof(long) +
2605 t->nftids * sizeof(*t->ftid_tab); 2632 t->nftids * sizeof(*t->ftid_tab) +
2633 t->nsftids * sizeof(*t->ftid_tab);
2606 2634
2607 t->tid_tab = t4_alloc_mem(size); 2635 t->tid_tab = t4_alloc_mem(size);
2608 if (!t->tid_tab) 2636 if (!t->tid_tab)
@@ -2610,7 +2638,7 @@ static int tid_init(struct tid_info *t)
2610 2638
2611 t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids]; 2639 t->atid_tab = (union aopen_entry *)&t->tid_tab[t->ntids];
2612 t->stid_tab = (struct serv_entry *)&t->atid_tab[natids]; 2640 t->stid_tab = (struct serv_entry *)&t->atid_tab[natids];
2613 t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids]; 2641 t->stid_bmap = (unsigned long *)&t->stid_tab[t->nstids + t->nsftids];
2614 t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size]; 2642 t->ftid_tab = (struct filter_entry *)&t->stid_bmap[stid_bmap_size];
2615 spin_lock_init(&t->stid_lock); 2643 spin_lock_init(&t->stid_lock);
2616 spin_lock_init(&t->atid_lock); 2644 spin_lock_init(&t->atid_lock);
@@ -2626,7 +2654,7 @@ static int tid_init(struct tid_info *t)
2626 t->atid_tab[natids - 1].next = &t->atid_tab[natids]; 2654 t->atid_tab[natids - 1].next = &t->atid_tab[natids];
2627 t->afree = t->atid_tab; 2655 t->afree = t->atid_tab;
2628 } 2656 }
2629 bitmap_zero(t->stid_bmap, t->nstids); 2657 bitmap_zero(t->stid_bmap, t->nstids + t->nsftids);
2630 return 0; 2658 return 0;
2631} 2659}
2632 2660
@@ -2988,6 +3016,7 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
2988{ 3016{
2989 void *handle; 3017 void *handle;
2990 struct cxgb4_lld_info lli; 3018 struct cxgb4_lld_info lli;
3019 unsigned short i;
2991 3020
2992 lli.pdev = adap->pdev; 3021 lli.pdev = adap->pdev;
2993 lli.l2t = adap->l2t; 3022 lli.l2t = adap->l2t;
@@ -3014,10 +3043,16 @@ static void uld_attach(struct adapter *adap, unsigned int uld)
3014 lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET( 3043 lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
3015 t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >> 3044 t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
3016 (adap->fn * 4)); 3045 (adap->fn * 4));
3046 lli.filt_mode = tp_vlan_pri_map;
3047 /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
3048 for (i = 0; i < NCHAN; i++)
3049 lli.tx_modq[i] = i;
3017 lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS); 3050 lli.gts_reg = adap->regs + MYPF_REG(SGE_PF_GTS);
3018 lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL); 3051 lli.db_reg = adap->regs + MYPF_REG(SGE_PF_KDOORBELL);
3019 lli.fw_vers = adap->params.fw_vers; 3052 lli.fw_vers = adap->params.fw_vers;
3020 lli.dbfifo_int_thresh = dbfifo_int_thresh; 3053 lli.dbfifo_int_thresh = dbfifo_int_thresh;
3054 lli.sge_pktshift = adap->sge.pktshift;
3055 lli.enable_fw_ofld_conn = adap->flags & FW_OFLD_CONN;
3021 3056
3022 handle = ulds[uld].add(&lli); 3057 handle = ulds[uld].add(&lli);
3023 if (IS_ERR(handle)) { 3058 if (IS_ERR(handle)) {
@@ -3258,7 +3293,7 @@ static int delete_filter(struct adapter *adapter, unsigned int fidx)
3258 struct filter_entry *f; 3293 struct filter_entry *f;
3259 int ret; 3294 int ret;
3260 3295
3261 if (fidx >= adapter->tids.nftids) 3296 if (fidx >= adapter->tids.nftids + adapter->tids.nsftids)
3262 return -EINVAL; 3297 return -EINVAL;
3263 3298
3264 f = &adapter->tids.ftid_tab[fidx]; 3299 f = &adapter->tids.ftid_tab[fidx];
@@ -3271,6 +3306,77 @@ static int delete_filter(struct adapter *adapter, unsigned int fidx)
3271 return 0; 3306 return 0;
3272} 3307}
3273 3308
3309int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
3310 __be32 sip, __be16 sport, unsigned int queue)
3311{
3312 int ret;
3313 struct filter_entry *f;
3314 struct adapter *adap;
3315 int i;
3316 u8 *val;
3317
3318 adap = netdev2adap(dev);
3319
3320 /* Check to make sure the filter requested is writable ...
3321 */
3322 f = &adap->tids.ftid_tab[stid];
3323 ret = writable_filter(f);
3324 if (ret)
3325 return ret;
3326
3327 /* Clear out any old resources being used by the filter before
3328 * we start constructing the new filter.
3329 */
3330 if (f->valid)
3331 clear_filter(adap, f);
3332
3333 /* Clear out filter specifications */
3334 memset(&f->fs, 0, sizeof(struct ch_filter_specification));
3335 f->fs.val.lport = cpu_to_be16(sport);
3336 f->fs.mask.lport = ~0;
3337 val = (u8 *)&sip;
3338 if ((val[0] | val[1] | val[2] | val[3]) != 0)
3339 for (i = 0; i < 4; i++) {
3340 f->fs.val.lip[i] = val[i];
3341 f->fs.mask.lip[i] = ~0;
3342 }
3343
3344 f->fs.dirsteer = 1;
3345 f->fs.iq = queue;
3346 /* Mark filter as locked */
3347 f->locked = 1;
3348 f->fs.rpttid = 1;
3349
3350 ret = set_filter_wr(adap, stid);
3351 if (ret) {
3352 clear_filter(adap, f);
3353 return ret;
3354 }
3355
3356 return 0;
3357}
3358EXPORT_SYMBOL(cxgb4_create_server_filter);
3359
3360int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
3361 unsigned int queue, bool ipv6)
3362{
3363 int ret;
3364 struct filter_entry *f;
3365 struct adapter *adap;
3366
3367 adap = netdev2adap(dev);
3368 f = &adap->tids.ftid_tab[stid];
3369 /* Unlock the filter */
3370 f->locked = 0;
3371
3372 ret = delete_filter(adap, stid);
3373 if (ret)
3374 return ret;
3375
3376 return 0;
3377}
3378EXPORT_SYMBOL(cxgb4_remove_server_filter);
3379
3274static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev, 3380static struct rtnl_link_stats64 *cxgb_get_stats(struct net_device *dev,
3275 struct rtnl_link_stats64 *ns) 3381 struct rtnl_link_stats64 *ns)
3276{ 3382{
@@ -3517,6 +3623,34 @@ static int adap_init1(struct adapter *adap, struct fw_caps_config_cmd *c)
3517 v = t4_read_reg(adap, TP_PIO_DATA); 3623 v = t4_read_reg(adap, TP_PIO_DATA);
3518 t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR); 3624 t4_write_reg(adap, TP_PIO_DATA, v & ~CSUM_HAS_PSEUDO_HDR);
3519 3625
3626 /* first 4 Tx modulation queues point to consecutive Tx channels */
3627 adap->params.tp.tx_modq_map = 0xE4;
3628 t4_write_reg(adap, A_TP_TX_MOD_QUEUE_REQ_MAP,
3629 V_TX_MOD_QUEUE_REQ_MAP(adap->params.tp.tx_modq_map));
3630
3631 /* associate each Tx modulation queue with consecutive Tx channels */
3632 v = 0x84218421;
3633 t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
3634 &v, 1, A_TP_TX_SCHED_HDR);
3635 t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
3636 &v, 1, A_TP_TX_SCHED_FIFO);
3637 t4_write_indirect(adap, TP_PIO_ADDR, TP_PIO_DATA,
3638 &v, 1, A_TP_TX_SCHED_PCMD);
3639
3640#define T4_TX_MODQ_10G_WEIGHT_DEFAULT 16 /* in KB units */
3641 if (is_offload(adap)) {
3642 t4_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0,
3643 V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
3644 V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
3645 V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
3646 V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT));
3647 t4_write_reg(adap, A_TP_TX_MOD_CHANNEL_WEIGHT,
3648 V_TX_MODQ_WEIGHT0(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
3649 V_TX_MODQ_WEIGHT1(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
3650 V_TX_MODQ_WEIGHT2(T4_TX_MODQ_10G_WEIGHT_DEFAULT) |
3651 V_TX_MODQ_WEIGHT3(T4_TX_MODQ_10G_WEIGHT_DEFAULT));
3652 }
3653
3520 /* get basic stuff going */ 3654 /* get basic stuff going */
3521 return t4_early_init(adap, adap->fn); 3655 return t4_early_init(adap, adap->fn);
3522} 3656}
@@ -4938,7 +5072,8 @@ static void remove_one(struct pci_dev *pdev)
4938 */ 5072 */
4939 if (adapter->tids.ftid_tab) { 5073 if (adapter->tids.ftid_tab) {
4940 struct filter_entry *f = &adapter->tids.ftid_tab[0]; 5074 struct filter_entry *f = &adapter->tids.ftid_tab[0];
4941 for (i = 0; i < adapter->tids.nftids; i++, f++) 5075 for (i = 0; i < (adapter->tids.nftids +
5076 adapter->tids.nsftids); i++, f++)
4942 if (f->valid) 5077 if (f->valid)
4943 clear_filter(adapter, f); 5078 clear_filter(adapter, f);
4944 } 5079 }
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index 59a61332b78c..065bbd5b2411 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -131,7 +131,7 @@ static inline void *lookup_atid(const struct tid_info *t, unsigned int atid)
131static inline void *lookup_stid(const struct tid_info *t, unsigned int stid) 131static inline void *lookup_stid(const struct tid_info *t, unsigned int stid)
132{ 132{
133 stid -= t->stid_base; 133 stid -= t->stid_base;
134 return stid < t->nstids ? t->stid_tab[stid].data : NULL; 134 return stid < (t->nstids + t->nsftids) ? t->stid_tab[stid].data : NULL;
135} 135}
136 136
137static inline void cxgb4_insert_tid(struct tid_info *t, void *data, 137static inline void cxgb4_insert_tid(struct tid_info *t, void *data,
@@ -143,6 +143,7 @@ static inline void cxgb4_insert_tid(struct tid_info *t, void *data,
143 143
144int cxgb4_alloc_atid(struct tid_info *t, void *data); 144int cxgb4_alloc_atid(struct tid_info *t, void *data);
145int cxgb4_alloc_stid(struct tid_info *t, int family, void *data); 145int cxgb4_alloc_stid(struct tid_info *t, int family, void *data);
146int cxgb4_alloc_sftid(struct tid_info *t, int family, void *data);
146void cxgb4_free_atid(struct tid_info *t, unsigned int atid); 147void cxgb4_free_atid(struct tid_info *t, unsigned int atid);
147void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family); 148void cxgb4_free_stid(struct tid_info *t, unsigned int stid, int family);
148void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid); 149void cxgb4_remove_tid(struct tid_info *t, unsigned int qid, unsigned int tid);
@@ -151,7 +152,10 @@ struct in6_addr;
151 152
152int cxgb4_create_server(const struct net_device *dev, unsigned int stid, 153int cxgb4_create_server(const struct net_device *dev, unsigned int stid,
153 __be32 sip, __be16 sport, unsigned int queue); 154 __be32 sip, __be16 sport, unsigned int queue);
154 155int cxgb4_create_server_filter(const struct net_device *dev, unsigned int stid,
156 __be32 sip, __be16 sport, unsigned int queue);
157int cxgb4_remove_server_filter(const struct net_device *dev, unsigned int stid,
158 unsigned int queue, bool ipv6);
155static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue) 159static inline void set_wr_txq(struct sk_buff *skb, int prio, int queue)
156{ 160{
157 skb_set_queue_mapping(skb, (queue << 1) | prio); 161 skb_set_queue_mapping(skb, (queue << 1) | prio);
@@ -223,9 +227,16 @@ struct cxgb4_lld_info {
223 unsigned int iscsi_iolen; /* iSCSI max I/O length */ 227 unsigned int iscsi_iolen; /* iSCSI max I/O length */
224 unsigned short udb_density; /* # of user DB/page */ 228 unsigned short udb_density; /* # of user DB/page */
225 unsigned short ucq_density; /* # of user CQs/page */ 229 unsigned short ucq_density; /* # of user CQs/page */
230 unsigned short filt_mode; /* filter optional components */
231 unsigned short tx_modq[NCHAN]; /* maps each tx channel to a */
232 /* scheduler queue */
226 void __iomem *gts_reg; /* address of GTS register */ 233 void __iomem *gts_reg; /* address of GTS register */
227 void __iomem *db_reg; /* address of kernel doorbell */ 234 void __iomem *db_reg; /* address of kernel doorbell */
228 int dbfifo_int_thresh; /* doorbell fifo int threshold */ 235 int dbfifo_int_thresh; /* doorbell fifo int threshold */
236 unsigned int sge_pktshift; /* Padding between CPL and */
237 /* packet data */
238 bool enable_fw_ofld_conn; /* Enable connection through fw */
239 /* WR */
229}; 240};
230 241
231struct cxgb4_uld_info { 242struct cxgb4_uld_info {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
index 75393f5cff41..aef529198922 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
@@ -1064,4 +1064,37 @@
1064#define ADDRESS(x) ((x) << ADDRESS_SHIFT) 1064#define ADDRESS(x) ((x) << ADDRESS_SHIFT)
1065 1065
1066#define XGMAC_PORT_INT_CAUSE 0x10dc 1066#define XGMAC_PORT_INT_CAUSE 0x10dc
1067
1068#define A_TP_TX_MOD_QUEUE_REQ_MAP 0x7e28
1069
1070#define A_TP_TX_MOD_CHANNEL_WEIGHT 0x7e34
1071
1072#define S_TX_MOD_QUEUE_REQ_MAP 0
1073#define M_TX_MOD_QUEUE_REQ_MAP 0xffffU
1074#define V_TX_MOD_QUEUE_REQ_MAP(x) ((x) << S_TX_MOD_QUEUE_REQ_MAP)
1075
1076#define A_TP_TX_MOD_QUEUE_WEIGHT0 0x7e30
1077
1078#define S_TX_MODQ_WEIGHT3 24
1079#define M_TX_MODQ_WEIGHT3 0xffU
1080#define V_TX_MODQ_WEIGHT3(x) ((x) << S_TX_MODQ_WEIGHT3)
1081
1082#define S_TX_MODQ_WEIGHT2 16
1083#define M_TX_MODQ_WEIGHT2 0xffU
1084#define V_TX_MODQ_WEIGHT2(x) ((x) << S_TX_MODQ_WEIGHT2)
1085
1086#define S_TX_MODQ_WEIGHT1 8
1087#define M_TX_MODQ_WEIGHT1 0xffU
1088#define V_TX_MODQ_WEIGHT1(x) ((x) << S_TX_MODQ_WEIGHT1)
1089
1090#define S_TX_MODQ_WEIGHT0 0
1091#define M_TX_MODQ_WEIGHT0 0xffU
1092#define V_TX_MODQ_WEIGHT0(x) ((x) << S_TX_MODQ_WEIGHT0)
1093
1094#define A_TP_TX_SCHED_HDR 0x23
1095
1096#define A_TP_TX_SCHED_FIFO 0x24
1097
1098#define A_TP_TX_SCHED_PCMD 0x25
1099
1067#endif /* __T4_REGS_H */ 1100#endif /* __T4_REGS_H */