Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4da0048 authored by Gertjan van Wingerde's avatar Gertjan van Wingerde Committed by John W. Linville
Browse files

rt2x00: Replace statically allocated DMA buffers with mapped skb's.



The current PCI drivers require a lot of pre-allocated DMA buffers. Reduce this
by using dynamically mapped skb's (using pci_map_single) instead of the pre-
allocated DMA buffers that are allocated at device start-up time.

At the same time move common RX path code into rt2x00lib from rt2x00pci and
rt2x00usb, as the RX paths now are now almost the same.

Signed-off-by: default avatarGertjan van Wingerde <gwingerde@kpnplanet.nl>
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 30caa6e3
Loading
Loading
Loading
Loading
+7 −6
Original line number Original line Diff line number Diff line
@@ -632,15 +632,15 @@ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
				   struct queue_entry *entry)
				   struct queue_entry *entry)
{
{
	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
	u32 word;
	u32 word;


	rt2x00_desc_read(entry_priv->desc, 2, &word);
	rt2x00_desc_read(entry_priv->desc, 2, &word);
	rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
	rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
			   entry->queue->data_size);
	rt2x00_desc_write(entry_priv->desc, 2, word);
	rt2x00_desc_write(entry_priv->desc, 2, word);


	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry_priv->data_dma);
	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
	rt2x00_desc_write(entry_priv->desc, 1, word);
	rt2x00_desc_write(entry_priv->desc, 1, word);


	rt2x00_desc_read(entry_priv->desc, 0, &word);
	rt2x00_desc_read(entry_priv->desc, 0, &word);
@@ -1012,7 +1012,7 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
	 * Start writing the descriptor words.
	 * Start writing the descriptor words.
	 */
	 */
	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry_priv->data_dma);
	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
	rt2x00_desc_write(entry_priv->desc, 1, word);
	rt2x00_desc_write(entry_priv->desc, 1, word);


	rt2x00_desc_read(txd, 2, &word);
	rt2x00_desc_read(txd, 2, &word);
@@ -1412,9 +1412,10 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
	rt2400pci_probe_hw_mode(rt2x00dev);
	rt2400pci_probe_hw_mode(rt2x00dev);


	/*
	/*
	 * This device requires the atim queue
	 * This device requires the atim queue and DMA-mapped skbs.
	 */
	 */
	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);


	/*
	/*
	 * Set the rssi offset.
	 * Set the rssi offset.
@@ -1526,7 +1527,7 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
	 * Write entire beacon with descriptor to register,
	 * Write entire beacon with descriptor to register,
	 * and kick the beacon generator.
	 * and kick the beacon generator.
	 */
	 */
	memcpy(entry_priv->data, skb->data, skb->len);
	rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
	rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
	rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);


+6 −4
Original line number Original line Diff line number Diff line
@@ -727,10 +727,11 @@ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
				   struct queue_entry *entry)
				   struct queue_entry *entry)
{
{
	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
	u32 word;
	u32 word;


	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry_priv->data_dma);
	rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
	rt2x00_desc_write(entry_priv->desc, 1, word);
	rt2x00_desc_write(entry_priv->desc, 1, word);


	rt2x00_desc_read(entry_priv->desc, 0, &word);
	rt2x00_desc_read(entry_priv->desc, 0, &word);
@@ -1171,7 +1172,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
	 * Start writing the descriptor words.
	 * Start writing the descriptor words.
	 */
	 */
	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry_priv->data_dma);
	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
	rt2x00_desc_write(entry_priv->desc, 1, word);
	rt2x00_desc_write(entry_priv->desc, 1, word);


	rt2x00_desc_read(txd, 2, &word);
	rt2x00_desc_read(txd, 2, &word);
