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_xge_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  * @got_rx: Buffer to return the flag set if receive interrupt is occured
 329  *
 330  * The function polls the Rx channel for the completed  descriptors     and     calls
 331  * the upper-layer driver (ULD) via     supplied completion     callback.
 332  *
 333  * Returns:     XGE_HAL_OK,     if the polling is completed     successful.
 334  * XGE_HAL_COMPLETIONS_REMAIN: There are still more     completed
 335  * descriptors available which are yet to be processed.
 336  *
 337  * See also: xge_hal_device_poll_tx_channel()
 338  */
 339 __HAL_STATIC_DEVICE __HAL_INLINE_DEVICE xge_hal_status_e
 340 xge_hal_device_poll_rx_channel(xge_hal_channel_t *channel, int *got_rx)
 341 {
 342         xge_hal_status_e ret = XGE_HAL_OK;
 343         xge_hal_dtr_h first_dtrh;
 344         xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh;
 345         u8 t_code;
 346         int got_bytes;
 347 
 348         /* for each opened rx channel */
 349         got_bytes = *got_rx = 0;
 350         ((xge_hal_ring_t *)channel)->cmpl_cnt = 0;
 351         channel->poll_bytes = 0;
 352         if ((ret = xge_hal_ring_dtr_next_completed (channel, &first_dtrh,
 353                 &t_code)) == XGE_HAL_OK) {
 354                 if (channel->callback(channel, first_dtrh,
 355                         t_code, channel->userdata) != XGE_HAL_OK) {
 356                         (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1;
 357                         got_bytes += channel->poll_bytes + 1;
 358                         ret = XGE_HAL_COMPLETIONS_REMAIN;
 359                 } else {
 360                         (*got_rx) += ((xge_hal_ring_t *)channel)->cmpl_cnt + 1;
 361                         got_bytes += channel->poll_bytes + 1;
 362                 }
 363         }
 364 
 365         if (*got_rx) {
 366                 hldev->irq_workload_rxd[channel->post_qid] += *got_rx;
 367                 hldev->irq_workload_rxcnt[channel->post_qid] ++;
 368         }
 369         hldev->irq_workload_rxlen[channel->post_qid] += got_bytes;
 370 
 371         return ret;
 372 }
 373 
 374 /**
 375  * xge_hal_device_poll_tx_channel -     Poll Tx channel for     completed
 376  * descriptors and process the same.
 377  * @channel: HAL channel.
 378  * @got_tx: Buffer to return the flag set if transmit interrupt is occured
 379  *
 380  * The function polls the Tx channel for the completed  descriptors     and     calls
 381  * the upper-layer driver (ULD) via     supplied completion     callback.
 382  *
 383  * Returns:     XGE_HAL_OK,     if the polling is completed     successful.
 384  * XGE_HAL_COMPLETIONS_REMAIN: There are still more     completed
 385  * descriptors available which are yet to be processed.
 386  *
 387  * See also: xge_hal_device_poll_rx_channel().
 388  */
 389 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE xge_hal_status_e
 390 xge_hal_device_poll_tx_channel(xge_hal_channel_t *channel, int *got_tx)
 391 {
 392         xge_hal_dtr_h first_dtrh;
 393         xge_hal_device_t *hldev = (xge_hal_device_t *)channel->devh;
 394         u8 t_code;
 395         int got_bytes;
 396 
 397         /* for each opened tx channel */
 398         got_bytes = *got_tx = 0;
 399         channel->poll_bytes = 0;
 400         if (xge_hal_fifo_dtr_next_completed (channel, &first_dtrh,
 401                 &t_code) == XGE_HAL_OK)     {
 402                 if (channel->callback(channel, first_dtrh,
 403                         t_code, channel->userdata) != XGE_HAL_OK) {
 404                         (*got_tx)++;
 405                         got_bytes += channel->poll_bytes + 1;
 406                         return XGE_HAL_COMPLETIONS_REMAIN;
 407                 }
 408                 (*got_tx)++;
 409                 got_bytes += channel->poll_bytes + 1;
 410         }
 411 
 412         if (*got_tx) {
 413                 hldev->irq_workload_txd[channel->post_qid] += *got_tx;
 414                 hldev->irq_workload_txcnt[channel->post_qid] ++;
 415         }
 416         hldev->irq_workload_txlen[channel->post_qid] += got_bytes;
 417 
 418         return XGE_HAL_OK;
 419 }
 420 
 421 /**
 422  * xge_hal_device_poll_rx_channels - Poll Rx channels for completed
 423  * descriptors and process the same.
 424  * @hldev: HAL device handle.
 425  * @got_rx: Buffer to return flag set if receive is ready
 426  *
 427  * The function polls the Rx channels for the completed descriptors     and     calls
 428  * the upper-layer driver (ULD) via     supplied completion     callback.
 429  *
 430  * Returns:     XGE_HAL_OK,     if the polling is completed     successful.
 431  * XGE_HAL_COMPLETIONS_REMAIN: There are still more     completed
 432  * descriptors available which are yet to be processed.
 433  *
 434  * See also: xge_hal_device_poll_tx_channels(), xge_hal_device_continue_irq().
 435  */
 436 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     xge_hal_status_e
 437 xge_hal_device_poll_rx_channels(xge_hal_device_t *hldev, int *got_rx)
 438 {
 439         xge_list_t *item;
 440         xge_hal_channel_t *channel;
 441 
 442         /* for each opened rx channel */
 443         xge_list_for_each(item, &hldev->ring_channels) {
 444                 if (hldev->terminating)
 445                         return XGE_HAL_OK;
 446                 channel = xge_container_of(item, xge_hal_channel_t,     item);

 447                 (void) xge_hal_device_poll_rx_channel(channel, got_rx);
 448         }

 449 
 450         return XGE_HAL_OK;
 451 }
 452 
 453 /**
 454  * xge_hal_device_poll_tx_channels - Poll Tx channels for completed
 455  * descriptors and process the same.
 456  * @hldev: HAL device handle.
 457  * @got_tx: Buffer to return flag set if transmit is ready
 458  *
 459  * The function polls the Tx channels for the completed descriptors     and     calls
 460  * the upper-layer driver (ULD) via     supplied completion     callback.
 461  *
 462  * Returns:     XGE_HAL_OK,     if the polling is completed     successful.
 463  * XGE_HAL_COMPLETIONS_REMAIN: There are still more     completed
 464  * descriptors available which are yet to be processed.
 465  *
 466  * See also: xge_hal_device_poll_rx_channels(), xge_hal_device_continue_irq().
 467  */
 468 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     xge_hal_status_e
 469 xge_hal_device_poll_tx_channels(xge_hal_device_t *hldev, int *got_tx)
 470 {
 471         xge_list_t *item;
 472         xge_hal_channel_t *channel;
 473 
 474         /* for each opened tx channel */
 475         xge_list_for_each(item, &hldev->fifo_channels) {
 476                 if (hldev->terminating)
 477                         return XGE_HAL_OK;
 478                 channel = xge_container_of(item, xge_hal_channel_t, item);
 479                 (void) xge_hal_device_poll_tx_channel(channel, got_tx);
 480         }
 481 
 482         return XGE_HAL_OK;
 483 }
 484 
 485 /**
















 486  * xge_hal_device_mask_tx -     Mask Tx interrupts.
 487  * @hldev: HAL device handle.
 488  *
 489  * Mask Tx device interrupts.
 490  *
 491  * See also: xge_hal_device_unmask_tx(), xge_hal_device_mask_rx(),
 492  * xge_hal_device_clear_tx().
 493  */
 494 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     void
 495 xge_hal_device_mask_tx(xge_hal_device_t *hldev)
 496 {
 497         xge_hal_pci_bar0_t *isrbar0     = (xge_hal_pci_bar0_t *)hldev->isrbar0;
 498 
 499         xge_os_pio_mem_write64(hldev->pdev,  hldev->regh0,
 500                                    0xFFFFFFFFFFFFFFFFULL,
 501                                    &isrbar0->tx_traffic_mask);
 502 }
 503 
 504 /**
 505  * xge_hal_device_mask_rx -     Mask Rx interrupts.
 506  * @hldev: HAL device handle.
 507  *
 508  * Mask Rx device interrupts.
 509  *
 510  * See also: xge_hal_device_unmask_rx(), xge_hal_device_mask_tx(),
 511  * xge_hal_device_clear_rx().
 512  */
 513 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     void
 514 xge_hal_device_mask_rx(xge_hal_device_t *hldev)
 515 {
 516         xge_hal_pci_bar0_t *isrbar0     = (xge_hal_pci_bar0_t *)hldev->isrbar0;
 517 
 518         xge_os_pio_mem_write64(hldev->pdev,  hldev->regh0,
 519                                    0xFFFFFFFFFFFFFFFFULL,
 520                                    &isrbar0->rx_traffic_mask);
 521 }
 522 
 523 /**
 524  * xge_hal_device_mask_all - Mask all device interrupts.
 525  * @hldev: HAL device handle.
 526  *
 527  * Mask all     device interrupts.
 528  *
 529  * See also: xge_hal_device_unmask_all()
 530  */
 531 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     void
 532 xge_hal_device_mask_all(xge_hal_device_t *hldev)
 533 {
 534         xge_hal_pci_bar0_t *isrbar0     = (xge_hal_pci_bar0_t *)hldev->isrbar0;
 535 
 536         xge_os_pio_mem_write64(hldev->pdev,  hldev->regh0,
 537                                    0xFFFFFFFFFFFFFFFFULL,
 538                                    &isrbar0->general_int_mask);
 539 }
 540 
 541 /**
 542  * xge_hal_device_unmask_tx     - Unmask Tx     interrupts.
 543  * @hldev: HAL device handle.
 544  *
 545  * Unmask Tx device     interrupts.
 546  *
 547  * See also: xge_hal_device_mask_tx(), xge_hal_device_clear_tx().
 548  */
 549 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     void
 550 xge_hal_device_unmask_tx(xge_hal_device_t *hldev)
 551 {
 552         xge_hal_pci_bar0_t *isrbar0     = (xge_hal_pci_bar0_t *)hldev->isrbar0;
 553 
 554         xge_os_pio_mem_write64(hldev->pdev,  hldev->regh0,
 555                                    0x0ULL,
 556                                    &isrbar0->tx_traffic_mask);
 557 }
 558 
 559 /**
 560  * xge_hal_device_unmask_rx     - Unmask Rx     interrupts.
 561  * @hldev: HAL device handle.
 562  *
 563  * Unmask Rx device     interrupts.
 564  *
 565  * See also: xge_hal_device_mask_rx(), xge_hal_device_clear_rx().
 566  */
 567 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     void
 568 xge_hal_device_unmask_rx(xge_hal_device_t *hldev)
 569 {
 570         xge_hal_pci_bar0_t *isrbar0     = (xge_hal_pci_bar0_t *)hldev->isrbar0;
 571 
 572         xge_os_pio_mem_write64(hldev->pdev,  hldev->regh0,
 573                                    0x0ULL,
 574                                    &isrbar0->rx_traffic_mask);
 575 }
 576 
 577 /**
 578  * xge_hal_device_unmask_all - Unmask all device interrupts.
 579  * @hldev: HAL device handle.
 580  *
 581  * Unmask all device interrupts.
 582  *
 583  * See also: xge_hal_device_mask_all()
 584  */
 585 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     void
 586 xge_hal_device_unmask_all(xge_hal_device_t *hldev)
 587 {
 588         xge_hal_pci_bar0_t *isrbar0     = (xge_hal_pci_bar0_t *)hldev->isrbar0;
 589 
 590         xge_os_pio_mem_write64(hldev->pdev,  hldev->regh0,
 591                                    0x0ULL,
 592                                    &isrbar0->general_int_mask);
 593 }
 594 
 595 
 596 /**
 597  * xge_hal_device_continue_irq - Continue handling IRQ: process all
 598  * completed descriptors.
 599  * @hldev: HAL device handle.
 600  *
 601  * Process completed descriptors and unmask     the     device interrupts.
 602  *
 603  * The xge_hal_device_continue_irq() walks all open     channels
 604  * and calls upper-layer driver (ULD) via supplied completion
 605  * callback. Note that the completion callback is specified     at channel open
 606  * time, see xge_hal_channel_open().
 607  *
 608  * Note that the xge_hal_device_continue_irq is part of the     _fast_ path.
 609  * To optimize the processing, the function     does _not_ check for
 610  * errors and alarms.
 611  *
 612  * The latter is done in a polling fashion,     via     xge_hal_device_poll().
 613  *
 614  * Returns:     XGE_HAL_OK.
 615  *
 616  * See also: xge_hal_device_handle_irq(), xge_hal_device_poll(),
 617  * xge_hal_ring_dtr_next_completed(),
 618  * xge_hal_fifo_dtr_next_completed(), xge_hal_channel_callback_f{}.
 619  */
 620 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     xge_hal_status_e
 621 xge_hal_device_continue_irq(xge_hal_device_t *hldev)
 622 {
 623         int     got_rx = 1,     got_tx = 1;
 624         int     isr_polling_cnt = hldev->config.isr_polling_cnt;
 625         int     count = 0;
 626 
 627         do
 628         {
 629                 if (got_rx)
 630                         (void) xge_hal_device_poll_rx_channels(hldev, &got_rx);
 631                 if (got_tx && hldev->tti_enabled)
 632                         (void) xge_hal_device_poll_tx_channels(hldev, &got_tx);
 633 
 634                 if (!got_rx && !got_tx)
 635                         break;
 636 
 637                 count += (got_rx + got_tx);
 638         }while (isr_polling_cnt--);
 639 
 640         if (!count)
 641                 hldev->stats.sw_dev_info_stats.not_traffic_intr_cnt++;
 642 
 643         return XGE_HAL_OK;
 644 }
 645 
 646 /**
 647  * xge_hal_device_handle_irq - Handle device IRQ.
 648  * @hldev: HAL device handle.
 649  *
 650  * Perform the complete handling of     the     line interrupt. The     function
 651  * performs     two     calls.
 652  * First it     uses xge_hal_device_begin_irq() to      check the reason for
 653  * the interrupt and mask the device interrupts.
 654  * Second, it calls     xge_hal_device_continue_irq() to process all
 655  * completed descriptors and re-enable the interrupts.
 656  *
 657  * Returns:     XGE_HAL_OK - success;
 658  * XGE_HAL_ERR_WRONG_IRQ - (shared)     IRQ     produced by     other device.
 659  *
 660  * See also: xge_hal_device_begin_irq(), xge_hal_device_continue_irq().
 661  */
 662 __HAL_STATIC_DEVICE     __HAL_INLINE_DEVICE     xge_hal_status_e
 663 xge_hal_device_handle_irq(xge_hal_device_t *hldev)
 664 {
 665         u64     reason;
 666         xge_hal_status_e status;
 667 
 668         xge_hal_device_mask_all(hldev);
 669 
 670         status = xge_hal_device_begin_irq(hldev, &reason);
 671         if (status != XGE_HAL_OK) {
 672                 xge_hal_device_unmask_all(hldev);
 673                 return status;
 674         }
 675 
 676         if (reason & XGE_HAL_GEN_INTR_RXTRAFFIC) {
 677                 xge_hal_device_clear_rx(hldev);
 678         }
 679 
 680         status = xge_hal_device_continue_irq(hldev);
 681 
 682         xge_hal_device_clear_tx(hldev);
 683 
 684         xge_hal_device_unmask_all(hldev);
 685 
 686         return status;
 687 }
 688 
 689 #if     defined(XGE_HAL_CONFIG_LRO)
 690 
 691 
 692 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
 693 __hal_lro_check_for_session_match(lro_t *lro, tcplro_t *tcp, iplro_t *ip)
 694 {
 695 
 696         /* Match Source address field */
 697         if ((lro->ip_hdr->saddr   != ip->saddr))
 698                 return XGE_HAL_FAIL;
 699 
 700         /* Match Destination address field */
 701         if ((lro->ip_hdr->daddr   != ip->daddr))
 702                 return XGE_HAL_FAIL;
 703 
 704         /* Match Source Port field */
 705         if ((lro->tcp_hdr->source != tcp->source))
 706                 return XGE_HAL_FAIL;
 707 
 708         /* Match Destination Port field */
 709         if ((lro->tcp_hdr->dest   != tcp->dest))
 710                 return XGE_HAL_FAIL;
 711                 
 712         return XGE_HAL_OK;
 713 }
 714 
 715 /*
 716  * __hal_tcp_seg_len: Find the tcp seg len.
 717  * @ip: ip header.
 718  * @tcp: tcp header.
 719  * returns:     Tcp     seg     length.
 720  */
 721 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL u16
 722 __hal_tcp_seg_len(iplro_t *ip, tcplro_t *tcp)
 723 {
 724         u16     ret;
 725 
 726         ret     =  (xge_os_ntohs(ip->tot_len) -
 727                    ((ip->version_ihl & 0x0F)<<2) -
 728                    ((tcp->doff_res)>>2));
 729         return (ret);
 730 }
 731 
 732 /*
 733  * __hal_ip_lro_capable: Finds whether ip is lro capable.
 734  * @ip: ip header.
 735  * @ext_info:  descriptor info.
 736  */
 737 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
 738 __hal_ip_lro_capable(iplro_t *ip,
 739                          xge_hal_dtr_info_t     *ext_info)
 740 {
 741 
 742 #ifdef XGE_LL_DEBUG_DUMP_PKT
 743                 {
 744                         u16     i;
 745                         u8 ch, *iph     = (u8 *)ip;
 746 
 747                         xge_debug_ring(XGE_TRACE, "Dump Ip:" );
 748                         for     (i =0; i < 40; i++)  {
 749                                 ch = ntohs(*((u8 *)(iph + i)) );
 750                                 printf("i:%d %02x, ",i,ch);
 751                         }
 752                 }
 753 #endif
 754 
 755         if (ip->version_ihl  != IP_FAST_PATH_HDR_MASK) {
 756                 xge_debug_ring(XGE_ERR, "iphdr !=45     :%d",ip->version_ihl);
 757                 return XGE_HAL_FAIL;
 758         }
 759 
 760         if (ext_info->proto  & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED) {
 761                 xge_debug_ring(XGE_ERR, "IP     fragmented");
 762                 return XGE_HAL_FAIL;
 763         }
 764 
 765         return XGE_HAL_OK;
 766 }
 767 
 768 /*
 769  * __hal_tcp_lro_capable: Finds whether tcp     is lro capable.
 770  * @ip: ip header.
 771  * @tcp: tcp header.
 772  */
 773 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
 774 __hal_tcp_lro_capable(iplro_t *ip, tcplro_t     *tcp, lro_t     *lro, int *ts_off)
 775 {
 776 #ifdef XGE_LL_DEBUG_DUMP_PKT
 777                 {
 778                         u8 ch;
 779                         u16     i;
 780 
 781                         xge_debug_ring(XGE_TRACE, "Dump Tcp:" );
 782                         for     (i =0; i < 20; i++)  {
 783                                 ch = ntohs(*((u8 *)((u8 *)tcp + i))     );
 784                                 xge_os_printf("i:%d     %02x, ",i,ch);
 785                         }
 786                 }
 787 #endif
 788         if ((TCP_FAST_PATH_HDR_MASK2 != tcp->ctrl) &&
 789                 (TCP_FAST_PATH_HDR_MASK3 !=     tcp->ctrl))
 790                 goto _exit_fail;
 791 
 792         *ts_off = -1;
 793         if (TCP_FAST_PATH_HDR_MASK1     != tcp->doff_res) {
 794                 u16     tcp_hdr_len     = tcp->doff_res      >> 2; /* TCP header       len     */
 795                 u16     off     = 20; /* Start of tcp options */
 796                 int     i, diff; 
 797 
 798                 /* Does Packet can contain time stamp */
 799                 if (tcp_hdr_len < 32) {
 800                         /*
 801                          * If the session is not opened, we     can     consider
 802                          * this packet for LRO
 803                          */
 804                         if (lro == NULL)
 805                                 return XGE_HAL_OK;
 806 
 807                         goto _exit_fail;
 808                 }
 809 
 810                 /* Ignore No-operation 0x1 */
 811                 while (((u8     *)tcp)[off]     == 0x1)
 812                         off++;
 813 
 814                 /* Next option == Timestamp     */
 815                 if (((u8 *)tcp)[off] != 0x8) {
 816                         /*
 817                          * If the session ie not opened, we     can     consider
 818                          * this packet for LRO
 819                          */
 820                         if (lro == NULL)
 821                                 return XGE_HAL_OK;
 822 
 823                         goto _exit_fail;
 824                 }
 825 
 826                 *ts_off = off;
 827                 if (lro == NULL)
 828                         return XGE_HAL_OK;
 829 
 830                 /*
 831                  * Now the session is opened. If the LRO frame doesn't
 832                  * have time stamp,     we cannot consider current packet for
 833                  * LRO.
 834                  */
 835                 if (lro->ts_off      == -1) {
 836                         xge_debug_ring(XGE_ERR, "Pkt received with time stamp after     session opened with     no time stamp : %02x %02x", tcp->doff_res, tcp->ctrl);
 837                         return XGE_HAL_FAIL;
 838                 }
 839 
 840                 /*
 841                  * If the difference is greater than three,     then there are
 842                  * more options possible.
 843                  * else, there are two cases:
 844                  * case 1: remaining are padding bytes.
 845                  * case 2: remaining can contain options or     padding
 846                  */
 847                 off     += ((u8 *)tcp)[off+1];
 848                 diff = tcp_hdr_len - off;
 849                 if (diff > 3) {
 850                         /*
 851                          * Probably     contains more options.
 852                          */
 853                         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     ", tcp->doff_res,    tcp->ctrl);
 854                         return XGE_HAL_FAIL;
 855                 }
 856 
 857                 for     (i = 0; i <  diff; i++) {
 858                         u8 byte = ((u8 *)tcp)[off+i];
 859 
 860                         /* Ignore No-operation 0x1 */
 861                         if ((byte == 0x0) || (byte == 0x1))     
 862                                 continue;
 863                         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     ", tcp->doff_res,    tcp->ctrl);
 864                         return XGE_HAL_FAIL;
 865                 }
 866         
 867                 /*
 868                  * Update the time stamp of     LRO     frame.
 869                  */
 870                 xge_os_memcpy(((char *)lro->tcp_hdr  + lro->ts_off +      2),
 871                                 (char *)((char *)tcp + (*ts_off) + 2), 8);
 872         }
 873 
 874         return XGE_HAL_OK;
 875 
 876 _exit_fail:
 877         xge_debug_ring(XGE_TRACE,       "tcphdr not     fastpth %02x %02x", tcp->doff_res, tcp->ctrl);
 878         return XGE_HAL_FAIL;
 879 
 880 }
 881 
 882 /*
 883  * __hal_lro_capable: Finds     whether frame is lro capable.
 884  * @buffer:     Ethernet frame.
 885  * @ip: ip frame.
 886  * @tcp: tcp frame.
 887  * @ext_info: Descriptor info.

 888  */
 889 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
 890 __hal_lro_capable( u8 *buffer,
 891                    iplro_t **ip,
 892                    tcplro_t     **tcp,
 893        xge_hal_dtr_info_t *ext_info)

 894 {
 895         u8 ip_off, ip_length;
 896 
 897         if (!(ext_info->proto &  XGE_HAL_FRAME_PROTO_TCP)) {
 898                 xge_debug_ring(XGE_ERR, "Cant do lro %d", ext_info->proto);
 899                 return XGE_HAL_FAIL;
 900         }
 901 
 902   if ( !*ip )
 903   {
 904 #ifdef XGE_LL_DEBUG_DUMP_PKT
 905                 {
 906                         u8 ch;
 907                         u16     i;
 908 
 909                         xge_os_printf("Dump     Eth:" );
 910                         for     (i =0; i < 60; i++)  {
 911                                 ch = ntohs(*((u8 *)(buffer + i)) );
 912                                 xge_os_printf("i:%d     %02x, ",i,ch);
 913                         }
 914                 }
 915 #endif
 916 
 917     switch (ext_info->frame) {
 918     case XGE_HAL_FRAME_TYPE_DIX:
 919       ip_off = XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE;
 920       break;
 921     case XGE_HAL_FRAME_TYPE_LLC:
 922       ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE   +
 923                 XGE_HAL_HEADER_802_2_SIZE);
 924       break;
 925     case XGE_HAL_FRAME_TYPE_SNAP:
 926       ip_off = (XGE_HAL_HEADER_ETHERNET_II_802_3_SIZE   +
 927                 XGE_HAL_HEADER_SNAP_SIZE);
 928       break;
 929     default: // XGE_HAL_FRAME_TYPE_IPX, etc.
 930       return XGE_HAL_FAIL;
 931     }
 932 
 933 
 934     if (ext_info->proto      & XGE_HAL_FRAME_PROTO_VLAN_TAGGED) {
 935       ip_off += XGE_HAL_HEADER_VLAN_SIZE;
 936     }
 937 
 938     /* Grab     ip,     tcp     headers */
 939     *ip = (iplro_t *)((char*)buffer     + ip_off);
 940   } /* !*ip */
 941 
 942         ip_length =     (u8)((*ip)->version_ihl      & 0x0F);
 943         ip_length =     ip_length <<2;
 944         *tcp = (tcplro_t *)((char *)*ip + ip_length);
 945 
 946         xge_debug_ring(XGE_TRACE, "ip_length:%d ip:"XGE_OS_LLXFMT
 947                    " tcp:"XGE_OS_LLXFMT"", (int)ip_length,
 948                 (unsigned long long)(ulong_t)*ip, (unsigned long long)(ulong_t)*tcp);
 949 
 950         return XGE_HAL_OK;
 951 
 952 }
 953 
 954 
 955 /*
 956  * __hal_open_lro_session: Open a new LRO session.
 957  * @buffer:     Ethernet frame.
 958  * @ip: ip header.
 959  * @tcp: tcp header.
 960  * @lro: lro pointer
 961  * @ext_info: Descriptor info.
 962  * @hldev: Hal context.
 963  * @ring_lro: LRO descriptor per rx ring.
 964  * @slot: Bucket no.
 965  * @tcp_seg_len: Length of tcp segment.
 966  * @ts_off:     time stamp offset in the packet.
 967  */
 968 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
 969 __hal_open_lro_session (u8 *buffer,     iplro_t *ip, tcplro_t *tcp,     lro_t **lro,
 970                         xge_hal_device_t *hldev, xge_hal_lro_desc_t     *ring_lro, int slot,
 971       u32 tcp_seg_len, int      ts_off)
 972 {
 973 
 974         lro_t *lro_new = &ring_lro->lro_pool[slot];
 975 
 976         lro_new->in_use                      =       1;
 977         lro_new->ll_hdr                      =       buffer;
 978         lro_new->ip_hdr                      =       ip;
 979         lro_new->tcp_hdr             =       tcp;
 980         lro_new->tcp_next_seq_num    =       tcp_seg_len     + xge_os_ntohl(
 981                                                                 tcp->seq);
 982         lro_new->tcp_seq_num         =       tcp->seq;
 983         lro_new->tcp_ack_num         =       tcp->ack_seq;
 984         lro_new->sg_num                      =       1;
 985         lro_new->total_length                =       xge_os_ntohs(ip->tot_len);
 986         lro_new->frags_len           =       0;
 987         lro_new->ts_off                      =       ts_off;
 988 
 989         hldev->stats.sw_dev_info_stats.tot_frms_lroised++;
 990         hldev->stats.sw_dev_info_stats.tot_lro_sessions++;
 991 
 992         *lro = ring_lro->lro_recent = lro_new;
 993         return;
 994 }

 995 /*
 996  * __hal_lro_get_free_slot:     Get     a free LRO bucket.
 997  * @ring_lro: LRO descriptor per ring.
 998  */
 999 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL int
