Example #1
0
/* Get packets from the host vring */
static int cfv_rx_poll(struct napi_struct *napi, int quota)
{
	struct cfv_info *cfv = container_of(napi, struct cfv_info, napi);
	int rxcnt = 0;
	int err = 0;
	void *buf;
	struct sk_buff *skb;
	struct vringh_kiov *riov = &cfv->ctx.riov;
	unsigned int skb_len;

	do {
		skb = NULL;

		/* Put the previous iovec back on the used ring and
		 * fetch a new iovec if we have processed all elements.
		 */
		if (riov->i == riov->used) {
			if (cfv->ctx.head != USHRT_MAX) {
				vringh_complete_kern(cfv->vr_rx,
						     cfv->ctx.head,
						     0);
				cfv->ctx.head = USHRT_MAX;
			}

			err = vringh_getdesc_kern(
				cfv->vr_rx,
				riov,
				NULL,
				&cfv->ctx.head,
				GFP_ATOMIC);

			if (err <= 0)
				goto exit;
		}

		buf = phys_to_virt((unsigned long) riov->iov[riov->i].iov_base);
		/* TODO: Add check on valid buffer address */

		skb = cfv_alloc_and_copy_skb(&err, cfv, buf,
					     riov->iov[riov->i].iov_len);
		if (unlikely(err))
			goto exit;

		/* Push received packet up the stack. */
		skb_len = skb->len;
		skb->protocol = htons(ETH_P_CAIF);
		skb_reset_mac_header(skb);
		skb->dev = cfv->ndev;
		err = netif_receive_skb(skb);
		if (unlikely(err)) {
			++cfv->ndev->stats.rx_dropped;
		} else {
			++cfv->ndev->stats.rx_packets;
			cfv->ndev->stats.rx_bytes += skb_len;
		}

		++riov->i;
		++rxcnt;
	} while (rxcnt < quota);

	++cfv->stats.rx_napi_resched;
	goto out;

exit:
	switch (err) {
	case 0:
		++cfv->stats.rx_napi_complete;

		/* Really out of patckets? (stolen from virtio_net)*/
		napi_complete(napi);
		if (unlikely(!vringh_notify_enable_kern(cfv->vr_rx)) &&
		    napi_schedule_prep(napi)) {
			vringh_notify_disable_kern(cfv->vr_rx);
			__napi_schedule(napi);
		}
		break;

	case -ENOMEM:
		++cfv->stats.rx_nomem;
		dev_kfree_skb(skb);
		/* Stop NAPI poll on OOM, we hope to be polled later */
		napi_complete(napi);
		vringh_notify_enable_kern(cfv->vr_rx);
		break;

	default:
		/* We're doomed, any modem fault is fatal */
		netdev_warn(cfv->ndev, "Bad ring, disable device\n");
		cfv->ndev->stats.rx_dropped = riov->used - riov->i;
		napi_complete(napi);
		vringh_notify_disable_kern(cfv->vr_rx);
		netif_carrier_off(cfv->ndev);
		break;
	}
out:
	if (rxcnt && vringh_need_notify_kern(cfv->vr_rx) > 0)
		vringh_notify(cfv->vr_rx);
	return rxcnt;
}
Example #2
0
/* setup netdev link state when PHY link status change and
 * update UMAC and RGMII block when link up
 */
void bcmgenet_mii_setup(struct net_device *dev)
{
	struct bcmgenet_priv *priv = netdev_priv(dev);
	struct phy_device *phydev = priv->phydev;
	u32 reg, cmd_bits = 0;
	bool status_changed = false;

	if (priv->old_link != phydev->link) {
		status_changed = true;
		priv->old_link = phydev->link;
	}

	if (phydev->link) {
		/* check speed/duplex/pause changes */
		if (priv->old_speed != phydev->speed) {
			status_changed = true;
			priv->old_speed = phydev->speed;
		}

		if (priv->old_duplex != phydev->duplex) {
			status_changed = true;
			priv->old_duplex = phydev->duplex;
		}

		if (priv->old_pause != phydev->pause) {
			status_changed = true;
			priv->old_pause = phydev->pause;
		}

		/* done if nothing has changed */
		if (!status_changed)
			return;

		/* speed */
		if (phydev->speed == SPEED_1000)
			cmd_bits = UMAC_SPEED_1000;
		else if (phydev->speed == SPEED_100)
			cmd_bits = UMAC_SPEED_100;
		else
			cmd_bits = UMAC_SPEED_10;
		cmd_bits <<= CMD_SPEED_SHIFT;

		/* duplex */
		if (phydev->duplex != DUPLEX_FULL)
			cmd_bits |= CMD_HD_EN;

		/* pause capability */
		if (!phydev->pause)
			cmd_bits |= CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;

		/*
		 * Program UMAC and RGMII block based on established
		 * link speed, duplex, and pause. The speed set in
		 * umac->cmd tell RGMII block which clock to use for
		 * transmit -- 25MHz(100Mbps) or 125MHz(1Gbps).
		 * Receive clock is provided by the PHY.
		 */
		reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
		reg &= ~OOB_DISABLE;
		reg |= RGMII_LINK;
		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);

		reg = bcmgenet_umac_readl(priv, UMAC_CMD);
		reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
			       CMD_HD_EN |
			       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
		reg |= cmd_bits;
		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
	} else {
		/* done if nothing has changed */
		if (!status_changed)
			return;

		/* needed for MoCA fixed PHY to reflect correct link status */
		netif_carrier_off(dev);
	}

	phy_print_status(phydev);
}
Example #3
0
/*
 * In Ad-Hoc mode, the IBSS is created if not found in scan list.
 * In both Ad-Hoc and infra mode, an deauthentication is performed
 * first.
 */
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
		      struct cfg80211_ssid *req_ssid)
{
	int ret;
	struct mwifiex_adapter *adapter = priv->adapter;
	struct mwifiex_bssdescriptor *bss_desc = NULL;

	priv->scan_block = false;

	if (bss) {
		mwifiex_process_country_ie(priv, bss);

		/* Allocate and fill new bss descriptor */
		bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
				   GFP_KERNEL);
		if (!bss_desc)
			return -ENOMEM;

		ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
		if (ret)
			goto done;
	}

	if (priv->bss_mode == NL80211_IFTYPE_STATION ||
	    priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
		u8 config_bands;

		ret = mwifiex_deauthenticate(priv, NULL);
		if (ret)
			goto done;

		if (!bss_desc)
			return -1;

		if (mwifiex_band_to_radio_type(bss_desc->bss_band) ==
						HostCmd_SCAN_RADIO_TYPE_BG)
			config_bands = BAND_B | BAND_G | BAND_GN | BAND_GAC;
		else
			config_bands = BAND_A | BAND_AN | BAND_AAC;

		if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands))
			adapter->config_bands = config_bands;

		ret = mwifiex_check_network_compatibility(priv, bss_desc);
		if (ret)
			goto done;

		if (mwifiex_11h_get_csa_closed_channel(priv) ==
							(u8)bss_desc->channel) {
			dev_err(adapter->dev,
				"Attempt to reconnect on csa closed chan(%d)\n",
				bss_desc->channel);
			goto done;
		}

		dev_dbg(adapter->dev, "info: SSID found in scan list ... "
				      "associating...\n");

		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
		if (netif_carrier_ok(priv->netdev))
			netif_carrier_off(priv->netdev);

		/* Clear any past association response stored for
		 * application retrieval */
		priv->assoc_rsp_size = 0;
		ret = mwifiex_associate(priv, bss_desc);

		/* If auth type is auto and association fails using open mode,
		 * try to connect using shared mode */
		if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
		    priv->sec_info.is_authtype_auto &&
		    priv->sec_info.wep_enabled) {
			priv->sec_info.authentication_mode =
						NL80211_AUTHTYPE_SHARED_KEY;
			ret = mwifiex_associate(priv, bss_desc);
		}

		if (bss)
			cfg80211_put_bss(priv->adapter->wiphy, bss);
	} else {
		/* Adhoc mode */
		/* If the requested SSID matches current SSID, return */
		if (bss_desc && bss_desc->ssid.ssid_len &&
		    (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
				       ssid, &bss_desc->ssid))) {
			kfree(bss_desc);
			return 0;
		}

		/* Exit Adhoc mode first */
		dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
		ret = mwifiex_deauthenticate(priv, NULL);
		if (ret)
			goto done;

		priv->adhoc_is_link_sensed = false;

		ret = mwifiex_check_network_compatibility(priv, bss_desc);

		mwifiex_stop_net_dev_queue(priv->netdev, adapter);
		if (netif_carrier_ok(priv->netdev))
			netif_carrier_off(priv->netdev);

		if (!ret) {
			dev_dbg(adapter->dev, "info: network found in scan"
							" list. Joining...\n");
			ret = mwifiex_adhoc_join(priv, bss_desc);
			if (bss)
				cfg80211_put_bss(priv->adapter->wiphy, bss);
		} else {
			dev_dbg(adapter->dev, "info: Network not found in "
				"the list, creating adhoc with ssid = %s\n",
				req_ssid->ssid);
			ret = mwifiex_adhoc_start(priv, req_ssid);
		}
	}

