コード例 #1
0
ファイル: uap_event.c プロジェクト: EvolutionMod/ath10-lenovo
/*
 * This function handles AP interface specific events generated by firmware.
 *
 * Event specific routines are called by this function based
 * upon the generated event cause.
 *
 *
 * Events supported for AP -
 *      - EVENT_UAP_STA_ASSOC
 *      - EVENT_UAP_STA_DEAUTH
 *      - EVENT_UAP_BSS_ACTIVE
 *      - EVENT_UAP_BSS_START
 *      - EVENT_UAP_BSS_IDLE
 *      - EVENT_UAP_MIC_COUNTERMEASURES:
 */
int mwifiex_process_uap_event(struct mwifiex_private *priv)
{
	struct mwifiex_adapter *adapter = priv->adapter;
	int len, i;
	u32 eventcause = adapter->event_cause;
	struct station_info sinfo;
	struct mwifiex_assoc_event *event;
	struct mwifiex_sta_node *node;
	u8 *deauth_mac;
	struct host_cmd_ds_11n_batimeout *ba_timeout;
	u16 ctrl;

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

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

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

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

		if (!priv->ap_11n_enabled)
			break;

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

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

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

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

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

		adapter->ps_state = PS_STATE_PRE_SLEEP;

		mwifiex_check_ps_cond(adapter);
		break;

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

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

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

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

	return 0;
}
コード例 #2
0
ファイル: main.c プロジェクト: iamroot12a/kernel
/*
 * This function removes the card.
 *
 * This function follows the following major steps to remove the device -
 *      - Stop data traffic
 *      - Shutdown firmware
 *      - Remove the logical interfaces
 *      - Terminate the work queue
 *      - Unregister the device
 *      - Free the adapter structure
 */
int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
{
    struct mwifiex_private *priv = NULL;
    int i;

    if (down_interruptible(sem))
        goto exit_sem_err;

    if (!adapter)
        goto exit_remove;

    /* We can no longer handle interrupts once we start doing the teardown
     * below. */
    if (adapter->if_ops.disable_int)
        adapter->if_ops.disable_int(adapter);

    adapter->surprise_removed = true;

    mwifiex_terminate_workqueue(adapter);

    /* Stop data */
    for (i = 0; i < adapter->priv_num; i++) {
        priv = adapter->priv[i];
        if (priv && priv->netdev) {
            mwifiex_stop_net_dev_queue(priv->netdev, adapter);
            if (netif_carrier_ok(priv->netdev))
                netif_carrier_off(priv->netdev);
        }
    }

    dev_dbg(adapter->dev, "cmd: calling mwifiex_shutdown_drv...\n");
    adapter->init_wait_q_woken = false;

    if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS)
        wait_event_interruptible(adapter->init_wait_q,
                                 adapter->init_wait_q_woken);
    dev_dbg(adapter->dev, "cmd: mwifiex_shutdown_drv done\n");
    if (atomic_read(&adapter->rx_pending) ||
            atomic_read(&adapter->tx_pending) ||
            atomic_read(&adapter->cmd_pending)) {
        dev_err(adapter->dev, "rx_pending=%d, tx_pending=%d, "
                "cmd_pending=%d\n",
                atomic_read(&adapter->rx_pending),
                atomic_read(&adapter->tx_pending),
                atomic_read(&adapter->cmd_pending));
    }

    for (i = 0; i < adapter->priv_num; i++) {
        priv = adapter->priv[i];

        if (!priv)
            continue;

        rtnl_lock();
        if (priv->netdev &&
                priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED)
            mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev);
        rtnl_unlock();
    }

    wiphy_unregister(adapter->wiphy);
    wiphy_free(adapter->wiphy);

    /* Unregister device */
    dev_dbg(adapter->dev, "info: unregister device\n");
    if (adapter->if_ops.unregister_dev)
        adapter->if_ops.unregister_dev(adapter);
    /* Free adapter structure */
    dev_dbg(adapter->dev, "info: free adapter\n");
    mwifiex_free_adapter(adapter);

exit_remove:
    up(sem);
exit_sem_err:
    return 0;
}
コード例 #3
0
/*
 * This function handles events generated by firmware.
 *
 * This is a generic function and handles all events.
 *
 * Event specific routines are called by this function based
 * upon the generated event cause.
 *
 * For the following events, the function just forwards them to upper
 * layers, optionally recording the change -
 *      - EVENT_LINK_SENSED
 *      - EVENT_MIC_ERR_UNICAST
 *      - EVENT_MIC_ERR_MULTICAST
 *      - EVENT_PORT_RELEASE
 *      - EVENT_RSSI_LOW
 *      - EVENT_SNR_LOW
 *      - EVENT_MAX_FAIL
 *      - EVENT_RSSI_HIGH
 *      - EVENT_SNR_HIGH
 *      - EVENT_DATA_RSSI_LOW
 *      - EVENT_DATA_SNR_LOW
 *      - EVENT_DATA_RSSI_HIGH
 *      - EVENT_DATA_SNR_HIGH
 *      - EVENT_LINK_QUALITY
 *      - EVENT_PRE_BEACON_LOST
 *      - EVENT_IBSS_COALESCED
 *      - EVENT_WEP_ICV_ERR
 *      - EVENT_BW_CHANGE
 *      - EVENT_HOSTWAKE_STAIE
  *
 * For the following events, no action is taken -
 *      - EVENT_MIB_CHANGED
 *      - EVENT_INIT_DONE
 *      - EVENT_DUMMY_HOST_WAKEUP_SIGNAL
 *
 * Rest of the supported events requires driver handling -
 *      - EVENT_DEAUTHENTICATED
 *      - EVENT_DISASSOCIATED
 *      - EVENT_LINK_LOST
 *      - EVENT_PS_SLEEP
 *      - EVENT_PS_AWAKE
 *      - EVENT_DEEP_SLEEP_AWAKE
 *      - EVENT_HS_ACT_REQ
 *      - EVENT_ADHOC_BCN_LOST
 *      - EVENT_BG_SCAN_REPORT
 *      - EVENT_WMM_STATUS_CHANGE
 *      - EVENT_ADDBA
 *      - EVENT_DELBA
 *      - EVENT_BA_STREAM_TIEMOUT
 *      - EVENT_AMSDU_AGGR_CTRL
 */
