All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/13] staging: most: net: remove useless variable channels_opened
@ 2017-05-12 10:59 Christian Gromm
  2017-05-12 10:59 ` [PATCH 02/13] staging: most: net: use dormant state Christian Gromm
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

The function most_nd_stop is only called by successful return from the
function most_nd_open, so the channels_opened is always true in the
function most_nd_stop.

The functions aim_resume_tx_channel and aim_rx_data are only called
after successful most_start_channel in the function most_nd_open, so the
channels_opened is always true in the functions aim_resume_tx_channel
and aim_rx_data.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index ce1764c..004dd7b 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -65,7 +65,6 @@ struct net_dev_channel {
 
 struct net_dev_context {
 	struct most_interface *iface;
-	bool channels_opened;
 	bool is_mamac;
 	struct net_device *dev;
 	struct net_dev_channel rx;
@@ -187,9 +186,6 @@ static int most_nd_open(struct net_device *dev)
 
 	BUG_ON(nd->dev != dev);
 
-	if (nd->channels_opened)
-		return -EFAULT;
-
 	BUG_ON(!nd->tx.linked || !nd->rx.linked);
 
 	if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
@@ -219,7 +215,6 @@ static int most_nd_open(struct net_device *dev)
 		}
 	}
 
-	nd->channels_opened = true;
 	netif_wake_queue(dev);
 	return 0;
 
@@ -237,12 +232,8 @@ static int most_nd_stop(struct net_device *dev)
 
 	BUG_ON(nd->dev != dev);
 	netif_stop_queue(dev);
-
-	if (nd->channels_opened) {
-		most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
-		most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
-		nd->channels_opened = false;
-	}
+	most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
+	most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
 
 	return 0;
 }
@@ -431,7 +422,7 @@ static int aim_resume_tx_channel(struct most_interface *iface,
 	struct net_dev_context *nd;
 
 	nd = get_net_dev_context(iface);
-	if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx)
+	if (!nd || nd->tx.ch_id != channel_idx)
 		return 0;
 
 	if (!nd->dev)
@@ -452,7 +443,7 @@ static int aim_rx_data(struct mbo *mbo)
 	unsigned int skb_len;
 
 	nd = get_net_dev_context(mbo->ifp);
-	if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id)
+	if (!nd || nd->rx.ch_id != mbo->hdm_channel_id)
 		return -EIO;
 
 	dev = nd->dev;
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 02/13] staging: most: net: use dormant state
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 03/13] staging: most: net: add carrier information Christian Gromm
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Andrey Shvetsov, Christian Gromm

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This replaces the call of wait_for_completion in case of an invalid MAC
address in the function most_nd_open() with the dormant state of the
network device.

As a side effect, opening the network device cannot fail anymore.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 31 ++++++---------------------
 1 file changed, 6 insertions(+), 25 deletions(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index 004dd7b..ce29427 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -69,7 +69,6 @@ struct net_dev_context {
 	struct net_device *dev;
 	struct net_dev_channel rx;
 	struct net_dev_channel tx;
-	struct completion mac_compl;
 	struct list_head list;
 };
 
@@ -180,7 +179,6 @@ static int most_nd_set_mac_address(struct net_device *dev, void *p)
 static int most_nd_open(struct net_device *dev)
 {
 	struct net_dev_context *nd = dev->ml_priv;
-	long ret;
 
 	netdev_info(dev, "open net device\n");
 
@@ -199,29 +197,13 @@ static int most_nd_open(struct net_device *dev)
 		return -EBUSY;
 	}
 
-	if (!is_valid_ether_addr(dev->dev_addr)) {
-		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
-		ret = wait_for_completion_interruptible_timeout(
-			      &nd->mac_compl, msecs_to_jiffies(5000));
-		if (!ret) {
-			netdev_err(dev, "mac timeout\n");
-			ret = -EBUSY;
-			goto err;
-		}
-
-		if (ret < 0) {
-			netdev_warn(dev, "mac waiting interrupted\n");
-			goto err;
-		}
-	}
-
+	if (is_valid_ether_addr(dev->dev_addr))
+		netif_dormant_off(dev);
+	else
+		netif_dormant_on(dev);
 	netif_wake_queue(dev);
+	nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
 	return 0;
-
-err:
-	most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
-	most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
-	return ret;
 }
 
 static int most_nd_stop(struct net_device *dev)
@@ -337,7 +319,6 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 		if (!nd)
 			return -ENOMEM;
 
-		init_completion(&nd->mac_compl);
 		nd->iface = iface;
 
 		spin_lock_irqsave(&list_lock, flags);
@@ -569,7 +550,7 @@ void most_deliver_netinfo(struct most_interface *iface,
 			netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n",
 				    m[0], m[1], m[2], m[3], m[4], m[5]);
 			ether_addr_copy(dev->dev_addr, m);
-			complete(&nd->mac_compl);
+			netif_dormant_off(dev);
 		} else if (!ether_addr_equal(dev->dev_addr, m)) {
 			netdev_warn(dev, "reject mac %02x-%02x-%02x-%02x-%02x-%02x\n",
 				    m[0], m[1], m[2], m[3], m[4], m[5]);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 03/13] staging: most: net: add carrier information
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
  2017-05-12 10:59 ` [PATCH 02/13] staging: most: net: use dormant state Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 04/13] staging: most: check availability of the callback request_netinfo Christian Gromm
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This adds the carrier information for the network devices based on the
INIC controllers.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index ce29427..5822902 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -197,6 +197,7 @@ static int most_nd_open(struct net_device *dev)
 		return -EBUSY;
 	}
 
+	netif_carrier_off(dev);
 	if (is_valid_ether_addr(dev->dev_addr))
 		netif_dormant_off(dev);
 	else
@@ -545,6 +546,11 @@ void most_deliver_netinfo(struct most_interface *iface,
 	if (!dev)
 		return;
 
+	if (link_stat)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
+
 	if (m && is_valid_ether_addr(m)) {
 		if (!is_valid_ether_addr(dev->dev_addr)) {
 			netdev_info(dev, "set mac %02x-%02x-%02x-%02x-%02x-%02x\n",
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 04/13] staging: most: check availability of the callback request_netinfo
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
  2017-05-12 10:59 ` [PATCH 02/13] staging: most: net: use dormant state Christian Gromm
  2017-05-12 10:59 ` [PATCH 03/13] staging: most: net: add carrier information Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 05/13] staging: most: i2c: remove empty " Christian Gromm
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

Since not all HDMs implement the callback request_netinfo, this patch
adds checking of its availability.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index 5822902..03ddbd2 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -203,7 +203,8 @@ static int most_nd_open(struct net_device *dev)
 	else
 		netif_dormant_on(dev);
 	netif_wake_queue(dev);
-	nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
+	if (nd->iface->request_netinfo)
+		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
 	return 0;
 }
 
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 05/13] staging: most: i2c: remove empty callback request_netinfo
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (2 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 04/13] staging: most: check availability of the callback request_netinfo Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 06/13] staging: most: remove dependency on networking-aim Christian Gromm
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Andrey Shvetsov, Christian Gromm

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

Since the networking-aim checks the availability of the callback
request_netinfo, this patch removes the empty callback request_netinfo
from the i2c-hdm.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/hdm-i2c/hdm_i2c.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
index 1d5b229..2b4de40 100644
--- a/drivers/staging/most/hdm-i2c/hdm_i2c.c
+++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c
@@ -185,12 +185,6 @@ static int poison_channel(struct most_interface *most_iface,
 	return 0;
 }
 
-static void request_netinfo(struct most_interface *most_iface,
-			    int ch_idx)
-{
-	pr_info("request_netinfo()\n");
-}
-
 static void do_rx_work(struct hdm_i2c *dev)
 {
 	struct mbo *mbo;
@@ -343,7 +337,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	dev->most_iface.configure = configure_channel;
 	dev->most_iface.enqueue = enqueue;
 	dev->most_iface.poison_channel = poison_channel;
-	dev->most_iface.request_netinfo = request_netinfo;
 
 	INIT_LIST_HEAD(&dev->rx.list);
 	mutex_init(&dev->rx.list_mutex);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 06/13] staging: most: remove dependency on networking-aim
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (3 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 05/13] staging: most: i2c: remove empty " Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 07/13] staging: most: use unsafe version of list traversing Christian Gromm
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

The modules hdm-usb and hdm-dim2 depend on the module aim-network, because
they use the function most_deliver_netinfo that it exports.

To remove this dependency, this patch replaces the call of the function
most_deliver_netinfo with the call of the function that is the parameter
'on_netinfo' of the function request_netinfo.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 15 +++++++++------
 drivers/staging/most/aim-network/networking.h | 21 ---------------------
 drivers/staging/most/hdm-dim2/Kconfig         |  1 -
 drivers/staging/most/hdm-dim2/dim2_hdm.c      | 18 ++++++++++++++----
 drivers/staging/most/hdm-usb/Kconfig          |  2 +-
 drivers/staging/most/hdm-usb/hdm_usb.c        | 15 ++++++++++++---
 drivers/staging/most/mostcore/mostcore.h      |  7 ++++++-
 7 files changed, 42 insertions(+), 37 deletions(-)
 delete mode 100644 drivers/staging/most/aim-network/networking.h

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index 03ddbd2..a3009fd 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -22,7 +22,6 @@
 #include <linux/wait.h>
 #include <linux/kobject.h>
 #include "mostcore.h"
-#include "networking.h"
 
 #define MEP_HDR_LEN 8
 #define MDP_HDR_LEN 16
@@ -176,6 +175,9 @@ static int most_nd_set_mac_address(struct net_device *dev, void *p)
 	return 0;
 }
 
+static void on_netinfo(struct most_interface *iface,
+		       unsigned char link_stat, unsigned char *mac_addr);
+
 static int most_nd_open(struct net_device *dev)
 {
 	struct net_dev_context *nd = dev->ml_priv;
@@ -204,7 +206,7 @@ static int most_nd_open(struct net_device *dev)
 		netif_dormant_on(dev);
 	netif_wake_queue(dev);
 	if (nd->iface->request_netinfo)
-		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
+		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, on_netinfo);
 	return 0;
 }
 
@@ -216,6 +218,8 @@ static int most_nd_stop(struct net_device *dev)
 
 	BUG_ON(nd->dev != dev);
 	netif_stop_queue(dev);
+	if (nd->iface->request_netinfo)
+		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
 	most_stop_channel(nd->iface, nd->rx.ch_id, &aim);
 	most_stop_channel(nd->iface, nd->tx.ch_id, &aim);
 
@@ -527,13 +531,13 @@ static void __exit most_net_exit(void)
 }
 
 /**
- * most_deliver_netinfo - callback for HDM to be informed about HW's MAC
+ * on_netinfo - callback for HDM to be informed about HW's MAC
  * @param iface - most interface instance
  * @param link_stat - link status
  * @param mac_addr - MAC address
  */
-void most_deliver_netinfo(struct most_interface *iface,
-			  unsigned char link_stat, unsigned char *mac_addr)
+static void on_netinfo(struct most_interface *iface,
+		       unsigned char link_stat, unsigned char *mac_addr)
 {
 	struct net_dev_context *nd;
 	struct net_device *dev;
@@ -564,7 +568,6 @@ void most_deliver_netinfo(struct most_interface *iface,
 		}
 	}
 }
-EXPORT_SYMBOL(most_deliver_netinfo);
 
 module_init(most_net_init);
 module_exit(most_net_exit);
