Ejemplo n.º 1
0
/* This is called if for some node with MAC address addr, we only get frames
 * over one of the slave interfaces. This would indicate an open network ring
 * (i.e. a link has failed somewhere).
 */
void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN],
                      struct hsr_port *port)
{
    struct sk_buff *skb;
    void *msg_head;
    struct hsr_port *master;
    int res;

    skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
    if (!skb)
        goto fail;

    msg_head = genlmsg_put(skb, 0, 0, &hsr_genl_family, 0, HSR_C_RING_ERROR);
    if (!msg_head)
        goto nla_put_failure;

    res = nla_put(skb, HSR_A_NODE_ADDR, ETH_ALEN, addr);
    if (res < 0)
        goto nla_put_failure;

    res = nla_put_u32(skb, HSR_A_IFINDEX, port->dev->ifindex);
    if (res < 0)
        goto nla_put_failure;

    genlmsg_end(skb, msg_head);
    genlmsg_multicast(&hsr_genl_family, skb, 0, 0, GFP_ATOMIC);

    return;

nla_put_failure:
    kfree_skb(skb);

fail:
    rcu_read_lock();
    master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
    netdev_warn(master->dev, "Could not send HSR ring error message\n");
    rcu_read_unlock();
}
Ejemplo n.º 2
0
/*
 * Hard reset the card. This used to pause for the same period that a
 * 8390 reset command required, but that shouldn't be necessary.
 */
static void mcf8390_reset_8390(struct net_device *dev)
{
	unsigned long reset_start_time = jiffies;
	u32 addr = dev->base_addr;
	struct ei_device *ei_local = netdev_priv(dev);

	netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);

	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);

	ei_status.txing = 0;
	ei_status.dmaing = 0;

	/* This check _should_not_ be necessary, omit eventually. */
	while ((ei_inb(addr + NE_EN0_ISR) & ENISR_RESET) == 0) {
		if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
			netdev_warn(dev, "%s: did not complete\n", __func__);
			break;
		}
	}

	ei_outb(ENISR_RESET, addr + NE_EN0_ISR);
}
Ejemplo n.º 3
0
u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
		       u8 *pMCSFilter)
{
	u8		i, j;
	u8		bitMap;
	u8		mcsRate = 0;
	u8		availableMcsRate[16];

	if (pMCSRateSet == NULL || pMCSFilter == NULL) {
		netdev_warn(ieee->dev,
			    "%s(): pMCSRateSet and pMCSFilter are null\n",
			    __func__);
		return false;
	}
	for (i = 0; i < 16; i++)
		availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i];

	for (i = 0; i < 16; i++) {
		if (availableMcsRate[i] != 0)
			break;
	}
	if (i == 16)
		return false;

	for (i = 0; i < 16; i++) {
		if (availableMcsRate[i] != 0) {
			bitMap = availableMcsRate[i];
			for (j = 0; j < 8; j++) {
				if ((bitMap%2) != 0) {
					if (HTMcsToDataRate(ieee, (8*i+j)) >
					    HTMcsToDataRate(ieee, mcsRate))
						mcsRate = (8*i+j);
				}
				bitMap >>= 1;
			}
		}
	}
Ejemplo n.º 4
0
static void hip04_config_port(struct net_device *ndev, u32 speed, u32 duplex)
{
    struct hip04_priv *priv = netdev_priv(ndev);
    u32 val;

    priv->speed = speed;
    priv->duplex = duplex;

    switch (priv->phy_mode) {
    case PHY_INTERFACE_MODE_SGMII:
        if (speed == SPEED_1000)
            val = SGMII_SPEED_1000;
        else if (speed == SPEED_100)
            val = SGMII_SPEED_100;
        else
            val = SGMII_SPEED_10;
        break;
    case PHY_INTERFACE_MODE_MII:
        if (speed == SPEED_100)
            val = MII_SPEED_100;
        else
            val = MII_SPEED_10;
        break;
    default:
        netdev_warn(ndev, "not supported mode\n");
        val = MII_SPEED_10;
        break;
    }
    writel_relaxed(val, priv->base + GE_PORT_MODE);

    val = duplex ? GE_DUPLEX_FULL : GE_DUPLEX_HALF;
    writel_relaxed(val, priv->base + GE_DUPLEX_TYPE);

    val = GE_MODE_CHANGE_EN;
    writel_relaxed(val, priv->base + GE_MODE_CHANGE_REG);
}
Ejemplo n.º 5
0
/* Grab the 8390 specific header. Similar to the block_input routine, but
 * we don't need to be concerned with ring wrap as the header will be at
 * the start of a page, so we optimize accordingly.
 */
static void zorro8390_get_8390_hdr(struct net_device *dev,
				   struct e8390_pkt_hdr *hdr, int ring_page)
{
	int nic_base = dev->base_addr;
	int cnt;
	short *ptrs;

	/* This *shouldn't* happen.
	 * If it does, it's the last thing you'll see
	 */
	if (ei_status.dmaing) {
		netdev_warn(dev,
			    "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
			    __func__, ei_status.dmaing, ei_status.irqlock);
		return;
	}

	ei_status.dmaing |= 0x01;
	z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
	z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
	z_writeb(0, nic_base + NE_EN0_RCNTHI);
	z_writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
	z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
	z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);

	ptrs = (short *)hdr;
	for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
		*ptrs++ = z_readw(NE_BASE + NE_DATAPORT);

	z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr */

	hdr->count = WORDSWAP(hdr->count);

	ei_status.dmaing &= ~0x01;
}
Ejemplo n.º 6
0
static struct adapter *rtw_usb_if1_init(struct dvobj_priv *dvobj,
	struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
{
	struct adapter *padapter = NULL;
	struct net_device *pnetdev = NULL;
	struct net_device *pmondev;
	int status = _FAIL;

	padapter = vzalloc(sizeof(*padapter));
	if (!padapter)
		goto exit;
	padapter->dvobj = dvobj;
	dvobj->if1 = padapter;

	padapter->bDriverStopped = true;
	mutex_init(&padapter->hw_init_mutex);

	pnetdev = rtw_init_netdev(padapter);
	if (!pnetdev)
		goto free_adapter;
	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
	padapter = rtw_netdev_priv(pnetdev);

	if (padapter->registrypriv.monitor_enable) {
		pmondev = rtl88eu_mon_init();
		if (!pmondev)
			netdev_warn(pnetdev, "Failed to initialize monitor interface");
		padapter->pmondev = pmondev;
	}

	padapter->HalData = kzalloc(sizeof(struct hal_data_8188e), GFP_KERNEL);
	if (!padapter->HalData)
		DBG_88E("cant not alloc memory for HAL DATA\n");

	/* step read_chip_version */
	rtw_hal_read_chip_version(padapter);

	/* step usb endpoint mapping */
	rtw_hal_chip_configure(padapter);

	/* step read efuse/eeprom data and get mac_addr */
	rtw_hal_read_chip_info(padapter);

	/* step 5. */
	if (rtw_init_drv_sw(padapter) == _FAIL) {
		RT_TRACE(_module_hci_intfs_c_, _drv_err_,
			 ("Initialize driver software resource Failed!\n"));
		goto free_hal_data;
	}

#ifdef CONFIG_PM
	if (padapter->pwrctrlpriv.bSupportRemoteWakeup) {
		dvobj->pusbdev->do_remote_wakeup = 1;
		pusb_intf->needs_remote_wakeup = 1;
		device_init_wakeup(&pusb_intf->dev, 1);
		pr_debug("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
		pr_debug("\n  padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
			device_may_wakeup(&pusb_intf->dev));
	}
#endif

	/* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto
	 * suspend influence */
	if (usb_autopm_get_interface(pusb_intf) < 0)
		pr_debug("can't get autopm:\n");

	/*  alloc dev name after read efuse. */
	rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
	rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
	memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
	pr_debug("MAC Address from pnetdev->dev_addr =  %pM\n",
		pnetdev->dev_addr);

	/* step 6. Tell the network stack we exist */
	if (register_netdev(pnetdev) != 0) {
		RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("register_netdev() failed\n"));
		goto free_hal_data;
	}

	pr_debug("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
		, padapter->bDriverStopped
		, padapter->bSurpriseRemoved
		, padapter->bup
		, padapter->hw_init_completed
	);

	status = _SUCCESS;

free_hal_data:
	if (status != _SUCCESS)
		kfree(padapter->HalData);
free_adapter:
	if (status != _SUCCESS) {
		if (pnetdev)
			rtw_free_netdev(pnetdev);
		else
			vfree(padapter);
		padapter = NULL;
	}
exit:
	return padapter;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
static int prism2_connect(struct wiphy *wiphy, struct net_device *dev,
			  struct cfg80211_connect_params *sme)
{
	struct wlandevice *wlandev = dev->ml_priv;
	struct ieee80211_channel *channel = sme->channel;
	struct p80211msg_lnxreq_autojoin msg_join;
	u32 did;
	int length = sme->ssid_len;
	int chan = -1;
	int is_wep = (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP40) ||
	    (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_WEP104);
	int result;
	int err = 0;

	/* Set the channel */
	if (channel) {
		chan = ieee80211_frequency_to_channel(channel->center_freq);
		result = prism2_domibset_uint32(wlandev,
						DIDMIB_DOT11PHY_DSSSTABLE_CURRENTCHANNEL,
						chan);
		if (result)
			goto exit;
	}

	/* Set the authorization */
	if ((sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) ||
	    ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && !is_wep))
		msg_join.authtype.data = P80211ENUM_authalg_opensystem;
	else if ((sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) ||
		 ((sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) && is_wep))
		msg_join.authtype.data = P80211ENUM_authalg_sharedkey;
	else
		netdev_warn(dev,
			    "Unhandled authorisation type for connect (%d)\n",
			    sme->auth_type);

	/* Set the encryption - we only support wep */
	if (is_wep) {
		if (sme->key) {
			if (sme->key_idx >= NUM_WEPKEYS) {
				err = -EINVAL;
				goto exit;
			}

			result = prism2_domibset_uint32(wlandev,
				DIDMIB_DOT11SMT_PRIVACYTABLE_WEPDEFAULTKEYID,
				sme->key_idx);
			if (result)
				goto exit;

			/* send key to driver */
			did = didmib_dot11smt_wepdefaultkeystable_key(
					sme->key_idx + 1);
			result = prism2_domibset_pstr32(wlandev,
							did, sme->key_len,
							(u8 *)sme->key);
			if (result)
				goto exit;
		}

		/* Assume we should set privacy invoked and exclude unencrypted
		 * We could possible use sme->privacy here, but the assumption
		 * seems reasonable anyways
		 */
		result = prism2_domibset_uint32(wlandev,
						DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED,
						P80211ENUM_truth_true);
		if (result)
			goto exit;

		result = prism2_domibset_uint32(wlandev,
						DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED,
						P80211ENUM_truth_true);
		if (result)
			goto exit;

	} else {
		/* Assume we should unset privacy invoked
		 * and exclude unencrypted
		 */
		result = prism2_domibset_uint32(wlandev,
						DIDMIB_DOT11SMT_PRIVACYTABLE_PRIVACYINVOKED,
						P80211ENUM_truth_false);
		if (result)
			goto exit;

		result = prism2_domibset_uint32(wlandev,
						DIDMIB_DOT11SMT_PRIVACYTABLE_EXCLUDEUNENCRYPTED,
						P80211ENUM_truth_false);
		if (result)
			goto exit;
	}

	/* Now do the actual join. Note there is no way that I can
	 * see to request a specific bssid
	 */
	msg_join.msgcode = DIDMSG_LNXREQ_AUTOJOIN;

	memcpy(msg_join.ssid.data.data, sme->ssid, length);
	msg_join.ssid.data.len = length;

	result = p80211req_dorequest(wlandev, (u8 *)&msg_join);

exit:
	if (result)
		err = -EFAULT;

	return err;
}
Ejemplo n.º 9
0
/*----------------------------------------------------------------
 * prism2mgmt_scan
 *
 * Initiate a scan for BSSs.
 *
 * This function corresponds to MLME-scan.request and part of
 * MLME-scan.confirm.  As far as I can tell in the standard, there
 * are no restrictions on when a scan.request may be issued.  We have
 * to handle in whatever state the driver/MAC happen to be.
 *
 * Arguments:
 *	wlandev		wlan device structure
 *	msgp		ptr to msg buffer
 *
 * Returns:
 *	0	success and done
 *	<0	success, but we're waiting for something to finish.
 *	>0	an error occurred while handling the message.
 * Side effects:
 *
 * Call context:
 *	process thread  (usually)
 *	interrupt
 *----------------------------------------------------------------
 */
int prism2mgmt_scan(struct wlandevice *wlandev, void *msgp)
{
	int result = 0;
	struct hfa384x *hw = wlandev->priv;
	struct p80211msg_dot11req_scan *msg = msgp;
	u16 roamingmode, word;
	int i, timeout;
	int istmpenable = 0;

	struct hfa384x_host_scan_request_data scanreq;

	/* gatekeeper check */
	if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
				     hw->ident_sta_fw.minor,
				     hw->ident_sta_fw.variant) <
	    HFA384x_FIRMWARE_VERSION(1, 3, 2)) {
		netdev_err(wlandev->netdev,
			   "HostScan not supported with current firmware (<1.3.2).\n");
		result = 1;
		msg->resultcode.data = P80211ENUM_resultcode_not_supported;
		goto exit;
	}

	memset(&scanreq, 0, sizeof(scanreq));

	/* save current roaming mode */
	result = hfa384x_drvr_getconfig16(hw,
					  HFA384x_RID_CNFROAMINGMODE,
					  &roamingmode);
	if (result) {
		netdev_err(wlandev->netdev,
			   "getconfig(ROAMMODE) failed. result=%d\n", result);
		msg->resultcode.data =
		    P80211ENUM_resultcode_implementation_failure;
		goto exit;
	}

	/* drop into mode 3 for the scan */
	result = hfa384x_drvr_setconfig16(hw,
					  HFA384x_RID_CNFROAMINGMODE,
					  HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
	if (result) {
		netdev_err(wlandev->netdev,
			   "setconfig(ROAMINGMODE) failed. result=%d\n",
			   result);
		msg->resultcode.data =
		    P80211ENUM_resultcode_implementation_failure;
		goto exit;
	}

	/* active or passive? */
	if (HFA384x_FIRMWARE_VERSION(hw->ident_sta_fw.major,
				     hw->ident_sta_fw.minor,
				     hw->ident_sta_fw.variant) >
	    HFA384x_FIRMWARE_VERSION(1, 5, 0)) {
		if (msg->scantype.data != P80211ENUM_scantype_active)
			word = msg->maxchanneltime.data;
		else
			word = 0;

		result =
		    hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPASSIVESCANCTRL,
					     word);
		if (result) {
			netdev_warn(wlandev->netdev,
				    "Passive scan not supported with current firmware.  (<1.5.1)\n");
		}
	}

	/* set up the txrate to be 2MBPS. Should be fastest basicrate... */
	word = HFA384x_RATEBIT_2;
	scanreq.tx_rate = cpu_to_le16(word);

	/* set up the channel list */
	word = 0;
	for (i = 0; i < msg->channellist.data.len; i++) {
		u8 channel = msg->channellist.data.data[i];

		if (channel > 14)
			continue;
		/* channel 1 is BIT 0 ... channel 14 is BIT 13 */
		word |= (1 << (channel - 1));
	}
	scanreq.channel_list = cpu_to_le16(word);

	/* set up the ssid, if present. */
	scanreq.ssid.len = cpu_to_le16(msg->ssid.data.len);
	memcpy(scanreq.ssid.data, msg->ssid.data.data, msg->ssid.data.len);

	/* Enable the MAC port if it's not already enabled  */
	result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_PORTSTATUS, &word);
	if (result) {
		netdev_err(wlandev->netdev,
			   "getconfig(PORTSTATUS) failed. result=%d\n", result);
		msg->resultcode.data =
		    P80211ENUM_resultcode_implementation_failure;
		goto exit;
	}
	if (word == HFA384x_PORTSTATUS_DISABLED) {
		__le16 wordbuf[17];

		result = hfa384x_drvr_setconfig16(hw,
					HFA384x_RID_CNFROAMINGMODE,
					HFA384x_ROAMMODE_HOSTSCAN_HOSTROAM);
		if (result) {
			netdev_err(wlandev->netdev,
				   "setconfig(ROAMINGMODE) failed. result=%d\n",
				   result);
			msg->resultcode.data =
			    P80211ENUM_resultcode_implementation_failure;
			goto exit;
		}
		/* Construct a bogus SSID and assign it to OwnSSID and
		 * DesiredSSID
		 */
		wordbuf[0] = cpu_to_le16(WLAN_SSID_MAXLEN);
		get_random_bytes(&wordbuf[1], WLAN_SSID_MAXLEN);
		result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
						wordbuf,
						HFA384x_RID_CNFOWNSSID_LEN);
		if (result) {
			netdev_err(wlandev->netdev, "Failed to set OwnSSID.\n");
			msg->resultcode.data =
			    P80211ENUM_resultcode_implementation_failure;
			goto exit;
		}
		result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
						wordbuf,
						HFA384x_RID_CNFDESIREDSSID_LEN);
		if (result) {
			netdev_err(wlandev->netdev,
				   "Failed to set DesiredSSID.\n");
			msg->resultcode.data =
			    P80211ENUM_resultcode_implementation_failure;
			goto exit;
		}
		/* bsstype */
		result = hfa384x_drvr_setconfig16(hw,
						  HFA384x_RID_CNFPORTTYPE,
						  HFA384x_PORTTYPE_IBSS);
		if (result) {
			netdev_err(wlandev->netdev,
				   "Failed to set CNFPORTTYPE.\n");
			msg->resultcode.data =
			    P80211ENUM_resultcode_implementation_failure;
			goto exit;
		}
		/* ibss options */
		result = hfa384x_drvr_setconfig16(hw,
					HFA384x_RID_CREATEIBSS,
					HFA384x_CREATEIBSS_JOINCREATEIBSS);
		if (result) {
			netdev_err(wlandev->netdev,
				   "Failed to set CREATEIBSS.\n");
			msg->resultcode.data =
			    P80211ENUM_resultcode_implementation_failure;
			goto exit;
		}
		result = hfa384x_drvr_enable(hw, 0);
		if (result) {
			netdev_err(wlandev->netdev,
				   "drvr_enable(0) failed. result=%d\n",
				   result);
			msg->resultcode.data =
			    P80211ENUM_resultcode_implementation_failure;
			goto exit;
		}
		istmpenable = 1;
	}

	/* Figure out our timeout first Kus, then HZ */
	timeout = msg->channellist.data.len * msg->maxchanneltime.data;
	timeout = (timeout * HZ) / 1000;

	/* Issue the scan request */
	hw->scanflag = 0;

	result = hfa384x_drvr_setconfig(hw,
					HFA384x_RID_HOSTSCAN, &scanreq,
					sizeof(scanreq));
	if (result) {
		netdev_err(wlandev->netdev,
			   "setconfig(SCANREQUEST) failed. result=%d\n",
			   result);
		msg->resultcode.data =
		    P80211ENUM_resultcode_implementation_failure;
		goto exit;
	}

	/* sleep until info frame arrives */
	wait_event_interruptible_timeout(hw->cmdq, hw->scanflag, timeout);

	msg->numbss.status = P80211ENUM_msgitem_status_data_ok;
	if (hw->scanflag == -1)
		hw->scanflag = 0;

	msg->numbss.data = hw->scanflag;

	hw->scanflag = 0;

	/* Disable port if we temporarily enabled it. */
	if (istmpenable) {
		result = hfa384x_drvr_disable(hw, 0);
		if (result) {
			netdev_err(wlandev->netdev,
				   "drvr_disable(0) failed. result=%d\n",
				   result);
			msg->resultcode.data =
			    P80211ENUM_resultcode_implementation_failure;
			goto exit;
		}
	}

	/* restore original roaming mode */
	result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFROAMINGMODE,
					  roamingmode);
	if (result) {
		netdev_err(wlandev->netdev,
			   "setconfig(ROAMMODE) failed. result=%d\n", result);
		msg->resultcode.data =
		    P80211ENUM_resultcode_implementation_failure;
		goto exit;
	}

	result = 0;
	msg->resultcode.data = P80211ENUM_resultcode_success;