int mwifiex_process_sta_event(struct mwifiex_private *priv)
{
    struct mwifiex_adapter *adapter = priv->adapter;
    int ret = 0;
    u32 eventcause = adapter->event_cause;
    u16 ctrl, reason_code;

    switch (eventcause) {
    case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
        dev_err(adapter->dev,
                "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n");
        break;
    case EVENT_LINK_SENSED:
        dev_dbg(adapter->dev, "event: LINK_SENSED\n");
        if (!netif_carrier_ok(priv->netdev))
            netif_carrier_on(priv->netdev);
        mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
        break;

    case EVENT_DEAUTHENTICATED:
        dev_dbg(adapter->dev, "event: Deauthenticated\n");
        if (priv->wps.session_enable) {
            dev_dbg(adapter->dev,
                    "info: receive deauth event in wps session\n");
            break;
        }
        adapter->dbg.num_event_deauth++;
        if (priv->media_connected) {
            reason_code =
                le16_to_cpu(*(__le16 *)adapter->event_body);
            mwifiex_reset_connect_state(priv, reason_code);
        }
        break;

    case EVENT_DISASSOCIATED:
        dev_dbg(adapter->dev, "event: Disassociated\n");
        if (priv->wps.session_enable) {
            dev_dbg(adapter->dev,
                    "info: receive disassoc event in wps session\n");
            break;
        }
        adapter->dbg.num_event_disassoc++;
        if (priv->media_connected) {
            reason_code =
                le16_to_cpu(*(__le16 *)adapter->event_body);
            mwifiex_reset_connect_state(priv, reason_code);
        }
        break;

    case EVENT_LINK_LOST:
        dev_dbg(adapter->dev, "event: Link lost\n");
        adapter->dbg.num_event_link_lost++;
        if (priv->media_connected) {
            reason_code =
                le16_to_cpu(*(__le16 *)adapter->event_body);
            mwifiex_reset_connect_state(priv, reason_code);
        }
        break;

    case EVENT_PS_SLEEP:
        dev_dbg(adapter->dev, "info: EVENT: SLEEP\n");

        adapter->ps_state = PS_STATE_PRE_SLEEP;

        mwifiex_check_ps_cond(adapter);
        break;

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

        break;

    case EVENT_DEEP_SLEEP_AWAKE:
        adapter->if_ops.wakeup_complete(adapter);
        dev_dbg(adapter->dev, "event: DS_AWAKE\n");
        if (adapter->is_deep_sleep)
            adapter->is_deep_sleep = false;
        break;

    case EVENT_HS_ACT_REQ:
        dev_dbg(adapter->dev, "event: HS_ACT_REQ\n");
        ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH,
                               0, 0, NULL, false);
        break;

    case EVENT_MIC_ERR_UNICAST:
        dev_dbg(adapter->dev, "event: UNICAST MIC ERROR\n");
        cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
                                     NL80211_KEYTYPE_PAIRWISE,
                                     -1, NULL, GFP_KERNEL);
        break;

    case EVENT_MIC_ERR_MULTICAST:
        dev_dbg(adapter->dev, "event: MULTICAST MIC ERROR\n");
        cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid,
                                     NL80211_KEYTYPE_GROUP,
                                     -1, NULL, GFP_KERNEL);
        break;
    case EVENT_MIB_CHANGED:
    case EVENT_INIT_DONE:
        break;

    case EVENT_ADHOC_BCN_LOST:
        dev_dbg(adapter->dev, "event: ADHOC_BCN_LOST\n");
        priv->adhoc_is_link_sensed = false;
        mwifiex_clean_txrx(priv);
        mwifiex_stop_net_dev_queue(priv->netdev, adapter);
        if (netif_carrier_ok(priv->netdev))
            netif_carrier_off(priv->netdev);
        break;

    case EVENT_BG_SCAN_REPORT:
        dev_dbg(adapter->dev, "event: BGS_REPORT\n");
        ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY,
                               HostCmd_ACT_GEN_GET, 0, NULL, false);
        break;

    case EVENT_PORT_RELEASE:
        dev_dbg(adapter->dev, "event: PORT RELEASE\n");
        break;

    case EVENT_EXT_SCAN_REPORT:
        dev_dbg(adapter->dev, "event: EXT_SCAN Report\n");
        if (adapter->ext_scan)
            ret = mwifiex_handle_event_ext_scan_report(priv,
                    adapter->event_skb->data);

        break;

    case EVENT_WMM_STATUS_CHANGE:
        dev_dbg(adapter->dev, "event: WMM status changed\n");
        ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS,
                               0, 0, NULL, false);
        break;

    case EVENT_RSSI_LOW:
        cfg80211_cqm_rssi_notify(priv->netdev,
                                 NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
                                 GFP_KERNEL);
        mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
                         HostCmd_ACT_GEN_GET, 0, NULL, false);
        priv->subsc_evt_rssi_state = RSSI_LOW_RECVD;
        dev_dbg(adapter->dev, "event: Beacon RSSI_LOW\n");
        break;
    case EVENT_SNR_LOW:
        dev_dbg(adapter->dev, "event: Beacon SNR_LOW\n");
        break;
    case EVENT_MAX_FAIL:
        dev_dbg(adapter->dev, "event: MAX_FAIL\n");
        break;
    case EVENT_RSSI_HIGH:
        cfg80211_cqm_rssi_notify(priv->netdev,
                                 NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
                                 GFP_KERNEL);
        mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
                         HostCmd_ACT_GEN_GET, 0, NULL, false);
        priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD;
        dev_dbg(adapter->dev, "event: Beacon RSSI_HIGH\n");
        break;
    case EVENT_SNR_HIGH:
        dev_dbg(adapter->dev, "event: Beacon SNR_HIGH\n");
        break;
    case EVENT_DATA_RSSI_LOW:
        dev_dbg(adapter->dev, "event: Data RSSI_LOW\n");
        break;
    case EVENT_DATA_SNR_LOW:
        dev_dbg(adapter->dev, "event: Data SNR_LOW\n");
        break;
    case EVENT_DATA_RSSI_HIGH:
        dev_dbg(adapter->dev, "event: Data RSSI_HIGH\n");
        break;
    case EVENT_DATA_SNR_HIGH:
        dev_dbg(adapter->dev, "event: Data SNR_HIGH\n");
        break;
    case EVENT_LINK_QUALITY:
        dev_dbg(adapter->dev, "event: Link Quality\n");
        break;
    case EVENT_PRE_BEACON_LOST:
        dev_dbg(adapter->dev, "event: Pre-Beacon Lost\n");
        break;
    case EVENT_IBSS_COALESCED:
        dev_dbg(adapter->dev, "event: IBSS_COALESCED\n");
        ret = mwifiex_send_cmd(priv,
                               HostCmd_CMD_802_11_IBSS_COALESCING_STATUS,
                               HostCmd_ACT_GEN_GET, 0, NULL, false);
        break;
    case EVENT_ADDBA:
        dev_dbg(adapter->dev, "event: ADDBA Request\n");
        mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP,
                         HostCmd_ACT_GEN_SET, 0,
                         adapter->event_body, false);
        break;
    case EVENT_DELBA:
        dev_dbg(adapter->dev, "event: DELBA Request\n");
        mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
        break;
    case EVENT_BA_STREAM_TIEMOUT:
        dev_dbg(adapter->dev, "event:  BA Stream timeout\n");
        mwifiex_11n_ba_stream_timeout(priv,
                                      (struct host_cmd_ds_11n_batimeout
                                       *)
                                      adapter->event_body);
        break;
    case EVENT_AMSDU_AGGR_CTRL:
        ctrl = le16_to_cpu(*(__le16 *)adapter->event_body);
        dev_dbg(adapter->dev, "event: AMSDU_AGGR_CTRL %d\n", ctrl);

        adapter->tx_buf_size =
            min_t(u16, adapter->curr_tx_buf_size, ctrl);
        dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
                adapter->tx_buf_size);
        break;

    case EVENT_WEP_ICV_ERR:
        dev_dbg(adapter->dev, "event: WEP ICV error\n");
        break;

    case EVENT_BW_CHANGE:
        dev_dbg(adapter->dev, "event: BW Change\n");
        break;

    case EVENT_HOSTWAKE_STAIE:
        dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause);
        break;

    case EVENT_REMAIN_ON_CHAN_EXPIRED:
        dev_dbg(adapter->dev, "event: Remain on channel expired\n");
        cfg80211_remain_on_channel_expired(priv->wdev,
                                           priv->roc_cfg.cookie,
                                           &priv->roc_cfg.chan,
                                           GFP_ATOMIC);

        memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg));

        break;

    case EVENT_CHANNEL_SWITCH_ANN:
        dev_dbg(adapter->dev, "event: Channel Switch Announcement\n");
        priv->csa_expire_time =
            jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME);
        priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel;
        ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
                               HostCmd_ACT_GEN_SET, 0,
                               priv->curr_bss_params.bss_descriptor.mac_address,
                               false);
        break;

    case EVENT_TDLS_GENERIC_EVENT:
        ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
        break;

    default:
        dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
                eventcause);
        break;
    }

    return ret;
}
コード例 #4
0
ファイル: join.c プロジェクト: AMouri/linux
/*
 * This function handles the command response of ad-hoc start and
 * ad-hoc join.
 *
 * The function generates a device-connected event to notify
 * the applications, in case of successful ad-hoc start/join, and
 * saves the beacon buffer.
 */
int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
			      struct host_cmd_ds_command *resp)
{
	int ret = 0;
	struct mwifiex_adapter *adapter = priv->adapter;
	struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result;
	struct mwifiex_bssdescriptor *bss_desc;

	adhoc_result = &resp->params.adhoc_result;

	bss_desc = priv->attempted_bss_desc;

	/* Join result code 0 --> SUCCESS */
	if (le16_to_cpu(resp->result)) {
		dev_err(priv->adapter->dev, "ADHOC_RESP: failed\n");
		if (priv->media_connected)
			mwifiex_reset_connect_state(priv);

		memset(&priv->curr_bss_params.bss_descriptor,
		       0x00, sizeof(struct mwifiex_bssdescriptor));

		ret = -1;
		goto done;
	}

	/* Send a Media Connected event, according to the Spec */
	priv->media_connected = true;

	if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) {
		dev_dbg(priv->adapter->dev, "info: ADHOC_S_RESP %s\n",
				bss_desc->ssid.ssid);

		/* Update the created network descriptor with the new BSSID */
		memcpy(bss_desc->mac_address,
		       adhoc_result->bssid, ETH_ALEN);

		priv->adhoc_state = ADHOC_STARTED;
	} else {
		/*
		 * Now the join cmd should be successful.
		 * If BSSID has changed use SSID to compare instead of BSSID
		 */
		dev_dbg(priv->adapter->dev, "info: ADHOC_J_RESP %s\n",
				bss_desc->ssid.ssid);

		/*
		 * Make a copy of current BSSID descriptor, only needed for
		 * join since the current descriptor is already being used
		 * for adhoc start
		 */
		memcpy(&priv->curr_bss_params.bss_descriptor,
		       bss_desc, sizeof(struct mwifiex_bssdescriptor));

		priv->adhoc_state = ADHOC_JOINED;
	}

	dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: channel = %d\n",
				priv->adhoc_channel);
	dev_dbg(priv->adapter->dev, "info: ADHOC_RESP: BSSID = %pM\n",
	       priv->curr_bss_params.bss_descriptor.mac_address);

	if (!netif_carrier_ok(priv->netdev))
		netif_carrier_on(priv->netdev);
	if (netif_queue_stopped(priv->netdev))
		netif_wake_queue(priv->netdev);

	mwifiex_save_curr_bcn(priv);

