brintos

brintos / linux-shallow public Read only

0
0
Text · 19.3 KiB · 230726d Raw
677 lines · c
1/*2 * AMD 10Gb Ethernet driver3 *4 * This file is available to you under your choice of the following two5 * licenses:6 *7 * License 1: GPLv28 *9 * Copyright (c) 2014 Advanced Micro Devices, Inc.10 *11 * This file is free software; you may copy, redistribute and/or modify12 * it under the terms of the GNU General Public License as published by13 * the Free Software Foundation, either version 2 of the License, or (at14 * your option) any later version.15 *16 * This file is distributed in the hope that it will be useful, but17 * WITHOUT ANY WARRANTY; without even the implied warranty of18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU19 * General Public License for more details.20 *21 * You should have received a copy of the GNU General Public License22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.23 *24 * This file incorporates work covered by the following copyright and25 * permission notice:26 *     The Synopsys DWC ETHER XGMAC Software Driver and documentation27 *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,28 *     Inc. unless otherwise expressly agreed to in writing between Synopsys29 *     and you.30 *31 *     The Software IS NOT an item of Licensed Software or Licensed Product32 *     under any End User Software License Agreement or Agreement for Licensed33 *     Product with Synopsys or any supplement thereto.  Permission is hereby34 *     granted, free of charge, to any person obtaining a copy of this software35 *     annotated with this license and the Software, to deal in the Software36 *     without restriction, including without limitation the rights to use,37 *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies38 *     of the Software, and to permit persons to whom the Software is furnished39 *     to do so, subject to the following conditions:40 *41 *     The above copyright notice and this permission notice shall be included42 *     in all copies or substantial portions of the Software.43 *44 *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"45 *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED46 *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A47 *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS48 *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR49 *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF50 *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS51 *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN52 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)53 *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF54 *     THE POSSIBILITY OF SUCH DAMAGE.55 *56 *57 * License 2: Modified BSD58 *59 * Copyright (c) 2014 Advanced Micro Devices, Inc.60 * All rights reserved.61 *62 * Redistribution and use in source and binary forms, with or without63 * modification, are permitted provided that the following conditions are met:64 *     * Redistributions of source code must retain the above copyright65 *       notice, this list of conditions and the following disclaimer.66 *     * Redistributions in binary form must reproduce the above copyright67 *       notice, this list of conditions and the following disclaimer in the68 *       documentation and/or other materials provided with the distribution.69 *     * Neither the name of Advanced Micro Devices, Inc. nor the70 *       names of its contributors may be used to endorse or promote products71 *       derived from this software without specific prior written permission.72 *73 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"74 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE76 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY77 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;79 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND80 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT81 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF82 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.83 *84 * This file incorporates work covered by the following copyright and85 * permission notice:86 *     The Synopsys DWC ETHER XGMAC Software Driver and documentation87 *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,88 *     Inc. unless otherwise expressly agreed to in writing between Synopsys89 *     and you.90 *91 *     The Software IS NOT an item of Licensed Software or Licensed Product92 *     under any End User Software License Agreement or Agreement for Licensed93 *     Product with Synopsys or any supplement thereto.  Permission is hereby94 *     granted, free of charge, to any person obtaining a copy of this software95 *     annotated with this license and the Software, to deal in the Software96 *     without restriction, including without limitation the rights to use,97 *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies98 *     of the Software, and to permit persons to whom the Software is furnished99 *     to do so, subject to the following conditions:100 *101 *     The above copyright notice and this permission notice shall be included102 *     in all copies or substantial portions of the Software.103 *104 *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"105 *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED106 *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A107 *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS108 *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR109 *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF110 *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS111 *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN112 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)113 *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF114 *     THE POSSIBILITY OF SUCH DAMAGE.115 */116 117#include "xgbe.h"118#include "xgbe-common.h"119 120static void xgbe_unmap_rdata(struct xgbe_prv_data *, struct xgbe_ring_data *);121 122static void xgbe_free_ring(struct xgbe_prv_data *pdata,123			   struct xgbe_ring *ring)124{125	struct xgbe_ring_data *rdata;126	unsigned int i;127 128	if (!ring)129		return;130 131	if (ring->rdata) {132		for (i = 0; i < ring->rdesc_count; i++) {133			rdata = XGBE_GET_DESC_DATA(ring, i);134			xgbe_unmap_rdata(pdata, rdata);135		}136 137		kfree(ring->rdata);138		ring->rdata = NULL;139	}140 141	if (ring->rx_hdr_pa.pages) {142		dma_unmap_page(pdata->dev, ring->rx_hdr_pa.pages_dma,143			       ring->rx_hdr_pa.pages_len, DMA_FROM_DEVICE);144		put_page(ring->rx_hdr_pa.pages);145 146		ring->rx_hdr_pa.pages = NULL;147		ring->rx_hdr_pa.pages_len = 0;148		ring->rx_hdr_pa.pages_offset = 0;149		ring->rx_hdr_pa.pages_dma = 0;150	}151 152	if (ring->rx_buf_pa.pages) {153		dma_unmap_page(pdata->dev, ring->rx_buf_pa.pages_dma,154			       ring->rx_buf_pa.pages_len, DMA_FROM_DEVICE);155		put_page(ring->rx_buf_pa.pages);156 157		ring->rx_buf_pa.pages = NULL;158		ring->rx_buf_pa.pages_len = 0;159		ring->rx_buf_pa.pages_offset = 0;160		ring->rx_buf_pa.pages_dma = 0;161	}162 163	if (ring->rdesc) {164		dma_free_coherent(pdata->dev,165				  (sizeof(struct xgbe_ring_desc) *166				   ring->rdesc_count),167				  ring->rdesc, ring->rdesc_dma);168		ring->rdesc = NULL;169	}170}171 172static void xgbe_free_ring_resources(struct xgbe_prv_data *pdata)173{174	struct xgbe_channel *channel;175	unsigned int i;176 177	DBGPR("-->xgbe_free_ring_resources\n");178 179	for (i = 0; i < pdata->channel_count; i++) {180		channel = pdata->channel[i];181		xgbe_free_ring(pdata, channel->tx_ring);182		xgbe_free_ring(pdata, channel->rx_ring);183	}184 185	DBGPR("<--xgbe_free_ring_resources\n");186}187 188static void *xgbe_alloc_node(size_t size, int node)189{190	void *mem;191 192	mem = kzalloc_node(size, GFP_KERNEL, node);193	if (!mem)194		mem = kzalloc(size, GFP_KERNEL);195 196	return mem;197}198 199static void *xgbe_dma_alloc_node(struct device *dev, size_t size,200				 dma_addr_t *dma, int node)201{202	void *mem;203	int cur_node = dev_to_node(dev);204 205	set_dev_node(dev, node);206	mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL);207	set_dev_node(dev, cur_node);208 209	if (!mem)210		mem = dma_alloc_coherent(dev, size, dma, GFP_KERNEL);211 212	return mem;213}214 215static int xgbe_init_ring(struct xgbe_prv_data *pdata,216			  struct xgbe_ring *ring, unsigned int rdesc_count)217{218	size_t size;219 220	if (!ring)221		return 0;222 223	/* Descriptors */224	size = rdesc_count * sizeof(struct xgbe_ring_desc);225 226	ring->rdesc_count = rdesc_count;227	ring->rdesc = xgbe_dma_alloc_node(pdata->dev, size, &ring->rdesc_dma,228					  ring->node);229	if (!ring->rdesc)230		return -ENOMEM;231 232	/* Descriptor information */233	size = rdesc_count * sizeof(struct xgbe_ring_data);234 235	ring->rdata = xgbe_alloc_node(size, ring->node);236	if (!ring->rdata)237		return -ENOMEM;238 239	netif_dbg(pdata, drv, pdata->netdev,240		  "rdesc=%p, rdesc_dma=%pad, rdata=%p, node=%d\n",241		  ring->rdesc, &ring->rdesc_dma, ring->rdata, ring->node);242 243	return 0;244}245 246static int xgbe_alloc_ring_resources(struct xgbe_prv_data *pdata)247{248	struct xgbe_channel *channel;249	unsigned int i;250	int ret;251 252	for (i = 0; i < pdata->channel_count; i++) {253		channel = pdata->channel[i];254		netif_dbg(pdata, drv, pdata->netdev, "%s - Tx ring:\n",255			  channel->name);256 257		ret = xgbe_init_ring(pdata, channel->tx_ring,258				     pdata->tx_desc_count);259		if (ret) {260			netdev_alert(pdata->netdev,261				     "error initializing Tx ring\n");262			goto err_ring;263		}264 265		netif_dbg(pdata, drv, pdata->netdev, "%s - Rx ring:\n",266			  channel->name);267 268		ret = xgbe_init_ring(pdata, channel->rx_ring,269				     pdata->rx_desc_count);270		if (ret) {271			netdev_alert(pdata->netdev,272				     "error initializing Rx ring\n");273			goto err_ring;274		}275	}276 277	return 0;278 279err_ring:280	xgbe_free_ring_resources(pdata);281 282	return ret;283}284 285static int xgbe_alloc_pages(struct xgbe_prv_data *pdata,286			    struct xgbe_page_alloc *pa, int alloc_order,287			    int node)288{289	struct page *pages = NULL;290	dma_addr_t pages_dma;291	gfp_t gfp;292	int order;293 294again:295	order = alloc_order;296 297	/* Try to obtain pages, decreasing order if necessary */298	gfp = GFP_ATOMIC | __GFP_COMP | __GFP_NOWARN;299	while (order >= 0) {300		pages = alloc_pages_node(node, gfp, order);301		if (pages)302			break;303 304		order--;305	}306 307	/* If we couldn't get local pages, try getting from anywhere */308	if (!pages && (node != NUMA_NO_NODE)) {309		node = NUMA_NO_NODE;310		goto again;311	}312 313	if (!pages)314		return -ENOMEM;315 316	/* Map the pages */317	pages_dma = dma_map_page(pdata->dev, pages, 0,318				 PAGE_SIZE << order, DMA_FROM_DEVICE);319	if (dma_mapping_error(pdata->dev, pages_dma)) {320		put_page(pages);321		return -ENOMEM;322	}323 324	pa->pages = pages;325	pa->pages_len = PAGE_SIZE << order;326	pa->pages_offset = 0;327	pa->pages_dma = pages_dma;328 329	return 0;330}331 332static void xgbe_set_buffer_data(struct xgbe_buffer_data *bd,333				 struct xgbe_page_alloc *pa,334				 unsigned int len)335{336	get_page(pa->pages);337	bd->pa = *pa;338 339	bd->dma_base = pa->pages_dma;340	bd->dma_off = pa->pages_offset;341	bd->dma_len = len;342 343	pa->pages_offset += len;344	if ((pa->pages_offset + len) > pa->pages_len) {345		/* This data descriptor is responsible for unmapping page(s) */346		bd->pa_unmap = *pa;347 348		/* Get a new allocation next time */349		pa->pages = NULL;350		pa->pages_len = 0;351		pa->pages_offset = 0;352		pa->pages_dma = 0;353	}354}355 356static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,357			      struct xgbe_ring *ring,358			      struct xgbe_ring_data *rdata)359{360	int ret;361 362	if (!ring->rx_hdr_pa.pages) {363		ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, 0, ring->node);364		if (ret)365			return ret;366	}367 368	if (!ring->rx_buf_pa.pages) {369		ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa,370				       PAGE_ALLOC_COSTLY_ORDER, ring->node);371		if (ret)372			return ret;373	}374 375	/* Set up the header page info */376	xgbe_set_buffer_data(&rdata->rx.hdr, &ring->rx_hdr_pa,377			     XGBE_SKB_ALLOC_SIZE);378 379	/* Set up the buffer page info */380	xgbe_set_buffer_data(&rdata->rx.buf, &ring->rx_buf_pa,381			     pdata->rx_buf_size);382 383	return 0;384}385 386static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)387{388	struct xgbe_hw_if *hw_if = &pdata->hw_if;389	struct xgbe_channel *channel;390	struct xgbe_ring *ring;391	struct xgbe_ring_data *rdata;392	struct xgbe_ring_desc *rdesc;393	dma_addr_t rdesc_dma;394	unsigned int i, j;395 396	DBGPR("-->xgbe_wrapper_tx_descriptor_init\n");397 398	for (i = 0; i < pdata->channel_count; i++) {399		channel = pdata->channel[i];400		ring = channel->tx_ring;401		if (!ring)402			break;403 404		rdesc = ring->rdesc;405		rdesc_dma = ring->rdesc_dma;406 407		for (j = 0; j < ring->rdesc_count; j++) {408			rdata = XGBE_GET_DESC_DATA(ring, j);409 410			rdata->rdesc = rdesc;411			rdata->rdesc_dma = rdesc_dma;412 413			rdesc++;414			rdesc_dma += sizeof(struct xgbe_ring_desc);415		}416 417		ring->cur = 0;418		ring->dirty = 0;419		memset(&ring->tx, 0, sizeof(ring->tx));420 421		hw_if->tx_desc_init(channel);422	}423 424	DBGPR("<--xgbe_wrapper_tx_descriptor_init\n");425}426 427static void xgbe_wrapper_rx_descriptor_init(struct xgbe_prv_data *pdata)428{429	struct xgbe_hw_if *hw_if = &pdata->hw_if;430	struct xgbe_channel *channel;431	struct xgbe_ring *ring;432	struct xgbe_ring_desc *rdesc;433	struct xgbe_ring_data *rdata;434	dma_addr_t rdesc_dma;435	unsigned int i, j;436 437	DBGPR("-->xgbe_wrapper_rx_descriptor_init\n");438 439	for (i = 0; i < pdata->channel_count; i++) {440		channel = pdata->channel[i];441		ring = channel->rx_ring;442		if (!ring)443			break;444 445		rdesc = ring->rdesc;446		rdesc_dma = ring->rdesc_dma;447 448		for (j = 0; j < ring->rdesc_count; j++) {449			rdata = XGBE_GET_DESC_DATA(ring, j);450 451			rdata->rdesc = rdesc;452			rdata->rdesc_dma = rdesc_dma;453 454			if (xgbe_map_rx_buffer(pdata, ring, rdata))455				break;456 457			rdesc++;458			rdesc_dma += sizeof(struct xgbe_ring_desc);459		}460 461		ring->cur = 0;462		ring->dirty = 0;463 464		hw_if->rx_desc_init(channel);465	}466 467	DBGPR("<--xgbe_wrapper_rx_descriptor_init\n");468}469 470static void xgbe_unmap_rdata(struct xgbe_prv_data *pdata,471			     struct xgbe_ring_data *rdata)472{473	if (rdata->skb_dma) {474		if (rdata->mapped_as_page) {475			dma_unmap_page(pdata->dev, rdata->skb_dma,476				       rdata->skb_dma_len, DMA_TO_DEVICE);477		} else {478			dma_unmap_single(pdata->dev, rdata->skb_dma,479					 rdata->skb_dma_len, DMA_TO_DEVICE);480		}481		rdata->skb_dma = 0;482		rdata->skb_dma_len = 0;483	}484 485	if (rdata->skb) {486		dev_kfree_skb_any(rdata->skb);487		rdata->skb = NULL;488	}489 490	if (rdata->rx.hdr.pa.pages)491		put_page(rdata->rx.hdr.pa.pages);492 493	if (rdata->rx.hdr.pa_unmap.pages) {494		dma_unmap_page(pdata->dev, rdata->rx.hdr.pa_unmap.pages_dma,495			       rdata->rx.hdr.pa_unmap.pages_len,496			       DMA_FROM_DEVICE);497		put_page(rdata->rx.hdr.pa_unmap.pages);498	}499 500	if (rdata->rx.buf.pa.pages)501		put_page(rdata->rx.buf.pa.pages);502 503	if (rdata->rx.buf.pa_unmap.pages) {504		dma_unmap_page(pdata->dev, rdata->rx.buf.pa_unmap.pages_dma,505			       rdata->rx.buf.pa_unmap.pages_len,506			       DMA_FROM_DEVICE);507		put_page(rdata->rx.buf.pa_unmap.pages);508	}509 510	memset(&rdata->tx, 0, sizeof(rdata->tx));511	memset(&rdata->rx, 0, sizeof(rdata->rx));512 513	rdata->mapped_as_page = 0;514 515	if (rdata->state_saved) {516		rdata->state_saved = 0;517		rdata->state.skb = NULL;518		rdata->state.len = 0;519		rdata->state.error = 0;520	}521}522 523static int xgbe_map_tx_skb(struct xgbe_channel *channel, struct sk_buff *skb)524{525	struct xgbe_prv_data *pdata = channel->pdata;526	struct xgbe_ring *ring = channel->tx_ring;527	struct xgbe_ring_data *rdata;528	struct xgbe_packet_data *packet;529	skb_frag_t *frag;530	dma_addr_t skb_dma;531	unsigned int start_index, cur_index;532	unsigned int offset, tso, vlan, datalen, len;533	unsigned int i;534 535	DBGPR("-->xgbe_map_tx_skb: cur = %d\n", ring->cur);536 537	offset = 0;538	start_index = ring->cur;539	cur_index = ring->cur;540 541	packet = &ring->packet_data;542	packet->rdesc_count = 0;543	packet->length = 0;544 545	tso = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,546			     TSO_ENABLE);547	vlan = XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,548			      VLAN_CTAG);549 550	/* Save space for a context descriptor if needed */551	if ((tso && (packet->mss != ring->tx.cur_mss)) ||552	    (vlan && (packet->vlan_ctag != ring->tx.cur_vlan_ctag)))553		cur_index++;554	rdata = XGBE_GET_DESC_DATA(ring, cur_index);555 556	if (tso) {557		/* Map the TSO header */558		skb_dma = dma_map_single(pdata->dev, skb->data,559					 packet->header_len, DMA_TO_DEVICE);560		if (dma_mapping_error(pdata->dev, skb_dma)) {561			netdev_alert(pdata->netdev, "dma_map_single failed\n");562			goto err_out;563		}564		rdata->skb_dma = skb_dma;565		rdata->skb_dma_len = packet->header_len;566		netif_dbg(pdata, tx_queued, pdata->netdev,567			  "skb header: index=%u, dma=%pad, len=%u\n",568			  cur_index, &skb_dma, packet->header_len);569 570		offset = packet->header_len;571 572		packet->length += packet->header_len;573 574		cur_index++;575		rdata = XGBE_GET_DESC_DATA(ring, cur_index);576	}577 578	/* Map the (remainder of the) packet */579	for (datalen = skb_headlen(skb) - offset; datalen; ) {580		len = min_t(unsigned int, datalen, XGBE_TX_MAX_BUF_SIZE);581 582		skb_dma = dma_map_single(pdata->dev, skb->data + offset, len,583					 DMA_TO_DEVICE);584		if (dma_mapping_error(pdata->dev, skb_dma)) {585			netdev_alert(pdata->netdev, "dma_map_single failed\n");586			goto err_out;587		}588		rdata->skb_dma = skb_dma;589		rdata->skb_dma_len = len;590		netif_dbg(pdata, tx_queued, pdata->netdev,591			  "skb data: index=%u, dma=%pad, len=%u\n",592			  cur_index, &skb_dma, len);593 594		datalen -= len;595		offset += len;596 597		packet->length += len;598 599		cur_index++;600		rdata = XGBE_GET_DESC_DATA(ring, cur_index);601	}602 603	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {604		netif_dbg(pdata, tx_queued, pdata->netdev,605			  "mapping frag %u\n", i);606 607		frag = &skb_shinfo(skb)->frags[i];608		offset = 0;609 610		for (datalen = skb_frag_size(frag); datalen; ) {611			len = min_t(unsigned int, datalen,612				    XGBE_TX_MAX_BUF_SIZE);613 614			skb_dma = skb_frag_dma_map(pdata->dev, frag, offset,615						   len, DMA_TO_DEVICE);616			if (dma_mapping_error(pdata->dev, skb_dma)) {617				netdev_alert(pdata->netdev,618					     "skb_frag_dma_map failed\n");619				goto err_out;620			}621			rdata->skb_dma = skb_dma;622			rdata->skb_dma_len = len;623			rdata->mapped_as_page = 1;624			netif_dbg(pdata, tx_queued, pdata->netdev,625				  "skb frag: index=%u, dma=%pad, len=%u\n",626				  cur_index, &skb_dma, len);627 628			datalen -= len;629			offset += len;630 631			packet->length += len;632 633			cur_index++;634			rdata = XGBE_GET_DESC_DATA(ring, cur_index);635		}636	}637 638	/* Save the skb address in the last entry. We always have some data639	 * that has been mapped so rdata is always advanced past the last640	 * piece of mapped data - use the entry pointed to by cur_index - 1.641	 */642	rdata = XGBE_GET_DESC_DATA(ring, cur_index - 1);643	rdata->skb = skb;644 645	/* Save the number of descriptor entries used */646	packet->rdesc_count = cur_index - start_index;647 648	DBGPR("<--xgbe_map_tx_skb: count=%u\n", packet->rdesc_count);649 650	return packet->rdesc_count;651 652err_out:653	while (start_index < cur_index) {654		rdata = XGBE_GET_DESC_DATA(ring, start_index++);655		xgbe_unmap_rdata(pdata, rdata);656	}657 658	DBGPR("<--xgbe_map_tx_skb: count=0\n");659 660	return 0;661}662 663void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if)664{665	DBGPR("-->xgbe_init_function_ptrs_desc\n");666 667	desc_if->alloc_ring_resources = xgbe_alloc_ring_resources;668	desc_if->free_ring_resources = xgbe_free_ring_resources;669	desc_if->map_tx_skb = xgbe_map_tx_skb;670	desc_if->map_rx_buffer = xgbe_map_rx_buffer;671	desc_if->unmap_rdata = xgbe_unmap_rdata;672	desc_if->wrapper_tx_desc_init = xgbe_wrapper_tx_descriptor_init;673	desc_if->wrapper_rx_desc_init = xgbe_wrapper_rx_descriptor_init;674 675	DBGPR("<--xgbe_init_function_ptrs_desc\n");676}677