exit:
	msg->resultcode.status = P80211ENUM_msgitem_status_data_ok;

	return result;
}
Ejemplo n.º 10
0
/* Stop the Ethernet port activity */
static void mvneta_port_down(struct mvneta_port *pp)
{
	u32 val;
	int count;

	/* Stop Rx port activity. Check port Rx activity. */
	val = mvreg_read(pp, MVNETA_RXQ_CMD) & MVNETA_RXQ_ENABLE_MASK;

	/* Issue stop command for active channels only */
	if (val != 0)
		mvreg_write(pp, MVNETA_RXQ_CMD,
			    val << MVNETA_RXQ_DISABLE_SHIFT);

	/* Wait for all Rx activity to terminate. */
	count = 0;
	do {
		if (count++ >= MVNETA_RX_DISABLE_TIMEOUT_MSEC) {
			netdev_warn(pp->dev,
				    "TIMEOUT for RX stopped ! rx_queue_cmd: 0x08%x\n",
				    val);
			break;
		}
		mdelay(1);

		val = mvreg_read(pp, MVNETA_RXQ_CMD);
	} while (val & 0xff);

	/* Stop Tx port activity. Check port Tx activity. Issue stop
	 * command for active channels only
	 */
	val = (mvreg_read(pp, MVNETA_TXQ_CMD)) & MVNETA_TXQ_ENABLE_MASK;

	if (val != 0)
		mvreg_write(pp, MVNETA_TXQ_CMD,
			    (val << MVNETA_TXQ_DISABLE_SHIFT));

	/* Wait for all Tx activity to terminate. */
	count = 0;
	do {
		if (count++ >= MVNETA_TX_DISABLE_TIMEOUT_MSEC) {
			netdev_warn(pp->dev,
				    "TIMEOUT for TX stopped status=0x%08x\n",
				    val);
			break;
		}
		mdelay(1);

		/* Check TX Command reg that all Txqs are stopped */
		val = mvreg_read(pp, MVNETA_TXQ_CMD);

	} while (val & 0xff);

	/* Double check to verify that TX FIFO is empty */
	count = 0;
	do {
		if (count++ >= MVNETA_TX_FIFO_EMPTY_TIMEOUT) {
			netdev_warn(pp->dev,
				    "TX FIFO empty timeout status=0x08%x\n",
				    val);
			break;
		}
		mdelay(1);

		val = mvreg_read(pp, MVNETA_PORT_STATUS);
	} while (!(val & MVNETA_TX_FIFO_EMPTY) &&
		 (val & MVNETA_TX_IN_PRGRS));

	udelay(200);
}
Ejemplo n.º 11
0
static netdev_tx_t
qcaspi_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
{
	u32 frame_len;
	u8 *ptmp;
	struct qcaspi *qca = netdev_priv(dev);
	u16 new_tail;
	struct sk_buff *tskb;
	u8 pad_len = 0;

	if (skb->len < QCAFRM_ETHMINLEN)
		pad_len = QCAFRM_ETHMINLEN - skb->len;

	if (qca->txr.skb[qca->txr.tail]) {
		netdev_warn(qca->net_dev, "queue was unexpectedly full!\n");
		netif_stop_queue(qca->net_dev);
		qca->stats.ring_full++;
		return NETDEV_TX_BUSY;
	}

	if ((skb_headroom(skb) < QCAFRM_HEADER_LEN) ||
	    (skb_tailroom(skb) < QCAFRM_FOOTER_LEN + pad_len)) {
		tskb = skb_copy_expand(skb, QCAFRM_HEADER_LEN,
				       QCAFRM_FOOTER_LEN + pad_len, GFP_ATOMIC);
		if (!tskb) {
			netdev_dbg(qca->net_dev, "could not allocate tx_buff\n");
			qca->stats.out_of_mem++;
			return NETDEV_TX_BUSY;
		}
		dev_kfree_skb(skb);
		skb = tskb;
	}

	frame_len = skb->len + pad_len;

	ptmp = skb_push(skb, QCAFRM_HEADER_LEN);
	qcafrm_create_header(ptmp, frame_len);

	if (pad_len) {
		ptmp = skb_put(skb, pad_len);
		memset(ptmp, 0, pad_len);
	}

	ptmp = skb_put(skb, QCAFRM_FOOTER_LEN);
	qcafrm_create_footer(ptmp);

	netdev_dbg(qca->net_dev, "Tx-ing packet: Size: 0x%08x\n",
		   skb->len);

	qca->txr.size += skb->len + QCASPI_HW_PKT_LEN;

	new_tail = qca->txr.tail + 1;
	if (new_tail >= qca->txr.count)
		new_tail = 0;

	qca->txr.skb[qca->txr.tail] = skb;
	qca->txr.tail = new_tail;

	if (!qcaspi_tx_ring_has_space(&qca->txr)) {
		netif_stop_queue(qca->net_dev);
		qca->stats.ring_full++;
	}

	dev->trans_start = jiffies;

	if (qca->spi_thread &&
	    qca->spi_thread->state != TASK_RUNNING)
		wake_up_process(qca->spi_thread);

	return NETDEV_TX_OK;
}
Ejemplo n.º 12
0
static void media_check(unsigned long arg)
{
    struct net_device *dev = (struct net_device *)(arg);
    struct el3_private *lp = netdev_priv(dev);
    unsigned int ioaddr = dev->base_addr;
    u16 media, errs;
    unsigned long flags;

    if (!netif_device_present(dev)) goto reschedule;

    /* Check for pending interrupt with expired latency timer: with
       this, we can limp along even if the interrupt is blocked */
    if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
	(inb(ioaddr + EL3_TIMER) == 0xff)) {
	if (!lp->fast_poll)
		netdev_warn(dev, "interrupt(s) dropped!\n");

	local_irq_save(flags);
	el3_interrupt(dev->irq, dev);
	local_irq_restore(flags);

	lp->fast_poll = HZ;
    }
    if (lp->fast_poll) {
	lp->fast_poll--;
	lp->media.expires = jiffies + HZ/100;
	add_timer(&lp->media);
	return;
    }

    /* lp->lock guards the EL3 window. Window should always be 1 except
       when the lock is held */
    spin_lock_irqsave(&lp->lock, flags);
    EL3WINDOW(4);
    media = inw(ioaddr+WN4_MEDIA) & 0xc810;

    /* Ignore collisions unless we've had no irq's recently */
    if (time_before(jiffies, lp->last_irq + HZ)) {
	media &= ~0x0010;
    } else {
	/* Try harder to detect carrier errors */
	EL3WINDOW(6);
	outw(StatsDisable, ioaddr + EL3_CMD);
	errs = inb(ioaddr + 0);
	outw(StatsEnable, ioaddr + EL3_CMD);
	dev->stats.tx_carrier_errors += errs;
	if (errs || (lp->media_status & 0x0010)) media |= 0x0010;
    }

    if (media != lp->media_status) {
	if ((media & lp->media_status & 0x8000) &&
	    ((lp->media_status ^ media) & 0x0800))
		netdev_info(dev, "%s link beat\n",
			    (lp->media_status & 0x0800 ? "lost" : "found"));
	else if ((media & lp->media_status & 0x4000) &&
		 ((lp->media_status ^ media) & 0x0010))
		netdev_info(dev, "coax cable %s\n",
			    (lp->media_status & 0x0010 ? "ok" : "problem"));
	if (dev->if_port == 0) {
	    if (media & 0x8000) {
		if (media & 0x0800)
			netdev_info(dev, "flipped to 10baseT\n");
		else
			tc589_set_xcvr(dev, 2);
	    } else if (media & 0x4000) {
		if (media & 0x0010)
		    tc589_set_xcvr(dev, 1);
		else
		    netdev_info(dev, "flipped to 10base2\n");
	    }
	}
	lp->media_status = media;
    }

    EL3WINDOW(1);
    spin_unlock_irqrestore(&lp->lock, flags);

reschedule:
    lp->media.expires = jiffies + HZ;
    add_timer(&lp->media);
}
Ejemplo n.º 13
0
static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
{
	struct can_priv *priv = netdev_priv(dev);
	const struct can_bittiming_const *btc = priv->bittiming_const;
	long rate, best_rate = 0;
	long best_error = 1000000000, error = 0;
	int best_tseg = 0, best_brp = 0, brp = 0;
	int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
	int spt_error = 1000, spt = 0, sampl_pt;
	u64 v64;

	if (!priv->bittiming_const)
		return -ENOTSUPP;

	
	if (bt->sample_point) {
		sampl_pt = bt->sample_point;
	} else {
		if (bt->bitrate > 800000)
			sampl_pt = 750;
		else if (bt->bitrate > 500000)
			sampl_pt = 800;
		else
			sampl_pt = 875;
	}

	
	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
		tsegall = 1 + tseg / 2;
		
		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
		
		brp = (brp / btc->brp_inc) * btc->brp_inc;
		if ((brp < btc->brp_min) || (brp > btc->brp_max))
			continue;
		rate = priv->clock.freq / (brp * tsegall);
		error = bt->bitrate - rate;
		
		if (error < 0)
			error = -error;
		if (error > best_error)
			continue;
		best_error = error;
		if (error == 0) {
			spt = can_update_spt(btc, sampl_pt, tseg / 2,
					     &tseg1, &tseg2);
			error = sampl_pt - spt;
			if (error < 0)
				error = -error;
			if (error > spt_error)
				continue;
			spt_error = error;
		}
		best_tseg = tseg / 2;
		best_brp = brp;
		best_rate = rate;
		if (error == 0)
			break;
	}

	if (best_error) {
		
		error = (best_error * 1000) / bt->bitrate;
		if (error > CAN_CALC_MAX_ERROR) {
			netdev_err(dev,
				   "bitrate error %ld.%ld%% too high\n",
				   error / 10, error % 10);
			return -EDOM;
		} else {
			netdev_warn(dev, "bitrate error %ld.%ld%%\n",
				    error / 10, error % 10);
		}
	}

	
	bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg,
					  &tseg1, &tseg2);

	v64 = (u64)best_brp * 1000000000UL;
	do_div(v64, priv->clock.freq);
	bt->tq = (u32)v64;
	bt->prop_seg = tseg1 / 2;
	bt->phase_seg1 = tseg1 - bt->prop_seg;
	bt->phase_seg2 = tseg2;

	
	if (!bt->sjw || !btc->sjw_max)
		bt->sjw = 1;
	else {
		
		if (bt->sjw > btc->sjw_max)
			bt->sjw = btc->sjw_max;
		
		if (tseg2 < bt->sjw)
			bt->sjw = tseg2;
	}

	bt->brp = best_brp;
	
	bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));

	return 0;
}
Ejemplo n.º 14
0
Archivo: eth.c Proyecto: krzk/linux
/**
 * eth_change_mtu - set new MTU size
 * @dev: network device
 * @new_mtu: new Maximum Transfer Unit
 *
 * Allow changing MTU size. Needs to be overridden for devices
 * supporting jumbo frames.
 */
int eth_change_mtu(struct net_device *dev, int new_mtu)
{
	netdev_warn(dev, "%s is deprecated\n", __func__);
	dev->mtu = new_mtu;
	return 0;
}
Ejemplo n.º 15
0
static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
	struct ems_usb *dev = netdev_priv(netdev);
	struct ems_tx_urb_context *context = NULL;
	struct net_device_stats *stats = &netdev->stats;
	struct can_frame *cf = (struct can_frame *)skb->data;
	struct ems_cpc_msg *msg;
	struct urb *urb;
	u8 *buf;
	int i, err;
	size_t size = CPC_HEADER_SIZE + CPC_MSG_HEADER_LEN
			+ sizeof(struct cpc_can_msg);

	if (can_dropped_invalid_skb(netdev, skb))
		return NETDEV_TX_OK;

	/* create a URB, and a buffer for it, and copy the data to the URB */
	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb) {
		netdev_err(netdev, "No memory left for URBs\n");
		goto nomem;
	}

	buf = usb_alloc_coherent(dev->udev, size, GFP_ATOMIC, &urb->transfer_dma);
	if (!buf) {
		netdev_err(netdev, "No memory left for USB buffer\n");
		usb_free_urb(urb);
		goto nomem;
	}

	msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];

	msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK;
	msg->msg.can_msg.length = cf->can_dlc;

	if (cf->can_id & CAN_RTR_FLAG) {
		msg->type = cf->can_id & CAN_EFF_FLAG ?
			CPC_CMD_TYPE_EXT_RTR_FRAME : CPC_CMD_TYPE_RTR_FRAME;

		msg->length = CPC_CAN_MSG_MIN_SIZE;
	} else {
		msg->type = cf->can_id & CAN_EFF_FLAG ?
			CPC_CMD_TYPE_EXT_CAN_FRAME : CPC_CMD_TYPE_CAN_FRAME;

		for (i = 0; i < cf->can_dlc; i++)
			msg->msg.can_msg.msg[i] = cf->data[i];

		msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc;
	}

	/* Respect byte order */
	msg->msg.can_msg.id = cpu_to_le32(msg->msg.can_msg.id);

	for (i = 0; i < MAX_TX_URBS; i++) {
		if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) {
			context = &dev->tx_contexts[i];
			break;
		}
	}

	/*
	 * May never happen! When this happens we'd more URBs in flight as
	 * allowed (MAX_TX_URBS).
	 */
	if (!context) {
		usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
		usb_free_urb(urb);

		netdev_warn(netdev, "couldn't find free context\n");

		return NETDEV_TX_BUSY;
	}

	context->dev = dev;
	context->echo_index = i;
	context->dlc = cf->can_dlc;

	usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), buf,
			  size, ems_usb_write_bulk_callback, context);
	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
	usb_anchor_urb(urb, &dev->tx_submitted);

	can_put_echo_skb(skb, netdev, context->echo_index);

	atomic_inc(&dev->active_tx_urbs);

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (unlikely(err)) {
		can_free_echo_skb(netdev, context->echo_index);

		usb_unanchor_urb(urb);
		usb_free_coherent(dev->udev, size, buf, urb->transfer_dma);
		dev_kfree_skb(skb);

		atomic_dec(&dev->active_tx_urbs);

		if (err == -ENODEV) {
			netif_device_detach(netdev);
		} else {
			netdev_warn(netdev, "failed tx_urb %d\n", err);

			stats->tx_dropped++;
		}
	} else {
		netdev->trans_start = jiffies;

		/* Slow down tx path */
		if (atomic_read(&dev->active_tx_urbs) >= MAX_TX_URBS ||
		    dev->free_slots < 5) {
			netif_stop_queue(netdev);
		}
	}

	/*
	 * Release our reference to this URB, the USB core will eventually free
	 * it entirely.
	 */
	usb_free_urb(urb);

	return NETDEV_TX_OK;

nomem:
	dev_kfree_skb(skb);
	stats->tx_dropped++;

	return NETDEV_TX_OK;
}
Ejemplo n.º 16
0
static int bond_changelink(struct net_device *bond_dev,
			   struct nlattr *tb[], struct nlattr *data[])
{
	struct bonding *bond = netdev_priv(bond_dev);
	struct bond_opt_value newval;
	int miimon = 0;
	int err;

	if (!data)
		return 0;

	if (data[IFLA_BOND_MODE]) {
		int mode = nla_get_u8(data[IFLA_BOND_MODE]);

		bond_opt_initval(&newval, mode);
		err = __bond_opt_set(bond, BOND_OPT_MODE, &newval);
		if (err)
			return err;
	}
	if (data[IFLA_BOND_ACTIVE_SLAVE]) {
		int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
		struct net_device *slave_dev;
		char *active_slave = "";

		if (ifindex != 0) {
			slave_dev = __dev_get_by_index(dev_net(bond_dev),
						       ifindex);
			if (!slave_dev)
				return -ENODEV;
			active_slave = slave_dev->name;
		}
		bond_opt_initstr(&newval, active_slave);
		err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval);
		if (err)
			return err;
	}
	if (data[IFLA_BOND_MIIMON]) {
		miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);

		bond_opt_initval(&newval, miimon);
		err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval);
		if (err)
			return err;
	}
	if (data[IFLA_BOND_UPDELAY]) {
		int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);

		bond_opt_initval(&newval, updelay);
		err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval);
		if (err)
			return err;
	}
	if (data[IFLA_BOND_DOWNDELAY]) {
		int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);

		bond_opt_initval(&newval, downdelay);
		err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval);
		if (err)
			return err;
	}
	if (data[IFLA_BOND_USE_CARRIER]) {
		int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);

		bond_opt_initval(&newval, use_carrier);
		err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval);
		if (err)
			return err;
	}
	if (data[IFLA_BOND_ARP_INTERVAL]) {
		int arp_interval = nla_get_u32(data[IFLA_BOND_ARP_INTERVAL]);

		if (arp_interval && miimon) {
			netdev_err(bond->dev, "ARP monitoring cannot be used with MII monitoring\n");
			return -EINVAL;
		}

		bond_opt_initval(&newval, arp_interval);
		err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval);
		if (err)
			return err;
	}
	if (data[IFLA_BOND_ARP_IP_TARGET]) {
		struct nlattr *attr;
		int i = 0, rem;

		bond_option_arp_ip_targets_clear(bond);
		nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
			__be32 target;

			if (nla_len(attr) < sizeof(target))
				return -EINVAL;

			target = nla_get_be32(attr);

			bond_opt_initval(&newval, (__force u64)target);
			err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
					     &newval);
			if (err)
				break;
			i++;
		}
		if (i == 0 && bond->params.arp_interval)
			netdev_warn(bond->dev, "Removing last arp target with arp_interval on\n");
		if (err)
			return err;
	}