done:
	/* beacon_ie buffer was allocated in function
	 * mwifiex_fill_new_bss_desc(). Free it now.
	 */
	if (bss_desc)
		kfree(bss_desc->beacon_buf);
	kfree(bss_desc);
	return ret;
}
Example #4
0
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_HW_CSUM | NETIF_F_SG |
			   NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE |
			   NETIF_F_HIGHDMA | NETIF_F_SCTP_CRC |
			   NETIF_F_ALL_FCOE;

	dev->features |= dev->hw_features | NETIF_F_LLTX;
	dev->gso_max_size = real_dev->gso_max_size;
	dev->gso_max_segs = real_dev->gso_max_segs;
	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)) {
		ether_addr_copy(dev->dev_addr, real_dev->dev_addr);
		dev->addr_assign_type = NET_ADDR_STOLEN;
	}
	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;
}
Example #5
0
void ag71xx_link_adjust(struct ag71xx *ag)
{
	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
	u32 cfg2;
	u32 ifctl;
	u32 fifo5;
	u32 mii_speed;

	if (!ag->link) {
		netif_carrier_off(ag->dev);
		if (netif_msg_link(ag))
			printk(KERN_INFO "%s: link down\n", ag->dev->name);
		return;
	}

	cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2);
	cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX);
	cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0;

	ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL);
	ifctl &= ~(MAC_IFCTL_SPEED);

	fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5);
	fifo5 &= ~FIFO_CFG5_BM;

	switch (ag->speed) {
	case SPEED_1000:
		mii_speed =  MII_CTRL_SPEED_1000;
		cfg2 |= MAC_CFG2_IF_1000;
		fifo5 |= FIFO_CFG5_BM;
		break;
	case SPEED_100:
		mii_speed = MII_CTRL_SPEED_100;
		cfg2 |= MAC_CFG2_IF_10_100;
		ifctl |= MAC_IFCTL_SPEED;
		break;
	case SPEED_10:
		mii_speed = MII_CTRL_SPEED_10;
		cfg2 |= MAC_CFG2_IF_10_100;
		break;
	default:
		BUG();
		return;
	}

	if (pdata->is_ar91xx)
		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff);
	else if (pdata->is_ar724x)
		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3);
	else
		ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff);

	if (pdata->set_pll)
		pdata->set_pll(ag->speed);

	ag71xx_mii_ctrl_set_speed(ag, mii_speed);

	ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2);
	ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5);
	ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl);

	netif_carrier_on(ag->dev);
	if (netif_msg_link(ag))
		printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n",
			ag->dev->name,
			ag71xx_speed_str(ag),
			(DUPLEX_FULL == ag->duplex) ? "Full" : "Half");

	DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2));

	DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4),
		ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5));

	DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n",
		ag->dev->name,
		ag71xx_rr(ag, AG71XX_REG_MAC_CFG2),
		ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL),
		ag71xx_mii_ctrl_rr(ag));
}
Example #6
0
/* Incoming data */
static void zd1201_usbrx(struct urb *urb)
{
	struct zd1201 *zd = urb->context;
	int free = 0;
	unsigned char *data = urb->transfer_buffer;
	struct sk_buff *skb;
	unsigned char type;

	if (!zd)
		return;

	switch(urb->status) {
		case -EILSEQ:
		case -ENODEV:
		case -ETIME:
		case -ENOENT:
		case -EPIPE:
		case -EOVERFLOW:
		case -ESHUTDOWN:
			dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n",
			    zd->dev->name, urb->status);
			free = 1;
			goto exit;
	}
	
	if (urb->status != 0 || urb->actual_length == 0)
		goto resubmit;

	type = data[0];
	if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) {
		memcpy(zd->rxdata, data, urb->actual_length);
		zd->rxlen = urb->actual_length;
		zd->rxdatas = 1;
		wake_up(&zd->rxdataq);
	}
	/* Info frame */
	if (type == ZD1201_PACKET_INQUIRE) {
		int i = 0;
		unsigned short infotype, framelen, copylen;
		framelen = le16_to_cpu(*(__le16*)&data[4]);
		infotype = le16_to_cpu(*(__le16*)&data[6]);

		if (infotype == ZD1201_INF_LINKSTATUS) {
			short linkstatus;

			linkstatus = le16_to_cpu(*(__le16*)&data[8]);
			switch(linkstatus) {
				case 1:
					netif_carrier_on(zd->dev);
					break;
				case 2:
					netif_carrier_off(zd->dev);
					break;
				case 3:
					netif_carrier_off(zd->dev);
					break;
				case 4:
					netif_carrier_on(zd->dev);
					break;
				default:
					netif_carrier_off(zd->dev);
			}
			goto resubmit;
		}
		if (infotype == ZD1201_INF_ASSOCSTATUS) {
			short status = le16_to_cpu(*(__le16*)(data+8));
			int event;
			union iwreq_data wrqu;

			switch (status) {
				case ZD1201_ASSOCSTATUS_STAASSOC:
				case ZD1201_ASSOCSTATUS_REASSOC:
					event = IWEVREGISTERED;
					break;
				case ZD1201_ASSOCSTATUS_DISASSOC:
				case ZD1201_ASSOCSTATUS_ASSOCFAIL:
				case ZD1201_ASSOCSTATUS_AUTHFAIL:
				default:
					event = IWEVEXPIRED;
			}
			memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN);
			wrqu.addr.sa_family = ARPHRD_ETHER;

			/* Send event to user space */
			wireless_send_event(zd->dev, event, &wrqu, NULL);

			goto resubmit;
		}
		if (infotype == ZD1201_INF_AUTHREQ) {
			union iwreq_data wrqu;

			memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN);
			wrqu.addr.sa_family = ARPHRD_ETHER;
			/* There isn't a event that trully fits this request.
			   We assume that userspace will be smart enough to
			   see a new station being expired and sends back a
			   authstation ioctl to authorize it. */
			wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL);
			goto resubmit;
		}
		/* Other infotypes are handled outside this handler */
		zd->rxlen = 0;
		while (i < urb->actual_length) {
			copylen = le16_to_cpu(*(__le16*)&data[i+2]);
			/* Sanity check, sometimes we get junk */
			if (copylen+zd->rxlen > sizeof(zd->rxdata))
				break;
			memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen);
			zd->rxlen += copylen;
			i += 64;
		}
		if (i >= urb->actual_length) {
			zd->rxdatas = 1;
			wake_up(&zd->rxdataq);
		}
		goto  resubmit;
	}
	/* Actual data */
	if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) {
		int datalen = urb->actual_length-1;
		unsigned short len, fc, seq;
		struct hlist_node *node;

		len = ntohs(*(__be16 *)&data[datalen-2]);
		if (len>datalen)
			len=datalen;
		fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
		seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);

		if (zd->monitor) {
			if (datalen < 24)
				goto resubmit;
			if (!(skb = dev_alloc_skb(datalen+24)))
				goto resubmit;
			
			memcpy(skb_put(skb, 2), &data[datalen-16], 2);
			memcpy(skb_put(skb, 2), &data[datalen-2], 2);
			memcpy(skb_put(skb, 6), &data[datalen-14], 6);
			memcpy(skb_put(skb, 6), &data[datalen-22], 6);
			memcpy(skb_put(skb, 6), &data[datalen-8], 6);
			memcpy(skb_put(skb, 2), &data[datalen-24], 2);
			memcpy(skb_put(skb, len), data, len);
			skb->protocol = eth_type_trans(skb, zd->dev);
			zd->dev->stats.rx_packets++;
			zd->dev->stats.rx_bytes += skb->len;
			netif_rx(skb);
			goto resubmit;
		}
			
		if ((seq & IEEE80211_SCTL_FRAG) ||
		    (fc & IEEE80211_FCTL_MOREFRAGS)) {
			struct zd1201_frag *frag = NULL;
			char *ptr;

			if (datalen<14)
				goto resubmit;
			if ((seq & IEEE80211_SCTL_FRAG) == 0) {
				frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
				if (!frag)
					goto resubmit;
				skb = dev_alloc_skb(IEEE80211_MAX_DATA_LEN +14+2);
				if (!skb) {
					kfree(frag);
					goto resubmit;
				}
				frag->skb = skb;
				frag->seq = seq & IEEE80211_SCTL_SEQ;
				skb_reserve(skb, 2);
				memcpy(skb_put(skb, 12), &data[datalen-14], 12);
				memcpy(skb_put(skb, 2), &data[6], 2);
				memcpy(skb_put(skb, len), data+8, len);
				hlist_add_head(&frag->fnode, &zd->fraglist);
				goto resubmit;
			}
			hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
				if (frag->seq == (seq&IEEE80211_SCTL_SEQ))
					break;
			if (!frag)
				goto resubmit;
			skb = frag->skb;
			ptr = skb_put(skb, len);
			if (ptr)
				memcpy(ptr, data+8, len);
			if (fc & IEEE80211_FCTL_MOREFRAGS)
				goto resubmit;
			hlist_del_init(&frag->fnode);
			kfree(frag);
		} else {
			if (datalen<14)
Example #7
0
static int veth_newlink(struct net_device *dev,
			 struct nlattr *tb[], struct nlattr *data[])
{
	int err;
	struct net_device *peer;
	struct veth_priv *priv;
	char ifname[IFNAMSIZ];
	struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;

	/*
	 * create and register peer first
	 *
	 * struct ifinfomsg is at the head of VETH_INFO_PEER, but we
	 * skip it since no info from it is useful yet
	 */

	if (data != NULL && data[VETH_INFO_PEER] != NULL) {
		struct nlattr *nla_peer;

		nla_peer = data[VETH_INFO_PEER];
		err = nla_parse(peer_tb, IFLA_MAX,
				nla_data(nla_peer) + sizeof(struct ifinfomsg),
				nla_len(nla_peer) - sizeof(struct ifinfomsg),
				ifla_policy);
		if (err < 0)
			return err;

		err = veth_validate(peer_tb, NULL);
		if (err < 0)
			return err;

		tbp = peer_tb;
	} else
		tbp = tb;

	if (tbp[IFLA_IFNAME])
		nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
	else
		snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");

	peer = rtnl_create_link(dev_net(dev), ifname, &veth_link_ops, tbp);
	if (IS_ERR(peer))
		return PTR_ERR(peer);

	if (tbp[IFLA_ADDRESS] == NULL)
		random_ether_addr(peer->dev_addr);

	err = register_netdevice(peer);
	if (err < 0)
		goto err_register_peer;

	netif_carrier_off(peer);

	/*
	 * register dev last
	 *
	 * note, that since we've registered new device the dev's name
	 * should be re-allocated
	 */

	if (tb[IFLA_ADDRESS] == NULL)
		random_ether_addr(dev->dev_addr);

	if (tb[IFLA_IFNAME])
		nla_strlcpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);
	else
		snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d");

	if (strchr(dev->name, '%')) {
		err = dev_alloc_name(dev, dev->name);
		if (err < 0)
			goto err_alloc_name;
	}

	err = register_netdevice(dev);
	if (err < 0)
		goto err_register_dev;

	netif_carrier_off(dev);

	/*
	 * tie the deviced together
	 */

	priv = netdev_priv(dev);
	priv->peer = peer;

	priv = netdev_priv(peer);
	priv->peer = dev;
	return 0;

err_register_dev:
	/* nothing to do */
err_alloc_name:
	unregister_netdevice(peer);
	return err;

err_register_peer:
	free_netdev(peer);
	return err;
}
Example #8
0
netdev_tx_t mpodp_start_xmit(struct sk_buff *skb,
			     struct net_device *netdev)
{
	struct mpodp_if_priv *priv = netdev_priv(netdev);
	struct mpodp_tx *tx;
	struct dma_async_tx_descriptor *dma_txd;
	struct mpodp_cache_entry *entry;
	int ret;
	uint8_t fifo_mode;
	int16_t requested_engine;
	struct mpodp_pkt_hdr *hdr;
	uint32_t tx_autoloop_next;
	uint32_t tx_submitted, tx_next, tx_done;
	uint32_t tx_mppa_idx;
	int qidx;
	unsigned long flags = 0;
	struct mpodp_txq *txq;

	/* Fetch HW queue selected by the kernel */
	qidx = skb_get_queue_mapping(skb);
	txq = &priv->txqs[qidx];

	if (atomic_read(&priv->reset) == 1) {
		mpodp_clean_tx_unlocked(priv, txq, -1);
		goto addr_error;
	}

	tx_submitted = atomic_read(&txq->submitted);
	/* Compute txd id */
	tx_next = (tx_submitted + 1);
	if (tx_next == txq->size)
		tx_next = 0;

	/* MPPA H2C Entry to use */
	tx_mppa_idx = atomic_read(&txq->autoloop_cur);

	tx_done = atomic_read(&txq->done);
	if (tx_done != tx_submitted &&
	    ((txq->ring[tx_done].jiffies + msecs_to_jiffies(5) >= jiffies) ||
	     (tx_submitted < tx_done && tx_submitted + txq->size - tx_done >= TX_POLL_THRESHOLD) ||
	     (tx_submitted >= tx_done && tx_submitted - tx_done >= TX_POLL_THRESHOLD))) {
		mpodp_clean_tx_unlocked(priv, txq, -1);
	}

	/* Check if there are txd available */
	if (tx_next == atomic_read(&txq->done)) {
		/* Ring is full */
		if (netif_msg_tx_err(priv))
			netdev_err(netdev, "txq[%d]: ring full \n", txq->id);
		netif_tx_stop_queue(txq->txq);
		return NETDEV_TX_BUSY;
	}

	tx = &(txq->ring[tx_submitted]);
	entry = &(txq->cache[tx_mppa_idx]);

	/* take the time */
	mppa_pcie_time_get(priv->tx_time, &tx->time);

	/* configure channel */
	tx->dst_addr = entry->addr;

	/* Check the provided address */
	ret =
	    mppa_pcie_dma_check_addr(priv->pdata, tx->dst_addr, &fifo_mode,
				     &requested_engine);
	if (ret) {
		if (netif_msg_tx_err(priv))
			netdev_err(netdev, "txq[%d] tx[%d]: invalid send address %llx\n",
				   txq->id, tx_submitted, tx->dst_addr);
		goto addr_error;
	}
	if (!fifo_mode) {
		if (netif_msg_tx_err(priv))
			netdev_err(netdev, "txq[%d] tx[%d]: %llx is not a PCI2Noc addres\n",
				   txq->id, tx_submitted, tx->dst_addr);
		goto addr_error;
	}
	if (requested_engine >= MPODP_NOC_CHAN_COUNT) {
		if (netif_msg_tx_err(priv))
			netdev_err(netdev,
				   "txq[%d] tx[%d]: address %llx using NoC engine out of range (%d >= %d)\n",
				   txq->id, tx_submitted, tx->dst_addr,
				   requested_engine, MPODP_NOC_CHAN_COUNT);
		goto addr_error;
	}

	tx->chanidx = requested_engine;

	/* The packet needs a header to determine size,timestamp, etc.
	 * Add it */
	if (skb_headroom(skb) < sizeof(struct mpodp_pkt_hdr)) {
		struct sk_buff *skb_new;

		skb_new =
			skb_realloc_headroom(skb, sizeof(struct mpodp_pkt_hdr));
		if (!skb_new) {
			netdev->stats.tx_errors++;
			kfree_skb(skb);
			return NETDEV_TX_OK;
		}
		kfree_skb(skb);
		skb = skb_new;
	}

	hdr = (struct mpodp_pkt_hdr *)
		skb_push(skb, sizeof(struct mpodp_pkt_hdr));
	hdr->timestamp = priv->packet_id;
	hdr->info._.pkt_id = priv->packet_id;
	hdr->info.dword = 0ULL;
	hdr->info._.pkt_size = skb->len; /* Also count the header size */
	hdr->info._.pkt_id = priv->packet_id;
	priv->packet_id++;

	/* save skb to free it later */
	tx->skb = skb;
	tx->len = skb->len;

