caif-hsi: Postpone init of HSI until open()

Do the initialization of the HSI interface when the
interface is opened, instead of upon registration.
When the interface is closed the HSI interface is
de-initialized, allowing other modules to use the
HSI interface.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
sjur.brandeland@stericsson.com 2012-04-12 08:27:27 +00:00 committed by David S. Miller
parent 2df1fe7f10
commit 39abbaef19

View File

@ -6,6 +6,8 @@
* License terms: GNU General Public License (GPL) version 2.
*/
#define pr_fmt(fmt) KBUILD_MODNAME fmt
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
@ -1127,21 +1129,7 @@ static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
static int cfhsi_open(struct net_device *dev)
{
return 0;
}
static int cfhsi_close(struct net_device *dev)
{
return 0;
}
static const struct net_device_ops cfhsi_ops = {
.ndo_open = cfhsi_open,
.ndo_stop = cfhsi_close,
.ndo_start_xmit = cfhsi_xmit
};
static const struct net_device_ops cfhsi_ops;
static void cfhsi_setup(struct net_device *dev)
{
@ -1167,7 +1155,7 @@ int cfhsi_probe(struct platform_device *pdev)
{
struct cfhsi *cfhsi = NULL;
struct net_device *ndev;
struct cfhsi_dev *dev;
int res;
ndev = alloc_netdev(sizeof(struct cfhsi), "cfhsi%d", cfhsi_setup);
@ -1178,6 +1166,34 @@ int cfhsi_probe(struct platform_device *pdev)
cfhsi->ndev = ndev;
cfhsi->pdev = pdev;
/* Assign the HSI device. */
cfhsi->dev = pdev->dev.platform_data;
/* Assign the driver to this HSI device. */
cfhsi->dev->drv = &cfhsi->drv;
/* Register network device. */
res = register_netdev(ndev);
if (res) {
dev_err(&ndev->dev, "%s: Registration error: %d.\n",
__func__, res);
free_netdev(ndev);
}
/* Add CAIF HSI device to list. */
spin_lock(&cfhsi_list_lock);
list_add_tail(&cfhsi->list, &cfhsi_list);
spin_unlock(&cfhsi_list_lock);
return res;
}
static int cfhsi_open(struct net_device *ndev)
{
struct cfhsi *cfhsi = netdev_priv(ndev);
int res;
clear_bit(CFHSI_SHUTDOWN, &cfhsi->bits);
/* Initialize state vaiables. */
cfhsi->tx_state = CFHSI_TX_STATE_IDLE;
cfhsi->rx_state.state = CFHSI_RX_STATE_DESC;
@ -1187,12 +1203,6 @@ int cfhsi_probe(struct platform_device *pdev)
cfhsi->q_low_mark = LOW_WATER_MARK;
cfhsi->q_high_mark = HIGH_WATER_MARK;
/* Assign the HSI device. */
dev = (struct cfhsi_dev *)pdev->dev.platform_data;
cfhsi->dev = dev;
/* Assign the driver to this HSI device. */
dev->drv = &cfhsi->drv;
/*
* Allocate a TX buffer with the size of a HSI packet descriptors
@ -1260,9 +1270,9 @@ int cfhsi_probe(struct platform_device *pdev)
clear_bit(CFHSI_AWAKE, &cfhsi->bits);
/* Create work thread. */
cfhsi->wq = create_singlethread_workqueue(pdev->name);
cfhsi->wq = create_singlethread_workqueue(cfhsi->pdev->name);
if (!cfhsi->wq) {
dev_err(&ndev->dev, "%s: Failed to create work queue.\n",
dev_err(&cfhsi->ndev->dev, "%s: Failed to create work queue.\n",
__func__);
res = -ENODEV;
goto err_create_wq;
@ -1286,11 +1296,6 @@ int cfhsi_probe(struct platform_device *pdev)
cfhsi->aggregation_timer.data = (unsigned long)cfhsi;
cfhsi->aggregation_timer.function = cfhsi_aggregation_tout;
/* Add CAIF HSI device to list. */
spin_lock(&cfhsi_list_lock);
list_add_tail(&cfhsi->list, &cfhsi_list);
spin_unlock(&cfhsi_list_lock);
/* Activate HSI interface. */
res = cfhsi->dev->cfhsi_up(cfhsi->dev);
if (res) {
@ -1303,15 +1308,7 @@ int cfhsi_probe(struct platform_device *pdev)
/* Flush FIFO */
res = cfhsi_flush_fifo(cfhsi);
if (res) {
dev_err(&ndev->dev, "%s: Can't flush FIFO: %d.\n",
__func__, res);
goto err_net_reg;
}
/* Register network device. */
res = register_netdev(ndev);
if (res) {
dev_err(&ndev->dev, "%s: Registration error: %d.\n",
dev_err(&cfhsi->ndev->dev, "%s: Can't flush FIFO: %d.\n",
__func__, res);
goto err_net_reg;
}
@ -1328,13 +1325,12 @@ int cfhsi_probe(struct platform_device *pdev)
err_alloc_rx:
kfree(cfhsi->tx_buf);
err_alloc_tx:
free_netdev(ndev);
return res;
}
static void cfhsi_shutdown(struct cfhsi *cfhsi)
static int cfhsi_close(struct net_device *ndev)
{
struct cfhsi *cfhsi = netdev_priv(ndev);
u8 *tx_buf, *rx_buf, *flip_buf;
/* going to shutdown driver */
@ -1364,15 +1360,19 @@ static void cfhsi_shutdown(struct cfhsi *cfhsi)
/* Deactivate interface */
cfhsi->dev->cfhsi_down(cfhsi->dev);
/* Finally unregister the network device. */
unregister_netdev(cfhsi->ndev);
/* Free buffers. */
kfree(tx_buf);
kfree(rx_buf);
kfree(flip_buf);
return 0;
}
static const struct net_device_ops cfhsi_ops = {
.ndo_open = cfhsi_open,
.ndo_stop = cfhsi_close,
.ndo_start_xmit = cfhsi_xmit
};
int cfhsi_remove(struct platform_device *pdev)
{
struct list_head *list_node;
@ -1389,10 +1389,6 @@ int cfhsi_remove(struct platform_device *pdev)
/* Remove from list. */
list_del(list_node);
spin_unlock(&cfhsi_list_lock);
/* Shutdown driver. */
cfhsi_shutdown(cfhsi);
return 0;
}
}
@ -1423,8 +1419,7 @@ static void __exit cfhsi_exit_module(void)
list_del(list_node);
spin_unlock(&cfhsi_list_lock);
/* Shutdown driver. */
cfhsi_shutdown(cfhsi);
unregister_netdevice(cfhsi->ndev);
spin_lock(&cfhsi_list_lock);
}
@ -1449,8 +1444,6 @@ static int __init cfhsi_init_module(void)
goto err_dev_register;
}
return result;
err_dev_register:
return result;
}