Ejemplo n.º 17
0
static void bfin_mac_adjust_link(struct net_device *dev)
{
	struct bfin_mac_local *lp = netdev_priv(dev);
	struct phy_device *phydev = lp->phydev;
	unsigned long flags;
	int new_state = 0;

	spin_lock_irqsave(&lp->lock, flags);
	if (phydev->link) {
		if (phydev->duplex != lp->old_duplex) {
			u32 opmode = bfin_read_EMAC_OPMODE();
			new_state = 1;

			if (phydev->duplex)
				opmode |= FDMODE;
			else
				opmode &= ~(FDMODE);

			bfin_write_EMAC_OPMODE(opmode);
			lp->old_duplex = phydev->duplex;
		}

		if (phydev->speed != lp->old_speed) {
			if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
				u32 opmode = bfin_read_EMAC_OPMODE();
				switch (phydev->speed) {
				case 10:
					opmode |= RMII_10;
					break;
				case 100:
					opmode &= ~RMII_10;
					break;
				default:
					netdev_warn(dev,
						"Ack! Speed (%d) is not 10/100!\n",
						phydev->speed);
					break;
				}
				bfin_write_EMAC_OPMODE(opmode);
			}

			new_state = 1;
			lp->old_speed = phydev->speed;
		}

		if (!lp->old_link) {
			new_state = 1;
			lp->old_link = 1;
		}
	} else if (lp->old_link) {
		new_state = 1;
		lp->old_link = 0;
		lp->old_speed = 0;
		lp->old_duplex = -1;
	}

	if (new_state) {
		u32 opmode = bfin_read_EMAC_OPMODE();
		phy_print_status(phydev);
		pr_debug("EMAC_OPMODE = 0x%08x\n", opmode);
	}

	spin_unlock_irqrestore(&lp->lock, flags);
}
Ejemplo n.º 18
0
static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt)
{
	struct can_priv *priv = netdev_priv(dev);
	const struct can_bittiming_const *btc = priv->bittiming_const;
	long rate, best_rate = 0;
	long best_error = 1000000000, error = 0;
	int best_tseg = 0, best_brp = 0, brp = 0;
	int tsegall, tseg = 0, tseg1 = 0, tseg2 = 0;
	int spt_error = 1000, spt = 0, sampl_pt;
	u64 v64;

	if (!priv->bittiming_const)
		return -ENOTSUPP;

	/* Use CIA recommended sample points */
	if (bt->sample_point) {
		sampl_pt = bt->sample_point;
	} else {
		if (bt->bitrate > 800000)
			sampl_pt = 750;
		else if (bt->bitrate > 500000)
			sampl_pt = 800;
		else
			sampl_pt = 875;
	}

	/* tseg even = round down, odd = round up */
	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
		tsegall = 1 + tseg / 2;
		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
		/* chose brp step which is possible in system */
		brp = (brp / btc->brp_inc) * btc->brp_inc;
		if ((brp < btc->brp_min) || (brp > btc->brp_max))
			continue;
		rate = priv->clock.freq / (brp * tsegall);
		error = bt->bitrate - rate;
		/* tseg brp biterror */
		if (error < 0)
			error = -error;
		if (error > best_error)
			continue;
		best_error = error;
		if (error == 0) {
			spt = can_update_spt(btc, sampl_pt, tseg / 2,
					     &tseg1, &tseg2);
			error = sampl_pt - spt;
			if (error < 0)
				error = -error;
			if (error > spt_error)
				continue;
			spt_error = error;
		}
		best_tseg = tseg / 2;
		best_brp = brp;
		best_rate = rate;
		if (error == 0)
			break;
	}

	if (best_error) {
		/* Error in one-tenth of a percent */
		error = (best_error * 1000) / bt->bitrate;
		if (error > CAN_CALC_MAX_ERROR) {
			netdev_err(dev,
				   "bitrate error %ld.%ld%% too high\n",
				   error / 10, error % 10);
			return -EDOM;
		} else {
			netdev_warn(dev, "bitrate error %ld.%ld%%\n",
				    error / 10, error % 10);
		}
	}

	/* real sample point */
	bt->sample_point = can_update_spt(btc, sampl_pt, best_tseg,
					  &tseg1, &tseg2);

	v64 = (u64)best_brp * 1000000000UL;
	do_div(v64, priv->clock.freq);
	bt->tq = (u32)v64;
	bt->prop_seg = tseg1 / 2;
	bt->phase_seg1 = tseg1 - bt->prop_seg;
	bt->phase_seg2 = tseg2;

	/* check for sjw user settings */
	if (!bt->sjw || !btc->sjw_max)
		bt->sjw = 1;
	else {
		/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
		if (bt->sjw > btc->sjw_max)
			bt->sjw = btc->sjw_max;
		/* bt->sjw must not be higher than tseg2 */
		if (tseg2 < bt->sjw)
			bt->sjw = tseg2;
	}

	bt->brp = best_brp;
	/* real bit-rate */
	bt->bitrate = priv->clock.freq / (bt->brp * (tseg1 + tseg2 + 1));

	return 0;
}
Ejemplo n.º 19
0
static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
{
	struct rtllib_device *ieee = (struct rtllib_device *)
				     netdev_priv_rsl(dev);
	struct rtllib_txb *txb = NULL;
	struct rtllib_hdr_3addrqos *frag_hdr;
	int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
	unsigned long flags;
	struct net_device_stats *stats = &ieee->stats;
	int ether_type = 0, encrypt;
	int bytes, fc, qos_ctl = 0, hdr_len;
	struct sk_buff *skb_frag;
	struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */
		.duration_id = 0,
		.seq_ctl = 0,
		.qos_ctl = 0
	};
	int qos_actived = ieee->current_network.qos_data.active;
	u8 dest[ETH_ALEN];
	u8 src[ETH_ALEN];
	struct lib80211_crypt_data *crypt = NULL;
	struct cb_desc *tcb_desc;
	u8 bIsMulticast = false;
	u8 IsAmsdu = false;
	bool	bdhcp = false;

	spin_lock_irqsave(&ieee->lock, flags);

	/* If there is no driver handler to take the TXB, don't bother
	 * creating it...
	 */
	if ((!ieee->hard_start_xmit && !(ieee->softmac_features &
	   IEEE_SOFTMAC_TX_QUEUE)) ||
	   ((!ieee->softmac_data_hard_start_xmit &&
	   (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
		netdev_warn(ieee->dev, "No xmit handler.\n");
		goto success;
	}


	if (likely(ieee->raw_tx == 0)) {
		if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
			netdev_warn(ieee->dev, "skb too small (%d).\n",
				    skb->len);
			goto success;
		}
		/* Save source and destination addresses */
		ether_addr_copy(dest, skb->data);
		ether_addr_copy(src, skb->data + ETH_ALEN);

		memset(skb->cb, 0, sizeof(skb->cb));
		ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);

		if (ieee->iw_mode == IW_MODE_MONITOR) {
			txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
			if (unlikely(!txb)) {
				netdev_warn(ieee->dev,
					    "Could not allocate TXB\n");
				goto failed;
			}

			txb->encrypted = 0;
			txb->payload_size = cpu_to_le16(skb->len);
			skb_put_data(txb->fragments[0], skb->data, skb->len);

			goto success;
		}

		if (skb->len > 282) {
			if (ether_type == ETH_P_IP) {
				const struct iphdr *ip = (struct iphdr *)
					((u8 *)skb->data+14);
				if (ip->protocol == IPPROTO_UDP) {
					struct udphdr *udp;

					udp = (struct udphdr *)((u8 *)ip +
					      (ip->ihl << 2));
					if (((((u8 *)udp)[1] == 68) &&
					   (((u8 *)udp)[3] == 67)) ||
					   ((((u8 *)udp)[1] == 67) &&
					   (((u8 *)udp)[3] == 68))) {
						bdhcp = true;
						ieee->LPSDelayCnt = 200;
					}
				}
			} else if (ether_type == ETH_P_ARP) {
				netdev_info(ieee->dev,
					    "=================>DHCP Protocol start tx ARP pkt!!\n");
				bdhcp = true;
				ieee->LPSDelayCnt =
					 ieee->current_network.tim.tim_count;
			}
		}

		skb->priority = rtllib_classify(skb, IsAmsdu);
		crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
		encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
			ieee->host_encrypt && crypt && crypt->ops;
		if (!encrypt && ieee->ieee802_1x &&
		    ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
			stats->tx_dropped++;
			goto success;
		}
		if (crypt && !encrypt && ether_type == ETH_P_PAE) {
			struct eapol *eap = (struct eapol *)(skb->data +
				sizeof(struct ethhdr) - SNAP_SIZE -
				sizeof(u16));
			netdev_dbg(ieee->dev,
				   "TX: IEEE 802.11 EAPOL frame: %s\n",
				   eap_get_type(eap->type));
		}

		/* Advance the SKB to the start of the payload */
		skb_pull(skb, sizeof(struct ethhdr));

		/* Determine total amount of storage required for TXB packets */
		bytes = skb->len + SNAP_SIZE + sizeof(u16);

		if (encrypt)
			fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP;
		else
			fc = RTLLIB_FTYPE_DATA;

		if (qos_actived)
			fc |= RTLLIB_STYPE_QOS_DATA;
		else
			fc |= RTLLIB_STYPE_DATA;

		if (ieee->iw_mode == IW_MODE_INFRA) {
			fc |= RTLLIB_FCTL_TODS;
			/* To DS: Addr1 = BSSID, Addr2 = SA,
			 * Addr3 = DA
			 */
			ether_addr_copy(header.addr1,
					ieee->current_network.bssid);
			ether_addr_copy(header.addr2, src);
			if (IsAmsdu)
				ether_addr_copy(header.addr3,
						ieee->current_network.bssid);
			else
				ether_addr_copy(header.addr3, dest);
		} else if (ieee->iw_mode == IW_MODE_ADHOC) {
			/* not From/To DS: Addr1 = DA, Addr2 = SA,
			 * Addr3 = BSSID
			 */
			ether_addr_copy(header.addr1, dest);
			ether_addr_copy(header.addr2, src);
			ether_addr_copy(header.addr3,
					ieee->current_network.bssid);
		}

		bIsMulticast = is_multicast_ether_addr(header.addr1);

		header.frame_ctl = cpu_to_le16(fc);

		/* Determine fragmentation size based on destination (multicast
		 * and broadcast are not fragmented)
		 */
		if (bIsMulticast) {
			frag_size = MAX_FRAG_THRESHOLD;
			qos_ctl |= QOS_CTL_NOTCONTAIN_ACK;
		} else {
			frag_size = ieee->fts;
			qos_ctl = 0;
		}

		if (qos_actived) {
			hdr_len = RTLLIB_3ADDR_LEN + 2;

			/* in case we are a client verify acm is not set for this ac */
			while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) {
				netdev_info(ieee->dev, "skb->priority = %x\n",
						skb->priority);
				if (wme_downgrade_ac(skb))
					break;
				netdev_info(ieee->dev, "converted skb->priority = %x\n",
					   skb->priority);
			}

			qos_ctl |= skb->priority;
			header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID);

		} else {
			hdr_len = RTLLIB_3ADDR_LEN;
		}
		/* Determine amount of payload per fragment.  Regardless of if
		 * this stack is providing the full 802.11 header, one will
		 * eventually be affixed to this fragment -- so we must account
		 * for it when determining the amount of payload space.
		 */
		bytes_per_frag = frag_size - hdr_len;
		if (ieee->config &
		   (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
			bytes_per_frag -= RTLLIB_FCS_LEN;

		/* Each fragment may need to have room for encrypting
		 * pre/postfix
		 */
		if (encrypt) {
			bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
				crypt->ops->extra_mpdu_postfix_len +
				crypt->ops->extra_msdu_prefix_len +
				crypt->ops->extra_msdu_postfix_len;
		}
		/* Number of fragments is the total bytes_per_frag /
		 * payload_per_fragment
		 */
		nr_frags = bytes / bytes_per_frag;
		bytes_last_frag = bytes % bytes_per_frag;
		if (bytes_last_frag)
			nr_frags++;
		else
			bytes_last_frag = bytes_per_frag;

		/* When we allocate the TXB we allocate enough space for the
		 * reserve and full fragment bytes (bytes_per_frag doesn't
		 * include prefix, postfix, header, FCS, etc.)
		 */
		txb = rtllib_alloc_txb(nr_frags, frag_size +
				       ieee->tx_headroom, GFP_ATOMIC);
		if (unlikely(!txb)) {
			netdev_warn(ieee->dev, "Could not allocate TXB\n");
			goto failed;
		}
		txb->encrypted = encrypt;
		txb->payload_size = cpu_to_le16(bytes);

		if (qos_actived)
			txb->queue_index = UP2AC(skb->priority);
		else
			txb->queue_index = WME_AC_BE;

		for (i = 0; i < nr_frags; i++) {
			skb_frag = txb->fragments[i];
			tcb_desc = (struct cb_desc *)(skb_frag->cb +
				    MAX_DEV_ADDR_SIZE);
			if (qos_actived) {
				skb_frag->priority = skb->priority;
				tcb_desc->queue_index =  UP2AC(skb->priority);
			} else {
				skb_frag->priority = WME_AC_BE;
				tcb_desc->queue_index = WME_AC_BE;
			}
			skb_reserve(skb_frag, ieee->tx_headroom);

			if (encrypt) {
				if (ieee->hwsec_active)
					tcb_desc->bHwSec = 1;
				else
					tcb_desc->bHwSec = 0;
				skb_reserve(skb_frag,
					    crypt->ops->extra_mpdu_prefix_len +
					    crypt->ops->extra_msdu_prefix_len);
			} else {
				tcb_desc->bHwSec = 0;
			}
			frag_hdr = skb_put_data(skb_frag, &header, hdr_len);

			/* If this is not the last fragment, then add the
			 * MOREFRAGS bit to the frame control
			 */
			if (i != nr_frags - 1) {
				frag_hdr->frame_ctl = cpu_to_le16(
					fc | RTLLIB_FCTL_MOREFRAGS);
				bytes = bytes_per_frag;

			} else {
				/* The last fragment has the remaining length */
				bytes = bytes_last_frag;
			}
			if ((qos_actived) && (!bIsMulticast)) {
				frag_hdr->seq_ctl =
					 cpu_to_le16(rtllib_query_seqnum(ieee, skb_frag,
							     header.addr1));
				frag_hdr->seq_ctl =
					 cpu_to_le16(le16_to_cpu(frag_hdr->seq_ctl)<<4 | i);
			} else {
				frag_hdr->seq_ctl =
					 cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
			}
			/* Put a SNAP header on the first fragment */
			if (i == 0) {
				rtllib_put_snap(
					skb_put(skb_frag, SNAP_SIZE +
					sizeof(u16)), ether_type);
				bytes -= SNAP_SIZE + sizeof(u16);
			}

			skb_put_data(skb_frag, skb->data, bytes);

			/* Advance the SKB... */
			skb_pull(skb, bytes);

			/* Encryption routine will move the header forward in
			 * order to insert the IV between the header and the
			 * payload
			 */
			if (encrypt)
				rtllib_encrypt_fragment(ieee, skb_frag,
							hdr_len);
			if (ieee->config &
			   (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS))
				skb_put(skb_frag, 4);
		}

		if ((qos_actived) && (!bIsMulticast)) {
			if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
				ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
			else
				ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
		} else {
			if (ieee->seq_ctrl[0] == 0xFFF)
				ieee->seq_ctrl[0] = 0;
			else
					ieee->seq_ctrl[0]++;
		}
	} else {
		if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) {
			netdev_warn(ieee->dev, "skb too small (%d).\n",
				    skb->len);
			goto success;
		}

		txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC);
		if (!txb) {
			netdev_warn(ieee->dev, "Could not allocate TXB\n");
			goto failed;
		}

		txb->encrypted = 0;
		txb->payload_size = cpu_to_le16(skb->len);
		skb_put_data(txb->fragments[0], skb->data, skb->len);
	}

 success:
	if (txb) {
		struct cb_desc *tcb_desc = (struct cb_desc *)
				(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
		tcb_desc->bTxEnableFwCalcDur = 1;
		tcb_desc->priority = skb->priority;

		if (ether_type == ETH_P_PAE) {
			if (ieee->pHTInfo->IOTAction &
			    HT_IOT_ACT_WA_IOT_Broadcom) {
				tcb_desc->data_rate =
					 MgntQuery_TxRateExcludeCCKRates(ieee);
				tcb_desc->bTxDisableRateFallBack = false;
			} else {
				tcb_desc->data_rate = ieee->basic_rate;
				tcb_desc->bTxDisableRateFallBack = 1;
			}


			tcb_desc->RATRIndex = 7;
			tcb_desc->bTxUseDriverAssingedRate = 1;
		} else {
			if (is_multicast_ether_addr(header.addr1))
				tcb_desc->bMulticast = 1;
			if (is_broadcast_ether_addr(header.addr1))
				tcb_desc->bBroadcast = 1;
			rtllib_txrate_selectmode(ieee, tcb_desc);
			if (tcb_desc->bMulticast ||  tcb_desc->bBroadcast)
				tcb_desc->data_rate = ieee->basic_rate;
			else
				tcb_desc->data_rate = rtllib_current_rate(ieee);

			if (bdhcp) {
				if (ieee->pHTInfo->IOTAction &
				    HT_IOT_ACT_WA_IOT_Broadcom) {
					tcb_desc->data_rate =
					   MgntQuery_TxRateExcludeCCKRates(ieee);
					tcb_desc->bTxDisableRateFallBack = false;
				} else {
					tcb_desc->data_rate = MGN_1M;
					tcb_desc->bTxDisableRateFallBack = 1;
				}


				tcb_desc->RATRIndex = 7;
				tcb_desc->bTxUseDriverAssingedRate = 1;
				tcb_desc->bdhcp = 1;
			}

			rtllib_qurey_ShortPreambleMode(ieee, tcb_desc);
			rtllib_tx_query_agg_cap(ieee, txb->fragments[0],
						tcb_desc);
			rtllib_query_HTCapShortGI(ieee, tcb_desc);
			rtllib_query_BandwidthMode(ieee, tcb_desc);
			rtllib_query_protectionmode(ieee, tcb_desc,
						    txb->fragments[0]);
		}
	}
	spin_unlock_irqrestore(&ieee->lock, flags);
	dev_kfree_skb_any(skb);
	if (txb) {
		if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) {
			dev->stats.tx_packets++;
			dev->stats.tx_bytes += le16_to_cpu(txb->payload_size);
			rtllib_softmac_xmit(txb, ieee);
		} else {
			if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
				stats->tx_packets++;
				stats->tx_bytes += le16_to_cpu(txb->payload_size);
				return 0;
			}
			rtllib_txb_free(txb);
		}
	}

	return 0;

 failed:
	spin_unlock_irqrestore(&ieee->lock, flags);
	netif_stop_queue(dev);
	stats->tx_errors++;
	return 1;

}

