diff options
Diffstat (limited to 'drivers/net/cxgb3')
-rw-r--r-- | drivers/net/cxgb3/adapter.h | 18 | ||||
-rw-r--r-- | drivers/net/cxgb3/common.h | 1 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_ctl_defs.h | 5 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_ioctl.h | 1 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 19 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_offload.c | 32 | ||||
-rw-r--r-- | drivers/net/cxgb3/l2t.c | 2 | ||||
-rw-r--r-- | drivers/net/cxgb3/regs.h | 10 | ||||
-rw-r--r-- | drivers/net/cxgb3/sge.c | 391 | ||||
-rw-r--r-- | drivers/net/cxgb3/t3_cpl.h | 51 | ||||
-rw-r--r-- | drivers/net/cxgb3/t3cdev.h | 4 |
11 files changed, 469 insertions, 65 deletions
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index acebe431d068..271140433b09 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/cache.h> | 42 | #include <linux/cache.h> |
43 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
44 | #include <linux/bitops.h> | 44 | #include <linux/bitops.h> |
45 | #include <linux/inet_lro.h> | ||
45 | #include "t3cdev.h" | 46 | #include "t3cdev.h" |
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
47 | 48 | ||
@@ -92,6 +93,7 @@ struct sge_fl { /* SGE per free-buffer list state */ | |||
92 | unsigned int gen; /* free list generation */ | 93 | unsigned int gen; /* free list generation */ |
93 | struct fl_pg_chunk pg_chunk;/* page chunk cache */ | 94 | struct fl_pg_chunk pg_chunk;/* page chunk cache */ |
94 | unsigned int use_pages; /* whether FL uses pages or sk_buffs */ | 95 | unsigned int use_pages; /* whether FL uses pages or sk_buffs */ |
96 | unsigned int order; /* order of page allocations */ | ||
95 | struct rx_desc *desc; /* address of HW Rx descriptor ring */ | 97 | struct rx_desc *desc; /* address of HW Rx descriptor ring */ |
96 | struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ | 98 | struct rx_sw_desc *sdesc; /* address of SW Rx descriptor ring */ |
97 | dma_addr_t phys_addr; /* physical address of HW ring start */ | 99 | dma_addr_t phys_addr; /* physical address of HW ring start */ |
@@ -116,12 +118,15 @@ struct sge_rspq { /* state for an SGE response queue */ | |||
116 | unsigned int polling; /* is the queue serviced through NAPI? */ | 118 | unsigned int polling; /* is the queue serviced through NAPI? */ |
117 | unsigned int holdoff_tmr; /* interrupt holdoff timer in 100ns */ | 119 | unsigned int holdoff_tmr; /* interrupt holdoff timer in 100ns */ |
118 | unsigned int next_holdoff; /* holdoff time for next interrupt */ | 120 | unsigned int next_holdoff; /* holdoff time for next interrupt */ |
121 | unsigned int rx_recycle_buf; /* whether recycling occurred | ||
122 | within current sop-eop */ | ||
119 | struct rsp_desc *desc; /* address of HW response ring */ | 123 | struct rsp_desc *desc; /* address of HW response ring */ |
120 | dma_addr_t phys_addr; /* physical address of the ring */ | 124 | dma_addr_t phys_addr; /* physical address of the ring */ |
121 | unsigned int cntxt_id; /* SGE context id for the response q */ | 125 | unsigned int cntxt_id; /* SGE context id for the response q */ |
122 | spinlock_t lock; /* guards response processing */ | 126 | spinlock_t lock; /* guards response processing */ |
123 | struct sk_buff *rx_head; /* offload packet receive queue head */ | 127 | struct sk_buff *rx_head; /* offload packet receive queue head */ |
124 | struct sk_buff *rx_tail; /* offload packet receive queue tail */ | 128 | struct sk_buff *rx_tail; /* offload packet receive queue tail */ |
129 | struct sk_buff *pg_skb; /* used to build frag list in napi handler */ | ||
125 | 130 | ||
126 | unsigned long offload_pkts; | 131 | unsigned long offload_pkts; |
127 | unsigned long offload_bundles; | 132 | unsigned long offload_bundles; |
@@ -169,16 +174,29 @@ enum { /* per port SGE statistics */ | |||
169 | SGE_PSTAT_TX_CSUM, /* # of TX checksum offloads */ | 174 | SGE_PSTAT_TX_CSUM, /* # of TX checksum offloads */ |
170 | SGE_PSTAT_VLANEX, /* # of VLAN tag extractions */ | 175 | SGE_PSTAT_VLANEX, /* # of VLAN tag extractions */ |
171 | SGE_PSTAT_VLANINS, /* # of VLAN tag insertions */ | 176 | SGE_PSTAT_VLANINS, /* # of VLAN tag insertions */ |
177 | SGE_PSTAT_LRO_AGGR, /* # of page chunks added to LRO sessions */ | ||
178 | SGE_PSTAT_LRO_FLUSHED, /* # of flushed LRO sessions */ | ||
179 | SGE_PSTAT_LRO_NO_DESC, /* # of overflown LRO sessions */ | ||
172 | 180 | ||
173 | SGE_PSTAT_MAX /* must be last */ | 181 | SGE_PSTAT_MAX /* must be last */ |
174 | }; | 182 | }; |
175 | 183 | ||
184 | #define T3_MAX_LRO_SES 8 | ||
185 | #define T3_MAX_LRO_MAX_PKTS 64 | ||
186 | |||
176 | struct sge_qset { /* an SGE queue set */ | 187 | struct sge_qset { /* an SGE queue set */ |
177 | struct adapter *adap; | 188 | struct adapter *adap; |
178 | struct napi_struct napi; | 189 | struct napi_struct napi; |
179 | struct sge_rspq rspq; | 190 | struct sge_rspq rspq; |
180 | struct sge_fl fl[SGE_RXQ_PER_SET]; | 191 | struct sge_fl fl[SGE_RXQ_PER_SET]; |
181 | struct sge_txq txq[SGE_TXQ_PER_SET]; | 192 | struct sge_txq txq[SGE_TXQ_PER_SET]; |
193 | struct net_lro_mgr lro_mgr; | ||
194 | struct net_lro_desc lro_desc[T3_MAX_LRO_SES]; | ||
195 | struct skb_frag_struct *lro_frag_tbl; | ||
196 | int lro_nfrags; | ||
197 | int lro_enabled; | ||
198 | int lro_frag_len; | ||
199 | void *lro_va; | ||
182 | struct net_device *netdev; | 200 | struct net_device *netdev; |
183 | unsigned long txq_stopped; /* which Tx queues are stopped */ | 201 | unsigned long txq_stopped; /* which Tx queues are stopped */ |
184 | struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ | 202 | struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ |
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 8e8ebd788537..9ecf8a6dc97f 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h | |||
@@ -351,6 +351,7 @@ struct tp_params { | |||
351 | 351 | ||
352 | struct qset_params { /* SGE queue set parameters */ | 352 | struct qset_params { /* SGE queue set parameters */ |
353 | unsigned int polling; /* polling/interrupt service for rspq */ | 353 | unsigned int polling; /* polling/interrupt service for rspq */ |
354 | unsigned int lro; /* large receive offload */ | ||
354 | unsigned int coalesce_usecs; /* irq coalescing timer */ | 355 | unsigned int coalesce_usecs; /* irq coalescing timer */ |
355 | unsigned int rspq_size; /* # of entries in response queue */ | 356 | unsigned int rspq_size; /* # of entries in response queue */ |
356 | unsigned int fl_size; /* # of entries in regular free list */ | 357 | unsigned int fl_size; /* # of entries in regular free list */ |
diff --git a/drivers/net/cxgb3/cxgb3_ctl_defs.h b/drivers/net/cxgb3/cxgb3_ctl_defs.h index ed0ecd9679cb..6ad92405d9a0 100644 --- a/drivers/net/cxgb3/cxgb3_ctl_defs.h +++ b/drivers/net/cxgb3/cxgb3_ctl_defs.h | |||
@@ -111,10 +111,7 @@ struct ulp_iscsi_info { | |||
111 | unsigned int llimit; | 111 | unsigned int llimit; |
112 | unsigned int ulimit; | 112 | unsigned int ulimit; |
113 | unsigned int tagmask; | 113 | unsigned int tagmask; |
114 | unsigned int pgsz3; | 114 | u8 pgsz_factor[4]; |
115 | unsigned int pgsz2; | ||
116 | unsigned int pgsz1; | ||
117 | unsigned int pgsz0; | ||
118 | unsigned int max_rxsz; | 115 | unsigned int max_rxsz; |
119 | unsigned int max_txsz; | 116 | unsigned int max_txsz; |
120 | struct pci_dev *pdev; | 117 | struct pci_dev *pdev; |
diff --git a/drivers/net/cxgb3/cxgb3_ioctl.h b/drivers/net/cxgb3/cxgb3_ioctl.h index 0a82fcddf2d8..68200a14065e 100644 --- a/drivers/net/cxgb3/cxgb3_ioctl.h +++ b/drivers/net/cxgb3/cxgb3_ioctl.h | |||
@@ -90,6 +90,7 @@ struct ch_qset_params { | |||
90 | int32_t fl_size[2]; | 90 | int32_t fl_size[2]; |
91 | int32_t intr_lat; | 91 | int32_t intr_lat; |
92 | int32_t polling; | 92 | int32_t polling; |
93 | int32_t lro; | ||
93 | int32_t cong_thres; | 94 | int32_t cong_thres; |
94 | }; | 95 | }; |
95 | 96 | ||
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 3a3127216791..5447f3e60f07 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -1212,6 +1212,9 @@ static char stats_strings[][ETH_GSTRING_LEN] = { | |||
1212 | "VLANinsertions ", | 1212 | "VLANinsertions ", |
1213 | "TxCsumOffload ", | 1213 | "TxCsumOffload ", |
1214 | "RxCsumGood ", | 1214 | "RxCsumGood ", |
1215 | "LroAggregated ", | ||
1216 | "LroFlushed ", | ||
1217 | "LroNoDesc ", | ||
1215 | "RxDrops ", | 1218 | "RxDrops ", |
1216 | 1219 | ||
1217 | "CheckTXEnToggled ", | 1220 | "CheckTXEnToggled ", |
@@ -1340,6 +1343,9 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, | |||
1340 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS); | 1343 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_VLANINS); |
1341 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); | 1344 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_TX_CSUM); |
1342 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); | 1345 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_RX_CSUM_GOOD); |
1346 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_AGGR); | ||
1347 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_FLUSHED); | ||
1348 | *data++ = collect_sge_port_stats(adapter, pi, SGE_PSTAT_LRO_NO_DESC); | ||
1343 | *data++ = s->rx_cong_drops; | 1349 | *data++ = s->rx_cong_drops; |
1344 | 1350 | ||
1345 | *data++ = s->num_toggled; | 1351 | *data++ = s->num_toggled; |
@@ -1558,6 +1564,13 @@ static int set_rx_csum(struct net_device *dev, u32 data) | |||
1558 | struct port_info *p = netdev_priv(dev); | 1564 | struct port_info *p = netdev_priv(dev); |
1559 | 1565 | ||
1560 | p->rx_csum_offload = data; | 1566 | p->rx_csum_offload = data; |
1567 | if (!data) { | ||
1568 | struct adapter *adap = p->adapter; | ||
1569 | int i; | ||
1570 | |||
1571 | for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) | ||
1572 | adap->sge.qs[i].lro_enabled = 0; | ||
1573 | } | ||
1561 | return 0; | 1574 | return 0; |
1562 | } | 1575 | } |
1563 | 1576 | ||
@@ -1830,6 +1843,11 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1830 | } | 1843 | } |
1831 | } | 1844 | } |
1832 | } | 1845 | } |
1846 | if (t.lro >= 0) { | ||
1847 | struct sge_qset *qs = &adapter->sge.qs[t.qset_idx]; | ||
1848 | q->lro = t.lro; | ||
1849 | qs->lro_enabled = t.lro; | ||
1850 | } | ||
1833 | break; | 1851 | break; |
1834 | } | 1852 | } |
1835 | case CHELSIO_GET_QSET_PARAMS:{ | 1853 | case CHELSIO_GET_QSET_PARAMS:{ |
@@ -1849,6 +1867,7 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr) | |||
1849 | t.fl_size[0] = q->fl_size; | 1867 | t.fl_size[0] = q->fl_size; |
1850 | t.fl_size[1] = q->jumbo_size; | 1868 | t.fl_size[1] = q->jumbo_size; |
1851 | t.polling = q->polling; | 1869 | t.polling = q->polling; |
1870 | t.lro = q->lro; | ||
1852 | t.intr_lat = q->coalesce_usecs; | 1871 | t.intr_lat = q->coalesce_usecs; |
1853 | t.cong_thres = q->cong_thres; | 1872 | t.cong_thres = q->cong_thres; |
1854 | 1873 | ||
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c index cf2696873796..c5b3de1bb456 100644 --- a/drivers/net/cxgb3/cxgb3_offload.c +++ b/drivers/net/cxgb3/cxgb3_offload.c | |||
@@ -207,6 +207,17 @@ static int cxgb_ulp_iscsi_ctl(struct adapter *adapter, unsigned int req, | |||
207 | break; | 207 | break; |
208 | case ULP_ISCSI_SET_PARAMS: | 208 | case ULP_ISCSI_SET_PARAMS: |
209 | t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask); | 209 | t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask); |
210 | /* set MaxRxData and MaxCoalesceSize to 16224 */ | ||
211 | t3_write_reg(adapter, A_TP_PARA_REG2, 0x3f603f60); | ||
212 | /* program the ddp page sizes */ | ||
213 | { | ||
214 | int i; | ||
215 | unsigned int val = 0; | ||
216 | for (i = 0; i < 4; i++) | ||
217 | val |= (uiip->pgsz_factor[i] & 0xF) << (8 * i); | ||
218 | if (val) | ||
219 | t3_write_reg(adapter, A_ULPRX_ISCSI_PSZ, val); | ||
220 | } | ||
210 | break; | 221 | break; |
211 | default: | 222 | default: |
212 | ret = -EOPNOTSUPP; | 223 | ret = -EOPNOTSUPP; |
@@ -1255,6 +1266,25 @@ static inline void unregister_tdev(struct t3cdev *tdev) | |||
1255 | mutex_unlock(&cxgb3_db_lock); | 1266 | mutex_unlock(&cxgb3_db_lock); |
1256 | } | 1267 | } |
1257 | 1268 | ||
1269 | static inline int adap2type(struct adapter *adapter) | ||
1270 | { | ||
1271 | int type = 0; | ||
1272 | |||
1273 | switch (adapter->params.rev) { | ||
1274 | case T3_REV_A: | ||
1275 | type = T3A; | ||
1276 | break; | ||
1277 | case T3_REV_B: | ||
1278 | case T3_REV_B2: | ||
1279 | type = T3B; | ||
1280 | break; | ||
1281 | case T3_REV_C: | ||
1282 | type = T3C; | ||
1283 | break; | ||
1284 | } | ||
1285 | return type; | ||
1286 | } | ||
1287 | |||
1258 | void __devinit cxgb3_adapter_ofld(struct adapter *adapter) | 1288 | void __devinit cxgb3_adapter_ofld(struct adapter *adapter) |
1259 | { | 1289 | { |
1260 | struct t3cdev *tdev = &adapter->tdev; | 1290 | struct t3cdev *tdev = &adapter->tdev; |
@@ -1264,7 +1294,7 @@ void __devinit cxgb3_adapter_ofld(struct adapter *adapter) | |||
1264 | cxgb3_set_dummy_ops(tdev); | 1294 | cxgb3_set_dummy_ops(tdev); |
1265 | tdev->send = t3_offload_tx; | 1295 | tdev->send = t3_offload_tx; |
1266 | tdev->ctl = cxgb_offload_ctl; | 1296 | tdev->ctl = cxgb_offload_ctl; |
1267 | tdev->type = adapter->params.rev == 0 ? T3A : T3B; | 1297 | tdev->type = adap2type(adapter); |
1268 | 1298 | ||
1269 | register_tdev(tdev); | 1299 | register_tdev(tdev); |
1270 | } | 1300 | } |
diff --git a/drivers/net/cxgb3/l2t.c b/drivers/net/cxgb3/l2t.c index f510140885ae..825e510bd9ed 100644 --- a/drivers/net/cxgb3/l2t.c +++ b/drivers/net/cxgb3/l2t.c | |||
@@ -337,7 +337,7 @@ struct l2t_entry *t3_l2t_get(struct t3cdev *cdev, struct neighbour *neigh, | |||
337 | atomic_set(&e->refcnt, 1); | 337 | atomic_set(&e->refcnt, 1); |
338 | neigh_replace(e, neigh); | 338 | neigh_replace(e, neigh); |
339 | if (neigh->dev->priv_flags & IFF_802_1Q_VLAN) | 339 | if (neigh->dev->priv_flags & IFF_802_1Q_VLAN) |
340 | e->vlan = vlan_dev_info(neigh->dev)->vlan_id; | 340 | e->vlan = vlan_dev_vlan_id(neigh->dev); |
341 | else | 341 | else |
342 | e->vlan = VLAN_NONE; | 342 | e->vlan = VLAN_NONE; |
343 | spin_unlock(&e->lock); | 343 | spin_unlock(&e->lock); |
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index 567178879345..4bda27c551c9 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h | |||
@@ -1517,16 +1517,18 @@ | |||
1517 | 1517 | ||
1518 | #define A_ULPRX_ISCSI_TAGMASK 0x514 | 1518 | #define A_ULPRX_ISCSI_TAGMASK 0x514 |
1519 | 1519 | ||
1520 | #define S_HPZ0 0 | 1520 | #define A_ULPRX_ISCSI_PSZ 0x518 |
1521 | #define M_HPZ0 0xf | ||
1522 | #define V_HPZ0(x) ((x) << S_HPZ0) | ||
1523 | #define G_HPZ0(x) (((x) >> S_HPZ0) & M_HPZ0) | ||
1524 | 1521 | ||
1525 | #define A_ULPRX_TDDP_LLIMIT 0x51c | 1522 | #define A_ULPRX_TDDP_LLIMIT 0x51c |
1526 | 1523 | ||
1527 | #define A_ULPRX_TDDP_ULIMIT 0x520 | 1524 | #define A_ULPRX_TDDP_ULIMIT 0x520 |
1528 | #define A_ULPRX_TDDP_PSZ 0x528 | 1525 | #define A_ULPRX_TDDP_PSZ 0x528 |
1529 | 1526 | ||
1527 | #define S_HPZ0 0 | ||
1528 | #define M_HPZ0 0xf | ||
1529 | #define V_HPZ0(x) ((x) << S_HPZ0) | ||
1530 | #define G_HPZ0(x) (((x) >> S_HPZ0) & M_HPZ0) | ||
1531 | |||
1530 | #define A_ULPRX_STAG_LLIMIT 0x52c | 1532 | #define A_ULPRX_STAG_LLIMIT 0x52c |
1531 | 1533 | ||
1532 | #define A_ULPRX_STAG_ULIMIT 0x530 | 1534 | #define A_ULPRX_STAG_ULIMIT 0x530 |
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 796eb305cdc3..a96331c875e6 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c | |||
@@ -55,6 +55,9 @@ | |||
55 | * directly. | 55 | * directly. |
56 | */ | 56 | */ |
57 | #define FL0_PG_CHUNK_SIZE 2048 | 57 | #define FL0_PG_CHUNK_SIZE 2048 |
58 | #define FL0_PG_ORDER 0 | ||
59 | #define FL1_PG_CHUNK_SIZE (PAGE_SIZE > 8192 ? 16384 : 8192) | ||
60 | #define FL1_PG_ORDER (PAGE_SIZE > 8192 ? 0 : 1) | ||
58 | 61 | ||
59 | #define SGE_RX_DROP_THRES 16 | 62 | #define SGE_RX_DROP_THRES 16 |
60 | 63 | ||
@@ -359,7 +362,7 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) | |||
359 | } | 362 | } |
360 | 363 | ||
361 | if (q->pg_chunk.page) { | 364 | if (q->pg_chunk.page) { |
362 | __free_page(q->pg_chunk.page); | 365 | __free_pages(q->pg_chunk.page, q->order); |
363 | q->pg_chunk.page = NULL; | 366 | q->pg_chunk.page = NULL; |
364 | } | 367 | } |
365 | } | 368 | } |
@@ -376,13 +379,16 @@ static void free_rx_bufs(struct pci_dev *pdev, struct sge_fl *q) | |||
376 | * Add a buffer of the given length to the supplied HW and SW Rx | 379 | * Add a buffer of the given length to the supplied HW and SW Rx |
377 | * descriptors. | 380 | * descriptors. |
378 | */ | 381 | */ |
379 | static inline void add_one_rx_buf(void *va, unsigned int len, | 382 | static inline int add_one_rx_buf(void *va, unsigned int len, |
380 | struct rx_desc *d, struct rx_sw_desc *sd, | 383 | struct rx_desc *d, struct rx_sw_desc *sd, |
381 | unsigned int gen, struct pci_dev *pdev) | 384 | unsigned int gen, struct pci_dev *pdev) |
382 | { | 385 | { |
383 | dma_addr_t mapping; | 386 | dma_addr_t mapping; |
384 | 387 | ||
385 | mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE); | 388 | mapping = pci_map_single(pdev, va, len, PCI_DMA_FROMDEVICE); |
389 | if (unlikely(pci_dma_mapping_error(mapping))) | ||
390 | return -ENOMEM; | ||
391 | |||
386 | pci_unmap_addr_set(sd, dma_addr, mapping); | 392 | pci_unmap_addr_set(sd, dma_addr, mapping); |
387 | 393 | ||
388 | d->addr_lo = cpu_to_be32(mapping); | 394 | d->addr_lo = cpu_to_be32(mapping); |
@@ -390,12 +396,14 @@ static inline void add_one_rx_buf(void *va, unsigned int len, | |||
390 | wmb(); | 396 | wmb(); |
391 | d->len_gen = cpu_to_be32(V_FLD_GEN1(gen)); | 397 | d->len_gen = cpu_to_be32(V_FLD_GEN1(gen)); |
392 | d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); | 398 | d->gen2 = cpu_to_be32(V_FLD_GEN2(gen)); |
399 | return 0; | ||
393 | } | 400 | } |
394 | 401 | ||
395 | static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) | 402 | static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp, |
403 | unsigned int order) | ||
396 | { | 404 | { |
397 | if (!q->pg_chunk.page) { | 405 | if (!q->pg_chunk.page) { |
398 | q->pg_chunk.page = alloc_page(gfp); | 406 | q->pg_chunk.page = alloc_pages(gfp, order); |
399 | if (unlikely(!q->pg_chunk.page)) | 407 | if (unlikely(!q->pg_chunk.page)) |
400 | return -ENOMEM; | 408 | return -ENOMEM; |
401 | q->pg_chunk.va = page_address(q->pg_chunk.page); | 409 | q->pg_chunk.va = page_address(q->pg_chunk.page); |
@@ -404,7 +412,7 @@ static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) | |||
404 | sd->pg_chunk = q->pg_chunk; | 412 | sd->pg_chunk = q->pg_chunk; |
405 | 413 | ||
406 | q->pg_chunk.offset += q->buf_size; | 414 | q->pg_chunk.offset += q->buf_size; |
407 | if (q->pg_chunk.offset == PAGE_SIZE) | 415 | if (q->pg_chunk.offset == (PAGE_SIZE << order)) |
408 | q->pg_chunk.page = NULL; | 416 | q->pg_chunk.page = NULL; |
409 | else { | 417 | else { |
410 | q->pg_chunk.va += q->buf_size; | 418 | q->pg_chunk.va += q->buf_size; |
@@ -424,15 +432,18 @@ static int alloc_pg_chunk(struct sge_fl *q, struct rx_sw_desc *sd, gfp_t gfp) | |||
424 | * allocated with the supplied gfp flags. The caller must assure that | 432 | * allocated with the supplied gfp flags. The caller must assure that |
425 | * @n does not exceed the queue's capacity. | 433 | * @n does not exceed the queue's capacity. |
426 | */ | 434 | */ |
427 | static void refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) | 435 | static int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) |
428 | { | 436 | { |
429 | void *buf_start; | 437 | void *buf_start; |
430 | struct rx_sw_desc *sd = &q->sdesc[q->pidx]; | 438 | struct rx_sw_desc *sd = &q->sdesc[q->pidx]; |
431 | struct rx_desc *d = &q->desc[q->pidx]; | 439 | struct rx_desc *d = &q->desc[q->pidx]; |
440 | unsigned int count = 0; | ||
432 | 441 | ||
433 | while (n--) { | 442 | while (n--) { |
443 | int err; | ||
444 | |||
434 | if (q->use_pages) { | 445 | if (q->use_pages) { |
435 | if (unlikely(alloc_pg_chunk(q, sd, gfp))) { | 446 | if (unlikely(alloc_pg_chunk(q, sd, gfp, q->order))) { |
436 | nomem: q->alloc_failed++; | 447 | nomem: q->alloc_failed++; |
437 | break; | 448 | break; |
438 | } | 449 | } |
@@ -447,8 +458,16 @@ nomem: q->alloc_failed++; | |||
447 | buf_start = skb->data; | 458 | buf_start = skb->data; |
448 | } | 459 | } |
449 | 460 | ||
450 | add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, | 461 | err = add_one_rx_buf(buf_start, q->buf_size, d, sd, q->gen, |
451 | adap->pdev); | 462 | adap->pdev); |
463 | if (unlikely(err)) { | ||
464 | if (!q->use_pages) { | ||
465 | kfree_skb(sd->skb); | ||
466 | sd->skb = NULL; | ||
467 | } | ||
468 | break; | ||
469 | } | ||
470 | |||
452 | d++; | 471 | d++; |
453 | sd++; | 472 | sd++; |
454 | if (++q->pidx == q->size) { | 473 | if (++q->pidx == q->size) { |
@@ -458,14 +477,19 @@ nomem: q->alloc_failed++; | |||
458 | d = q->desc; | 477 | d = q->desc; |
459 | } | 478 | } |
460 | q->credits++; | 479 | q->credits++; |
480 | count++; | ||
461 | } | 481 | } |
462 | wmb(); | 482 | wmb(); |
463 | t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); | 483 | if (likely(count)) |
484 | t3_write_reg(adap, A_SG_KDOORBELL, V_EGRCNTX(q->cntxt_id)); | ||
485 | |||
486 | return count; | ||
464 | } | 487 | } |
465 | 488 | ||
466 | static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl) | 489 | static inline void __refill_fl(struct adapter *adap, struct sge_fl *fl) |
467 | { | 490 | { |
468 | refill_fl(adap, fl, min(16U, fl->size - fl->credits), GFP_ATOMIC); | 491 | refill_fl(adap, fl, min(16U, fl->size - fl->credits), |
492 | GFP_ATOMIC | __GFP_COMP); | ||
469 | } | 493 | } |
470 | 494 | ||
471 | /** | 495 | /** |
@@ -560,6 +584,8 @@ static void t3_reset_qset(struct sge_qset *q) | |||
560 | memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); | 584 | memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); |
561 | q->txq_stopped = 0; | 585 | q->txq_stopped = 0; |
562 | memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); | 586 | memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); |
587 | kfree(q->lro_frag_tbl); | ||
588 | q->lro_nfrags = q->lro_frag_len = 0; | ||
563 | } | 589 | } |
564 | 590 | ||
565 | 591 | ||
@@ -740,19 +766,22 @@ use_orig_buf: | |||
740 | * that are page chunks rather than sk_buffs. | 766 | * that are page chunks rather than sk_buffs. |
741 | */ | 767 | */ |
742 | static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, | 768 | static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, |
743 | unsigned int len, unsigned int drop_thres) | 769 | struct sge_rspq *q, unsigned int len, |
770 | unsigned int drop_thres) | ||
744 | { | 771 | { |
745 | struct sk_buff *skb = NULL; | 772 | struct sk_buff *newskb, *skb; |
746 | struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; | 773 | struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; |
747 | 774 | ||
748 | if (len <= SGE_RX_COPY_THRES) { | 775 | newskb = skb = q->pg_skb; |
749 | skb = alloc_skb(len, GFP_ATOMIC); | 776 | |
750 | if (likely(skb != NULL)) { | 777 | if (!skb && (len <= SGE_RX_COPY_THRES)) { |
751 | __skb_put(skb, len); | 778 | newskb = alloc_skb(len, GFP_ATOMIC); |
779 | if (likely(newskb != NULL)) { | ||
780 | __skb_put(newskb, len); | ||
752 | pci_dma_sync_single_for_cpu(adap->pdev, | 781 | pci_dma_sync_single_for_cpu(adap->pdev, |
753 | pci_unmap_addr(sd, dma_addr), len, | 782 | pci_unmap_addr(sd, dma_addr), len, |
754 | PCI_DMA_FROMDEVICE); | 783 | PCI_DMA_FROMDEVICE); |
755 | memcpy(skb->data, sd->pg_chunk.va, len); | 784 | memcpy(newskb->data, sd->pg_chunk.va, len); |
756 | pci_dma_sync_single_for_device(adap->pdev, | 785 | pci_dma_sync_single_for_device(adap->pdev, |
757 | pci_unmap_addr(sd, dma_addr), len, | 786 | pci_unmap_addr(sd, dma_addr), len, |
758 | PCI_DMA_FROMDEVICE); | 787 | PCI_DMA_FROMDEVICE); |
@@ -761,14 +790,16 @@ static struct sk_buff *get_packet_pg(struct adapter *adap, struct sge_fl *fl, | |||
761 | recycle: | 790 | recycle: |
762 | fl->credits--; | 791 | fl->credits--; |
763 | recycle_rx_buf(adap, fl, fl->cidx); | 792 | recycle_rx_buf(adap, fl, fl->cidx); |
764 | return skb; | 793 | q->rx_recycle_buf++; |
794 | return newskb; | ||
765 | } | 795 | } |
766 | 796 | ||
767 | if (unlikely(fl->credits <= drop_thres)) | 797 | if (unlikely(q->rx_recycle_buf || (!skb && fl->credits <= drop_thres))) |
768 | goto recycle; | 798 | goto recycle; |
769 | 799 | ||
770 | skb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); | 800 | if (!skb) |
771 | if (unlikely(!skb)) { | 801 | newskb = alloc_skb(SGE_RX_PULL_LEN, GFP_ATOMIC); |
802 | if (unlikely(!newskb)) { | ||
772 | if (!drop_thres) | 803 | if (!drop_thres) |
773 | return NULL; | 804 | return NULL; |
774 | goto recycle; | 805 | goto recycle; |
@@ -776,21 +807,29 @@ recycle: | |||
776 | 807 | ||
777 | pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), | 808 | pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), |
778 | fl->buf_size, PCI_DMA_FROMDEVICE); | 809 | fl->buf_size, PCI_DMA_FROMDEVICE); |
779 | __skb_put(skb, SGE_RX_PULL_LEN); | 810 | if (!skb) { |
780 | memcpy(skb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN); | 811 | __skb_put(newskb, SGE_RX_PULL_LEN); |
781 | skb_fill_page_desc(skb, 0, sd->pg_chunk.page, | 812 | memcpy(newskb->data, sd->pg_chunk.va, SGE_RX_PULL_LEN); |
782 | sd->pg_chunk.offset + SGE_RX_PULL_LEN, | 813 | skb_fill_page_desc(newskb, 0, sd->pg_chunk.page, |
783 | len - SGE_RX_PULL_LEN); | 814 | sd->pg_chunk.offset + SGE_RX_PULL_LEN, |
784 | skb->len = len; | 815 | len - SGE_RX_PULL_LEN); |
785 | skb->data_len = len - SGE_RX_PULL_LEN; | 816 | newskb->len = len; |
786 | skb->truesize += skb->data_len; | 817 | newskb->data_len = len - SGE_RX_PULL_LEN; |
818 | } else { | ||
819 | skb_fill_page_desc(newskb, skb_shinfo(newskb)->nr_frags, | ||
820 | sd->pg_chunk.page, | ||
821 | sd->pg_chunk.offset, len); | ||
822 | newskb->len += len; | ||
823 | newskb->data_len += len; | ||
824 | } | ||
825 | newskb->truesize += newskb->data_len; | ||
787 | 826 | ||
788 | fl->credits--; | 827 | fl->credits--; |
789 | /* | 828 | /* |
790 | * We do not refill FLs here, we let the caller do it to overlap a | 829 | * We do not refill FLs here, we let the caller do it to overlap a |
791 | * prefetch. | 830 | * prefetch. |
792 | */ | 831 | */ |
793 | return skb; | 832 | return newskb; |
794 | } | 833 | } |
795 | 834 | ||
796 | /** | 835 | /** |
@@ -1831,9 +1870,10 @@ static void restart_tx(struct sge_qset *qs) | |||
1831 | * if it was immediate data in a response. | 1870 | * if it was immediate data in a response. |
1832 | */ | 1871 | */ |
1833 | static void rx_eth(struct adapter *adap, struct sge_rspq *rq, | 1872 | static void rx_eth(struct adapter *adap, struct sge_rspq *rq, |
1834 | struct sk_buff *skb, int pad) | 1873 | struct sk_buff *skb, int pad, int lro) |
1835 | { | 1874 | { |
1836 | struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad); | 1875 | struct cpl_rx_pkt *p = (struct cpl_rx_pkt *)(skb->data + pad); |
1876 | struct sge_qset *qs = rspq_to_qset(rq); | ||
1837 | struct port_info *pi; | 1877 | struct port_info *pi; |
1838 | 1878 | ||
1839 | skb_pull(skb, sizeof(*p) + pad); | 1879 | skb_pull(skb, sizeof(*p) + pad); |
@@ -1850,18 +1890,202 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq, | |||
1850 | if (unlikely(p->vlan_valid)) { | 1890 | if (unlikely(p->vlan_valid)) { |
1851 | struct vlan_group *grp = pi->vlan_grp; | 1891 | struct vlan_group *grp = pi->vlan_grp; |
1852 | 1892 | ||
1853 | rspq_to_qset(rq)->port_stats[SGE_PSTAT_VLANEX]++; | 1893 | qs->port_stats[SGE_PSTAT_VLANEX]++; |
1854 | if (likely(grp)) | 1894 | if (likely(grp)) |
1855 | __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan), | 1895 | if (lro) |
1856 | rq->polling); | 1896 | lro_vlan_hwaccel_receive_skb(&qs->lro_mgr, skb, |
1897 | grp, | ||
1898 | ntohs(p->vlan), | ||
1899 | p); | ||
1900 | else | ||
1901 | __vlan_hwaccel_rx(skb, grp, ntohs(p->vlan), | ||
1902 | rq->polling); | ||
1857 | else | 1903 | else |
1858 | dev_kfree_skb_any(skb); | 1904 | dev_kfree_skb_any(skb); |
1859 | } else if (rq->polling) | 1905 | } else if (rq->polling) { |
1860 | netif_receive_skb(skb); | 1906 | if (lro) |
1861 | else | 1907 | lro_receive_skb(&qs->lro_mgr, skb, p); |
1908 | else | ||
1909 | netif_receive_skb(skb); | ||
1910 | } else | ||
1862 | netif_rx(skb); | 1911 | netif_rx(skb); |
1863 | } | 1912 | } |
1864 | 1913 | ||
1914 | static inline int is_eth_tcp(u32 rss) | ||
1915 | { | ||
1916 | return G_HASHTYPE(ntohl(rss)) == RSS_HASH_4_TUPLE; | ||
1917 | } | ||
1918 | |||
1919 | /** | ||
1920 | * lro_frame_ok - check if an ingress packet is eligible for LRO | ||
1921 | * @p: the CPL header of the packet | ||
1922 | * | ||
1923 | * Returns true if a received packet is eligible for LRO. | ||
1924 | * The following conditions must be true: | ||
1925 | * - packet is TCP/IP Ethernet II (checked elsewhere) | ||
1926 | * - not an IP fragment | ||
1927 | * - no IP options | ||
1928 | * - TCP/IP checksums are correct | ||
1929 | * - the packet is for this host | ||
1930 | */ | ||
1931 | static inline int lro_frame_ok(const struct cpl_rx_pkt *p) | ||
1932 | { | ||
1933 | const struct ethhdr *eh = (struct ethhdr *)(p + 1); | ||
1934 | const struct iphdr *ih = (struct iphdr *)(eh + 1); | ||
1935 | |||
1936 | return (*((u8 *)p + 1) & 0x90) == 0x10 && p->csum == htons(0xffff) && | ||
1937 | eh->h_proto == htons(ETH_P_IP) && ih->ihl == (sizeof(*ih) >> 2); | ||
1938 | } | ||
1939 | |||
1940 | #define TCP_FLAG_MASK (TCP_FLAG_CWR | TCP_FLAG_ECE | TCP_FLAG_URG |\ | ||
1941 | TCP_FLAG_ACK | TCP_FLAG_PSH | TCP_FLAG_RST |\ | ||
1942 | TCP_FLAG_SYN | TCP_FLAG_FIN) | ||
1943 | #define TSTAMP_WORD ((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |\ | ||
1944 | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP) | ||
1945 | |||
1946 | /** | ||
1947 | * lro_segment_ok - check if a TCP segment is eligible for LRO | ||
1948 | * @tcph: the TCP header of the packet | ||
1949 | * | ||
1950 | * Returns true if a TCP packet is eligible for LRO. This requires that | ||
1951 | * the packet have only the ACK flag set and no TCP options besides | ||
1952 | * time stamps. | ||
1953 | */ | ||
1954 | static inline int lro_segment_ok(const struct tcphdr *tcph) | ||
1955 | { | ||
1956 | int optlen; | ||
1957 | |||
1958 | if (unlikely((tcp_flag_word(tcph) & TCP_FLAG_MASK) != TCP_FLAG_ACK)) | ||
1959 | return 0; | ||
1960 | |||
1961 | optlen = (tcph->doff << 2) - sizeof(*tcph); | ||
1962 | if (optlen) { | ||
1963 | const u32 *opt = (const u32 *)(tcph + 1); | ||
1964 | |||
1965 | if (optlen != TCPOLEN_TSTAMP_ALIGNED || | ||
1966 | *opt != htonl(TSTAMP_WORD) || !opt[2]) | ||
1967 | return 0; | ||
1968 | } | ||
1969 | return 1; | ||
1970 | } | ||
1971 | |||
1972 | static int t3_get_lro_header(void **eh, void **iph, void **tcph, | ||
1973 | u64 *hdr_flags, void *priv) | ||
1974 | { | ||
1975 | const struct cpl_rx_pkt *cpl = priv; | ||
1976 | |||
1977 | if (!lro_frame_ok(cpl)) | ||
1978 | return -1; | ||
1979 | |||
1980 | *eh = (struct ethhdr *)(cpl + 1); | ||
1981 | *iph = (struct iphdr *)((struct ethhdr *)*eh + 1); | ||
1982 | *tcph = (struct tcphdr *)((struct iphdr *)*iph + 1); | ||
1983 | |||
1984 | if (!lro_segment_ok(*tcph)) | ||
1985 | return -1; | ||
1986 | |||
1987 | *hdr_flags = LRO_IPV4 | LRO_TCP; | ||
1988 | return 0; | ||
1989 | } | ||
1990 | |||
1991 | static int t3_get_skb_header(struct sk_buff *skb, | ||
1992 | void **iph, void **tcph, u64 *hdr_flags, | ||
1993 | void *priv) | ||
1994 | { | ||
1995 | void *eh; | ||
1996 | |||
1997 | return t3_get_lro_header(&eh, iph, tcph, hdr_flags, priv); | ||
1998 | } | ||
1999 | |||
2000 | static int t3_get_frag_header(struct skb_frag_struct *frag, void **eh, | ||
2001 | void **iph, void **tcph, u64 *hdr_flags, | ||
2002 | void *priv) | ||
2003 | { | ||
2004 | return t3_get_lro_header(eh, iph, tcph, hdr_flags, priv); | ||
2005 | } | ||
2006 | |||
2007 | /** | ||
2008 | * lro_add_page - add a page chunk to an LRO session | ||
2009 | * @adap: the adapter | ||
2010 | * @qs: the associated queue set | ||
2011 | * @fl: the free list containing the page chunk to add | ||
2012 | * @len: packet length | ||
2013 | * @complete: Indicates the last fragment of a frame | ||
2014 | * | ||
2015 | * Add a received packet contained in a page chunk to an existing LRO | ||
2016 | * session. | ||
2017 | */ | ||
2018 | static void lro_add_page(struct adapter *adap, struct sge_qset *qs, | ||
2019 | struct sge_fl *fl, int len, int complete) | ||
2020 | { | ||
2021 | struct rx_sw_desc *sd = &fl->sdesc[fl->cidx]; | ||
2022 | struct cpl_rx_pkt *cpl; | ||
2023 | struct skb_frag_struct *rx_frag = qs->lro_frag_tbl; | ||
2024 | int nr_frags = qs->lro_nfrags, frag_len = qs->lro_frag_len; | ||
2025 | int offset = 0; | ||
2026 | |||
2027 | if (!nr_frags) { | ||
2028 | offset = 2 + sizeof(struct cpl_rx_pkt); | ||
2029 | qs->lro_va = cpl = sd->pg_chunk.va + 2; | ||
2030 | } | ||
2031 | |||
2032 | fl->credits--; | ||
2033 | |||
2034 | len -= offset; | ||
2035 | pci_unmap_single(adap->pdev, pci_unmap_addr(sd, dma_addr), | ||
2036 | fl->buf_size, PCI_DMA_FROMDEVICE); | ||
2037 | |||
2038 | rx_frag += nr_frags; | ||
2039 | rx_frag->page = sd->pg_chunk.page; | ||
2040 | rx_frag->page_offset = sd->pg_chunk.offset + offset; | ||
2041 | rx_frag->size = len; | ||
2042 | frag_len += len; | ||
2043 | qs->lro_nfrags++; | ||
2044 | qs->lro_frag_len = frag_len; | ||
2045 | |||
2046 | if (!complete) | ||
2047 | return; | ||
2048 | |||
2049 | qs->lro_nfrags = qs->lro_frag_len = 0; | ||
2050 | cpl = qs->lro_va; | ||
2051 | |||
2052 | if (unlikely(cpl->vlan_valid)) { | ||
2053 | struct net_device *dev = qs->netdev; | ||
2054 | struct port_info *pi = netdev_priv(dev); | ||
2055 | struct vlan_group *grp = pi->vlan_grp; | ||
2056 | |||
2057 | if (likely(grp != NULL)) { | ||
2058 | lro_vlan_hwaccel_receive_frags(&qs->lro_mgr, | ||
2059 | qs->lro_frag_tbl, | ||
2060 | frag_len, frag_len, | ||
2061 | grp, ntohs(cpl->vlan), | ||
2062 | cpl, 0); | ||
2063 | return; | ||
2064 | } | ||
2065 | } | ||
2066 | lro_receive_frags(&qs->lro_mgr, qs->lro_frag_tbl, | ||
2067 | frag_len, frag_len, cpl, 0); | ||
2068 | } | ||
2069 | |||
2070 | /** | ||
2071 | * init_lro_mgr - initialize a LRO manager object | ||
2072 | * @lro_mgr: the LRO manager object | ||
2073 | */ | ||
2074 | static void init_lro_mgr(struct sge_qset *qs, struct net_lro_mgr *lro_mgr) | ||
2075 | { | ||
2076 | lro_mgr->dev = qs->netdev; | ||
2077 | lro_mgr->features = LRO_F_NAPI; | ||
2078 | lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; | ||
2079 | lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; | ||
2080 | lro_mgr->max_desc = T3_MAX_LRO_SES; | ||
2081 | lro_mgr->lro_arr = qs->lro_desc; | ||
2082 | lro_mgr->get_frag_header = t3_get_frag_header; | ||
2083 | lro_mgr->get_skb_header = t3_get_skb_header; | ||
2084 | lro_mgr->max_aggr = T3_MAX_LRO_MAX_PKTS; | ||
2085 | if (lro_mgr->max_aggr > MAX_SKB_FRAGS) | ||
2086 | lro_mgr->max_aggr = MAX_SKB_FRAGS; | ||
2087 | } | ||
2088 | |||
1865 | /** | 2089 | /** |
1866 | * handle_rsp_cntrl_info - handles control information in a response | 2090 | * handle_rsp_cntrl_info - handles control information in a response |
1867 | * @qs: the queue set corresponding to the response | 2091 | * @qs: the queue set corresponding to the response |
@@ -1947,6 +2171,12 @@ static inline int is_new_response(const struct rsp_desc *r, | |||
1947 | return (r->intr_gen & F_RSPD_GEN2) == q->gen; | 2171 | return (r->intr_gen & F_RSPD_GEN2) == q->gen; |
1948 | } | 2172 | } |
1949 | 2173 | ||
2174 | static inline void clear_rspq_bufstate(struct sge_rspq * const q) | ||
2175 | { | ||
2176 | q->pg_skb = NULL; | ||
2177 | q->rx_recycle_buf = 0; | ||
2178 | } | ||
2179 | |||
1950 | #define RSPD_GTS_MASK (F_RSPD_TXQ0_GTS | F_RSPD_TXQ1_GTS) | 2180 | #define RSPD_GTS_MASK (F_RSPD_TXQ0_GTS | F_RSPD_TXQ1_GTS) |
1951 | #define RSPD_CTRL_MASK (RSPD_GTS_MASK | \ | 2181 | #define RSPD_CTRL_MASK (RSPD_GTS_MASK | \ |
1952 | V_RSPD_TXQ0_CR(M_RSPD_TXQ0_CR) | \ | 2182 | V_RSPD_TXQ0_CR(M_RSPD_TXQ0_CR) | \ |
@@ -1984,10 +2214,11 @@ static int process_responses(struct adapter *adap, struct sge_qset *qs, | |||
1984 | q->next_holdoff = q->holdoff_tmr; | 2214 | q->next_holdoff = q->holdoff_tmr; |
1985 | 2215 | ||
1986 | while (likely(budget_left && is_new_response(r, q))) { | 2216 | while (likely(budget_left && is_new_response(r, q))) { |
1987 | int eth, ethpad = 2; | 2217 | int packet_complete, eth, ethpad = 2, lro = qs->lro_enabled; |
1988 | struct sk_buff *skb = NULL; | 2218 | struct sk_buff *skb = NULL; |
1989 | u32 len, flags = ntohl(r->flags); | 2219 | u32 len, flags = ntohl(r->flags); |
1990 | __be32 rss_hi = *(const __be32 *)r, rss_lo = r->rss_hdr.rss_hash_val; | 2220 | __be32 rss_hi = *(const __be32 *)r, |
2221 | rss_lo = r->rss_hdr.rss_hash_val; | ||
1991 | 2222 | ||
1992 | eth = r->rss_hdr.opcode == CPL_RX_PKT; | 2223 | eth = r->rss_hdr.opcode == CPL_RX_PKT; |
1993 | 2224 | ||
@@ -2015,6 +2246,9 @@ no_mem: | |||
2015 | } else if ((len = ntohl(r->len_cq)) != 0) { | 2246 | } else if ((len = ntohl(r->len_cq)) != 0) { |
2016 | struct sge_fl *fl; | 2247 | struct sge_fl *fl; |
2017 | 2248 | ||
2249 | if (eth) | ||
2250 | lro = qs->lro_enabled && is_eth_tcp(rss_hi); | ||
2251 | |||
2018 | fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; | 2252 | fl = (len & F_RSPD_FLQ) ? &qs->fl[1] : &qs->fl[0]; |
2019 | if (fl->use_pages) { | 2253 | if (fl->use_pages) { |
2020 | void *addr = fl->sdesc[fl->cidx].pg_chunk.va; | 2254 | void *addr = fl->sdesc[fl->cidx].pg_chunk.va; |
@@ -2024,9 +2258,18 @@ no_mem: | |||
2024 | prefetch(addr + L1_CACHE_BYTES); | 2258 | prefetch(addr + L1_CACHE_BYTES); |
2025 | #endif | 2259 | #endif |
2026 | __refill_fl(adap, fl); | 2260 | __refill_fl(adap, fl); |
2261 | if (lro > 0) { | ||
2262 | lro_add_page(adap, qs, fl, | ||
2263 | G_RSPD_LEN(len), | ||
2264 | flags & F_RSPD_EOP); | ||
2265 | goto next_fl; | ||
2266 | } | ||
2027 | 2267 | ||
2028 | skb = get_packet_pg(adap, fl, G_RSPD_LEN(len), | 2268 | skb = get_packet_pg(adap, fl, q, |
2029 | eth ? SGE_RX_DROP_THRES : 0); | 2269 | G_RSPD_LEN(len), |
2270 | eth ? | ||
2271 | SGE_RX_DROP_THRES : 0); | ||
2272 | q->pg_skb = skb; | ||
2030 | } else | 2273 | } else |
2031 | skb = get_packet(adap, fl, G_RSPD_LEN(len), | 2274 | skb = get_packet(adap, fl, G_RSPD_LEN(len), |
2032 | eth ? SGE_RX_DROP_THRES : 0); | 2275 | eth ? SGE_RX_DROP_THRES : 0); |
@@ -2036,7 +2279,7 @@ no_mem: | |||
2036 | q->rx_drops++; | 2279 | q->rx_drops++; |
2037 | } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT)) | 2280 | } else if (unlikely(r->rss_hdr.opcode == CPL_TRACE_PKT)) |
2038 | __skb_pull(skb, 2); | 2281 | __skb_pull(skb, 2); |
2039 | 2282 | next_fl: | |
2040 | if (++fl->cidx == fl->size) | 2283 | if (++fl->cidx == fl->size) |
2041 | fl->cidx = 0; | 2284 | fl->cidx = 0; |
2042 | } else | 2285 | } else |
@@ -2060,9 +2303,13 @@ no_mem: | |||
2060 | q->credits = 0; | 2303 | q->credits = 0; |
2061 | } | 2304 | } |
2062 | 2305 | ||
2063 | if (likely(skb != NULL)) { | 2306 | packet_complete = flags & |
2307 | (F_RSPD_EOP | F_RSPD_IMM_DATA_VALID | | ||
2308 | F_RSPD_ASYNC_NOTIF); | ||
2309 | |||
2310 | if (skb != NULL && packet_complete) { | ||
2064 | if (eth) | 2311 | if (eth) |
2065 | rx_eth(adap, q, skb, ethpad); | 2312 | rx_eth(adap, q, skb, ethpad, lro); |
2066 | else { | 2313 | else { |
2067 | q->offload_pkts++; | 2314 | q->offload_pkts++; |
2068 | /* Preserve the RSS info in csum & priority */ | 2315 | /* Preserve the RSS info in csum & priority */ |
@@ -2072,11 +2319,19 @@ no_mem: | |||
2072 | offload_skbs, | 2319 | offload_skbs, |
2073 | ngathered); | 2320 | ngathered); |
2074 | } | 2321 | } |
2322 | |||
2323 | if (flags & F_RSPD_EOP) | ||
2324 | clear_rspq_bufstate(q); | ||
2075 | } | 2325 | } |
2076 | --budget_left; | 2326 | --budget_left; |
2077 | } | 2327 | } |
2078 | 2328 | ||
2079 | deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered); | 2329 | deliver_partial_bundle(&adap->tdev, q, offload_skbs, ngathered); |
2330 | lro_flush_all(&qs->lro_mgr); | ||
2331 | qs->port_stats[SGE_PSTAT_LRO_AGGR] = qs->lro_mgr.stats.aggregated; | ||
2332 | qs->port_stats[SGE_PSTAT_LRO_FLUSHED] = qs->lro_mgr.stats.flushed; | ||
2333 | qs->port_stats[SGE_PSTAT_LRO_NO_DESC] = qs->lro_mgr.stats.no_desc; | ||
2334 | |||
2080 | if (sleeping) | 2335 | if (sleeping) |
2081 | check_ring_db(adap, qs, sleeping); | 2336 | check_ring_db(adap, qs, sleeping); |
2082 | 2337 | ||
@@ -2618,8 +2873,9 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2618 | int irq_vec_idx, const struct qset_params *p, | 2873 | int irq_vec_idx, const struct qset_params *p, |
2619 | int ntxq, struct net_device *dev) | 2874 | int ntxq, struct net_device *dev) |
2620 | { | 2875 | { |
2621 | int i, ret = -ENOMEM; | 2876 | int i, avail, ret = -ENOMEM; |
2622 | struct sge_qset *q = &adapter->sge.qs[id]; | 2877 | struct sge_qset *q = &adapter->sge.qs[id]; |
2878 | struct net_lro_mgr *lro_mgr = &q->lro_mgr; | ||
2623 | 2879 | ||
2624 | init_qset_cntxt(q, id); | 2880 | init_qset_cntxt(q, id); |
2625 | init_timer(&q->tx_reclaim_timer); | 2881 | init_timer(&q->tx_reclaim_timer); |
@@ -2687,11 +2943,23 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2687 | #else | 2943 | #else |
2688 | q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data); | 2944 | q->fl[0].buf_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data); |
2689 | #endif | 2945 | #endif |
2690 | q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0; | 2946 | #if FL1_PG_CHUNK_SIZE > 0 |
2947 | q->fl[1].buf_size = FL1_PG_CHUNK_SIZE; | ||
2948 | #else | ||
2691 | q->fl[1].buf_size = is_offload(adapter) ? | 2949 | q->fl[1].buf_size = is_offload(adapter) ? |
2692 | (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : | 2950 | (16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : |
2693 | MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt); | 2951 | MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt); |
2952 | #endif | ||
2694 | 2953 | ||
2954 | q->fl[0].use_pages = FL0_PG_CHUNK_SIZE > 0; | ||
2955 | q->fl[1].use_pages = FL1_PG_CHUNK_SIZE > 0; | ||
2956 | q->fl[0].order = FL0_PG_ORDER; | ||
2957 | q->fl[1].order = FL1_PG_ORDER; | ||
2958 | |||
2959 | q->lro_frag_tbl = kcalloc(MAX_FRAME_SIZE / FL1_PG_CHUNK_SIZE + 1, | ||
2960 | sizeof(struct skb_frag_struct), | ||
2961 | GFP_KERNEL); | ||
2962 | q->lro_nfrags = q->lro_frag_len = 0; | ||
2695 | spin_lock_irq(&adapter->sge.reg_lock); | 2963 | spin_lock_irq(&adapter->sge.reg_lock); |
2696 | 2964 | ||
2697 | /* FL threshold comparison uses < */ | 2965 | /* FL threshold comparison uses < */ |
@@ -2742,8 +3010,23 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2742 | q->netdev = dev; | 3010 | q->netdev = dev; |
2743 | t3_update_qset_coalesce(q, p); | 3011 | t3_update_qset_coalesce(q, p); |
2744 | 3012 | ||
2745 | refill_fl(adapter, &q->fl[0], q->fl[0].size, GFP_KERNEL); | 3013 | init_lro_mgr(q, lro_mgr); |
2746 | refill_fl(adapter, &q->fl[1], q->fl[1].size, GFP_KERNEL); | 3014 | |
3015 | avail = refill_fl(adapter, &q->fl[0], q->fl[0].size, | ||
3016 | GFP_KERNEL | __GFP_COMP); | ||
3017 | if (!avail) { | ||
3018 | CH_ALERT(adapter, "free list queue 0 initialization failed\n"); | ||
3019 | goto err; | ||
3020 | } | ||
3021 | if (avail < q->fl[0].size) | ||
3022 | CH_WARN(adapter, "free list queue 0 enabled with %d credits\n", | ||
3023 | avail); | ||
3024 | |||
3025 | avail = refill_fl(adapter, &q->fl[1], q->fl[1].size, | ||
3026 | GFP_KERNEL | __GFP_COMP); | ||
3027 | if (avail < q->fl[1].size) | ||
3028 | CH_WARN(adapter, "free list queue 1 enabled with %d credits\n", | ||
3029 | avail); | ||
2747 | refill_rspq(adapter, &q->rspq, q->rspq.size - 1); | 3030 | refill_rspq(adapter, &q->rspq, q->rspq.size - 1); |
2748 | 3031 | ||
2749 | t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) | | 3032 | t3_write_reg(adapter, A_SG_GTS, V_RSPQ(q->rspq.cntxt_id) | |
@@ -2752,9 +3035,9 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, | |||
2752 | mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); | 3035 | mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); |
2753 | return 0; | 3036 | return 0; |
2754 | 3037 | ||
2755 | err_unlock: | 3038 | err_unlock: |
2756 | spin_unlock_irq(&adapter->sge.reg_lock); | 3039 | spin_unlock_irq(&adapter->sge.reg_lock); |
2757 | err: | 3040 | err: |
2758 | t3_free_qset(adapter, q); | 3041 | t3_free_qset(adapter, q); |
2759 | return ret; | 3042 | return ret; |
2760 | } | 3043 | } |
@@ -2876,7 +3159,7 @@ void t3_sge_prep(struct adapter *adap, struct sge_params *p) | |||
2876 | q->coalesce_usecs = 5; | 3159 | q->coalesce_usecs = 5; |
2877 | q->rspq_size = 1024; | 3160 | q->rspq_size = 1024; |
2878 | q->fl_size = 1024; | 3161 | q->fl_size = 1024; |
2879 | q->jumbo_size = 512; | 3162 | q->jumbo_size = 512; |
2880 | q->txq_size[TXQ_ETH] = 1024; | 3163 | q->txq_size[TXQ_ETH] = 1024; |
2881 | q->txq_size[TXQ_OFLD] = 1024; | 3164 | q->txq_size[TXQ_OFLD] = 1024; |
2882 | q->txq_size[TXQ_CTRL] = 256; | 3165 | q->txq_size[TXQ_CTRL] = 256; |
diff --git a/drivers/net/cxgb3/t3_cpl.h b/drivers/net/cxgb3/t3_cpl.h index b7a1a310dfd4..917970ed24a1 100644 --- a/drivers/net/cxgb3/t3_cpl.h +++ b/drivers/net/cxgb3/t3_cpl.h | |||
@@ -174,6 +174,13 @@ enum { /* TCP congestion control algorithms */ | |||
174 | CONG_ALG_HIGHSPEED | 174 | CONG_ALG_HIGHSPEED |
175 | }; | 175 | }; |
176 | 176 | ||
177 | enum { /* RSS hash type */ | ||
178 | RSS_HASH_NONE = 0, | ||
179 | RSS_HASH_2_TUPLE = 1, | ||
180 | RSS_HASH_4_TUPLE = 2, | ||
181 | RSS_HASH_TCPV6 = 3 | ||
182 | }; | ||
183 | |||
177 | union opcode_tid { | 184 | union opcode_tid { |
178 | __be32 opcode_tid; | 185 | __be32 opcode_tid; |
179 | __u8 opcode; | 186 | __u8 opcode; |
@@ -184,6 +191,13 @@ union opcode_tid { | |||
184 | #define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF) | 191 | #define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF) |
185 | #define G_TID(x) ((x) & 0xFFFFFF) | 192 | #define G_TID(x) ((x) & 0xFFFFFF) |
186 | 193 | ||
194 | #define S_QNUM 0 | ||
195 | #define G_QNUM(x) (((x) >> S_QNUM) & 0xFFFF) | ||
196 | |||
197 | #define S_HASHTYPE 22 | ||
198 | #define M_HASHTYPE 0x3 | ||
199 | #define G_HASHTYPE(x) (((x) >> S_HASHTYPE) & M_HASHTYPE) | ||
200 | |||
187 | /* tid is assumed to be 24-bits */ | 201 | /* tid is assumed to be 24-bits */ |
188 | #define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid)) | 202 | #define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid)) |
189 | 203 | ||
@@ -768,6 +782,12 @@ struct tx_data_wr { | |||
768 | __be32 param; | 782 | __be32 param; |
769 | }; | 783 | }; |
770 | 784 | ||
785 | /* tx_data_wr.flags fields */ | ||
786 | #define S_TX_ACK_PAGES 21 | ||
787 | #define M_TX_ACK_PAGES 0x7 | ||
788 | #define V_TX_ACK_PAGES(x) ((x) << S_TX_ACK_PAGES) | ||
789 | #define G_TX_ACK_PAGES(x) (((x) >> S_TX_ACK_PAGES) & M_TX_ACK_PAGES) | ||
790 | |||
771 | /* tx_data_wr.param fields */ | 791 | /* tx_data_wr.param fields */ |
772 | #define S_TX_PORT 0 | 792 | #define S_TX_PORT 0 |
773 | #define M_TX_PORT 0x7 | 793 | #define M_TX_PORT 0x7 |
@@ -1441,4 +1461,35 @@ struct cpl_rdma_terminate { | |||
1441 | #define M_TERM_TID 0xFFFFF | 1461 | #define M_TERM_TID 0xFFFFF |
1442 | #define V_TERM_TID(x) ((x) << S_TERM_TID) | 1462 | #define V_TERM_TID(x) ((x) << S_TERM_TID) |
1443 | #define G_TERM_TID(x) (((x) >> S_TERM_TID) & M_TERM_TID) | 1463 | #define G_TERM_TID(x) (((x) >> S_TERM_TID) & M_TERM_TID) |
1464 | |||
1465 | /* ULP_TX opcodes */ | ||
1466 | enum { ULP_MEM_READ = 2, ULP_MEM_WRITE = 3, ULP_TXPKT = 4 }; | ||
1467 | |||
1468 | #define S_ULPTX_CMD 28 | ||
1469 | #define M_ULPTX_CMD 0xF | ||
1470 | #define V_ULPTX_CMD(x) ((x) << S_ULPTX_CMD) | ||
1471 | |||
1472 | #define S_ULPTX_NFLITS 0 | ||
1473 | #define M_ULPTX_NFLITS 0xFF | ||
1474 | #define V_ULPTX_NFLITS(x) ((x) << S_ULPTX_NFLITS) | ||
1475 | |||
1476 | struct ulp_mem_io { | ||
1477 | WR_HDR; | ||
1478 | __be32 cmd_lock_addr; | ||
1479 | __be32 len; | ||
1480 | }; | ||
1481 | |||
1482 | /* ulp_mem_io.cmd_lock_addr fields */ | ||
1483 | #define S_ULP_MEMIO_ADDR 0 | ||
1484 | #define M_ULP_MEMIO_ADDR 0x7FFFFFF | ||
1485 | #define V_ULP_MEMIO_ADDR(x) ((x) << S_ULP_MEMIO_ADDR) | ||
1486 | #define S_ULP_MEMIO_LOCK 27 | ||
1487 | #define V_ULP_MEMIO_LOCK(x) ((x) << S_ULP_MEMIO_LOCK) | ||
1488 | #define F_ULP_MEMIO_LOCK V_ULP_MEMIO_LOCK(1U) | ||
1489 | |||
1490 | /* ulp_mem_io.len fields */ | ||
1491 | #define S_ULP_MEMIO_DATA_LEN 28 | ||
1492 | #define M_ULP_MEMIO_DATA_LEN 0xF | ||
1493 | #define V_ULP_MEMIO_DATA_LEN(x) ((x) << S_ULP_MEMIO_DATA_LEN) | ||
1494 | |||
1444 | #endif /* T3_CPL_H */ | 1495 | #endif /* T3_CPL_H */ |
diff --git a/drivers/net/cxgb3/t3cdev.h b/drivers/net/cxgb3/t3cdev.h index a18c8a140424..0a21cfbd2b21 100644 --- a/drivers/net/cxgb3/t3cdev.h +++ b/drivers/net/cxgb3/t3cdev.h | |||
@@ -45,7 +45,8 @@ struct cxgb3_client; | |||
45 | 45 | ||
46 | enum t3ctype { | 46 | enum t3ctype { |
47 | T3A = 0, | 47 | T3A = 0, |
48 | T3B | 48 | T3B, |
49 | T3C, | ||
49 | }; | 50 | }; |
50 | 51 | ||
51 | struct t3cdev { | 52 | struct t3cdev { |
@@ -63,6 +64,7 @@ struct t3cdev { | |||
63 | void *l3opt; /* optional layer 3 data */ | 64 | void *l3opt; /* optional layer 3 data */ |
64 | void *l4opt; /* optional layer 4 data */ | 65 | void *l4opt; /* optional layer 4 data */ |
65 | void *ulp; /* ulp stuff */ | 66 | void *ulp; /* ulp stuff */ |
67 | void *ulp_iscsi; /* ulp iscsi */ | ||
66 | }; | 68 | }; |
67 | 69 | ||
68 | #endif /* _T3CDEV_H_ */ | 70 | #endif /* _T3CDEV_H_ */ |