Commit b01b4bab authored by Stefan Richter's avatar Stefan Richter

firewire: net: fix card driver reloading

Fix some problems from "firewire: net: allow for unordered unit
discovery":
  - fwnet_remove was missing a list_del, causing fwnet_probe to crash if
    called after fwnet_remove, e.g. if firewire-ohci was unloaded and
    reloaded.
  - fwnet_probe should set its new_netdev flag only if it actually
    allocated a net_device.
  - Use dev_set_drvdata and dev_get_drvdata instead of deprecated direct
    access to device.driver_data.
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent d645f4da
...@@ -1390,7 +1390,8 @@ static int fwnet_add_peer(struct fwnet_device *dev, ...@@ -1390,7 +1390,8 @@ static int fwnet_add_peer(struct fwnet_device *dev,
if (!peer) if (!peer)
return -ENOMEM; return -ENOMEM;
unit->device.driver_data = peer; dev_set_drvdata(&unit->device, peer);
peer->dev = dev; peer->dev = dev;
peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
peer->fifo = FWNET_NO_FIFO_ADDR; peer->fifo = FWNET_NO_FIFO_ADDR;
...@@ -1417,27 +1418,26 @@ static int fwnet_probe(struct device *_dev) ...@@ -1417,27 +1418,26 @@ static int fwnet_probe(struct device *_dev)
struct fw_device *device = fw_parent_device(unit); struct fw_device *device = fw_parent_device(unit);
struct fw_card *card = device->card; struct fw_card *card = device->card;
struct net_device *net; struct net_device *net;
bool allocated_netdev = false;
struct fwnet_device *dev; struct fwnet_device *dev;
unsigned max_mtu; unsigned max_mtu;
bool new_netdev;
int ret; int ret;
mutex_lock(&fwnet_device_mutex); mutex_lock(&fwnet_device_mutex);
dev = fwnet_dev_find(card); dev = fwnet_dev_find(card);
if (dev) { if (dev) {
new_netdev = false;
net = dev->netdev; net = dev->netdev;
goto have_dev; goto have_dev;
} }
new_netdev = true;
net = alloc_netdev(sizeof(*dev), "firewire%d", fwnet_init_dev); net = alloc_netdev(sizeof(*dev), "firewire%d", fwnet_init_dev);
if (net == NULL) { if (net == NULL) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
allocated_netdev = true;
SET_NETDEV_DEV(net, card->device); SET_NETDEV_DEV(net, card->device);
dev = netdev_priv(net); dev = netdev_priv(net);
...@@ -1479,12 +1479,12 @@ static int fwnet_probe(struct device *_dev) ...@@ -1479,12 +1479,12 @@ static int fwnet_probe(struct device *_dev)
net->name, (unsigned long long)card->guid); net->name, (unsigned long long)card->guid);
have_dev: have_dev:
ret = fwnet_add_peer(dev, unit, device); ret = fwnet_add_peer(dev, unit, device);
if (ret && new_netdev) { if (ret && allocated_netdev) {
unregister_netdev(net); unregister_netdev(net);
list_del(&dev->dev_link); list_del(&dev->dev_link);
} }
out: out:
if (ret && new_netdev) if (ret && allocated_netdev)
free_netdev(net); free_netdev(net);
mutex_unlock(&fwnet_device_mutex); mutex_unlock(&fwnet_device_mutex);
...@@ -1508,7 +1508,7 @@ static void fwnet_remove_peer(struct fwnet_peer *peer) ...@@ -1508,7 +1508,7 @@ static void fwnet_remove_peer(struct fwnet_peer *peer)
static int fwnet_remove(struct device *_dev) static int fwnet_remove(struct device *_dev)
{ {
struct fwnet_peer *peer = _dev->driver_data; struct fwnet_peer *peer = dev_get_drvdata(_dev);
struct fwnet_device *dev = peer->dev; struct fwnet_device *dev = peer->dev;
struct net_device *net; struct net_device *net;
struct fwnet_packet_task *ptask, *pt_next; struct fwnet_packet_task *ptask, *pt_next;
...@@ -1544,6 +1544,8 @@ static int fwnet_remove(struct device *_dev) ...@@ -1544,6 +1544,8 @@ static int fwnet_remove(struct device *_dev)
dev_kfree_skb_any(ptask->skb); dev_kfree_skb_any(ptask->skb);
kmem_cache_free(fwnet_packet_task_cache, ptask); kmem_cache_free(fwnet_packet_task_cache, ptask);
} }
list_del(&dev->dev_link);
free_netdev(net); free_netdev(net);
} }
...@@ -1559,7 +1561,7 @@ static int fwnet_remove(struct device *_dev) ...@@ -1559,7 +1561,7 @@ static int fwnet_remove(struct device *_dev)
static void fwnet_update(struct fw_unit *unit) static void fwnet_update(struct fw_unit *unit)
{ {
struct fw_device *device = fw_parent_device(unit); struct fw_device *device = fw_parent_device(unit);
struct fwnet_peer *peer = unit->device.driver_data; struct fwnet_peer *peer = dev_get_drvdata(&unit->device);
int generation; int generation;
generation = device->generation; generation = device->generation;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment