|
@@ -404,6 +404,46 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
|
|
rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
|
|
|
}
|
|
|
|
|
|
+static int rt2x00queue_write_tx_data(struct queue_entry *entry,
|
|
|
+ struct txentry_desc *txdesc)
|
|
|
+{
|
|
|
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This should not happen, we already checked the entry
|
|
|
+ * was ours. When the hardware disagrees there has been
|
|
|
+ * a queue corruption!
|
|
|
+ */
|
|
|
+ if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
|
|
|
+ rt2x00dev->ops->lib->get_entry_state(entry))) {
|
|
|
+ ERROR(rt2x00dev,
|
|
|
+ "Corrupt queue %d, accessing entry which is not ours.\n"
|
|
|
+ "Please file bug report to %s.\n",
|
|
|
+ entry->queue->qid, DRV_PROJECT);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Add the requested extra tx headroom in front of the skb.
|
|
|
+ */
|
|
|
+ skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
|
|
|
+ memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Call the driver's write_tx_datadesc function, if it exists.
|
|
|
+ */
|
|
|
+ if (rt2x00dev->ops->lib->write_tx_datadesc)
|
|
|
+ rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Map the skb to DMA.
|
|
|
+ */
|
|
|
+ if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
|
|
|
+ rt2x00queue_map_txskb(rt2x00dev, entry->skb);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
|
|
|
struct txentry_desc *txdesc)
|
|
|
{
|
|
@@ -515,8 +555,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
|
|
|
* call failed. Since we always return NETDEV_TX_OK to mac80211,
|
|
|
* this frame will simply be dropped.
|
|
|
*/
|
|
|
- if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry,
|
|
|
- &txdesc))) {
|
|
|
+ if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
|
|
|
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
|
|
|
entry->skb = NULL;
|
|
|
return -EIO;
|