diff options
Diffstat (limited to 'usr/src/uts/common/io/xge/drv/xgell.c')
-rw-r--r-- | usr/src/uts/common/io/xge/drv/xgell.c | 358 |
1 files changed, 201 insertions, 157 deletions
diff --git a/usr/src/uts/common/io/xge/drv/xgell.c b/usr/src/uts/common/io/xge/drv/xgell.c index e9b8885d89..a153880f13 100644 --- a/usr/src/uts/common/io/xge/drv/xgell.c +++ b/usr/src/uts/common/io/xge/drv/xgell.c @@ -40,6 +40,7 @@ #include <netinet/ip.h> #include <netinet/tcp.h> +#include <netinet/udp.h> #define XGELL_MAX_FRAME_SIZE(hldev) ((hldev)->config.mtu + \ sizeof (struct ether_vlan_header)) @@ -62,7 +63,7 @@ static struct ddi_dma_attr tx_dma_attr = { 1, /* dma_attr_minxfer */ 0xFFFFFFFFULL, /* dma_attr_maxxfer */ 0xFFFFFFFFFFFFFFFFULL, /* dma_attr_seg */ - 4, /* dma_attr_sgllen */ + 18, /* dma_attr_sgllen */ 1, /* dma_attr_granular */ 0 /* dma_attr_flags */ }; @@ -167,6 +168,11 @@ xge_device_poll(void *data) xge_hal_device_poll(data); lldev->timeout_id = timeout(xge_device_poll, data, XGE_DEV_POLL_TICKS); + } else if (lldev->in_reset == 1) { + lldev->timeout_id = timeout(xge_device_poll, data, + XGE_DEV_POLL_TICKS); + } else { + lldev->timeout_id = 0; } mutex_exit(&lldev->genlock); } @@ -182,10 +188,10 @@ xge_device_poll_now(void *data) xgelldev_t *lldev = xge_hal_device_private(data); mutex_enter(&lldev->genlock); - (void) untimeout(lldev->timeout_id); - lldev->timeout_id = timeout(xge_device_poll, data, 0); + if (lldev->is_initialized) { + xge_hal_device_poll(data); + } mutex_exit(&lldev->genlock); - } /* @@ -234,6 +240,8 @@ xgell_rx_buffer_replenish_all(xgelldev_t *lldev) xgell_rx_buffer_t *rx_buffer; xgell_rxd_priv_t *rxd_priv; + xge_assert(mutex_owned(&lldev->bf_pool.pool_lock)); + while ((lldev->bf_pool.free > 0) && (xge_hal_ring_dtr_reserve(lldev->ring_main.channelh, &dtr) == XGE_HAL_OK)) { @@ -258,21 +266,20 @@ xgell_rx_buffer_replenish_all(xgelldev_t *lldev) * xgell_rx_buffer_release * * The only thing done here is to put the buffer back to the pool. + * Calling this function need be protected by mutex, bf_pool.pool_lock. */ static void xgell_rx_buffer_release(xgell_rx_buffer_t *rx_buffer) { xgelldev_t *lldev = rx_buffer->lldev; - mutex_enter(&lldev->bf_pool.pool_lock); + xge_assert(mutex_owned(&lldev->bf_pool.pool_lock)); /* Put the buffer back to pool */ rx_buffer->next = lldev->bf_pool.head; lldev->bf_pool.head = rx_buffer; lldev->bf_pool.free++; - - mutex_exit(&lldev->bf_pool.pool_lock); } /* @@ -287,9 +294,9 @@ xgell_rx_buffer_recycle(char *arg) xgell_rx_buffer_t *rx_buffer = (xgell_rx_buffer_t *)arg; xgelldev_t *lldev = rx_buffer->lldev; - xgell_rx_buffer_release(rx_buffer); - mutex_enter(&lldev->bf_pool.pool_lock); + + xgell_rx_buffer_release(rx_buffer); lldev->bf_pool.post--; /* @@ -323,7 +330,7 @@ xgell_rx_buffer_alloc(xgelldev_t *lldev) extern ddi_device_acc_attr_t *p_xge_dev_attr; xgell_rx_buffer_t *rx_buffer; - hldev = lldev->devh; + hldev = (xge_hal_device_t *)lldev->devh; if (ddi_dma_alloc_handle(hldev->pdev, p_hal_dma_attr, DDI_DMA_SLEEP, 0, &dma_handle) != DDI_SUCCESS) { @@ -463,7 +470,6 @@ xgell_rx_create_buffer_pool(xgelldev_t *lldev) lldev->bf_pool.free = 0; lldev->bf_pool.post = 0; lldev->bf_pool.post_hiwat = lldev->config.rx_buffer_post_hiwat; - lldev->bf_pool.recycle_hiwat = lldev->config.rx_buffer_recycle_hiwat; mutex_init(&lldev->bf_pool.pool_lock, NULL, MUTEX_DRIVER, hldev->irqh); @@ -576,9 +582,6 @@ xgell_rx_hcksum_assoc(mblk_t *mp, char *vaddr, int pkt_length, xge_hal_dtr_info_t *ext_info) { int cksum_flags = 0; - int ip_off; - - ip_off = xgell_get_ip_offset(ext_info); if (!(ext_info->proto & XGE_HAL_FRAME_PROTO_IP_FRAGMENTED)) { if (ext_info->proto & XGE_HAL_FRAME_PROTO_TCP_OR_UDP) { @@ -599,6 +602,7 @@ xgell_rx_hcksum_assoc(mblk_t *mp, char *vaddr, int pkt_length, /* * Just pass the partial cksum up to IP. */ + int ip_off = xgell_get_ip_offset(ext_info); int start, end = pkt_length - ip_off; if (ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4) { @@ -621,12 +625,12 @@ xgell_rx_hcksum_assoc(mblk_t *mp, char *vaddr, int pkt_length, * Allocate message header for data buffer, and decide if copy the packet to * new data buffer to release big rx_buffer to save memory. * - * If the pkt_length <= XGELL_DMA_BUFFER_SIZE_LOWAT, call allocb() to allocate + * If the pkt_length <= XGELL_RX_DMA_LOWAT, call allocb() to allocate * new message and copy the payload in. */ static mblk_t * -xgell_rx_1b_msg_alloc(xgell_rx_buffer_t *rx_buffer, int pkt_length, - xge_hal_dtr_info_t *ext_info, boolean_t *copyit) +xgell_rx_1b_msg_alloc(xgelldev_t *lldev, xgell_rx_buffer_t *rx_buffer, + int pkt_length, xge_hal_dtr_info_t *ext_info, boolean_t *copyit) { mblk_t *mp; mblk_t *nmp = NULL; @@ -634,13 +638,12 @@ xgell_rx_1b_msg_alloc(xgell_rx_buffer_t *rx_buffer, int pkt_length, int hdr_length = 0; #ifdef XGELL_L3_ALIGNED - int doalign = 1; + boolean_t doalign = B_TRUE; struct ip *ip; struct tcphdr *tcp; int tcp_off; int mp_align_len; int ip_off; - #endif vaddr = (char *)rx_buffer->vaddr + HEADROOM; @@ -649,7 +652,7 @@ xgell_rx_1b_msg_alloc(xgell_rx_buffer_t *rx_buffer, int pkt_length, /* Check ip_off with HEADROOM */ if ((ip_off & 3) == HEADROOM) { - doalign = 0; + doalign = B_FALSE; } /* @@ -658,7 +661,7 @@ xgell_rx_1b_msg_alloc(xgell_rx_buffer_t *rx_buffer, int pkt_length, /* Is IPv4 or IPv6? */ if (doalign && !(ext_info->proto & XGE_HAL_FRAME_PROTO_IPV4 || ext_info->proto & XGE_HAL_FRAME_PROTO_IPV6)) { - doalign = 0; + doalign = B_FALSE; } /* Is TCP? */ @@ -672,15 +675,15 @@ xgell_rx_1b_msg_alloc(xgell_rx_buffer_t *rx_buffer, int pkt_length, hdr_length = pkt_length; } } else { - doalign = 0; + doalign = B_FALSE; } #endif /* * Copy packet into new allocated message buffer, if pkt_length - * is less than XGELL_DMA_BUFFER_LOWAT + * is less than XGELL_RX_DMA_LOWAT */ - if (*copyit || pkt_length <= XGELL_DMA_BUFFER_SIZE_LOWAT) { + if (*copyit || pkt_length <= lldev->config.rx_dma_lowat) { /* Keep room for alignment */ if ((mp = allocb(pkt_length + HEADROOM + 4, 0)) == NULL) { return (NULL); @@ -766,13 +769,14 @@ xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, xgell_rx_buffer_t *rx_buffer; mblk_t *mp_head = NULL; mblk_t *mp_end = NULL; + int pkt_burst = 0; + + mutex_enter(&lldev->bf_pool.pool_lock); do { - int ret; int pkt_length; dma_addr_t dma_data; mblk_t *mp; - boolean_t copyit = B_FALSE; xgell_rxd_priv_t *rxd_priv = ((xgell_rxd_priv_t *) @@ -801,9 +805,8 @@ xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, /* * Sync the DMA memory */ - ret = ddi_dma_sync(rx_buffer->dma_handle, 0, pkt_length, - DDI_DMA_SYNC_FORKERNEL); - if (ret != DDI_SUCCESS) { + if (ddi_dma_sync(rx_buffer->dma_handle, 0, pkt_length, + DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS) { xge_debug_ll(XGE_ERR, "%s%d: rx: can not do DMA sync", XGELL_IFNAME, lldev->instance); xge_hal_ring_dtr_free(channelh, dtr); /* drop it */ @@ -820,8 +823,8 @@ xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, copyit = B_FALSE; } - mp = xgell_rx_1b_msg_alloc(rx_buffer, pkt_length, &ext_info, - ©it); + mp = xgell_rx_1b_msg_alloc(lldev, rx_buffer, pkt_length, + &ext_info, ©it); xge_hal_ring_dtr_free(channelh, dtr); @@ -834,19 +837,18 @@ xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, /* * Count it since the buffer should be loaned up. */ - mutex_enter(&lldev->bf_pool.pool_lock); lldev->bf_pool.post++; - mutex_exit(&lldev->bf_pool.pool_lock); } if (mp == NULL) { xge_debug_ll(XGE_ERR, - "%s%d: rx: can not allocate mp mblk", XGELL_IFNAME, - lldev->instance); + "%s%d: rx: can not allocate mp mblk", + XGELL_IFNAME, lldev->instance); continue; } /* - * Associate cksum_flags per packet type and h/w cksum flags. + * Associate cksum_flags per packet type and h/w + * cksum flags. */ xgell_rx_hcksum_assoc(mp, (char *)rx_buffer->vaddr + HEADROOM, pkt_length, &ext_info); @@ -859,20 +861,35 @@ xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, mp_end = mp; } + if (++pkt_burst < lldev->config.rx_pkt_burst) + continue; + + if (lldev->bf_pool.post > lldev->bf_pool.post_hiwat) { + /* Replenish rx buffers */ + xgell_rx_buffer_replenish_all(lldev); + } + mutex_exit(&lldev->bf_pool.pool_lock); + if (mp_head != NULL) { + mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle, + mp_head); + } + mp_head = mp_end = NULL; + pkt_burst = 0; + mutex_enter(&lldev->bf_pool.pool_lock); + } while (xge_hal_ring_dtr_next_completed(channelh, &dtr, &t_code) == XGE_HAL_OK); - if (mp_head) { - mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle, mp_head); - } - /* * Always call replenish_all to recycle rx_buffers. */ - mutex_enter(&lldev->bf_pool.pool_lock); xgell_rx_buffer_replenish_all(lldev); mutex_exit(&lldev->bf_pool.pool_lock); + if (mp_head != NULL) { + mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle, mp_head); + } + return (XGE_HAL_OK); } @@ -894,9 +911,7 @@ xgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, xgell_txd_priv_t *txd_priv = ((xgell_txd_priv_t *) xge_hal_fifo_dtr_private(dtr)); mblk_t *mp = txd_priv->mblk; -#if !defined(XGELL_TX_NOMAP_COPY) int i; -#endif if (t_code) { xge_debug_ll(XGE_TRACE, "%s%d: tx: dtr 0x%"PRIx64 @@ -907,14 +922,12 @@ xgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, t_code); } -#if !defined(XGELL_TX_NOMAP_COPY) for (i = 0; i < txd_priv->handle_cnt; i++) { xge_assert(txd_priv->dma_handles[i]); (void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]); ddi_dma_free_handle(&txd_priv->dma_handles[i]); txd_priv->dma_handles[i] = 0; } -#endif xge_hal_fifo_dtr_free(channelh, dtr); @@ -939,7 +952,7 @@ xgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, /* * xgell_send - * @hldev: pointer to s2hal_device_t strucutre + * @hldev: pointer to xge_hal_device_t strucutre * @mblk: pointer to network buffer, i.e. mblk_t structure * * Called by the xgell_m_tx to transmit the packet to the XFRAME firmware. @@ -947,24 +960,22 @@ xgell_xmit_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code, * this routine. */ static boolean_t -xgell_send(xge_hal_device_t *hldev, mblk_t *mp) +xgell_send(xgelldev_t *lldev, mblk_t *mp) { mblk_t *bp; - int retry, repeat; + boolean_t retry; + xge_hal_device_t *hldev = lldev->devh; xge_hal_status_e status; xge_hal_dtr_h dtr; - xgelldev_t *lldev = xge_hal_device_private(hldev); xgell_txd_priv_t *txd_priv; - uint32_t pflags; -#ifndef XGELL_TX_NOMAP_COPY - int handle_cnt, frag_cnt, ret, i; -#endif + uint32_t hckflags; + uint32_t mss; + int handle_cnt, frag_cnt, ret, i, copied; + boolean_t used_copy; _begin: - retry = repeat = 0; -#ifndef XGELL_TX_NOMAP_COPY + retry = B_FALSE; handle_cnt = frag_cnt = 0; -#endif if (!lldev->is_initialized || lldev->in_reset) return (B_FALSE); @@ -976,14 +987,14 @@ _begin: * gld through gld_sched call, when the free dtrs count exceeds * the higher threshold. */ - if (__hal_channel_dtr_count(lldev->fifo_channel) + if (xge_hal_channel_dtr_count(lldev->fifo_channel) <= XGELL_TX_LEVEL_LOW) { xge_debug_ll(XGE_TRACE, "%s%d: queue %d: err on xmit," "free descriptors count at low threshold %d", XGELL_IFNAME, lldev->instance, ((xge_hal_channel_t *)lldev->fifo_channel)->post_qid, XGELL_TX_LEVEL_LOW); - retry = 1; + retry = B_TRUE; goto _exit; } @@ -996,7 +1007,7 @@ _begin: lldev->instance, ((xge_hal_channel_t *) lldev->fifo_channel)->post_qid); - retry = 1; + retry = B_TRUE; goto _exit; case XGE_HAL_INF_OUT_OF_DESCRIPTORS: xge_debug_ll(XGE_TRACE, "%s%d: queue %d: error in xmit," @@ -1004,7 +1015,7 @@ _begin: lldev->instance, ((xge_hal_channel_t *) lldev->fifo_channel)->post_qid); - retry = 1; + retry = B_TRUE; goto _exit; default: return (B_FALSE); @@ -1029,31 +1040,17 @@ _begin: * * evhp = (struct ether_vlan_header *)mp->b_rptr; * if (evhp->ether_tpid == htons(VLAN_TPID)) { - * tci = ntohs(evhp->ether_tci); - * (void) bcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ, + * tci = ntohs(evhp->ether_tci); + * (void) bcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ, * 2 * ETHERADDRL); - * mp->b_rptr += VLAN_TAGSZ; + * mp->b_rptr += VLAN_TAGSZ; * - * xge_hal_fifo_dtr_vlan_set(dtr, tci); + * xge_hal_fifo_dtr_vlan_set(dtr, tci); * } */ -#ifdef XGELL_TX_NOMAP_COPY - for (bp = mp; bp != NULL; bp = bp->b_cont) { - int mblen; - xge_hal_status_e rc; - - /* skip zero-length message blocks */ - mblen = MBLKL(bp); - if (mblen == 0) { - continue; - } - rc = xge_hal_fifo_dtr_buffer_append(lldev->fifo_channel, dtr, - bp->b_rptr, mblen); - xge_assert(rc == XGE_HAL_OK); - } - xge_hal_fifo_dtr_buffer_finalize(lldev->fifo_channel, dtr, 0); -#else + copied = 0; + used_copy = B_FALSE; for (bp = mp; bp != NULL; bp = bp->b_cont) { int mblen; uint_t ncookies; @@ -1066,12 +1063,36 @@ _begin: continue; } + /* + * Check the message length to decide to DMA or bcopy() data + * to tx descriptor(s). + */ + if (mblen < lldev->config.tx_dma_lowat && + (copied + mblen) < lldev->tx_copied_max) { + xge_hal_status_e rc; + rc = xge_hal_fifo_dtr_buffer_append(lldev->fifo_channel, + dtr, bp->b_rptr, mblen); + if (rc == XGE_HAL_OK) { + used_copy = B_TRUE; + copied += mblen; + continue; + } else if (used_copy) { + xge_hal_fifo_dtr_buffer_finalize( + lldev->fifo_channel, dtr, frag_cnt++); + used_copy = B_FALSE; + } + } else if (used_copy) { + xge_hal_fifo_dtr_buffer_finalize(lldev->fifo_channel, + dtr, frag_cnt++); + used_copy = B_FALSE; + } + ret = ddi_dma_alloc_handle(lldev->dev_info, &tx_dma_attr, DDI_DMA_DONTWAIT, 0, &dma_handle); if (ret != DDI_SUCCESS) { xge_debug_ll(XGE_ERR, - "%s%d: can not allocate dma handle", - XGELL_IFNAME, lldev->instance); + "%s%d: can not allocate dma handle", XGELL_IFNAME, + lldev->instance); goto _exit_cleanup; } @@ -1104,7 +1125,7 @@ _begin: goto _exit_cleanup; } - if (ncookies + frag_cnt > XGE_HAL_DEFAULT_FIFO_FRAGS) { + if (ncookies + frag_cnt > hldev->config.fifo.max_frags) { xge_debug_ll(XGE_ERR, "%s%d: too many fragments, " "requested c:%d+f:%d", XGELL_IFNAME, lldev->instance, ncookies, frag_cnt); @@ -1128,7 +1149,7 @@ _begin: if (bp->b_cont && (frag_cnt + XGE_HAL_DEFAULT_FIFO_FRAGS_THRESHOLD >= - XGE_HAL_DEFAULT_FIFO_FRAGS)) { + hldev->config.fifo.max_frags)) { mblk_t *nmp; xge_debug_ll(XGE_TRACE, @@ -1146,15 +1167,28 @@ _begin: } } + /* finalize unfinished copies */ + if (used_copy) { + xge_hal_fifo_dtr_buffer_finalize(lldev->fifo_channel, dtr, + frag_cnt++); + } + txd_priv->handle_cnt = handle_cnt; -#endif /* XGELL_TX_NOMAP_COPY */ - hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, NULL, &pflags); - if (pflags & HCK_IPV4_HDRCKSUM) { + /* + * If LSO is required, just call xge_hal_fifo_dtr_mss_set(dtr, mss) to + * do all necessary work. + */ + hcksum_retrieve(mp, NULL, NULL, NULL, NULL, NULL, &mss, &hckflags); + if ((hckflags & HW_LSO) && (mss != 0)) { + xge_hal_fifo_dtr_mss_set(dtr, mss); + } + + if (hckflags & HCK_IPV4_HDRCKSUM) { xge_hal_fifo_dtr_cksum_set_bits(dtr, XGE_HAL_TXD_TX_CKO_IPV4_EN); } - if (pflags & HCK_FULLCKSUM) { + if (hckflags & HCK_FULLCKSUM) { xge_hal_fifo_dtr_cksum_set_bits(dtr, XGE_HAL_TXD_TX_CKO_TCP_EN | XGE_HAL_TXD_TX_CKO_UDP_EN); } @@ -1165,20 +1199,14 @@ _begin: _exit_cleanup: -#if !defined(XGELL_TX_NOMAP_COPY) for (i = 0; i < handle_cnt; i++) { (void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]); ddi_dma_free_handle(&txd_priv->dma_handles[i]); txd_priv->dma_handles[i] = 0; } -#endif xge_hal_fifo_dtr_free(lldev->fifo_channel, dtr); - if (repeat) { - goto _begin; - } - _exit: if (retry) { if (lldev->resched_avail != lldev->resched_send && @@ -1197,7 +1225,7 @@ _exit: /* * xge_m_tx - * @arg: pointer to the s2hal_device_t structure + * @arg: pointer to the xgelldev_t structure * @resid: resource id * @mp: pointer to the message buffer * @@ -1206,14 +1234,14 @@ _exit: static mblk_t * xgell_m_tx(void *arg, mblk_t *mp) { - xge_hal_device_t *hldev = arg; + xgelldev_t *lldev = arg; mblk_t *next; while (mp != NULL) { next = mp->b_next; mp->b_next = NULL; - if (!xgell_send(hldev, mp)) { + if (!xgell_send(lldev, mp)) { mp->b_next = next; break; } @@ -1238,8 +1266,12 @@ xgell_rx_dtr_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, xgell_rx_buffer_t *rx_buffer = rxd_priv->rx_buffer; if (state == XGE_HAL_DTR_STATE_POSTED) { + xgelldev_t *lldev = rx_buffer->lldev; + + mutex_enter(&lldev->bf_pool.pool_lock); xge_hal_ring_dtr_free(channelh, dtrh); xgell_rx_buffer_release(rx_buffer); + mutex_exit(&lldev->bf_pool.pool_lock); } } @@ -1256,9 +1288,8 @@ xgell_tx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, xgell_txd_priv_t *txd_priv = ((xgell_txd_priv_t *)xge_hal_fifo_dtr_private(dtrh)); mblk_t *mp = txd_priv->mblk; -#if !defined(XGELL_TX_NOMAP_COPY) int i; -#endif + /* * for Tx we must clean up the DTR *only* if it has been * posted! @@ -1267,14 +1298,12 @@ xgell_tx_term(xge_hal_channel_h channelh, xge_hal_dtr_h dtrh, return; } -#if !defined(XGELL_TX_NOMAP_COPY) for (i = 0; i < txd_priv->handle_cnt; i++) { xge_assert(txd_priv->dma_handles[i]); (void) ddi_dma_unbind_handle(txd_priv->dma_handles[i]); ddi_dma_free_handle(&txd_priv->dma_handles[i]); txd_priv->dma_handles[i] = 0; } -#endif xge_hal_fifo_dtr_free(channelh, dtrh); @@ -1390,6 +1419,17 @@ xgell_initiate_start(xgelldev_t *lldev) return (EIO); } + /* tune jumbo/normal frame UFC counters */ + hldev->config.ring.queue[XGELL_RING_MAIN_QID].rti.ufc_b = \ + maxpkt > XGE_HAL_DEFAULT_MTU ? + XGE_HAL_DEFAULT_RX_UFC_B_J : + XGE_HAL_DEFAULT_RX_UFC_B_N; + + hldev->config.ring.queue[XGELL_RING_MAIN_QID].rti.ufc_c = \ + maxpkt > XGE_HAL_DEFAULT_MTU ? + XGE_HAL_DEFAULT_RX_UFC_C_J : + XGE_HAL_DEFAULT_RX_UFC_C_N; + /* now, enable the device */ status = xge_hal_device_enable(lldev->devh); if (status != XGE_HAL_OK) { @@ -1414,10 +1454,6 @@ xgell_initiate_start(xgelldev_t *lldev) return (ENOMEM); } -#ifdef XGELL_TX_NOMAP_COPY - hldev->config.fifo.alignment_size = XGELL_MAX_FRAME_SIZE(hldev); -#endif - if (!xgell_tx_open(lldev)) { status = xge_hal_device_disable(lldev->devh); if (status != XGE_HAL_OK) { @@ -1487,8 +1523,8 @@ xgell_initiate_stop(xgelldev_t *lldev) static int xgell_m_start(void *arg) { - xge_hal_device_t *hldev = arg; - xgelldev_t *lldev = xge_hal_device_private(hldev); + xgelldev_t *lldev = arg; + xge_hal_device_t *hldev = lldev->devh; int ret; xge_debug_ll(XGE_TRACE, "%s%d: M_START", XGELL_IFNAME, @@ -1511,12 +1547,6 @@ xgell_m_start(void *arg) lldev->timeout_id = timeout(xge_device_poll, hldev, XGE_DEV_POLL_TICKS); - if (!lldev->timeout_id) { - xgell_initiate_stop(lldev); - mutex_exit(&lldev->genlock); - return (EINVAL); - } - mutex_exit(&lldev->genlock); return (0); @@ -1534,17 +1564,11 @@ xgell_m_start(void *arg) static void xgell_m_stop(void *arg) { - xge_hal_device_t *hldev; - xgelldev_t *lldev; + xgelldev_t *lldev = arg; + xge_hal_device_t *hldev = lldev->devh; xge_debug_ll(XGE_TRACE, "%s", "MAC_STOP"); - hldev = arg; - xge_assert(hldev); - - lldev = (xgelldev_t *)xge_hal_device_private(hldev); - xge_assert(lldev); - mutex_enter(&lldev->genlock); if (!lldev->is_initialized) { xge_debug_ll(XGE_ERR, "%s", "device is not initialized..."); @@ -1560,7 +1584,9 @@ xgell_m_stop(void *arg) mutex_exit(&lldev->genlock); - (void) untimeout(lldev->timeout_id); + if (lldev->timeout_id != 0) { + (void) untimeout(lldev->timeout_id); + } xge_debug_ll(XGE_TRACE, "%s", "returning back to MAC Layer..."); } @@ -1608,8 +1634,8 @@ static int xgell_m_unicst(void *arg, const uint8_t *macaddr) { xge_hal_status_e status; - xge_hal_device_t *hldev = arg; - xgelldev_t *lldev = (xgelldev_t *)xge_hal_device_private(hldev); + xgelldev_t *lldev = (xgelldev_t *)arg; + xge_hal_device_t *hldev = lldev->devh; xge_debug_ll(XGE_TRACE, "%s", "MAC_UNICST"); xge_debug_ll(XGE_TRACE, "%s", "M_UNICAST"); @@ -1648,8 +1674,8 @@ static int xgell_m_multicst(void *arg, boolean_t add, const uint8_t *mc_addr) { xge_hal_status_e status; - xge_hal_device_t *hldev = (xge_hal_device_t *)arg; - xgelldev_t *lldev = xge_hal_device_private(hldev); + xgelldev_t *lldev = (xgelldev_t *)arg; + xge_hal_device_t *hldev = lldev->devh; xge_debug_ll(XGE_TRACE, "M_MULTICAST add %d", add); @@ -1692,8 +1718,8 @@ xgell_m_multicst(void *arg, boolean_t add, const uint8_t *mc_addr) static int xgell_m_promisc(void *arg, boolean_t on) { - xge_hal_device_t *hldev = (xge_hal_device_t *)arg; - xgelldev_t *lldev = xge_hal_device_private(hldev); + xgelldev_t *lldev = (xgelldev_t *)arg; + xge_hal_device_t *hldev = lldev->devh; mutex_enter(&lldev->genlock); @@ -1728,8 +1754,8 @@ static int xgell_m_stat(void *arg, uint_t stat, uint64_t *val) { xge_hal_stats_hw_info_t *hw_info; - xge_hal_device_t *hldev = (xge_hal_device_t *)arg; - xgelldev_t *lldev = xge_hal_device_private(hldev); + xgelldev_t *lldev = (xgelldev_t *)arg; + xge_hal_device_t *hldev = lldev->devh; xge_debug_ll(XGE_TRACE, "%s", "MAC_STATS_GET"); @@ -1752,23 +1778,28 @@ xgell_m_stat(void *arg, uint_t stat, uint64_t *val) break; case MAC_STAT_MULTIRCV: - *val = hw_info->rmac_vld_mcst_frms; + *val = ((u64) hw_info->rmac_vld_mcst_frms_oflow << 32) | + hw_info->rmac_vld_mcst_frms; break; case MAC_STAT_BRDCSTRCV: - *val = hw_info->rmac_vld_bcst_frms; + *val = ((u64) hw_info->rmac_vld_bcst_frms_oflow << 32) | + hw_info->rmac_vld_bcst_frms; break; case MAC_STAT_MULTIXMT: - *val = hw_info->tmac_mcst_frms; + *val = ((u64) hw_info->tmac_mcst_frms_oflow << 32) | + hw_info->tmac_mcst_frms; break; case MAC_STAT_BRDCSTXMT: - *val = hw_info->tmac_bcst_frms; + *val = ((u64) hw_info->tmac_bcst_frms_oflow << 32) | + hw_info->tmac_bcst_frms; break; case MAC_STAT_RBYTES: - *val = hw_info->rmac_ttl_octets; + *val = ((u64) hw_info->rmac_ttl_octets_oflow << 32) | + hw_info->rmac_ttl_octets; break; case MAC_STAT_NORCVBUF: @@ -1776,11 +1807,13 @@ xgell_m_stat(void *arg, uint_t stat, uint64_t *val) break; case MAC_STAT_IERRORS: - *val = hw_info->rmac_discarded_frms; + *val = ((u64) hw_info->rmac_discarded_frms_oflow << 32) | + hw_info->rmac_discarded_frms; break; case MAC_STAT_OBYTES: - *val = hw_info->tmac_ttl_octets; + *val = ((u64) hw_info->tmac_ttl_octets_oflow << 32) | + hw_info->tmac_ttl_octets; break; case MAC_STAT_NOXMTBUF: @@ -1788,15 +1821,18 @@ xgell_m_stat(void *arg, uint_t stat, uint64_t *val) break; case MAC_STAT_OERRORS: - *val = hw_info->tmac_any_err_frms; + *val = ((u64) hw_info->tmac_any_err_frms_oflow << 32) | + hw_info->tmac_any_err_frms; break; case MAC_STAT_IPACKETS: - *val = hw_info->rmac_vld_frms; + *val = ((u64) hw_info->rmac_vld_frms_oflow << 32) | + hw_info->rmac_vld_frms; break; case MAC_STAT_OPACKETS: - *val = hw_info->tmac_frms; + *val = ((u64) hw_info->tmac_frms_oflow << 32) | + hw_info->tmac_frms; break; case ETHER_STAT_FCS_ERRORS: @@ -1839,7 +1875,6 @@ xgell_device_alloc(xge_hal_device_h devh, lldev = kmem_zalloc(sizeof (xgelldev_t), KM_SLEEP); - /* allocate mac */ lldev->devh = hldev; lldev->instance = instance; lldev->dev_info = dev_info; @@ -1869,8 +1904,7 @@ xgell_device_free(xgelldev_t *lldev) static void xgell_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) { - xge_hal_device_t *hldev = (xge_hal_device_t *)arg; - xgelldev_t *lldev = (xgelldev_t *)xge_hal_device_private(hldev); + xgelldev_t *lldev = arg; struct iocblk *iocp; int err = 0; int cmd; @@ -1945,6 +1979,8 @@ xgell_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) static boolean_t xgell_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) { + xgelldev_t *lldev = arg; + switch (cap) { case MAC_CAPAB_HCKSUM: { uint32_t *hcksum_txflags = cap_data; @@ -1952,13 +1988,17 @@ xgell_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) HCKSUM_IPHDRCKSUM; break; } - case MAC_CAPAB_POLL: - /* - * Fallthrough to default, as we don't support GLDv3 - * polling. When blanking is implemented, we will need to - * change this to return B_TRUE in addition to registering - * an mc_resources callback. - */ + case MAC_CAPAB_LSO: { + mac_capab_lso_t *cap_lso = cap_data; + + if (lldev->config.lso_enable) { + cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; + cap_lso->lso_basic_tcp_ipv4.lso_max = XGELL_LSO_MAXLEN; + break; + } else { + return (B_FALSE); + } + } default: return (B_FALSE); } @@ -2242,10 +2282,8 @@ xgell_devconfig_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) int xgell_device_register(xgelldev_t *lldev, xgell_config_t *config) { - mac_register_t *macp; + mac_register_t *macp = NULL; xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh; - int err; - if (nd_load(&lldev->ndp, "pciconf", xgell_pciconf_get, NULL, (caddr_t)lldev) == B_FALSE) @@ -2289,7 +2327,7 @@ xgell_device_register(xgelldev_t *lldev, xgell_config_t *config) if ((macp = mac_alloc(MAC_VERSION)) == NULL) goto xgell_register_fail; macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; - macp->m_driver = hldev; + macp->m_driver = lldev; macp->m_dip = lldev->dev_info; macp->m_src_addr = hldev->macaddr[0]; macp->m_callbacks = &xgell_m_callbacks; @@ -2299,11 +2337,15 @@ xgell_device_register(xgelldev_t *lldev, xgell_config_t *config) * Finally, we're ready to register ourselves with the Nemo * interface; if this succeeds, we're all ready to start() */ - err = mac_register(macp, &lldev->mh); - mac_free(macp); - if (err != 0) + + if (mac_register(macp, &lldev->mh) != 0) goto xgell_register_fail; + /* Calculate tx_copied_max here ??? */ + lldev->tx_copied_max = hldev->config.fifo.max_frags * + hldev->config.fifo.alignment_size * + hldev->config.fifo.max_aligned_frags; + xge_debug_ll(XGE_TRACE, "etherenet device %s%d registered", XGELL_IFNAME, lldev->instance); @@ -2315,6 +2357,8 @@ xgell_ndd_fail: return (DDI_FAILURE); xgell_register_fail: + if (macp != NULL) + mac_free(macp); nd_free(&lldev->ndp); mutex_destroy(&lldev->genlock); /* Ignore return value, since RX not start */ |