Crossbow - transition to Mercurial
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright (c) 2002-2006 Neterion, Inc.
22 */
23
24 #ifdef XGE_DEBUG_FP
25 #include "xgehal-device.h"
26 #endif
27
28 #include "xgehal-ring.h"
29 #include "xgehal-fifo.h"
30
31 /**
32 * xge_hal_device_bar0 - Get BAR0 mapped address.
33 * @hldev: HAL device handle.
34 *
35 * Returns: BAR0 address of the specified device.
36 */
37 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char *
38 xge_hal_device_bar0(xge_hal_device_t *hldev)
39 {
40 return hldev->bar0;
41 }
42
43 /**
44 * xge_hal_device_isrbar0 - Get BAR0 mapped address.
45 * @hldev: HAL device handle.
46 *
47 * Returns: BAR0 address of the specified device.
48 */
49 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char *
50 xge_hal_device_isrbar0(xge_hal_device_t *hldev)
51 {
52 return hldev->isrbar0;
53 }
54
55 /**
56 * xge_hal_device_bar1 - Get BAR1 mapped address.
57 * @hldev: HAL device handle.
58 *
59 * Returns: BAR1 address of the specified device.
60 */
61 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE char *
62 xge_hal_device_bar1(xge_hal_device_t *hldev)
63 {
64 return hldev->bar1;
65 }
66
67 /**
68 * xge_hal_device_bar0_set - Set BAR0 mapped address.
69 * @hldev: HAL device handle.
70 * @bar0: BAR0 mapped address.
71 * * Set BAR0 address in the HAL device object.
72 */
73 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
74 xge_hal_device_bar0_set(xge_hal_device_t *hldev, char *bar0)
75 {
76 xge_assert(bar0);
77 hldev->bar0 = bar0;
78 }
79
80 /**
81 * xge_hal_device_isrbar0_set - Set BAR0 mapped address.
82 * @hldev: HAL device handle.
83 * @isrbar0: BAR0 mapped address.
84 * * Set BAR0 address in the HAL device object.
85 */
86 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
87 xge_hal_device_isrbar0_set(xge_hal_device_t *hldev, char *isrbar0)
88 {
89 xge_assert(isrbar0);
90 hldev->isrbar0 = isrbar0;
91 }
92
93 /**
94 * xge_hal_device_bar1_set - Set BAR1 mapped address.
95 * @hldev: HAL device handle.
96 * @channelh: Channel handle.
97 * @bar1: BAR1 mapped address.
98 *
99 * Set BAR1 address for the given channel.
100 */
101 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
102 xge_hal_device_bar1_set(xge_hal_device_t *hldev, xge_hal_channel_h channelh,
103 char *bar1)
104 {
105 xge_hal_fifo_t *fifo = (xge_hal_fifo_t *)channelh;
106
107 xge_assert(bar1);
108 xge_assert(fifo);
109
110 /* Initializing the BAR1 address as the start of
111 * the FIFO queue pointer and as a location of FIFO control
112 * word. */
113 fifo->hw_pair =
114 (xge_hal_fifo_hw_pair_t *) (bar1 +
115 (fifo->channel.post_qid * XGE_HAL_FIFO_HW_PAIR_OFFSET));
116 hldev->bar1 = bar1;
117 }
118
119
120 /**
121 * xge_hal_device_rev - Get Device revision number.
122 * @hldev: HAL device handle.
123 *
124 * Returns: Device revision number
125 */
126 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE int
127 xge_hal_device_rev(xge_hal_device_t *hldev)
128 {
129 return hldev->revision;
130 }
131
132
133 /**
134 * xge_hal_device_begin_irq - Begin IRQ processing.
135 * @hldev: HAL device handle.
136 * @reason: "Reason" for the interrupt, the value of Xframe's
137 * general_int_status register.
138 *
139 * The function performs two actions, It first checks whether (shared IRQ) the
140 * interrupt was raised by the device. Next, it masks the device interrupts.
141 *
142 * Note:
143 * xge_hal_device_begin_irq() does not flush MMIO writes through the
144 * bridge. Therefore, two back-to-back interrupts are potentially possible.
145 * It is the responsibility of the ULD to make sure that only one
146 * xge_hal_device_continue_irq() runs at a time.
147 *
148 * Returns: 0, if the interrupt is not "ours" (note that in this case the
149 * device remain enabled).
150 * Otherwise, xge_hal_device_begin_irq() returns 64bit general adapter
151 * status.
152 * See also: xge_hal_device_handle_irq()
153 */
154 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
155 xge_hal_device_begin_irq(xge_hal_device_t *hldev, u64 *reason)
156 {
157 u64 val64;
158 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
159
160 hldev->stats.sw_dev_info_stats.total_intr_cnt++;
161
162 val64 = xge_os_pio_mem_read64(hldev->pdev,
163 hldev->regh0, &isrbar0->general_int_status);
164 if (xge_os_unlikely(!val64)) {
165 /* not Xframe interrupt */
166 hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
167 *reason = 0;
168 return XGE_HAL_ERR_WRONG_IRQ;
169 }
170
171 if (xge_os_unlikely(val64 == XGE_HAL_ALL_FOXES)) {
172 u64 adapter_status =
173 xge_os_pio_mem_read64(hldev->pdev, hldev->regh0,
174 &isrbar0->adapter_status);
175 if (adapter_status == XGE_HAL_ALL_FOXES) {
176 (void) xge_queue_produce(hldev->queueh,
177 XGE_HAL_EVENT_SLOT_FREEZE,
178 hldev,
179 1, /* critical: slot freeze */
180 sizeof(u64),
181 (void*)&adapter_status);
182 *reason = 0;
183 return XGE_HAL_ERR_CRITICAL;
184 }
185 }
186
187 *reason = val64;
188
189 /* separate fast path, i.e. no errors */
190 if (val64 & XGE_HAL_GEN_INTR_RXTRAFFIC) {
191 hldev->stats.sw_dev_info_stats.rx_traffic_intr_cnt++;
192 return XGE_HAL_OK;
193 }
194 if (val64 & XGE_HAL_GEN_INTR_TXTRAFFIC) {
195 hldev->stats.sw_dev_info_stats.tx_traffic_intr_cnt++;
196 return XGE_HAL_OK;
197 }
198
199 hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
200 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXPIC)) {
201 xge_hal_status_e status;
202 hldev->stats.sw_dev_info_stats.txpic_intr_cnt++;
203 status = __hal_device_handle_txpic(hldev, val64);
204 if (status != XGE_HAL_OK) {
205 return status;
206 }
207 }
208
209 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXDMA)) {
210 xge_hal_status_e status;
211 hldev->stats.sw_dev_info_stats.txdma_intr_cnt++;
212 status = __hal_device_handle_txdma(hldev, val64);
213 if (status != XGE_HAL_OK) {
214 return status;
215 }
216 }
217
218 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXMAC)) {
219 xge_hal_status_e status;
220 hldev->stats.sw_dev_info_stats.txmac_intr_cnt++;
221 status = __hal_device_handle_txmac(hldev, val64);
222 if (status != XGE_HAL_OK) {
223 return status;
224 }
225 }
226
227 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_TXXGXS)) {
228 xge_hal_status_e status;
229 hldev->stats.sw_dev_info_stats.txxgxs_intr_cnt++;
230 status = __hal_device_handle_txxgxs(hldev, val64);
231 if (status != XGE_HAL_OK) {
232 return status;
233 }
234 }
235
236 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXPIC)) {
237 xge_hal_status_e status;
238 hldev->stats.sw_dev_info_stats.rxpic_intr_cnt++;
239 status = __hal_device_handle_rxpic(hldev, val64);
240 if (status != XGE_HAL_OK) {
241 return status;
242 }
243 }
244
245 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXDMA)) {
246 xge_hal_status_e status;
247 hldev->stats.sw_dev_info_stats.rxdma_intr_cnt++;
248 status = __hal_device_handle_rxdma(hldev, val64);
249 if (status != XGE_HAL_OK) {
250 return status;
251 }
252 }
253
254 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXMAC)) {
255 xge_hal_status_e status;
256 hldev->stats.sw_dev_info_stats.rxmac_intr_cnt++;
257 status = __hal_device_handle_rxmac(hldev, val64);
258 if (status != XGE_HAL_OK) {
259 return status;
260 }
261 }
262
263 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_RXXGXS)) {
264 xge_hal_status_e status;
265 hldev->stats.sw_dev_info_stats.rxxgxs_intr_cnt++;
266 status = __hal_device_handle_rxxgxs(hldev, val64);
267 if (status != XGE_HAL_OK) {
268 return status;
269 }
270 }
271
272 if (xge_os_unlikely(val64 & XGE_HAL_GEN_INTR_MC)) {
273 xge_hal_status_e status;
274 hldev->stats.sw_dev_info_stats.mc_intr_cnt++;
275 status = __hal_device_handle_mc(hldev, val64);
276 if (status != XGE_HAL_OK) {
277 return status;
278 }
279 }
280
281 return XGE_HAL_OK;
282 }
283
284 /**
285 * xge_hal_device_clear_rx - Acknowledge (that is, clear) the
286 * condition that has caused the RX interrupt.
287 * @hldev: HAL device handle.
288 *
289 * Acknowledge (that is, clear) the condition that has caused
290 * the Rx interrupt.
291 * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(),
292 * xge_hal_device_clear_tx(), xge_hal_device_mask_rx().
293 */
294 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
295 xge_hal_device_clear_rx(xge_hal_device_t *hldev)
296 {
297 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
298
299 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
300 0xFFFFFFFFFFFFFFFFULL,
301 &isrbar0->rx_traffic_int);
302 }
303
304 /**
305 * xge_hal_device_clear_tx - Acknowledge (that is, clear) the
306 * condition that has caused the TX interrupt.
307 * @hldev: HAL device handle.
308 *
309 * Acknowledge (that is, clear) the condition that has caused
310 * the Tx interrupt.
311 * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq(),
312 * xge_hal_device_clear_rx(), xge_hal_device_mask_tx().
313 */
314 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
315 xge_hal_device_clear_tx(xge_hal_device_t *hldev)
316 {
317 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
318
319 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
320 0xFFFFFFFFFFFFFFFFULL,
321 &isrbar0->tx_traffic_int);
322 }
323
324 /**
325 * xge_hal_device_poll_rx_channel - Poll Rx channel for completed
326 * descriptors and process the same.
327 * @channel: HAL channel.
328 *
329 * The function polls the Rx channel for the completed descriptors and calls
330 * the upper-layer driver (ULD) via supplied completion callback.
331 *
332 * Returns: XGE_HAL_OK, if the polling is completed successful.
333 * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
334 * descriptors available which are yet to be processed.
335 *
336 * See also: xge_hal_device_poll_tx_channel()
337 */
338 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
339 xge_hal_device_poll_rx_channel(xge_hal_channel_t *channel, int *got_rx)
340 {
341 xge_hal_status_e ret = XGE_HAL_OK;
342 xge_hal_dtr_h first_dtrh;
343 xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh;
344 u8 t_code;
345 int got_bytes;
346
347 /* for each opened rx channel */
348 got_bytes = *got_rx = 0;
349 ((xge_hal_ring_t *)channel)->cmpl_cnt = 0;
350 channel->poll_bytes = 0;
351 if ((ret = xge_hal_ring_dtr_next_completed (channel, &first_dtrh,
352 &t_code)) == XGE_HAL_OK) {
353 if (channel->callback(channel, first_dtrh,
354 t_code, channel->userdata) != XGE_HAL_OK) {
355 (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1;
356 got_bytes += channel->poll_bytes + 1;
357 ret = XGE_HAL_COMPLETIONS_REMAIN;
358 } else {
359 (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1;
360 got_bytes += channel->poll_bytes + 1;
361 }
362 }
363
364 if (*got_rx) {
365 hldev->irq_workload_rxd[channel->post_qid] += *got_rx;
366 hldev->irq_workload_rxcnt[channel->post_qid] ++;
367 }
368 hldev->irq_workload_rxlen[channel->post_qid] += got_bytes;
369
370 return ret;
371 }
372
373 /**
374 * xge_hal_device_poll_tx_channel - Poll Tx channel for completed
375 * descriptors and process the same.
376 * @hldev: HAL channel.
377 *
378 * The function polls the Tx channel for the completed descriptors and calls
379 * the upper-layer driver (ULD) via supplied completion callback.
380 *
381 * Returns: XGE_HAL_OK, if the polling is completed successful.
382 * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
383 * descriptors available which are yet to be processed.
384 *
385 * See also: xge_hal_device_poll_rx_channel().
386 */
387 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
388 xge_hal_device_poll_tx_channel(xge_hal_channel_t *channel, int *got_tx)
389 {
390 xge_hal_dtr_h first_dtrh;
391 xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh;
392 u8 t_code;
393 int got_bytes;
394
395 /* for each opened tx channel */
396 got_bytes = *got_tx = 0;
397 channel->poll_bytes = 0;
398 if (xge_hal_fifo_dtr_next_completed (channel, &first_dtrh,
399 &t_code) == XGE_HAL_OK) {
400 if (channel->callback(channel, first_dtrh,
401 t_code, channel->userdata) != XGE_HAL_OK) {
402 (*got_tx)++;
403 got_bytes += channel->poll_bytes + 1;
404 return XGE_HAL_COMPLETIONS_REMAIN;
405 }
406 (*got_tx)++;
407 got_bytes += channel->poll_bytes + 1;
408 }
409
410 if (*got_tx) {
411 hldev->irq_workload_txd[channel->post_qid] += *got_tx;
412 hldev->irq_workload_txcnt[channel->post_qid] ++;
413 }
414 hldev->irq_workload_txlen[channel->post_qid] += got_bytes;
415
416 return XGE_HAL_OK;
417 }
418
419 /**
420 * xge_hal_device_poll_rx_channels - Poll Rx channels for completed
421 * descriptors and process the same.
422 * @hldev: HAL device handle.
423 *
424 * The function polls the Rx channels for the completed descriptors and calls
425 * the upper-layer driver (ULD) via supplied completion callback.
426 *
427 * Returns: XGE_HAL_OK, if the polling is completed successful.
428 * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
429 * descriptors available which are yet to be processed.
430 *
431 * See also: xge_hal_device_poll_tx_channels(), xge_hal_device_continue_irq().
432 */
433 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
434 xge_hal_device_poll_rx_channels(xge_hal_device_t *hldev, int *got_rx)
435 {
436 xge_list_t *item;
437 xge_hal_channel_t *channel;
438
439 /* for each opened rx channel */
440 xge_list_for_each(item, &hldev->ring_channels) {
441 if (hldev->terminating)
442 return XGE_HAL_OK;
443 channel = xge_container_of(item, xge_hal_channel_t, item);
444 if (!(channel->flags & XGE_HAL_CHANNEL_FLAG_USE_RX_POLLING)) {
445 (void) xge_hal_device_poll_rx_channel(channel, got_rx);
446 }
447 }
448
449 return XGE_HAL_OK;
450 }
451
452 /**
453 * xge_hal_device_poll_tx_channels - Poll Tx channels for completed
454 * descriptors and process the same.
455 * @hldev: HAL device handle.
456 *
457 * The function polls the Tx channels for the completed descriptors and calls
458 * the upper-layer driver (ULD) via supplied completion callback.
459 *
460 * Returns: XGE_HAL_OK, if the polling is completed successful.
461 * XGE_HAL_COMPLETIONS_REMAIN: There are still more completed
462 * descriptors available which are yet to be processed.
463 *
464 * See also: xge_hal_device_poll_rx_channels(), xge_hal_device_continue_irq().
465 */
466 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
467 xge_hal_device_poll_tx_channels(xge_hal_device_t *hldev, int *got_tx)
468 {
469 xge_list_t *item;
470 xge_hal_channel_t *channel;
471
472 /* for each opened tx channel */
473 xge_list_for_each(item, &hldev->fifo_channels) {
474 if (hldev->terminating)
475 return XGE_HAL_OK;
476 channel = xge_container_of(item, xge_hal_channel_t, item);
477 (void) xge_hal_device_poll_tx_channel(channel, got_tx);
478 }
479
480 return XGE_HAL_OK;
481 }
482
483 /**
484 *
485 */
486 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
487 xge_hal_device_rx_channel_enable_polling(xge_hal_channel_t *channel)
488 {
489 channel->flags |= XGE_HAL_CHANNEL_FLAG_USE_RX_POLLING;
490 }
491
492 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
493 xge_hal_device_rx_channel_disable_polling(xge_hal_channel_t *channel)
494 {
495 channel->flags &= ~XGE_HAL_CHANNEL_FLAG_USE_RX_POLLING;
496 }
497
498
499 /**
500 * xge_hal_device_mask_tx - Mask Tx interrupts.
501 * @hldev: HAL device handle.
502 *
503 * Mask Tx device interrupts.
504 *
505 * See also: xge_hal_device_unmask_tx(), xge_hal_device_mask_rx(),
506 * xge_hal_device_clear_tx().
507 */
508 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
509 xge_hal_device_mask_tx(xge_hal_device_t *hldev)
510 {
511 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
512
513 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
514 0xFFFFFFFFFFFFFFFFULL,
515 &isrbar0->tx_traffic_mask);
516 }
517
518 /**
519 * xge_hal_device_mask_rx - Mask Rx interrupts.
520 * @hldev: HAL device handle.
521 *
522 * Mask Rx device interrupts.
523 *
524 * See also: xge_hal_device_unmask_rx(), xge_hal_device_mask_tx(),
525 * xge_hal_device_clear_rx().
526 */
527 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
528 xge_hal_device_mask_rx(xge_hal_device_t *hldev)
529 {
530 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
531
532 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
533 0xFFFFFFFFFFFFFFFFULL,
534 &isrbar0->rx_traffic_mask);
535 }
536
537 /**
538 * xge_hal_device_mask_all - Mask all device interrupts.
539 * @hldev: HAL device handle.
540 *
541 * Mask all device interrupts.
542 *
543 * See also: xge_hal_device_unmask_all()
544 */
545 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
546 xge_hal_device_mask_all(xge_hal_device_t *hldev)
547 {
548 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
549
550 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
551 0xFFFFFFFFFFFFFFFFULL,
552 &isrbar0->general_int_mask);
553 }
554
555 /**
556 * xge_hal_device_unmask_tx - Unmask Tx interrupts.
557 * @hldev: HAL device handle.
558 *
559 * Unmask Tx device interrupts.
560 *
561 * See also: xge_hal_device_mask_tx(), xge_hal_device_clear_tx().
562 */
563 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
564 xge_hal_device_unmask_tx(xge_hal_device_t *hldev)
565 {
566 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
567
568 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
569 0x0ULL,
570 &isrbar0->tx_traffic_mask);
571 }
572
573 /**
574 * xge_hal_device_unmask_rx - Unmask Rx interrupts.
575 * @hldev: HAL device handle.
576 *
577 * Unmask Rx device interrupts.
578 *
579 * See also: xge_hal_device_mask_rx(), xge_hal_device_clear_rx().
580 */
581 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
582 xge_hal_device_unmask_rx(xge_hal_device_t *hldev)
583 {
584 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
585
586 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
587 0x0ULL,
588 &isrbar0->rx_traffic_mask);
589 }
590
591 /**
592 * xge_hal_device_unmask_all - Unmask all device interrupts.
593 * @hldev: HAL device handle.
594 *
595 * Unmask all device interrupts.
596 *
597 * See also: xge_hal_device_mask_all()
598 */
599 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE void
600 xge_hal_device_unmask_all(xge_hal_device_t *hldev)
601 {
602 xge_hal_pci_bar0_t *isrbar0 = (xge_hal_pci_bar0_t *)hldev->isrbar0;
603
604 xge_os_pio_mem_write64(hldev->pdev, hldev->regh0,
605 0x0ULL,
606 &isrbar0->general_int_mask);
607 }
608
609
610 /**
611 * xge_hal_device_continue_irq - Continue handling IRQ: process all
612 * completed descriptors.
613 * @hldev: HAL device handle.
614 *
615 * Process completed descriptors and unmask the device interrupts.
616 *
617 * The xge_hal_device_continue_irq() walks all open channels
618 * and calls upper-layer driver (ULD) via supplied completion
619 * callback. Note that the completion callback is specified at channel open
620 * time, see xge_hal_channel_open().
621 *
622 * Note that the xge_hal_device_continue_irq is part of the _fast_ path.
623 * To optimize the processing, the function does _not_ check for
624 * errors and alarms.
625 *
626 * The latter is done in a polling fashion, via xge_hal_device_poll().
627 *
628 * Returns: XGE_HAL_OK.
629 *
630 * See also: xge_hal_device_handle_irq(), xge_hal_device_poll(),
631 * xge_hal_ring_dtr_next_completed(),
632 * xge_hal_fifo_dtr_next_completed(), xge_hal_channel_callback_f{}.
633 */
634 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
635 xge_hal_device_continue_irq(xge_hal_device_t *hldev)
636 {
637 int got_rx = 1, got_tx = 1;
638 int isr_polling_cnt = hldev->config.isr_polling_cnt;
639 int count = 0;
640
641 do
642 {
643 if (got_rx)
644 (void) xge_hal_device_poll_rx_channels(hldev, &got_rx);
645 if (got_tx && hldev->tti_enabled)
646 (void) xge_hal_device_poll_tx_channels(hldev, &got_tx);
647
648 if (!got_rx && !got_tx)
649 break;
650
651 count += (got_rx + got_tx);
652 }while (isr_polling_cnt--);
653
654 if (!count)
655 hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
656
657 return XGE_HAL_OK;
658 }
659
660 /**
661 * xge_hal_device_handle_irq - Handle device IRQ.
662 * @hldev: HAL device handle.
663 *
664 * Perform the complete handling of the line interrupt. The function
665 * performs two calls.
666 * First it uses xge_hal_device_begin_irq() to check the reason for
667 * the interrupt and mask the device interrupts.
668 * Second, it calls xge_hal_device_continue_irq() to process all
669 * completed descriptors and re-enable the interrupts.
670 *
671 * Returns: XGE_HAL_OK - success;
672 * XGE_HAL_ERR_WRONG_IRQ - (shared) IRQ produced by other device.
673 *
674 * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq().
675 */
676 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
677 xge_hal_device_handle_irq(xge_hal_device_t *hldev)
678 {
679 u64 reason;
680 xge_hal_status_e status;
681
682 xge_hal_device_mask_all(hldev);
683
684 status = xge_hal_device_begin_irq(hldev, &reason);
685 if (status != XGE_HAL_OK) {
686 xge_hal_device_unmask_all(hldev);
687 return status;
688 }
689
690 if (reason & XGE_HAL_GEN_INTR_RXTRAFFIC) {
691 xge_hal_device_clear_rx(hldev);
692 }
693
694 status = xge_hal_device_continue_irq(hldev);
695
696 xge_hal_device_clear_tx(hldev);
697
698 xge_hal_device_unmask_all(hldev);
699
700 return status;
701 }
702
703 #if defined(XGE_HAL_CONFIG_LRO)
704
705
706 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
707 __hal_lro_check_for_session_match(lro_t *lro, tcplro_t *tcp, iplro_t *ip)
708 {
709
710 /* Match Source address field */
711 if ((lro->ip_hdr->saddr != ip->saddr))
712 return XGE_HAL_FAIL;
713
714 /* Match Destination address field */
715 if ((lro->ip_hdr->daddr != ip->daddr))
716 return XGE_HAL_FAIL;
717
718 /* Match Source Port field */
719 if ((lro->tcp_hdr->source != tcp->source))
720 return XGE_HAL_FAIL;
721
722 /* Match Destination Port field */
723 if ((lro->tcp_hdr->dest != tcp->dest))
724 return XGE_HAL_FAIL;
725
726 return XGE_HAL_OK;
727 }
728
729 /*
730 * __hal_tcp_seg_len: Find the tcp seg len.
731 * @ip: ip header.
732 * @tcp: tcp header.
733 * returns: Tcp seg length.
734 */
735 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u16
736 __hal_tcp_seg_len(iplro_t *ip, tcplro_t *tcp)
737 {
738 u16 ret;
739
740 ret = (xge_os_ntohs(ip->tot_len) -
741 ((ip->version_ihl & 0x0F)<<2) -
742 ((tcp->doff_res)>>2));
743 return (ret);
744 }
745
746 /*
747 * __hal_ip_lro_capable: Finds whether ip is lro capable.
748 * @ip: ip header.
749 * @ext_info: descriptor info.
750 */
751 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
752 __hal_ip_lro_capable(iplro_t *ip,
753 xge_hal_dtr_info_t *ext_info)
754 {
755
756 #ifdef XGE_LL_DEBUG_DUMP_PKT
757 {
758 u16 i;
759 u8 ch, *iph = (u8 *)ip;
760
761 xge_debug_ring(XGE_TRACE, "Dump Ip:" );
762 for (i =0; i < 40; i++) {
763 ch = ntohs(*((u8 *)(iph + i)) );
764 printf("i:%d %02x, ",i,ch);
765 }
766 }
767 #endif
768
769 if (ip->version_ihl != IP_FAST_PATH_HDR_MASK) {
770 xge_debug_ring(XGE_ERR, "iphdr !=45 :%d",ip->version_ihl);
771 return XGE_HAL_FAIL;
772 }
773
774 if (ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED) {
775 xge_debug_ring(XGE_ERR, "IP fragmented");
776 return XGE_HAL_FAIL;
777 }
778
779 return XGE_HAL_OK;
780 }
781
782 /*
783 * __hal_tcp_lro_capable: Finds whether tcp is lro capable.
784 * @ip: ip header.
785 * @tcp: tcp header.
786 */
787 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
788 __hal_tcp_lro_capable(iplro_t *ip, tcplro_t *tcp, lro_t *lro, int *ts_off)
789 {
790 #ifdef XGE_LL_DEBUG_DUMP_PKT
791 {
792 u8 ch;
793 u16 i;
794
795 xge_debug_ring(XGE_TRACE, "Dump Tcp:" );
796 for (i =0; i < 20; i++) {
797 ch = ntohs(*((u8 *)((u8 *)tcp + i)) );
798 xge_os_printf("i:%d %02x, ",i,ch);
799 }
800 }
801 #endif
802 if ((TCP_FAST_PATH_HDR_MASK2 != tcp->ctrl) &&
803 (TCP_FAST_PATH_HDR_MASK3 != tcp->ctrl))
804 goto _exit_fail;
805
806 *ts_off = -1;
807 if (TCP_FAST_PATH_HDR_MASK1 != tcp->doff_res) {
808 u16 tcp_hdr_len = tcp->doff_res >> 2; /* TCP header len */
809 u16 off = 20; /* Start of tcp options */
810 int i, diff;
811
812 /* Does Packet can contain time stamp */
813 if (tcp_hdr_len < 32) {
814 /*
815 * If the session is not opened, we can consider
816 * this packet for LRO
817 */
818 if (lro == NULL)
819 return XGE_HAL_OK;
820
821 goto _exit_fail;
822 }
823
824 /* Ignore No-operation 0x1 */
825 while (((u8 *)tcp)[off] == 0x1)
826 off++;
827
828 /* Next option == Timestamp */
829 if (((u8 *)tcp)[off] != 0x8) {
830 /*
831 * If the session ie not opened, we can consider
832 * this packet for LRO
833 */
834 if (lro == NULL)
835 return XGE_HAL_OK;
836
837 goto _exit_fail;
838 }
839
840 *ts_off = off;
841 if (lro == NULL)
842 return XGE_HAL_OK;
843
844 /*
845 * Now the session is opened. If the LRO frame doesn't
846 * have time stamp, we cannot consider current packet for
847 * LRO.
848 */
849 if (lro->ts_off == -1) {
850 xge_debug_ring(XGE_ERR, "Pkt received with time stamp after session opened with no time stamp : %02x %02x\n", tcp->doff_res, tcp->ctrl);
851 return XGE_HAL_FAIL;
852 }
853
854 /*
855 * If the difference is greater than three, then there are
856 * more options possible.
857 * else, there are two cases:
858 * case 1: remaining are padding bytes.
859 * case 2: remaining can contain options or padding
860 */
861 off += ((u8 *)tcp)[off+1];
862 diff = tcp_hdr_len - off;
863 if (diff > 3) {
864 /*
865 * Probably contains more options.
866 */
867 xge_debug_ring(XGE_ERR, "tcphdr not fastpth : pkt received with tcp options in addition to time stamp after the session is opened %02x %02x \n", tcp->doff_res, tcp->ctrl);
868 return XGE_HAL_FAIL;
869 }
870
871 for (i = 0; i < diff; i++) {
872 u8 byte = ((u8 *)tcp)[off+i];
873
874 /* Ignore No-operation 0x1 */
875 if ((byte == 0x0) || (byte == 0x1))
876 continue;
877 xge_debug_ring(XGE_ERR, "tcphdr not fastpth : pkt received with tcp options in addition to time stamp after the session is opened %02x %02x \n", tcp->doff_res, tcp->ctrl);
878 return XGE_HAL_FAIL;
879 }
880
881 /*
882 * Update the time stamp of LRO frame.
883 */
884 xge_os_memcpy(((char *)lro->tcp_hdr + lro->ts_off + 2),
885 (char *)((char *)tcp + (*ts_off) + 2), 8);
886 }
887
888 return XGE_HAL_OK;
889
890 _exit_fail:
891 xge_debug_ring(XGE_ERR, "tcphdr not fastpth %02x %02x\n", tcp->doff_res, tcp->ctrl);
892 return XGE_HAL_FAIL;
893
894 }
895
896 /*
897 * __hal_lro_capable: Finds whether frame is lro capable.
898 * @buffer: Ethernet frame.
899 * @ip: ip frame.
900 * @tcp: tcp frame.
901 * @ext_info: Descriptor info.
902 * @hldev: Hal context.
903 */
904 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
905 __hal_lro_capable( u8 *buffer,
906 iplro_t **ip,
907 tcplro_t **tcp,
908 xge_hal_dtr_info_t *ext_info,
909 xge_hal_device_t *hldev)
910 {
911 u8 ip_off, ip_length;
912
913 if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_TCP)) {
914 xge_debug_ring(XGE_ERR, "Cant do lro %d", ext_info->proto);
915 return XGE_HAL_FAIL;
916 }
917 #ifdef XGE_LL_DEBUG_DUMP_PKT
918 {
919 u8 ch;
920 u16 i;
921
922 xge_os_printf("Dump Eth:" );
923 for (i =0; i < 60; i++) {
924 ch = ntohs(*((u8 *)(buffer + i)) );
925 xge_os_printf("i:%d %02x, ",i,ch);
926 }
927 }
928 #endif
929
930 switch (ext_info->frame) {
931 case XGE_HAL_FRAME_TYPE_DIX:
932 ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE;
933 break;
934 case XGE_HAL_FRAME_TYPE_LLC:
935 ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
936 XGE_HAL_HEADER_802_2_SIZE);
937 break;
938 case XGE_HAL_FRAME_TYPE_SNAP:
939 ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE +
940 XGE_HAL_HEADER_SNAP_SIZE);
941 break;
942 default: // XGE_HAL_FRAME_TYPE_IPX, etc.
943 return XGE_HAL_FAIL;
944 }
945
946
947 if (ext_info->proto & XGE_HAL_FRAME_PROTO_VLAN_TAGGED) {
948 ip_off += XGE_HAL_HEADER_VLAN_SIZE;
949 }
950
951 /* Grab ip, tcp headers */
952 *ip = (iplro_t *)((char*)buffer + ip_off);
953
954 ip_length = (u8)((*ip)->version_ihl & 0x0F);
955 ip_length = ip_length <<2;
956 *tcp = (tcplro_t *)((unsigned long)*ip + ip_length);
957
958 xge_debug_ring(XGE_TRACE, "ip_length:%d ip:"XGE_OS_LLXFMT
959 " tcp:"XGE_OS_LLXFMT"", (int)ip_length,
960 (unsigned long long)(long)*ip, (unsigned long long)(long)*tcp);
961
962 return XGE_HAL_OK;
963
964 }
965
966
967 /*
968 * __hal_open_lro_session: Open a new LRO session.
969 * @buffer: Ethernet frame.
970 * @ip: ip header.
971 * @tcp: tcp header.
972 * @lro: lro pointer
973 * @ext_info: Descriptor info.
974 * @hldev: Hal context.
975 * @slot: Bucket no.
976 * @tcp_seg_len: Length of tcp segment.
977 * @ts_off: time stamp offset in the packet.
978 */
979 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
980 __hal_open_lro_session (u8 *buffer, iplro_t *ip, tcplro_t *tcp, lro_t **lro,
981 xge_hal_device_t *hldev, int slot, u32 tcp_seg_len,
982 int ts_off)
983 {
984
985 lro_t *lro_new = &hldev->lro_pool[slot];
986
987 lro_new->in_use = 1;
988 lro_new->ll_hdr = buffer;
989 lro_new->ip_hdr = ip;
990 lro_new->tcp_hdr = tcp;
991 lro_new->tcp_next_seq_num = tcp_seg_len + xge_os_ntohl(
992 tcp->seq);
993 lro_new->tcp_seq_num = tcp->seq;
994 lro_new->tcp_ack_num = tcp->ack_seq;
995 lro_new->sg_num = 1;
996 lro_new->total_length = xge_os_ntohs(ip->tot_len);
997 lro_new->frags_len = 0;
998 lro_new->ts_off = ts_off;
999
1000 hldev->stats.sw_dev_info_stats.tot_frms_lroised++;
1001 hldev->stats.sw_dev_info_stats.tot_lro_sessions++;
1002
1003 *lro = hldev->lro_recent = lro_new;
1004 return;
1005 }
1006
1007 /*
1008 * __hal_lro_get_free_slot: Get a free LRO bucket.
1009 * @hldev: Hal context.
1010 */
1011 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
1012 __hal_lro_get_free_slot (xge_hal_device_t *hldev)
1013 {
1014 int i;
1015
1016 for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
1017 lro_t *lro_temp = &hldev->lro_pool[i];
1018
1019 if (!lro_temp->in_use)
1020 return i;
1021 }
1022 return -1;
1023 }
1024
1025 /*
1026 * __hal_get_lro_session: Gets matching LRO session or creates one.
1027 * @buffer: Ethernet frame.
1028 * @ip: ip header.
1029 * @tcp: tcp header.
1030 * @lro: lro pointer
1031 * @ext_info: Descriptor info.
1032 * @hldev: Hal context.
1033 */
1034 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1035 __hal_get_lro_session (u8 *buffer,
1036 iplro_t *ip,
1037 tcplro_t *tcp,
1038 lro_t **lro,
1039 xge_hal_dtr_info_t *ext_info,
1040 xge_hal_device_t *hldev,
1041 lro_t **lro_end3 /* Valid only when ret=END_3 */)
1042 {
1043 lro_t *lro_match;
1044 int i, free_slot = -1;
1045 u32 tcp_seg_len;
1046 int ts_off = -1;
1047
1048 *lro = lro_match = NULL;
1049 /*
1050 * Compare the incoming frame with the lro session left from the
1051 * previous call. There is a good chance that this incoming frame
1052 * matches the lro session.
1053 */
1054 if (hldev->lro_recent && hldev->lro_recent->in_use) {
1055 if (__hal_lro_check_for_session_match(hldev->lro_recent,
1056 tcp, ip)
1057 == XGE_HAL_OK)
1058 lro_match = hldev->lro_recent;
1059 }
1060
1061 if (!lro_match) {
1062 /*
1063 * Search in the pool of LROs for the session that matches
1064 * the incoming frame.
1065 */
1066 for (i = 0; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
1067 lro_t *lro_temp = &hldev->lro_pool[i];
1068
1069 if (!lro_temp->in_use) {
1070 if (free_slot == -1)
1071 free_slot = i;
1072 continue;
1073 }
1074
1075 if (__hal_lro_check_for_session_match(lro_temp, tcp,
1076 ip) == XGE_HAL_OK) {
1077 lro_match = lro_temp;
1078 break;
1079 }
1080 }
1081 }
1082
1083
1084 if (lro_match) {
1085 /*
1086 * Matching LRO Session found
1087 */
1088 *lro = lro_match;
1089
1090 if (lro_match->tcp_next_seq_num != xge_os_ntohl(tcp->seq)) {
1091 xge_debug_ring(XGE_ERR, "**retransmit **"
1092 "found***");
1093 hldev->stats.sw_dev_info_stats.lro_out_of_seq_pkt_cnt++;
1094 return XGE_HAL_INF_LRO_END_2;
1095 }
1096
1097 if (XGE_HAL_OK != __hal_ip_lro_capable(ip, ext_info))
1098 return XGE_HAL_INF_LRO_END_2;
1099
1100 if (XGE_HAL_OK != __hal_tcp_lro_capable(ip, tcp, lro_match,
1101 &ts_off)) {
1102 /*
1103 * Close the current session and open a new
1104 * LRO session with this packet,
1105 * provided it has tcp payload
1106 */
1107 tcp_seg_len = __hal_tcp_seg_len(ip, tcp);
1108 if (tcp_seg_len == 0)
1109 return XGE_HAL_INF_LRO_END_2;
1110
1111 /* Get a free bucket */
1112 free_slot = __hal_lro_get_free_slot(hldev);
1113 if (free_slot == -1)
1114 return XGE_HAL_INF_LRO_END_2;
1115
1116 /*
1117 * Open a new LRO session
1118 */
1119 __hal_open_lro_session (buffer, ip, tcp, lro_end3,
1120 hldev, free_slot, tcp_seg_len,
1121 ts_off);
1122
1123 return XGE_HAL_INF_LRO_END_3;
1124 }
1125
1126 /*
1127 * The frame is good, in-sequence, can be LRO-ed;
1128 * take its (latest) ACK - unless it is a dupack.
1129 * Note: to be exact need to check window size as well..
1130 */
1131 if (lro_match->tcp_ack_num == tcp->ack_seq &&
1132 lro_match->tcp_seq_num == tcp->seq) {
1133 hldev->stats.sw_dev_info_stats.lro_dup_pkt_cnt++;
1134 return XGE_HAL_INF_LRO_END_2;
1135 }
1136
1137 lro_match->tcp_seq_num = tcp->seq;
1138 lro_match->tcp_ack_num = tcp->ack_seq;
1139 lro_match->frags_len += __hal_tcp_seg_len(ip, tcp);
1140
1141 hldev->lro_recent = lro_match;
1142
1143 return XGE_HAL_INF_LRO_CONT;
1144 }
1145
1146 /* ********** New Session ***************/
1147 if (free_slot == -1)
1148 return XGE_HAL_INF_LRO_UNCAPABLE;
1149
1150 if (XGE_HAL_FAIL == __hal_ip_lro_capable(ip, ext_info))
1151 return XGE_HAL_INF_LRO_UNCAPABLE;
1152
1153 if (XGE_HAL_FAIL == __hal_tcp_lro_capable(ip, tcp, NULL, &ts_off))
1154 return XGE_HAL_INF_LRO_UNCAPABLE;
1155
1156 xge_debug_ring(XGE_TRACE, "Creating lro session.");
1157
1158 /*
1159 * Open a LRO session, provided the packet contains payload.
1160 */
1161 tcp_seg_len = __hal_tcp_seg_len(ip, tcp);
1162 if (tcp_seg_len == 0)
1163 return XGE_HAL_INF_LRO_UNCAPABLE;
1164
1165 __hal_open_lro_session (buffer, ip, tcp, lro, hldev, free_slot,
1166 tcp_seg_len, ts_off);
1167
1168 return XGE_HAL_INF_LRO_BEGIN;
1169 }
1170
1171 /*
1172 * __hal_lro_under_optimal_thresh: Finds whether combined session is optimal.
1173 * @ip: ip header.
1174 * @tcp: tcp header.
1175 * @lro: lro pointer
1176 * @hldev: Hal context.
1177 */
1178 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1179 __hal_lro_under_optimal_thresh (iplro_t *ip,
1180 tcplro_t *tcp,
1181 lro_t *lro,
1182 xge_hal_device_t *hldev)
1183 {
1184 if (!lro) return XGE_HAL_FAIL;
1185
1186 if ((lro->total_length + __hal_tcp_seg_len(ip, tcp) ) >
1187 hldev->config.lro_frm_len) {
1188 xge_debug_ring(XGE_TRACE, "Max LRO frame len exceeded:"
1189 "max length %d \n", hldev->config.lro_frm_len);
1190 hldev->stats.sw_dev_info_stats.lro_frm_len_exceed_cnt++;
1191 return XGE_HAL_FAIL;
1192 }
1193
1194 if (lro->sg_num == hldev->config.lro_sg_size) {
1195 xge_debug_ring(XGE_TRACE, "Max sg count exceeded:"
1196 "max sg %d \n", hldev->config.lro_sg_size);
1197 hldev->stats.sw_dev_info_stats.lro_sg_exceed_cnt++;
1198 return XGE_HAL_FAIL;
1199 }
1200
1201 return XGE_HAL_OK;
1202 }
1203
1204 /*
1205 * __hal_collapse_ip_hdr: Collapses ip header.
1206 * @ip: ip header.
1207 * @tcp: tcp header.
1208 * @lro: lro pointer
1209 * @hldev: Hal context.
1210 */
1211 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1212 __hal_collapse_ip_hdr ( iplro_t *ip,
1213 tcplro_t *tcp,
1214 lro_t *lro,
1215 xge_hal_device_t *hldev)
1216 {
1217
1218 lro->total_length += __hal_tcp_seg_len(ip, tcp);
1219
1220 /* May be we have to handle time stamps or more options */
1221
1222 return XGE_HAL_OK;
1223
1224 }
1225
1226 /*
1227 * __hal_collapse_tcp_hdr: Collapses tcp header.
1228 * @ip: ip header.
1229 * @tcp: tcp header.
1230 * @lro: lro pointer
1231 * @hldev: Hal context.
1232 */
1233 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1234 __hal_collapse_tcp_hdr ( iplro_t *ip,
1235 tcplro_t *tcp,
1236 lro_t *lro,
1237 xge_hal_device_t *hldev)
1238 {
1239 lro->tcp_next_seq_num += __hal_tcp_seg_len(ip, tcp);
1240 return XGE_HAL_OK;
1241
1242 }
1243
1244 /*
1245 * __hal_append_lro: Appends new frame to existing LRO session.
1246 * @ip: ip header.
1247 * @tcp: IN tcp header, OUT tcp payload.
1248 * @seg_len: tcp payload length.
1249 * @lro: lro pointer
1250 * @hldev: Hal context.
1251 */
1252 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1253 __hal_append_lro(iplro_t *ip,
1254 tcplro_t **tcp,
1255 u32 *seg_len,
1256 lro_t *lro,
1257 xge_hal_device_t *hldev)
1258 {
1259 (void) __hal_collapse_ip_hdr(ip, *tcp, lro, hldev);
1260 (void) __hal_collapse_tcp_hdr(ip, *tcp, lro, hldev);
1261 // Update mbuf chain will be done in ll driver.
1262 // xge_hal_accumulate_large_rx on success of appending new frame to
1263 // lro will return to ll driver tcpdata pointer, and tcp payload length.
1264 // along with return code lro frame appended.
1265
1266 lro->sg_num++;
1267 *seg_len = __hal_tcp_seg_len(ip, *tcp);
1268 *tcp = (tcplro_t *)((unsigned long)*tcp + (((*tcp)->doff_res)>>2));
1269
1270 return XGE_HAL_OK;
1271
1272 }
1273
1274 /**
1275 * xge_hal_accumulate_large_rx: LRO a given frame
1276 * frames
1277 * @buffer: Ethernet frame.
1278 * @tcp: tcp header.
1279 * @seglen: packet length.
1280 * @p_lro: lro pointer.
1281 * @ext_info: descriptor info, see xge_hal_dtr_info_t{}.
1282 * @hldev: HAL device.
1283 *
1284 * LRO the newly received frame, i.e. attach it (if possible) to the
1285 * already accumulated (i.e., already LRO-ed) received frames (if any),
1286 * to form one super-sized frame for the subsequent processing
1287 * by the stack.
1288 */
1289 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1290 xge_hal_accumulate_large_rx(u8 *buffer, tcplro_t **tcp, u32 *seglen,
1291 lro_t **p_lro, xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev,
1292 lro_t **lro_end3)
1293 {
1294 iplro_t *ip;
1295 xge_hal_status_e ret;
1296 lro_t *lro;
1297
1298 xge_debug_ring(XGE_TRACE, "Entered accumu lro. ");
1299 if (XGE_HAL_OK != __hal_lro_capable(buffer, &ip, (tcplro_t **)tcp,
1300 ext_info, hldev))
1301 return XGE_HAL_INF_LRO_UNCAPABLE;
1302
1303 /*
1304 * This function shall get matching LRO or else
1305 * create one and return it
1306 */
1307 ret = __hal_get_lro_session(buffer, ip, (tcplro_t *)*tcp,
1308 p_lro, ext_info, hldev, lro_end3);
1309 xge_debug_ring(XGE_TRACE, "ret from get_lro:%d ",ret);
1310 lro = *p_lro;
1311 if (XGE_HAL_INF_LRO_CONT == ret) {
1312 if (XGE_HAL_OK == __hal_lro_under_optimal_thresh(ip,
1313 (tcplro_t *)*tcp, lro, hldev)) {
1314 (void) __hal_append_lro(ip,(tcplro_t **) tcp, seglen,
1315 lro,
1316 hldev);
1317 hldev->stats.sw_dev_info_stats.tot_frms_lroised++;
1318
1319 if (lro->sg_num >= hldev->config.lro_sg_size) {
1320 hldev->stats.sw_dev_info_stats.lro_sg_exceed_cnt++;
1321 ret = XGE_HAL_INF_LRO_END_1;
1322 }
1323
1324 } else ret = XGE_HAL_INF_LRO_END_2;
1325 }
1326
1327 /*
1328 * Since its time to flush,
1329 * update ip header so that it can be sent up
1330 */
1331 if ((ret == XGE_HAL_INF_LRO_END_1) ||
1332 (ret == XGE_HAL_INF_LRO_END_2) ||
1333 (ret == XGE_HAL_INF_LRO_END_3)) {
1334 lro->ip_hdr->tot_len = xge_os_htons((*p_lro)->total_length);
1335 lro->ip_hdr->check = xge_os_htons(0);
1336 lro->ip_hdr->check = XGE_LL_IP_FAST_CSUM(((u8 *)(lro->ip_hdr)),
1337 (lro->ip_hdr->version_ihl & 0x0F));
1338 lro->tcp_hdr->ack_seq = lro->tcp_ack_num;
1339 }
1340
1341 return (ret);
1342 }
1343
1344 /**
1345 * xge_hal_lro_close_session: Close LRO session
1346 * @lro: LRO Session.
1347 * @hldev: HAL Context.
1348 */
1349 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
1350 xge_hal_lro_close_session (lro_t *lro)
1351 {
1352 lro->in_use = 0;
1353 }
1354
1355 /**
1356 * xge_hal_lro_get_next_session: Returns next LRO session in the list or NULL
1357 * if none exists.
1358 * @hldev: Hal context.
1359 */
1360 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t *
1361 xge_hal_lro_get_next_session (xge_hal_device_t *hldev)
1362 {
1363 int i;
1364 int start_idx = hldev->lro_next_idx;
1365
1366 for(i = start_idx; i < XGE_HAL_LRO_MAX_BUCKETS; i++) {
1367 lro_t *lro = &hldev->lro_pool[i];
1368
1369 if (!lro->in_use)
1370 continue;
1371
1372 lro->ip_hdr->tot_len = xge_os_htons(lro->total_length);
1373 lro->ip_hdr->check = xge_os_htons(0);
1374 lro->ip_hdr->check = XGE_LL_IP_FAST_CSUM(((u8 *)(lro->ip_hdr)),
1375 (lro->ip_hdr->version_ihl & 0x0F));
1376 hldev->lro_next_idx = i + 1;
1377 return lro;
1378 }
1379
1380 hldev->lro_next_idx = 0;
1381 return NULL;
1382
1383 }
1384 #endif
--- EOF ---