	/* prepare sg */
	if (map_skb(&priv->pdev->dev, skb, tx)){
		if (netif_msg_tx_err(priv))
			netdev_err(netdev, "tx %d: failed to map skb to dma\n",
				   tx_submitted);
		goto busy;
	}

	if (priv->n_txqs > MPODP_NOC_CHAN_COUNT)
		spin_lock_irqsave(&priv->tx_lock[requested_engine], flags);

	/* Prepare slave args */
	priv->tx_config[requested_engine].cfg.dst_addr = tx->dst_addr;
	priv->tx_config[requested_engine].requested_engine = requested_engine;
	/* FIFO mode, direction, latency were filled at setup */

	if (dmaengine_slave_config(priv->tx_chan[requested_engine],
				   &priv->tx_config[requested_engine].cfg)) {
		/* board has reset, wait for reset of netdev */
		netif_tx_stop_queue(txq->txq);
		netif_carrier_off(netdev);
		if (netif_msg_tx_err(priv))
			netdev_err(netdev, "txq[%d] tx[%d]: cannot configure channel\n",
				   txq->id, tx_submitted);
		goto busy;
	}

	/* get transfer descriptor */
	dma_txd =
	    dmaengine_prep_slave_sg(priv->tx_chan[requested_engine], tx->sg,
				    tx->sg_len, DMA_MEM_TO_DEV, 0);
	if (dma_txd == NULL) {
		/* dmaengine_prep_slave_sg failed, retry */
		if (netif_msg_tx_err(priv))
			netdev_err(netdev, "txq[%d] tx[%d]: cannot get dma descriptor\n",
				   txq->id, tx_submitted);
		goto busy;
	}
	if (netif_msg_tx_queued(priv))
		netdev_info(netdev,
			    "txq[%d] tx[%d]: transfer start (submitted: %d done: %d) len=%d, sg_len=%d\n",
			    txq->id, tx_submitted, tx_next, atomic_read(&txq->done),
			    tx->len, tx->sg_len);

	skb_orphan(skb);

	/* submit and issue descriptor */
	tx->jiffies = jiffies;
	tx->cookie = dmaengine_submit(dma_txd);
	dma_async_issue_pending(priv->tx_chan[requested_engine]);

	if (priv->n_txqs > MPODP_NOC_CHAN_COUNT)
		spin_unlock_irqrestore(&priv->tx_lock[requested_engine], flags);

	/* Count number of bytes on the fly for DQL */
	netdev_tx_sent_queue(txq->txq, skb->len);
	if (test_bit(__QUEUE_STATE_STACK_XOFF, &txq->txq->state)){
		/* We reached over the limit of DQL. Try to clean some
		 * tx so we are rescheduled right now */
		mpodp_clean_tx_unlocked(priv, txq, -1);
	}

	/* Increment tail pointer locally */
	atomic_set(&txq->submitted, tx_next);

	/* Update H2C entry offset */
	tx_autoloop_next = tx_mppa_idx + 1;
	if (tx_autoloop_next == txq->cached_head)
		tx_autoloop_next = 0;
	atomic_set(&txq->autoloop_cur, tx_autoloop_next);

	skb_tx_timestamp(skb);

	/* Check if there is room for another txd
	 * or stop the queue if there is not */
	tx_next = (tx_next + 1);
	if (tx_next == txq->size)
		tx_next = 0;

	if (tx_next == atomic_read(&txq->done)) {
		if (netif_msg_tx_queued(priv))
			netdev_info(netdev, "txq[%d]: ring full \n", txq->id);
		netif_tx_stop_queue(txq->txq);
	}

	return NETDEV_TX_OK;

      busy:
	unmap_skb(&priv->pdev->dev, skb, tx);
	return NETDEV_TX_BUSY;

 addr_error:
	netdev->stats.tx_dropped++;
	dev_kfree_skb(skb);
	/* We can't do anything, just stop the queue artificially */
	netif_tx_stop_queue(txq->txq);
	return NETDEV_TX_OK;
}
Example #9
0
/*
 * This function handles AP interface specific events generated by firmware.
 *
 * Event specific routines are called by this function based
 * upon the generated event cause.
 *
 *
 * Events supported for AP -
 *      - EVENT_UAP_STA_ASSOC
 *      - EVENT_UAP_STA_DEAUTH
 *      - EVENT_UAP_BSS_ACTIVE
 *      - EVENT_UAP_BSS_START
 *      - EVENT_UAP_BSS_IDLE
 *      - EVENT_UAP_MIC_COUNTERMEASURES:
 */
int mwifiex_process_uap_event(struct mwifiex_private *priv)
{
	struct mwifiex_adapter *adapter = priv->adapter;
	int len, i;
	u32 eventcause = adapter->event_cause;
	struct station_info sinfo;
	struct mwifiex_assoc_event *event;
	struct mwifiex_sta_node *node;
	u8 *deauth_mac;
	struct host_cmd_ds_11n_batimeout *ba_timeout;
	u16 ctrl;

	switch (eventcause) {
	case EVENT_UAP_STA_ASSOC:
		memset(&sinfo, 0, sizeof(sinfo));
		event = (struct mwifiex_assoc_event *)
			(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
		if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
			len = -1;

			if (ieee80211_is_assoc_req(event->frame_control))
				len = 0;
			else if (ieee80211_is_reassoc_req(event->frame_control))
				/* There will be ETH_ALEN bytes of
				 * current_ap_addr before the re-assoc ies.
				 */
				len = ETH_ALEN;

			if (len != -1) {
				sinfo.assoc_req_ies = &event->data[len];
				len = (u8 *)sinfo.assoc_req_ies -
				      (u8 *)&event->frame_control;
				sinfo.assoc_req_ies_len =
					le16_to_cpu(event->len) - (u16)len;
			}
		}
		cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
				 GFP_KERNEL);

		node = mwifiex_add_sta_entry(priv, event->sta_addr);
		if (!node) {
			mwifiex_dbg(adapter, ERROR,
				    "could not create station entry!\n");
			return -1;
		}

		if (!priv->ap_11n_enabled)
			break;

		mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies,
				       sinfo.assoc_req_ies_len, node);

		for (i = 0; i < MAX_NUM_TID; i++) {
			if (node->is_11n_enabled)
				node->ampdu_sta[i] =
					      priv->aggr_prio_tbl[i].ampdu_user;
			else
				node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
		}
		memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
		break;
	case EVENT_UAP_STA_DEAUTH:
		deauth_mac = adapter->event_body +
			     MWIFIEX_UAP_EVENT_EXTRA_HEADER;
		cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);

		if (priv->ap_11n_enabled) {
			mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
			mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
		}
		mwifiex_wmm_del_peer_ra_list(priv, deauth_mac);
		mwifiex_del_sta_entry(priv, deauth_mac);
		break;
	case EVENT_UAP_BSS_IDLE:
		priv->media_connected = false;
		priv->port_open = false;
		if (netif_carrier_ok(priv->netdev))
			netif_carrier_off(priv->netdev);
		mwifiex_stop_net_dev_queue(priv->netdev, adapter);

		mwifiex_clean_txrx(priv);
		mwifiex_del_all_sta_list(priv);
		break;
	case EVENT_UAP_BSS_ACTIVE:
		priv->media_connected = true;
		priv->port_open = true;
		if (!netif_carrier_ok(priv->netdev))
			netif_carrier_on(priv->netdev);
		mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
		break;
	case EVENT_UAP_BSS_START:
		mwifiex_dbg(adapter, EVENT,
			    "AP EVENT: event id: %#x\n", eventcause);
		priv->port_open = false;
		memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
		       ETH_ALEN);
		if (priv->hist_data)
			mwifiex_hist_data_reset(priv);
		mwifiex_check_uap_capabilties(priv, adapter->event_skb);
		break;
	case EVENT_UAP_MIC_COUNTERMEASURES:
		/* For future development */
		mwifiex_dbg(adapter, EVENT,
			    "AP EVENT: event id: %#x\n", eventcause);
		break;
	case EVENT_AMSDU_AGGR_CTRL:
		ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
		mwifiex_dbg(adapter, EVENT,
			    "event: AMSDU_AGGR_CTRL %d\n", ctrl);

		if (priv->media_connected) {
			adapter->tx_buf_size =
				min_t(u16, adapter->curr_tx_buf_size, ctrl);
			mwifiex_dbg(adapter, EVENT,
				    "event: tx_buf_size %d\n",
				    adapter->tx_buf_size);
		}
		break;
	case EVENT_ADDBA:
		mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n");
		if (priv->media_connected)
			mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
					 HostCmd_ACT_GEN_SET, 0,
					 adapter->event_body, false);
		break;
	case EVENT_DELBA:
		mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n");
		if (priv->media_connected)
			mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
		break;
	case EVENT_BA_STREAM_TIEMOUT:
		mwifiex_dbg(adapter, EVENT, "event:  BA Stream timeout\n");
		if (priv->media_connected) {
			ba_timeout = (void *)adapter->event_body;
			mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
		}
		break;
	case EVENT_EXT_SCAN_REPORT:
		mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n");
		if (adapter->ext_scan)
			return mwifiex_handle_event_ext_scan_report(priv,
						adapter->event_skb->data);
		break;
	case EVENT_TX_STATUS_REPORT:
		mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
		mwifiex_parse_tx_status_event(priv, adapter->event_body);
		break;
	case EVENT_PS_SLEEP:
		mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n");

		adapter->ps_state = PS_STATE_PRE_SLEEP;

		mwifiex_check_ps_cond(adapter);
		break;

	case EVENT_PS_AWAKE:
		mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
		if (!adapter->pps_uapsd_mode &&
		    priv->media_connected && adapter->sleep_period.period) {
				adapter->pps_uapsd_mode = true;
				mwifiex_dbg(adapter, EVENT,
					    "event: PPS/UAPSD mode activated\n");
		}
		adapter->tx_lock_flag = false;
		if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) {
			if (mwifiex_check_last_packet_indication(priv)) {
				if (adapter->data_sent) {
					adapter->ps_state = PS_STATE_AWAKE;
					adapter->pm_wakeup_card_req = false;
					adapter->pm_wakeup_fw_try = false;
					break;
				}
				if (!mwifiex_send_null_packet
					(priv,
					 MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET |
					 MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET))
						adapter->ps_state =
							PS_STATE_SLEEP;
					return 0;
			}
		}
		adapter->ps_state = PS_STATE_AWAKE;
		adapter->pm_wakeup_card_req = false;
		adapter->pm_wakeup_fw_try = false;
		break;

	case EVENT_CHANNEL_REPORT_RDY:
		mwifiex_dbg(adapter, EVENT, "event: Channel Report\n");
		mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb);
		break;
	case EVENT_RADAR_DETECTED:
		mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
		mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
		break;
	case EVENT_BT_COEX_WLAN_PARA_CHANGE:
		dev_err(adapter->dev, "EVENT: BT coex wlan param update\n");
		mwifiex_bt_coex_wlan_param_update_event(priv,
							adapter->event_skb);
		break;
	case EVENT_TX_DATA_PAUSE:
		mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
		mwifiex_process_tx_pause_event(priv, adapter->event_skb);
		break;

	case EVENT_MULTI_CHAN_INFO:
		mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
		mwifiex_process_multi_chan_event(priv, adapter->event_skb);
		break;

	default:
		mwifiex_dbg(adapter, EVENT,
			    "event: unknown event id: %#x\n", eventcause);
		break;
	}

	return 0;
}
Example #10
0
/* Handle the 21143 uniquely: do autoselect with NWay, not the EEPROM list
   of available transceivers.  */