int rtllib_xmit(struct sk_buff *skb, struct net_device *dev)
{
	memset(skb->cb, 0, sizeof(skb->cb));
	return rtllib_xmit_inter(skb, dev);
}
Ejemplo n.º 20
0
static int phylink_parse_fixedlink(struct phylink *pl, struct device_node *np)
{
	struct device_node *fixed_node;
	const struct phy_setting *s;
	struct gpio_desc *desc;
	const __be32 *fixed_prop;
	u32 speed;
	int ret, len;

	fixed_node = of_get_child_by_name(np, "fixed-link");
	if (fixed_node) {
		ret = of_property_read_u32(fixed_node, "speed", &speed);

		pl->link_config.speed = speed;
		pl->link_config.duplex = DUPLEX_HALF;

		if (of_property_read_bool(fixed_node, "full-duplex"))
			pl->link_config.duplex = DUPLEX_FULL;

		/* We treat the "pause" and "asym-pause" terminology as
		 * defining the link partner's ability. */
		if (of_property_read_bool(fixed_node, "pause"))
			pl->link_config.pause |= MLO_PAUSE_SYM;
		if (of_property_read_bool(fixed_node, "asym-pause"))
			pl->link_config.pause |= MLO_PAUSE_ASYM;

		if (ret == 0) {
			desc = fwnode_get_named_gpiod(&fixed_node->fwnode,
						      "link-gpios", 0,
						      GPIOD_IN, "?");

			if (!IS_ERR(desc))
				pl->link_gpio = desc;
			else if (desc == ERR_PTR(-EPROBE_DEFER))
				ret = -EPROBE_DEFER;
		}
		of_node_put(fixed_node);

		if (ret)
			return ret;
	} else {
		fixed_prop = of_get_property(np, "fixed-link", &len);
		if (!fixed_prop) {
			netdev_err(pl->netdev, "broken fixed-link?\n");
			return -EINVAL;
		}
		if (len == 5 * sizeof(*fixed_prop)) {
			pl->link_config.duplex = be32_to_cpu(fixed_prop[1]) ?
						DUPLEX_FULL : DUPLEX_HALF;
			pl->link_config.speed = be32_to_cpu(fixed_prop[2]);
			if (be32_to_cpu(fixed_prop[3]))
				pl->link_config.pause |= MLO_PAUSE_SYM;
			if (be32_to_cpu(fixed_prop[4]))
				pl->link_config.pause |= MLO_PAUSE_ASYM;
		}
	}

	if (pl->link_config.speed > SPEED_1000 &&
	    pl->link_config.duplex != DUPLEX_FULL)
		netdev_warn(pl->netdev, "fixed link specifies half duplex for %dMbps link?\n",
			    pl->link_config.speed);

	bitmap_fill(pl->supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
	linkmode_copy(pl->link_config.advertising, pl->supported);
	phylink_validate(pl, pl->supported, &pl->link_config);

	s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex,
			       pl->supported,
			       __ETHTOOL_LINK_MODE_MASK_NBITS, true);
	linkmode_zero(pl->supported);
	phylink_set(pl->supported, MII);
	if (s) {
		__set_bit(s->bit, pl->supported);
	} else {
		netdev_warn(pl->netdev, "fixed link %s duplex %dMbps not recognised\n",
			    pl->link_config.duplex == DUPLEX_FULL ? "full" : "half",
			    pl->link_config.speed);
	}

	linkmode_and(pl->link_config.advertising, pl->link_config.advertising,
		     pl->supported);

	pl->link_config.link = 1;
	pl->link_config.an_complete = 1;

	return 0;
}
Ejemplo n.º 21
0
/*
 * Start interface
 */
static int ems_usb_start(struct ems_usb *dev)
{
	struct net_device *netdev = dev->netdev;
	int err, i;

	dev->intr_in_buffer[0] = 0;
	dev->free_slots = 15; /* initial size */

	for (i = 0; i < MAX_RX_URBS; i++) {
		struct urb *urb = NULL;
		u8 *buf = NULL;

		/* create a URB, and a buffer for it */
		urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!urb) {
			netdev_err(netdev, "No memory left for URBs\n");
			err = -ENOMEM;
			break;
		}

		buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE, GFP_KERNEL,
					 &urb->transfer_dma);
		if (!buf) {
			netdev_err(netdev, "No memory left for USB buffer\n");
			usb_free_urb(urb);
			err = -ENOMEM;
			break;
		}

		usb_fill_bulk_urb(urb, dev->udev, usb_rcvbulkpipe(dev->udev, 2),
				  buf, RX_BUFFER_SIZE,
				  ems_usb_read_bulk_callback, dev);
		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		usb_anchor_urb(urb, &dev->rx_submitted);

		err = usb_submit_urb(urb, GFP_KERNEL);
		if (err) {
			usb_unanchor_urb(urb);
			usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
					  urb->transfer_dma);
			usb_free_urb(urb);
			break;
		}

		/* Drop reference, USB core will take care of freeing it */
		usb_free_urb(urb);
	}

	/* Did we submit any URBs */
	if (i == 0) {
		netdev_warn(netdev, "couldn't setup read URBs\n");
		return err;
	}

	/* Warn if we've couldn't transmit all the URBs */
	if (i < MAX_RX_URBS)
		netdev_warn(netdev, "rx performance may be slow\n");

	/* Setup and start interrupt URB */
	usb_fill_int_urb(dev->intr_urb, dev->udev,
			 usb_rcvintpipe(dev->udev, 1),
			 dev->intr_in_buffer,
			 INTR_IN_BUFFER_SIZE,
			 ems_usb_read_interrupt_callback, dev, 1);

	err = usb_submit_urb(dev->intr_urb, GFP_KERNEL);
	if (err) {
		netdev_warn(netdev, "intr URB submit failed: %d\n", err);

		return err;
	}

	/* CPC-USB will transfer received message to host */
	err = ems_usb_control_cmd(dev, CONTR_CAN_MESSAGE | CONTR_CONT_ON);
	if (err)
		goto failed;

	/* CPC-USB will transfer CAN state changes to host */
	err = ems_usb_control_cmd(dev, CONTR_CAN_STATE | CONTR_CONT_ON);
	if (err)
		goto failed;

	/* CPC-USB will transfer bus errors to host */
	err = ems_usb_control_cmd(dev, CONTR_BUS_ERROR | CONTR_CONT_ON);
	if (err)
		goto failed;

	err = ems_usb_write_mode(dev, SJA1000_MOD_NORMAL);
	if (err)
		goto failed;

	dev->can.state = CAN_STATE_ERROR_ACTIVE;

	return 0;

failed:
	netdev_warn(netdev, "couldn't submit control: %d\n", err);

	return err;
}
Ejemplo n.º 22
0
static int zorro8390_init(struct net_device *dev, unsigned long board,
			  const char *name, void __iomem *ioaddr)
{
	int i;
	int err;
	unsigned char SA_prom[32];
	int start_page, stop_page;
	struct ei_device *ei_local = netdev_priv(dev);
	static u32 zorro8390_offsets[16] = {
		0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
		0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
	};

	/* Reset card. Who knows what dain-bramaged state it was left in. */
	{
		unsigned long reset_start_time = jiffies;

		z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);

		while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
			if (time_after(jiffies,
				       reset_start_time + 2 * HZ / 100)) {
				netdev_warn(dev, "not found (no reset ack)\n");
				return -ENODEV;
			}

		z_writeb(0xff, ioaddr + NE_EN0_ISR);	/* Ack all intr. */
	}

	/* Read the 16 bytes of station address PROM.
	 * We must first initialize registers,
	 * similar to NS8390_init(eifdev, 0).
	 * We can't reliably read the SAPROM address without this.
	 * (I learned the hard way!).
	 */
	{
		static const struct {
			u32 value;
			u32 offset;
		} program_seq[] = {
			{E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
						/* Select page 0 */
			{0x48,	NE_EN0_DCFG},	/* 0x48: Set byte-wide access */
			{0x00,	NE_EN0_RCNTLO},	/* Clear the count regs */
			{0x00,	NE_EN0_RCNTHI},
			{0x00,	NE_EN0_IMR},	/* Mask completion irq */
			{0xFF,	NE_EN0_ISR},
			{E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
			{E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
			{32,	NE_EN0_RCNTLO},
			{0x00,	NE_EN0_RCNTHI},
			{0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000 */
			{0x00,	NE_EN0_RSARHI},
			{E8390_RREAD + E8390_START, NE_CMD},
		};
		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
			z_writeb(program_seq[i].value,
				 ioaddr + program_seq[i].offset);
	}
	for (i = 0; i < 16; i++) {
		SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
		(void)z_readb(ioaddr + NE_DATAPORT);
	}

	/* We must set the 8390 for word mode. */
	z_writeb(0x49, ioaddr + NE_EN0_DCFG);
	start_page = NESM_START_PG;
	stop_page = NESM_STOP_PG;

	dev->base_addr = (unsigned long)ioaddr;
	dev->irq = IRQ_AMIGA_PORTS;

	/* Install the Interrupt handler */
	i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
			IRQF_SHARED, DRV_NAME, dev);
	if (i)
		return i;

	for (i = 0; i < ETH_ALEN; i++)
		dev->dev_addr[i] = SA_prom[i];

	pr_debug("Found ethernet address: %pM\n", dev->dev_addr);

	ei_status.name = name;
	ei_status.tx_start_page = start_page;
	ei_status.stop_page = stop_page;
	ei_status.word16 = 1;

	ei_status.rx_start_page = start_page + TX_PAGES;

	ei_status.reset_8390 = zorro8390_reset_8390;
	ei_status.block_input = zorro8390_block_input;
	ei_status.block_output = zorro8390_block_output;
	ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
	ei_status.reg_offset = zorro8390_offsets;

	dev->netdev_ops = &zorro8390_netdev_ops;
	__NS8390_init(dev, 0);

	ei_local->msg_enable = zorro8390_msg_enable;

	err = register_netdev(dev);
	if (err) {
		free_irq(IRQ_AMIGA_PORTS, dev);
		return err;
	}

	netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
		    name, board, dev->dev_addr);

	return 0;
}
Ejemplo n.º 23
0
/* The EL3 interrupt handler. */
static irqreturn_t el3_interrupt(int irq, void *dev_id)
{
    struct net_device *dev = (struct net_device *) dev_id;
    struct el3_private *lp = netdev_priv(dev);
    unsigned int ioaddr;
    __u16 status;
    int i = 0, handled = 1;

    if (!netif_device_present(dev))
	return IRQ_NONE;

    ioaddr = dev->base_addr;

    netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS));

    spin_lock(&lp->lock);
    while ((status = inw(ioaddr + EL3_STATUS)) &
	(IntLatch | RxComplete | StatsFull)) {
	if ((status & 0xe000) != 0x2000) {
		netdev_dbg(dev, "interrupt from dead card\n");
		handled = 0;
		break;
	}
	if (status & RxComplete)
		el3_rx(dev);
	if (status & TxAvailable) {
		netdev_dbg(dev, "    TX room bit was handled.\n");
		/* There's room in the FIFO for a full-sized packet. */
		outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
		netif_wake_queue(dev);
	}
	if (status & TxComplete)
		pop_tx_status(dev);
	if (status & (AdapterFailure | RxEarly | StatsFull)) {
	    /* Handle all uncommon interrupts. */
	    if (status & StatsFull)		/* Empty statistics. */
		update_stats(dev);
	    if (status & RxEarly) {		/* Rx early is unused. */
		el3_rx(dev);
		outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
	    }
	    if (status & AdapterFailure) {
		u16 fifo_diag;
		EL3WINDOW(4);
		fifo_diag = inw(ioaddr + 4);
		EL3WINDOW(1);
		netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n",
			    fifo_diag);
		if (fifo_diag & 0x0400) {
		    /* Tx overrun */
		    tc589_wait_for_completion(dev, TxReset);
		    outw(TxEnable, ioaddr + EL3_CMD);
		}
		if (fifo_diag & 0x2000) {
		    /* Rx underrun */
		    tc589_wait_for_completion(dev, RxReset);
		    set_rx_mode(dev);
		    outw(RxEnable, ioaddr + EL3_CMD);
		}
		outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
	    }
	}
	if (++i > 10) {
		netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n",
			   status);
		/* Clear all interrupts */
		outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
		break;
	}
	/* Acknowledge the IRQ. */
	outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
    }
    lp->last_irq = jiffies;
    spin_unlock(&lp->lock);
    netdev_dbg(dev, "exiting interrupt, status %4.4x.\n",
	       inw(ioaddr + EL3_STATUS));
    return IRQ_RETVAL(handled);
}
Ejemplo n.º 24
0
int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb)
{
	struct rtllib_hdr_3addr *req = NULL;
	u16 rc = 0;
	u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
	struct ba_record *pBA = NULL;
	union ba_param_set *pBaParamSet = NULL;
	u16 *pBaTimeoutVal = NULL;
	union sequence_control *pBaStartSeqCtrl = NULL;
	struct rx_ts_record *pTS = NULL;

	if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
		netdev_warn(ieee->dev, "Invalid skb len in BAREQ(%d / %d)\n",
			    (int)skb->len,
			    (int)(sizeof(struct rtllib_hdr_3addr) + 9));
		return -1;
	}

