Skip to contentSkip to conversation

fakelb: rework driver implementation

RFC New Alexander Aring 1 participant 14 messages May 16, 2015

Subsystems (2)
lore
Share & tools
lore

Alexander Aring

author maintainer
#0 lore raw

cover fakelb: rework driver implementation

Hi,

this patch series completes rework the fakelb driver. After loading the fakelb driver you have as default two registered phys. Example use:

1. Creating a lowpan interface on each wpan interface.

2. try IPv6 connection between the two lowpan interfaces.

This patch series based on
"mac802154: fakelb: Fix potential NULL pointer dereference." by Martin Townsend.

- Alex

Alexander Aring (13):
fakelb: creating two virtual phys per default
fakelb: use list_for_each_entry_safe
fakelb: rename fakelb_dev_priv to fakelb_phy
fakelb: don't deliver when one phy
fakelb: declare rwlock static
fakelb: declare fakelb list static
fakelb: move lock out of iteration
fakelb: introduce fakelb ifup phys list
fakelb: use own channel and page attributes
fakelb: add virtual phy reset defaults
fakelb: remove fakelb_hw_deliver
fakelb: add support for async xmit handling
fakelb: cleanup code

 drivers/net/ieee802154/fakelb.c | 180 +++++++++++++++++-----------------------
 1 file changed, 76 insertions(+), 104 deletions(-)
Signature · 1 line
2.3.7
author maintainer
#1 lore raw

RFC 1/13 fakelb: creating two virtual phys per default

This patch change the default virtual wpan phys of fakelb driver from one to two. To have one virtual phy makes no sense, because it need at least two virtual phy's to speak to each other.

---
 drivers/net/ieee802154/fakelb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ieee802154/fakelb.c +1 -1
index baa8d36..0fe42b0 100644
@@ -27,7 +27,7 @@
 #include <net/mac802154.h>
 #include <net/cfg802154.h>
 