void t21142_timer(unsigned long data)
{
	struct net_device *dev = (struct net_device *)data;
	struct tulip_private *tp = netdev_priv(dev);
	void __iomem *ioaddr = tp->base_addr;
	int csr12 = ioread32(ioaddr + CSR12);
	int next_tick = 60*HZ;
	int new_csr6 = 0;

	if (tulip_debug > 2)
		printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n",
			   dev->name, csr12, medianame[dev->if_port]);
	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
		if (tulip_check_duplex(dev) < 0) {
			netif_carrier_off(dev);
			next_tick = 3*HZ;
		} else {
			netif_carrier_on(dev);
			next_tick = 60*HZ;
		}
	} else if (tp->nwayset) {
		/* Don't screw up a negotiated session! */
		if (tulip_debug > 1)
			printk(KERN_INFO"%s: Using NWay-set %s media, csr12 %8.8x.\n",
				   dev->name, medianame[dev->if_port], csr12);
	} else if (tp->medialock) {
			;
	} else if (dev->if_port == 3) {
		if (csr12 & 2) {	/* No 100mbps link beat, revert to 10mbps. */
			if (tulip_debug > 1)
				printk(KERN_INFO"%s: No 21143 100baseTx link beat, %8.8x, "
					   "trying NWay.\n", dev->name, csr12);
			t21142_start_nway(dev);
			next_tick = 3*HZ;
		}
	} else if ((csr12 & 0x7000) != 0x5000) {
		/* Negotiation failed.  Search media types. */
		if (tulip_debug > 1)
			printk(KERN_INFO"%s: 21143 negotiation failed, status %8.8x.\n",
				   dev->name, csr12);
		if (!(csr12 & 4)) {		/* 10mbps link beat good. */
			new_csr6 = 0x82420000;
			dev->if_port = 0;
			iowrite32(0, ioaddr + CSR13);
			iowrite32(0x0003FFFF, ioaddr + CSR14);
			iowrite16(t21142_csr15[dev->if_port], ioaddr + CSR15);
			iowrite32(t21142_csr13[dev->if_port], ioaddr + CSR13);
		} else {
			/* Select 100mbps port to check for link beat. */
			new_csr6 = 0x83860000;
			dev->if_port = 3;
			iowrite32(0, ioaddr + CSR13);
			iowrite32(0x0003FF7F, ioaddr + CSR14);
			iowrite16(8, ioaddr + CSR15);
			iowrite32(1, ioaddr + CSR13);
		}
		if (tulip_debug > 1)
			printk(KERN_INFO"%s: Testing new 21143 media %s.\n",
				   dev->name, medianame[dev->if_port]);
		if (new_csr6 != (tp->csr6 & ~0x00D5)) {
			tp->csr6 &= 0x00D5;
			tp->csr6 |= new_csr6;
			iowrite32(0x0301, ioaddr + CSR12);
			tulip_restart_rxtx(tp);
		}
		next_tick = 3*HZ;
	}

	/* mod_timer synchronizes us with potential add_timer calls
	 * from interrupts.
	 */
	mod_timer(&tp->timer, RUN_AT(next_tick));
}
static struct net_device *fs_init_instance(struct device *dev,
		struct fs_platform_info *fpi)
{
	struct net_device *ndev = NULL;
	struct fs_enet_private *fep = NULL;
	int privsize, i, r, err = 0, registered = 0;

	fpi->fs_no = fs_get_id(fpi);
	/* guard */
	if ((unsigned int)fpi->fs_no >= FS_MAX_INDEX)
		return ERR_PTR(-EINVAL);

	privsize = sizeof(*fep) + (sizeof(struct sk_buff **) *
			    (fpi->rx_ring + fpi->tx_ring));

	ndev = alloc_etherdev(privsize);
	if (!ndev) {
		err = -ENOMEM;
		goto err;
	}
	SET_MODULE_OWNER(ndev);

	fep = netdev_priv(ndev);
	memset(fep, 0, privsize);	/* clear everything */

	fep->dev = dev;
	dev_set_drvdata(dev, ndev);
	fep->fpi = fpi;
	if (fpi->init_ioports)
		fpi->init_ioports((struct fs_platform_info *)fpi);

#ifdef CONFIG_FS_ENET_HAS_FEC
	if (fs_get_fec_index(fpi->fs_no) >= 0)
		fep->ops = &fs_fec_ops;
#endif

#ifdef CONFIG_FS_ENET_HAS_SCC
	if (fs_get_scc_index(fpi->fs_no) >=0 )
		fep->ops = &fs_scc_ops;
#endif

#ifdef CONFIG_FS_ENET_HAS_FCC
	if (fs_get_fcc_index(fpi->fs_no) >= 0)
		fep->ops = &fs_fcc_ops;
#endif

	if (fep->ops == NULL) {
		printk(KERN_ERR DRV_MODULE_NAME
		       ": %s No matching ops found (%d).\n",
		       ndev->name, fpi->fs_no);
		err = -EINVAL;
		goto err;
	}

	r = (*fep->ops->setup_data)(ndev);
	if (r != 0) {
		printk(KERN_ERR DRV_MODULE_NAME
		       ": %s setup_data failed\n",
			ndev->name);
		err = r;
		goto err;
	}

	/* point rx_skbuff, tx_skbuff */
	fep->rx_skbuff = (struct sk_buff **)&fep[1];
	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;

	/* init locks */
	spin_lock_init(&fep->lock);
	spin_lock_init(&fep->tx_lock);

	/*
	 * Set the Ethernet address. 
	 */
	for (i = 0; i < 6; i++)
		ndev->dev_addr[i] = fpi->macaddr[i];
	
	r = (*fep->ops->allocate_bd)(ndev);
	
	if (fep->ring_base == NULL) {
		printk(KERN_ERR DRV_MODULE_NAME
		       ": %s buffer descriptor alloc failed (%d).\n", ndev->name, r);
		err = r;
		goto err;
	}

	/*
	 * Set receive and transmit descriptor base.
	 */
	fep->rx_bd_base = fep->ring_base;
	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;

	/* initialize ring size variables */
	fep->tx_ring = fpi->tx_ring;
	fep->rx_ring = fpi->rx_ring;

	/*
	 * The FEC Ethernet specific entries in the device structure. 
	 */
	ndev->open = fs_enet_open;
	ndev->hard_start_xmit = fs_enet_start_xmit;
	ndev->tx_timeout = fs_timeout;
	ndev->watchdog_timeo = 2 * HZ;
	ndev->stop = fs_enet_close;
	ndev->get_stats = fs_enet_get_stats;
	ndev->set_multicast_list = fs_set_multicast_list;
	if (fpi->use_napi) {
		ndev->poll = fs_enet_rx_napi;
		ndev->weight = fpi->napi_weight;
	}
	ndev->ethtool_ops = &fs_ethtool_ops;
	ndev->do_ioctl = fs_ioctl;

	init_timer(&fep->phy_timer_list);

	netif_carrier_off(ndev);

	err = register_netdev(ndev);
	if (err != 0) {
		printk(KERN_ERR DRV_MODULE_NAME
		       ": %s register_netdev failed.\n", ndev->name);
		goto err;
	}
	registered = 1;


	return ndev;

      err:
	if (ndev != NULL) {

		if (registered)
			unregister_netdev(ndev);

		if (fep != NULL) {
			(*fep->ops->free_bd)(ndev);
			(*fep->ops->cleanup_data)(ndev);
		}

		free_netdev(ndev);
	}

	dev_set_drvdata(dev, NULL);

	return ERR_PTR(err);
}
Example #12
0
static int __devinit fs_enet_probe(struct of_device *ofdev,
                                   const struct of_device_id *match)
{
	struct net_device *ndev;
	struct fs_enet_private *fep;
	struct fs_platform_info *fpi;
	const u32 *data;
	const u8 *mac_addr;
	int privsize, len, ret = -ENODEV;

	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
	if (!fpi)
		return -ENOMEM;

	if (!IS_FEC(match)) {
		data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
		if (!data || len != 4)
			goto out_free_fpi;

		fpi->cp_command = *data;
	}

	fpi->rx_ring = 32;
	fpi->tx_ring = 32;
	fpi->rx_copybreak = 240;
	fpi->use_napi = 1;
	fpi->napi_weight = 17;

	ret = find_phy(ofdev->node, fpi);
	if (ret)
		goto out_free_fpi;

	privsize = sizeof(*fep) +
	           sizeof(struct sk_buff **) *
	           (fpi->rx_ring + fpi->tx_ring);

	ndev = alloc_etherdev(privsize);
	if (!ndev) {
		ret = -ENOMEM;
		goto out_free_fpi;
	}

	dev_set_drvdata(&ofdev->dev, ndev);

	fep = netdev_priv(ndev);
	fep->dev = &ofdev->dev;
	fep->ndev = ndev;
	fep->fpi = fpi;
	fep->ops = match->data;

	ret = fep->ops->setup_data(ndev);
	if (ret)
		goto out_free_dev;

	fep->rx_skbuff = (struct sk_buff **)&fep[1];
	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;

	spin_lock_init(&fep->lock);
	spin_lock_init(&fep->tx_lock);

	mac_addr = of_get_mac_address(ofdev->node);
	if (mac_addr)
		memcpy(ndev->dev_addr, mac_addr, 6);

	ret = fep->ops->allocate_bd(ndev);
	if (ret)
		goto out_cleanup_data;

	fep->rx_bd_base = fep->ring_base;
	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;

	fep->tx_ring = fpi->tx_ring;
	fep->rx_ring = fpi->rx_ring;

	ndev->open = fs_enet_open;
	ndev->hard_start_xmit = fs_enet_start_xmit;
	ndev->tx_timeout = fs_timeout;
	ndev->watchdog_timeo = 2 * HZ;
	ndev->stop = fs_enet_close;
	ndev->get_stats = fs_enet_get_stats;
	ndev->set_multicast_list = fs_set_multicast_list;

	if (fpi->use_napi)
		netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
		               fpi->napi_weight);

	ndev->ethtool_ops = &fs_ethtool_ops;
	ndev->do_ioctl = fs_ioctl;

	init_timer(&fep->phy_timer_list);

	netif_carrier_off(ndev);

	ret = register_netdev(ndev);
	if (ret)
		goto out_free_bd;

	printk(KERN_INFO "%s: fs_enet: %02x:%02x:%02x:%02x:%02x:%02x\n",
	       ndev->name,
	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);

	return 0;

out_free_bd:
	fep->ops->free_bd(ndev);
out_cleanup_data:
	fep->ops->cleanup_data(ndev);
out_free_dev:
	free_netdev(ndev);
	dev_set_drvdata(&ofdev->dev, NULL);
out_free_fpi:
	kfree(fpi);
	return ret;
}
Example #13
0
/**
 *
 * This function intends to handle the activation of an interface
 * i.e. when it is brought Up/Active from a Down state.
 *
 */
static int netdev_open(struct net_device *pnetdev)
{
	struct _adapter *padapter = netdev_priv(pnetdev);

	mutex_lock(&padapter->mutex_start);
	if (!padapter->bup) {
		padapter->bDriverStopped = false;
		padapter->bSurpriseRemoved = false;
		padapter->bup = true;
		if (rtl871x_hal_init(padapter) != _SUCCESS)
			goto netdev_open_error;
		if (!r8712_initmac)
			/* Use the mac address stored in the Efuse */
			memcpy(pnetdev->dev_addr,
				padapter->eeprompriv.mac_addr, ETH_ALEN);
		else {
			/* We have to inform f/w to use user-supplied MAC
			 * address.
			 */
			msleep(200);
			r8712_setMacAddr_cmd(padapter, (u8 *)pnetdev->dev_addr);
			/*
			 * The "myid" function will get the wifi mac address
			 * from eeprompriv structure instead of netdev
			 * structure. So, we have to overwrite the mac_addr
			 * stored in the eeprompriv structure. In this case,
			 * the real mac address won't be used anymore. So that,
			 * the eeprompriv.mac_addr should store the mac which
			 * users specify.
			 */
			memcpy(padapter->eeprompriv.mac_addr,
				pnetdev->dev_addr, ETH_ALEN);
		}
		if (start_drv_threads(padapter) != _SUCCESS)
			goto netdev_open_error;
		if (!padapter->dvobjpriv.inirp_init)
			goto netdev_open_error;
		else
			padapter->dvobjpriv.inirp_init(padapter);
		r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
				  padapter->registrypriv.smart_ps);
	}
	if (!netif_queue_stopped(pnetdev))
		netif_start_queue(pnetdev);
	else
		netif_wake_queue(pnetdev);

	if (video_mode)
		enable_video_mode(padapter, cbw40_enable);
	/* start driver mlme relation timer */
	start_drv_timers(padapter);
	padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
	mutex_unlock(&padapter->mutex_start);
	return 0;