#ifdef VERBOSE_DEBUG
	print_hex_dump_bytes("rtllib_rx_ADDBAReq(): ", DUMP_PREFIX_NONE,
			     skb->data, skb->len);
#endif

	req = (struct rtllib_hdr_3addr *) skb->data;
	tag = (u8 *)req;
	dst = (u8 *)(&req->addr2[0]);
	tag += sizeof(struct rtllib_hdr_3addr);
	pDialogToken = tag + 2;
	pBaParamSet = (union ba_param_set *)(tag + 3);
	pBaTimeoutVal = (u16 *)(tag + 5);
	pBaStartSeqCtrl = (union sequence_control *)(req + 7);

	RT_TRACE(COMP_DBG, "====>rx ADDBAREQ from : %pM\n", dst);
	if (ieee->current_network.qos_data.active == 0  ||
	    (ieee->pHTInfo->bCurrentHTSupport == false) ||
	    (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) {
		rc = ADDBA_STATUS_REFUSED;
		netdev_warn(ieee->dev,
			    "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n",
			    ieee->current_network.qos_data.active,
			    ieee->pHTInfo->bCurrentHTSupport);
		goto OnADDBAReq_Fail;
	}
	if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
	    (u8)(pBaParamSet->field.TID), RX_DIR, true)) {
		rc = ADDBA_STATUS_REFUSED;
		netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__);
		goto OnADDBAReq_Fail;
	}
	pBA = &pTS->RxAdmittedBARecord;

	if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
		rc = ADDBA_STATUS_INVALID_PARAM;
		netdev_warn(ieee->dev, "%s(): BA Policy is not correct\n",
			    __func__);
		goto OnADDBAReq_Fail;
	}

	rtllib_FlushRxTsPendingPkts(ieee, pTS);

	DeActivateBAEntry(ieee, pBA);
	pBA->DialogToken = *pDialogToken;
	pBA->BaParamSet = *pBaParamSet;
	pBA->BaTimeoutValue = *pBaTimeoutVal;
	pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;

	if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev) ||
	   (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT))
		pBA->BaParamSet.field.BufferSize = 1;
	else
		pBA->BaParamSet.field.BufferSize = 32;

	ActivateBAEntry(ieee, pBA, 0);
	rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);

	return 0;

OnADDBAReq_Fail:
	{
		struct ba_record BA;

		BA.BaParamSet = *pBaParamSet;
		BA.BaTimeoutValue = *pBaTimeoutVal;
		BA.DialogToken = *pDialogToken;
		BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
		rtllib_send_ADDBARsp(ieee, dst, &BA, rc);
		return 0;
	}
}
Ejemplo n.º 25
0
static int smsc95xx_reset(struct usbnet *dev)
{
	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
	u32 read_buf, write_buf, burst_cap = 0;
	int ret = 0, timeout;

	netif_dbg(dev, ifup, dev->net, "entering %s\n", __func__);

	write_buf = HW_CFG_LRST_;
	ret = smsc95xx_write_reg(dev, HW_CFG, write_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG register, ret = %d\n",
			    ret);
		return ret;
	}

	timeout = 0;
	do {
		ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
		if (ret < 0) {
			netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
			return ret;
		}
		udelay(1000 * 10);
		timeout++;
	} while ((read_buf & HW_CFG_LRST_) && (timeout < 100));

	if (timeout >= 100) {
		netdev_warn(dev->net, "timeout waiting for completion of Lite Reset\n");
		return ret;
	}

	write_buf = PM_CTL_PHY_RST_;
	ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write PM_CTRL: %d\n", ret);
		return ret;
	}

	timeout = 0;
	do {
		ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
		if (ret < 0) {
			netdev_warn(dev->net, "Failed to read PM_CTRL: %d\n", ret);
			return ret;
		}
		udelay(1000 * 10);
		timeout++;
	} while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));

	if (timeout >= 100) {
		netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
		return ret;
	}

	ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
		return ret;
	}

	netif_dbg(dev, ifup, dev->net,
		  "Read Value from HW_CFG : 0x%08x\n", read_buf);

	read_buf |= HW_CFG_BIR_;

	ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write HW_CFG_BIR_ bit in HW_CFG register, ret = %d\n",
			    ret);
		return ret;
	}

	ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
		return ret;
	}
	netif_dbg(dev, ifup, dev->net,
		  "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n",
		  read_buf);

	if (!turbo_mode) {
		burst_cap = 0;
		dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
	} else if (0) { /* highspeed */
		burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
		dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
	} else {
		burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
		dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
	}

	netif_dbg(dev, ifup, dev->net,
		  "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size);

	ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
		return ret;
	}

	ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
		return ret;
	}
	netif_dbg(dev, ifup, dev->net,
		  "Read Value from BURST_CAP after writing: 0x%08x\n",
		  read_buf);

	read_buf = DEFAULT_BULK_IN_DELAY;
	ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "ret = %d\n", ret);
		return ret;
	}

	ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
		return ret;
	}
	netif_dbg(dev, ifup, dev->net,
		  "Read Value from BULK_IN_DLY after writing: 0x%08x\n",
		  read_buf);

	ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
		return ret;
	}
	netif_dbg(dev, ifup, dev->net,
		  "Read Value from HW_CFG: 0x%08x\n", read_buf);

	if (turbo_mode)
		read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_);

	read_buf &= ~HW_CFG_RXDOFF_;

	/* set Rx data offset=2, Make IP header aligns on word boundary. */
	read_buf |= NET_IP_ALIGN << 9;

	ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write HW_CFG register, ret=%d\n",
			    ret);
		return ret;
	}

	ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
		return ret;
	}
	netif_dbg(dev, ifup, dev->net,
		  "Read Value from HW_CFG after writing: 0x%08x\n", read_buf);

	write_buf = 0xFFFFFFFF;
	ret = smsc95xx_write_reg(dev, INT_STS, write_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write INT_STS register, ret=%d\n",
			    ret);
		return ret;
	}

	ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
		return ret;
	}
	netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);

	/* Configure GPIO pins as LED outputs */
	write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
		LED_GPIO_CFG_FDX_LED;
	ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write LED_GPIO_CFG register, ret=%d\n",
			    ret);
		return ret;
	}

	/* Init Tx */
	write_buf = 0;
	ret = smsc95xx_write_reg(dev, FLOW, write_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
		return ret;
	}

	read_buf = AFC_CFG_DEFAULT;
	ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write AFC_CFG: %d\n", ret);
		return ret;
	}

	/* Don't need mac_cr_lock during initialisation */
	ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
		return ret;
	}

	/* Init Rx */
	/* Set Vlan */
	write_buf = (u32)ETH_P_8021Q;
	ret = smsc95xx_write_reg(dev, VLAN1, write_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write VAN1: %d\n", ret);
		return ret;
	}

	ret = smsc95xx_set_csums(dev);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to set csum offload: %d\n", ret);
		return ret;
	}

	smsc95xx_set_multicast(dev);

	if (smsc95xx_phy_initialize(dev) < 0)
		return -EIO;

	ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
		return ret;
	}

	/* enable PHY interrupts */
	read_buf |= INT_EP_CTL_PHY_INT_;

	ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
	if (ret < 0) {
		netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
		return ret;
	}

	smsc95xx_start_tx_path(dev);
	smsc95xx_start_rx_path(dev);

	netif_dbg(dev, ifup, dev->net, "%s: return 0\n", __func__);
	return 0;
}
Ejemplo n.º 26
0
int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb)
{
	 struct rtllib_hdr_3addr *rsp = NULL;
	struct ba_record *pPendingBA, *pAdmittedBA;
	struct tx_ts_record *pTS = NULL;
	u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
	u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
	union ba_param_set *pBaParamSet = NULL;
	u16			ReasonCode;

	if (skb->len < sizeof(struct rtllib_hdr_3addr) + 9) {
		netdev_warn(ieee->dev, "Invalid skb len in BARSP(%d / %d)\n",
			    (int)skb->len,
			    (int)(sizeof(struct rtllib_hdr_3addr) + 9));
		return -1;
	}
	rsp = (struct rtllib_hdr_3addr *)skb->data;
	tag = (u8 *)rsp;
	dst = (u8 *)(&rsp->addr2[0]);
	tag += sizeof(struct rtllib_hdr_3addr);
	pDialogToken = tag + 2;
	pStatusCode = (u16 *)(tag + 3);
	pBaParamSet = (union ba_param_set *)(tag + 5);
	pBaTimeoutVal = (u16 *)(tag + 7);

	RT_TRACE(COMP_DBG, "====>rx ADDBARSP from : %pM\n", dst);
	if (ieee->current_network.qos_data.active == 0  ||
	    ieee->pHTInfo->bCurrentHTSupport == false ||
	    ieee->pHTInfo->bCurrentAMPDUEnable == false) {
		netdev_warn(ieee->dev,
			    "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",
			    ieee->current_network.qos_data.active,
			    ieee->pHTInfo->bCurrentHTSupport,
			    ieee->pHTInfo->bCurrentAMPDUEnable);
		ReasonCode = DELBA_REASON_UNKNOWN_BA;
		goto OnADDBARsp_Reject;
	}


	if (!GetTs(ieee, (struct ts_common_info **)(&pTS), dst,
		   (u8)(pBaParamSet->field.TID), TX_DIR, false)) {
		netdev_warn(ieee->dev, "%s(): can't get TS\n", __func__);
		ReasonCode = DELBA_REASON_UNKNOWN_BA;
		goto OnADDBARsp_Reject;
	}

	pTS->bAddBaReqInProgress = false;
	pPendingBA = &pTS->TxPendingBARecord;
	pAdmittedBA = &pTS->TxAdmittedBARecord;


	if (pAdmittedBA->bValid == true) {
		netdev_dbg(ieee->dev, "%s(): ADDBA response already admitted\n",
			   __func__);
		return -1;
	} else if ((pPendingBA->bValid == false) ||
		   (*pDialogToken != pPendingBA->DialogToken)) {
		netdev_warn(ieee->dev,
			    "%s(): ADDBA Rsp. BA invalid, DELBA!\n",
			    __func__);
		ReasonCode = DELBA_REASON_UNKNOWN_BA;
		goto OnADDBARsp_Reject;
	} else {
		netdev_dbg(ieee->dev,
			   "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n",
			   __func__, *pStatusCode);
		DeActivateBAEntry(ieee, pPendingBA);
	}


	if (*pStatusCode == ADDBA_STATUS_SUCCESS) {
		if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
			pTS->bAddBaReqDelayed = true;
			DeActivateBAEntry(ieee, pAdmittedBA);
			ReasonCode = DELBA_REASON_END_BA;
			goto OnADDBARsp_Reject;
		}


		pAdmittedBA->DialogToken = *pDialogToken;
		pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
		pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
		pAdmittedBA->BaParamSet = *pBaParamSet;
		DeActivateBAEntry(ieee, pAdmittedBA);
		ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
	} else {
		pTS->bAddBaReqDelayed = true;
		pTS->bDisable_AddBa = true;
		ReasonCode = DELBA_REASON_END_BA;
		goto OnADDBARsp_Reject;
	}

	return 0;

OnADDBARsp_Reject:
	{
		struct ba_record BA;

		BA.BaParamSet = *pBaParamSet;
		rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
		return 0;
	}
}
static int qlcnic_set_led(struct net_device *dev,
			  enum ethtool_phys_id_state state)
{
	struct qlcnic_adapter *adapter = netdev_priv(dev);
	int max_sds_rings = adapter->max_sds_rings;
	int err = -EIO, active = 1;