-static int numlbs = 1;
+static int numlbs = 2;
 
 struct fakelb_dev_priv {
 	struct ieee802154_hw *hw;
Signature · 1 line
2.3.7
author maintainer
#2 lore raw

RFC 2/13 fakelb: use list_for_each_entry_safe

In reply to Alexander Aring

Iterate and removing items from a list, we should use list_for_each_entry_safe instead list_for_each_entry to avoid accidents by removing.

---
 drivers/net/ieee802154/fakelb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ieee802154/fakelb.c +2 -2
index 0fe42b0..43b0336 100644
@@ -215,7 +215,7 @@ static void fakelb_del(struct fakelb_dev_priv *priv)
 static int fakelb_probe(struct platform_device *pdev)
 {
 	struct fakelb_priv *priv;
-	struct fakelb_dev_priv *dp;
+	struct fakelb_dev_priv *dp, *tmp;
 	int err = -ENOMEM;
 	int i;
 
@@ -238,7 +238,7 @@ static int fakelb_probe(struct platform_device *pdev)
 	return 0;
 
 err_slave:
-	list_for_each_entry(dp, &priv->list, list)
+	list_for_each_entry_safe(dp, tmp, &priv->list, list)
 		fakelb_del(dp);
 err_alloc:
 	return err;
Signature · 1 line
2.3.7
author maintainer
#3 lore raw

RFC 3/13 fakelb: rename fakelb_dev_priv to fakelb_phy

In reply to Alexander Aring

This patch renames fakelb_dev_priv to fakelb_phy. We don't faking devices here, we fake wpan phys. This avoids also confusing with the variable priv, which is used several times in this driver to represent this structure.

---
 drivers/net/ieee802154/fakelb.c | 93 +++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 46 deletions(-)
drivers/net/ieee802154/fakelb.c +47 -46
index 43b0336..084208d 100644
@@ -29,7 +29,7 @@
 
 static int numlbs = 2;
 
-struct fakelb_dev_priv {
+struct fakelb_phy {
 	struct ieee802154_hw *hw;
 
 	struct list_head list;
@@ -62,36 +62,37 @@ fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 }
 
 static void
-fakelb_hw_deliver(struct fakelb_dev_priv *priv, struct sk_buff *skb)
+fakelb_hw_deliver(struct fakelb_phy *phy, struct sk_buff *skb)
 {
 	struct sk_buff *newskb;
 
-	spin_lock(&priv->lock);
-	if (priv->working) {
+	spin_lock(&phy->lock);
+	if (phy->working) {
 		newskb = pskb_copy(skb, GFP_ATOMIC);
 		if (newskb)
-			ieee802154_rx_irqsafe(priv->hw, newskb, 0xcc);
+			ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc);
 	}
-	spin_unlock(&priv->lock);
+	spin_unlock(&phy->lock);
 }
 
 static int
 fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 {
-	struct fakelb_dev_priv *priv = hw->priv;
-	struct fakelb_priv *fake = priv->fake;
+	struct fakelb_phy *current_phy = hw->priv;
+	struct fakelb_priv *fake = current_phy->fake;
 
 	read_lock_bh(&fake->lock);
-	if (priv->list.next == priv->list.prev) {
+	if (current_phy->list.next == current_phy->list.prev) {
 		/* we are the only one device */
-		fakelb_hw_deliver(priv, skb);
+		fakelb_hw_deliver(current_phy, skb);
 	} else {
-		struct fakelb_dev_priv *dp;
-		list_for_each_entry(dp, &priv->fake->list, list) {
-			if (dp != priv &&
-			    (dp->hw->phy->current_channel ==
-			     priv->hw->phy->current_channel))
-				fakelb_hw_deliver(dp, skb);
+		struct fakelb_phy *phy;
+
+		list_for_each_entry(phy, &current_phy->fake->list, list) {
+			if (current_phy != phy &&
+			    (phy->hw->phy->current_channel ==
+			     current_phy->hw->phy->current_channel))
+				fakelb_hw_deliver(phy, skb);
 		}
 	}
 	read_unlock_bh(&fake->lock);
@@ -101,26 +102,26 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 
 static int
 fakelb_hw_start(struct ieee802154_hw *hw) {
-	struct fakelb_dev_priv *priv = hw->priv;
+	struct fakelb_phy *phy = hw->priv;
 	int ret = 0;
 
-	spin_lock(&priv->lock);
-	if (priv->working)
+	spin_lock(&phy->lock);
+	if (phy->working)
 		ret = -EBUSY;
 	else
-		priv->working = 1;
-	spin_unlock(&priv->lock);
+		phy->working = 1;
+	spin_unlock(&phy->lock);
 
 	return ret;
 }
 
 static void
 fakelb_hw_stop(struct ieee802154_hw *hw) {
-	struct fakelb_dev_priv *priv = hw->priv;
+	struct fakelb_phy *phy = hw->priv;
 
-	spin_lock(&priv->lock);
-	priv->working = 0;
-	spin_unlock(&priv->lock);
+	spin_lock(&phy->lock);
+	phy->working = 0;
+	spin_unlock(&phy->lock);
 }
 
 static const struct ieee802154_ops fakelb_ops = {
@@ -138,16 +139,16 @@ MODULE_PARM_DESC(numlbs, " number of pseudo devices");
 
 static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
 {
-	struct fakelb_dev_priv *priv;
+	struct fakelb_phy *phy;
 	int err;
 	struct ieee802154_hw *hw;
 
-	hw = ieee802154_alloc_hw(sizeof(*priv), &fakelb_ops);
+	hw = ieee802154_alloc_hw(sizeof(*phy), &fakelb_ops);
 	if (!hw)
 		return -ENOMEM;
 
-	priv = hw->priv;
-	priv->hw = hw;
+	phy = hw->priv;
+	phy->hw = hw;
 
 	/* 868 MHz BPSK	802.15.4-2003 */
 	hw->phy->channels_supported[0] |= 1;
@@ -180,10 +181,10 @@ static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
 	/* 950 MHz GFSK 802.15.4d-2009 */
 	hw->phy->channels_supported[6] |= 0x3ffc00;
 
-	INIT_LIST_HEAD(&priv->list);
-	priv->fake = fake;
+	INIT_LIST_HEAD(&phy->list);
+	phy->fake = fake;
 
-	spin_lock_init(&priv->lock);
+	spin_lock_init(&phy->lock);
 
 	hw->parent = dev;
 
@@ -192,30 +193,30 @@ static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
 		goto err_reg;
 
 	write_lock_bh(&fake->lock);
-	list_add_tail(&priv->list, &fake->list);
+	list_add_tail(&phy->list, &fake->list);
 	write_unlock_bh(&fake->lock);
 
 	return 0;
 
 err_reg:
-	ieee802154_free_hw(priv->hw);
+	ieee802154_free_hw(phy->hw);
 	return err;
 }
 
-static void fakelb_del(struct fakelb_dev_priv *priv)
+static void fakelb_del(struct fakelb_phy *phy)
 {
-	write_lock_bh(&priv->fake->lock);
-	list_del(&priv->list);
-	write_unlock_bh(&priv->fake->lock);
+	write_lock_bh(&phy->fake->lock);
+	list_del(&phy->list);
+	write_unlock_bh(&phy->fake->lock);
 
-	ieee802154_unregister_hw(priv->hw);
-	ieee802154_free_hw(priv->hw);
+	ieee802154_unregister_hw(phy->hw);
+	ieee802154_free_hw(phy->hw);
 }
 
 static int fakelb_probe(struct platform_device *pdev)
 {
 	struct fakelb_priv *priv;
-	struct fakelb_dev_priv *dp, *tmp;
+	struct fakelb_phy *phy, *tmp;
 	int err = -ENOMEM;
 	int i;
 
@@ -238,8 +239,8 @@ static int fakelb_probe(struct platform_device *pdev)
 	return 0;
 
 err_slave:
-	list_for_each_entry_safe(dp, tmp, &priv->list, list)
-		fakelb_del(dp);
+	list_for_each_entry_safe(phy, tmp, &priv->list, list)
+		fakelb_del(phy);
 err_alloc:
 	return err;
 }
@@ -247,10 +248,10 @@ err_alloc:
 static int fakelb_remove(struct platform_device *pdev)
 {
 	struct fakelb_priv *priv = platform_get_drvdata(pdev);
-	struct fakelb_dev_priv *dp, *temp;
+	struct fakelb_phy *phy, *temp;
 
-	list_for_each_entry_safe(dp, temp, &priv->list, list)
-		fakelb_del(dp);
+	list_for_each_entry_safe(phy, temp, &priv->list, list)
+		fakelb_del(phy);
 
 	return 0;
 }
Signature · 1 line
2.3.7
author maintainer
#4 lore raw

RFC 4/13 fakelb: don't deliver when one phy

In reply to Alexander Aring

A real phy don't transmit the transmitted frame back to the phy. This behaviour will confuse the 6LoWPAN and the upper IPv6 neighbour discovery cache. We need now at least two virtual phy's to creating a virtual wpan network.

---
 drivers/net/ieee802154/fakelb.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)
drivers/net/ieee802154/fakelb.c +8 -12
index 084208d..e10eb85 100644
@@ -80,20 +80,16 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 {
 	struct fakelb_phy *current_phy = hw->priv;
 	struct fakelb_priv *fake = current_phy->fake;
+	struct fakelb_phy *phy;
 
 	read_lock_bh(&fake->lock);
-	if (current_phy->list.next == current_phy->list.prev) {
-		/* we are the only one device */
-		fakelb_hw_deliver(current_phy, skb);
-	} else {
-		struct fakelb_phy *phy;
-
-		list_for_each_entry(phy, &current_phy->fake->list, list) {
-			if (current_phy != phy &&
-			    (phy->hw->phy->current_channel ==
-			     current_phy->hw->phy->current_channel))
-				fakelb_hw_deliver(phy, skb);
-		}
+	list_for_each_entry(phy, &current_phy->fake->list, list) {
+		if (current_phy == phy)
+			continue;
+
+		if (phy->hw->phy->current_channel ==
+		    current_phy->hw->phy->current_channel)
+			fakelb_hw_deliver(phy, skb);
 	}
 	read_unlock_bh(&fake->lock);
 
Signature · 1 line
2.3.7
author maintainer
#5 lore raw

RFC 5/13 fakelb: declare rwlock static

In reply to Alexander Aring

This patch moves the rwlock declarition into a static variable.

---
 drivers/net/ieee802154/fakelb.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)
drivers/net/ieee802154/fakelb.c +7 -9
index e10eb85..2dcc209 100644
@@ -28,6 +28,7 @@
 #include <net/cfg802154.h>
 
 static int numlbs = 2;
+static DEFINE_RWLOCK(fakelb_lock);
 
 struct fakelb_phy {
 	struct ieee802154_hw *hw;
@@ -41,7 +42,6 @@ struct fakelb_phy {
 
 struct fakelb_priv {
 	struct list_head list;
-	rwlock_t lock;
 };
 
 static int
@@ -79,10 +79,9 @@ static int
 fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 {
 	struct fakelb_phy *current_phy = hw->priv;
-	struct fakelb_priv *fake = current_phy->fake;
 	struct fakelb_phy *phy;
 
-	read_lock_bh(&fake->lock);
+	read_lock_bh(&fakelb_lock);
 	list_for_each_entry(phy, &current_phy->fake->list, list) {
 		if (current_phy == phy)
 			continue;
@@ -91,7 +90,7 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 		    current_phy->hw->phy->current_channel)
 			fakelb_hw_deliver(phy, skb);
 	}
-	read_unlock_bh(&fake->lock);
+	read_unlock_bh(&fakelb_lock);
 
 	return 0;
 }
@@ -188,9 +187,9 @@ static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
 	if (err)
 		goto err_reg;
 
-	write_lock_bh(&fake->lock);
+	write_lock_bh(&fakelb_lock);
 	list_add_tail(&phy->list, &fake->list);
-	write_unlock_bh(&fake->lock);
+	write_unlock_bh(&fakelb_lock);
 
 	return 0;
 
@@ -201,9 +200,9 @@ err_reg:
 
 static void fakelb_del(struct fakelb_phy *phy)
 {
-	write_lock_bh(&phy->fake->lock);
+	write_lock_bh(&fakelb_lock);
 	list_del(&phy->list);
-	write_unlock_bh(&phy->fake->lock);
+	write_unlock_bh(&fakelb_lock);
 
 	ieee802154_unregister_hw(phy->hw);
 	ieee802154_free_hw(phy->hw);
@@ -222,7 +221,6 @@ static int fakelb_probe(struct platform_device *pdev)
 		goto err_alloc;
 
 	INIT_LIST_HEAD(&priv->list);
-	rwlock_init(&priv->lock);
 
 	for (i = 0; i < numlbs; i++) {
 		err = fakelb_add_one(&pdev->dev, priv);
Signature · 1 line
2.3.7
author maintainer
#6 lore raw

RFC 6/13 fakelb: declare fakelb list static

In reply to Alexander Aring

This patch moves the fakelb list of all registered phy's in a static declaration in the fakelb driver.

---
 drivers/net/ieee802154/fakelb.c | 32 +++++++-------------------------
 1 file changed, 7 insertions(+), 25 deletions(-)
drivers/net/ieee802154/fakelb.c +7 -25
index 2dcc209..850d5b3 100644
@@ -29,21 +29,17 @@
 
 static int numlbs = 2;
 static DEFINE_RWLOCK(fakelb_lock);
+static LIST_HEAD(fakelb_phys);
 
 struct fakelb_phy {
 	struct ieee802154_hw *hw;
 
 	struct list_head list;
-	struct fakelb_priv *fake;
 
 	spinlock_t lock;
 	bool working;
 };
 
-struct fakelb_priv {
-	struct list_head list;
-};
-
 static int
 fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
 {
@@ -82,7 +78,7 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 	struct fakelb_phy *phy;
 
 	read_lock_bh(&fakelb_lock);
-	list_for_each_entry(phy, &current_phy->fake->list, list) {
+	list_for_each_entry(phy, &fakelb_phys, list) {
 		if (current_phy == phy)
 			continue;
 
@@ -132,7 +128,7 @@ static const struct ieee802154_ops fakelb_ops = {
 module_param(numlbs, int, 0);
 MODULE_PARM_DESC(numlbs, " number of pseudo devices");
 
-static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
+static int fakelb_add_one(struct device *dev)
 {
 	struct fakelb_phy *phy;
 	int err;
@@ -176,9 +172,6 @@ static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
 	/* 950 MHz GFSK 802.15.4d-2009 */
 	hw->phy->channels_supported[6] |= 0x3ffc00;
 
-	INIT_LIST_HEAD(&phy->list);
-	phy->fake = fake;
-
 	spin_lock_init(&phy->lock);
 
 	hw->parent = dev;
@@ -188,7 +181,7 @@ static int fakelb_add_one(struct device *dev, struct fakelb_priv *fake)
 		goto err_reg;
 
 	write_lock_bh(&fakelb_lock);
-	list_add_tail(&phy->list, &fake->list);
+	list_add_tail(&phy->list, &fakelb_phys);
 	write_unlock_bh(&fakelb_lock);
 
 	return 0;
@@ -210,41 +203,30 @@ static void fakelb_del(struct fakelb_phy *phy)
 
 static int fakelb_probe(struct platform_device *pdev)
 {
-	struct fakelb_priv *priv;
 	struct fakelb_phy *phy, *tmp;
 	int err = -ENOMEM;
 	int i;
 
-	priv = devm_kzalloc(&pdev->dev, sizeof(struct fakelb_priv),
-			    GFP_KERNEL);
-	if (!priv)
-		goto err_alloc;
-
-	INIT_LIST_HEAD(&priv->list);
-
 	for (i = 0; i < numlbs; i++) {
-		err = fakelb_add_one(&pdev->dev, priv);
+		err = fakelb_add_one(&pdev->dev);
 		if (err < 0)
 			goto err_slave;
 	}
 
-	platform_set_drvdata(pdev, priv);
 	dev_info(&pdev->dev, "added ieee802154 hardware\n");
 	return 0;
 
 err_slave:
-	list_for_each_entry_safe(phy, tmp, &priv->list, list)
+	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
 		fakelb_del(phy);
-err_alloc:
 	return err;
 }
 
 static int fakelb_remove(struct platform_device *pdev)
 {
-	struct fakelb_priv *priv = platform_get_drvdata(pdev);
 	struct fakelb_phy *phy, *temp;
 
-	list_for_each_entry_safe(phy, temp, &priv->list, list)
+	list_for_each_entry_safe(phy, temp, &fakelb_phys, list)
 		fakelb_del(phy);
 
 	return 0;
Signature · 1 line
2.3.7
author maintainer
#7 lore raw

RFC 7/13 fakelb: move lock out of iteration

In reply to Alexander Aring

The list need to be protected while iteration which is need when other list iterates at the same time over this list.

---
 drivers/net/ieee802154/fakelb.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ieee802154/fakelb.c +4 -3
index 850d5b3..47f8ba5 100644
@@ -193,9 +193,7 @@ err_reg:
 
 static void fakelb_del(struct fakelb_phy *phy)
 {
-	write_lock_bh(&fakelb_lock);
 	list_del(&phy->list);
-	write_unlock_bh(&fakelb_lock);
 
 	ieee802154_unregister_hw(phy->hw);
 	ieee802154_free_hw(phy->hw);
@@ -217,8 +215,10 @@ static int fakelb_probe(struct platform_device *pdev)
 	return 0;
 
 err_slave:
+	write_lock_bh(&fakelb_lock);
 	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
 		fakelb_del(phy);
+	write_unlock_bh(&fakelb_lock);
 	return err;
 }
 
@@ -226,9 +226,10 @@ static int fakelb_remove(struct platform_device *pdev)
 {
 	struct fakelb_phy *phy, *temp;
 
+	write_lock_bh(&fakelb_lock);
 	list_for_each_entry_safe(phy, temp, &fakelb_phys, list)
 		fakelb_del(phy);
-
+	write_unlock_bh(&fakelb_lock);
 	return 0;
 }
 
Signature · 1 line
2.3.7
author maintainer
#8 lore raw

RFC 8/13 fakelb: introduce fakelb ifup phys list

In reply to Alexander Aring

This patch introduce a fakelb ifup phys list, which stores all registered phys which are in an operated mode. This will reduce the iterations of non-operated phys while transmit frames. There exists two locks now, one rwlock for the operated interfaces and the spinlock for protecting the list for all registered virtual phys.

---
 drivers/net/ieee802154/fakelb.c | 58 ++++++++++++++++++-----------------------
 1 file changed, 25 insertions(+), 33 deletions(-)
drivers/net/ieee802154/fakelb.c +25 -33
index 47f8ba5..12e3510 100644
@@ -28,16 +28,18 @@
 #include <net/cfg802154.h>
 
 static int numlbs = 2;
-static DEFINE_RWLOCK(fakelb_lock);
+
 static LIST_HEAD(fakelb_phys);
+static DEFINE_SPINLOCK(fakelb_phys_lock);
+
+static LIST_HEAD(fakelb_ifup_phys);
+static DEFINE_RWLOCK(fakelb_ifup_phys_lock);
 
 struct fakelb_phy {
 	struct ieee802154_hw *hw;
 
 	struct list_head list;
-
-	spinlock_t lock;
-	bool working;
+	struct list_head list_ifup;
 };
 
 static int
@@ -62,13 +64,9 @@ fakelb_hw_deliver(struct fakelb_phy *phy, struct sk_buff *skb)
 {
 	struct sk_buff *newskb;
 
-	spin_lock(&phy->lock);
-	if (phy->working) {
-		newskb = pskb_copy(skb, GFP_ATOMIC);
-		if (newskb)
-			ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc);
-	}
-	spin_unlock(&phy->lock);
+	newskb = pskb_copy(skb, GFP_ATOMIC);
+	if (newskb)
+		ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc);
 }
 
 static int
@@ -77,8 +75,8 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 	struct fakelb_phy *current_phy = hw->priv;
 	struct fakelb_phy *phy;
 
-	read_lock_bh(&fakelb_lock);
-	list_for_each_entry(phy, &fakelb_phys, list) {
+	read_lock_bh(&fakelb_ifup_phys_lock);
+	list_for_each_entry(phy, &fakelb_ifup_phys, list_ifup) {
 		if (current_phy == phy)
 			continue;
 
@@ -86,7 +84,7 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 		    current_phy->hw->phy->current_channel)
 			fakelb_hw_deliver(phy, skb);
 	}
-	read_unlock_bh(&fakelb_lock);
+	read_unlock_bh(&fakelb_ifup_phys_lock);
 
 	return 0;
 }
@@ -94,25 +92,21 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 static int
 fakelb_hw_start(struct ieee802154_hw *hw) {
 	struct fakelb_phy *phy = hw->priv;
-	int ret = 0;
 
-	spin_lock(&phy->lock);
-	if (phy->working)
-		ret = -EBUSY;
-	else
-		phy->working = 1;
-	spin_unlock(&phy->lock);
+	write_lock_bh(&fakelb_ifup_phys_lock);
+	list_add(&phy->list_ifup, &fakelb_ifup_phys);
+	write_unlock_bh(&fakelb_ifup_phys_lock);
 
-	return ret;
+	return 0;
 }
 
 static void
 fakelb_hw_stop(struct ieee802154_hw *hw) {
 	struct fakelb_phy *phy = hw->priv;
 
-	spin_lock(&phy->lock);
-	phy->working = 0;
-	spin_unlock(&phy->lock);
+	write_lock_bh(&fakelb_ifup_phys_lock);
+	list_del(&phy->list_ifup);
+	write_unlock_bh(&fakelb_ifup_phys_lock);
 }
 
 static const struct ieee802154_ops fakelb_ops = {
@@ -172,17 +166,15 @@ static int fakelb_add_one(struct device *dev)
 	/* 950 MHz GFSK 802.15.4d-2009 */
 	hw->phy->channels_supported[6] |= 0x3ffc00;
 
-	spin_lock_init(&phy->lock);
-
 	hw->parent = dev;
 
 	err = ieee802154_register_hw(hw);
 	if (err)
 		goto err_reg;
 
-	write_lock_bh(&fakelb_lock);
+	spin_lock(&fakelb_phys_lock);
 	list_add_tail(&phy->list, &fakelb_phys);
-	write_unlock_bh(&fakelb_lock);
+	spin_unlock(&fakelb_phys_lock);
 
 	return 0;
 
@@ -215,10 +207,10 @@ static int fakelb_probe(struct platform_device *pdev)
 	return 0;
 
 err_slave:
-	write_lock_bh(&fakelb_lock);
+	spin_lock(&fakelb_phys_lock);
 	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
 		fakelb_del(phy);
-	write_unlock_bh(&fakelb_lock);
+	spin_unlock(&fakelb_phys_lock);
 	return err;
 }
 
@@ -226,10 +218,10 @@ static int fakelb_remove(struct platform_device *pdev)
 {
 	struct fakelb_phy *phy, *temp;
 
-	write_lock_bh(&fakelb_lock);
+	spin_lock(&fakelb_phys_lock);
 	list_for_each_entry_safe(phy, temp, &fakelb_phys, list)
 		fakelb_del(phy);
-	write_unlock_bh(&fakelb_lock);
+	spin_unlock(&fakelb_phys_lock);
 	return 0;
 }
 
Signature · 1 line
2.3.7
author maintainer
#9 lore raw

RFC 9/13 fakelb: use own channel and page attributes

In reply to Alexander Aring

This patch adds an own phy attribute for page and channel into fakelb_phy. The current way is to use the internal mac802154 stored phy pib values which can occur in locking issues while using it inside the driver layer.

---
 drivers/net/ieee802154/fakelb.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/net/ieee802154/fakelb.c +10 -3
index 12e3510..e435d7b 100644
@@ -38,6 +38,9 @@ static DEFINE_RWLOCK(fakelb_ifup_phys_lock);
 struct fakelb_phy {
 	struct ieee802154_hw *hw;
 
+	u8 page;
+	u8 channel;
+
 	struct list_head list;
 	struct list_head list_ifup;
 };
@@ -54,8 +57,12 @@ fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
 static int
 fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 {
-	pr_debug("set channel to %d\n", channel);
+	struct fakelb_phy *phy = hw->priv;
 
+	write_lock_bh(&fakelb_ifup_phys_lock);
+	phy->page = page;
+	phy->channel = channel;
+	write_unlock_bh(&fakelb_ifup_phys_lock);
 	return 0;
 }
 
@@ -80,8 +87,8 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 		if (current_phy == phy)
 			continue;
 
-		if (phy->hw->phy->current_channel ==
-		    current_phy->hw->phy->current_channel)
+		if (current_phy->page == phy->page &&
+		    current_phy->channel == phy->channel)
 			fakelb_hw_deliver(phy, skb);
 	}
 	read_unlock_bh(&fakelb_ifup_phys_lock);
Signature · 1 line
2.3.7
author maintainer
#10 lore raw

RFC 10/13 fakelb: add virtual phy reset defaults

In reply to Alexander Aring

This patch adds reset defaults for the fakelb phy. I used the channel 13 and page 0 which is the same default like at86rf233.

---
 drivers/net/ieee802154/fakelb.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/net/ieee802154/fakelb.c +5 -0
index e435d7b..8b3f65c 100644
@@ -173,6 +173,11 @@ static int fakelb_add_one(struct device *dev)
 	/* 950 MHz GFSK 802.15.4d-2009 */
 	hw->phy->channels_supported[6] |= 0x3ffc00;
 
+	ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
+	/* fake phy channel 13 as default */
+	hw->phy->current_channel = 13;
+	phy->channel = hw->phy->current_channel;
+
 	hw->parent = dev;
 
 	err = ieee802154_register_hw(hw);
Signature · 1 line
2.3.7
author maintainer
#11 lore raw

RFC 11/13 fakelb: remove fakelb_hw_deliver

In reply to Alexander Aring

This patch cleanups the fakelb_hw_deliver function by removing them.

---
 drivers/net/ieee802154/fakelb.c | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)
drivers/net/ieee802154/fakelb.c +6 -12
index 8b3f65c..0deecc6 100644
@@ -66,16 +66,6 @@ fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 	return 0;
 }
 
-static void
-fakelb_hw_deliver(struct fakelb_phy *phy, struct sk_buff *skb)
-{
-	struct sk_buff *newskb;
-
-	newskb = pskb_copy(skb, GFP_ATOMIC);
-	if (newskb)
-		ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc);
-}
-
 static int
 fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 {
@@ -88,8 +78,12 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 			continue;
 
 		if (current_phy->page == phy->page &&
-		    current_phy->channel == phy->channel)
-			fakelb_hw_deliver(phy, skb);
+		    current_phy->channel == phy->channel) {
+			struct sk_buff *newskb = pskb_copy(skb, GFP_ATOMIC);
+
+			if (newskb)
+				ieee802154_rx_irqsafe(phy->hw, newskb, 0xcc);
+		}
 	}
 	read_unlock_bh(&fakelb_ifup_phys_lock);
 
Signature · 1 line
2.3.7
author maintainer
#12 lore raw

RFC 12/13 fakelb: add support for async xmit handling

In reply to Alexander Aring

This patch will add async xmit support for the fakelb driver.

---
 drivers/net/ieee802154/fakelb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ieee802154/fakelb.c +2 -1
index 0deecc6..51b6043 100644
@@ -87,6 +87,7 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 	}
 	read_unlock_bh(&fakelb_ifup_phys_lock);
 
+	ieee802154_xmit_complete(hw, skb, false);
 	return 0;
 }
 
@@ -112,7 +113,7 @@ fakelb_hw_stop(struct ieee802154_hw *hw) {
 
 static const struct ieee802154_ops fakelb_ops = {
 	.owner = THIS_MODULE,
-	.xmit_sync = fakelb_hw_xmit,
+	.xmit_async = fakelb_hw_xmit,
 	.ed = fakelb_hw_ed,
 	.set_channel = fakelb_hw_channel,
 	.start = fakelb_hw_start,
Signature · 1 line
2.3.7
author maintainer
#13 lore raw

RFC 13/13 fakelb: cleanup code

In reply to Alexander Aring

This patch just cleanups the code at serveral places.

---
 drivers/net/ieee802154/fakelb.c | 29 ++++++++++++-----------------
 1 file changed, 12 insertions(+), 17 deletions(-)
drivers/net/ieee802154/fakelb.c +12 -17
index 51b6043..2bdfa48 100644
@@ -45,8 +45,7 @@ struct fakelb_phy {
 	struct list_head list_ifup;
 };
 
-static int
-fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
+static int fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
 {
 	BUG_ON(!level);
 	*level = 0xbe;
@@ -54,8 +53,7 @@ fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
 	return 0;
 }
 
-static int
-fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+static int fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 {
 	struct fakelb_phy *phy = hw->priv;
 
@@ -66,11 +64,9 @@ fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
 	return 0;
 }
 
-static int
-fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+static int fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 {
-	struct fakelb_phy *current_phy = hw->priv;
-	struct fakelb_phy *phy;
+	struct fakelb_phy *current_phy = hw->priv, *phy;
 
 	read_lock_bh(&fakelb_ifup_phys_lock);
 	list_for_each_entry(phy, &fakelb_ifup_phys, list_ifup) {
@@ -91,8 +87,8 @@ fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
 	return 0;
 }
 
-static int
-fakelb_hw_start(struct ieee802154_hw *hw) {
+static int fakelb_hw_start(struct ieee802154_hw *hw)
+{
 	struct fakelb_phy *phy = hw->priv;
 
 	write_lock_bh(&fakelb_ifup_phys_lock);
@@ -102,8 +98,8 @@ fakelb_hw_start(struct ieee802154_hw *hw) {
 	return 0;
 }
 
-static void
-fakelb_hw_stop(struct ieee802154_hw *hw) {
+static void fakelb_hw_stop(struct ieee802154_hw *hw)
+{
 	struct fakelb_phy *phy = hw->priv;
 
 	write_lock_bh(&fakelb_ifup_phys_lock);
@@ -126,9 +122,9 @@ MODULE_PARM_DESC(numlbs, " number of pseudo devices");
 
 static int fakelb_add_one(struct device *dev)
 {
+	struct ieee802154_hw *hw;
 	struct fakelb_phy *phy;
 	int err;
-	struct ieee802154_hw *hw;
 
 	hw = ieee802154_alloc_hw(sizeof(*phy), &fakelb_ops);
 	if (!hw)
@@ -201,8 +197,7 @@ static void fakelb_del(struct fakelb_phy *phy)
 static int fakelb_probe(struct platform_device *pdev)
 {
 	struct fakelb_phy *phy, *tmp;
-	int err = -ENOMEM;
-	int i;
+	int err, i;
 
 	for (i = 0; i < numlbs; i++) {
 		err = fakelb_add_one(&pdev->dev);
@@ -223,10 +218,10 @@ err_slave:
 
 static int fakelb_remove(struct platform_device *pdev)
 {
-	struct fakelb_phy *phy, *temp;
+	struct fakelb_phy *phy, *tmp;
 
 	spin_lock(&fakelb_phys_lock);
-	list_for_each_entry_safe(phy, temp, &fakelb_phys, list)
+	list_for_each_entry_safe(phy, tmp, &fakelb_phys, list)
 		fakelb_del(phy);
 	spin_unlock(&fakelb_phys_lock);
 	return 0;
Signature · 1 line
2.3.7