done:
	/* Need to indicate IOCTL complete */
	if (adapter->curr_cmd->wait_q_enabled) {
		if (ret)
			adapter->cmd_wait_q.status = -1;
		else
			adapter->cmd_wait_q.status = 0;

	}

	return ret;
}
コード例 #5
0
ファイル: ipheth.c プロジェクト: 020gzh/linux
static u32 ipheth_ethtool_op_get_link(struct net_device *net)
{
	struct ipheth_device *dev = netdev_priv(net);
	return netif_carrier_ok(dev->net);
}
コード例 #6
0
ファイル: xen-netfront.c プロジェクト: jay-caoj/linux-3.9.6
static void xennet_alloc_rx_buffers(struct net_device *dev)
{
	unsigned short id;
	struct netfront_info *np = netdev_priv(dev);
	struct sk_buff *skb;
	struct page *page;
	int i, batch_target, notify;
	RING_IDX req_prod = np->rx.req_prod_pvt;
	grant_ref_t ref;
	unsigned long pfn;
	void *vaddr;
	struct xen_netif_rx_request *req;

	if (unlikely(!netif_carrier_ok(dev)))
		return;

	/*
	 * Allocate skbuffs greedily, even though we batch updates to the
	 * receive ring. This creates a less bursty demand on the memory
	 * allocator, so should reduce the chance of failed allocation requests
	 * both for ourself and for other kernel subsystems.
	 */
	batch_target = np->rx_target - (req_prod - np->rx.rsp_cons);
	for (i = skb_queue_len(&np->rx_batch); i < batch_target; i++) {
		skb = __netdev_alloc_skb(dev, RX_COPY_THRESHOLD + NET_IP_ALIGN,
					 GFP_ATOMIC | __GFP_NOWARN);
		if (unlikely(!skb))
			goto no_skb;

		/* Align ip header to a 16 bytes boundary */
		skb_reserve(skb, NET_IP_ALIGN);

		page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
		if (!page) {
			kfree_skb(skb);
no_skb:
			/* Any skbuffs queued for refill? Force them out. */
			if (i != 0)
				goto refill;
			/* Could not allocate any skbuffs. Try again later. */
			mod_timer(&np->rx_refill_timer,
				  jiffies + (HZ/10));
			break;
		}

		__skb_fill_page_desc(skb, 0, page, 0, 0);
		skb_shinfo(skb)->nr_frags = 1;
		__skb_queue_tail(&np->rx_batch, skb);
	}

	/* Is the batch large enough to be worthwhile? */
	if (i < (np->rx_target/2)) {
		if (req_prod > np->rx.sring->req_prod)
			goto push;
		return;
	}

	/* Adjust our fill target if we risked running out of buffers. */
	if (((req_prod - np->rx.sring->rsp_prod) < (np->rx_target / 4)) &&
	    ((np->rx_target *= 2) > np->rx_max_target))
		np->rx_target = np->rx_max_target;

 refill:
	for (i = 0; ; i++) {
		skb = __skb_dequeue(&np->rx_batch);
		if (skb == NULL)
			break;

		skb->dev = dev;

		id = xennet_rxidx(req_prod + i);

		BUG_ON(np->rx_skbs[id]);
		np->rx_skbs[id] = skb;

		ref = gnttab_claim_grant_reference(&np->gref_rx_head);
		BUG_ON((signed short)ref < 0);
		np->grant_rx_ref[id] = ref;

		pfn = page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[0]));
		vaddr = page_address(skb_frag_page(&skb_shinfo(skb)->frags[0]));

		req = RING_GET_REQUEST(&np->rx, req_prod + i);
		gnttab_grant_foreign_access_ref(ref,
						np->xbdev->otherend_id,
						pfn_to_mfn(pfn),
						0);

		req->id = id;
		req->gref = ref;
	}

	wmb();		/* barrier so backend seens requests */

	/* Above is a suitable barrier to ensure backend will see requests. */
	np->rx.req_prod_pvt = req_prod + i;
 push:
	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->rx, notify);
	if (notify)
		notify_remote_via_irq(np->netdev->irq);
}
コード例 #7
0
static int netvsc_probe(struct device *device)
{
	struct driver_context *driver_ctx =
		driver_to_driver_context(device->driver);
	struct netvsc_driver_context *net_drv_ctx =
		(struct netvsc_driver_context *)driver_ctx;
	struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
	struct vm_device *device_ctx = device_to_vm_device(device);
	struct hv_device *device_obj = &device_ctx->device_obj;
	struct net_device *net = NULL;
	struct net_device_context *net_device_ctx;
	struct netvsc_device_info device_info;
	int ret;

	DPRINT_ENTER(NETVSC_DRV);

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

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

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

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

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

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

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

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

	net->netdev_ops = &device_ops;

	/* TODO: Add GSO and Checksum offload */
	net->features = NETIF_F_SG;

	SET_ETHTOOL_OPS(net, &ethtool_ops);
	SET_NETDEV_DEV(net, device);

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

	DPRINT_EXIT(NETVSC_DRV);
	return ret;
}
コード例 #8
0
ファイル: rtl8150.c プロジェクト: JBTech/ralink_rt5350
static int rtl8150_ethtool_ioctl(struct net_device *netdev, void *uaddr)
{
	rtl8150_t *dev;
	int cmd;
	char tmp[128];

	dev = netdev->priv;
	if (get_user(cmd, (int *) uaddr))
		return -EFAULT;

	switch (cmd) {
	case ETHTOOL_GDRVINFO:{
			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };

			strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN);
			strncpy(info.version, DRIVER_VERSION,
				ETHTOOL_BUSINFO_LEN);
			sprintf(tmp, "usb%d:%d", dev->udev->bus->busnum,
				dev->udev->devnum);
			strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
			if (copy_to_user(uaddr, &info, sizeof(info)))
				return -EFAULT;
			return 0;
		}
	case ETHTOOL_GSET:{
			struct ethtool_cmd ecmd;
			short lpa, bmcr;

			if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
				return -EFAULT;
			ecmd.supported = (SUPPORTED_10baseT_Half |
					  SUPPORTED_10baseT_Full |
					  SUPPORTED_100baseT_Half |
					  SUPPORTED_100baseT_Full |
					  SUPPORTED_Autoneg |
					  SUPPORTED_TP | SUPPORTED_MII);
			ecmd.port = PORT_TP;
			ecmd.transceiver = XCVR_INTERNAL;
			ecmd.phy_address = dev->phy;
			get_registers(dev, BMCR, 2, &bmcr);
			get_registers(dev, ANLP, 2, &lpa);
			if (bmcr & BMCR_ANENABLE) {
				ecmd.autoneg = AUTONEG_ENABLE;
				ecmd.speed =
				    (lpa & (LPA_100HALF | LPA_100FULL)) ?
				    SPEED_100 : SPEED_10;
				if (ecmd.speed == SPEED_100)
					ecmd.duplex = (lpa & LPA_100FULL) ?
					    DUPLEX_FULL : DUPLEX_HALF;
				else
					ecmd.duplex = (lpa & LPA_10FULL) ?
					    DUPLEX_FULL : DUPLEX_HALF;
			} else {
				ecmd.autoneg = AUTONEG_DISABLE;
				ecmd.speed = (bmcr & BMCR_SPEED100) ?
				    SPEED_100 : SPEED_10;
				ecmd.duplex = (bmcr & BMCR_FULLDPLX) ?
				    DUPLEX_FULL : DUPLEX_HALF;
			}
			if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
				return -EFAULT;
			return 0;
		}
	case ETHTOOL_SSET:
		return -ENOTSUPP;
	case ETHTOOL_GLINK:{
			struct ethtool_value edata = { ETHTOOL_GLINK };

			edata.data = netif_carrier_ok(netdev);
			if (copy_to_user(uaddr, &edata, sizeof(edata)))
				return -EFAULT;
			return 0;
		}
	default:
		return -EOPNOTSUPP;
	}
}
コード例 #9
0
static int
e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
	struct e1000_adapter *adapter = netdev->priv;
	struct e1000_hw *hw = &adapter->hw;

	if(hw->media_type == e1000_media_type_copper) {

		ecmd->supported = (SUPPORTED_10baseT_Half |
		                   SUPPORTED_10baseT_Full |
		                   SUPPORTED_100baseT_Half |
		                   SUPPORTED_100baseT_Full |
		                   SUPPORTED_1000baseT_Full|
		                   SUPPORTED_Autoneg |
		                   SUPPORTED_TP);

		ecmd->advertising = ADVERTISED_TP;

		if(hw->autoneg == 1) {
			ecmd->advertising |= ADVERTISED_Autoneg;

			/* the e1000 autoneg seems to match ethtool nicely */

			ecmd->advertising |= hw->autoneg_advertised;
		}

		ecmd->port = PORT_TP;
		ecmd->phy_address = hw->phy_addr;

		if(hw->mac_type == e1000_82543)
			ecmd->transceiver = XCVR_EXTERNAL;
		else
			ecmd->transceiver = XCVR_INTERNAL;

	} else {
		ecmd->supported   = (SUPPORTED_1000baseT_Full |
				     SUPPORTED_FIBRE |
				     SUPPORTED_Autoneg);

		ecmd->advertising = (SUPPORTED_1000baseT_Full |
				     SUPPORTED_FIBRE |
				     SUPPORTED_Autoneg);

		ecmd->port = PORT_FIBRE;

		if(hw->mac_type >= e1000_82545)
			ecmd->transceiver = XCVR_INTERNAL;
		else
			ecmd->transceiver = XCVR_EXTERNAL;
	}

	if(netif_carrier_ok(adapter->netdev)) {

		e1000_get_speed_and_duplex(hw, &adapter->link_speed,
		                                   &adapter->link_duplex);
		ecmd->speed = adapter->link_speed;

		/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
		 *          and HALF_DUPLEX != DUPLEX_HALF */

		if(adapter->link_duplex == FULL_DUPLEX)
			ecmd->duplex = DUPLEX_FULL;
		else
			ecmd->duplex = DUPLEX_HALF;
	} else {
		ecmd->speed = -1;
		ecmd->duplex = -1;
	}

	ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) ||
			 hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
	return 0;
}
コード例 #10
0
/*
 * The link status has changed on the indicated "port" (Virtual Interface).
 */
void t4vf_os_link_changed(struct adapter *adapter, int pidx, int link_ok)
{
	struct net_device *dev = adapter->port[pidx];

	/*
	 * If the port is disabled or the current recorded "link up"
	 * status matches the new status, just return.
	 */
	if (!netif_running(dev) || link_ok == netif_carrier_ok(dev))
		return;

	/*
	 * Tell the OS that the link status has changed and print a short
	 * informative message on the console about the event.
	 */
	if (link_ok) {
		const char *s;
		const char *fc;
		const struct port_info *pi = netdev_priv(dev);

		netif_carrier_on(dev);

		switch (pi->link_cfg.speed) {
		case SPEED_10000:
			s = "10Gbps";
			break;

		case SPEED_1000:
			s = "1000Mbps";
			break;

		case SPEED_100:
			s = "100Mbps";
			break;

		default:
			s = "unknown";
			break;
		}

		switch (pi->link_cfg.fc) {
		case PAUSE_RX:
			fc = "RX";
			break;

		case PAUSE_TX:
			fc = "TX";
			break;

		case PAUSE_RX|PAUSE_TX:
			fc = "RX/TX";
			break;

		default:
			fc = "no";
			break;
		}

		netdev_info(dev, "link up, %s, full-duplex, %s PAUSE\n", s, fc);
	} else {
		netif_carrier_off(dev);
		netdev_info(dev, "link down\n");
	}
}
コード例 #11
0
ファイル: af_mpls.c プロジェクト: 3bsa/linux
static bool mpls_output_possible(const struct net_device *dev)
{
	return dev && (dev->flags & IFF_UP) && netif_carrier_ok(dev);
}
コード例 #12
0
int netpoll_setup(struct netpoll *np)
{
	struct net_device *ndev = NULL;
	struct in_device *in_dev;
	struct netpoll_info *npinfo;
	unsigned long flags;
	int err;

	if (np->dev_name)
		ndev = dev_get_by_name(np->dev_name);
	if (!ndev) {
		printk(KERN_ERR "%s: %s doesn't exist, aborting.\n",
		       np->name, np->dev_name);
		return -ENODEV;
	}

	np->dev = ndev;
	if (!ndev->npinfo) {
		npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
		if (!npinfo) {
			err = -ENOMEM;
			goto release;
		}

		npinfo->rx_flags = 0;
		npinfo->rx_np = NULL;
		spin_lock_init(&npinfo->poll_lock);
		npinfo->poll_owner = -1;

		spin_lock_init(&npinfo->rx_lock);
		skb_queue_head_init(&npinfo->arp_tx);
		skb_queue_head_init(&npinfo->txq);
		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);

		atomic_set(&npinfo->refcnt, 1);
	} else {
		npinfo = ndev->npinfo;
		atomic_inc(&npinfo->refcnt);
	}

	if (!ndev->poll_controller) {
		printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
		       np->name, np->dev_name);
		err = -ENOTSUPP;
		goto release;
	}

	if (!netif_running(ndev)) {
		unsigned long atmost, atleast;

		printk(KERN_INFO "%s: device %s not up yet, forcing it\n",
		       np->name, np->dev_name);

		rtnl_lock();
		err = dev_open(ndev);
		rtnl_unlock();

		if (err) {
			printk(KERN_ERR "%s: failed to open %s\n",
			       np->name, ndev->name);
			goto release;
		}

		atleast = jiffies + HZ/10;
		atmost = jiffies + 4*HZ;
		while (!netif_carrier_ok(ndev)) {
			if (time_after(jiffies, atmost)) {
				printk(KERN_NOTICE
				       "%s: timeout waiting for carrier\n",
				       np->name);
				break;
			}
			cond_resched();
		}

		/* If carrier appears to come up instantly, we don't
		 * trust it and pause so that we don't pump all our
		 * queued console messages into the bitbucket.
		 */

		if (time_before(jiffies, atleast)) {
			printk(KERN_NOTICE "%s: carrier detect appears"
			       " untrustworthy, waiting 4 seconds\n",
			       np->name);
			msleep(4000);
		}
	}

	if (is_zero_ether_addr(np->local_mac) && ndev->dev_addr)
		memcpy(np->local_mac, ndev->dev_addr, 6);

	if (!np->local_ip) {
		rcu_read_lock();
		in_dev = __in_dev_get_rcu(ndev);

		if (!in_dev || !in_dev->ifa_list) {
			rcu_read_unlock();
			printk(KERN_ERR "%s: no IP address for %s, aborting\n",
			       np->name, np->dev_name);
			err = -EDESTADDRREQ;
			goto release;
		}

		np->local_ip = ntohl(in_dev->ifa_list->ifa_local);
		rcu_read_unlock();
		printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n",
		       np->name, HIPQUAD(np->local_ip));
	}

	if (np->rx_hook) {
		spin_lock_irqsave(&npinfo->rx_lock, flags);
		npinfo->rx_flags |= NETPOLL_RX_ENABLED;
		npinfo->rx_np = np;
		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
	}

	/* fill up the skb queue */
	refill_skbs();

	/* last thing to do is link it to the net device structure */
	ndev->npinfo = npinfo;

	/* avoid racing with NAPI reading npinfo */
	synchronize_rcu();

	return 0;

 release:
	if (!ndev->npinfo)
		kfree(npinfo);
	np->dev = NULL;
	dev_put(ndev);
	return err;
}
コード例 #13
0
ファイル: bcmmii.c プロジェクト: Claruarius/stblinux-2.6.37
/*
 * setup netdev link state when PHY link status change and
 * update UMAC and RGMII block when link up
 */
void bcmgenet_mii_setup(struct net_device *dev)
{
	struct BcmEnet_devctrl *pDevCtrl = netdev_priv(dev);
	struct ethtool_cmd ecmd ;
	volatile struct uniMacRegs *umac = pDevCtrl->umac;
	int cur_link, prev_link;
	unsigned int val, cmd_bits = 0;

	if (pDevCtrl->phyType == BRCM_PHY_TYPE_MOCA)
		return;

	cur_link = mii_link_ok(&pDevCtrl->mii);
	prev_link = netif_carrier_ok(pDevCtrl->dev);
	if (cur_link && !prev_link) {
		mii_ethtool_gset(&pDevCtrl->mii, &ecmd);
		/*
		 * program UMAC and RGMII block based on established link
		 * speed, pause, and duplex.
		 * the speed set in umac->cmd tell RGMII block which clock
		 * 25MHz(100Mbps)/125MHz(1Gbps) to use for transmit.
		 * receive clock is provided by PHY.
		 */
		if (pDevCtrl->phyType != BRCM_PHY_TYPE_EXT_RGMII_IBS) {
			GENET_RGMII_OOB_CTRL(pDevCtrl) &= ~OOB_DISABLE;
			GENET_RGMII_OOB_CTRL(pDevCtrl) |= RGMII_LINK;

			/* speed */
			if (ecmd.speed == SPEED_1000)
				cmd_bits = UMAC_SPEED_1000;
			else if (ecmd.speed == SPEED_100)
				cmd_bits = UMAC_SPEED_100;
			else
				cmd_bits = UMAC_SPEED_10;
			cmd_bits <<= CMD_SPEED_SHIFT;

			/* duplex */
			if (ecmd.duplex != DUPLEX_FULL)
				cmd_bits |= CMD_HD_EN;

		}
		/* pause capability */
		if (pDevCtrl->phyType == BRCM_PHY_TYPE_INT ||
		    pDevCtrl->phyType == BRCM_PHY_TYPE_EXT_MII) {
			val = bcmgenet_mii_read(
				dev, pDevCtrl->phyAddr, MII_LPA);
			if (!(val & LPA_PAUSE_CAP)) {
				cmd_bits |= CMD_RX_PAUSE_IGNORE;
				cmd_bits |= CMD_TX_PAUSE_IGNORE;
			}
		} else if (pDevCtrl->phyType == BRCM_PHY_TYPE_EXT_RGMII ||
			   pDevCtrl->phyType == BRCM_PHY_TYPE_EXT_RGMII_IBS) {
			val = bcmgenet_mii_read(dev,
				pDevCtrl->phyAddr, MII_BRCM_AUX_STAT_SUM);
			if (!(val & MII_BRCM_AUX_GPHY_RX_PAUSE))
				cmd_bits |= CMD_RX_PAUSE_IGNORE;
			if (!(val & MII_BRCM_AUX_GPHY_TX_PAUSE))
				cmd_bits |= CMD_TX_PAUSE_IGNORE;
		}

		umac->cmd &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
			       CMD_HD_EN |
			       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
		umac->cmd |= cmd_bits;

		netif_carrier_on(pDevCtrl->dev);
		netdev_info(dev, "link up, %d Mbps, %s duplex\n", ecmd.speed,
			ecmd.duplex == DUPLEX_FULL ? "full" : "half");
	} else if (!cur_link && prev_link) {
		netif_carrier_off(pDevCtrl->dev);
		netdev_info(dev, "link down\n");
	}
}
コード例 #14
0
ファイル: link_watch.c プロジェクト: AlexShiLucky/linux
void linkwatch_init_dev(struct net_device *dev)
{
	/* Handle pre-registration link state changes */
	if (!netif_carrier_ok(dev) || netif_dormant(dev))
		rfc2863_policy(dev);
}
コード例 #15
0
ファイル: sta_ioctl.c プロジェクト: Astralix/mainline-dss11
/*
 * In Ad-Hoc mode, the IBSS is created if not found in scan list.
 * In both Ad-Hoc and infra mode, an deauthentication is performed
 * first.
 */
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
		      struct cfg80211_ssid *req_ssid)
{
	int ret;
	struct mwifiex_adapter *adapter = priv->adapter;
	struct mwifiex_bssdescriptor *bss_desc = NULL;

	priv->scan_block = false;

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

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

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

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

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

		if (!bss_desc)
			return -1;

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

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

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

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

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

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

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

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

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

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

		priv->adhoc_is_link_sensed = false;