	if (qlcnic_83xx_check(adapter))
		return qlcnic_83xx_set_led(dev, state);

	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
		netdev_warn(dev, "LED test not supported for non "
				"privilege function\n");
		return -EOPNOTSUPP;
	}

	switch (state) {
	case ETHTOOL_ID_ACTIVE:
		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
			return -EBUSY;

		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
			break;

		if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
			if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
				break;
			set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
		}

		if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
			err = 0;
			break;
		}

		dev_err(&adapter->pdev->dev,
			"Failed to set LED blink state.\n");
		break;

	case ETHTOOL_ID_INACTIVE:
		active = 0;

		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
			break;

		if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
			if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
				break;
			set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
		}

		if (adapter->nic_ops->config_led(adapter, 0, 0xf))
			dev_err(&adapter->pdev->dev,
				"Failed to reset LED blink state.\n");

		break;

	default:
		return -EINVAL;
	}

	if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
		qlcnic_diag_free_res(dev, max_sds_rings);

	if (!active || err)
		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);

	return err;
}
Ejemplo n.º 28
0
int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb)
{
	 struct rtllib_hdr_3addr *delba = NULL;
	union delba_param_set *pDelBaParamSet = NULL;
	u16 *pReasonCode = NULL;
	u8 *dst = NULL;

	if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
		netdev_warn(ieee->dev, "Invalid skb len in DELBA(%d / %d)\n",
			    (int)skb->len,
			    (int)(sizeof(struct rtllib_hdr_3addr) + 6));
		return -1;
	}

	if (ieee->current_network.qos_data.active == 0  ||
		ieee->pHTInfo->bCurrentHTSupport == false) {
		netdev_warn(ieee->dev,
			    "received DELBA while QOS or HT is not supported(%d, %d)\n",
			    ieee->current_network. qos_data.active,
			    ieee->pHTInfo->bCurrentHTSupport);
		return -1;
	}

#ifdef VERBOSE_DEBUG
	print_hex_dump_bytes("rtllib_rx_DELBA(): ", DUMP_PREFIX_NONE, skb->data,
			     skb->len);
#endif
	delba = (struct rtllib_hdr_3addr *)skb->data;
	dst = (u8 *)(&delba->addr2[0]);
	delba += sizeof(struct rtllib_hdr_3addr);
	pDelBaParamSet = (union delba_param_set *)(delba+2);
	pReasonCode = (u16 *)(delba+4);

	if (pDelBaParamSet->field.Initiator == 1) {
		struct rx_ts_record *pRxTs;

		if (!GetTs(ieee, (struct ts_common_info **)&pRxTs, dst,
		    (u8)pDelBaParamSet->field.TID, RX_DIR, false)) {
			netdev_warn(ieee->dev,
				    "%s(): can't get TS for RXTS. dst:%pM TID:%d\n",
				    __func__, dst,
				    (u8)pDelBaParamSet->field.TID);
			return -1;
		}

		RxTsDeleteBA(ieee, pRxTs);
	} else {
		struct tx_ts_record *pTxTs;

		if (!GetTs(ieee, (struct ts_common_info **)&pTxTs, dst,
			   (u8)pDelBaParamSet->field.TID, TX_DIR, false)) {
			netdev_warn(ieee->dev, "%s(): can't get TS for TXTS\n",
				    __func__);
			return -1;
		}

		pTxTs->bUsingBa = false;
		pTxTs->bAddBaReqInProgress = false;
		pTxTs->bAddBaReqDelayed = false;
		del_timer_sync(&pTxTs->TsAddBaTimer);
		TxTsDeleteBA(ieee, pTxTs);
	}
	return 0;
}
Ejemplo n.º 29
0
/* Send close command to device */
static int usb_8dev_cmd_close(struct usb_8dev_priv *priv)
{
	struct usb_8dev_cmd_msg inmsg;
	struct usb_8dev_cmd_msg outmsg = {
		.channel = 0,
		.command = USB_8DEV_CLOSE,
		.opt1 = 0,
		.opt2 = 0
	};

	return usb_8dev_send_cmd(priv, &outmsg, &inmsg);
}

/* Get firmware and hardware version */
static int usb_8dev_cmd_version(struct usb_8dev_priv *priv, u32 *res)
{
	struct usb_8dev_cmd_msg	inmsg;
	struct usb_8dev_cmd_msg	outmsg = {
		.channel = 0,
		.command = USB_8DEV_GET_SOFTW_HARDW_VER,
		.opt1 = 0,
		.opt2 = 0
	};

	int err = usb_8dev_send_cmd(priv, &outmsg, &inmsg);
	if (err)
		return err;

	*res = be32_to_cpup((__be32 *)inmsg.data);

	return err;
}

/* Set network device mode
 *
 * Maybe we should leave this function empty, because the device
 * set mode variable with open command.
 */
static int usb_8dev_set_mode(struct net_device *netdev, enum can_mode mode)
{
	struct usb_8dev_priv *priv = netdev_priv(netdev);
	int err = 0;

	switch (mode) {
	case CAN_MODE_START:
		err = usb_8dev_cmd_open(priv);
		if (err)
			netdev_warn(netdev, "couldn't start device");
		break;

	default:
		return -EOPNOTSUPP;
	}

	return err;
}

/* Read error/status frames */
static void usb_8dev_rx_err_msg(struct usb_8dev_priv *priv,
				struct usb_8dev_rx_msg *msg)
{
	struct can_frame *cf;
	struct sk_buff *skb;
	struct net_device_stats *stats = &priv->netdev->stats;

	/* Error message:
	 * byte 0: Status
	 * byte 1: bit   7: Receive Passive
	 * byte 1: bit 0-6: Receive Error Counter
	 * byte 2: Transmit Error Counter
	 * byte 3: Always 0 (maybe reserved for future use)
	 */

	u8 state = msg->data[0];
	u8 rxerr = msg->data[1] & USB_8DEV_RP_MASK;
	u8 txerr = msg->data[2];
	int rx_errors = 0;
	int tx_errors = 0;

	skb = alloc_can_err_skb(priv->netdev, &cf);
	if (!skb)
		return;

	switch (state) {
	case USB_8DEV_STATUSMSG_OK:
		priv->can.state = CAN_STATE_ERROR_ACTIVE;
		cf->can_id |= CAN_ERR_PROT;
		cf->data[2] = CAN_ERR_PROT_ACTIVE;
		break;
	case USB_8DEV_STATUSMSG_BUSOFF:
		priv->can.state = CAN_STATE_BUS_OFF;
		cf->can_id |= CAN_ERR_BUSOFF;
		can_bus_off(priv->netdev);
		break;
	case USB_8DEV_STATUSMSG_OVERRUN:
	case USB_8DEV_STATUSMSG_BUSLIGHT:
	case USB_8DEV_STATUSMSG_BUSHEAVY:
		cf->can_id |= CAN_ERR_CRTL;
		break;
	default:
		priv->can.state = CAN_STATE_ERROR_WARNING;
		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
		priv->can.can_stats.bus_error++;
		break;
	}

	switch (state) {
	case USB_8DEV_STATUSMSG_OK:
	case USB_8DEV_STATUSMSG_BUSOFF:
		break;
	case USB_8DEV_STATUSMSG_ACK:
		cf->can_id |= CAN_ERR_ACK;
		tx_errors = 1;
		break;
	case USB_8DEV_STATUSMSG_CRC:
		cf->data[2] |= CAN_ERR_PROT_UNSPEC;
		cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ |
			       CAN_ERR_PROT_LOC_CRC_DEL;
		rx_errors = 1;
		break;
	case USB_8DEV_STATUSMSG_BIT0:
		cf->data[2] |= CAN_ERR_PROT_BIT0;
		tx_errors = 1;
		break;
	case USB_8DEV_STATUSMSG_BIT1:
		cf->data[2] |= CAN_ERR_PROT_BIT1;
		tx_errors = 1;
		break;
	case USB_8DEV_STATUSMSG_FORM:
		cf->data[2] |= CAN_ERR_PROT_FORM;
		rx_errors = 1;
		break;
	case USB_8DEV_STATUSMSG_STUFF:
		cf->data[2] |= CAN_ERR_PROT_STUFF;
		rx_errors = 1;
		break;
	case USB_8DEV_STATUSMSG_OVERRUN:
		cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
		stats->rx_over_errors++;
		rx_errors = 1;
		break;
	case USB_8DEV_STATUSMSG_BUSLIGHT:
		priv->can.state = CAN_STATE_ERROR_WARNING;
		cf->data[1] = (txerr > rxerr) ?
			CAN_ERR_CRTL_TX_WARNING :
			CAN_ERR_CRTL_RX_WARNING;
		priv->can.can_stats.error_warning++;
		break;
	case USB_8DEV_STATUSMSG_BUSHEAVY:
		priv->can.state = CAN_STATE_ERROR_PASSIVE;
		cf->data[1] = (txerr > rxerr) ?
			CAN_ERR_CRTL_TX_PASSIVE :
			CAN_ERR_CRTL_RX_PASSIVE;
		priv->can.can_stats.error_passive++;
		break;
	default:
		netdev_warn(priv->netdev,
			    "Unknown status/error message (%d)\n", state);
		break;
	}

	if (tx_errors) {
		cf->data[2] |= CAN_ERR_PROT_TX;
		stats->tx_errors++;
	}

	if (rx_errors)
		stats->rx_errors++;

	cf->data[6] = txerr;
	cf->data[7] = rxerr;

	priv->bec.txerr = txerr;
	priv->bec.rxerr = rxerr;

	netif_rx(skb);

	stats->rx_packets++;
	stats->rx_bytes += cf->can_dlc;
}

/* Read data and status frames */
static void usb_8dev_rx_can_msg(struct usb_8dev_priv *priv,
				struct usb_8dev_rx_msg *msg)
{
	struct can_frame *cf;
	struct sk_buff *skb;
	struct net_device_stats *stats = &priv->netdev->stats;

	if (msg->type == USB_8DEV_TYPE_ERROR_FRAME &&
		   msg->flags == USB_8DEV_ERR_FLAG) {
		usb_8dev_rx_err_msg(priv, msg);
	} else if (msg->type == USB_8DEV_TYPE_CAN_FRAME) {
		skb = alloc_can_skb(priv->netdev, &cf);
		if (!skb)
			return;

		cf->can_id = be32_to_cpu(msg->id);
		cf->can_dlc = get_can_dlc(msg->dlc & 0xF);

		if (msg->flags & USB_8DEV_EXTID)
			cf->can_id |= CAN_EFF_FLAG;

		if (msg->flags & USB_8DEV_RTR)
			cf->can_id |= CAN_RTR_FLAG;
		else
			memcpy(cf->data, msg->data, cf->can_dlc);

		netif_rx(skb);

		stats->rx_packets++;
		stats->rx_bytes += cf->can_dlc;

		can_led_event(priv->netdev, CAN_LED_EVENT_RX);
	} else {
		netdev_warn(priv->netdev, "frame type %d unknown",
			 msg->type);
	}

}

/* Callback for reading data from device
 *
 * Check urb status, call read function and resubmit urb read operation.
 */
static void usb_8dev_read_bulk_callback(struct urb *urb)
{
	struct usb_8dev_priv *priv = urb->context;
	struct net_device *netdev;
	int retval;
	int pos = 0;

	netdev = priv->netdev;

	if (!netif_device_present(netdev))
		return;

	switch (urb->status) {
	case 0: /* success */
		break;

	case -ENOENT:
	case -ESHUTDOWN:
		return;

	default:
		netdev_info(netdev, "Rx URB aborted (%d)\n",
			 urb->status);
		goto resubmit_urb;
	}

	while (pos < urb->actual_length) {
		struct usb_8dev_rx_msg *msg;

		if (pos + sizeof(struct usb_8dev_rx_msg) > urb->actual_length) {
			netdev_err(priv->netdev, "format error\n");
			break;
		}

		msg = (struct usb_8dev_rx_msg *)(urb->transfer_buffer + pos);
		usb_8dev_rx_can_msg(priv, msg);

		pos += sizeof(struct usb_8dev_rx_msg);
	}

resubmit_urb:
	usb_fill_bulk_urb(urb, priv->udev,
			  usb_rcvbulkpipe(priv->udev, USB_8DEV_ENDP_DATA_RX),
			  urb->transfer_buffer, RX_BUFFER_SIZE,
			  usb_8dev_read_bulk_callback, priv);

	retval = usb_submit_urb(urb, GFP_ATOMIC);

	if (retval == -ENODEV)
		netif_device_detach(netdev);
	else if (retval)
		netdev_err(netdev,
			"failed resubmitting read bulk urb: %d\n", retval);
}

/* Callback handler for write operations
 *
 * Free allocated buffers, check transmit status and
 * calculate statistic.
 */
static void usb_8dev_write_bulk_callback(struct urb *urb)
{
	struct usb_8dev_tx_urb_context *context = urb->context;
	struct usb_8dev_priv *priv;
	struct net_device *netdev;

	BUG_ON(!context);

	priv = context->priv;
	netdev = priv->netdev;

	/* free up our allocated buffer */
	usb_free_coherent(urb->dev, urb->transfer_buffer_length,
			  urb->transfer_buffer, urb->transfer_dma);

	atomic_dec(&priv->active_tx_urbs);

	if (!netif_device_present(netdev))
		return;

	if (urb->status)
		netdev_info(netdev, "Tx URB aborted (%d)\n",
			 urb->status);

	netdev->stats.tx_packets++;
	netdev->stats.tx_bytes += context->dlc;

	can_get_echo_skb(netdev, context->echo_index);

	can_led_event(netdev, CAN_LED_EVENT_TX);

	/* Release context */
	context->echo_index = MAX_TX_URBS;

	netif_wake_queue(netdev);
}

/* Send data to device */
static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
				      struct net_device *netdev)
{
	struct usb_8dev_priv *priv = netdev_priv(netdev);
	struct net_device_stats *stats = &netdev->stats;
	struct can_frame *cf = (struct can_frame *) skb->data;
	struct usb_8dev_tx_msg *msg;
	struct urb *urb;
	struct usb_8dev_tx_urb_context *context = NULL;
	u8 *buf;
	int i, err;
	size_t size = sizeof(struct usb_8dev_tx_msg);

	if (can_dropped_invalid_skb(netdev, skb))
		return NETDEV_TX_OK;

	/* create a URB, and a buffer for it, and copy the data to the URB */
	urb = usb_alloc_urb(0, GFP_ATOMIC);
	if (!urb) {
		netdev_err(netdev, "No memory left for URBs\n");
		goto nomem;
	}

