static int fwnet_probe()

in net.c [1438:1523]


static int fwnet_probe(struct fw_unit *unit,
		       const struct ieee1394_device_id *id)
{
	struct fw_device *device = fw_parent_device(unit);
	struct fw_card *card = device->card;
	struct net_device *net;
	bool allocated_netdev = false;
	struct fwnet_device *dev;
	union fwnet_hwaddr ha;
	int ret;

	mutex_lock(&fwnet_device_mutex);

	dev = fwnet_dev_find(card);
	if (dev) {
		net = dev->netdev;
		goto have_dev;
	}

	net = alloc_netdev(sizeof(*dev), "firewire%d", NET_NAME_UNKNOWN,
			   fwnet_init_dev);
	if (net == NULL) {
		mutex_unlock(&fwnet_device_mutex);
		return -ENOMEM;
	}

	allocated_netdev = true;
	SET_NETDEV_DEV(net, card->device);
	dev = netdev_priv(net);

	spin_lock_init(&dev->lock);
	dev->broadcast_state = FWNET_BROADCAST_ERROR;
	dev->broadcast_rcv_context = NULL;
	dev->broadcast_xmt_max_payload = 0;
	dev->broadcast_xmt_datagramlabel = 0;
	dev->local_fifo = FWNET_NO_FIFO_ADDR;
	dev->queued_datagrams = 0;
	INIT_LIST_HEAD(&dev->peer_list);
	dev->card = card;
	dev->netdev = net;

	ret = fwnet_fifo_start(dev);
	if (ret < 0)
		goto out;
	dev->local_fifo = dev->handler.offset;

	/*
	 * default MTU: RFC 2734 cl. 4, RFC 3146 cl. 4
	 * maximum MTU: RFC 2734 cl. 4.2, fragment encapsulation header's
	 *              maximum possible datagram_size + 1 = 0xfff + 1
	 */
	net->mtu = 1500U;
	net->min_mtu = ETH_MIN_MTU;
	net->max_mtu = 4096U;

	/* Set our hardware address while we're at it */
	ha.uc.uniq_id = cpu_to_be64(card->guid);
	ha.uc.max_rec = dev->card->max_receive;
	ha.uc.sspd = dev->card->link_speed;
	ha.uc.fifo_hi = cpu_to_be16(dev->local_fifo >> 32);
	ha.uc.fifo_lo = cpu_to_be32(dev->local_fifo & 0xffffffff);
	dev_addr_set(net, ha.u);

	memset(net->broadcast, -1, net->addr_len);

	ret = register_netdev(net);
	if (ret)
		goto out;

	list_add_tail(&dev->dev_link, &fwnet_device_list);
	dev_notice(&net->dev, "IP over IEEE 1394 on card %s\n",
		   dev_name(card->device));
 have_dev:
	ret = fwnet_add_peer(dev, unit, device);
	if (ret && allocated_netdev) {
		unregister_netdev(net);
		list_del(&dev->dev_link);
 out:
		fwnet_fifo_stop(dev);
		free_netdev(net);
	}

	mutex_unlock(&fwnet_device_mutex);

	return ret;
}