netdev_open_error:
	padapter->bup = false;
	netif_carrier_off(pnetdev);
	netif_stop_queue(pnetdev);
	mutex_unlock(&padapter->mutex_start);
	return -1;
}
Example #14
0
static int xgbe_probe(struct platform_device *pdev)
{
	struct xgbe_prv_data *pdata;
	struct xgbe_hw_if *hw_if;
	struct xgbe_desc_if *desc_if;
	struct net_device *netdev;
	struct device *dev = &pdev->dev;
	struct resource *res;
	const u8 *mac_addr;
	int ret;

	DBGPR("--> xgbe_probe\n");

	netdev = alloc_etherdev_mq(sizeof(struct xgbe_prv_data),
				   XGBE_MAX_DMA_CHANNELS);
	if (!netdev) {
		dev_err(dev, "alloc_etherdev failed\n");
		ret = -ENOMEM;
		goto err_alloc;
	}
	SET_NETDEV_DEV(netdev, dev);
	pdata = netdev_priv(netdev);
	pdata->netdev = netdev;
	pdata->pdev = pdev;
	pdata->dev = dev;
	platform_set_drvdata(pdev, netdev);

	spin_lock_init(&pdata->lock);
	mutex_init(&pdata->xpcs_mutex);

	/* Set and validate the number of descriptors for a ring */
	BUILD_BUG_ON_NOT_POWER_OF_2(TX_DESC_CNT);
	pdata->tx_desc_count = TX_DESC_CNT;
	if (pdata->tx_desc_count & (pdata->tx_desc_count - 1)) {
		dev_err(dev, "tx descriptor count (%d) is not valid\n",
			pdata->tx_desc_count);
		ret = -EINVAL;
		goto err_io;
	}
	BUILD_BUG_ON_NOT_POWER_OF_2(RX_DESC_CNT);
	pdata->rx_desc_count = RX_DESC_CNT;
	if (pdata->rx_desc_count & (pdata->rx_desc_count - 1)) {
		dev_err(dev, "rx descriptor count (%d) is not valid\n",
			pdata->rx_desc_count);
		ret = -EINVAL;
		goto err_io;
	}

	/* Obtain the system clock setting */
	pdata->sysclock = devm_clk_get(dev, NULL);
	if (IS_ERR(pdata->sysclock)) {
		dev_err(dev, "devm_clk_get failed\n");
		ret = PTR_ERR(pdata->sysclock);
		goto err_io;
	}

	/* Obtain the mmio areas for the device */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	pdata->xgmac_regs = devm_ioremap_resource(dev, res);
	if (IS_ERR(pdata->xgmac_regs)) {
		dev_err(dev, "xgmac ioremap failed\n");
		ret = PTR_ERR(pdata->xgmac_regs);
		goto err_io;
	}
	DBGPR("  xgmac_regs = %p\n", pdata->xgmac_regs);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	pdata->xpcs_regs = devm_ioremap_resource(dev, res);
	if (IS_ERR(pdata->xpcs_regs)) {
		dev_err(dev, "xpcs ioremap failed\n");
		ret = PTR_ERR(pdata->xpcs_regs);
		goto err_io;
	}
	DBGPR("  xpcs_regs  = %p\n", pdata->xpcs_regs);

	/* Set the DMA mask */
	if (!dev->dma_mask)
		dev->dma_mask = &dev->coherent_dma_mask;
	*(dev->dma_mask) = DMA_BIT_MASK(40);
	dev->coherent_dma_mask = DMA_BIT_MASK(40);

	ret = platform_get_irq(pdev, 0);
	if (ret < 0) {
		dev_err(dev, "platform_get_irq failed\n");
		goto err_io;
	}
	netdev->irq = ret;
	netdev->base_addr = (unsigned long)pdata->xgmac_regs;

	/* Set all the function pointers */
	xgbe_init_all_fptrs(pdata);
	hw_if = &pdata->hw_if;
	desc_if = &pdata->desc_if;

	/* Issue software reset to device */
	hw_if->exit(pdata);

	/* Populate the hardware features */
	xgbe_get_all_hw_features(pdata);

	/* Retrieve the MAC address */
	mac_addr = of_get_mac_address(dev->of_node);
	if (!mac_addr) {
		dev_err(dev, "invalid mac address for this device\n");
		ret = -EINVAL;
		goto err_io;
	}
	memcpy(netdev->dev_addr, mac_addr, netdev->addr_len);

	/* Retrieve the PHY mode - it must be "xgmii" */
	pdata->phy_mode = of_get_phy_mode(dev->of_node);
	if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII) {
		dev_err(dev, "invalid phy-mode specified for this device\n");
		ret = -EINVAL;
		goto err_io;
	}

	/* Set default configuration data */
	xgbe_default_config(pdata);

	/* Calculate the number of Tx and Rx rings to be created */
	pdata->tx_ring_count = min_t(unsigned int, num_online_cpus(),
				     pdata->hw_feat.tx_ch_cnt);
	ret = netif_set_real_num_tx_queues(netdev, pdata->tx_ring_count);
	if (ret) {
		dev_err(dev, "error setting real tx queue count\n");
		goto err_io;
	}

	pdata->rx_ring_count = min_t(unsigned int,
				     netif_get_num_default_rss_queues(),
				     pdata->hw_feat.rx_ch_cnt);
	ret = netif_set_real_num_rx_queues(netdev, pdata->rx_ring_count);
	if (ret) {
		dev_err(dev, "error setting real rx queue count\n");
		goto err_io;
	}

	/* Allocate the rings for the DMA channels */
	pdata->channel = xgbe_alloc_rings(pdata);
	if (!pdata->channel) {
		dev_err(dev, "ring allocation failed\n");
		ret = -ENOMEM;
		goto err_io;
	}

	/* Prepare to regsiter with MDIO */
	pdata->mii_bus_id = kasprintf(GFP_KERNEL, "%s", pdev->name);
	if (!pdata->mii_bus_id) {
		dev_err(dev, "failed to allocate mii bus id\n");
		ret = -ENOMEM;
		goto err_io;
	}
	ret = xgbe_mdio_register(pdata);
	if (ret)
		goto err_bus_id;

	/* Set network and ethtool operations */
	netdev->netdev_ops = xgbe_get_netdev_ops();
	netdev->ethtool_ops = xgbe_get_ethtool_ops();

	/* Set device features */
	netdev->hw_features = NETIF_F_SG |
			      NETIF_F_IP_CSUM |
			      NETIF_F_IPV6_CSUM |
			      NETIF_F_RXCSUM |
			      NETIF_F_TSO |
			      NETIF_F_TSO6 |
			      NETIF_F_GRO |
			      NETIF_F_HW_VLAN_CTAG_RX |
			      NETIF_F_HW_VLAN_CTAG_TX;

	netdev->vlan_features |= NETIF_F_SG |
				 NETIF_F_IP_CSUM |
				 NETIF_F_IPV6_CSUM |
				 NETIF_F_TSO |
				 NETIF_F_TSO6;

	netdev->features |= netdev->hw_features;
	pdata->netdev_features = netdev->features;

	xgbe_init_rx_coalesce(pdata);
	xgbe_init_tx_coalesce(pdata);

	netif_carrier_off(netdev);
	ret = register_netdev(netdev);
	if (ret) {
		dev_err(dev, "net device registration failed\n");
		goto err_reg_netdev;
	}

	xgbe_debugfs_init(pdata);

	netdev_notice(netdev, "net device enabled\n");

	DBGPR("<-- xgbe_probe\n");

	return 0;

err_reg_netdev:
	xgbe_mdio_unregister(pdata);

err_bus_id:
	kfree(pdata->mii_bus_id);

err_io:
	free_netdev(netdev);

err_alloc:
	dev_notice(dev, "net device not enabled\n");

	return ret;
}
Example #15
0
static int rtw_gspi_suspend(struct spi_device *spi, pm_message_t mesg)
{
    struct dvobj_priv *dvobj = spi_get_drvdata(spi);
    PADAPTER padapter = dvobj->if1;
    struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
    struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
    struct net_device *pnetdev = padapter->pnetdev;
    int ret = 0;

    u32 start_time = rtw_get_current_time();

    _func_enter_;

    DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);

    pwrpriv->bInSuspend = _TRUE;

    while (pwrpriv->bips_processing == _TRUE)
        rtw_msleep_os(1);

    if((!padapter->bup) || (padapter->bDriverStopped)||(padapter->bSurpriseRemoved))
    {
        DBG_871X("%s bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n", __FUNCTION__
                 ,padapter->bup, padapter->bDriverStopped,padapter->bSurpriseRemoved);
        goto exit;
    }

    rtw_cancel_all_timer(padapter);
    LeaveAllPowerSaveMode(padapter);

    //padapter->net_closed = _TRUE;
    //s1.
    if(pnetdev)
    {
        netif_carrier_off(pnetdev);
        rtw_netif_stop_queue(pnetdev);
    }
#ifdef CONFIG_WOWLAN
    padapter->pwrctrlpriv.bSupportRemoteWakeup=_TRUE;
#else
    //s2.
    //s2-1.  issue rtw_disassoc_cmd to fw
    disconnect_hdl(padapter, NULL);
    //rtw_disassoc_cmd(padapter);
#endif

#ifdef CONFIG_LAYER2_ROAMING_RESUME
    if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED) )
    {
        DBG_871X("%s %s(" MAC_FMT "), length:%d assoc_ssid.length:%d\n",__FUNCTION__,
                 pmlmepriv->cur_network.network.Ssid.Ssid,
                 MAC_ARG(pmlmepriv->cur_network.network.MacAddress),
                 pmlmepriv->cur_network.network.Ssid.SsidLength,
                 pmlmepriv->assoc_ssid.SsidLength);

        pmlmepriv->to_roaming = 1;
    }
#endif

    //s2-2.  indicate disconnect to os
    rtw_indicate_disconnect(padapter);
    //s2-3.
    rtw_free_assoc_resources(padapter, 1);

    //s2-4.
    rtw_free_network_queue(padapter, _TRUE);

    rtw_led_control(padapter, LED_CTL_POWER_OFF);

    rtw_dev_unload(padapter);

    if(check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
        rtw_indicate_scan_done(padapter, 1);

    if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
        rtw_indicate_disconnect(padapter);

    // interface deinit
    gspi_deinit(dvobj);
    RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("%s: deinit GSPI complete!\n", __FUNCTION__));

    rtw_wifi_gpio_wlan_ctrl(WLAN_PWDN_OFF);
    rtw_mdelay_os(1);
exit:
    DBG_871X("<===  %s return %d.............. in %dms\n", __FUNCTION__
             , ret, rtw_get_passing_time_ms(start_time));

    _func_exit_;
    return ret;
}
Example #16
0
/** 
 * \fn     wlanDrvIf_SetupNetif
 * \brief  Setup driver network interface
 * 
 * Called in driver creation process.
 * Setup driver network interface.
 *
 * \note   
 * \param  drv - The driver object handle
 * \return 0 - OK, else - failure
 * \sa     
 */ 
static int wlanDrvIf_SetupNetif (TWlanDrvIfObj *drv)
{
   struct net_device *dev;
   int res;

   /* Allocate network interface structure for the driver */
   dev = alloc_etherdev (0);
   if (dev == NULL)
   {
      ti_dprintf (TIWLAN_LOG_ERROR, "alloc_etherdev() failed\n");
      return -ENOMEM;
   }

   /* Setup the network interface */
   ether_setup (dev);

/* the following is required on at least BSP 23.8 and higher.
    Without it, the Open function of the driver will not be called
    when trying to 'ifconfig up' the interface */
//#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
//   dev->validate_addr   = NULL;
//#endif

   NETDEV_SET_PRIVATE(dev,drv);
   drv->netdev = dev;
   strcpy (dev->name, TIWLAN_DRV_IF_NAME);
   netif_carrier_off (dev);
/*
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
   dev->open = wlanDrvIf_Start;
   dev->stop = wlanDrvIf_Stop;
#else
   dev->open = wlanDrvIf_Open;
   dev->stop = wlanDrvIf_Release;
#endif
*/
   /*dev->hard_start_xmit = wlanDrvIf_XmitDummy;*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)  
   dev->netdev_ops = &tiwlan_netdev_ops;
#else
   dev->open = wlanDrvIf_Start;
   dev->stop = wlanDrvIf_Stop;
   dev->hard_start_xmit = wlanDrvIf_Xmit;
   dev->addr_len = MAC_ADDR_LEN;
   dev->get_stats = wlanDrvIf_NetGetStat;
   dev->tx_queue_len = 100;
   dev->do_ioctl = NULL;
#endif

   /* Initialize Wireless Extensions interface (WEXT) */
   wlanDrvWext_Init (dev);

   res = register_netdev (dev);
   if (res != 0)
   {
      ti_dprintf (TIWLAN_LOG_ERROR, "register_netdev() failed : %d\n", res);
      kfree (dev);
      return res;
   }
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
#if defined HOST_PLATFORM_OMAP3430 || defined HOST_PLATFORM_ZOOM2 || defined HOST_PLATFORM_ZOOM1 || defined HOST_PLATFORM_MX25
   sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend);
#endif
#else
#ifdef CONFIG_PM
   sdioDrv_register_pm(wlanDrvIf_pm_resume, wlanDrvIf_pm_suspend);