diff --git a/drivers/staging/most/aim-network/networking.h b/drivers/staging/most/aim-network/networking.h
deleted file mode 100644
index 6f346d4..0000000
--- a/drivers/staging/most/aim-network/networking.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Networking AIM - Networking Application Interface Module for MostCore
- *
- * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * This file is licensed under GPLv2.
- */
-#ifndef _NETWORKING_H_
-#define _NETWORKING_H_
-
-#include "mostcore.h"
-
-void most_deliver_netinfo(struct most_interface *iface,
-			  unsigned char link_stat, unsigned char *mac_addr);
-
-#endif
diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig
index 28a0e17..663bfeb 100644
--- a/drivers/staging/most/hdm-dim2/Kconfig
+++ b/drivers/staging/most/hdm-dim2/Kconfig
@@ -4,7 +4,6 @@
 
 config HDM_DIM2
 	tristate "DIM2 HDM"
-	depends on AIM_NETWORK
 	depends on HAS_IOMEM
 
 	---help---
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
index 902824e..4607d03 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hdm.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c
@@ -26,7 +26,6 @@
 #include <linux/kthread.h>
 
 #include <mostcore.h>
-#include <networking.h>
 #include "dim2_hal.h"
 #include "dim2_hdm.h"
 #include "dim2_errors.h"
@@ -107,6 +106,8 @@ struct dim2_hdm {
 	unsigned char link_state;
 	int atx_idx;
 	struct medialb_bus bus;
+	void (*on_netinfo)(struct most_interface *,
+			   unsigned char, unsigned char *);
 };
 
 #define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
@@ -287,8 +288,11 @@ static int deliver_netinfo_thread(void *data)
 
 		if (dev->deliver_netinfo) {
 			dev->deliver_netinfo--;
-			most_deliver_netinfo(&dev->most_iface, dev->link_state,
-					     dev->mac_addrs);
+			if (dev->on_netinfo) {
+				dev->on_netinfo(&dev->most_iface,
+						dev->link_state,
+						dev->mac_addrs);
+			}
 		}
 	}
 
