if_bce.c (163338) | if_bce.c (163339) |
---|---|
1/*- 2 * Copyright (c) 2006 Broadcom Corporation 3 * David Christensen <davidch@broadcom.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 15 unchanged lines hidden (view full) --- 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2006 Broadcom Corporation 3 * David Christensen <davidch@broadcom.com>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * --- 15 unchanged lines hidden (view full) --- 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> |
32__FBSDID("$FreeBSD: head/sys/dev/bce/if_bce.c 163338 2006-10-14 04:28:23Z scottl $"); | 32__FBSDID("$FreeBSD: head/sys/dev/bce/if_bce.c 163339 2006-10-14 05:30:12Z scottl $"); |
33 34/* 35 * The following controllers are supported by this driver: 36 * BCM5706C A2, A3 37 * BCM5708C B1 38 * 39 * The following controllers are not supported by this driver: 40 * (These are not "Production" versions of the controller.) --- 254 unchanged lines hidden (view full) --- 295static int bce_blockinit (struct bce_softc *); 296static int bce_get_buf (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *); 297 298static int bce_init_tx_chain (struct bce_softc *); 299static int bce_init_rx_chain (struct bce_softc *); 300static void bce_free_rx_chain (struct bce_softc *); 301static void bce_free_tx_chain (struct bce_softc *); 302 | 33 34/* 35 * The following controllers are supported by this driver: 36 * BCM5706C A2, A3 37 * BCM5708C B1 38 * 39 * The following controllers are not supported by this driver: 40 * (These are not "Production" versions of the controller.) --- 254 unchanged lines hidden (view full) --- 295static int bce_blockinit (struct bce_softc *); 296static int bce_get_buf (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *); 297 298static int bce_init_tx_chain (struct bce_softc *); 299static int bce_init_rx_chain (struct bce_softc *); 300static void bce_free_rx_chain (struct bce_softc *); 301static void bce_free_tx_chain (struct bce_softc *); 302 |
303static int bce_tx_encap (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *); | 303static int bce_tx_encap (struct bce_softc *, struct mbuf *, u16 *); |
304static void bce_start_locked (struct ifnet *); 305static void bce_start (struct ifnet *); 306static int bce_ioctl (struct ifnet *, u_long, caddr_t); 307static void bce_watchdog (struct ifnet *); 308static int bce_ifmedia_upd (struct ifnet *); 309static void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *); 310static void bce_init_locked (struct bce_softc *); 311static void bce_init (void *); --- 4322 unchanged lines hidden (view full) --- 4634/****************************************************************************/ 4635/* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */ 4636/* memory visible to the controller. */ 4637/* */ 4638/* Returns: */ 4639/* 0 for success, positive value for failure. */ 4640/****************************************************************************/ 4641static int | 304static void bce_start_locked (struct ifnet *); 305static void bce_start (struct ifnet *); 306static int bce_ioctl (struct ifnet *, u_long, caddr_t); 307static void bce_watchdog (struct ifnet *); 308static int bce_ifmedia_upd (struct ifnet *); 309static void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *); 310static void bce_init_locked (struct bce_softc *); 311static void bce_init (void *); --- 4322 unchanged lines hidden (view full) --- 4634/****************************************************************************/ 4635/* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */ 4636/* memory visible to the controller. */ 4637/* */ 4638/* Returns: */ 4639/* 0 for success, positive value for failure. */ 4640/****************************************************************************/ 4641static int |
4642bce_tx_encap(struct bce_softc *sc, struct mbuf *m_head, u16 *prod, 4643 u16 *chain_prod, u32 *prod_bseq) | 4642bce_tx_encap(struct bce_softc *sc, struct mbuf *m_head, u16 *prod) |
4644{ 4645 u32 vlan_tag_flags = 0; | 4643{ 4644 u32 vlan_tag_flags = 0; |
4645 u16 chain_prod; |
|
4646 struct bce_dmamap_arg map_arg; 4647 bus_dmamap_t map; 4648 int error, rc = 0; 4649 4650 /* Transfer any checksum offload flags to the bd. */ 4651 if (m_head->m_pkthdr.csum_flags) { 4652 if (m_head->m_pkthdr.csum_flags & CSUM_IP) 4653 vlan_tag_flags |= TX_BD_FLAGS_IP_CKSUM; 4654 if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 4655 vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; 4656 } 4657 4658 /* Transfer any VLAN tags to the bd. */ 4659 if (m_head->m_flags & M_VLANTAG) 4660 vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | 4661 (m_head->m_pkthdr.ether_vtag << 16)); 4662 4663 /* Map the mbuf into DMAable memory. */ | 4646 struct bce_dmamap_arg map_arg; 4647 bus_dmamap_t map; 4648 int error, rc = 0; 4649 4650 /* Transfer any checksum offload flags to the bd. */ 4651 if (m_head->m_pkthdr.csum_flags) { 4652 if (m_head->m_pkthdr.csum_flags & CSUM_IP) 4653 vlan_tag_flags |= TX_BD_FLAGS_IP_CKSUM; 4654 if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 4655 vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; 4656 } 4657 4658 /* Transfer any VLAN tags to the bd. */ 4659 if (m_head->m_flags & M_VLANTAG) 4660 vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | 4661 (m_head->m_pkthdr.ether_vtag << 16)); 4662 4663 /* Map the mbuf into DMAable memory. */ |
4664 map = sc->tx_mbuf_map[*chain_prod]; | 4664 chain_prod = TX_CHAIN_IDX(*prod); 4665 map = sc->tx_mbuf_map[chain_prod]; |
4665 map_arg.sc = sc; 4666 map_arg.prod = *prod; | 4666 map_arg.sc = sc; 4667 map_arg.prod = *prod; |
4667 map_arg.chain_prod = *chain_prod; 4668 map_arg.prod_bseq = *prod_bseq; | 4668 map_arg.chain_prod = chain_prod; 4669 map_arg.prod_bseq = sc->tx_prod_bseq; |
4669 map_arg.tx_flags = vlan_tag_flags; 4670 map_arg.maxsegs = USABLE_TX_BD - sc->used_tx_bd - 4671 BCE_TX_SLACK_SPACE; 4672 4673 KASSERT(map_arg.maxsegs > 0, ("Invalid TX maxsegs value!")); 4674 4675 /* Map the mbuf into our DMA address space. */ 4676 error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, map, m_head, --- 32 unchanged lines hidden (view full) --- 4709 * Ensure that the map for this transmission 4710 * is placed at the array index of the last 4711 * descriptor in this chain. This is done 4712 * because a single map is used for all 4713 * segments of the mbuf and we don't want to 4714 * delete the map before all of the segments 4715 * have been freed. 4716 */ | 4670 map_arg.tx_flags = vlan_tag_flags; 4671 map_arg.maxsegs = USABLE_TX_BD - sc->used_tx_bd - 4672 BCE_TX_SLACK_SPACE; 4673 4674 KASSERT(map_arg.maxsegs > 0, ("Invalid TX maxsegs value!")); 4675 4676 /* Map the mbuf into our DMA address space. */ 4677 error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, map, m_head, --- 32 unchanged lines hidden (view full) --- 4710 * Ensure that the map for this transmission 4711 * is placed at the array index of the last 4712 * descriptor in this chain. This is done 4713 * because a single map is used for all 4714 * segments of the mbuf and we don't want to 4715 * delete the map before all of the segments 4716 * have been freed. 4717 */ |
4717 sc->tx_mbuf_map[*chain_prod] = | 4718 sc->tx_mbuf_map[chain_prod] = |
4718 sc->tx_mbuf_map[map_arg.chain_prod]; 4719 sc->tx_mbuf_map[map_arg.chain_prod] = map; 4720 sc->tx_mbuf_ptr[map_arg.chain_prod] = m_head; 4721 sc->used_tx_bd += map_arg.maxsegs; 4722 4723 DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark), 4724 sc->tx_hi_watermark = sc->used_tx_bd); 4725 4726 DBRUNIF(1, sc->tx_mbuf_alloc++); 4727 | 4719 sc->tx_mbuf_map[map_arg.chain_prod]; 4720 sc->tx_mbuf_map[map_arg.chain_prod] = map; 4721 sc->tx_mbuf_ptr[map_arg.chain_prod] = m_head; 4722 sc->used_tx_bd += map_arg.maxsegs; 4723 4724 DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark), 4725 sc->tx_hi_watermark = sc->used_tx_bd); 4726 4727 DBRUNIF(1, sc->tx_mbuf_alloc++); 4728 |
4728 DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_mbuf_chain(sc, *chain_prod, | 4729 DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_mbuf_chain(sc, chain_prod, |
4729 map_arg.maxsegs)); 4730 4731 /* prod still points the last used tx_bd at this point. */ 4732 *prod = map_arg.prod; | 4730 map_arg.maxsegs)); 4731 4732 /* prod still points the last used tx_bd at this point. */ 4733 *prod = map_arg.prod; |
4733 *chain_prod = map_arg.chain_prod; 4734 *prod_bseq = map_arg.prod_bseq; | 4734 sc->tx_prod_bseq = map_arg.prod_bseq; |
4735 4736bce_tx_encap_exit: 4737 4738 return(rc); 4739} 4740 4741 4742/****************************************************************************/ --- 4 unchanged lines hidden (view full) --- 4747/****************************************************************************/ 4748static void 4749bce_start_locked(struct ifnet *ifp) 4750{ 4751 struct bce_softc *sc = ifp->if_softc; 4752 struct mbuf *m_head = NULL; 4753 int count = 0; 4754 u16 tx_prod, tx_chain_prod; | 4735 4736bce_tx_encap_exit: 4737 4738 return(rc); 4739} 4740 4741 4742/****************************************************************************/ --- 4 unchanged lines hidden (view full) --- 4747/****************************************************************************/ 4748static void 4749bce_start_locked(struct ifnet *ifp) 4750{ 4751 struct bce_softc *sc = ifp->if_softc; 4752 struct mbuf *m_head = NULL; 4753 int count = 0; 4754 u16 tx_prod, tx_chain_prod; |
4755 u32 tx_prod_bseq; | |
4756 4757 /* If there's no link or the transmit queue is empty then just exit. */ 4758 if (!sc->bce_link || IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 4759 DBPRINT(sc, BCE_INFO_SEND, "%s(): No link or transmit queue empty.\n", 4760 __FUNCTION__); 4761 goto bce_start_locked_exit; 4762 } 4763 4764 /* prod points to the next free tx_bd. */ 4765 tx_prod = sc->tx_prod; 4766 tx_chain_prod = TX_CHAIN_IDX(tx_prod); | 4755 4756 /* If there's no link or the transmit queue is empty then just exit. */ 4757 if (!sc->bce_link || IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 4758 DBPRINT(sc, BCE_INFO_SEND, "%s(): No link or transmit queue empty.\n", 4759 __FUNCTION__); 4760 goto bce_start_locked_exit; 4761 } 4762 4763 /* prod points to the next free tx_bd. */ 4764 tx_prod = sc->tx_prod; 4765 tx_chain_prod = TX_CHAIN_IDX(tx_prod); |
4767 tx_prod_bseq = sc->tx_prod_bseq; | |
4768 4769 DBPRINT(sc, BCE_INFO_SEND, 4770 "%s(): Start: tx_prod = 0x%04X, tx_chain_prod = %04X, " 4771 "tx_prod_bseq = 0x%08X\n", | 4766 4767 DBPRINT(sc, BCE_INFO_SEND, 4768 "%s(): Start: tx_prod = 0x%04X, tx_chain_prod = %04X, " 4769 "tx_prod_bseq = 0x%08X\n", |
4772 __FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq); | 4770 __FUNCTION__, tx_prod, tx_chain_prod, sc->tx_prod_bseq); |
4773 4774 /* Keep adding entries while there is space in the ring. */ 4775 while(sc->tx_mbuf_ptr[tx_chain_prod] == NULL) { 4776 4777 /* Check for any frames to send. */ 4778 IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 4779 if (m_head == NULL) 4780 break; 4781 4782 /* 4783 * Pack the data into the transmit ring. If we 4784 * don't have room, place the mbuf back at the 4785 * head of the queue and set the OACTIVE flag 4786 * to wait for the NIC to drain the chain. 4787 */ | 4771 4772 /* Keep adding entries while there is space in the ring. */ 4773 while(sc->tx_mbuf_ptr[tx_chain_prod] == NULL) { 4774 4775 /* Check for any frames to send. */ 4776 IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 4777 if (m_head == NULL) 4778 break; 4779 4780 /* 4781 * Pack the data into the transmit ring. If we 4782 * don't have room, place the mbuf back at the 4783 * head of the queue and set the OACTIVE flag 4784 * to wait for the NIC to drain the chain. 4785 */ |
4788 if (bce_tx_encap(sc, m_head, &tx_prod, &tx_chain_prod, &tx_prod_bseq)) { | 4786 if (bce_tx_encap(sc, m_head, &tx_prod)) { |
4789 IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 4790 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 4791 DBPRINT(sc, BCE_INFO_SEND, 4792 "TX chain is closed for business! Total tx_bd used = %d\n", 4793 sc->used_tx_bd); 4794 break; 4795 } 4796 4797 count++; 4798 4799 /* Send a copy of the frame to any BPF listeners. */ 4800 BPF_MTAP(ifp, m_head); 4801 4802 tx_prod = NEXT_TX_BD(tx_prod); | 4787 IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 4788 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 4789 DBPRINT(sc, BCE_INFO_SEND, 4790 "TX chain is closed for business! Total tx_bd used = %d\n", 4791 sc->used_tx_bd); 4792 break; 4793 } 4794 4795 count++; 4796 4797 /* Send a copy of the frame to any BPF listeners. */ 4798 BPF_MTAP(ifp, m_head); 4799 4800 tx_prod = NEXT_TX_BD(tx_prod); |
4803 tx_chain_prod = TX_CHAIN_IDX(tx_prod); | |
4804 } 4805 4806 if (count == 0) { 4807 /* no packets were dequeued */ 4808 DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): No packets were dequeued\n", 4809 __FUNCTION__); 4810 goto bce_start_locked_exit; 4811 } 4812 4813 /* Update the driver's counters. */ 4814 sc->tx_prod = tx_prod; | 4801 } 4802 4803 if (count == 0) { 4804 /* no packets were dequeued */ 4805 DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): No packets were dequeued\n", 4806 __FUNCTION__); 4807 goto bce_start_locked_exit; 4808 } 4809 4810 /* Update the driver's counters. */ 4811 sc->tx_prod = tx_prod; |
4815 sc->tx_prod_bseq = tx_prod_bseq; | 4812 tx_chain_prod = TX_CHAIN_IDX(tx_prod); |
4816 4817 DBPRINT(sc, BCE_INFO_SEND, 4818 "%s(): End: tx_prod = 0x%04X, tx_chain_prod = 0x%04X, " 4819 "tx_prod_bseq = 0x%08X\n", | 4813 4814 DBPRINT(sc, BCE_INFO_SEND, 4815 "%s(): End: tx_prod = 0x%04X, tx_chain_prod = 0x%04X, " 4816 "tx_prod_bseq = 0x%08X\n", |
4820 __FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq); | 4817 __FUNCTION__, tx_prod, tx_chain_prod, sc->tx_prod_bseq); |
4821 4822 /* Start the transmit. */ 4823 REG_WR16(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BIDX, sc->tx_prod); 4824 REG_WR(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq); 4825 4826 /* Set the tx timeout. */ 4827 ifp->if_timer = BCE_TX_TIMEOUT; 4828 --- 2035 unchanged lines hidden --- | 4818 4819 /* Start the transmit. */ 4820 REG_WR16(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BIDX, sc->tx_prod); 4821 REG_WR(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq); 4822 4823 /* Set the tx timeout. */ 4824 ifp->if_timer = BCE_TX_TIMEOUT; 4825 --- 2035 unchanged lines hidden --- |