#endif
#endif
/*
On the latest Kernel there is no more support for the below macro.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
   SET_MODULE_OWNER (dev);
#endif
   return 0;
}
Example #17
0
static int netvsc_probe(struct device *device)
{
	struct driver_context *driver_ctx =
		driver_to_driver_context(device->driver);
	struct netvsc_driver_context *net_drv_ctx =
		(struct netvsc_driver_context *)driver_ctx;
	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
	struct device_context *device_ctx = device_to_device_context(device);
	struct hv_device *device_obj = &device_ctx->device_obj;
	struct net_device *net = NULL;
	struct net_device_context *net_device_ctx;
	struct netvsc_device_info device_info;
	int ret;

	DPRINT_ENTER(NETVSC_DRV);

	if (!net_drv_obj->Base.OnDeviceAdd)
		return -1;

	net = alloc_etherdev(sizeof(struct net_device_context));
	if (!net)
		return -1;

	/* Set initial state */
	netif_carrier_off(net);
	netif_stop_queue(net);

	net_device_ctx = netdev_priv(net);
	net_device_ctx->device_ctx = device_ctx;
	dev_set_drvdata(device, net);

	/* Notify the netvsc driver of the new device */
	ret = net_drv_obj->Base.OnDeviceAdd(device_obj, &device_info);
	if (ret != 0) {
		free_netdev(net);
		dev_set_drvdata(device, NULL);

		DPRINT_ERR(NETVSC_DRV, "unable to add netvsc device (ret %d)",
			   ret);
		return ret;
	}

	/*
	 * If carrier is still off ie we did not get a link status callback,
	 * update it if necessary
	 */
	/*
	 * FIXME: We should use a atomic or test/set instead to avoid getting
	 * out of sync with the device's link status
	 */
	if (!netif_carrier_ok(net))
		if (!device_info.LinkState)
			netif_carrier_on(net);

	memcpy(net->dev_addr, device_info.MacAddr, ETH_ALEN);

	net->netdev_ops = &device_ops;

	SET_NETDEV_DEV(net, device);

	ret = register_netdev(net);
	if (ret != 0) {
		/* Remove the device and release the resource */
		net_drv_obj->Base.OnDeviceRemove(device_obj);
		free_netdev(net);
	}

	DPRINT_EXIT(NETVSC_DRV);
	return ret;
}
Example #18
0
static int rtw_hw_suspend(struct adapter *padapter)
{
	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
	struct net_device *pnetdev = padapter->pnetdev;


	if ((!padapter->bup) || (padapter->bDriverStopped) ||
	    (padapter->bSurpriseRemoved)) {
		DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
			padapter->bup, padapter->bDriverStopped,
			padapter->bSurpriseRemoved);
		goto error_exit;
	}

	/* system suspend */
	LeaveAllPowerSaveMode(padapter);

	DBG_88E("==> rtw_hw_suspend\n");
	_enter_pwrlock(&pwrpriv->lock);
	pwrpriv->bips_processing = true;
	/* s1. */
	if (pnetdev) {
		netif_carrier_off(pnetdev);
		netif_tx_stop_all_queues(pnetdev);
	}

	/* s2. */
	rtw_disassoc_cmd(padapter, 500, false);

	/* s2-2.  indicate disconnect to os */
	{
		struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;

		if (check_fwstate(pmlmepriv, _FW_LINKED)) {
			_clr_fwstate_(pmlmepriv, _FW_LINKED);

			rtw_led_control(padapter, LED_CTL_NO_LINK);

			rtw_os_indicate_disconnect(padapter);

			/* donnot enqueue cmd */
			rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 0);
		}
	}
	/* s2-3. */
	rtw_free_assoc_resources(padapter);

	/* s2-4. */
	rtw_free_network_queue(padapter, true);
	rtw_ips_dev_unload(padapter);
	pwrpriv->rf_pwrstate = rf_off;
	pwrpriv->bips_processing = false;

	_exit_pwrlock(&pwrpriv->lock);

	return 0;

error_exit:
	DBG_88E("%s, failed\n", __func__);
	return -1;
}
Example #19
0
static void phylink_resolve(struct work_struct *w)
{
	struct phylink *pl = container_of(w, struct phylink, resolve);
	struct phylink_link_state link_state;
	struct net_device *ndev = pl->netdev;

	mutex_lock(&pl->state_mutex);
	if (pl->phylink_disable_state) {
		pl->mac_link_dropped = false;
		link_state.link = false;
	} else if (pl->mac_link_dropped) {
		link_state.link = false;
	} else {
		switch (pl->link_an_mode) {
		case MLO_AN_PHY:
			link_state = pl->phy_state;
			phylink_resolve_flow(pl, &link_state);
			phylink_mac_config(pl, &link_state);
			break;

		case MLO_AN_FIXED:
			phylink_get_fixed_state(pl, &link_state);
			phylink_mac_config(pl, &link_state);
			break;

		case MLO_AN_INBAND:
			phylink_get_mac_state(pl, &link_state);
			if (pl->phydev) {
				bool changed = false;

				link_state.link = link_state.link &&
						  pl->phy_state.link;

				if (pl->phy_state.interface !=
				    link_state.interface) {
					link_state.interface = pl->phy_state.interface;
					changed = true;
				}

				/* Propagate the flow control from the PHY
				 * to the MAC. Also propagate the interface
				 * if changed.
				 */
				if (pl->phy_state.link || changed) {
					link_state.pause |= pl->phy_state.pause;
					phylink_resolve_flow(pl, &link_state);

					phylink_mac_config(pl, &link_state);
				}
			}
			break;
		}
	}

	if (link_state.link != netif_carrier_ok(ndev)) {
		if (!link_state.link) {
			netif_carrier_off(ndev);
			pl->ops->mac_link_down(ndev, pl->link_an_mode,
					       pl->phy_state.interface);
			netdev_info(ndev, "Link is Down\n");
		} else {
			pl->ops->mac_link_up(ndev, pl->link_an_mode,
					     pl->phy_state.interface,
					     pl->phydev);

			netif_carrier_on(ndev);

			netdev_info(ndev,
				    "Link is Up - %s/%s - flow control %s\n",
				    phy_speed_to_str(link_state.speed),
				    phy_duplex_to_str(link_state.duplex),
				    phylink_pause_to_str(link_state.pause));
		}
	}
	if (!link_state.link && pl->mac_link_dropped) {
		pl->mac_link_dropped = false;
		queue_work(system_power_efficient_wq, &pl->resolve);
	}
	mutex_unlock(&pl->state_mutex);
}
Example #20
0
/*
 * In Ad-Hoc mode, the IBSS is created if not found in scan list.
 * In both Ad-Hoc and infra mode, an deauthentication is performed
 * first.
 */
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
		      struct cfg80211_ssid *req_ssid)
{
	int ret;
	struct mwifiex_adapter *adapter = priv->adapter;
	struct mwifiex_bssdescriptor *bss_desc = NULL;

	priv->scan_block = false;

	if (bss) {
		/* Allocate and fill new bss descriptor */
		bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
				GFP_KERNEL);
		if (!bss_desc) {
			dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
			return -ENOMEM;
		}

		ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
		if (ret)
			goto done;
	}

	if (priv->bss_mode == NL80211_IFTYPE_STATION) {
		/* Infra mode */
		ret = mwifiex_deauthenticate(priv, NULL);
		if (ret)
			goto done;

		ret = mwifiex_check_network_compatibility(priv, bss_desc);
		if (ret)
			goto done;

		dev_dbg(adapter->dev, "info: SSID found in scan list ... "
				      "associating...\n");

		if (!netif_queue_stopped(priv->netdev))
			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
		if (netif_carrier_ok(priv->netdev))
			netif_carrier_off(priv->netdev);

		/* Clear any past association response stored for
		 * application retrieval */
		priv->assoc_rsp_size = 0;
		ret = mwifiex_associate(priv, bss_desc);

		/* If auth type is auto and association fails using open mode,
		 * try to connect using shared mode */
		if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG &&
		    priv->sec_info.is_authtype_auto &&
		    priv->sec_info.wep_enabled) {
			priv->sec_info.authentication_mode =
						NL80211_AUTHTYPE_SHARED_KEY;
			ret = mwifiex_associate(priv, bss_desc);
		}

		if (bss)
			cfg80211_put_bss(bss);
	} else {
		/* Adhoc mode */
		/* If the requested SSID matches current SSID, return */
		if (bss_desc && bss_desc->ssid.ssid_len &&
		    (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor.
				       ssid, &bss_desc->ssid))) {
			kfree(bss_desc);
			return 0;
		}

		/* Exit Adhoc mode first */
		dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
		ret = mwifiex_deauthenticate(priv, NULL);
		if (ret)
			goto done;

		priv->adhoc_is_link_sensed = false;

		ret = mwifiex_check_network_compatibility(priv, bss_desc);

		if (!netif_queue_stopped(priv->netdev))
			mwifiex_stop_net_dev_queue(priv->netdev, adapter);
		if (netif_carrier_ok(priv->netdev))
			netif_carrier_off(priv->netdev);

		if (!ret) {
			dev_dbg(adapter->dev, "info: network found in scan"
							" list. Joining...\n");
			ret = mwifiex_adhoc_join(priv, bss_desc);
			if (bss)
				cfg80211_put_bss(bss);
		} else {
			dev_dbg(adapter->dev, "info: Network not found in "
				"the list, creating adhoc with ssid = %s\n",
				req_ssid->ssid);
			ret = mwifiex_adhoc_start(priv, req_ssid);
		}
	}

done:
	kfree(bss_desc);
	return ret;
}
static int rt2860_suspend(
	struct pci_dev *pci_dev,
	pm_message_t state)
{
	struct net_device *net_dev = pci_get_drvdata(pci_dev);
	VOID *pAd = NULL;
	INT32 retval = 0;


	DBGPRINT(RT_DEBUG_TRACE, ("===> rt2860_suspend()\n"));

	if (net_dev == NULL)
	{
		DBGPRINT(RT_DEBUG_ERROR, ("net_dev == NULL!\n"));
	}
	else
	{
		ULONG IfNum;

		GET_PAD_FROM_NET_DEV(pAd, net_dev);

		/* we can not use IFF_UP because ra0 down but ra1 up */
		/* and 1 suspend/resume function for 1 module, not for each interface */
		/* so Linux will call suspend/resume function once */
		RTMP_DRIVER_VIRTUAL_INF_NUM_GET(pAd, &IfNum);
		if (IfNum > 0)
		{
			/* avoid users do suspend after interface is down */

			/* stop interface */
			netif_carrier_off(net_dev);
			netif_stop_queue(net_dev);

			/* mark device as removed from system and therefore no longer available */
			netif_device_detach(net_dev);

			/* mark halt flag */
/*			RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS); */
/*			RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_RADIO_OFF); */
			RTMP_DRIVER_PCI_SUSPEND(pAd);

			/* take down the device */
			rt28xx_close((PNET_DEV)net_dev);

			RT_MOD_DEC_USE_COUNT();
		}
	}

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)
	/* reference to http://vovo2000.com/type-lab/linux/kernel-api/linux-kernel-api.html */
	/* enable device to generate PME# when suspended */
	/* pci_choose_state(): Choose the power state of a PCI device to be suspended */
	retval = pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state), 1);
	/* save the PCI configuration space of a device before suspending */
	pci_save_state(pci_dev);
	/* disable PCI device after use */
	pci_disable_device(pci_dev);

	retval = pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
#endif

	DBGPRINT(RT_DEBUG_TRACE, ("<=== rt2860_suspend()\n"));
	return retval;
}
Example #22
0
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;

	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 {
		INFO(dev, "MAC %pM\n", net->dev_addr);
		INFO(dev, "HOST MAC %pM\n", dev->host_mac);

		the_dev = dev;
	}

	return status;
}
Example #23
0
int hostapd_mode_init(_adapter *padapter)
{
	unsigned char mac[ETH_ALEN];
	struct hostapd_priv *phostapdpriv;
	struct net_device *pnetdev;
	
	pnetdev = rtw_alloc_etherdev(sizeof(struct hostapd_priv));	
	if (!pnetdev)
	   return -ENOMEM;

	//SET_MODULE_OWNER(pnetdev);
       ether_setup(pnetdev);

	//pnetdev->type = ARPHRD_IEEE80211;
	
	phostapdpriv = rtw_netdev_priv(pnetdev);
	phostapdpriv->pmgnt_netdev = pnetdev;
	phostapdpriv->padapter= padapter;
	padapter->phostapdpriv = phostapdpriv;
	
	//pnetdev->init = NULL;
	
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,29))

	DBG_8192C("register rtl871x_mgnt_netdev_ops to netdev_ops\n");

	pnetdev->netdev_ops = &rtl871x_mgnt_netdev_ops;
	