@@ -1752,9 +1753,10 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
	rt2500pci_probe_hw_mode(rt2x00dev);
	rt2500pci_probe_hw_mode(rt2x00dev);


	/*
	/*
	 * This device requires the atim queue
	 * This device requires the atim queue and DMA-mapped skbs.
	 */
	 */
	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);


	/*
	/*
	 * Set the rssi offset.
	 * Set the rssi offset.
@@ -1842,7 +1844,7 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
	 * Write entire beacon with descriptor to register,
	 * Write entire beacon with descriptor to register,
	 * and kick the beacon generator.
	 * and kick the beacon generator.
	 */
	 */
	memcpy(entry_priv->data, skb->data, skb->len);
	rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
	rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
	rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);


+23 −5
Original line number Original line Diff line number Diff line
@@ -601,6 +601,7 @@ enum rt2x00_flags {
	DRIVER_REQUIRE_BEACON_GUARD,
	DRIVER_REQUIRE_BEACON_GUARD,
	DRIVER_REQUIRE_ATIM_QUEUE,
	DRIVER_REQUIRE_ATIM_QUEUE,
	DRIVER_REQUIRE_SCHEDULED,
	DRIVER_REQUIRE_SCHEDULED,
	DRIVER_REQUIRE_DMA,


	/*
	/*
	 * Driver configuration
	 * Driver configuration
@@ -899,16 +900,33 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
}
}


/**
/**
 * rt2x00queue_alloc_skb - allocate a skb.
 * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes.
 * @rt2x00dev: Pointer to &struct rt2x00_dev.
 * @queue: The queue for which the skb will be applicable.
 * @queue: The queue for which the skb will be applicable.
 */
 */
struct sk_buff *rt2x00queue_alloc_skb(struct data_queue *queue);
struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
					struct queue_entry *entry);

/**
 * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
 * @rt2x00dev: Pointer to &struct rt2x00_dev.
 * @skb: The skb to map.
 */
void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);

/**
 * rt2x00queue_unmap_skb - Unmap a skb from DMA.
 * @rt2x00dev: Pointer to &struct rt2x00_dev.
 * @skb: The skb to unmap.
 */
void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);


/**
/**
 * rt2x00queue_free_skb - free a skb
 * rt2x00queue_free_skb - free a skb
 * @rt2x00dev: Pointer to &struct rt2x00_dev.
 * @skb: The skb to free.
 * @skb: The skb to free.
 */
 */
void rt2x00queue_free_skb(struct sk_buff *skb);
void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);


/**
/**
 * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input
 * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input
@@ -977,8 +995,8 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_txdone(struct queue_entry *entry,
void rt2x00lib_txdone(struct queue_entry *entry,
		      struct txdone_entry_desc *txdesc);
		      struct txdone_entry_desc *txdesc);
void rt2x00lib_rxdone(struct queue_entry *entry,
void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
		      struct rxdone_entry_desc *rxdesc);
		      struct queue_entry *entry);


/*
/*
 * mac80211 handlers.
 * mac80211 handlers.
+45 −19
Original line number Original line Diff line number Diff line
@@ -468,6 +468,7 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
				      struct ieee80211_vif *vif)
				      struct ieee80211_vif *vif)
{
{
	struct rt2x00_dev *rt2x00dev = data;
	struct rt2x00_intf *intf = vif_to_intf(vif);
	struct rt2x00_intf *intf = vif_to_intf(vif);


	if (vif->type != IEEE80211_IF_TYPE_AP &&
	if (vif->type != IEEE80211_IF_TYPE_AP &&
@@ -477,7 +478,7 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
	/*
	/*
	 * Clean up the beacon skb.
	 * Clean up the beacon skb.
	 */
	 */
	dev_kfree_skb_irq(intf->beacon->skb);
	rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb);
	intf->beacon->skb = NULL;
	intf->beacon->skb = NULL;


	spin_lock(&intf->lock);
	spin_lock(&intf->lock);
@@ -555,34 +556,55 @@ void rt2x00lib_txdone(struct queue_entry *entry,
}
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);


void rt2x00lib_rxdone(struct queue_entry *entry,
void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
		      struct rxdone_entry_desc *rxdesc)
		      struct queue_entry *entry)
{
{
	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
	struct rxdone_entry_desc rxdesc;
	struct sk_buff *skb;
	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
	struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
	unsigned int header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
	struct ieee80211_supported_band *sband;
	struct ieee80211_supported_band *sband;
	struct ieee80211_hdr *hdr;
	struct ieee80211_hdr *hdr;
	const struct rt2x00_rate *rate;
	const struct rt2x00_rate *rate;
	unsigned int header_size;
	unsigned int align;
	unsigned int align;
	unsigned int i;
	unsigned int i;
	int idx = -1;
	int idx = -1;


	/*
	 * Allocate a new sk_buffer. If no new buffer available, drop the
	 * received frame and reuse the existing buffer.
	 */
	skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry);
	if (!skb)
		return;

	/*
	 * Unmap the skb.
	 */
	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);

	/*
	 * Extract the RXD details.
	 */
	memset(&rxdesc, 0, sizeof(rxdesc));
	rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);

	/*
	/*
	 * The data behind the ieee80211 header must be
	 * The data behind the ieee80211 header must be
	 * aligned on a 4 byte boundary.
	 * aligned on a 4 byte boundary.
	 */
	 */
	header_size = ieee80211_get_hdrlen_from_skb(entry->skb);
	align = ((unsigned long)(entry->skb->data + header_size)) & 3;
	align = ((unsigned long)(entry->skb->data + header_size)) & 3;


	if (align) {
	if (align) {
		skb_push(entry->skb, align);
		skb_push(entry->skb, align);
		/* Move entire frame in 1 command */
		/* Move entire frame in 1 command */
		memmove(entry->skb->data, entry->skb->data + align,
		memmove(entry->skb->data, entry->skb->data + align,
			rxdesc->size);
			rxdesc.size);
	}
	}


	/* Update data pointers, trim buffer to correct size */
	/* Update data pointers, trim buffer to correct size */
	skb_trim(entry->skb, rxdesc->size);
	skb_trim(entry->skb, rxdesc.size);


	/*
	/*
	 * Update RX statistics.
	 * Update RX statistics.
@@ -591,10 +613,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry,
	for (i = 0; i < sband->n_bitrates; i++) {
	for (i = 0; i < sband->n_bitrates; i++) {
		rate = rt2x00_get_rate(sband->bitrates[i].hw_value);
		rate = rt2x00_get_rate(sband->bitrates[i].hw_value);


		if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
		if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
		     (rate->plcp == rxdesc->signal)) ||
		     (rate->plcp == rxdesc.signal)) ||
		    (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) &&
		    (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) &&
		      (rate->bitrate == rxdesc->signal))) {
		      (rate->bitrate == rxdesc.signal))) {
			idx = i;
			idx = i;
			break;
			break;
		}
		}
@@ -602,8 +624,8 @@ void rt2x00lib_rxdone(struct queue_entry *entry,


	if (idx < 0) {
	if (idx < 0) {
		WARNING(rt2x00dev, "Frame received with unrecognized signal,"
		WARNING(rt2x00dev, "Frame received with unrecognized signal,"
			"signal=0x%.2x, plcp=%d.\n", rxdesc->signal,
			"signal=0x%.2x, plcp=%d.\n", rxdesc.signal,
			!!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP));
			!!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP));
		idx = 0;
		idx = 0;
	}
	}


@@ -612,16 +634,16 @@ void rt2x00lib_rxdone(struct queue_entry *entry,
	 */
	 */
	hdr = (struct ieee80211_hdr *)entry->skb->data;
	hdr = (struct ieee80211_hdr *)entry->skb->data;
	if (ieee80211_is_beacon(hdr->frame_control) &&
	if (ieee80211_is_beacon(hdr->frame_control) &&
	    (rxdesc->dev_flags & RXDONE_MY_BSS))
	    (rxdesc.dev_flags & RXDONE_MY_BSS))
		rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi);
		rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi);


	rt2x00dev->link.qual.rx_success++;
	rt2x00dev->link.qual.rx_success++;


	rx_status->rate_idx = idx;
	rx_status->rate_idx = idx;
	rx_status->qual =
	rx_status->qual =
	    rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi);
	    rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi);
	rx_status->signal = rxdesc->rssi;
	rx_status->signal = rxdesc.rssi;
	rx_status->flag = rxdesc->flags;
	rx_status->flag = rxdesc.flags;
	rx_status->antenna = rt2x00dev->link.ant.active.rx;
	rx_status->antenna = rt2x00dev->link.ant.active.rx;


	/*
	/*
@@ -630,7 +652,11 @@ void rt2x00lib_rxdone(struct queue_entry *entry,
	 */
	 */
	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb);
	ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
	ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status);
	entry->skb = NULL;

	/*
	 * Replace the skb with the freshly allocated one.
	 */
	entry->skb = skb;
}
}
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);


