drivers/net/wireless/marvell/libertas/mesh.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/marvell/libertas/mesh.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/marvell/libertas/mesh.c
Extension
.c
Size
29451 bytes
Lines
1162
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops mesh_netdev_ops = {
	.ndo_open		= lbs_mesh_dev_open,
	.ndo_stop 		= lbs_mesh_stop,
	.ndo_start_xmit		= lbs_hard_start_xmit,
	.ndo_set_mac_address	= lbs_set_mac_address,
	.ndo_set_rx_mode	= lbs_set_multicast_list,
};

/**
 * lbs_add_mesh - add mshX interface
 *
 * @priv:	A pointer to the &struct lbs_private structure
 * returns:	0 if successful, -X otherwise
 */
static int lbs_add_mesh(struct lbs_private *priv)
{
	struct net_device *mesh_dev = NULL;
	struct wireless_dev *mesh_wdev;
	int ret = 0;

	/* Allocate a virtual mesh device */
	mesh_wdev = kzalloc_obj(struct wireless_dev);
	if (!mesh_wdev) {
		lbs_deb_mesh("init mshX wireless device failed\n");
		ret = -ENOMEM;
		goto done;
	}

	mesh_dev = alloc_netdev(0, "msh%d", NET_NAME_UNKNOWN, ether_setup);
	if (!mesh_dev) {
		lbs_deb_mesh("init mshX device failed\n");
		ret = -ENOMEM;
		goto err_free_wdev;
	}

	mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT;
	mesh_wdev->wiphy = priv->wdev->wiphy;

	if (priv->mesh_tlv) {
		sprintf(mesh_wdev->u.mesh.id, "mesh");
		mesh_wdev->u.mesh.id_up_len = 4;
	}

	mesh_wdev->netdev = mesh_dev;

	mesh_dev->ml_priv = priv;
	mesh_dev->ieee80211_ptr = mesh_wdev;
	priv->mesh_dev = mesh_dev;

	mesh_dev->netdev_ops = &mesh_netdev_ops;
	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
	eth_hw_addr_inherit(mesh_dev, priv->dev);

	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);

	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
	mesh_dev->sysfs_groups[0] = &lbs_mesh_attr_group;
	mesh_dev->sysfs_groups[1] = &boot_opts_group;
	mesh_dev->sysfs_groups[2] = &mesh_ie_group;

	/* Register virtual mesh interface */
	ret = register_netdev(mesh_dev);
	if (ret) {
		pr_err("cannot register mshX virtual interface\n");
		goto err_free_netdev;
	}

	/* Everything successful */
	ret = 0;
	goto done;

err_free_netdev:
	free_netdev(mesh_dev);

err_free_wdev:
	kfree(mesh_wdev);

done:
	return ret;
}

void lbs_remove_mesh(struct lbs_private *priv)
{
	struct net_device *mesh_dev;

	mesh_dev = priv->mesh_dev;
	if (!mesh_dev)
		return;

	netif_stop_queue(mesh_dev);

Annotation

Implementation Notes