Merge branch 'netcp-fixes'
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>
This commit is contained in:
commit
b2428f94f4
|
@ -2112,6 +2112,7 @@ probe_quit:
|
|||
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;
|
||||
|
||||
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -2875,22 +2873,20 @@ 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");
|
||||
|
@ -2898,11 +2894,11 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
|
|||
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);
|
||||
|
@ -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");
|
||||
|
@ -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));
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue