Skip to content

Commit

Permalink
Merge branch 'netcp-fixes'
Browse files Browse the repository at this point in the history
Murali Karicheri says:

====================
net: netcp: bug fixes for dynamic module support

This series fixes few bugs to allow keystone netcp modules to be
dynamically loaded and removed. Currently it allows following
sequence multiple times

 insmod cpsw_ale.ko
 insmod davinci_mdio.ko
 insmod keystone_netcp.ko
 insmod keystone_netcp_ethss.ko
 ifup eth0
 ifup eth1
 ping <hosts on eth0>
 ping <hosts on eth1>
 ifdown eth1
 ifdown eth0
 rmmod keystone_netcp_ethss.ko
 rmmod keystone_netcp.ko
 rmmod davinci_mdio.ko
 rmmod cpsw_ale.ko
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 30, 2015
2 parents 2482abb + 31a184b commit b2428f9
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 33 deletions.
14 changes: 11 additions & 3 deletions drivers/net/ethernet/ti/netcp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,7 @@ static int netcp_probe(struct platform_device *pdev)
static int netcp_remove(struct platform_device *pdev)
{
struct netcp_device *netcp_device = platform_get_drvdata(pdev);
struct netcp_intf *netcp_intf, *netcp_tmp;
struct netcp_inst_modpriv *inst_modpriv, *tmp;
struct netcp_module *module;

Expand All @@ -2123,10 +2124,17 @@ static int netcp_remove(struct platform_device *pdev)
list_del(&inst_modpriv->inst_list);
kfree(inst_modpriv);
}
WARN(!list_empty(&netcp_device->interface_head), "%s interface list not empty!\n",
pdev->name);

devm_kfree(&pdev->dev, netcp_device);
/* now that all modules are removed, clean up the interfaces */
list_for_each_entry_safe(netcp_intf, netcp_tmp,
&netcp_device->interface_head,
interface_list) {
netcp_delete_interface(netcp_device, netcp_intf->ndev);
}

WARN(!list_empty(&netcp_device->interface_head),
"%s interface list not empty!\n", pdev->name);

pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
platform_set_drvdata(pdev, NULL);
Expand Down
49 changes: 19 additions & 30 deletions drivers/net/ethernet/ti/netcp_ethss.c
Original file line number Diff line number Diff line change
Expand Up @@ -2508,10 +2508,9 @@ static void free_secondary_ports(struct gbe_priv *gbe_dev)
{
struct gbe_slave *slave;

for (;;) {
while (!list_empty(&gbe_dev->secondary_slaves)) {
slave = first_sec_slave(gbe_dev);
if (!slave)
break;

if (slave->phy)
phy_disconnect(slave->phy);
list_del(&slave->slave_list);
Expand Down Expand Up @@ -2857,14 +2856,13 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
&gbe_dev->dma_chan_name);
if (ret < 0) {
dev_err(dev, "missing \"tx-channel\" parameter\n");
ret = -ENODEV;
goto quit;
return -EINVAL;
}

if (!strcmp(node->name, "gbe")) {
ret = get_gbe_resource_version(gbe_dev, node);
if (ret)
goto quit;
return ret;

dev_dbg(dev, "ss_version: 0x%08x\n", gbe_dev->ss_version);

Expand All @@ -2875,34 +2873,32 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
else
ret = -ENODEV;

if (ret)
goto quit;
} else if (!strcmp(node->name, "xgbe")) {
ret = set_xgbe_ethss10_priv(gbe_dev, node);
if (ret)
goto quit;
return ret;
ret = netcp_xgbe_serdes_init(gbe_dev->xgbe_serdes_regs,
gbe_dev->ss_regs);
if (ret)
goto quit;
} else {
dev_err(dev, "unknown GBE node(%s)\n", node->name);
ret = -ENODEV;
goto quit;
}

if (ret)
return ret;

interfaces = of_get_child_by_name(node, "interfaces");
if (!interfaces)
dev_err(dev, "could not find interfaces\n");

ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device,
gbe_dev->dma_chan_name, gbe_dev->tx_queue_id);
if (ret)
goto quit;
return ret;

ret = netcp_txpipe_open(&gbe_dev->tx_pipe);
if (ret)
goto quit;
return ret;

/* Create network interfaces */
INIT_LIST_HEAD(&gbe_dev->gbe_intf_head);
Expand All @@ -2917,6 +2913,7 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
break;
}
of_node_put(interfaces);

if (!gbe_dev->num_slaves)
dev_warn(dev, "No network interface configured\n");
Expand All @@ -2929,9 +2926,10 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
of_node_put(secondary_ports);

if (!gbe_dev->num_slaves) {
dev_err(dev, "No network interface or secondary ports configured\n");
dev_err(dev,
"No network interface or secondary ports configured\n");
ret = -ENODEV;
goto quit;
goto free_sec_ports;
}

memset(&ale_params, 0, sizeof(ale_params));
Expand All @@ -2945,7 +2943,7 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
if (!gbe_dev->ale) {
dev_err(gbe_dev->dev, "error initializing ale engine\n");
ret = -ENODEV;
goto quit;
goto free_sec_ports;
} else {
dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n");
}
Expand All @@ -2961,14 +2959,8 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
*inst_priv = gbe_dev;
return 0;

quit:
if (gbe_dev->hw_stats)
devm_kfree(dev, gbe_dev->hw_stats);
cpsw_ale_destroy(gbe_dev->ale);
if (gbe_dev->ss_regs)
devm_iounmap(dev, gbe_dev->ss_regs);
of_node_put(interfaces);
devm_kfree(dev, gbe_dev);
free_sec_ports:
free_secondary_ports(gbe_dev);
return ret;
}

Expand Down Expand Up @@ -3041,12 +3033,9 @@ static int gbe_remove(struct netcp_device *netcp_device, void *inst_priv)
free_secondary_ports(gbe_dev);

if (!list_empty(&gbe_dev->gbe_intf_head))
dev_alert(gbe_dev->dev, "unreleased ethss interfaces present\n");
dev_alert(gbe_dev->dev,
"unreleased ethss interfaces present\n");

devm_kfree(gbe_dev->dev, gbe_dev->hw_stats);
devm_iounmap(gbe_dev->dev, gbe_dev->ss_regs);
memset(gbe_dev, 0x00, sizeof(*gbe_dev));
devm_kfree(gbe_dev->dev, gbe_dev);
return 0;
}

Expand Down

0 comments on commit b2428f9

Please sign in to comment.