	buf = usb_alloc_coherent(priv->udev, size, GFP_ATOMIC,
				 &urb->transfer_dma);
	if (!buf) {
		netdev_err(netdev, "No memory left for USB buffer\n");
		goto nomembuf;
	}

	memset(buf, 0, size);

	msg = (struct usb_8dev_tx_msg *)buf;
	msg->begin = USB_8DEV_DATA_START;
	msg->flags = 0x00;

	if (cf->can_id & CAN_RTR_FLAG)
		msg->flags |= USB_8DEV_RTR;

	if (cf->can_id & CAN_EFF_FLAG)
		msg->flags |= USB_8DEV_EXTID;

	msg->id = cpu_to_be32(cf->can_id & CAN_ERR_MASK);
	msg->dlc = cf->can_dlc;
	memcpy(msg->data, cf->data, cf->can_dlc);
	msg->end = USB_8DEV_DATA_END;

	for (i = 0; i < MAX_TX_URBS; i++) {
		if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
			context = &priv->tx_contexts[i];
			break;
		}
	}

	/* May never happen! When this happens we'd more URBs in flight as
	 * allowed (MAX_TX_URBS).
	 */
	if (!context)
		goto nofreecontext;

	context->priv = priv;
	context->echo_index = i;
	context->dlc = cf->can_dlc;

	usb_fill_bulk_urb(urb, priv->udev,
			  usb_sndbulkpipe(priv->udev, USB_8DEV_ENDP_DATA_TX),
			  buf, size, usb_8dev_write_bulk_callback, context);
	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
	usb_anchor_urb(urb, &priv->tx_submitted);

	can_put_echo_skb(skb, netdev, context->echo_index);

	atomic_inc(&priv->active_tx_urbs);

	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (unlikely(err))
		goto failed;
	else if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
		/* Slow down tx path */
		netif_stop_queue(netdev);

	/* Release our reference to this URB, the USB core will eventually free
	 * it entirely.
	 */
	usb_free_urb(urb);

	return NETDEV_TX_OK;

nofreecontext:
	usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);
	usb_free_urb(urb);

	netdev_warn(netdev, "couldn't find free context");

	return NETDEV_TX_BUSY;

failed:
	can_free_echo_skb(netdev, context->echo_index);

	usb_unanchor_urb(urb);
	usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);

	atomic_dec(&priv->active_tx_urbs);

	if (err == -ENODEV)
		netif_device_detach(netdev);
	else
		netdev_warn(netdev, "failed tx_urb %d\n", err);

nomembuf:
	usb_free_urb(urb);

nomem:
	dev_kfree_skb(skb);
	stats->tx_dropped++;

	return NETDEV_TX_OK;
}

static int usb_8dev_get_berr_counter(const struct net_device *netdev,
				     struct can_berr_counter *bec)
{
	struct usb_8dev_priv *priv = netdev_priv(netdev);

	bec->txerr = priv->bec.txerr;
	bec->rxerr = priv->bec.rxerr;

	return 0;
}

/* Start USB device */
static int usb_8dev_start(struct usb_8dev_priv *priv)
{
	struct net_device *netdev = priv->netdev;
	int err, i;

	for (i = 0; i < MAX_RX_URBS; i++) {
		struct urb *urb = NULL;
		u8 *buf;

		/* create a URB, and a buffer for it */
		urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!urb) {
			netdev_err(netdev, "No memory left for URBs\n");
			err = -ENOMEM;
			break;
		}

		buf = usb_alloc_coherent(priv->udev, RX_BUFFER_SIZE, GFP_KERNEL,
					 &urb->transfer_dma);
		if (!buf) {
			netdev_err(netdev, "No memory left for USB buffer\n");
			usb_free_urb(urb);
			err = -ENOMEM;
			break;
		}

		usb_fill_bulk_urb(urb, priv->udev,
				  usb_rcvbulkpipe(priv->udev,
						  USB_8DEV_ENDP_DATA_RX),
				  buf, RX_BUFFER_SIZE,
				  usb_8dev_read_bulk_callback, priv);
		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		usb_anchor_urb(urb, &priv->rx_submitted);

		err = usb_submit_urb(urb, GFP_KERNEL);
		if (err) {
			usb_unanchor_urb(urb);
			usb_free_coherent(priv->udev, RX_BUFFER_SIZE, buf,
					  urb->transfer_dma);
			usb_free_urb(urb);
			break;
		}

		/* Drop reference, USB core will take care of freeing it */
		usb_free_urb(urb);
	}

	/* Did we submit any URBs */
	if (i == 0) {
		netdev_warn(netdev, "couldn't setup read URBs\n");
		return err;
	}

	/* Warn if we've couldn't transmit all the URBs */
	if (i < MAX_RX_URBS)
		netdev_warn(netdev, "rx performance may be slow\n");

	err = usb_8dev_cmd_open(priv);
	if (err)
		goto failed;

	priv->can.state = CAN_STATE_ERROR_ACTIVE;

	return 0;

failed:
	if (err == -ENODEV)
		netif_device_detach(priv->netdev);

	netdev_warn(netdev, "couldn't submit control: %d\n", err);

	return err;
}

/* Open USB device */
static int usb_8dev_open(struct net_device *netdev)
{
	struct usb_8dev_priv *priv = netdev_priv(netdev);
	int err;

	/* common open */
	err = open_candev(netdev);
	if (err)
		return err;

	can_led_event(netdev, CAN_LED_EVENT_OPEN);

	/* finally start device */
	err = usb_8dev_start(priv);
	if (err) {
		if (err == -ENODEV)
			netif_device_detach(priv->netdev);

		netdev_warn(netdev, "couldn't start device: %d\n",
			 err);

		close_candev(netdev);

		return err;
	}

	netif_start_queue(netdev);

	return 0;
}

static void unlink_all_urbs(struct usb_8dev_priv *priv)
{
	int i;

	usb_kill_anchored_urbs(&priv->rx_submitted);

	usb_kill_anchored_urbs(&priv->tx_submitted);
	atomic_set(&priv->active_tx_urbs, 0);

	for (i = 0; i < MAX_TX_URBS; i++)
		priv->tx_contexts[i].echo_index = MAX_TX_URBS;
}

/* Close USB device */
static int usb_8dev_close(struct net_device *netdev)
{
	struct usb_8dev_priv *priv = netdev_priv(netdev);
	int err = 0;

	/* Send CLOSE command to CAN controller */
	err = usb_8dev_cmd_close(priv);
	if (err)
		netdev_warn(netdev, "couldn't stop device");

	priv->can.state = CAN_STATE_STOPPED;

	netif_stop_queue(netdev);

	/* Stop polling */
	unlink_all_urbs(priv);

	close_candev(netdev);

	can_led_event(netdev, CAN_LED_EVENT_STOP);

	return err;
}

static const struct net_device_ops usb_8dev_netdev_ops = {
	.ndo_open = usb_8dev_open,
	.ndo_stop = usb_8dev_close,
	.ndo_start_xmit = usb_8dev_start_xmit,
	.ndo_change_mtu = can_change_mtu,
};

static const struct can_bittiming_const usb_8dev_bittiming_const = {
	.name = "usb_8dev",
	.tseg1_min = 1,
	.tseg1_max = 16,
	.tseg2_min = 1,
	.tseg2_max = 8,
	.sjw_max = 4,
	.brp_min = 1,
	.brp_max = 1024,
	.brp_inc = 1,
};

/* Probe USB device
 *
 * Check device and firmware.
 * Set supported modes and bittiming constants.
 * Allocate some memory.
 */
static int usb_8dev_probe(struct usb_interface *intf,
			 const struct usb_device_id *id)
{
	struct net_device *netdev;
	struct usb_8dev_priv *priv;
	int i, err = -ENOMEM;
	u32 version;
	char buf[18];
	struct usb_device *usbdev = interface_to_usbdev(intf);

	/* product id looks strange, better we also check iProduct string */
	if (usb_string(usbdev, usbdev->descriptor.iProduct, buf,
		       sizeof(buf)) > 0 && strcmp(buf, "USB2CAN converter")) {
		dev_info(&usbdev->dev, "ignoring: not an USB2CAN converter\n");
		return -ENODEV;
	}

	netdev = alloc_candev(sizeof(struct usb_8dev_priv), MAX_TX_URBS);
	if (!netdev) {
		dev_err(&intf->dev, "Couldn't alloc candev\n");
		return -ENOMEM;
	}

	priv = netdev_priv(netdev);

	priv->udev = usbdev;
	priv->netdev = netdev;

	priv->can.state = CAN_STATE_STOPPED;
	priv->can.clock.freq = USB_8DEV_ABP_CLOCK;
	priv->can.bittiming_const = &usb_8dev_bittiming_const;
	priv->can.do_set_mode = usb_8dev_set_mode;
	priv->can.do_get_berr_counter = usb_8dev_get_berr_counter;
	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
				      CAN_CTRLMODE_LISTENONLY |
				      CAN_CTRLMODE_ONE_SHOT;

	netdev->netdev_ops = &usb_8dev_netdev_ops;

	netdev->flags |= IFF_ECHO; /* we support local echo */

	init_usb_anchor(&priv->rx_submitted);

	init_usb_anchor(&priv->tx_submitted);
	atomic_set(&priv->active_tx_urbs, 0);

	for (i = 0; i < MAX_TX_URBS; i++)
		priv->tx_contexts[i].echo_index = MAX_TX_URBS;

	priv->cmd_msg_buffer = kzalloc(sizeof(struct usb_8dev_cmd_msg),
				      GFP_KERNEL);
	if (!priv->cmd_msg_buffer)
		goto cleanup_candev;

	usb_set_intfdata(intf, priv);

	SET_NETDEV_DEV(netdev, &intf->dev);

	mutex_init(&priv->usb_8dev_cmd_lock);

	err = register_candev(netdev);
	if (err) {
		netdev_err(netdev,
			"couldn't register CAN device: %d\n", err);
		goto cleanup_cmd_msg_buffer;
	}

	err = usb_8dev_cmd_version(priv, &version);
	if (err) {
		netdev_err(netdev, "can't get firmware version\n");
		goto cleanup_unregister_candev;
	} else {
		netdev_info(netdev,
			 "firmware: %d.%d, hardware: %d.%d\n",
			 (version>>24) & 0xff, (version>>16) & 0xff,
			 (version>>8) & 0xff, version & 0xff);
	}

	devm_can_led_init(netdev);

	return 0;

cleanup_unregister_candev:
	unregister_netdev(priv->netdev);

cleanup_cmd_msg_buffer:
	kfree(priv->cmd_msg_buffer);

cleanup_candev:
	free_candev(netdev);

	return err;

}

/* Called by the usb core when driver is unloaded or device is removed */
static void usb_8dev_disconnect(struct usb_interface *intf)
{
	struct usb_8dev_priv *priv = usb_get_intfdata(intf);

	usb_set_intfdata(intf, NULL);

	if (priv) {
		netdev_info(priv->netdev, "device disconnected\n");

		unregister_netdev(priv->netdev);
		free_candev(priv->netdev);

		unlink_all_urbs(priv);
	}

}

static struct usb_driver usb_8dev_driver = {
	.name =		"usb_8dev",
	.probe =	usb_8dev_probe,
	.disconnect =	usb_8dev_disconnect,
	.id_table =	usb_8dev_table,
};

module_usb_driver(usb_8dev_driver);

MODULE_AUTHOR("Bernd Krumboeck <*****@*****.**>");
MODULE_DESCRIPTION("CAN driver for 8 devices USB2CAN interfaces");
MODULE_LICENSE("GPL v2");
Ejemplo n.º 30
0
static struct sk_buff *rtllib_ADDBA(struct rtllib_device *ieee, u8 *Dst,
				    struct ba_record *pBA,
				    u16 StatusCode, u8 type)
{
	struct sk_buff *skb = NULL;
	 struct rtllib_hdr_3addr *BAReq = NULL;
	u8 *tag = NULL;
	u16 len = ieee->tx_headroom + 9;

	netdev_dbg(ieee->dev, "%s(): frame(%d) sentd to: %pM, ieee->dev:%p\n",
		   __func__, type, Dst, ieee->dev);

	if (pBA == NULL) {
		netdev_warn(ieee->dev, "pBA is NULL\n");
		return NULL;
	}
	skb = dev_alloc_skb(len + sizeof(struct rtllib_hdr_3addr));
	if (skb == NULL)
		return NULL;

	memset(skb->data, 0, sizeof(struct rtllib_hdr_3addr));

	skb_reserve(skb, ieee->tx_headroom);

	BAReq = (struct rtllib_hdr_3addr *)skb_put(skb,
		 sizeof(struct rtllib_hdr_3addr));

	ether_addr_copy(BAReq->addr1, Dst);
	ether_addr_copy(BAReq->addr2, ieee->dev->dev_addr);

	ether_addr_copy(BAReq->addr3, ieee->current_network.bssid);
	BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT);

	tag = (u8 *)skb_put(skb, 9);
	*tag++ = ACT_CAT_BA;
	*tag++ = type;
	*tag++ = pBA->DialogToken;

	if (ACT_ADDBARSP == type) {
		RT_TRACE(COMP_DBG, "====>to send ADDBARSP\n");

		put_unaligned_le16(StatusCode, tag);
		tag += 2;
	}

	put_unaligned_le16(pBA->BaParamSet.shortData, tag);
	tag += 2;

	put_unaligned_le16(pBA->BaTimeoutValue, tag);
	tag += 2;

	if (ACT_ADDBAREQ == type) {
		memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2);
		tag += 2;
	}

#ifdef VERBOSE_DEBUG
	print_hex_dump_bytes("rtllib_ADDBA(): ", DUMP_PREFIX_NONE, skb->data,
			     skb->len);
#endif
	return skb;
}