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 ---