		ret = mwifiex_check_network_compatibility(priv, bss_desc);

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

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

done:
	/* beacon_ie buffer was allocated in function
	 * mwifiex_fill_new_bss_desc(). Free it now.
	 */
	if (bss_desc)
		kfree(bss_desc->beacon_buf);
	kfree(bss_desc);
	return ret;
}
コード例 #16
0
ファイル: phylink.c プロジェクト: SantoshShilimkar/linux
static void phylink_resolve(struct work_struct *w)
{
	struct phylink *pl = container_of(w, struct phylink, resolve);
	struct phylink_link_state link_state;
	struct net_device *ndev = pl->netdev;

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

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

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

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

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

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

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

		case MLO_AN_8023Z:
			phylink_get_mac_state(pl, &link_state);
			break;
		}
	}

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

			netif_carrier_on(ndev);

			netdev_info(ndev,
				    "Link is Up - %s/%s - flow control %s\n",
				    phy_speed_to_str(link_state.speed),
				    phy_duplex_to_str(link_state.duplex),
				    phylink_pause_to_str(link_state.pause));
		}
	}
	if (!link_state.link && pl->mac_link_dropped) {
		pl->mac_link_dropped = false;
		queue_work(system_power_efficient_wq, &pl->resolve);
	}
	mutex_unlock(&pl->state_mutex);
}
コード例 #17
0
ファイル: wext.c プロジェクト: Addision/LVS
static int orinoco_ioctl_setiwencode(struct net_device *dev,
				     struct iw_request_info *info,
				     struct iw_point *erq,
				     char *keybuf)
{
	struct orinoco_private *priv = ndev_priv(dev);
	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
	int setindex = priv->tx_key;
	enum orinoco_alg encode_alg = priv->encode_alg;
	int restricted = priv->wep_restrict;
	int err = -EINPROGRESS;		/* Call commit handler */
	unsigned long flags;

	if (!priv->has_wep)
		return -EOPNOTSUPP;

	if (erq->pointer) {
		/* We actually have a key to set - check its length */
		if (erq->length > LARGE_KEY_SIZE)
			return -E2BIG;

		if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep)
			return -E2BIG;
	}

	if (orinoco_lock(priv, &flags) != 0)
		return -EBUSY;

	/* Clear any TKIP key we have */
	if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
		(void) orinoco_clear_tkip_key(priv, setindex);

	if (erq->length > 0) {
		if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
			index = priv->tx_key;

		/* Switch on WEP if off */
		if (encode_alg != ORINOCO_ALG_WEP) {
			setindex = index;
			encode_alg = ORINOCO_ALG_WEP;
		}
	} else {
		/* Important note : if the user do "iwconfig eth0 enc off",
		 * we will arrive there with an index of -1. This is valid
		 * but need to be taken care off... Jean II */
		if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
			if ((index != -1) || (erq->flags == 0)) {
				err = -EINVAL;
				goto out;
			}
		} else {
			/* Set the index : Check that the key is valid */
			if (priv->keys[index].key_len == 0) {
				err = -EINVAL;
				goto out;
			}
			setindex = index;
		}
	}

	if (erq->flags & IW_ENCODE_DISABLED)
		encode_alg = ORINOCO_ALG_NONE;
	if (erq->flags & IW_ENCODE_OPEN)
		restricted = 0;
	if (erq->flags & IW_ENCODE_RESTRICTED)
		restricted = 1;

	if (erq->pointer && erq->length > 0) {
		err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
				      erq->length, NULL, 0);
	}
	priv->tx_key = setindex;

	/* Try fast key change if connected and only keys are changed */
	if ((priv->encode_alg == encode_alg) &&
	    (priv->wep_restrict == restricted) &&
	    netif_carrier_ok(dev)) {
		err = __orinoco_hw_setup_wepkeys(priv);
		/* No need to commit if successful */
		goto out;
	}

	priv->encode_alg = encode_alg;
	priv->wep_restrict = restricted;

 out:
	orinoco_unlock(priv, &flags);

	return err;
}
コード例 #18
0
static bool linkwatch_urgent_event(struct net_device *dev)
{
	return netif_running(dev) && netif_carrier_ok(dev) &&
		qdisc_tx_changing(dev);
}
コード例 #19
0
ファイル: xen-netfront.c プロジェクト: jay-caoj/linux-3.9.6
static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	unsigned short id;
	struct netfront_info *np = netdev_priv(dev);
	struct netfront_stats *stats = this_cpu_ptr(np->stats);
	struct xen_netif_tx_request *tx;
	struct xen_netif_extra_info *extra;
	char *data = skb->data;
	RING_IDX i;
	grant_ref_t ref;
	unsigned long mfn;
	int notify;
	int slots;
	unsigned int offset = offset_in_page(data);
	unsigned int len = skb_headlen(skb);
	unsigned long flags;

	/* If skb->len is too big for wire format, drop skb and alert
	 * user about misconfiguration.
	 */
	if (unlikely(skb->len > XEN_NETIF_MAX_TX_SIZE)) {
		net_alert_ratelimited(
			"xennet: skb->len = %u, too big for wire format\n",
			skb->len);
		goto drop;
	}

	slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
		xennet_count_skb_frag_slots(skb);
	if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
		net_alert_ratelimited(
			"xennet: skb rides the rocket: %d slots\n", slots);
		goto drop;
	}

	spin_lock_irqsave(&np->tx_lock, flags);

	if (unlikely(!netif_carrier_ok(dev) ||
		     (slots > 1 && !xennet_can_sg(dev)) ||
		     netif_needs_gso(skb, netif_skb_features(skb)))) {
		spin_unlock_irqrestore(&np->tx_lock, flags);
		goto drop;
	}

	i = np->tx.req_prod_pvt;

	id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
	np->tx_skbs[id].skb = skb;

	tx = RING_GET_REQUEST(&np->tx, i);

	tx->id   = id;
	ref = gnttab_claim_grant_reference(&np->gref_tx_head);
	BUG_ON((signed short)ref < 0);
	mfn = virt_to_mfn(data);
	gnttab_grant_foreign_access_ref(
		ref, np->xbdev->otherend_id, mfn, GNTMAP_readonly);
	tx->gref = np->grant_tx_ref[id] = ref;
	tx->offset = offset;
	tx->size = len;
	extra = NULL;

	tx->flags = 0;
	if (skb->ip_summed == CHECKSUM_PARTIAL)
		/* local packet? */
		tx->flags |= XEN_NETTXF_csum_blank | XEN_NETTXF_data_validated;
	else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
		/* remote but checksummed. */
		tx->flags |= XEN_NETTXF_data_validated;

	if (skb_shinfo(skb)->gso_size) {
		struct xen_netif_extra_info *gso;

		gso = (struct xen_netif_extra_info *)
			RING_GET_REQUEST(&np->tx, ++i);

		if (extra)
			extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
		else
			tx->flags |= XEN_NETTXF_extra_info;

		gso->u.gso.size = skb_shinfo(skb)->gso_size;
		gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
		gso->u.gso.pad = 0;
		gso->u.gso.features = 0;

		gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
		gso->flags = 0;
		extra = gso;
	}

	np->tx.req_prod_pvt = i + 1;

	xennet_make_frags(skb, dev, tx);
	tx->size = skb->len;

	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&np->tx, notify);
	if (notify)
		notify_remote_via_irq(np->netdev->irq);

	u64_stats_update_begin(&stats->syncp);
	stats->tx_bytes += skb->len;
	stats->tx_packets++;
	u64_stats_update_end(&stats->syncp);

	/* Note: It is not safe to access skb after xennet_tx_buf_gc()! */
	xennet_tx_buf_gc(dev);

	if (!netfront_tx_slot_available(np))
		netif_stop_queue(dev);

	spin_unlock_irqrestore(&np->tx_lock, flags);

	return NETDEV_TX_OK;

 drop:
	dev->stats.tx_dropped++;
	dev_kfree_skb(skb);
	return NETDEV_TX_OK;
}
コード例 #20
0
ファイル: ethtool.c プロジェクト: A-K/linux
static int e1000_get_settings(struct net_device *netdev,
			      struct ethtool_cmd *ecmd)
{
	struct e1000_adapter *adapter = netdev_priv(netdev);
	struct e1000_hw *hw = &adapter->hw;
	u32 speed;

	if (hw->phy.media_type == e1000_media_type_copper) {

		ecmd->supported = (SUPPORTED_10baseT_Half |
				   SUPPORTED_10baseT_Full |
				   SUPPORTED_100baseT_Half |
				   SUPPORTED_100baseT_Full |
				   SUPPORTED_1000baseT_Full |
				   SUPPORTED_Autoneg |
				   SUPPORTED_TP);
		if (hw->phy.type == e1000_phy_ife)
			ecmd->supported &= ~SUPPORTED_1000baseT_Full;
		ecmd->advertising = ADVERTISED_TP;

		if (hw->mac.autoneg == 1) {
			ecmd->advertising |= ADVERTISED_Autoneg;
			/* the e1000 autoneg seems to match ethtool nicely */
			ecmd->advertising |= hw->phy.autoneg_advertised;
		}

		ecmd->port = PORT_TP;
		ecmd->phy_address = hw->phy.addr;
		ecmd->transceiver = XCVR_INTERNAL;

	} else {
		ecmd->supported   = (SUPPORTED_1000baseT_Full |
				     SUPPORTED_FIBRE |
				     SUPPORTED_Autoneg);

		ecmd->advertising = (ADVERTISED_1000baseT_Full |
				     ADVERTISED_FIBRE |
				     ADVERTISED_Autoneg);

		ecmd->port = PORT_FIBRE;
		ecmd->transceiver = XCVR_EXTERNAL;
	}

	speed = -1;
	ecmd->duplex = -1;

	if (netif_running(netdev)) {
		if (netif_carrier_ok(netdev)) {
			speed = adapter->link_speed;
			ecmd->duplex = adapter->link_duplex - 1;
		}
	} else {
		u32 status = er32(STATUS);
		if (status & E1000_STATUS_LU) {
			if (status & E1000_STATUS_SPEED_1000)
				speed = SPEED_1000;
			else if (status & E1000_STATUS_SPEED_100)
				speed = SPEED_100;
			else
				speed = SPEED_10;

			if (status & E1000_STATUS_FD)
				ecmd->duplex = DUPLEX_FULL;
			else
				ecmd->duplex = DUPLEX_HALF;
		}
	}