#else

	pnetdev->open = mgnt_netdev_open;

	pnetdev->stop = mgnt_netdev_close;	
	
	pnetdev->hard_start_xmit = mgnt_xmit_entry;
	
	//pnetdev->set_mac_address = r871x_net_set_mac_address;
	
	//pnetdev->get_stats = r871x_net_get_stats;

	//pnetdev->do_ioctl = r871x_mp_ioctl;
	
#endif

	pnetdev->watchdog_timeo = HZ; /* 1 second timeout */	

	//pnetdev->wireless_handlers = NULL;

#ifdef CONFIG_TCP_CSUM_OFFLOAD_TX
	pnetdev->features |= NETIF_F_IP_CSUM;
#endif	

	
	
	if(dev_alloc_name(pnetdev,"mgnt.wlan%d") < 0)
	{
		DBG_8192C("hostapd_mode_init(): dev_alloc_name, fail! \n");		
	}


	//SET_NETDEV_DEV(pnetdev, pintfpriv->udev);


	mac[0]=0x00;
	mac[1]=0xe0;
	mac[2]=0x4c;
	mac[3]=0x87;
	mac[4]=0x11;
	mac[5]=0x12;
				
	_rtw_memcpy(pnetdev->dev_addr, mac, ETH_ALEN);
	

	netif_carrier_off(pnetdev);


	/* Tell the network stack we exist */
	if (register_netdev(pnetdev) != 0)
	{
		DBG_8192C("hostapd_mode_init(): register_netdev fail!\n");
		
		if(pnetdev)
      		{	 
			rtw_free_netdev(pnetdev);
      		}
	}
	
	return 0;
	
}
Example #24
0
/* slave device setup *******************************************************/
struct net_device *
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, ether_setup);
	if (slave_dev == NULL)
		return slave_dev;

	slave_dev->features = master->vlan_features;
	SET_ETHTOOL_OPS(slave_dev, &dsa_slave_ethtool_ops);
	memcpy(slave_dev->dev_addr, master->dev_addr, ETH_ALEN);
	slave_dev->tx_queue_len = 0;

	switch (ds->dst->tag_protocol) {
#ifdef CONFIG_NET_DSA_TAG_DSA
	case htons(ETH_P_DSA):
		slave_dev->netdev_ops = &dsa_netdev_ops;
		break;
#endif
#ifdef CONFIG_NET_DSA_TAG_EDSA
	case htons(ETH_P_EDSA):
		slave_dev->netdev_ops = &edsa_netdev_ops;
		break;
#endif
#ifdef CONFIG_NET_DSA_TAG_TRAILER
	case htons(ETH_P_TRAILER):
		slave_dev->netdev_ops = &trailer_netdev_ops;
		break;
#endif
	default:
		BUG();
	}

	SET_NETDEV_DEV(slave_dev, parent);
	slave_dev->vlan_features = master->vlan_features;

	p = netdev_priv(slave_dev);
	p->dev = slave_dev;
	p->parent = ds;
	p->port = port;
	p->phy = ds->slave_mii_bus->phy_map[port];

	ret = register_netdev(slave_dev);
	if (ret) {
		printk(KERN_ERR "%s: error %d registering interface %s\n",
				master->name, ret, slave_dev->name);
		free_netdev(slave_dev);
		return NULL;
	}

	netif_carrier_off(slave_dev);

	if (p->phy != NULL) {
		phy_attach(slave_dev, dev_name(&p->phy->dev),
			   0, PHY_INTERFACE_MODE_GMII);

		p->phy->autoneg = AUTONEG_ENABLE;
		p->phy->speed = 0;
		p->phy->duplex = 0;
		p->phy->advertising = p->phy->supported | ADVERTISED_Autoneg;
		phy_start_aneg(p->phy);
	}

	return slave_dev;
}
Example #25
0
int _netdev_open(struct net_device *pnetdev)
{
	uint status;	
	_adapter *padapter = (_adapter *)rtw_netdev_priv(pnetdev);
	struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;

	RT_TRACE(_module_os_intfs_c_,_drv_info_,("+871x_drv - dev_open\n"));
	DBG_8192C("+871x_drv - drv_open, bup=%d\n", padapter->bup);

	if(pwrctrlpriv->ps_flag == _TRUE){
		padapter->net_closed = _FALSE;
		goto netdev_open_normal_process;
	}
		
	if(padapter->bup == _FALSE)
    	{    
		padapter->bDriverStopped = _FALSE;
	 	padapter->bSurpriseRemoved = _FALSE;	 
		padapter->bCardDisableWOHSM = _FALSE;        	
	
		status = rtw_hal_init(padapter);		
		if (status ==_FAIL)
		{			
			RT_TRACE(_module_os_intfs_c_,_drv_err_,("rtl871x_hal_init(): Can't init h/w!\n"));
			goto netdev_open_error;
		}
		
		DBG_8192C("MAC Address = "MAC_FMT"\n", MAC_ARG(pnetdev->dev_addr));

		
		status=rtw_start_drv_threads(padapter);
		if(status ==_FAIL)
		{			
			RT_TRACE(_module_os_intfs_c_,_drv_err_,("Initialize driver software resource Failed!\n"));			
			goto netdev_open_error;			
		}


		if (init_hw_mlme_ext(padapter) == _FAIL)
		{
			RT_TRACE(_module_os_intfs_c_,_drv_err_,("can't init mlme_ext_priv\n"));
			goto netdev_open_error;
		}


#ifdef CONFIG_DRVEXT_MODULE
		init_drvext(padapter);
#endif

		if(padapter->intf_start)
		{
			padapter->intf_start(padapter);
		}

#ifdef CONFIG_PROC_DEBUG
#ifndef RTK_DMP_PLATFORM
		rtw_proc_init_one(pnetdev);
#endif
#endif

#ifdef CONFIG_IOCTL_CFG80211
		rtw_cfg80211_init_wiphy(padapter);
#endif

		rtw_led_control(padapter, LED_CTL_NO_LINK);

		padapter->bup = _TRUE;
	}
	padapter->net_closed = _FALSE;

	_set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);

	if(( pwrctrlpriv->power_mgnt != PS_MODE_ACTIVE ) ||(padapter->pwrctrlpriv.bHWPwrPindetect))
	{
		padapter->pwrctrlpriv.bips_processing = _FALSE;	
		rtw_set_pwr_state_check_timer(&padapter->pwrctrlpriv);
 	}

	//netif_carrier_on(pnetdev);//call this func when rtw_joinbss_event_callback return success       
 	if(!netif_queue_stopped(pnetdev))
      		netif_start_queue(pnetdev);
	else
		netif_wake_queue(pnetdev);

#ifdef CONFIG_BR_EXT

#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
	rcu_read_lock();
#endif	// (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))

	//if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE)
	{
		//struct net_bridge	*br = pnetdev->br_port->br;//->dev->dev_addr;
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
		if (pnetdev->br_port) 
#else   // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
		if (rcu_dereference(padapter->pnetdev->rx_handler_data))
#endif  // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) 
		{
			struct net_device *br_netdev;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
			br_netdev = dev_get_by_name(CONFIG_BR_EXT_BRNAME);
#else	// (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
			struct net *devnet = NULL;

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
			devnet = pnetdev->nd_net;
#else	// (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))
			devnet = dev_net(pnetdev);
#endif	// (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26))

			br_netdev = dev_get_by_name(devnet, CONFIG_BR_EXT_BRNAME);
#endif	// (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))

			if (br_netdev) {
				memcpy(padapter->br_mac, br_netdev->dev_addr, ETH_ALEN);
				dev_put(br_netdev);
			} else
				printk("%s()-%d: dev_get_by_name(%s) failed!", __FUNCTION__, __LINE__, CONFIG_BR_EXT_BRNAME);
		}
		
		padapter->ethBrExtInfo.addPPPoETag = 1;
	}

#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
	rcu_read_unlock();
#endif	// (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))

#endif	// CONFIG_BR_EXT

netdev_open_normal_process:

	RT_TRACE(_module_os_intfs_c_,_drv_info_,("-871x_drv - dev_open\n"));
	DBG_8192C("-871x_drv - drv_open, bup=%d\n", padapter->bup);
		
	return 0;
	
netdev_open_error:

	padapter->bup = _FALSE;
	
	netif_carrier_off(pnetdev);	
	netif_stop_queue(pnetdev);
	
	RT_TRACE(_module_os_intfs_c_,_drv_err_,("-871x_drv - dev_open, fail!\n"));
	DBG_8192C("-871x_drv - drv_open fail, bup=%d\n", padapter->bup);
	
	return (-1);
	
}
Example #26
0
static int bgmac_fixed_phy_register(struct bgmac *bgmac)
{
	struct fixed_phy_status fphy_status = {
		.link = 1,
		.speed = SPEED_1000,
		.duplex = DUPLEX_FULL,
	};
	struct phy_device *phy_dev;
	int err;

	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
	if (!phy_dev || IS_ERR(phy_dev)) {
		bgmac_err(bgmac, "Failed to register fixed PHY device\n");
		return -ENODEV;
	}

	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
				 PHY_INTERFACE_MODE_MII);
	if (err) {
		bgmac_err(bgmac, "Connecting PHY failed\n");
		return err;
	}

	bgmac->phy_dev = phy_dev;

	return err;
}

static int bgmac_mii_register(struct bgmac *bgmac)
{
	struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo;
	struct mii_bus *mii_bus;
	struct phy_device *phy_dev;
	char bus_id[MII_BUS_ID_SIZE + 3];
	int err = 0;

	if (ci->id == BCMA_CHIP_ID_BCM4707 ||
	    ci->id == BCMA_CHIP_ID_BCM53018)
		return bgmac_fixed_phy_register(bgmac);

	mii_bus = mdiobus_alloc();
	if (!mii_bus)
		return -ENOMEM;

	mii_bus->name = "bgmac mii bus";
	sprintf(mii_bus->id, "%s-%d-%d", "bgmac", bgmac->core->bus->num,
		bgmac->core->core_unit);
	mii_bus->priv = bgmac;
	mii_bus->read = bgmac_mii_read;
	mii_bus->write = bgmac_mii_write;
	mii_bus->parent = &bgmac->core->dev;
	mii_bus->phy_mask = ~(1 << bgmac->phyaddr);

	err = mdiobus_register(mii_bus);
	if (err) {
		bgmac_err(bgmac, "Registration of mii bus failed\n");
		goto err_free_bus;
	}

	bgmac->mii_bus = mii_bus;

	/* Connect to the PHY */
	snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id,
		 bgmac->phyaddr);
	phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
			      PHY_INTERFACE_MODE_MII);
	if (IS_ERR(phy_dev)) {
		bgmac_err(bgmac, "PHY connecton failed\n");
		err = PTR_ERR(phy_dev);
		goto err_unregister_bus;
	}
	bgmac->phy_dev = phy_dev;

	return err;

err_unregister_bus:
	mdiobus_unregister(mii_bus);
err_free_bus:
	mdiobus_free(mii_bus);
	return err;
}

static void bgmac_mii_unregister(struct bgmac *bgmac)
{
	struct mii_bus *mii_bus = bgmac->mii_bus;

	mdiobus_unregister(mii_bus);
	mdiobus_free(mii_bus);
}