@@ -654,12 +658,18 @@ static int enqueue(struct most_interface *most_iface, int ch_idx,
  * Send a command to INIC which triggers retrieving of network info by means of
  * "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
  */
-static void request_netinfo(struct most_interface *most_iface, int ch_idx)
+static void request_netinfo(struct most_interface *most_iface, int ch_idx,
+			    void (*on_netinfo)(struct most_interface *,
+					       unsigned char, unsigned char *))
 {
 	struct dim2_hdm *dev = iface_to_hdm(most_iface);
 	struct mbo *mbo;
 	u8 *data;
 
+	dev->on_netinfo = on_netinfo;
+	if (!on_netinfo)
+		return;
+
 	if (dev->atx_idx < 0) {
 		pr_err("Async Tx Not initialized\n");
 		return;
diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig
index ec15463..487f1f3 100644
--- a/drivers/staging/most/hdm-usb/Kconfig
+++ b/drivers/staging/most/hdm-usb/Kconfig
@@ -5,7 +5,7 @@
 config HDM_USB
 	tristate "USB HDM"
 	depends on USB && NET
-	select AIM_NETWORK
+
 	---help---
 	  Say Y here if you want to connect via USB to network tranceiver.
 	  This device driver depends on the networking AIM.
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
index a95b591..d0f68cb 100644
--- a/drivers/staging/most/hdm-usb/hdm_usb.c
+++ b/drivers/staging/most/hdm-usb/hdm_usb.c
@@ -30,7 +30,6 @@
 #include <linux/etherdevice.h>
 #include <linux/uaccess.h>
 #include "mostcore.h"
-#include "networking.h"
 
 #define USB_MTU			512
 #define NO_ISOCHRONOUS_URB	0
@@ -126,6 +125,8 @@ struct most_dev {
 	struct mutex io_mutex;
 	struct timer_list link_stat_timer;
 	struct work_struct poll_work_obj;
+	void (*on_netinfo)(struct most_interface *, unsigned char,
+			   unsigned char *);
 };
 
 #define to_mdev(d) container_of(d, struct most_dev, iface)
@@ -719,12 +720,19 @@ static int hdm_configure_channel(struct most_interface *iface, int channel,
  * polls for the NI state of the INIC every 2 seconds.
  *
  */
-static void hdm_request_netinfo(struct most_interface *iface, int channel)
+static void hdm_request_netinfo(struct most_interface *iface, int channel,
+				void (*on_netinfo)(struct most_interface *,
+						   unsigned char,
+						   unsigned char *))
 {
 	struct most_dev *mdev;
 
 	BUG_ON(!iface);
 	mdev = to_mdev(iface);
+	mdev->on_netinfo = on_netinfo;
+	if (!on_netinfo)
+		return;
+
 	mdev->link_stat_timer.expires = jiffies + HZ;
 	mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
 }
@@ -786,7 +794,8 @@ static void wq_netinfo(struct work_struct *wq_obj)
 	hw_addr[4] = lo >> 8;
 	hw_addr[5] = lo;
 
-	most_deliver_netinfo(&mdev->iface, link, hw_addr);
+	if (mdev->on_netinfo)
+		mdev->on_netinfo(&mdev->iface, link, hw_addr);
 }
 
 /**
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
index 5f8339b..915e515 100644
--- a/drivers/staging/most/mostcore/mostcore.h
+++ b/drivers/staging/most/mostcore/mostcore.h
@@ -233,6 +233,8 @@ struct mbo {
  *   The callback returns a negative value on error, otherwise 0.
  * @request_netinfo: triggers retrieving of network info from the HDM by
  *   means of "Message exchange over MDP/MEP"
+ *   The call of the function request_netinfo with the parameter on_netinfo as
+ *   NULL prohibits use of the previously obtained function pointer.
  * @priv Private field used by mostcore to store context information.
  */
 struct most_interface {
@@ -246,7 +248,10 @@ struct most_interface {
 	int (*enqueue)(struct most_interface *iface, int channel_idx,
 		       struct mbo *mbo);
 	int (*poison_channel)(struct most_interface *iface, int channel_idx);
-	void (*request_netinfo)(struct most_interface *iface, int channel_idx);
+	void (*request_netinfo)(struct most_interface *iface, int channel_idx,
+				void (*on_netinfo)(struct most_interface *iface,
+						   unsigned char link_stat,
+						   unsigned char *mac_addr));
 	void *priv;
 };
 
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 07/13] staging: most: use unsafe version of list traversing
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (4 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 06/13] staging: most: remove dependency on networking-aim Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 08/13] staging: most: net: remove redundant cleanup code Christian Gromm
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Andrey Shvetsov, Christian Gromm

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

The function get_net_dev_context does not remove elements of the list.
Hence, list traversing does not need to be secured.

This patch replaces list_for_each_entry_safe with the
list_for_each_entry.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index a3009fd..11f03d3 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -290,11 +290,11 @@ static void most_net_rm_netdev_safe(struct net_dev_context *nd)
 static struct net_dev_context *get_net_dev_context(
 	struct most_interface *iface)
 {
-	struct net_dev_context *nd, *tmp;
+	struct net_dev_context *nd;
 	unsigned long flags;
 
 	spin_lock_irqsave(&list_lock, flags);
-	list_for_each_entry_safe(nd, tmp, &net_devices, list) {
+	list_for_each_entry(nd, &net_devices, list) {
 		if (nd->iface == iface) {
 			spin_unlock_irqrestore(&list_lock, flags);
 			return nd;
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 08/13] staging: most: net: remove redundant cleanup code
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (5 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 07/13] staging: most: use unsafe version of list traversing Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 09/13] staging: most: net: prefer __func__ over the function name Christian Gromm
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This removes redundant cleanup code that is executed anyway when the
most_deregister_aim() is called.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 19 +------------------
 1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index 11f03d3..e2935cc 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -509,25 +509,8 @@ static int __init most_net_init(void)
 
 static void __exit most_net_exit(void)
 {
-	struct net_dev_context *nd, *tmp;
-	unsigned long flags;
-
-	spin_lock_irqsave(&list_lock, flags);
-	list_for_each_entry_safe(nd, tmp, &net_devices, list) {
-		list_del(&nd->list);
-		spin_unlock_irqrestore(&list_lock, flags);
-		/*
-		 * do not call most_stop_channel() here, because channels are
-		 * going to be closed in ndo_stop() after unregister_netdev()
-		 */
-		most_net_rm_netdev_safe(nd);
-		kfree(nd);
-		spin_lock_irqsave(&list_lock, flags);
-	}
-	spin_unlock_irqrestore(&list_lock, flags);
-
-	most_deregister_aim(&aim);
 	pr_info("most_net_exit()\n");
+	most_deregister_aim(&aim);
 }
 
 /**
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 09/13] staging: most: net: prefer __func__ over the function name
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (6 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 08/13] staging: most: net: remove redundant cleanup code Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-15  9:55   ` Greg KH
  2017-05-12 10:59 ` [PATCH 10/13] staging: most: allocate private net_dev_context with the alloc_netdev Christian Gromm
                   ` (3 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Andrey Shvetsov, Christian Gromm

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This replaces the function names in the print messages with the __func__
macro.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index e2935cc..36483b9 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -502,14 +502,14 @@ static int aim_rx_data(struct mbo *mbo)
 
 static int __init most_net_init(void)
 {
-	pr_info("most_net_init()\n");
+	pr_info("%s()\n", __func__);
 	spin_lock_init(&list_lock);
 	return most_register_aim(&aim);
 }
 
 static void __exit most_net_exit(void)
 {
-	pr_info("most_net_exit()\n");
+	pr_info("%s()\n", __func__);
 	most_deregister_aim(&aim);
 }
 
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 10/13] staging: most: allocate private net_dev_context with the alloc_netdev
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (7 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 09/13] staging: most: net: prefer __func__ over the function name Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-12 10:59 ` [PATCH 11/13] staging: most: net: fix race between create/destroy device Christian Gromm
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This moves the allocation of the net_dev to the aim_probe_channel() and
uses the parameter sizeof_priv of the function alloc_netdev to reserve
the space for the struct net_dev_context.

As a side effect, the nd->dev always points to the existing net_dev.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 81 +++++++--------------------
 1 file changed, 20 insertions(+), 61 deletions(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index 36483b9..cbd9500 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -154,14 +154,12 @@ static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
 
 static int most_nd_set_mac_address(struct net_device *dev, void *p)
 {
-	struct net_dev_context *nd = dev->ml_priv;
+	struct net_dev_context *nd = netdev_priv(dev);
 	int err = eth_mac_addr(dev, p);
 
 	if (err)
 		return err;
 
-	BUG_ON(nd->dev != dev);
-
 	nd->is_mamac =
 		(dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
 		 dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
@@ -180,12 +178,10 @@ static void on_netinfo(struct most_interface *iface,
 
 static int most_nd_open(struct net_device *dev)
 {
-	struct net_dev_context *nd = dev->ml_priv;
+	struct net_dev_context *nd = netdev_priv(dev);
 
 	netdev_info(dev, "open net device\n");
 
-	BUG_ON(nd->dev != dev);
-
 	BUG_ON(!nd->tx.linked || !nd->rx.linked);
 
 	if (most_start_channel(nd->iface, nd->rx.ch_id, &aim)) {
@@ -212,11 +208,10 @@ static int most_nd_open(struct net_device *dev)
 
 static int most_nd_stop(struct net_device *dev)
 {
-	struct net_dev_context *nd = dev->ml_priv;
+	struct net_dev_context *nd = netdev_priv(dev);
 
 	netdev_info(dev, "stop net device\n");
 
-	BUG_ON(nd->dev != dev);
 	netif_stop_queue(dev);
 	if (nd->iface->request_netinfo)
 		nd->iface->request_netinfo(nd->iface, nd->tx.ch_id, NULL);
@@ -229,12 +224,10 @@ static int most_nd_stop(struct net_device *dev)
 static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
 				      struct net_device *dev)
 {
-	struct net_dev_context *nd = dev->ml_priv;
+	struct net_dev_context *nd = netdev_priv(dev);
 	struct mbo *mbo;
 	int ret;
 
-	BUG_ON(nd->dev != dev);
-
 	mbo = most_get_mbo(nd->iface, nd->tx.ch_id, &aim);
 
 	if (!mbo) {
@@ -275,18 +268,6 @@ static void most_nd_setup(struct net_device *dev)
 	dev->netdev_ops = &most_nd_ops;
 }
 
-static void most_net_rm_netdev_safe(struct net_dev_context *nd)
-{
-	if (!nd->dev)
-		return;
-
-	pr_info("remove net device %p\n", nd->dev);
-
-	unregister_netdev(nd->dev);
-	free_netdev(nd->dev);
-	nd->dev = NULL;
-}
-
 static struct net_dev_context *get_net_dev_context(
 	struct most_interface *iface)
 {
@@ -321,11 +302,16 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 	nd = get_net_dev_context(iface);
 
 	if (!nd) {
-		nd = kzalloc(sizeof(*nd), GFP_KERNEL);
-		if (!nd)
+		struct net_device *dev;
+
+		dev = alloc_netdev(sizeof(struct net_dev_context), "meth%d",
+				   NET_NAME_UNKNOWN, most_nd_setup);
+		if (!dev)
 			return -ENOMEM;
 
+		nd = netdev_priv(dev);
 		nd->iface = iface;
+		nd->dev = dev;
 
 		spin_lock_irqsave(&list_lock, flags);
 		list_add(&nd->list, &net_devices);
@@ -338,31 +324,13 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 		return -EINVAL;
 	}
 
-	if (nd->tx.linked || nd->rx.linked) {
-		struct net_device *dev =
-			alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN,
-				     most_nd_setup);
-
-		if (!dev) {
-			pr_err("no memory for net_device\n");
-			return -ENOMEM;
-		}
-
-		nd->dev = dev;
-		ch->ch_id = channel_idx;
-		ch->linked = true;
-
-		dev->ml_priv = nd;
-		if (register_netdev(dev)) {
-			pr_err("registering net device failed\n");
-			ch->linked = false;
-			free_netdev(dev);
-			return -EINVAL;
-		}
-	}
-
 	ch->ch_id = channel_idx;
 	ch->linked = true;
+	if (nd->tx.linked && nd->rx.linked && register_netdev(nd->dev)) {
+		pr_err("register_netdev() failed\n");
+		ch->linked = false;
+		return -EINVAL;
+	}
 
 	return 0;
 }
@@ -385,19 +353,19 @@ static int aim_disconnect_channel(struct most_interface *iface,
 	else
 		return -EINVAL;
 
-	ch->linked = false;
-
 	/*
 	 * do not call most_stop_channel() here, because channels are
 	 * going to be closed in ndo_stop() after unregister_netdev()
 	 */
-	most_net_rm_netdev_safe(nd);
+	if (nd->rx.linked && nd->tx.linked)
+		unregister_netdev(nd->dev);
 
+	ch->linked = false;
 	if (!nd->rx.linked && !nd->tx.linked) {
 		spin_lock_irqsave(&list_lock, flags);
 		list_del(&nd->list);
 		spin_unlock_irqrestore(&list_lock, flags);
-		kfree(nd);
+		free_netdev(nd->dev);
 	}
 
 	return 0;
@@ -412,9 +380,6 @@ static int aim_resume_tx_channel(struct most_interface *iface,
 	if (!nd || nd->tx.ch_id != channel_idx)
 		return 0;
 
-	if (!nd->dev)
-		return 0;
-
 	netif_wake_queue(nd->dev);
 	return 0;
 }
@@ -434,10 +399,6 @@ static int aim_rx_data(struct mbo *mbo)
 		return -EIO;
 
 	dev = nd->dev;
-	if (!dev) {
-		pr_err_once("drop packet: missing net_device\n");
-		return -EIO;
-	}
 
 	if (nd->is_mamac) {
 		if (!PMS_IS_MAMAC(buf, len))
@@ -531,8 +492,6 @@ static void on_netinfo(struct most_interface *iface,
 		return;
 
 	dev = nd->dev;
-	if (!dev)
-		return;
 
 	if (link_stat)
 		netif_carrier_on(dev);
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 11/13] staging: most: net: fix race between create/destroy device
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (8 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 10/13] staging: most: allocate private net_dev_context with the alloc_netdev Christian Gromm
@ 2017-05-12 10:59 ` Christian Gromm
  2017-05-15  9:58   ` Greg KH
  2017-05-12 11:00 ` [PATCH 12/13] staging: most: dim2: enable flow control for isoc channels Christian Gromm
  2017-05-12 11:00 ` [PATCH 13/13] staging: most: dim2: replace function parameter with the expression Christian Gromm
  11 siblings, 1 reply; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 10:59 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Andrey Shvetsov, Christian Gromm

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This introduces the kref for the net_dev_context to prevent the
destruction of the network devices that are in use.

Each get_net_dev_context is completed with the put_net_dev_context,
except the function aim_probe_channel that calls one more
get_net_dev_context or kref_get and the function aim_disconnect_channel
that calls one more put_net_dev_context.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/aim-network/networking.c | 92 +++++++++++++++++++++------
 1 file changed, 72 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
index cbd9500..8cf1c81 100644
--- a/drivers/staging/most/aim-network/networking.c
+++ b/drivers/staging/most/aim-network/networking.c
@@ -21,6 +21,7 @@
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/kobject.h>
+#include <linux/kref.h>
 #include "mostcore.h"
 
 #define MEP_HDR_LEN 8
@@ -69,6 +70,7 @@ struct net_dev_context {
 	struct net_dev_channel rx;
 	struct net_dev_channel tx;
 	struct list_head list;
+	struct kref kref;
 };
 
 static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
@@ -268,6 +270,26 @@ static void most_nd_setup(struct net_device *dev)
 	dev->netdev_ops = &most_nd_ops;
 }
 
+static void release_nd(struct kref *kref)
+{
+	struct net_dev_context *nd;
+
+	nd = container_of(kref, struct net_dev_context, kref);
+	list_del(&nd->list);
+}
+
+static inline void put_net_dev_context(struct net_dev_context *nd)
+{
+	unsigned long flags;
+	int released;
+
+	spin_lock_irqsave(&list_lock, flags);
+	released = kref_put(&nd->kref, release_nd);
+	spin_unlock_irqrestore(&list_lock, flags);
+	if (released)
+		free_netdev(nd->dev);
+}
+
 static struct net_dev_context *get_net_dev_context(
 	struct most_interface *iface)
 {
@@ -277,6 +299,7 @@ static struct net_dev_context *get_net_dev_context(
 	spin_lock_irqsave(&list_lock, flags);
 	list_for_each_entry(nd, &net_devices, list) {
 		if (nd->iface == iface) {
+			kref_get(&nd->kref);
 			spin_unlock_irqrestore(&list_lock, flags);
 			return nd;
 		}
@@ -300,7 +323,6 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 		return -EINVAL;
 
 	nd = get_net_dev_context(iface);
-
 	if (!nd) {
 		struct net_device *dev;
 
@@ -309,19 +331,34 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 		if (!dev)
 			return -ENOMEM;
 
+		/*
+		 * The network device for the given iface may be added with use
+		 * of the other channel just after the get_net_dev_context
+		 * call.  Free our duplicate of net_device in this case.
+		 */
+		spin_lock_irqsave(&list_lock, flags);
+		list_for_each_entry(nd, &net_devices, list) {
+			if (nd->iface == iface) {
+				kref_get(&nd->kref);
+				spin_unlock_irqrestore(&list_lock, flags);
+				free_netdev(dev);
+				goto ok;
+			}
+		}
+
 		nd = netdev_priv(dev);
+		kref_init(&nd->kref);
 		nd->iface = iface;
 		nd->dev = dev;
-
-		spin_lock_irqsave(&list_lock, flags);
 		list_add(&nd->list, &net_devices);
 		spin_unlock_irqrestore(&list_lock, flags);
 	}
 
+ok:
 	ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
 	if (ch->linked) {
 		pr_err("only one channel per instance & direction allowed\n");
-		return -EINVAL;
+		goto err;
 	}
 
 	ch->ch_id = channel_idx;
@@ -329,10 +366,14 @@ static int aim_probe_channel(struct most_interface *iface, int channel_idx,
 	if (nd->tx.linked && nd->rx.linked && register_netdev(nd->dev)) {
 		pr_err("register_netdev() failed\n");
 		ch->linked = false;
-		return -EINVAL;
+		goto err;
 	}
 
 	return 0;
+
+err:
+	put_net_dev_context(nd);
+	return -EINVAL;
 }
 
 static int aim_disconnect_channel(struct most_interface *iface,
@@ -340,7 +381,7 @@ static int aim_disconnect_channel(struct most_interface *iface,
 {
 	struct net_dev_context *nd;
 	struct net_dev_channel *ch;
-	unsigned long flags;
+	int ret = -EINVAL;
 
 	nd = get_net_dev_context(iface);
 	if (!nd)
@@ -351,7 +392,7 @@ static int aim_disconnect_channel(struct most_interface *iface,
 	else if (nd->tx.linked && channel_idx == nd->tx.ch_id)
 		ch = &nd->tx;
 	else
-		return -EINVAL;
+		goto put_nd;
 
 	/*
 	 * do not call most_stop_channel() here, because channels are
@@ -361,14 +402,12 @@ static int aim_disconnect_channel(struct most_interface *iface,
 		unregister_netdev(nd->dev);
 
 	ch->linked = false;
-	if (!nd->rx.linked && !nd->tx.linked) {
-		spin_lock_irqsave(&list_lock, flags);
-		list_del(&nd->list);
-		spin_unlock_irqrestore(&list_lock, flags);
-		free_netdev(nd->dev);
-	}
+	put_net_dev_context(nd);
+	ret = 0;
 
-	return 0;
+put_nd:
+	put_net_dev_context(nd);
+	return ret;
 }
 
 static int aim_resume_tx_channel(struct most_interface *iface,
@@ -377,10 +416,13 @@ static int aim_resume_tx_channel(struct most_interface *iface,
 	struct net_dev_context *nd;
 
 	nd = get_net_dev_context(iface);
-	if (!nd || nd->tx.ch_id != channel_idx)
+	if (!nd)
 		return 0;
 
-	netif_wake_queue(nd->dev);
+	if (nd->tx.ch_id == channel_idx)
+		netif_wake_queue(nd->dev);
+
+	put_net_dev_context(nd);
 	return 0;
 }
 
@@ -393,25 +435,30 @@ static int aim_rx_data(struct mbo *mbo)
 	struct sk_buff *skb;
 	struct net_device *dev;
 	unsigned int skb_len;
+	int ret = -EIO;
 
 	nd = get_net_dev_context(mbo->ifp);
-	if (!nd || nd->rx.ch_id != mbo->hdm_channel_id)
+	if (!nd)
 		return -EIO;
 
+	if (nd->rx.ch_id != mbo->hdm_channel_id)
+		goto put_nd;
+
 	dev = nd->dev;
 
 	if (nd->is_mamac) {
 		if (!PMS_IS_MAMAC(buf, len))
-			return -EIO;
+			goto put_nd;
 
 		skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
 	} else {
 		if (!PMS_IS_MEP(buf, len))
-			return -EIO;
+			goto put_nd;
 
 		skb = dev_alloc_skb(len - MEP_HDR_LEN);
 	}
 
+	ret = 0;
 	if (!skb) {
 		dev->stats.rx_dropped++;
 		pr_err_once("drop packet: no memory for skb\n");
@@ -450,7 +497,10 @@ static int aim_rx_data(struct mbo *mbo)
 
 out:
 	most_put_mbo(mbo);
-	return 0;
+
+put_nd:
+	put_net_dev_context(nd);
+	return ret;
 }
 
 static struct most_aim aim = {
@@ -509,6 +559,8 @@ static void on_netinfo(struct most_interface *iface,
 				    m[0], m[1], m[2], m[3], m[4], m[5]);
 		}
 	}
+
+	put_net_dev_context(nd);
 }
 
 module_init(most_net_init);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 12/13] staging: most: dim2: enable flow control for isoc channels
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (9 preceding siblings ...)
  2017-05-12 10:59 ` [PATCH 11/13] staging: most: net: fix race between create/destroy device Christian Gromm
@ 2017-05-12 11:00 ` Christian Gromm
  2017-05-12 11:00 ` [PATCH 13/13] staging: most: dim2: replace function parameter with the expression Christian Gromm
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 11:00 UTC (permalink / raw)
  To: gregkh; +Cc: Christian Gromm, driverdev-devel

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This patch enables the flow control feature for the isochronous channels
of the DIM2 macro.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/hdm-dim2/dim2_hal.c | 2 ++
 drivers/staging/most/hdm-dim2/dim2_reg.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
index d604ec09..b9f3495 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hal.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.c
@@ -219,10 +219,12 @@ static inline void dim2_clear_ctr(u32 ctr_addr)
 static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
 			       bool read_not_write, bool sync_mfe)
 {
+	bool isoc_fce = ch_type == CAT_CT_VAL_ISOC;
 	u16 const cat =
 		(read_not_write << CAT_RNW_BIT) |
 		(ch_type << CAT_CT_SHIFT) |
 		(ch_addr << CAT_CL_SHIFT) |
+		(isoc_fce << CAT_FCE_BIT) |
 		(sync_mfe << CAT_MFE_BIT) |
 		(false << CAT_MT_BIT) |
 		(true << CAT_CE_BIT);
diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h
index 01fe499..f7d9fbc 100644
--- a/drivers/staging/most/hdm-dim2/dim2_reg.h
+++ b/drivers/staging/most/hdm-dim2/dim2_reg.h
@@ -141,6 +141,7 @@ enum {
 	ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
 	ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
 
+	CAT_FCE_BIT = 14,
 	CAT_MFE_BIT = 14,
 
 	CAT_MT_BIT = 13,
-- 
1.9.1

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 13/13] staging: most: dim2: replace function parameter with the expression
  2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
                   ` (10 preceding siblings ...)
  2017-05-12 11:00 ` [PATCH 12/13] staging: most: dim2: enable flow control for isoc channels Christian Gromm
@ 2017-05-12 11:00 ` Christian Gromm
  11 siblings, 0 replies; 15+ messages in thread
From: Christian Gromm @ 2017-05-12 11:00 UTC (permalink / raw)
  To: gregkh; +Cc: driverdev-devel, Andrey Shvetsov, Christian Gromm

From: Andrey Shvetsov <andrey.shvetsov@k2l.de>

This replaces the function parameter sync_mfe with the expression
(ch_type == CAT_CT_VAL_SYNC) what is the same.

Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
---
 drivers/staging/most/hdm-dim2/dim2_hal.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
index b9f3495..9148464 100644
--- a/drivers/staging/most/hdm-dim2/dim2_hal.c
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.c
@@ -217,9 +217,10 @@ static inline void dim2_clear_ctr(u32 ctr_addr)
 }
 
 static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
-			       bool read_not_write, bool sync_mfe)
+			       bool read_not_write)
 {
 	bool isoc_fce = ch_type == CAT_CT_VAL_ISOC;
+	bool sync_mfe = ch_type == CAT_CT_VAL_SYNC;
 	u16 const cat =
 		(read_not_write << CAT_RNW_BIT) |
 		(ch_type << CAT_CT_SHIFT) |
@@ -352,13 +353,13 @@ static void dim2_clear_ctram(void)
 
 static void dim2_configure_channel(
 	u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
-	u16 packet_length, bool sync_mfe)
+	u16 packet_length)
 {
 	dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
-	dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0, sync_mfe);
+	dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0);
 
 	dim2_configure_adt(ch_addr);
-	dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1, sync_mfe);
+	dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1);
 
 	/* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
 	dimcb_io_write(&g.dim2->ACMR0,
@@ -773,7 +774,7 @@ static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
 	channel_init(ch, ch_address / 2);
 
 	dim2_configure_channel(ch->addr, type, is_tx,
-			       ch->dbr_addr, ch->dbr_size, 0, false);
+			       ch->dbr_addr, ch->dbr_size, 0);
 
 	return DIM_NO_ERROR;
 }
@@ -859,7 +860,7 @@ u8 dim_init_isoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
 	isoc_init(ch, ch_address / 2, packet_length);
 
 	dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
-			       ch->dbr_size, packet_length, false);
+			       ch->dbr_size, packet_length);
 
 	return DIM_NO_ERROR;
 }
@@ -887,7 +888,7 @@ u8 dim_init_sync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
 
 	dim2_clear_dbr(ch->dbr_addr, ch->dbr_size);
 	dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
-			       ch->dbr_addr, ch->dbr_size, 0, true);
+			       ch->dbr_addr, ch->dbr_size, 0);
 
 	return DIM_NO_ERROR;
 }
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 09/13] staging: most: net: prefer __func__ over the function name
  2017-05-12 10:59 ` [PATCH 09/13] staging: most: net: prefer __func__ over the function name Christian Gromm
@ 2017-05-15  9:55   ` Greg KH
  0 siblings, 0 replies; 15+ messages in thread
From: Greg KH @ 2017-05-15  9:55 UTC (permalink / raw)
  To: Christian Gromm; +Cc: driverdev-devel

On Fri, May 12, 2017 at 12:59:57PM +0200, Christian Gromm wrote:
> From: Andrey Shvetsov <andrey.shvetsov@k2l.de>
> 
> This replaces the function names in the print messages with the __func__
> macro.
> 
> Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
> Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
> ---
>  drivers/staging/most/aim-network/networking.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
> index e2935cc..36483b9 100644
> --- a/drivers/staging/most/aim-network/networking.c
> +++ b/drivers/staging/most/aim-network/networking.c
> @@ -502,14 +502,14 @@ static int aim_rx_data(struct mbo *mbo)
>  
>  static int __init most_net_init(void)
>  {
> -	pr_info("most_net_init()\n");
> +	pr_info("%s()\n", __func__);
>  	spin_lock_init(&list_lock);
>  	return most_register_aim(&aim);
>  }
>  
>  static void __exit most_net_exit(void)
>  {
> -	pr_info("most_net_exit()\n");
> +	pr_info("%s()\n", __func__);

No, these need to just be deleted entirely, no need to be noisy for no
good reason at all.  If you really need to trace the code, use the
built-in kernel tracing functionality.

thanks,

greg k-h
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 11/13] staging: most: net: fix race between create/destroy device
  2017-05-12 10:59 ` [PATCH 11/13] staging: most: net: fix race between create/destroy device Christian Gromm
@ 2017-05-15  9:58   ` Greg KH
  0 siblings, 0 replies; 15+ messages in thread
From: Greg KH @ 2017-05-15  9:58 UTC (permalink / raw)
  To: Christian Gromm; +Cc: driverdev-devel

On Fri, May 12, 2017 at 12:59:59PM +0200, Christian Gromm wrote:
> From: Andrey Shvetsov <andrey.shvetsov@k2l.de>
> 
> This introduces the kref for the net_dev_context to prevent the
> destruction of the network devices that are in use.
> 
> Each get_net_dev_context is completed with the put_net_dev_context,
> except the function aim_probe_channel that calls one more
> get_net_dev_context or kref_get and the function aim_disconnect_channel
> that calls one more put_net_dev_context.
> 
> Signed-off-by: Andrey Shvetsov <andrey.shvetsov@k2l.de>
> Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
> ---
>  drivers/staging/most/aim-network/networking.c | 92 +++++++++++++++++++++------
>  1 file changed, 72 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
> index cbd9500..8cf1c81 100644
> --- a/drivers/staging/most/aim-network/networking.c
> +++ b/drivers/staging/most/aim-network/networking.c
> @@ -21,6 +21,7 @@
>  #include <linux/list.h>
>  #include <linux/wait.h>
>  #include <linux/kobject.h>
> +#include <linux/kref.h>
>  #include "mostcore.h"
>  
>  #define MEP_HDR_LEN 8
> @@ -69,6 +70,7 @@ struct net_dev_context {
>  	struct net_dev_channel rx;
>  	struct net_dev_channel tx;
>  	struct list_head list;
> +	struct kref kref;
>  };
>  
>  static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
> @@ -268,6 +270,26 @@ static void most_nd_setup(struct net_device *dev)
>  	dev->netdev_ops = &most_nd_ops;
>  }
>  
> +static void release_nd(struct kref *kref)
> +{
> +	struct net_dev_context *nd;
> +
> +	nd = container_of(kref, struct net_dev_context, kref);
> +	list_del(&nd->list);

That might delete something off of the list, but it does not free the
structure itself, where is that handled?

Why do you need a reference count for all of this?  Doesn't the
networking core provide you the needed functions for this?

thanks,

greg k-h
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2017-05-15  9:58 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-12 10:59 [PATCH 01/13] staging: most: net: remove useless variable channels_opened Christian Gromm
2017-05-12 10:59 ` [PATCH 02/13] staging: most: net: use dormant state Christian Gromm
2017-05-12 10:59 ` [PATCH 03/13] staging: most: net: add carrier information Christian Gromm
2017-05-12 10:59 ` [PATCH 04/13] staging: most: check availability of the callback request_netinfo Christian Gromm
2017-05-12 10:59 ` [PATCH 05/13] staging: most: i2c: remove empty " Christian Gromm
2017-05-12 10:59 ` [PATCH 06/13] staging: most: remove dependency on networking-aim Christian Gromm
2017-05-12 10:59 ` [PATCH 07/13] staging: most: use unsafe version of list traversing Christian Gromm
2017-05-12 10:59 ` [PATCH 08/13] staging: most: net: remove redundant cleanup code Christian Gromm
2017-05-12 10:59 ` [PATCH 09/13] staging: most: net: prefer __func__ over the function name Christian Gromm
2017-05-15  9:55   ` Greg KH
2017-05-12 10:59 ` [PATCH 10/13] staging: most: allocate private net_dev_context with the alloc_netdev Christian Gromm
2017-05-12 10:59 ` [PATCH 11/13] staging: most: net: fix race between create/destroy device Christian Gromm
2017-05-15  9:58   ` Greg KH
2017-05-12 11:00 ` [PATCH 12/13] staging: most: dim2: enable flow control for isoc channels Christian Gromm
2017-05-12 11:00 ` [PATCH 13/13] staging: most: dim2: replace function parameter with the expression Christian Gromm

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.