	ethtool_cmd_speed_set(ecmd, speed);
	ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) ||
			 hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE;

	/* MDI-X => 2; MDI =>1; Invalid =>0 */
	if ((hw->phy.media_type == e1000_media_type_copper) &&
	    netif_carrier_ok(netdev))
		ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X :
		                                      ETH_TP_MDI;
	else
		ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID;

	if (hw->phy.mdix == AUTO_ALL_MODES)
		ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO;
	else
		ecmd->eth_tp_mdix_ctrl = hw->phy.mdix;

	return 0;
}
コード例 #21
0
ファイル: pegasus.c プロジェクト: iPodLinux/linux-2.6.7-ipod
static int pegasus_ethtool_ioctl(struct net_device *net, void __user *uaddr)
{
	pegasus_t *pegasus;
	int cmd;

	pegasus = net->priv;
	if (get_user(cmd, (int __user *) uaddr))
		return -EFAULT;
	switch (cmd) {
	case ETHTOOL_GDRVINFO:{
			struct ethtool_drvinfo info;
			memset (&info, 0, sizeof (info));
			info.cmd = ETHTOOL_GDRVINFO;
			strncpy(info.driver, driver_name,
				sizeof (info.driver) - 1);
			strncpy(info.version, DRIVER_VERSION,
				sizeof (info.version) - 1);
			usb_make_path(pegasus->usb, info.bus_info,
				      sizeof (info.bus_info));
			if (copy_to_user(uaddr, &info, sizeof (info)))
				return -EFAULT;
			return 0;
		}
	case ETHTOOL_GSET:{
			struct ethtool_cmd ecmd;
			short lpa, bmcr;
			u8 port;

			memset(&ecmd, 0, sizeof (ecmd));
			ecmd.supported = (SUPPORTED_10baseT_Half |
					  SUPPORTED_10baseT_Full |
					  SUPPORTED_100baseT_Half |
					  SUPPORTED_100baseT_Full |
					  SUPPORTED_Autoneg |
					  SUPPORTED_TP | SUPPORTED_MII);
			get_registers(pegasus, Reg7b, 1, &port);
			if (port == 0)
				ecmd.port = PORT_MII;
			else
				ecmd.port = PORT_TP;
			ecmd.transceiver = XCVR_INTERNAL;
			ecmd.phy_address = pegasus->phy;
			read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
			read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
			if (bmcr & BMCR_ANENABLE) {
				ecmd.autoneg = AUTONEG_ENABLE;
				ecmd.speed = lpa & (LPA_100HALF | LPA_100FULL) ?
				    SPEED_100 : SPEED_10;
				if (ecmd.speed == SPEED_100)
					ecmd.duplex = lpa & LPA_100FULL ?
					    DUPLEX_FULL : DUPLEX_HALF;
				else
					ecmd.duplex = lpa & LPA_10FULL ?
					    DUPLEX_FULL : DUPLEX_HALF;
			} else {
				ecmd.autoneg = AUTONEG_DISABLE;
				ecmd.speed = bmcr & BMCR_SPEED100 ?
				    SPEED_100 : SPEED_10;
				ecmd.duplex = bmcr & BMCR_FULLDPLX ?
				    DUPLEX_FULL : DUPLEX_HALF;
			}
			if (copy_to_user(uaddr, &ecmd, sizeof (ecmd)))
				return -EFAULT;

			return 0;
		}
	case ETHTOOL_SSET:{
			return -EOPNOTSUPP;
		}
	case ETHTOOL_GLINK:{
			struct ethtool_value edata = { ETHTOOL_GLINK };
			edata.data = netif_carrier_ok(net);
			if (copy_to_user(uaddr, &edata, sizeof (edata)))
				return -EFAULT;
			return 0;
		}
	default:
		return -EOPNOTSUPP;
	}
}
コード例 #22
0
ファイル: debugfs.c プロジェクト: DenisLug/mptcp
/*
 * Proc info file read handler.
 *
 * This function is called when the 'info' file is opened for reading.
 * It prints the following driver related information -
 *      - Driver name
 *      - Driver version
 *      - Driver extended version
 *      - Interface name
 *      - BSS mode
 *      - Media state (connected or disconnected)
 *      - MAC address
 *      - Total number of Tx bytes
 *      - Total number of Rx bytes
 *      - Total number of Tx packets
 *      - Total number of Rx packets
 *      - Total number of dropped Tx packets
 *      - Total number of dropped Rx packets
 *      - Total number of corrupted Tx packets
 *      - Total number of corrupted Rx packets
 *      - Carrier status (on or off)
 *      - Tx queue status (started or stopped)
 *
 * For STA mode drivers, it also prints the following extra -
 *      - ESSID
 *      - BSSID
 *      - Channel
 *      - Region code
 *      - Multicast count
 *      - Multicast addresses
 */
static ssize_t
mwifiex_info_read(struct file *file, char __user *ubuf,
		  size_t count, loff_t *ppos)
{
	struct mwifiex_private *priv =
		(struct mwifiex_private *) file->private_data;
	struct net_device *netdev = priv->netdev;
	struct netdev_hw_addr *ha;
	struct netdev_queue *txq;
	unsigned long page = get_zeroed_page(GFP_KERNEL);
	char *p = (char *) page, fmt[64];
	struct mwifiex_bss_info info;
	ssize_t ret;
	int i = 0;

	if (!p)
		return -ENOMEM;

	memset(&info, 0, sizeof(info));
	ret = mwifiex_get_bss_info(priv, &info);
	if (ret)
		goto free_and_exit;

	mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1);

	if (!priv->version_str[0])
		mwifiex_get_ver_ext(priv);

	p += sprintf(p, "driver_name = " "\"mwifiex\"\n");
	p += sprintf(p, "driver_version = %s", fmt);
	p += sprintf(p, "\nverext = %s", priv->version_str);
	p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name);

	if (info.bss_mode >= ARRAY_SIZE(bss_modes))
		p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode);
	else
		p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]);

	p += sprintf(p, "media_state=\"%s\"\n",
		     (!priv->media_connected ? "Disconnected" : "Connected"));
	p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr);

	if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
		p += sprintf(p, "multicast_count=\"%d\"\n",
			     netdev_mc_count(netdev));
		p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
		p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
		p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
		p += sprintf(p, "country_code = \"%s\"\n", info.country_code);

		netdev_for_each_mc_addr(ha, netdev)
			p += sprintf(p, "multicast_address[%d]=\"%pM\"\n",
					i++, ha->addr);
	}

	p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes);
	p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes);
	p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets);
	p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets);
	p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped);
	p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped);
	p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors);
	p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors);
	p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev))
					 ? "on" : "off"));
	p += sprintf(p, "tx queue");
	for (i = 0; i < netdev->num_tx_queues; i++) {
		txq = netdev_get_tx_queue(netdev, i);
		p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ?
			     "stopped" : "started");
	}
	p += sprintf(p, "\n");

	ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
				      (unsigned long) p - page);

free_and_exit:
	free_page(page);
	return ret;
}
コード例 #23
0
ファイル: join.c プロジェクト: AMouri/linux
/*
 * Association firmware command response handler
 *
 * The response buffer for the association command has the following
 * memory layout.
 *
 * For cases where an association response was not received (indicated
 * by the CapInfo and AId field):
 *
 *     .------------------------------------------------------------.
 *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
 *     .------------------------------------------------------------.
 *     |  cap_info/Error Return(t_u16):                             |
 *     |           0xFFFF(-1): Internal error                       |
 *     |           0xFFFE(-2): Authentication unhandled message     |
 *     |           0xFFFD(-3): Authentication refused               |
 *     |           0xFFFC(-4): Timeout waiting for AP response      |
 *     .------------------------------------------------------------.
 *     |  status_code(t_u16):                                       |
 *     |        If cap_info is -1:                                  |
 *     |           An internal firmware failure prevented the       |
 *     |           command from being processed.  The status_code   |
 *     |           will be set to 1.                                |
 *     |                                                            |
 *     |        If cap_info is -2:                                  |
 *     |           An authentication frame was received but was     |
 *     |           not handled by the firmware.  IEEE Status        |
 *     |           code for the failure is returned.                |
 *     |                                                            |
 *     |        If cap_info is -3:                                  |
 *     |           An authentication frame was received and the     |
 *     |           status_code is the IEEE Status reported in the   |
 *     |           response.                                        |
 *     |                                                            |
 *     |        If cap_info is -4:                                  |
 *     |           (1) Association response timeout                 |
 *     |           (2) Authentication response timeout              |
 *     .------------------------------------------------------------.
 *     |  a_id(t_u16): 0xFFFF                                       |
 *     .------------------------------------------------------------.
 *
 *
 * For cases where an association response was received, the IEEE
 * standard association response frame is returned:
 *
 *     .------------------------------------------------------------.
 *     |  Header(4 * sizeof(t_u16)):  Standard command response hdr |
 *     .------------------------------------------------------------.
 *     |  cap_info(t_u16): IEEE Capability                          |
 *     .------------------------------------------------------------.
 *     |  status_code(t_u16): IEEE Status Code                      |
 *     .------------------------------------------------------------.
 *     |  a_id(t_u16): IEEE Association ID                          |
 *     .------------------------------------------------------------.
 *     |  IEEE IEs(variable): Any received IEs comprising the       |
 *     |                      remaining portion of a received       |
 *     |                      association response frame.           |
 *     .------------------------------------------------------------.
 *
 * For simplistic handling, the status_code field can be used to determine
 * an association success (0) or failure (non-zero).
 */
int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
			     struct host_cmd_ds_command *resp)
{
	struct mwifiex_adapter *adapter = priv->adapter;
	int ret = 0;
	struct ieee_types_assoc_rsp *assoc_rsp;
	struct mwifiex_bssdescriptor *bss_desc;
	u8 enable_data = true;

	assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params;

	priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN,
				     sizeof(priv->assoc_rsp_buf));

	memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size);

	if (le16_to_cpu(assoc_rsp->status_code)) {
		priv->adapter->dbg.num_cmd_assoc_failure++;
		dev_err(priv->adapter->dev, "ASSOC_RESP: association failed, "
		       "status code = %d, error = 0x%x, a_id = 0x%x\n",
		       le16_to_cpu(assoc_rsp->status_code),
		       le16_to_cpu(assoc_rsp->cap_info_bitmap),
		       le16_to_cpu(assoc_rsp->a_id));

		ret = -1;
		goto done;
	}

	/* Send a Media Connected event, according to the Spec */
	priv->media_connected = true;

	priv->adapter->ps_state = PS_STATE_AWAKE;
	priv->adapter->pps_uapsd_mode = false;
	priv->adapter->tx_lock_flag = false;

	/* Set the attempted BSSID Index to current */
	bss_desc = priv->attempted_bss_desc;

	dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: %s\n",
						bss_desc->ssid.ssid);

	/* Make a copy of current BSSID descriptor */
	memcpy(&priv->curr_bss_params.bss_descriptor,
	       bss_desc, sizeof(struct mwifiex_bssdescriptor));

	/* Update curr_bss_params */
	priv->curr_bss_params.bss_descriptor.channel
		= bss_desc->phy_param_set.ds_param_set.current_chan;

	priv->curr_bss_params.band = (u8) bss_desc->bss_band;

	if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
		priv->curr_bss_params.wmm_enabled = true;
	else
		priv->curr_bss_params.wmm_enabled = false;

	if ((priv->wmm_required || bss_desc->bcn_ht_cap)
			&& priv->curr_bss_params.wmm_enabled)
		priv->wmm_enabled = true;
	else
		priv->wmm_enabled = false;

	priv->curr_bss_params.wmm_uapsd_enabled = false;

	if (priv->wmm_enabled)
		priv->curr_bss_params.wmm_uapsd_enabled
			= ((bss_desc->wmm_ie.qos_info_bitmap &
				IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0);

	dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: curr_pkt_filter is %#x\n",
	       priv->curr_pkt_filter);
	if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
		priv->wpa_is_gtk_set = false;

	if (priv->wmm_enabled) {
		/* Don't re-enable carrier until we get the WMM_GET_STATUS
		   event */
		enable_data = false;
	} else {
		/* Since WMM is not enabled, setup the queues with the
		   defaults */
		mwifiex_wmm_setup_queue_priorities(priv, NULL);
		mwifiex_wmm_setup_ac_downgrade(priv);
	}

	if (enable_data)
		dev_dbg(priv->adapter->dev,
			"info: post association, re-enabling data flow\n");

	/* Reset SNR/NF/RSSI values */
	priv->data_rssi_last = 0;
	priv->data_nf_last = 0;
	priv->data_rssi_avg = 0;
	priv->data_nf_avg = 0;
	priv->bcn_rssi_last = 0;
	priv->bcn_nf_last = 0;
	priv->bcn_rssi_avg = 0;
	priv->bcn_nf_avg = 0;
	priv->rxpd_rate = 0;
	priv->rxpd_htinfo = 0;

	mwifiex_save_curr_bcn(priv);

	priv->adapter->dbg.num_cmd_assoc_success++;

	dev_dbg(priv->adapter->dev, "info: ASSOC_RESP: associated\n");

	/* Add the ra_list here for infra mode as there will be only 1 ra
	   always */
	mwifiex_ralist_add(priv,
			   priv->curr_bss_params.bss_descriptor.mac_address);

	if (!netif_carrier_ok(priv->netdev))
		netif_carrier_on(priv->netdev);
	if (netif_queue_stopped(priv->netdev))
		netif_wake_queue(priv->netdev);

	if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
		priv->scan_block = true;

