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