1000 __hal_lro_get_free_slot (xge_hal_lro_desc_t     *ring_lro)
1001 {
1002         int     i;
1003 
1004         for     (i = 0; i <  XGE_HAL_LRO_MAX_BUCKETS; i++) {
1005                 lro_t *lro_temp = &ring_lro->lro_pool[i];
1006 
1007                 if (!lro_temp->in_use)
1008                         return i;
1009         }
1010         return -1;      
1011 }
1012 
1013 /*
1014  * __hal_get_lro_session: Gets matching LRO     session or creates one.
1015  * @eth_hdr:    Ethernet header.
1016  * @ip: ip header.
1017  * @tcp: tcp header.
1018  * @lro: lro pointer
1019  * @ext_info: Descriptor info.
1020  * @hldev: Hal context.
1021  * @ring_lro: LRO descriptor per rx ring
1022  */
1023 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1024 __hal_get_lro_session (u8 *eth_hdr,
1025                            iplro_t *ip,
1026                            tcplro_t     *tcp,
1027                            lro_t **lro,
1028                            xge_hal_dtr_info_t *ext_info,
1029                            xge_hal_device_t     *hldev,
1030                            xge_hal_lro_desc_t   *ring_lro,
1031                            lro_t **lro_end3     /* Valid only when ret=END_3 */)
1032 {
1033         lro_t *lro_match;
1034         int     i, free_slot = -1;
1035         u32     tcp_seg_len;
1036         int     ts_off = -1;
1037 
1038         *lro = lro_match = NULL;
1039         /*
1040          * Compare the incoming frame with the lro session left from the 
1041          * previous     call.  There is a good chance that this incoming frame
1042          * matches the lro session.
1043          */
1044         if (ring_lro->lro_recent && ring_lro->lro_recent->in_use)      {
1045                 if (__hal_lro_check_for_session_match(ring_lro->lro_recent,
1046                                                           tcp, ip)
1047                                                         == XGE_HAL_OK)
1048                         lro_match =     ring_lro->lro_recent;
1049         }
1050         
1051         if (!lro_match) {
1052                 /*
1053                  * Search in the pool of LROs for the session that matches 
1054                  * the incoming frame.
1055                  */
1056                 for     (i = 0; i <  XGE_HAL_LRO_MAX_BUCKETS; i++) {
1057                         lro_t *lro_temp = &ring_lro->lro_pool[i];
1058 
1059                         if (!lro_temp->in_use) {
1060                                 if (free_slot == -1)
1061                                         free_slot =     i;
1062                                 continue;
1063                         }       
1064 
1065                         if (__hal_lro_check_for_session_match(lro_temp, tcp,
1066                                                           ip) == XGE_HAL_OK) {
1067                                 lro_match =     lro_temp;
1068                                 break;
1069                         }
1070                 }
1071         }
1072 
1073         
1074         if (lro_match) {
1075                 /*
1076                  * Matching     LRO     Session found
1077                  */                     
1078                 *lro = lro_match;
1079 
1080                 if (lro_match->tcp_next_seq_num      != xge_os_ntohl(tcp->seq)) {
1081      xge_debug_ring(XGE_ERR,    "**retransmit  **"
1082                                                 "found***");
1083                         hldev->stats.sw_dev_info_stats.lro_out_of_seq_pkt_cnt++;
1084                         return XGE_HAL_INF_LRO_END_2;
1085                 }
1086 
1087                 if (XGE_HAL_OK != __hal_ip_lro_capable(ip, ext_info))
1088     {
1089                         return XGE_HAL_INF_LRO_END_2;
1090     }
1091 
1092                 if (XGE_HAL_OK != __hal_tcp_lro_capable(ip,     tcp, lro_match,
1093                                                         &ts_off)) {
1094                         /*
1095                          * Close the current session and open a new
1096                          * LRO session with     this packet,
1097                          * provided     it has tcp payload
1098                          */     
1099                         tcp_seg_len     = __hal_tcp_seg_len(ip, tcp);
1100                         if (tcp_seg_len == 0)
1101       {
1102                                 return XGE_HAL_INF_LRO_END_2;
1103       }
1104 
1105                         /* Get a free bucket  */
1106                         free_slot =     __hal_lro_get_free_slot(ring_lro);
1107                         if (free_slot == -1)
1108       {
1109                                 return XGE_HAL_INF_LRO_END_2;
1110       }
1111 
1112                         /* 
1113                          * Open a new LRO session
1114                          */
1115                         __hal_open_lro_session (eth_hdr,        ip,     tcp, lro_end3,
1116                                                 hldev, ring_lro, free_slot, tcp_seg_len,
1117                                                 ts_off);
1118 
1119                         return XGE_HAL_INF_LRO_END_3;
1120                 }
1121 
1122                                 /*
1123                  * The frame is good, in-sequence, can be LRO-ed;
1124                  * take its     (latest) ACK - unless it is     a dupack.
1125                  * Note: to     be exact need to check window size as well..
1126                 */
1127                 if (lro_match->tcp_ack_num == tcp->ack_seq &&
1128                         lro_match->tcp_seq_num == tcp->seq)       {
1129                         hldev->stats.sw_dev_info_stats.lro_dup_pkt_cnt++;
1130                         return XGE_HAL_INF_LRO_END_2;
1131                 }
1132 
1133                 lro_match->tcp_seq_num = tcp->seq;
1134                 lro_match->tcp_ack_num = tcp->ack_seq;
1135                 lro_match->frags_len +=      __hal_tcp_seg_len(ip, tcp);
1136 
1137                 ring_lro->lro_recent =       lro_match;
1138         
1139                 return XGE_HAL_INF_LRO_CONT;
1140         }
1141 
1142         /* ********** New Session ***************/
1143         if (free_slot == -1)
1144                 return XGE_HAL_INF_LRO_UNCAPABLE;
1145         
1146         if (XGE_HAL_FAIL ==     __hal_ip_lro_capable(ip, ext_info))
1147                 return XGE_HAL_INF_LRO_UNCAPABLE;
1148 
1149         if (XGE_HAL_FAIL ==     __hal_tcp_lro_capable(ip, tcp, NULL, &ts_off))
1150                 return XGE_HAL_INF_LRO_UNCAPABLE;
1151                 
1152         xge_debug_ring(XGE_TRACE, "Creating     lro     session.");
1153 
1154         /*
1155          * Open a LRO session, provided the     packet contains payload.
1156          */
1157         tcp_seg_len     = __hal_tcp_seg_len(ip, tcp);
1158         if (tcp_seg_len == 0)
1159                 return XGE_HAL_INF_LRO_UNCAPABLE;
1160 
1161         __hal_open_lro_session (eth_hdr,        ip,     tcp, lro, hldev, ring_lro, free_slot,
1162                                 tcp_seg_len, ts_off);
1163 
1164         return XGE_HAL_INF_LRO_BEGIN;
1165 }
1166 
1167 /*
1168  * __hal_lro_under_optimal_thresh: Finds whether combined session is optimal.
1169  * @ip: ip header.
1170  * @tcp: tcp header.
1171  * @lro: lro pointer
1172  * @hldev: Hal context.
1173  */
1174 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1175 __hal_lro_under_optimal_thresh (iplro_t *ip,
1176                                         tcplro_t *tcp,
1177                                 lro_t *lro,
1178                                 xge_hal_device_t *hldev)
1179 {
1180         if (!lro) return XGE_HAL_FAIL;
1181 
1182         if ((lro->total_length + __hal_tcp_seg_len(ip, tcp)  ) >  
1183                                                 hldev->config.lro_frm_len) {
1184                 xge_debug_ring(XGE_TRACE, "Max LRO frame len exceeded:"
1185                  "max length %d ", hldev->config.lro_frm_len);
1186                 hldev->stats.sw_dev_info_stats.lro_frm_len_exceed_cnt++;
1187                 return XGE_HAL_FAIL;
1188         }
1189 
1190         if (lro->sg_num      == hldev->config.lro_sg_size) {
1191                 xge_debug_ring(XGE_TRACE, "Max sg count exceeded:"
1192                                  "max sg %d     ", hldev->config.lro_sg_size);
1193                 hldev->stats.sw_dev_info_stats.lro_sg_exceed_cnt++;
1194                 return XGE_HAL_FAIL;
1195         }
1196 
1197         return XGE_HAL_OK;
1198 }
1199 
1200 /*
1201  * __hal_collapse_ip_hdr: Collapses     ip header.
1202  * @ip: ip header.
1203  * @tcp: tcp header.
1204  * @lro: lro pointer
1205  * @hldev: Hal context.
1206  */
1207 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1208 __hal_collapse_ip_hdr ( iplro_t *ip,
1209                         tcplro_t *tcp,
1210                         lro_t *lro,
1211                         xge_hal_device_t *hldev)
1212 {
1213 
1214         lro->total_length += __hal_tcp_seg_len(ip, tcp);
1215 
1216         /* May be we have to handle     time stamps     or more options */
1217 
1218         return XGE_HAL_OK;
1219 
1220 }
1221 
1222 /*
1223  * __hal_collapse_tcp_hdr: Collapses tcp header.
1224  * @ip: ip header.
1225  * @tcp: tcp header.
1226  * @lro: lro pointer
1227  * @hldev: Hal context.
1228  */
1229 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1230 __hal_collapse_tcp_hdr ( iplro_t *ip,
1231                          tcplro_t *tcp,
1232                          lro_t *lro,
1233                          xge_hal_device_t *hldev)
1234 {
1235         lro->tcp_next_seq_num += __hal_tcp_seg_len(ip, tcp);
1236         return XGE_HAL_OK;
1237 
1238 }
1239 
1240 /*
1241  * __hal_append_lro: Appends new frame to existing LRO session.
1242  * @ip: ip header.
1243  * @tcp: IN     tcp     header, OUT     tcp     payload.
1244  * @seg_len: tcp payload length.
1245  * @lro: lro pointer
1246  * @hldev: Hal context.
1247  */
1248 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1249 __hal_append_lro(iplro_t *ip,
1250                  tcplro_t **tcp,
1251                  u32 *seg_len,
1252                  lro_t *lro,
1253                  xge_hal_device_t *hldev)
1254 {
1255         (void) __hal_collapse_ip_hdr(ip, *tcp,  lro, hldev);
1256         (void) __hal_collapse_tcp_hdr(ip, *tcp, lro, hldev);
1257         // Update mbuf chain will be done in ll driver.
1258         // xge_hal_accumulate_large_rx on success of appending new frame to
1259         // lro will     return to ll driver     tcpdata pointer, and tcp payload length.
1260         // along with return code lro frame     appended.
1261 
1262         lro->sg_num++;
1263         *seg_len = __hal_tcp_seg_len(ip, *tcp);
1264         *tcp = (tcplro_t *)((char *)*tcp        + (((*tcp)->doff_res)>>2));
1265 
1266         return XGE_HAL_OK;
1267 
1268 }
1269 
1270 /**
1271  * __xge_hal_accumulate_large_rx:       LRO     a given frame
1272  * frames
1273  * @ring: rx ring number
1274  * @eth_hdr: ethernet header.
1275  * @ip_hdr: ip header (optional)
1276  * @tcp: tcp header.
1277  * @seglen:     packet length.
1278  * @p_lro: lro pointer.
1279  * @ext_info: descriptor info, see xge_hal_dtr_info_t{}.
1280  * @hldev: HAL device.
1281  * @lro_end3: for lro_end3 output
1282  *
1283  * LRO the newly received frame, i.e. attach it (if     possible) to the
1284  * already accumulated (i.e., already LRO-ed) received frames (if any),
1285  * to form one super-sized frame for the subsequent     processing
1286  * by the stack.
1287  */
1288 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1289 xge_hal_lro_process_rx(int ring, u8 *eth_hdr, u8 *ip_hdr, tcplro_t **tcp,
1290                        u32 *seglen, lro_t **p_lro,
1291                        xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev,
1292                        lro_t **lro_end3)
1293 {
1294         iplro_t *ip = (iplro_t *)ip_hdr;
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(eth_hdr, &ip, (tcplro_t **)tcp,
1300                                       ext_info))
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(eth_hdr, ip, (tcplro_t *)*tcp,
1308                               p_lro, ext_info, hldev,   &hldev->lro_desc[ring],
1309                               lro_end3);
1310         xge_debug_ring(XGE_TRACE, "ret from get_lro:%d ",ret);
1311         lro = *p_lro;
1312         if (XGE_HAL_INF_LRO_CONT == ret) {
1313                 if (XGE_HAL_OK == __hal_lro_under_optimal_thresh(ip,
1314                                                 (tcplro_t *)*tcp, lro, hldev)) {
1315                         (void) __hal_append_lro(ip,(tcplro_t **) tcp, seglen,
1316                                                          lro, 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_accumulate_large_rx: LRO     a given frame
1346  * frames
1347  * @buffer:     Ethernet frame.
1348  * @tcp: tcp header.
1349  * @seglen:     packet length.
1350  * @p_lro: lro pointer.
1351  * @ext_info: descriptor info, see xge_hal_dtr_info_t{}.
1352  * @hldev: HAL device.
1353  * @lro_end3: for lro_end3 output
1354  *
1355  * LRO the newly received frame, i.e. attach it (if     possible) to the
1356  * already accumulated (i.e., already LRO-ed) received frames (if any),
1357  * to form one super-sized frame for the subsequent     processing
1358  * by the stack.
1359  */
1360 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL xge_hal_status_e
1361 xge_hal_accumulate_large_rx(u8 *buffer, tcplro_t **tcp, u32 *seglen,
1362 lro_t **p_lro, xge_hal_dtr_info_t *ext_info, xge_hal_device_t *hldev,
1363 lro_t **lro_end3)
1364 {
1365   int ring = 0;
1366   return xge_hal_lro_process_rx(ring, buffer, NULL, tcp, seglen, p_lro,
1367                                 ext_info, hldev, lro_end3);
1368 }
1369 
1370 /**
1371  * xge_hal_lro_close_session: Close LRO session
1372  * @lro: LRO Session.
1373  * @hldev: HAL Context.
1374  */
1375 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL void
1376 xge_hal_lro_close_session (lro_t *lro)
1377 {
1378         lro->in_use = 0;
1379 }
1380 
1381 /**
1382  * xge_hal_lro_next_session: Returns next LRO session in the list or NULL
1383  *                                      if none exists.
1384  * @hldev: HAL Context.
1385  * @ring: rx ring number.
1386  */
1387 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t *
1388 xge_hal_lro_next_session (xge_hal_device_t *hldev, int ring)
1389 {
1390 xge_hal_lro_desc_t *ring_lro = &hldev->lro_desc[ring];
1391         int     i;
1392         int     start_idx =     ring_lro->lro_next_idx;
1393 
1394         for(i = start_idx; i < XGE_HAL_LRO_MAX_BUCKETS;      i++) {
1395                 lro_t *lro = &ring_lro->lro_pool[i];
1396 
1397                 if (!lro->in_use)
1398                         continue;
1399 
1400                 lro->ip_hdr->tot_len = xge_os_htons(lro->total_length);
1401                 lro->ip_hdr->check = xge_os_htons(0);
1402                 lro->ip_hdr->check = XGE_LL_IP_FAST_CSUM(((u8 *)(lro->ip_hdr)),
1403                                                                 (lro->ip_hdr->version_ihl &   0x0F));
1404                 ring_lro->lro_next_idx       = i     + 1;
1405                 return lro;
1406         }
1407 
1408         ring_lro->lro_next_idx       = 0;
1409         return NULL;
1410 
1411 }
1412 
1413 __HAL_STATIC_CHANNEL __HAL_INLINE_CHANNEL lro_t *
1414 xge_hal_lro_get_next_session(xge_hal_device_t *hldev)
1415 {
1416   int ring = 0; /* assume default ring=0 */
1417   return xge_hal_lro_next_session(hldev, ring);
1418 }
1419 #endif
--- EOF ---