done:
	/* Need to indicate IOCTL complete */
	if (adapter->curr_cmd->wait_q_enabled) {
		if (ret)
			adapter->cmd_wait_q.status = -1;
		else
			adapter->cmd_wait_q.status = 0;
	}

	return ret;
}
コード例 #24
0
ファイル: ethernet-rgmii.c プロジェクト: 303750856/linux-3.1
static void cvm_oct_rgmii_poll(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	unsigned long flags = 0;
	cvmx_helper_link_info_t link_info;
	int use_global_register_lock = (priv->phydev == NULL);

	BUG_ON(in_interrupt());
	if (use_global_register_lock) {
		/*
		 * Take the global register lock since we are going to
		 * touch registers that affect more than one port.
		 */
		spin_lock_irqsave(&global_register_lock, flags);
	} else {
		mutex_lock(&priv->phydev->bus->mdio_lock);
	}

	link_info = cvmx_helper_link_get(priv->port);
	if (link_info.u64 == priv->link_info) {

		/*
		 * If the 10Mbps preamble workaround is supported and we're
		 * at 10Mbps we may need to do some special checking.
		 */
		if (USE_10MBPS_PREAMBLE_WORKAROUND && (link_info.s.speed == 10)) {

			/*
			 * Read the GMXX_RXX_INT_REG[PCTERR] bit and
			 * see if we are getting preamble errors.
			 */
			int interface = INTERFACE(priv->port);
			int index = INDEX(priv->port);
			union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
			gmxx_rxx_int_reg.u64 =
			    cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
					  (index, interface));
			if (gmxx_rxx_int_reg.s.pcterr) {

				/*
				 * We are getting preamble errors at
				 * 10Mbps.  Most likely the PHY is
				 * giving us packets with mis aligned
				 * preambles. In order to get these
				 * packets we need to disable preamble
				 * checking and do it in software.
				 */
				union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
				union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;

				/* Disable preamble checking */
				gmxx_rxx_frm_ctl.u64 =
				    cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL
						  (index, interface));
				gmxx_rxx_frm_ctl.s.pre_chk = 0;
				cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL
					       (index, interface),
					       gmxx_rxx_frm_ctl.u64);

				/* Disable FCS stripping */
				ipd_sub_port_fcs.u64 =
				    cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
				ipd_sub_port_fcs.s.port_bit &=
				    0xffffffffull ^ (1ull << priv->port);
				cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS,
					       ipd_sub_port_fcs.u64);

				/* Clear any error bits */
				cvmx_write_csr(CVMX_GMXX_RXX_INT_REG
					       (index, interface),
					       gmxx_rxx_int_reg.u64);
				printk_ratelimited("%s: Using 10Mbps with software "
						   "preamble removal\n",
						   dev->name);
			}
		}

		if (use_global_register_lock)
			spin_unlock_irqrestore(&global_register_lock, flags);
		else
			mutex_unlock(&priv->phydev->bus->mdio_lock);
		return;
	}

	/* If the 10Mbps preamble workaround is allowed we need to on
	   preamble checking, FCS stripping, and clear error bits on
	   every speed change. If errors occur during 10Mbps operation
	   the above code will change this stuff */
	if (USE_10MBPS_PREAMBLE_WORKAROUND) {

		union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
		union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
		union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
		int interface = INTERFACE(priv->port);
		int index = INDEX(priv->port);

		/* Enable preamble checking */
		gmxx_rxx_frm_ctl.u64 =
		    cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface));
		gmxx_rxx_frm_ctl.s.pre_chk = 1;
		cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
			       gmxx_rxx_frm_ctl.u64);
		/* Enable FCS stripping */
		ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
		ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
		cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);
		/* Clear any error bits */
		gmxx_rxx_int_reg.u64 =
		    cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index, interface));
		cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
			       gmxx_rxx_int_reg.u64);
	}
	if (priv->phydev == NULL) {
		link_info = cvmx_helper_link_autoconf(priv->port);
		priv->link_info = link_info.u64;
	}

	if (use_global_register_lock)
		spin_unlock_irqrestore(&global_register_lock, flags);
	else {
		mutex_unlock(&priv->phydev->bus->mdio_lock);
	}

	if (priv->phydev == NULL) {
		/* Tell core. */
		if (link_info.s.link_up) {
			if (!netif_carrier_ok(dev))
				netif_carrier_on(dev);
			if (priv->queue != -1)
				printk_ratelimited("%s: %u Mbps %s duplex, "
						   "port %2d, queue %2d\n",
						   dev->name, link_info.s.speed,
						   (link_info.s.full_duplex) ?
						   "Full" : "Half",
						   priv->port, priv->queue);
			else
				printk_ratelimited("%s: %u Mbps %s duplex, "
						   "port %2d, POW\n",
						   dev->name, link_info.s.speed,
						   (link_info.s.full_duplex) ?
						   "Full" : "Half",
						   priv->port);
		} else {
			if (netif_carrier_ok(dev))
				netif_carrier_off(dev);
			printk_ratelimited("%s: Link down\n", dev->name);
		}
	}
}
コード例 #25
0
static int br_device_event(struct notifier_block *unused, unsigned long event, void *ptr)
{
    struct net_device *dev = ptr;
    struct net_bridge_port *p = dev->br_port;
    struct net_bridge *br;
    int err;

    /* not a port of a bridge */
    if (p == NULL)
        return NOTIFY_DONE;

    br = p->br;

    switch (event) {
    case NETDEV_CHANGEMTU:
        dev_set_mtu(br->dev, br_min_mtu(br));
        break;

    case NETDEV_CHANGEADDR:
        spin_lock_bh(&br->lock);
        br_fdb_changeaddr(p, dev->dev_addr);
        br_stp_recalculate_bridge_id(br);
        spin_unlock_bh(&br->lock);
        break;

    case NETDEV_CHANGE:
        br_port_carrier_check(p);
        break;

    case NETDEV_FEAT_CHANGE:
        spin_lock_bh(&br->lock);
        if (netif_running(br->dev))
            br_features_recompute(br);
        spin_unlock_bh(&br->lock);
        break;

    case NETDEV_DOWN:
        spin_lock_bh(&br->lock);
        if (br->dev->flags & IFF_UP)
            br_stp_disable_port(p);
        spin_unlock_bh(&br->lock);
        break;

    case NETDEV_UP:
        if (netif_carrier_ok(dev) && (br->dev->flags & IFF_UP)) {
            spin_lock_bh(&br->lock);
            br_stp_enable_port(p);
            spin_unlock_bh(&br->lock);
        }
        break;

    case NETDEV_UNREGISTER:
        br_del_if(br, dev);
        break;

    case NETDEV_CHANGENAME:
        err = br_sysfs_renameif(p);
        if (err)
            return notifier_from_errno(err);
        break;

    case NETDEV_PRE_TYPE_CHANGE:
        /* Forbid underlaying device to change its type. */
        return NOTIFY_BAD;
    }

    /* Events that may cause spanning tree to refresh */
    if (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
            event == NETDEV_CHANGE || event == NETDEV_DOWN)
        br_ifinfo_notify(RTM_NEWLINK, p);

    return NOTIFY_DONE;
}
コード例 #26
0
ファイル: interface.c プロジェクト: Daiki0525/linux
int xenvif_schedulable(struct xenvif *vif)
{
	return netif_running(vif->dev) && netif_carrier_ok(vif->dev);
}
コード例 #27
0
ファイル: main.c プロジェクト: iamroot12a/kernel
void mwifiex_dump_drv_info(struct mwifiex_adapter *adapter)
{
    void *p;
    char drv_version[64];
    struct usb_card_rec *cardp;
    struct sdio_mmc_card *sdio_card;
    struct mwifiex_private *priv;
    int i, idx;
    struct netdev_queue *txq;
    struct mwifiex_debug_info *debug_info;

    if (adapter->drv_info_dump) {
        vfree(adapter->drv_info_dump);
        adapter->drv_info_size = 0;
    }

    dev_info(adapter->dev, "=== DRIVER INFO DUMP START===\n");

    adapter->drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX);

    if (!adapter->drv_info_dump)
        return;

    p = (char *)(adapter->drv_info_dump);
    p += sprintf(p, "driver_name = " "\"mwifiex\"\n");

    mwifiex_drv_get_driver_version(adapter, drv_version,
                                   sizeof(drv_version) - 1);
    p += sprintf(p, "driver_version = %s\n", drv_version);

    if (adapter->iface_type == MWIFIEX_USB) {
        cardp = (struct usb_card_rec *)adapter->card;
        p += sprintf(p, "tx_cmd_urb_pending = %d\n",
                     atomic_read(&cardp->tx_cmd_urb_pending));
        p += sprintf(p, "tx_data_urb_pending = %d\n",
                     atomic_read(&cardp->tx_data_urb_pending));
        p += sprintf(p, "rx_cmd_urb_pending = %d\n",
                     atomic_read(&cardp->rx_cmd_urb_pending));
        p += sprintf(p, "rx_data_urb_pending = %d\n",
                     atomic_read(&cardp->rx_data_urb_pending));
    }

    p += sprintf(p, "tx_pending = %d\n",
                 atomic_read(&adapter->tx_pending));
    p += sprintf(p, "rx_pending = %d\n",
                 atomic_read(&adapter->rx_pending));

    if (adapter->iface_type == MWIFIEX_SDIO) {
        sdio_card = (struct sdio_mmc_card *)adapter->card;
        p += sprintf(p, "\nmp_rd_bitmap=0x%x curr_rd_port=0x%x\n",
                     sdio_card->mp_rd_bitmap, sdio_card->curr_rd_port);
        p += sprintf(p, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n",
                     sdio_card->mp_wr_bitmap, sdio_card->curr_wr_port);
    }

    for (i = 0; i < adapter->priv_num; i++) {
        if (!adapter->priv[i] || !adapter->priv[i]->netdev)
            continue;
        priv = adapter->priv[i];
        p += sprintf(p, "\n[interface  : \"%s\"]\n",
                     priv->netdev->name);
        p += sprintf(p, "wmm_tx_pending[0] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[0]));
        p += sprintf(p, "wmm_tx_pending[1] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[1]));
        p += sprintf(p, "wmm_tx_pending[2] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[2]));
        p += sprintf(p, "wmm_tx_pending[3] = %d\n",
                     atomic_read(&priv->wmm_tx_pending[3]));
        p += sprintf(p, "media_state=\"%s\"\n", !priv->media_connected ?
                     "Disconnected" : "Connected");
        p += sprintf(p, "carrier %s\n", (netif_carrier_ok(priv->netdev)
                                         ? "on" : "off"));
        for (idx = 0; idx < priv->netdev->num_tx_queues; idx++) {
            txq = netdev_get_tx_queue(priv->netdev, idx);
            p += sprintf(p, "tx queue %d:%s  ", idx,
                         netif_tx_queue_stopped(txq) ?
                         "stopped" : "started");
        }
        p += sprintf(p, "\n%s: num_tx_timeout = %d\n",
                     priv->netdev->name, priv->num_tx_timeout);
    }

    if (adapter->iface_type == MWIFIEX_SDIO) {
        p += sprintf(p, "\n=== SDIO register DUMP===\n");
        if (adapter->if_ops.reg_dump)
            p += adapter->if_ops.reg_dump(adapter, p);
    }

    p += sprintf(p, "\n=== MORE DEBUG INFORMATION\n");
    debug_info = kzalloc(sizeof(*debug_info), GFP_KERNEL);
    if (debug_info) {
        for (i = 0; i < adapter->priv_num; i++) {
            if (!adapter->priv[i] || !adapter->priv[i]->netdev)
                continue;
            priv = adapter->priv[i];
            mwifiex_get_debug_info(priv, debug_info);
            p += mwifiex_debug_info_to_buffer(priv, p, debug_info);
            break;
        }
        kfree(debug_info);
    }

    adapter->drv_info_size = p - adapter->drv_info_dump;
    dev_info(adapter->dev, "=== DRIVER INFO DUMP END===\n");
}
コード例 #28
0
u32 ethtool_op_get_link(struct net_device *dev)
{
	return netif_carrier_ok(dev) ? 1 : 0;
}
コード例 #29
0
/*
 * This function resets the connection state.
 *
 * The function is invoked after receiving a disconnect event from firmware,
 * and performs the following actions -
 *      - Set media status to disconnected
 *      - Clean up Tx and Rx packets
 *      - Resets SNR/NF/RSSI value in driver
 *      - Resets security configurations in driver
 *      - Enables auto data rate
 *      - Saves the previous SSID and BSSID so that they can
 *        be used for re-association, if required
 *      - Erases current SSID and BSSID information
 *      - Sends a disconnect event to upper layers/applications.
 */
void
mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
{
    struct mwifiex_adapter *adapter = priv->adapter;

    if (!priv->media_connected)
        return;

    dev_dbg(adapter->dev, "info: handles disconnect event\n");

    priv->media_connected = false;

    priv->scan_block = false;

    if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
            ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
        mwifiex_disable_all_tdls_links(priv);

    /* Free Tx and Rx packets, report disconnect to upper layer */
    mwifiex_clean_txrx(priv);

    /* Reset SNR/NF/RSSI values */
    priv->data_rssi_last = 0;
    priv->data_nf_last = 0;
    priv->data_rssi_avg = 0;
    priv->data_nf_avg = 0;
    priv->bcn_rssi_last = 0;
    priv->bcn_nf_last = 0;
    priv->bcn_rssi_avg = 0;
    priv->bcn_nf_avg = 0;
    priv->rxpd_rate = 0;
    priv->rxpd_htinfo = 0;
    priv->sec_info.wpa_enabled = false;
    priv->sec_info.wpa2_enabled = false;
    priv->wpa_ie_len = 0;

    priv->sec_info.wapi_enabled = false;
    priv->wapi_ie_len = 0;
    priv->sec_info.wapi_key_on = false;

    priv->sec_info.encryption_mode = 0;

    /* Enable auto data rate */
    priv->is_data_rate_auto = true;
    priv->data_rate = 0;

    if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
        priv->adhoc_state = ADHOC_IDLE;
        priv->adhoc_is_link_sensed = false;
    }

    /*
     * Memorize the previous SSID and BSSID so
     * it could be used for re-assoc
     */

    dev_dbg(adapter->dev, "info: previous SSID=%s, SSID len=%u\n",
            priv->prev_ssid.ssid, priv->prev_ssid.ssid_len);

    dev_dbg(adapter->dev, "info: current SSID=%s, SSID len=%u\n",
            priv->curr_bss_params.bss_descriptor.ssid.ssid,
            priv->curr_bss_params.bss_descriptor.ssid.ssid_len);

    memcpy(&priv->prev_ssid,
           &priv->curr_bss_params.bss_descriptor.ssid,
           sizeof(struct cfg80211_ssid));

    memcpy(priv->prev_bssid,
           priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN);

    /* Need to erase the current SSID and BSSID info */
    memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params));

    adapter->tx_lock_flag = false;
    adapter->pps_uapsd_mode = false;

    if (adapter->is_cmd_timedout && adapter->curr_cmd)
        return;
    priv->media_connected = false;
    dev_dbg(adapter->dev,
            "info: successfully disconnected from %pM: reason code %d\n",
            priv->cfg_bssid, reason_code);
    if (priv->bss_mode == NL80211_IFTYPE_STATION ||
            priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) {
        cfg80211_disconnected(priv->netdev, reason_code, NULL, 0,
                              GFP_KERNEL);
    }
    memset(priv->cfg_bssid, 0, ETH_ALEN);

    mwifiex_stop_net_dev_queue(priv->netdev, adapter);
    if (netif_carrier_ok(priv->netdev))
        netif_carrier_off(priv->netdev);
}
コード例 #30
0
/*
 * In Ad-Hoc mode, the IBSS is created if not found in scan list.
 * In both Ad-Hoc and infra mode, an deauthentication is performed
 * first.
 */
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
		      struct cfg80211_ssid *req_ssid)
{
	int ret;
	struct mwifiex_adapter *adapter = priv->adapter;
	struct mwifiex_bssdescriptor *bss_desc = NULL;

	priv->scan_block = false;

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

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

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

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

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

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

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

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

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

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

		priv->adhoc_is_link_sensed = false;

		ret = mwifiex_check_network_compatibility(priv, bss_desc);

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

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

done:
	kfree(bss_desc);
	return ret;
}