/**************************************************
 * BCMA bus ops
 **************************************************/

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
static int bgmac_probe(struct bcma_device *core)
{
	struct bcma_chipinfo *ci = &core->bus->chipinfo;
	struct net_device *net_dev;
	struct bgmac *bgmac;
	struct ssb_sprom *sprom = &core->bus->sprom;
	u8 *mac;
	int err;

	switch (core->core_unit) {
	case 0:
		mac = sprom->et0mac;
		break;
	case 1:
		mac = sprom->et1mac;
		break;
	case 2:
		mac = sprom->et2mac;
		break;
	default:
		pr_err("Unsupported core_unit %d\n", core->core_unit);
		return -ENOTSUPP;
	}

	if (!is_valid_ether_addr(mac)) {
		dev_err(&core->dev, "Invalid MAC addr: %pM\n", mac);
		eth_random_addr(mac);
		dev_warn(&core->dev, "Using random MAC: %pM\n", mac);
	}

	/* Allocation and references */
	net_dev = alloc_etherdev(sizeof(*bgmac));
	if (!net_dev)
		return -ENOMEM;
	net_dev->netdev_ops = &bgmac_netdev_ops;
	net_dev->irq = core->irq;
	net_dev->ethtool_ops = &bgmac_ethtool_ops;
	bgmac = netdev_priv(net_dev);
	bgmac->net_dev = net_dev;
	bgmac->core = core;
	bcma_set_drvdata(core, bgmac);

	/* Defaults */
	memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);

	/* On BCM4706 we need common core to access PHY */
	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
	    !core->bus->drv_gmac_cmn.core) {
		bgmac_err(bgmac, "GMAC CMN core not found (required for BCM4706)\n");
		err = -ENODEV;
		goto err_netdev_free;
	}
	bgmac->cmn = core->bus->drv_gmac_cmn.core;

	switch (core->core_unit) {
	case 0:
		bgmac->phyaddr = sprom->et0phyaddr;
		break;
	case 1:
		bgmac->phyaddr = sprom->et1phyaddr;
		break;
	case 2:
		bgmac->phyaddr = sprom->et2phyaddr;
		break;
	}
	bgmac->phyaddr &= BGMAC_PHY_MASK;
	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
		bgmac_err(bgmac, "No PHY found\n");
		err = -ENODEV;
		goto err_netdev_free;
	}
	bgmac_info(bgmac, "Found PHY addr: %d%s\n", bgmac->phyaddr,
		   bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");

	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
		bgmac_err(bgmac, "PCI setup not implemented\n");
		err = -ENOTSUPP;
		goto err_netdev_free;
	}

	bgmac_chip_reset(bgmac);

	/* For Northstar, we have to take all GMAC core out of reset */
	if (ci->id == BCMA_CHIP_ID_BCM4707 ||
	    ci->id == BCMA_CHIP_ID_BCM53018) {
		struct bcma_device *ns_core;
		int ns_gmac;

		/* Northstar has 4 GMAC cores */
		for (ns_gmac = 0; ns_gmac < 4; ns_gmac++) {
			/* As Northstar requirement, we have to reset all GMACs
			 * before accessing one. bgmac_chip_reset() call
			 * bcma_core_enable() for this core. Then the other
			 * three GMACs didn't reset.  We do it here.
			 */
			ns_core = bcma_find_core_unit(core->bus,
						      BCMA_CORE_MAC_GBIT,
						      ns_gmac);
			if (ns_core && !bcma_core_is_enabled(ns_core))
				bcma_core_enable(ns_core, 0);
		}
	}

	err = bgmac_dma_alloc(bgmac);
	if (err) {
		bgmac_err(bgmac, "Unable to alloc memory for DMA\n");
		goto err_netdev_free;
	}

	bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
	if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;

	/* TODO: reset the external phy. Specs are needed */
	bgmac_phy_reset(bgmac);

	bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo &
			       BGMAC_BFL_ENETROBO);
	if (bgmac->has_robosw)
		bgmac_warn(bgmac, "Support for Roboswitch not implemented\n");

	if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
		bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");

	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);

	err = bgmac_mii_register(bgmac);
	if (err) {
		bgmac_err(bgmac, "Cannot register MDIO\n");
		goto err_dma_free;
	}

	net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
	net_dev->hw_features = net_dev->features;
	net_dev->vlan_features = net_dev->features;

	err = register_netdev(bgmac->net_dev);
	if (err) {
		bgmac_err(bgmac, "Cannot register net device\n");
		goto err_mii_unregister;
	}

	netif_carrier_off(net_dev);

	return 0;

err_mii_unregister:
	bgmac_mii_unregister(bgmac);
err_dma_free:
	bgmac_dma_free(bgmac);

err_netdev_free:
	bcma_set_drvdata(core, NULL);
	free_netdev(net_dev);

	return err;
}

static void bgmac_remove(struct bcma_device *core)
{
	struct bgmac *bgmac = bcma_get_drvdata(core);

	unregister_netdev(bgmac->net_dev);
	bgmac_mii_unregister(bgmac);
	netif_napi_del(&bgmac->napi);
	bgmac_dma_free(bgmac);
	bcma_set_drvdata(core, NULL);
	free_netdev(bgmac->net_dev);
}

static struct bcma_driver bgmac_bcma_driver = {
	.name		= KBUILD_MODNAME,
	.id_table	= bgmac_bcma_tbl,
	.probe		= bgmac_probe,
	.remove		= bgmac_remove,
};

static int __init bgmac_init(void)
{
	int err;

	err = bcma_driver_register(&bgmac_bcma_driver);
	if (err)
		return err;
	pr_info("Broadcom 47xx GBit MAC driver loaded\n");

	return 0;
}
Example #27
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;
	struct usb_driver 	*driver = to_usb_driver(udev->dev.driver);

	/* usbnet already took usb runtime pm, so have to enable the feature
	 * for usb interface, otherwise usb_autopm_get_interface may return
	 * failure if USB_SUSPEND(RUNTIME_PM) is enabled.
	 */
	if (!driver->supports_autosuspend) {
		driver->supports_autosuspend = 1;
		pm_runtime_enable(&udev->dev);
	}

	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;
	}

	/* netdev_printk() needs this so do it as early as possible */
	SET_NETDEV_DEV(net, &udev->dev);

	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 &&
		    ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 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");
                /* RMNET devices should always be named "rmnet%d" */
                if ((dev->driver_info->flags & FLAG_RMNET) != 0)
                   strcpy(net->name, "rmnet%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);

	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;
}
static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
	struct rmnet_private *p = netdev_priv(dev);
	unsigned long flags;
	int awake;
	int ret = 0;

	if (netif_queue_stopped(dev)) {
		pr_err("[%s]fatal: rmnet_xmit called when "
			"netif_queue is stopped", dev->name);
		return 0;
	}

	spin_lock_irqsave(&p->lock, flags);
	awake = msm_bam_dmux_ul_power_vote();
	if (!awake) {
		/* send SKB once wakeup is complete */
		netif_stop_queue(dev);
		p->waiting_for_ul_skb = skb;
		spin_unlock_irqrestore(&p->lock, flags);
		ret = 0;
		goto exit;
	}
	spin_unlock_irqrestore(&p->lock, flags);

	ret = _rmnet_xmit(skb, dev);
	if (ret == -EPERM) {
		ret = NETDEV_TX_BUSY;
		goto exit;
	}

	/*
	 * detected SSR a bit early.  shut some things down now, and leave
	 * the rest to the main ssr handling code when that happens later
	 */
	if (ret == -EFAULT) {
		netif_carrier_off(dev);
		dev_kfree_skb_any(skb);
		ret = 0;
		goto exit;
	}

	if (ret == -EAGAIN) {
		/*
		 * This should not happen
		 * EAGAIN means we attempted to overflow the high watermark
		 * Clearly the queue is not stopped like it should be, so
		 * stop it and return BUSY to the TCP/IP framework.  It will
		 * retry this packet with the queue is restarted which happens
		 * in the write_done callback when the low watermark is hit.
		 */
		netif_stop_queue(dev);
		ret = NETDEV_TX_BUSY;
		goto exit;
	}

	spin_lock_irqsave(&p->tx_queue_lock, flags);
	if (msm_bam_dmux_is_ch_full(p->ch_id)) {
		netif_stop_queue(dev);
		DBG0("%s: High WM hit, stopping queue=%p\n",    __func__, skb);
	}
	spin_unlock_irqrestore(&p->tx_queue_lock, flags);

exit:
	msm_bam_dmux_ul_power_unvote();
	return ret;
}
Example #29
0
static int __devinit fs_enet_probe(struct of_device *ofdev,
                                   const struct of_device_id *match)
{
	struct net_device *ndev;
	struct fs_enet_private *fep;
	struct fs_platform_info *fpi;
	const u32 *data;
	const u8 *mac_addr;
	int privsize, len, ret = -ENODEV;

	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
	if (!fpi)
		return -ENOMEM;

	if (!IS_FEC(match)) {
		data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
		if (!data || len != 4)
			goto out_free_fpi;

		fpi->cp_command = *data;
	}

	fpi->rx_ring = 32;
	fpi->tx_ring = 32;
	fpi->rx_copybreak = 240;
	fpi->use_napi = 1;
	fpi->napi_weight = 17;
	fpi->phy_node = of_parse_phandle(ofdev->node, "phy-handle", 0);
	if ((!fpi->phy_node) && (!of_get_property(ofdev->node, "fixed-link",
						  NULL)))
		goto out_free_fpi;

	privsize = sizeof(*fep) +
	           sizeof(struct sk_buff **) *
	           (fpi->rx_ring + fpi->tx_ring);

	ndev = alloc_etherdev(privsize);
	if (!ndev) {
		ret = -ENOMEM;
		goto out_free_fpi;
	}

	SET_NETDEV_DEV(ndev, &ofdev->dev);
	dev_set_drvdata(&ofdev->dev, ndev);

	fep = netdev_priv(ndev);
	fep->dev = &ofdev->dev;
	fep->ndev = ndev;
	fep->fpi = fpi;
	fep->ops = match->data;

	ret = fep->ops->setup_data(ndev);
	if (ret)
		goto out_free_dev;

	fep->rx_skbuff = (struct sk_buff **)&fep[1];
	fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring;

	spin_lock_init(&fep->lock);
	spin_lock_init(&fep->tx_lock);

	mac_addr = of_get_mac_address(ofdev->node);
	if (mac_addr)
		memcpy(ndev->dev_addr, mac_addr, 6);

	ret = fep->ops->allocate_bd(ndev);
	if (ret)
		goto out_cleanup_data;

	fep->rx_bd_base = fep->ring_base;
	fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring;

	fep->tx_ring = fpi->tx_ring;
	fep->rx_ring = fpi->rx_ring;

	ndev->netdev_ops = &fs_enet_netdev_ops;
	ndev->watchdog_timeo = 2 * HZ;
	if (fpi->use_napi)
		netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi,
		               fpi->napi_weight);

	ndev->ethtool_ops = &fs_ethtool_ops;

	init_timer(&fep->phy_timer_list);

	netif_carrier_off(ndev);

	ret = register_netdev(ndev);
	if (ret)
		goto out_free_bd;

	printk(KERN_INFO "%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr);

	return 0;

out_free_bd:
	fep->ops->free_bd(ndev);
out_cleanup_data:
	fep->ops->cleanup_data(ndev);
out_free_dev:
	free_netdev(ndev);
	dev_set_drvdata(&ofdev->dev, NULL);
	of_node_put(fpi->phy_node);
out_free_fpi:
	kfree(fpi);
	return ret;
}
Example #30
0
static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
	const size_t size = sizeof(sync_serial_settings);
	sync_serial_settings new_line;
	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
	struct port *port = dev_to_port(dev);
	unsigned long flags;
	int clk;

	if (cmd != SIOCWANDEV)
		return hdlc_ioctl(dev, ifr, cmd);

	switch(ifr->ifr_settings.type) {
	case IF_GET_IFACE:
		ifr->ifr_settings.type = IF_IFACE_V35;
		if (ifr->ifr_settings.size < size) {
			ifr->ifr_settings.size = size; /* data size wanted */
			return -ENOBUFS;
		}
		memset(&new_line, 0, sizeof(new_line));
		new_line.clock_type = port->clock_type;
		new_line.clock_rate = 2048000; /* FIXME */
		new_line.loopback = port->loopback;
		if (copy_to_user(line, &new_line, size))
			return -EFAULT;
		return 0;

	case IF_IFACE_SYNC_SERIAL:
	case IF_IFACE_V35:
		if(!capable(CAP_NET_ADMIN))
			return -EPERM;
		if (copy_from_user(&new_line, line, size))
			return -EFAULT;

		clk = new_line.clock_type;
		if (port->plat->set_clock)
			clk = port->plat->set_clock(port->id, clk);

		if (clk != CLOCK_EXT && clk != CLOCK_INT)
			return -EINVAL;	/* No such clock setting */

		if (new_line.loopback != 0 && new_line.loopback != 1)
			return -EINVAL;

		port->clock_type = clk; /* Update settings */
		/* FIXME port->clock_rate = new_line.clock_rate */;
		port->loopback = new_line.loopback;

		spin_lock_irqsave(&npe_lock, flags);

		if (dev->flags & IFF_UP)
			hss_config(port);

		if (port->loopback || port->carrier)
			netif_carrier_on(port->netdev);
		else
			netif_carrier_off(port->netdev);
		spin_unlock_irqrestore(&npe_lock, flags);

		return 0;

	default:
		return hdlc_ioctl(dev, ifr, cmd);
	}
}