+33 −92
Original line number Original line Diff line number Diff line
@@ -65,7 +65,7 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry)
	skbdesc->desc_len = entry->queue->desc_size;
	skbdesc->desc_len = entry->queue->desc_size;
	skbdesc->entry = entry;
	skbdesc->entry = entry;


	memcpy(entry_priv->data, entry->skb->data, entry->skb->len);
	rt2x00queue_map_txskb(entry->queue->rt2x00dev, entry->skb);


	return 0;
	return 0;
}
}
@@ -74,75 +74,38 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
/*
/*
 * TX/RX data handlers.
 * TX/RX data handlers.
 */
 */
static void rt2x00pci_rxdone_entry(struct rt2x00_dev *rt2x00dev,
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
				   struct queue_entry *entry)
{
{
	struct sk_buff *skb;
	struct data_queue *queue = rt2x00dev->rx;
	struct queue_entry *entry;
	struct queue_entry_priv_pci *entry_priv;
	struct skb_frame_desc *skbdesc;
	struct skb_frame_desc *skbdesc;
	struct rxdone_entry_desc rxdesc;
	u32 word;
	struct queue_entry_priv_pci *entry_priv = entry->priv_data;

	/*
	 * Allocate a new sk_buffer. If no new buffer available, drop the
	 * received frame and reuse the existing buffer.
	 */
	skb = rt2x00queue_alloc_skb(entry->queue);
	if (!skb)
		return;


	/*
	while (1) {
	 * Extract the RXD details.
		entry = rt2x00queue_get_entry(queue, Q_INDEX);
	 */
		entry_priv = entry->priv_data;
	memset(&rxdesc, 0, sizeof(rxdesc));
		rt2x00_desc_read(entry_priv->desc, 0, &word);
	rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);


	/*
		if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
	 * Copy the received data to the entries' skb.
			break;
	 */
	memcpy(entry->skb->data, entry_priv->data, rxdesc.size);
	skb_trim(entry->skb, rxdesc.size);


		/*
		/*
	 * Fill in skb descriptor
		 * Fill in desc fields of the skb descriptor
		 */
		 */
		skbdesc = get_skb_frame_desc(entry->skb);
		skbdesc = get_skb_frame_desc(entry->skb);
	memset(skbdesc, 0, sizeof(*skbdesc));
		skbdesc->desc = entry_priv->desc;
		skbdesc->desc = entry_priv->desc;
		skbdesc->desc_len = entry->queue->desc_size;
		skbdesc->desc_len = entry->queue->desc_size;
	skbdesc->entry = entry;


		/*
		/*
		 * Send the frame to rt2x00lib for further processing.
		 * Send the frame to rt2x00lib for further processing.
		 */
		 */
	rt2x00lib_rxdone(entry, &rxdesc);
		rt2x00lib_rxdone(rt2x00dev, entry);


		/*
		/*
	 * Replace the entries' skb with the newly allocated one.
		 * Reset the RXD for this entry.
		 */
		 */
	entry->skb = skb;
		rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry);
}

void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
{
	struct data_queue *queue = rt2x00dev->rx;
	struct queue_entry *entry;
	struct queue_entry_priv_pci *entry_priv;
	u32 word;

	while (1) {
		entry = rt2x00queue_get_entry(queue, Q_INDEX);
		entry_priv = entry->priv_data;
		rt2x00_desc_read(entry_priv->desc, 0, &word);

		if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
			break;

		rt2x00pci_rxdone_entry(rt2x00dev, entry);

		if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) {
			rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
			rt2x00_desc_write(entry_priv->desc, 0, word);
		}


		rt2x00queue_index_inc(queue, Q_INDEX);
		rt2x00queue_index_inc(queue, Q_INDEX);
	}
	}
@@ -156,6 +119,11 @@ void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry,
	enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
	enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
	u32 word;
	u32 word;


	/*
	 * Unmap the skb.
	 */
	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);

	rt2x00lib_txdone(entry, txdesc);
	rt2x00lib_txdone(entry, txdesc);


	/*
	/*
@@ -185,33 +153,6 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
/*
/*
 * Device initialization handlers.
 * Device initialization handlers.
 */
 */
#define desc_size(__queue)			\
({						\
	 ((__queue)->limit * (__queue)->desc_size);\
})

#define data_size(__queue)			\
({						\
	 ((__queue)->limit * (__queue)->data_size);\
})

#define dma_size(__queue)			\
({						\
	data_size(__queue) + desc_size(__queue);\
})

#define desc_offset(__queue, __base, __i)	\
({						\
	(__base) + data_size(__queue) + 	\
	    ((__i) * (__queue)->desc_size);	\
})

#define data_offset(__queue, __base, __i)	\
({						\
	(__base) +				\
	    ((__i) * (__queue)->data_size);	\
})

static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
				     struct data_queue *queue)
				     struct data_queue *queue)
{
{
@@ -223,22 +164,21 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
	/*
	/*
	 * Allocate DMA memory for descriptor and buffer.
	 * Allocate DMA memory for descriptor and buffer.
	 */
	 */
	addr = dma_alloc_coherent(rt2x00dev->dev, dma_size(queue), &dma,
	addr = dma_alloc_coherent(rt2x00dev->dev,
				  GFP_KERNEL | GFP_DMA);
				  queue->limit * queue->desc_size,
				  &dma, GFP_KERNEL | GFP_DMA);
	if (!addr)
	if (!addr)
		return -ENOMEM;
		return -ENOMEM;


	memset(addr, 0, dma_size(queue));
	memset(addr, 0, queue->limit * queue->desc_size);


	/*
	/*
	 * Initialize all queue entries to contain valid addresses.
	 * Initialize all queue entries to contain valid addresses.
	 */
	 */
	for (i = 0; i < queue->limit; i++) {
	for (i = 0; i < queue->limit; i++) {
		entry_priv = queue->entries[i].priv_data;
		entry_priv = queue->entries[i].priv_data;
		entry_priv->desc = desc_offset(queue, addr, i);
		entry_priv->desc = addr + i * queue->desc_size;
		entry_priv->desc_dma = desc_offset(queue, dma, i);
		entry_priv->desc_dma = dma + i * queue->desc_size;
		entry_priv->data = data_offset(queue, addr, i);
		entry_priv->data_dma = data_offset(queue, dma, i);
	}
	}


	return 0;
	return 0;
@@ -250,10 +190,11 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev,
	struct queue_entry_priv_pci *entry_priv =
	struct queue_entry_priv_pci *entry_priv =
	    queue->entries[0].priv_data;
	    queue->entries[0].priv_data;


	if (entry_priv->data)
	if (entry_priv->desc)
		dma_free_coherent(rt2x00dev->dev, dma_size(queue),
		dma_free_coherent(rt2x00dev->dev,
				  entry_priv->data, entry_priv->data_dma);
				  queue->limit * queue->desc_size,
	entry_priv->data = NULL;
				  entry_priv->desc, entry_priv->desc_dma);
	entry_priv->desc = NULL;
}
}


int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
Loading