Search Linux Wireless

Re: [RFC][RFT][PATCH 0/5 v5] ar9170: ar9170 driver (aka mac80211's otus)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Christian!

> Based on the number of mails I got, this driver should be ready for
> inclusion.

ACK

> So, this is probably the last RFC and the official patches will follow on
> sunday (only if no one finds a bug that needs to be fixed ASAP.)

This is not same driver. Its much different, and I couldn't follow the changes in Johannes' git repository.

Today, if have implement rate control (the needed ieee80211_tx_status_irqsafe() calls) for the original code. Now after one hour this code already outdated. :/

In your code the implementation of it is not yet complete?

Regards
Alina

-- 
Aufgepasst: Sind Ihre Daten beim Online-Banking auch optimal geschützt?
Jetzt absichern: https://homebanking.gmx.net/?mc=mail@xxxxxxxxx
diff --git a/ar9170.h b/ar9170.h
index 4ad272c..b65da25 100644
--- a/ar9170.h
+++ b/ar9170.h
@@ -70,6 +70,8 @@ enum ar9170_rf_init_mode {
 #define AR9170_MAX_RX_BUFFER_SIZE		8192
 #define AR9170_NUM_RX_URBS			16
 
+#define AR9170_MAX_TX_STATUS			10
+
 struct ar9170;
 
 struct ar9170_led {
@@ -102,9 +104,8 @@ struct ar9170 {
 	int readlen;
 	u8 *readbuf;
 
-	struct sk_buff *tx_status_queue_head;
-	struct sk_buff *tx_status_queue_tail;
 	spinlock_t tx_status_lock;
+	struct sk_buff_head tx_status_queue;
 
 	/* power calibration data */
 	u8 power_5G_leg[4];
diff --git a/hw.h b/hw.h
index 7eae0ea..4d6c69c 100644
--- a/hw.h
+++ b/hw.h
@@ -149,7 +149,7 @@ enum ar9170_cmd {
 #define AR9170_MAC_REG_FTF_ACK			BIT(29)
 #define AR9170_MAC_REG_FTF_CFE			BIT(30)
 #define AR9170_MAC_REG_FTF_CFE_ACK		BIT(31)
-#define AR9170_MAC_REG_FTF_DEFAULTS		0x0500ffff
+#define AR9170_MAC_REG_FTF_DEFAULTS		0x2500ffff
 
 #define AR9170_MAC_REG_RX_TOTAL			(AR9170_MAC_REG_BASE + 0x6A0)
 #define AR9170_MAC_REG_RX_CRC32			(AR9170_MAC_REG_BASE + 0x6A4)
diff --git a/main.c b/main.c
index 8a9ddf7..7319c20 100644
--- a/main.c
+++ b/main.c
@@ -220,6 +220,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
 static void ar9170_op_stop(struct ieee80211_hw *hw)
 {
 	struct ar9170 *ar = hw->priv;
+	struct sk_buff *skb;
 
 	mutex_lock(&ar->mutex);
 
@@ -228,54 +229,53 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
 
 	ar->started = false;
 
-	mutex_unlock(&ar->mutex);
-}
+	while ((skb = skb_dequeue(&ar->tx_status_queue)))
+		dev_kfree_skb_any(skb);
 
-#if 0
-static inline void ar9170_add_tx_status_skb(struct ar9170 *ar,
-					    struct sk_buff *skb)
-{
-	skb->next = NULL;
-
-	if (ar->tx_status_queue_tail) {
-		ar->tx_status_queue_tail->next = skb;
-		ar->tx_status_queue_tail = skb;
-	} else {
-		ar->tx_status_queue_tail = skb;
-		ar->tx_status_queue_head = skb;
-	}
+	mutex_unlock(&ar->mutex);
 }
 
-static inline struct sk_buff *ar9170_get_tx_status_skb(struct ar9170 *ar)
+static void ar9170_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+                             int ack_signal, bool success)
 {
-	struct sk_buff *skb;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
-	skb = ar->tx_status_queue_head;
+	ieee80211_tx_info_clear_status(info);
 
-	if (skb) {
-		ar->tx_status_queue_head = skb->next;
-		if (ar->tx_status_queue_tail == skb)
-			ar->tx_status_queue_tail = NULL;
-	}
+	if (success)
+		info->flags |= IEEE80211_TX_STAT_ACK;
+	info->status.ack_signal = ack_signal;
 
-	return skb;
+	ieee80211_tx_status_irqsafe(hw, skb);
 }
-#endif
 
 static void tx_urb_complete(struct urb *urb)
 {
-	struct sk_buff *skb = (void *)urb->context;
-/*
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct ar9170 *ar = info->rate_driver_data[0];
- */
+	struct ieee80211_hw *hw = info->rate_driver_data[0];
+	struct ar9170 *ar = hw->priv;
+	struct sk_buff *outdated_skb;
 
 	/*
 	 * For proper rate control we really need to provide
-	 * TX status callbacks. For now, don't.
+	 * TX status callbacks.
 	 */
+
+	skb_pull(skb, sizeof(struct ar9170_tx_control));
+	if (urb->status || (info->flags & IEEE80211_TX_CTL_NO_ACK))
+		ar9170_tx_status(hw, skb, 0, !urb->status);
+	else {
+		skb_queue_tail(&ar->tx_status_queue, skb);
+
+		while (skb_queue_len(&ar->tx_status_queue) > AR9170_MAX_TX_STATUS) {
+			outdated_skb = skb_dequeue(&ar->tx_status_queue);
+			if (outdated_skb)
+				ar9170_tx_status(hw, outdated_skb, 0, 0);
+		}
+	}
+
 	usb_free_urb(urb);
-	dev_kfree_skb_irq(skb);
 }
 
 int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
@@ -419,7 +419,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	if (!urb)
 		goto free;
 
-	info->rate_driver_data[0] = ar;
+	info->rate_driver_data[0] = hw;
 
 	usb_fill_bulk_urb(urb, ar->udev,
 			  usb_sndbulkpipe(ar->udev, AR9170_EP_TX),
@@ -881,6 +881,7 @@ static struct ar9170 *ar9170_alloc(struct usb_interface *intf)
 	mutex_init(&ar->mutex);
 	spin_lock_init(&ar->cmdlock);
 	spin_lock_init(&ar->tx_status_lock);
+	skb_queue_head_init(&ar->tx_status_queue);
 	INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
 	INIT_WORK(&ar->led_work, ar9170_update_leds);
 	INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
@@ -1107,6 +1108,10 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
 	struct ieee80211_rx_status status;
 	int mpdu_len, i;
 	u8 error, antennas = 0, decrypt;
+	struct ieee80211_hdr *rx_hdr;
+	unsigned long flags;
+	struct sk_buff *tx_skb;
+	struct ieee80211_hdr *tx_hdr;
 	__le16 fc;
 	int reserved;
 
@@ -1239,8 +1244,30 @@ static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
 	}
 
 	buf += sizeof(struct ar9170_rx_head);
-	fc = *(__le16 *)buf;
 
+	/*
+	 * For proper rate control we really need to provide
+	 * TX status callbacks.
+	 */
+
+	rx_hdr = (struct ieee80211_hdr *)buf;
+	if (ieee80211_is_ack(rx_hdr->frame_control)) {
+		spin_lock_irqsave(&ar->tx_status_queue.lock, flags);
+
+		skb_queue_walk(&ar->tx_status_queue, tx_skb) {
+			tx_hdr = (struct ieee80211_hdr *)tx_skb->data;
+			if (memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN) == 0) {
+				__skb_unlink(tx_skb, &ar->tx_status_queue);
+				printk("!!!\n");
+				ar9170_tx_status(ar->hw, tx_skb, status.signal, 1);
+				break;
+			}
+		}
+
+		spin_unlock_irqrestore(&ar->tx_status_queue.lock, flags);
+	}
+
+	fc = *(__le16 *)buf;
 	if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc))
 		reserved=32+2;
 	else

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux