示例#1
0
/**
 * gether_setup_name - initialize one ethernet-over-usb link
 * @g: gadget to associated with these links
 * @ethaddr: NULL, or a buffer in which the ethernet address of the
 *	host side of the link is recorded
 * @netname: name for network device (for example, "usb")
 * Context: may sleep
 *
 * This sets up the single network link that may be exported by a
 * gadget driver using this framework.  The link layer addresses are
 * set up using module parameters.
 *
 * Returns negative errno, or zero on success
 */
struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
		const char *netname)
{
	struct eth_dev		*dev;
	struct net_device	*net;
	int			status;

	net = alloc_etherdev(sizeof *dev);
	if (!net)
		return ERR_PTR(-ENOMEM);

	dev = netdev_priv(net);
	spin_lock_init(&dev->lock);
	spin_lock_init(&dev->req_lock);
	INIT_WORK(&dev->work, eth_work);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->rx_reqs);

	skb_queue_head_init(&dev->rx_frames);

	/* network device setup */
	dev->net = net;
	snprintf(net->name, sizeof(net->name), "%s%%d", netname);

	if (get_ether_addr(dev_addr, net->dev_addr))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "self");
	if (get_ether_addr(host_addr, dev->host_mac))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "host");

	if (ethaddr)
		memcpy(ethaddr, dev->host_mac, ETH_ALEN);

	net->netdev_ops = &eth_netdev_ops;

	SET_ETHTOOL_OPS(net, &ops);

	dev->gadget = g;
	SET_NETDEV_DEV(net, &g->dev);
	SET_NETDEV_DEVTYPE(net, &gadget_type);

	status = register_netdev(net);
	if (status < 0) {
		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
		free_netdev(net);
		dev = ERR_PTR(status);
	} else {
		INFO(dev, "MAC %pM\n", net->dev_addr);
		INFO(dev, "HOST MAC %pM\n", dev->host_mac);

		/* two kinds of host-initiated state changes:
		 *  - iff DATA transfer is active, carrier is "on"
		 *  - tx queueing enabled if open *and* carrier is "on"
		 */
		netif_carrier_off(net);
	}

	return dev;
}
示例#2
0
void hsr_dev_setup(struct net_device *dev)
{
	random_ether_addr(dev->dev_addr);

	ether_setup(dev);
	dev->header_ops = &hsr_header_ops;
	dev->netdev_ops = &hsr_device_ops;
	SET_NETDEV_DEVTYPE(dev, &hsr_type);
	dev->priv_flags |= IFF_NO_QUEUE;

	dev->destructor = hsr_dev_destroy;

	dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
			   NETIF_F_GSO_MASK | NETIF_F_HW_CSUM |
			   NETIF_F_HW_VLAN_CTAG_TX;

	dev->features = dev->hw_features;

	/* Prevent recursive tx locking */
	dev->features |= NETIF_F_LLTX;
	/* VLAN on top of HSR needs testing and probably some work on
	 * hsr_header_create() etc.
	 */
	dev->features |= NETIF_F_VLAN_CHALLENGED;
	/* Not sure about this. Taken from bridge code. netdev_features.h says
	 * it means "Does not change network namespaces".
	 */
	dev->features |= NETIF_F_NETNS_LOCAL;
}
示例#3
0
文件: u_ether.c 项目: Chong-Li/cse522
struct net_device *gether_setup_name_default(const char *netname)
{
	struct net_device	*net;
	struct eth_dev		*dev;

	net = alloc_etherdev(sizeof(*dev));
	if (!net)
		return ERR_PTR(-ENOMEM);

	dev = netdev_priv(net);
	spin_lock_init(&dev->lock);
	spin_lock_init(&dev->req_lock);
	INIT_WORK(&dev->work, eth_work);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->rx_reqs);

	skb_queue_head_init(&dev->rx_frames);

	/* network device setup */
	dev->net = net;
	dev->qmult = QMULT_DEFAULT;
	snprintf(net->name, sizeof(net->name), "%s%%d", netname);

	eth_random_addr(dev->dev_mac);
	pr_warn("using random %s ethernet address\n", "self");
	eth_random_addr(dev->host_mac);
	pr_warn("using random %s ethernet address\n", "host");

	net->netdev_ops = &eth_netdev_ops;

	net->ethtool_ops = &ops;
	SET_NETDEV_DEVTYPE(net, &gadget_type);

	return net;
}
示例#4
0
文件: vlan_dev.c 项目: aejsmith/linux
static int vlan_dev_init(struct net_device *dev)
{
    struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;

    netif_carrier_off(dev);

    /* IFF_BROADCAST|IFF_MULTICAST; ??? */
    dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
                                      IFF_MASTER | IFF_SLAVE);
    dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
                                      (1<<__LINK_STATE_DORMANT))) |
                  (1<<__LINK_STATE_PRESENT);

    dev->hw_features = NETIF_F_ALL_CSUM | NETIF_F_SG |
                       NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE |
                       NETIF_F_HIGHDMA | NETIF_F_SCTP_CSUM |
                       NETIF_F_ALL_FCOE;

    dev->features |= real_dev->vlan_features | NETIF_F_LLTX |
                     NETIF_F_GSO_SOFTWARE;
    dev->gso_max_size = real_dev->gso_max_size;
    if (dev->features & NETIF_F_VLAN_FEATURES)
        netdev_warn(real_dev, "VLAN features are set incorrectly.  Q-in-Q configurations may not work correctly.\n");

    dev->vlan_features = real_dev->vlan_features & ~NETIF_F_ALL_FCOE;

    /* ipv6 shared card related stuff */
    dev->dev_id = real_dev->dev_id;

    if (is_zero_ether_addr(dev->dev_addr))
        eth_hw_addr_inherit(dev, real_dev);
    if (is_zero_ether_addr(dev->broadcast))
        memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);

#if IS_ENABLED(CONFIG_FCOE)
    dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
#endif

    dev->needed_headroom = real_dev->needed_headroom;
    if (vlan_hw_offload_capable(real_dev->features,
                                vlan_dev_priv(dev)->vlan_proto)) {
        dev->header_ops      = &vlan_passthru_header_ops;
        dev->hard_header_len = real_dev->hard_header_len;
    } else {
        dev->header_ops      = &vlan_header_ops;
        dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
    }

    dev->netdev_ops = &vlan_netdev_ops;

    SET_NETDEV_DEVTYPE(dev, &vlan_type);

    vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev));

    vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats);
    if (!vlan_dev_priv(dev)->vlan_pcpu_stats)
        return -ENOMEM;

    return 0;
}
static int vlan_dev_init(struct net_device *dev)
{
	struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
	int subclass = 0;

	netif_carrier_off(dev);

	/* IFF_BROADCAST|IFF_MULTICAST; ??? */
	dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI |
					  IFF_MASTER | IFF_SLAVE);
	dev->iflink = real_dev->ifindex;
	dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
					  (1<<__LINK_STATE_DORMANT))) |
		      (1<<__LINK_STATE_PRESENT);

	dev->hw_features = NETIF_F_ALL_CSUM | NETIF_F_SG |
			   NETIF_F_FRAGLIST | NETIF_F_ALL_TSO |
			   NETIF_F_HIGHDMA | NETIF_F_SCTP_CSUM |
			   NETIF_F_ALL_FCOE;

	dev->features |= real_dev->vlan_features | NETIF_F_LLTX;
	dev->gso_max_size = real_dev->gso_max_size;

	/* ipv6 shared card related stuff */
	dev->dev_id = real_dev->dev_id;

	if (is_zero_ether_addr(dev->dev_addr))
		memcpy(dev->dev_addr, real_dev->dev_addr, dev->addr_len);
	if (is_zero_ether_addr(dev->broadcast))
		memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);

#if IS_ENABLED(CONFIG_FCOE)
	dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
#endif

	dev->needed_headroom = real_dev->needed_headroom;
	if (real_dev->features & NETIF_F_HW_VLAN_CTAG_TX) {
		dev->header_ops      = real_dev->header_ops;
		dev->hard_header_len = real_dev->hard_header_len;
	} else {
		dev->header_ops      = &vlan_header_ops;
		dev->hard_header_len = real_dev->hard_header_len + VLAN_HLEN;
	}

	dev->netdev_ops = &vlan_netdev_ops;

	SET_NETDEV_DEVTYPE(dev, &vlan_type);

	if (is_vlan_dev(real_dev))
		subclass = 1;

	vlan_dev_set_lockdep_class(dev, subclass);

	vlan_dev_priv(dev)->vlan_pcpu_stats = alloc_percpu(struct vlan_pcpu_stats);
	if (!vlan_dev_priv(dev)->vlan_pcpu_stats)
		return -ENOMEM;

	return 0;
}
示例#6
0
static void l2tp_eth_dev_setup(struct net_device *dev)
{
	SET_NETDEV_DEVTYPE(dev, &l2tpeth_type);
	ether_setup(dev);
	dev->priv_flags		&= ~IFF_TX_SKB_SHARING;
	dev->features		|= NETIF_F_LLTX;
	dev->netdev_ops		= &l2tp_eth_netdev_ops;
	dev->needs_free_netdev	= true;
}
示例#7
0
/**
 * gether_qc_setup_name - initialize one ethernet-over-usb link
 * @g: gadget to associated with these links
 * @ethaddr: NULL, or a buffer in which the ethernet address of the
 *	host side of the link is recorded
 * @netname: name for network device (for example, "usb")
 * Context: may sleep
 *
 * This sets up the single network link that may be exported by a
 * gadget driver using this framework.  The link layer addresses are
 * set up using module parameters.
 *
 * Returns negative errno, or zero on success
 */
int gether_qc_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
		const char *netname)
{
	struct eth_qc_dev		*dev;
	struct net_device	*net;
	int			status;

	if (qc_dev)
		return -EBUSY;

	net = alloc_etherdev(sizeof *dev);
	if (!net)
		return -ENOMEM;

	dev = netdev_priv(net);
	spin_lock_init(&dev->lock);

	/* network device setup */
	dev->net = net;
	snprintf(net->name, sizeof(net->name), "%s%%d", netname);

	if (get_qc_ether_addr(qc_dev_addr, net->dev_addr))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "self");
	if (get_qc_ether_addr(qc_host_addr, dev->host_mac))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "host");

	if (ethaddr)
		memcpy(ethaddr, dev->host_mac, ETH_ALEN);

	net->netdev_ops = &eth_qc_netdev_ops;

	SET_ETHTOOL_OPS(net, &qc_ethtool_ops);

	netif_carrier_off(net);

	dev->gadget = g;
	SET_NETDEV_DEV(net, &g->dev);
	SET_NETDEV_DEVTYPE(net, &qc_gadget_type);

	status = register_netdev(net);
	if (status < 0) {
		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
		free_netdev(net);
	} else {
		INFO(dev, "MAC %pM\n", net->dev_addr);
		INFO(dev, "HOST MAC %pM\n", dev->host_mac);

		qc_dev = dev;
	}

	return status;
}
示例#8
0
int register_networkdev(struct bcm_mini_adapter *Adapter)
{
	struct net_device *net = Adapter->dev;
	struct bcm_interface_adapter *IntfAdapter = Adapter->pvInterfaceAdapter;
	struct usb_interface *udev = IntfAdapter->interface;
	struct usb_device *xdev = IntfAdapter->udev;

	int result;

	net->netdev_ops = &bcmNetDevOps;
	net->ethtool_ops = &bcm_ethtool_ops;
	net->mtu = MTU_SIZE;	/* 1400 Bytes */
	net->tx_queue_len = TX_QLEN;
	net->flags |= IFF_NOARP;

	netif_carrier_off(net);

	SET_NETDEV_DEVTYPE(net, &wimax_type);

	/* Read the MAC Address from EEPROM */
	result = ReadMacAddressFromNVM(Adapter);
	if (result != STATUS_SUCCESS) {
		dev_err(&udev->dev,
			PFX "Error in Reading the mac Address: %d", result);
		return -EIO;
	}

	result = register_netdev(net);
	if (result)
		return result;

	gblpnetdev = Adapter->dev;

	if (netif_msg_probe(Adapter))
		dev_info(&udev->dev, PFX "%s: register usb-%s-%s %pM\n",
			 net->name, xdev->bus->bus_name, xdev->devpath,
			 net->dev_addr);

	return 0;
}
示例#9
0
文件: slave.c 项目: andy-shev/linux
int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
		     int port, char *name)
{
	struct net_device *master = ds->dst->master_netdev;
	struct net_device *slave_dev;
	struct dsa_slave_priv *p;
	int ret;

	slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name,
				 NET_NAME_UNKNOWN, ether_setup);
	if (slave_dev == NULL)
		return -ENOMEM;

	slave_dev->features = master->vlan_features;
	slave_dev->ethtool_ops = &dsa_slave_ethtool_ops;
	eth_hw_addr_inherit(slave_dev, master);
	slave_dev->priv_flags |= IFF_NO_QUEUE;
	slave_dev->netdev_ops = &dsa_slave_netdev_ops;
	slave_dev->switchdev_ops = &dsa_slave_switchdev_ops;
	SET_NETDEV_DEVTYPE(slave_dev, &dsa_type);

	netdev_for_each_tx_queue(slave_dev, dsa_slave_set_lockdep_class_one,
				 NULL);

	SET_NETDEV_DEV(slave_dev, parent);
	slave_dev->dev.of_node = ds->pd->port_dn[port];
	slave_dev->vlan_features = master->vlan_features;

	p = netdev_priv(slave_dev);
	p->dev = slave_dev;
	p->parent = ds;
	p->port = port;

	switch (ds->dst->tag_protocol) {
#ifdef CONFIG_NET_DSA_TAG_DSA
	case DSA_TAG_PROTO_DSA:
		p->xmit = dsa_netdev_ops.xmit;
		break;
#endif
#ifdef CONFIG_NET_DSA_TAG_EDSA
	case DSA_TAG_PROTO_EDSA:
		p->xmit = edsa_netdev_ops.xmit;
		break;
#endif
#ifdef CONFIG_NET_DSA_TAG_TRAILER
	case DSA_TAG_PROTO_TRAILER:
		p->xmit = trailer_netdev_ops.xmit;
		break;
#endif
#ifdef CONFIG_NET_DSA_TAG_BRCM
	case DSA_TAG_PROTO_BRCM:
		p->xmit = brcm_netdev_ops.xmit;
		break;
#endif
	default:
		p->xmit	= dsa_slave_notag_xmit;
		break;
	}

	p->old_pause = -1;
	p->old_link = -1;
	p->old_duplex = -1;

	ds->ports[port] = slave_dev;
	ret = register_netdev(slave_dev);
	if (ret) {
		netdev_err(master, "error %d registering interface %s\n",
			   ret, slave_dev->name);
		ds->ports[port] = NULL;
		free_netdev(slave_dev);
		return ret;
	}

	netif_carrier_off(slave_dev);

	ret = dsa_slave_phy_setup(p, slave_dev);
	if (ret) {
		netdev_err(master, "error %d setting up slave phy\n", ret);
		unregister_netdev(slave_dev);
		free_netdev(slave_dev);
		return ret;
	}

	return 0;
}
示例#10
0
/**
 * gether_setup - initialize one ethernet-over-usb link
 * @g: gadget to associated with these links
 * @ethaddr: NULL, or a buffer in which the ethernet address of the
 *	host side of the link is recorded
 * Context: may sleep
 *
 * This sets up the single network link that may be exported by a
 * gadget driver using this framework.  The link layer addresses are
 * set up using module parameters.
 *
 * Returns negative errno, or zero on success
 */
int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
{
	struct eth_dev		*dev;
	struct net_device	*net;
	int			status;

	if (the_dev)
		return -EBUSY;

	net = alloc_etherdev(sizeof *dev);
	if (!net)
		return -ENOMEM;

#ifdef CONFIG_USB_ANDROID_VERIZON
	/* verizon requirement : mtu size fix to 1428 */        
	net->mtu = 1428;
#endif
	dev = netdev_priv(net);
	spin_lock_init(&dev->lock);
	spin_lock_init(&dev->req_lock);
	INIT_WORK(&dev->work, eth_work);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->rx_reqs);

	skb_queue_head_init(&dev->rx_frames);

	/* network device setup */
	dev->net = net;
	strcpy(net->name, "usb%d");

	if (get_ether_addr(dev_addr, net->dev_addr))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "self");
	if (get_ether_addr(host_addr, dev->host_mac))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "host");

	if (ethaddr)
		memcpy(ethaddr, dev->host_mac, ETH_ALEN);

	net->netdev_ops = &eth_netdev_ops;

	SET_ETHTOOL_OPS(net, &ops);

	/* two kinds of host-initiated state changes:
	 *  - iff DATA transfer is active, carrier is "on"
	 *  - tx queueing enabled if open *and* carrier is "on"
	 */
	netif_stop_queue(net);
	netif_carrier_off(net);

	dev->gadget = g;
	SET_NETDEV_DEV(net, &g->dev);
	SET_NETDEV_DEVTYPE(net, &gadget_type);

	status = register_netdev(net);
	if (status < 0) {
		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
		free_netdev(net);
	} else {
		the_dev = dev;
	}

	return status;
}
示例#11
0
int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{
	struct usbnet			*dev;
	struct net_device		*net;
	struct usb_host_interface	*interface;
	struct driver_info		*info;
	struct usb_device		*xdev;
	int				status;
	const char			*name;

	name = udev->dev.driver->name;
	info = (struct driver_info *) prod->driver_info;
	if (!info) {
		dev_dbg (&udev->dev, "blacklisted by %s\n", name);
		return -ENODEV;
	}
	xdev = interface_to_usbdev (udev);
	interface = udev->cur_altsetting;

	usb_get_dev (xdev);

	status = -ENOMEM;

	// set up our own records
	net = alloc_etherdev(sizeof(*dev));
	if (!net) {
		dbg ("can't kmalloc dev");
		goto out;
	}

	dev = netdev_priv(net);
	dev->udev = xdev;
	dev->intf = udev;
	dev->driver_info = info;
	dev->driver_name = name;
	dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV
				| NETIF_MSG_PROBE | NETIF_MSG_LINK);
	skb_queue_head_init (&dev->rxq);
	skb_queue_head_init (&dev->txq);
	skb_queue_head_init (&dev->done);
	skb_queue_head_init(&dev->rxq_pause);
	dev->bh.func = usbnet_bh;
	dev->bh.data = (unsigned long) dev;
	INIT_WORK (&dev->kevent, kevent);
	init_usb_anchor(&dev->deferred);
	dev->delay.function = usbnet_bh;
	dev->delay.data = (unsigned long) dev;
	init_timer (&dev->delay);
	mutex_init (&dev->phy_mutex);

	dev->net = net;
	strcpy (net->name, "usb%d");
	memcpy (net->dev_addr, node_id, sizeof node_id);

	/* rx and tx sides can use different message sizes;
	 * bind() should set rx_urb_size in that case.
	 */
	dev->hard_mtu = net->mtu + net->hard_header_len;
#if 0
// dma_supported() is deeply broken on almost all architectures
	// possible with some EHCI controllers
	if (dma_supported (&udev->dev, DMA_BIT_MASK(64)))
		net->features |= NETIF_F_HIGHDMA;
#endif

	net->netdev_ops = &usbnet_netdev_ops;
	net->watchdog_timeo = TX_TIMEOUT_JIFFIES;
	net->ethtool_ops = &usbnet_ethtool_ops;

	// allow device-specific bind/init procedures
	// NOTE net->name still not usable ...
	if (info->bind) {
		status = info->bind (dev, udev);
		if (status < 0)
			goto out1;

		// heuristic:  "usb%d" for links we know are two-host,
		// else "eth%d" when there's reasonable doubt.  userspace
		// can rename the link if it knows better.
		if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
		    (net->dev_addr [0] & 0x02) == 0)
			strcpy (net->name, "eth%d");
		/* WLAN devices should always be named "wlan%d" */
		if ((dev->driver_info->flags & FLAG_WLAN) != 0)
			strcpy(net->name, "wlan%d");
		/* WWAN devices should always be named "wwan%d" */
		if ((dev->driver_info->flags & FLAG_WWAN) != 0)
			strcpy(net->name, "wwan%d");

		/* maybe the remote can't receive an Ethernet MTU */
		if (net->mtu > (dev->hard_mtu - net->hard_header_len))
			net->mtu = dev->hard_mtu - net->hard_header_len;
	} else if (!info->in || !info->out)
		status = usbnet_get_endpoints (dev, udev);
	else {
		dev->in = usb_rcvbulkpipe (xdev, info->in);
		dev->out = usb_sndbulkpipe (xdev, info->out);
		if (!(info->flags & FLAG_NO_SETINT))
			status = usb_set_interface (xdev,
				interface->desc.bInterfaceNumber,
				interface->desc.bAlternateSetting);
		else
			status = 0;

	}
	if (status >= 0 && dev->status)
		status = init_status (dev, udev);
	if (status < 0)
		goto out3;

	if (!dev->rx_urb_size)
		dev->rx_urb_size = dev->hard_mtu;
	dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1);

	SET_NETDEV_DEV(net, &udev->dev);

	if ((dev->driver_info->flags & FLAG_WLAN) != 0)
		SET_NETDEV_DEVTYPE(net, &wlan_type);
	if ((dev->driver_info->flags & FLAG_WWAN) != 0)
		SET_NETDEV_DEVTYPE(net, &wwan_type);

	status = register_netdev (net);
	if (status)
		goto out3;
	netif_info(dev, probe, dev->net,
		   "register '%s' at usb-%s-%s, %s, %pM\n",
		   udev->dev.driver->name,
		   xdev->bus->bus_name, xdev->devpath,
		   dev->driver_info->description,
		   net->dev_addr);

	// ok, it's ready to go.
	usb_set_intfdata (udev, dev);

	netif_device_attach (net);

	if (dev->driver_info->flags & FLAG_LINK_INTR)
		netif_carrier_off(net);

	return 0;

out3:
	if (info->unbind)
		info->unbind (dev, udev);
out1:
	free_netdev(net);
out:
	usb_put_dev(xdev);
	return status;
}
示例#12
0
/*
 * Probe a i2400m interface and register it
 *
 * @iface:   USB interface to link to
 * @id:      USB class/subclass/protocol id
 * @returns: 0 if ok, < 0 errno code on error.
 *
 * Alloc a net device, initialize the bus-specific details and then
 * calls the bus-generic initialization routine. That will register
 * the wimax and netdev devices, upload the firmware [using
 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
 * communication with the device and then will start to talk to it to
 * finnish setting it up.
 */
static
int i2400mu_probe(struct usb_interface *iface,
		  const struct usb_device_id *id)
{
	int result;
	struct net_device *net_dev;
	struct device *dev = &iface->dev;
	struct i2400m *i2400m;
	struct i2400mu *i2400mu;
	struct usb_device *usb_dev = interface_to_usbdev(iface);

	if (usb_dev->speed != USB_SPEED_HIGH)
		dev_err(dev, "device not connected as high speed\n");

	/* Allocate instance [calls i2400m_netdev_setup() on it]. */
	result = -ENOMEM;
	net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
			       i2400mu_netdev_setup);
	if (net_dev == NULL) {
		dev_err(dev, "no memory for network device instance\n");
		goto error_alloc_netdev;
	}
	SET_NETDEV_DEV(net_dev, dev);
	SET_NETDEV_DEVTYPE(net_dev, &i2400mu_type);
	i2400m = net_dev_to_i2400m(net_dev);
	i2400mu = container_of(i2400m, struct i2400mu, i2400m);
	i2400m->wimax_dev.net_dev = net_dev;
	i2400mu->usb_dev = usb_get_dev(usb_dev);
	i2400mu->usb_iface = iface;
	usb_set_intfdata(iface, i2400mu);

	i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
	/*
	 * Room required in the Tx queue for USB message to accommodate
	 * a smallest payload while allocating header space is 16 bytes.
	 * Adding this room  for the new tx message increases the
	 * possibilities of including any payload with size <= 16 bytes.
	 */
	i2400m->bus_tx_room_min = I2400MU_BLK_SIZE;
	i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
	i2400m->bus_setup = NULL;
	i2400m->bus_dev_start = i2400mu_bus_dev_start;
	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
	i2400m->bus_release = NULL;
	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
	i2400m->bus_reset = i2400mu_bus_reset;
	i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES;
	i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
	i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
	i2400m->bus_bm_mac_addr_impaired = 0;

	switch (id->idProduct) {
	case USB_DEVICE_ID_I6050:
	case USB_DEVICE_ID_I6050_2:
	case USB_DEVICE_ID_I6150:
	case USB_DEVICE_ID_I6150_2:
	case USB_DEVICE_ID_I6150_3:
	case USB_DEVICE_ID_I6250:
		i2400mu->i6050 = 1;
		break;
	default:
		break;
	}

	if (i2400mu->i6050) {
		i2400m->bus_fw_names = i2400mu_bus_fw_names_6050;
		i2400mu->endpoint_cfg.bulk_out = 0;
		i2400mu->endpoint_cfg.notification = 3;
		i2400mu->endpoint_cfg.reset_cold = 2;
		i2400mu->endpoint_cfg.bulk_in = 1;
	} else {
		i2400m->bus_fw_names = i2400mu_bus_fw_names_5x50;
		i2400mu->endpoint_cfg.bulk_out = 0;
		i2400mu->endpoint_cfg.notification = 1;
		i2400mu->endpoint_cfg.reset_cold = 2;
		i2400mu->endpoint_cfg.bulk_in = 3;
	}
#ifdef CONFIG_PM
	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
	device_init_wakeup(dev, 1);
	pm_runtime_set_autosuspend_delay(&usb_dev->dev, 15000);
	usb_enable_autosuspend(usb_dev);
#endif

	result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);
	if (result < 0) {
		dev_err(dev, "cannot setup device: %d\n", result);
		goto error_setup;
	}
	result = i2400mu_debugfs_add(i2400mu);
	if (result < 0) {
		dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result);
		goto error_debugfs_add;
	}
	return 0;

error_debugfs_add:
	i2400m_release(i2400m);
error_setup:
	usb_set_intfdata(iface, NULL);
	usb_put_dev(i2400mu->usb_dev);
	free_netdev(net_dev);
error_alloc_netdev:
	return result;
}
/**
 * @brief This function adds the card. it will probe the
 * card, allocate the wlan_priv and initialize the device. 
 *  
 *  @param card    A pointer to card
 *  @return        A pointer to wlan_private structure
 */
wlan_private *
wlan_add_card(void *card)
{
    struct net_device *dev = NULL;
    wlan_private *priv = NULL;

    ENTER();

    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
        goto exit_sem_err;

    /* Allocate an Ethernet device and register it */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
    if (!(dev = init_etherdev(dev, sizeof(wlan_private)))) {
#else
    if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
#endif
        PRINTM(MSG, "Init ethernet device failed!\n");
        goto exit_add_err;
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
    /* Allocate device name */
    if (dev_alloc_name(dev, "mlan%d") < 0) {
        PRINTM(ERROR, "Could not allocate device name!\n");
        goto err_kmalloc;
    }
#endif

    priv = (wlan_private *) netdev_priv(dev);

    /* allocate buffer for wlan_adapter */
    if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
        PRINTM(MSG, "Allocate buffer for wlan_adapter failed!\n");
        goto err_kmalloc;
    }

    /* init wlan_adapter */
    memset(priv->adapter, 0, sizeof(wlan_adapter));

    priv->wlan_dev.netdev = dev;
    priv->wlan_dev.card = card;
    ((struct sdio_mmc_card *) card)->priv = priv;
    wlanpriv = priv; //XXX FB global var a virer ?

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    SET_MODULE_OWNER(dev);
#endif

    /* Setup the OS Interface to our functions */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
    dev->open = wlan_open;
    dev->hard_start_xmit = wlan_hard_start_xmit;
    dev->stop = wlan_close;
    dev->do_ioctl = wlan_do_ioctl;
    dev->set_mac_address = wlan_set_mac_address;
    dev->set_multicast_list = wlan_set_multicast_list;
    dev->tx_timeout = wlan_tx_timeout;
    dev->get_stats = wlan_get_stats;
#else
    dev->netdev_ops = &wlan_netdev_ops;
#endif
    dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
    dev->hard_header_len += sizeof(TxPD);
    dev->hard_header_len += SDIO_HEADER_LEN;
    dev->hard_header_len += HEADER_ALIGNMENT;

#ifdef  WIRELESS_EXT
#if WIRELESS_EXT < 21
    dev->get_wireless_stats = wlan_get_wireless_stats;
#endif
    dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
    dev->features |= NETIF_F_DYNALLOC;
#endif
    dev->flags |= IFF_BROADCAST | IFF_MULTICAST;

    /* init SW */
    if (wlan_init_sw(priv)) {
        PRINTM(FATAL, "Software Init Failed\n");
        goto err_kmalloc;
    }

    PRINTM(INFO, "Starting kthread...\n");
    priv->MainThread.priv = priv;
    wlan_create_thread(wlan_service_main_thread,
                       &priv->MainThread, "wlan_main_service");

    ConfigureThreadPriority();

#ifdef REASSOCIATION
    priv->ReassocThread.priv = priv;
    wlan_create_thread(wlan_reassociation_thread,
                       &priv->ReassocThread, "wlan_reassoc_service");
#endif /* REASSOCIATION */

    while ((priv->MainThread.pid == 0)
#ifdef REASSOCIATION
           || (priv->ReassocThread.pid == 0)
#endif
        ) {
        os_sched_timeout(2);
    }

    /* 
     * Register the device. Fill up the private data structure with
     * relevant information from the card and request for the required
     * IRQ. 
     */

    if (sbi_register_dev(priv) < 0) {
        PRINTM(FATAL, "Failed to register wlan device!\n");
        goto err_registerdev;
    }

    SET_NETDEV_DEV(dev, priv->hotplug_device);

    /* init FW and HW */
    if (wlan_init_fw(priv)) {
        PRINTM(FATAL, "Firmware Init Failed\n");
        goto err_init_fw;
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    SET_NETDEV_DEVTYPE(dev, &wlan_type);
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    if (register_netdev(dev)) {
        printk(KERN_ERR "Cannot register network device!\n");
        goto err_init_fw;
    }
#endif
    os_carrier_off(priv);
    os_stop_queue(priv);

    PRINTM(INFO, "%s: WLAN 802.11 Adapter revision 0x%02X\n",
           dev->name, priv->adapter->chip_rev);

#ifdef CONFIG_PROC_FS
    wlan_proc_entry(priv, dev);
#ifdef PROC_DEBUG
    wlan_debug_entry(priv, dev);
#endif
#endif /* CONFIG_PROC_FS */

    OS_REL_SEMAPHORE(&AddRemoveCardSem);
    LEAVE();
    return priv;

  err_init_fw:
    sbi_unregister_dev(priv);

  err_registerdev:
    priv->adapter->SurpriseRemoved = TRUE;
    if (priv->MainThread.pid) {
        /* Stop the thread servicing the interrupts */
        wake_up_interruptible(&priv->MainThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->MainThread);
#endif
    }
#ifdef REASSOCIATION
    if (priv->ReassocThread.pid) {
        wake_up_interruptible(&priv->ReassocThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->ReassocThread);
#endif
    }
#endif /* REASSOCIATION */

    /* waiting for main thread quit */
    while (priv->MainThread.pid
#ifdef REASSOCIATION
           || priv->ReassocThread.pid
#endif
        ) {
        os_sched_timeout(2);
    }
  err_kmalloc:
    if (dev->reg_state == NETREG_REGISTERED)
        unregister_netdev(dev);
    wlan_free_adapter(priv);
    priv->wlan_dev.netdev = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    free_netdev(dev);
#endif
    ((struct sdio_mmc_card *) card)->priv = NULL;
    wlanpriv = NULL;

  exit_add_err:
    OS_REL_SEMAPHORE(&AddRemoveCardSem);
  exit_sem_err:
    LEAVE();
    return NULL;
}

/** 
 *  @brief This function removes the card.
 *  
 *  @param card    A pointer to card
 *  @return        WLAN_STATUS_SUCCESS
 */
int
wlan_remove_card(void *card)
{
    wlan_private *priv = ((struct sdio_mmc_card *) card)->priv;
    wlan_adapter *Adapter = NULL;
    struct net_device *dev;
    union iwreq_data wrqu;

    ENTER();

    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
        goto exit_sem_err;

    if (!priv || !(Adapter = priv->adapter))
        goto exit_remove;

    Adapter->SurpriseRemoved = TRUE;

#ifdef REASSOCIATION
    if (Adapter->ReassocTimerIsSet == TRUE) {
        wlan_cancel_timer(&Adapter->MrvDrvTimer);
        Adapter->ReassocTimerIsSet = FALSE;
    }
#endif

    if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
        Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
        memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
        wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
        wlan_clean_txrx(priv);
    }

    /* Release all pending commands */
    wlan_clear_pending_cmd(priv);

    dev = priv->wlan_dev.netdev;
    /* Last reference is our one */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
    PRINTM(INFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
#else
    PRINTM(INFO, "refcnt = %d\n", netdev_refcnt_read(dev));
#endif

    PRINTM(INFO, "netdev_finish_unregister: %s\n", dev->name);
    if (dev->reg_state == NETREG_REGISTERED)
        unregister_netdev(dev);
    PRINTM(INFO, "Unregister finish\n");

    if (priv->MainThread.pid) {
        /* Stop the thread servicing the interrupts */
        wake_up_interruptible(&priv->MainThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->MainThread);
#endif
    }
#ifdef REASSOCIATION
    if (priv->ReassocThread.pid) {
        wake_up_interruptible(&priv->ReassocThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->ReassocThread);
#endif
    }
#endif /* REASSOCIATION */

    /* waiting for thread quit */
    while (priv->MainThread.pid
#ifdef REASSOCIATION
           || priv->ReassocThread.pid
#endif
        ) {
        os_sched_timeout(1);
    }

    wake_up_interruptible(&Adapter->HS_wait_q);

    if (Adapter->IsDeepSleep == TRUE) {
        Adapter->IsDeepSleep = FALSE;
        wake_up_interruptible(&Adapter->ds_awake_q);
    }

#ifdef CONFIG_PROC_FS
#ifdef PROC_DEBUG
    wlan_debug_remove(priv);
#endif
    wlan_proc_remove(priv);
#endif

    PRINTM(INFO, "unregister device\n");
    sbi_unregister_dev(priv);

    PRINTM(INFO, "Free Adapter\n");
    wlan_free_adapter(priv);
    priv->wlan_dev.netdev = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    free_netdev(dev);
#endif
    wlanpriv = NULL;

  exit_remove:
    OS_REL_SEMAPHORE(&AddRemoveCardSem);

  exit_sem_err:
    LEAVE();
    return WLAN_STATUS_SUCCESS;
}
示例#14
0
/**
 * gether_setup_name - initialize one ethernet-over-usb link
 * @g: gadget to associated with these links
 * @ethaddr: NULL, or a buffer in which the ethernet address of the
 *	host side of the link is recorded
 * @netname: name for network device (for example, "usb")
 * Context: may sleep
 *
 * This sets up the single network link that may be exported by a
 * gadget driver using this framework.  The link layer addresses are
 * set up using module parameters.
 *
 * Returns negative errno, or zero on success
 */
int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
		const char *netname)
{
	struct eth_dev		*dev;
	struct net_device	*net;
	int			status;

	if (the_dev)
		return -EBUSY;

	net = alloc_etherdev(sizeof *dev);
	if (!net)
		return -ENOMEM;

	dev = netdev_priv(net);
	spin_lock_init(&dev->lock);
	spin_lock_init(&dev->req_lock);
	INIT_WORK(&dev->work, eth_work);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->rx_reqs);
	//init_waitqueue_head(&dev->usb_tx_buf_wq);

	skb_queue_head_init(&dev->rx_frames);

	/* network device setup */
	dev->net = net;
	snprintf(net->name, sizeof(net->name), "%s%%d", netname);

	if (get_ether_addr(dev_addr, net->dev_addr))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "self");
	if (get_ether_addr(host_addr, dev->host_mac))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "host");

	if (ethaddr)
		memcpy(ethaddr, dev->host_mac, ETH_ALEN);

	net->netdev_ops = &eth_netdev_ops;

	SET_ETHTOOL_OPS(net, &ops);

	dev->gadget = g;
	SET_NETDEV_DEV(net, &g->dev);
	SET_NETDEV_DEVTYPE(net, &gadget_type);

	status = register_netdev(net);
	if (status < 0) {
		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
		free_netdev(net);
	} else {
		INFO(dev, "MAC %pM\n", net->dev_addr);
		INFO(dev, "HOST MAC %pM\n", dev->host_mac);

		dev->usb_tx_buf_flag = 0;
		dev->usb_tx_buf = kzalloc(MAX_USB_TX_BUF_SIZE, GFP_ATOMIC);
		if (dev->usb_tx_buf != NULL)
			printk("%s: kzalloc dev->usb_tx_buf = %p.\n", __FUNCTION__, dev->usb_tx_buf);
		else
			printk("%s: kzalloc failed.\n", __FUNCTION__);
		the_dev = dev;

		/* two kinds of host-initiated state changes:
		 *  - iff DATA transfer is active, carrier is "on"
		 *  - tx queueing enabled if open *and* carrier is "on"
		 */
		netif_carrier_off(net);
	}

	return status;
}
示例#15
0
int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
                      const char *netname)
{
    struct eth_dev		*dev;
    struct net_device	*net;
    int			status;

    if (the_dev) {
        memcpy(ethaddr, the_dev->host_mac, ETH_ALEN);
        return 0;
    }

    net = alloc_etherdev(sizeof *dev);
    if (!net)
        return -ENOMEM;

    dev = netdev_priv(net);
    spin_lock_init(&dev->lock);
    spin_lock_init(&dev->req_lock);
    INIT_WORK(&dev->work, eth_work);
    INIT_WORK(&dev->rx_work, process_rx_w);
    INIT_LIST_HEAD(&dev->tx_reqs);
    INIT_LIST_HEAD(&dev->rx_reqs);

    skb_queue_head_init(&dev->rx_frames);


    dev->net = net;
    snprintf(net->name, sizeof(net->name), "%s%%d", netname);

    if (get_ether_addr(dev_addr, net->dev_addr))
        dev_warn(&g->dev,
                 "using random %s ethernet address\n", "self");
    if (get_ether_addr(host_addr, dev->host_mac))
        dev_warn(&g->dev,
                 "using random %s ethernet address\n", "host");

    if (ethaddr)
        memcpy(ethaddr, dev->host_mac, ETH_ALEN);

    net->netdev_ops = &eth_netdev_ops;

    SET_ETHTOOL_OPS(net, &ops);

    dev->gadget = g;
    SET_NETDEV_DEV(net, &g->dev);
    SET_NETDEV_DEVTYPE(net, &gadget_type);

    status = register_netdev(net);
    if (status < 0) {
        dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
        free_netdev(net);
    } else {
        INFO(dev, "MAC %pM\n", net->dev_addr);
        INFO(dev, "HOST MAC %pM\n", dev->host_mac);

        the_dev = dev;

        netif_carrier_off(net);
    }

    return status;
}
示例#16
0
/**
 * gether_setup_name - initialize one ethernet-over-usb link
 * @g: gadget to associated with these links
 * @ethaddr: NULL, or a buffer in which the ethernet address of the
 *	host side of the link is recorded
 * @netname: name for network device (for example, "usb")
 * Context: may sleep
 *
 * This sets up the single network link that may be exported by a
 * gadget driver using this framework.  The link layer addresses are
 * set up using module parameters.
 *
 * Returns negative errno, or zero on success
 */
int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
		const char *netname)
{
	struct eth_dev		*dev;
	struct net_device	*net;
	int			status;

	if (the_dev)
		return -EBUSY;

	net = alloc_etherdev(sizeof *dev);
	if (!net)
		return -ENOMEM;

	dev = netdev_priv(net);
	spin_lock_init(&dev->lock);
	spin_lock_init(&dev->req_lock);
	INIT_WORK(&dev->work, eth_work);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->rx_reqs);

	skb_queue_head_init(&dev->rx_frames);

	/* network device setup */
	dev->net = net;
	snprintf(net->name, sizeof(net->name), "%s%%d", netname);

	if (get_ether_addr(dev_addr, net->dev_addr))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "self");

#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE
	memcpy(dev->host_mac, ethaddr, ETH_ALEN);
	printk(KERN_DEBUG "usb: set unique host mac\n");
#else
	if (get_ether_addr(host_addr, dev->host_mac))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "host");

	if (ethaddr)
		memcpy(ethaddr, dev->host_mac, ETH_ALEN);
#endif

	net->netdev_ops = &eth_netdev_ops;

	SET_ETHTOOL_OPS(net, &ops);

	dev->gadget = g;
	SET_NETDEV_DEV(net, &g->dev);
	SET_NETDEV_DEVTYPE(net, &gadget_type);

	status = register_netdev(net);
	if (status < 0) {
		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
		free_netdev(net);
	} else {
		the_dev = dev;

		/* two kinds of host-initiated state changes:
		 *  - iff DATA transfer is active, carrier is "on"
		 *  - tx queueing enabled if open *and* carrier is "on"
		 */
		netif_carrier_off(net);
	}

	return status;
}
示例#17
0
static int ipheth_probe(struct usb_interface *intf,
			const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(intf);
	struct usb_host_interface *hintf;
	struct usb_endpoint_descriptor *endp;
	struct ipheth_device *dev;
	struct net_device *netdev;
	int i;
	int retval;

	netdev = alloc_etherdev(sizeof(struct ipheth_device));
	if (!netdev)
		return -ENOMEM;

	netdev->netdev_ops = &ipheth_netdev_ops;
	netdev->watchdog_timeo = IPHETH_TX_TIMEOUT;
	strcpy(netdev->name, "wwan%d");

	dev = netdev_priv(netdev);
	dev->udev = udev;
	dev->net = netdev;
	dev->intf = intf;

	/* Set up endpoints */
	hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM);
	if (hintf == NULL) {
		retval = -ENODEV;
		err("Unable to find alternate settings interface");
		goto err_endpoints;
	}

	for (i = 0; i < hintf->desc.bNumEndpoints; i++) {
		endp = &hintf->endpoint[i].desc;
		if (usb_endpoint_is_bulk_in(endp))
			dev->bulk_in = endp->bEndpointAddress;
		else if (usb_endpoint_is_bulk_out(endp))
			dev->bulk_out = endp->bEndpointAddress;
	}
	if (!(dev->bulk_in && dev->bulk_out)) {
		retval = -ENODEV;
		err("Unable to find endpoints");
		goto err_endpoints;
	}

	dev->ctrl_buf = kmalloc(IPHETH_CTRL_BUF_SIZE, GFP_KERNEL);
	if (dev->ctrl_buf == NULL) {
		retval = -ENOMEM;
		goto err_alloc_ctrl_buf;
	}

	retval = ipheth_get_macaddr(dev);
	if (retval)
		goto err_get_macaddr;

	INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work);

	retval = ipheth_alloc_urbs(dev);
	if (retval) {
		err("error allocating urbs: %d", retval);
		goto err_alloc_urbs;
	}

	usb_set_intfdata(intf, dev);

	SET_NETDEV_DEV(netdev, &intf->dev);
	SET_ETHTOOL_OPS(netdev, &ops);
	SET_NETDEV_DEVTYPE(netdev, &ipheth_type);

	retval = register_netdev(netdev);
	if (retval) {
		err("error registering netdev: %d", retval);
		retval = -EIO;
		goto err_register_netdev;
	}

	dev_info(&intf->dev, "Apple iPhone USB Ethernet device attached\n");
	return 0;

err_register_netdev:
	ipheth_free_urbs(dev);
err_alloc_urbs:
err_get_macaddr:
err_alloc_ctrl_buf:
	kfree(dev->ctrl_buf);
err_endpoints:
	free_netdev(netdev);
	return retval;
}
/**
 * gether_setup - initialize one ethernet-over-usb link
 * @g: gadget to associated with these links
 * @ethaddr: NULL, or a buffer in which the ethernet address of the
 *	host side of the link is recorded
 * Context: may sleep
 *
 * This sets up the single network link that may be exported by a
 * gadget driver using this framework.  The link layer addresses are
 * set up using module parameters.
 *
 * Returns negative errno, or zero on success
 */
int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
{
	struct eth_dev		*dev;
	struct net_device	*net;
	int			status;
	int  			gpio_171, gpio_172, val;

	if (the_dev)
		return -EBUSY;

	net = alloc_etherdev(sizeof *dev);
	if (!net)
		return -ENOMEM;

	dev = netdev_priv(net);
	spin_lock_init(&dev->lock);
	spin_lock_init(&dev->req_lock);
	INIT_WORK(&dev->work, eth_work);
	INIT_LIST_HEAD(&dev->tx_reqs);
	INIT_LIST_HEAD(&dev->rx_reqs);

	skb_queue_head_init(&dev->rx_frames);

	/* network device setup */
	dev->net = net;
	strcpy(net->name, "usb%d");

	if (get_ether_addr(dev_addr, net->dev_addr)){
		dev_warn(&g->dev,
			"using %s ethernet address\n", "Quanta defined");
//			"using random %s ethernet address\n", "self");

		net->dev_addr[0] = 0x00;
		net->dev_addr[1] = 0x02;
		net->dev_addr[2] = 0x00;		
		net->dev_addr[3] = 0x00;
		net->dev_addr[4] = 0x00;
		
		gpio_171 = gpio_get_value(171);
		gpio_172 = gpio_get_value(172);
		
		//gpio_171 = 1;
		//gpio_172 = 1;
		
		val = (gpio_171 << 1) + gpio_172;
		 	
		printk("< Quanta_diagnostic >  gpio_171 = %d  gpio_172 = %d  val = %d\n", gpio_171, gpio_172, val );
		
		switch (val)
		{
			case 0:
				net->dev_addr[5] = 0x01;
				break;
			case 1:
				net->dev_addr[5] = 0x03;
				break;	
			case 2:
				net->dev_addr[5] = 0x07;	
				break;
			case 3:
				net->dev_addr[5] = 0x09;
				break;
			default:
				printk("default\n");
				break;

				//random_ether_addr(dev_addr);
		}	
		printk("< Quanta Diagnostic >  set dev_addr done !\n");

	}

	if (get_ether_addr(host_addr, dev->host_mac))
		dev_warn(&g->dev,
			"using random %s ethernet address\n", "host");

	if (ethaddr)
		memcpy(ethaddr, dev->host_mac, ETH_ALEN);

	net->netdev_ops = &eth_netdev_ops;

	SET_ETHTOOL_OPS(net, &ops);

	/* two kinds of host-initiated state changes:
	 *  - iff DATA transfer is active, carrier is "on"
	 *  - tx queueing enabled if open *and* carrier is "on"
	 */
	netif_stop_queue(net);
	netif_carrier_off(net);

	dev->gadget = g;
	SET_NETDEV_DEV(net, &g->dev);
	SET_NETDEV_DEVTYPE(net, &gadget_type);

	status = register_netdev(net);
	if (status < 0) {
		dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
		free_netdev(net);
	} else {
		INFO(dev, "MAC %pM\n", net->dev_addr);
		INFO(dev, "HOST MAC %pM\n", dev->host_mac);

		the_dev = dev;
	}

	return status;
}
示例#19
0
struct net_device *
islpci_setup(struct pci_dev *pdev)
{
	islpci_private *priv;
	struct net_device *ndev = alloc_etherdev(sizeof (islpci_private));

	if (!ndev)
		return ndev;

	pci_set_drvdata(pdev, ndev);
	SET_NETDEV_DEV(ndev, &pdev->dev);
	SET_NETDEV_DEVTYPE(ndev, &wlan_type);

	/* setup the structure members */
	ndev->base_addr = pci_resource_start(pdev, 0);
	ndev->irq = pdev->irq;

	/* initialize the function pointers */
	ndev->netdev_ops = &islpci_netdev_ops;
	ndev->wireless_handlers = &prism54_handler_def;
	ndev->ethtool_ops = &islpci_ethtool_ops;

	/* ndev->set_multicast_list = &islpci_set_multicast_list; */
	ndev->addr_len = ETH_ALEN;
	/* Get a non-zero dummy MAC address for nameif. Jean II */
	memcpy(ndev->dev_addr, dummy_mac, 6);

	ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT;

	/* allocate a private device structure to the network device  */
	priv = netdev_priv(ndev);
	priv->ndev = ndev;
	priv->pdev = pdev;
	priv->monitor_type = ARPHRD_IEEE80211;
	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?
		priv->monitor_type : ARPHRD_ETHER;

	/* Add pointers to enable iwspy support. */
	priv->wireless_data.spy_data = &priv->spy_data;
	ndev->wireless_data = &priv->wireless_data;

	/* save the start and end address of the PCI memory area */
	ndev->mem_start = (unsigned long) priv->device_base;
	ndev->mem_end = ndev->mem_start + ISL38XX_PCI_MEM_SIZE;

#if VERBOSE > SHOW_ERROR_MESSAGES
	DEBUG(SHOW_TRACING, "PCI Memory remapped to 0x%p\n", priv->device_base);
#endif

	init_waitqueue_head(&priv->reset_done);

	/* init the queue read locks, process wait counter */
	mutex_init(&priv->mgmt_lock);
	priv->mgmt_received = NULL;
	init_waitqueue_head(&priv->mgmt_wqueue);
	mutex_init(&priv->stats_lock);
	spin_lock_init(&priv->slock);

	/* init state machine with off#1 state */
	priv->state = PRV_STATE_OFF;
	priv->state_off = 1;

	/* initialize workqueue's */
	INIT_WORK(&priv->stats_work, prism54_update_stats);
	priv->stats_timestamp = 0;

	INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake);
	priv->reset_task_pending = 0;

	/* allocate various memory areas */
	if (islpci_alloc_memory(priv))
		goto do_free_netdev;

	/* select the firmware file depending on the device id */
	switch (pdev->device) {
	case 0x3877:
		strcpy(priv->firmware, ISL3877_IMAGE_FILE);
		break;

	case 0x3886:
		strcpy(priv->firmware, ISL3886_IMAGE_FILE);
		break;

	default:
		strcpy(priv->firmware, ISL3890_IMAGE_FILE);
		break;
	}

	if (register_netdev(ndev)) {
		DEBUG(SHOW_ERROR_MESSAGES,
		      "ERROR: register_netdev() failed\n");
		goto do_islpci_free_memory;
	}

	return ndev;

      do_islpci_free_memory:
	islpci_free_memory(priv);
      do_free_netdev:
	pci_set_drvdata(pdev, NULL);
	free_netdev(ndev);
	priv = NULL;
	return NULL;
}
示例#20
0
/*
 * Probe a i2400m interface and register it
 *
 * @iface:   USB interface to link to
 * @id:      USB class/subclass/protocol id
 * @returns: 0 if ok, < 0 errno code on error.
 *
 * Alloc a net device, initialize the bus-specific details and then
 * calls the bus-generic initialization routine. That will register
 * the wimax and netdev devices, upload the firmware [using
 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
 * communication with the device and then will start to talk to it to
 * finnish setting it up.
 */
static
int i2400mu_probe(struct usb_interface *iface,
		  const struct usb_device_id *id)
{
	int result;
	struct net_device *net_dev;
	struct device *dev = &iface->dev;
	struct i2400m *i2400m;
	struct i2400mu *i2400mu;
	struct usb_device *usb_dev = interface_to_usbdev(iface);

	if (usb_dev->speed != USB_SPEED_HIGH)
		dev_err(dev, "device not connected as high speed\n");

	/* Allocate instance [calls i2400m_netdev_setup() on it]. */
	result = -ENOMEM;
	net_dev = alloc_netdev(sizeof(*i2400mu), "wmx%d",
			       i2400mu_netdev_setup);
	if (net_dev == NULL) {
		dev_err(dev, "no memory for network device instance\n");
		goto error_alloc_netdev;
	}
	SET_NETDEV_DEV(net_dev, dev);
	SET_NETDEV_DEVTYPE(net_dev, &i2400mu_type);
	i2400m = net_dev_to_i2400m(net_dev);
	i2400mu = container_of(i2400m, struct i2400mu, i2400m);
	i2400m->wimax_dev.net_dev = net_dev;
	i2400mu->usb_dev = usb_get_dev(usb_dev);
	i2400mu->usb_iface = iface;
	usb_set_intfdata(iface, i2400mu);

	i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
	i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
	i2400m->bus_dev_start = i2400mu_bus_dev_start;
	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
	i2400m->bus_reset = i2400mu_bus_reset;
	i2400m->bus_bm_retries = I2400M_BOOT_RETRIES;
	i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send;
	i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack;
	i2400m->bus_fw_names = i2400mu_bus_fw_names;
	i2400m->bus_bm_mac_addr_impaired = 0;

#ifdef CONFIG_PM
	iface->needs_remote_wakeup = 1;		/* autosuspend (15s delay) */
	device_init_wakeup(dev, 1);
	usb_autopm_enable(i2400mu->usb_iface);
	usb_dev->autosuspend_delay = 15 * HZ;
	usb_dev->autosuspend_disabled = 0;
#endif

	result = i2400m_setup(i2400m, I2400M_BRI_MAC_REINIT);
	if (result < 0) {
		dev_err(dev, "cannot setup device: %d\n", result);
		goto error_setup;
	}
	result = i2400mu_debugfs_add(i2400mu);
	if (result < 0) {
		dev_err(dev, "Can't register i2400mu's debugfs: %d\n", result);
		goto error_debugfs_add;
	}
	return 0;

error_debugfs_add:
	i2400m_release(i2400m);
error_setup:
	usb_set_intfdata(iface, NULL);
	usb_put_dev(i2400mu->usb_dev);
	free_netdev(net_dev);
error_alloc_netdev:
	return result;
}
示例#21
0
/*
 * Probe a i2400m interface and register it
 *
 * @func:    SDIO function
 * @id:      SDIO device ID
 * @returns: 0 if ok, < 0 errno code on error.
 *
 * Alloc a net device, initialize the bus-specific details and then
 * calls the bus-generic initialization routine. That will register
 * the wimax and netdev devices, upload the firmware [using
 * _bus_bm_*()], call _bus_dev_start() to finalize the setup of the
 * communication with the device and then will start to talk to it to
 * finnish setting it up.
 *
 * Initialization is tricky; some instances of the hw are packed with
 * others in a way that requires a third driver that enables the WiMAX
 * function. In those cases, we can't enable the SDIO function and
 * we'll return with -ENODEV. When the driver that enables the WiMAX
 * function does its thing, it has to do a bus_rescan_devices() on the
 * SDIO bus so this driver is called again to enumerate the WiMAX
 * function.
 */
static
int i2400ms_probe(struct sdio_func *func,
		  const struct sdio_device_id *id)
{
	int result;
	struct net_device *net_dev;
	struct device *dev = &func->dev;
	struct i2400m *i2400m;
	struct i2400ms *i2400ms;

	/* Allocate instance [calls i2400m_netdev_setup() on it]. */
	result = -ENOMEM;
	net_dev = alloc_netdev(sizeof(*i2400ms), "wmx%d",
			       i2400ms_netdev_setup);
	if (net_dev == NULL) {
		dev_err(dev, "no memory for network device instance\n");
		goto error_alloc_netdev;
	}
	SET_NETDEV_DEV(net_dev, dev);
	SET_NETDEV_DEVTYPE(net_dev, &i2400ms_type);
	i2400m = net_dev_to_i2400m(net_dev);
	i2400ms = container_of(i2400m, struct i2400ms, i2400m);
	i2400m->wimax_dev.net_dev = net_dev;
	i2400ms->func = func;
	sdio_set_drvdata(func, i2400ms);

	i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
	/*
	 * Room required in the TX queue for SDIO message to accommodate
	 * a smallest payload while allocating header space is 224 bytes,
	 * which is the smallest message size(the block size 256 bytes)
	 * minus the smallest message header size(32 bytes).
	 */
	i2400m->bus_tx_room_min = I2400MS_BLK_SIZE - I2400M_PL_ALIGN * 2;
	i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
	i2400m->bus_setup = i2400ms_bus_setup;
	i2400m->bus_dev_start = i2400ms_bus_dev_start;
	i2400m->bus_dev_stop = NULL;
	i2400m->bus_release = i2400ms_bus_release;
	i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
	i2400m->bus_reset = i2400ms_bus_reset;
	/* The iwmc3200-wimax sometimes requires the driver to try
	 * hard when we paint it into a corner. */
	i2400m->bus_bm_retries = I2400M_SDIO_BOOT_RETRIES;
	i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send;
	i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack;
	i2400m->bus_fw_names = i2400ms_bus_fw_names;
	i2400m->bus_bm_mac_addr_impaired = 1;
	i2400m->bus_bm_pokes_table = &i2400ms_pokes[0];

	switch (func->device) {
	case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX:
	case SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX_2G5:
		i2400ms->iwmc3200 = 1;
		break;
	default:
		i2400ms->iwmc3200 = 0;
	}

	result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
	if (result < 0) {
		dev_err(dev, "cannot setup device: %d\n", result);
		goto error_setup;
	}

	result = i2400ms_debugfs_add(i2400ms);
	if (result < 0) {
		dev_err(dev, "cannot create SDIO debugfs: %d\n",
			result);
		goto error_debugfs_add;
	}
	return 0;

error_debugfs_add:
	i2400m_release(i2400m);
error_setup:
	sdio_set_drvdata(func, NULL);
	free_netdev(net_dev);
error_alloc_netdev:
	return result;
}