int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid, enum ieee80211_back_parties initiator) { struct ieee80211_local *local = hw_to_local(hw); struct sta_info *sta; int ret = 0; if (WARN_ON(!local->ops->ampdu_action)) return -EINVAL; if (tid >= STA_TID_NUM) return -EINVAL; rcu_read_lock(); sta = sta_info_get(local, ra); if (!sta) { rcu_read_unlock(); return -ENOENT; } ret = __ieee80211_stop_tx_ba_session(sta, tid, initiator); rcu_read_unlock(); return ret; }
char *__ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags, const struct ieee80211_tpt_blink *blink_table, unsigned int blink_table_len) { struct ieee80211_local *local = hw_to_local(hw); struct tpt_led_trigger *tpt_trig; if (WARN_ON(local->tpt_led_trigger)) return NULL; tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL); if (!tpt_trig) return NULL; snprintf(tpt_trig->name, sizeof(tpt_trig->name), "%stpt", wiphy_name(local->hw.wiphy)); tpt_trig->trig.name = tpt_trig->name; tpt_trig->blink_table = blink_table; tpt_trig->blink_table_len = blink_table_len; tpt_trig->want = flags; setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local); local->tpt_led_trigger = tpt_trig; return tpt_trig->name; }
IOReturn darwin_iwi4965::getHardwareAddress( IOEthernetAddress * addr ) { UInt16 val; if (fEnetAddr.bytes[0]==0 && fEnetAddr.bytes[1]==0 && fEnetAddr.bytes[2]==0 && fEnetAddr.bytes[3]==0 && fEnetAddr.bytes[4]==0 && fEnetAddr.bytes[5]==0) { //00:0e:35:e0:3d:b3 /*fEnetAddr.bytes[0]=0x00; fEnetAddr.bytes[1]=0x0e; fEnetAddr.bytes[2]=0x35; fEnetAddr.bytes[3]=0xe0; fEnetAddr.bytes[4]=0x3d; fEnetAddr.bytes[5]=0xb3; if (priv) memcpy(priv->eeprom.mac_address, fEnetAddr.bytes, ETH_ALEN);*/ if (priv) memcpy(fEnetAddr.bytes, priv->eeprom.mac_address, ETH_ALEN); IOLog("getHardwareAddress " MAC_FMT "\n",MAC_ARG(fEnetAddr.bytes)); } memcpy(addr, &fEnetAddr, sizeof(*addr)); if (priv) { memcpy(priv->mac_addr, &fEnetAddr.bytes, ETH_ALEN); struct ieee80211_local* loc=hw_to_local(priv->hw); memcpy(loc->mdev->dev_addr, &fEnetAddr.bytes, ETH_ALEN); //IOLog("getHardwareAddress " MAC_FMT "\n",MAC_ARG(priv->mac_addr)); } return kIOReturnSuccess; }
/* * initialize rxon structure with default values from eeprom */ void iwl_connection_init_rx_config(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { memset(&ctx->staging, 0, sizeof(ctx->staging)); if (!ctx->vif) { ctx->staging.dev_type = ctx->unused_devtype; } else switch (ctx->vif->type) { case NL80211_IFTYPE_AP: ctx->staging.dev_type = ctx->ap_devtype; break; case NL80211_IFTYPE_STATION: ctx->staging.dev_type = ctx->station_devtype; ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_ADHOC: ctx->staging.dev_type = ctx->ibss_devtype; ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; case NL80211_IFTYPE_MONITOR: ctx->staging.dev_type = RXON_DEV_TYPE_SNIFFER; break; default: IWL_ERR(priv, "Unsupported interface type %d\n", ctx->vif->type); break; } #if 0 /* TODO: Figure out when short_preamble would be set and cache from * that */ if (!hw_to_local(priv->hw)->short_preamble) ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; else ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif ctx->staging.channel = cpu_to_le16(priv->hw->conf.chandef.chan->hw_value); priv->band = priv->hw->conf.chandef.chan->band; iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); /* clear both MIX and PURE40 mode flag */ ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | RXON_FLG_CHANNEL_MODE_PURE_40); if (ctx->vif) memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff; }
int ieee80211_register_hwmode(struct ieee80211_hw *hw, struct ieee80211_hw_mode *mode) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate; int i; INIT_LIST_HEAD(&mode->list); list_add_tail(&mode->list, &local->modes_list); local->hw_modes |= (1 << mode->mode); for (i = 0; i < mode->num_rates; i++) { rate = &(mode->rates[i]); rate->rate_inv = CHAN_UTIL_RATE_LCM / rate->rate; } ieee80211_prepare_rates(local, mode); if (!local->oper_hw_mode) { /* Default to this mode */ local->hw.conf.phymode = mode->mode; local->oper_hw_mode = local->scan_hw_mode = mode; local->oper_channel = local->scan_channel = &mode->channels[0]; local->hw.conf.mode = local->oper_hw_mode; local->hw.conf.chan = local->oper_channel; } if (!(hw->flags & IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED)) ieee80211_set_default_regdomain(mode); return 0; }
char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); if (local->rx_led) return local->rx_led_name; return NULL; }
void ieee80211_free_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); mutex_destroy(&local->iflist_mtx); mutex_destroy(&local->scan_mtx); wiphy_free(local->hw.wiphy); }
void ieee80211_restart_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); /* use this reason, __ieee80211_resume will unblock it */ ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); schedule_work(&local->restart_work); }
void ieee802154_free_hw(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); BUG_ON(!list_empty(&local->interfaces)); mutex_destroy(&local->iflist_mtx); wpan_phy_free(local->phy); }
void ieee80211_free_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); mutex_destroy(&local->iflist_mtx); mutex_destroy(&local->mtx); if (local->wiphy_ciphers_allocated) kfree(local->hw.wiphy->cipher_suites); wiphy_free(local->hw.wiphy); }
void ieee80211_unregister_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); #ifdef CONFIG_INET unregister_inetaddr_notifier(&local->ifa_notifier); #endif rtnl_lock(); /* * At this point, interface list manipulations are fine * because the driver cannot be handing us frames any * more and the tasklet is killed. */ ieee80211_remove_interfaces(local); rtnl_unlock(); /* * Now all work items will be gone, but the * timer might still be armed, so delete it */ del_timer_sync(&local->work_timer); cancel_work_sync(&local->restart_work); cancel_work_sync(&local->reconfig_filter); ieee80211_clear_tx_pending(local); sta_info_stop(local); rate_control_deinitialize(local); if (skb_queue_len(&local->skb_queue) || skb_queue_len(&local->skb_queue_unreliable)) wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); skb_queue_purge(&local->skb_queue); skb_queue_purge(&local->skb_queue_unreliable); skb_queue_purge(&local->rx_skb_queue); destroy_workqueue(local->workqueue); wiphy_unregister(local->hw.wiphy); ieee80211_wep_free(local); ieee80211_led_exit(local); kfree(local->int_scan_req); }
void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) { struct ieee80211_local *local = hw_to_local(hw); struct sta_info *sta; u8 *state; if (tid >= STA_TID_NUM) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM); #endif return; } rcu_read_lock(); sta = sta_info_get(local, ra); if (!sta) { rcu_read_unlock(); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Could not find station: %pM\n", ra); #endif return; } state = &sta->ampdu_mlme.tid_state_tx[tid]; spin_lock_bh(&sta->lock); if (WARN_ON(!(*state & HT_ADDBA_REQUESTED_MSK))) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", *state); #endif spin_unlock_bh(&sta->lock); rcu_read_unlock(); return; } if (WARN_ON(*state & HT_ADDBA_DRV_READY_MSK)) goto out; *state |= HT_ADDBA_DRV_READY_MSK; if (*state == HT_AGG_STATE_OPERATIONAL) ieee80211_agg_tx_operational(local, sta, tid); out: spin_unlock_bh(&sta->lock); rcu_read_unlock(); }
void ieee80211_restart_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); trace_api_restart_hw(local); wiphy_info(hw->wiphy, "Hardware restart was requested\n"); /* use this reason, ieee80211_reconfig will unblock it */ ieee80211_stop_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); schedule_work(&local->restart_work); }
void ieee802154_unregister_hw(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); tasklet_kill(&local->tasklet); flush_workqueue(local->workqueue); destroy_workqueue(local->workqueue); rtnl_lock(); ieee802154_remove_interfaces(local); rtnl_unlock(); wpan_phy_unregister(local->phy); }
IOReturn darwin_iwi3945::enable( IONetworkInterface * netif ) { if (!fifnet) { char ii[4]; sprintf(ii,"%s%d" ,fNetif->getNamePrefix(), fNetif->getUnitNumber()); ifnet_find_by_name(ii,&fifnet); IWI_DEBUG("ifnet_t %s%d = %x\n",ifnet_name(fifnet),ifnet_unit(fifnet),fifnet); struct ieee80211_local* loc=hw_to_local(priv->hw); memcpy(&loc->mdev->name,ii,sizeof(ii)); loc->mdev->ifindex=fNetif->getUnitNumber(); priv->interface_id=fNetif->getUnitNumber(); } if (firstifup==0) { firstifup=1; return -1; } IWI_DEBUG("ifconfig up\n"); if ((fNetif->getFlags() & IFF_RUNNING)==0) { IWI_DEBUG("ifconfig going up\n "); //super::enable(fNetif); //fNetif->setPoweredOnByUser(true); //fNetif->setLinkState(kIO80211NetworkLinkUp); //(if_flags & ~mask) | (new_flags & mask) if mask has IFF_UP if_updown fires up (kpi_interface.c in xnu) if (priv->status & STATUS_AUTH) ifnet_set_flags(fifnet, IFF_RUNNING, IFF_RUNNING ); //fNetif->inputEvent(kIONetworkEventTypeLinkUp,NULL); fTransmitQueue->setCapacity(1024); fTransmitQueue->service(IOBasicOutputQueue::kServiceAsync); fTransmitQueue->start(); return kIOReturnSuccess; } else { IWI_DEBUG("ifconfig already up\n"); return kIOReturnExclusiveAccess; } }
static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, enum queue_stop_reason reason) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; trace_wake_queue(local, queue, reason); if (WARN_ON(queue >= hw->queues)) return; __clear_bit(reason, &local->queue_stop_reasons[queue]); if (local->queue_stop_reasons[queue] != 0) /* someone still has this queue stopped */ return; if (skb_queue_empty(&local->pending[queue])) { rcu_read_lock(); <<<<<<< HEAD
void ieee80211_unregister_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); tasklet_kill(&local->tx_pending_tasklet); tasklet_kill(&local->tasklet); pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); rtnl_lock(); /* * At this point, interface list manipulations are fine * because the driver cannot be handing us frames any * more and the tasklet is killed. */ ieee80211_remove_interfaces(local); rtnl_unlock(); cancel_work_sync(&local->reconfig_filter); ieee80211_clear_tx_pending(local); sta_info_stop(local); rate_control_deinitialize(local); if (skb_queue_len(&local->skb_queue) || skb_queue_len(&local->skb_queue_unreliable)) printk(KERN_WARNING "%s: skb_queue not empty\n", wiphy_name(local->hw.wiphy)); skb_queue_purge(&local->skb_queue); skb_queue_purge(&local->skb_queue_unreliable); destroy_workqueue(local->workqueue); wiphy_unregister(local->hw.wiphy); ieee80211_wep_free(local); ieee80211_led_exit(local); kfree(local->int_scan_req); }
__le16 ieee80211_rts_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, size_t frame_len, const struct ieee80211_tx_info *frame_txctl) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_rate *rate; struct ieee80211_sub_if_data *sdata; bool short_preamble; int erp; u16 dur; struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; short_preamble = false; rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; erp = 0; if (vif) { sdata = vif_to_sdata(vif); short_preamble = sdata->vif.bss_conf.use_short_preamble; if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) erp = rate->flags & IEEE80211_RATE_ERP_G; } /* CTS duration */ dur = ieee80211_frame_duration(local, 10, rate->bitrate, erp, short_preamble); /* Data frame duration */ dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, short_preamble); /* ACK duration */ dur += ieee80211_frame_duration(local, 10, rate->bitrate, erp, short_preamble); return cpu_to_le16(dur); }
void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, u16 tid) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_ra_tid *ra_tid; struct sk_buff *skb = dev_alloc_skb(0); if (unlikely(!skb)) { #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) printk(KERN_WARNING "%s: Not enough memory, " "dropping stop BA session", skb->dev->name); #endif return; } ra_tid = (struct ieee80211_ra_tid *) &skb->cb; memcpy(&ra_tid->ra, ra, ETH_ALEN); ra_tid->tid = tid; skb->pkt_type = IEEE80211_DELBA_MSG; skb_queue_tail(&local->skb_queue, skb); tasklet_schedule(&local->tasklet); }
/* Exported duration function for driver use */ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, size_t frame_len, struct ieee80211_rate *rate) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; u16 dur; int erp; bool short_preamble = false; erp = 0; if (vif) { sdata = vif_to_sdata(vif); short_preamble = sdata->vif.bss_conf.use_short_preamble; if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) erp = rate->flags & IEEE80211_RATE_ERP_G; } dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, short_preamble); return cpu_to_le16(dur); }
int ieee80211_register_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); int result; enum ieee80211_band band; int channels, max_bitrates; bool supp_ht; static const u32 cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, /* keep last -- depends on hw flags! */ WLAN_CIPHER_SUITE_AES_CMAC }; /* * generic code guarantees at least one band, * set this very early because much code assumes * that hw.conf.channel is assigned */ channels = 0; max_bitrates = 0; supp_ht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[band]; if (!sband) continue; if (!local->oper_channel) { /* init channel we're on */ local->hw.conf.channel = local->oper_channel = &sband->channels[0]; local->hw.conf.channel_type = NL80211_CHAN_NO_HT; } channels += sband->n_channels; if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; } local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + sizeof(void *) * channels, GFP_KERNEL); if (!local->int_scan_req) return -ENOMEM; /* if low-level driver supports AP, we also support VLAN */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); /* mac80211 always supports monitor */ local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"); /* * Calculate scan IE length -- we need this to alloc * memory and to subtract from the driver limit. It * includes the (extended) supported rates and HT * information -- SSID is the driver's responsibility. */ local->scan_ies_len = 4 + max_bitrates; /* (ext) supp rates */ if (supp_ht) local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ local->hw.wiphy->max_scan_ssids = 4; local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; } /* * If the driver supports any scan IEs, then assume the * limit includes the IEs mac80211 will add, otherwise * leave it at zero and let the driver sort it out; we * still pass our IEs to the driver but userspace will * not be allowed to in that case. */ if (local->hw.wiphy->max_scan_ie_len) local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; local->hw.wiphy->cipher_suites = cipher_suites; local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) local->hw.wiphy->n_cipher_suites--; result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; /* * We use the number of queues for feature tests (QoS, HT) internally * so restrict them appropriately. */ if (hw->queues > IEEE80211_MAX_QUEUES) hw->queues = IEEE80211_MAX_QUEUES; local->workqueue = create_singlethread_workqueue(wiphy_name(local->hw.wiphy)); if (!local->workqueue) { result = -ENOMEM; goto fail_workqueue; } /* * The hardware needs headroom for sending the frame, * and we need some headroom for passing the frame to monitor * interfaces, but never both at the same time. */ BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != sizeof(struct ieee80211_tx_status_rtap_hdr)); local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, sizeof(struct ieee80211_tx_status_rtap_hdr)); debugfs_hw_add(local); /* * if the driver doesn't specify a max listen interval we * use 5 which should be a safe default */ if (local->hw.max_listen_interval == 0) local->hw.max_listen_interval = 5; local->hw.conf.listen_interval = local->hw.max_listen_interval; local->dynamic_ps_forced_timeout = -1; result = sta_info_start(local); if (result < 0) goto fail_sta_info; result = ieee80211_wep_init(local); if (result < 0) printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", wiphy_name(local->hw.wiphy), result); rtnl_lock(); result = ieee80211_init_rate_ctrl_alg(local, hw->rate_control_algorithm); if (result < 0) { printk(KERN_DEBUG "%s: Failed to initialize rate control " "algorithm\n", wiphy_name(local->hw.wiphy)); goto fail_rate; } /* add one default STA interface if supported */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { result = ieee80211_if_add(local, "wlan%d", NULL, NL80211_IFTYPE_STATION, NULL); if (result) printk(KERN_WARNING "%s: Failed to add default virtual iface\n", wiphy_name(local->hw.wiphy)); } rtnl_unlock(); ieee80211_led_init(local); local->network_latency_notifier.notifier_call = ieee80211_max_network_latency; result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); if (result) { rtnl_lock(); goto fail_pm_qos; } #ifdef CONFIG_INET local->ifa_notifier.notifier_call = ieee80211_ifa_changed; result = register_inetaddr_notifier(&local->ifa_notifier); if (result) goto fail_ifa; #endif return 0; #ifdef CONFIG_INET fail_ifa: pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); rtnl_lock(); #endif fail_pm_qos: ieee80211_led_exit(local); ieee80211_remove_interfaces(local); fail_rate: rtnl_unlock(); ieee80211_wep_free(local); sta_info_stop(local); fail_sta_info: destroy_workqueue(local->workqueue); fail_workqueue: wiphy_unregister(local->hw.wiphy); fail_wiphy_register: kfree(local->int_scan_req); return result; }
char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); return local->tx_led_name; }
int ieee802154_register_hw(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); struct net_device *dev; int rc = -ENOSYS; local->workqueue = create_singlethread_workqueue(wpan_phy_name(local->phy)); if (!local->workqueue) { rc = -ENOMEM; goto out; } hrtimer_init(&local->ifs_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); local->ifs_timer.function = ieee802154_xmit_ifs_timer; wpan_phy_set_dev(local->phy, local->hw.parent); ieee802154_setup_wpan_phy_pib(local->phy); if (!(hw->flags & IEEE802154_HW_CSMA_PARAMS)) { local->phy->supported.min_csma_backoffs = 4; local->phy->supported.max_csma_backoffs = 4; local->phy->supported.min_maxbe = 5; local->phy->supported.max_maxbe = 5; local->phy->supported.min_minbe = 3; local->phy->supported.max_minbe = 3; } if (!(hw->flags & IEEE802154_HW_FRAME_RETRIES)) { /* TODO should be 3, but our default value is -1 which means * no ARET handling. */ local->phy->supported.min_frame_retries = -1; local->phy->supported.max_frame_retries = -1; } if (hw->flags & IEEE802154_HW_PROMISCUOUS) local->phy->supported.iftypes |= BIT(NL802154_IFTYPE_MONITOR); rc = wpan_phy_register(local->phy); if (rc < 0) goto out_wq; rtnl_lock(); dev = ieee802154_if_add(local, "wpan%d", NET_NAME_ENUM, NL802154_IFTYPE_NODE, cpu_to_le64(0x0000000000000000ULL)); if (IS_ERR(dev)) { rtnl_unlock(); rc = PTR_ERR(dev); goto out_phy; } rtnl_unlock(); return 0; out_phy: wpan_phy_unregister(local->phy); out_wq: destroy_workqueue(local->workqueue); out: return rc; }
void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) { struct ieee80211_local *local = hw_to_local(hw); struct sta_info *sta; u8 *state; if (tid >= STA_TID_NUM) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", tid, STA_TID_NUM); #endif return; } #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n", ra, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ rcu_read_lock(); sta = sta_info_get(local, ra); if (!sta) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Could not find station: %pM\n", ra); #endif rcu_read_unlock(); return; } state = &sta->ampdu_mlme.tid_state_tx[tid]; /* NOTE: no need to use sta->lock in this state check, as * ieee80211_stop_tx_ba_session will let only one stop call to * pass through per sta/tid */ if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); #endif rcu_read_unlock(); return; } if (*state & HT_AGG_STATE_INITIATOR_MSK) ieee80211_send_delba(sta->sdata, ra, tid, WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); spin_lock_bh(&sta->lock); spin_lock(&local->ampdu_lock); ieee80211_agg_splice_packets(local, sta, tid); *state = HT_AGG_STATE_IDLE; /* from now on packets are no longer put onto sta->pending */ kfree(sta->ampdu_mlme.tid_tx[tid]); sta->ampdu_mlme.tid_tx[tid] = NULL; ieee80211_agg_splice_finish(local, sta, tid); spin_unlock(&local->ampdu_lock); spin_unlock_bh(&sta->lock); rcu_read_unlock(); }
int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) { struct ieee80211_local *local = hw_to_local(hw); struct sta_info *sta; struct ieee80211_sub_if_data *sdata; u8 *state; int ret = 0; u16 start_seq_num; if (WARN_ON(!local->ops->ampdu_action)) return -EINVAL; if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) return -EINVAL; #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", ra, tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ rcu_read_lock(); sta = sta_info_get(local, ra); if (!sta) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Could not find the station\n"); #endif ret = -ENOENT; goto unlock; } /* * The aggregation code is not prepared to handle * anything but STA/AP due to the BSSID handling. * IBSS could work in the code but isn't supported * by drivers or the standard. */ if (sta->sdata->vif.type != NL80211_IFTYPE_STATION && sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sta->sdata->vif.type != NL80211_IFTYPE_AP) { ret = -EINVAL; goto unlock; } if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "Suspend in progress. " "Denying BA session request\n"); #endif ret = -EINVAL; goto unlock; } spin_lock_bh(&sta->lock); spin_lock(&local->ampdu_lock); sdata = sta->sdata; /* we have tried too many times, receiver does not want A-MPDU */ if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { ret = -EBUSY; goto err_unlock_sta; } state = &sta->ampdu_mlme.tid_state_tx[tid]; /* check if the TID is not in aggregation flow already */ if (*state != HT_AGG_STATE_IDLE) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "BA request denied - session is not " "idle on tid %u\n", tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ ret = -EAGAIN; goto err_unlock_sta; } /* * While we're asking the driver about the aggregation, * stop the AC queue so that we don't have to worry * about frames that came in while we were doing that, * which would require us to put them to the AC pending * afterwards which just makes the code more complex. */ ieee80211_stop_queue_by_reason( &local->hw, ieee80211_ac_from_tid(tid), IEEE80211_QUEUE_STOP_REASON_AGGREGATION); /* prepare A-MPDU MLME for Tx aggregation */ sta->ampdu_mlme.tid_tx[tid] = kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); if (!sta->ampdu_mlme.tid_tx[tid]) { #ifdef CONFIG_MAC80211_HT_DEBUG if (net_ratelimit()) printk(KERN_ERR "allocate tx mlme to tid %d failed\n", tid); #endif ret = -ENOMEM; goto err_wake_queue; } skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending); /* Tx timer */ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = sta_addba_resp_timer_expired; sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the * call back right away, it must see that the flow has begun */ *state |= HT_ADDBA_REQUESTED_MSK; start_seq_num = sta->tid_seq[tid]; ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_START, &sta->sta, tid, &start_seq_num); if (ret) { #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "BA request denied - HW unavailable for" " tid %d\n", tid); #endif /* CONFIG_MAC80211_HT_DEBUG */ *state = HT_AGG_STATE_IDLE; goto err_free; } /* Driver vetoed or OKed, but we can take packets again now */ ieee80211_wake_queue_by_reason( &local->hw, ieee80211_ac_from_tid(tid), IEEE80211_QUEUE_STOP_REASON_AGGREGATION); spin_unlock(&local->ampdu_lock); spin_unlock_bh(&sta->lock); /* send an addBA request */ sta->ampdu_mlme.dialog_token_allocator++; sta->ampdu_mlme.tid_tx[tid]->dialog_token = sta->ampdu_mlme.dialog_token_allocator; sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; ieee80211_send_addba_request(sta->sdata, ra, tid, sta->ampdu_mlme.tid_tx[tid]->dialog_token, sta->ampdu_mlme.tid_tx[tid]->ssn, 0x40, 5000); sta->ampdu_mlme.addba_req_num[tid]++; /* activate the timer for the recipient's addBA response */ sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = jiffies + ADDBA_RESP_INTERVAL; add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); #ifdef CONFIG_MAC80211_HT_DEBUG printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); #endif goto unlock; err_free: kfree(sta->ampdu_mlme.tid_tx[tid]); sta->ampdu_mlme.tid_tx[tid] = NULL; err_wake_queue: ieee80211_wake_queue_by_reason( &local->hw, ieee80211_ac_from_tid(tid), IEEE80211_QUEUE_STOP_REASON_AGGREGATION); err_unlock_sta: spin_unlock(&local->ampdu_lock); spin_unlock_bh(&sta->lock); unlock: rcu_read_unlock(); return ret; }
void ieee80211_napi_schedule(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); napi_schedule(&local->napi); }
int ieee80211_register_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); int result, i; enum ieee80211_band band; int channels, max_bitrates; bool supp_ht; static const u32 cipher_suites[] = { /* keep WEP first, it may be removed below */ WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, /* keep last -- depends on hw flags! */ WLAN_CIPHER_SUITE_AES_CMAC }; if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) #ifdef CONFIG_PM && (!local->ops->suspend || !local->ops->resume) #endif ) return -EINVAL; if (hw->max_report_rates == 0) hw->max_report_rates = hw->max_rates; /* * generic code guarantees at least one band, * set this very early because much code assumes * that hw.conf.channel is assigned */ channels = 0; max_bitrates = 0; supp_ht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[band]; if (!sband) continue; if (!local->oper_channel) { /* init channel we're on */ local->hw.conf.channel = local->oper_channel = &sband->channels[0]; local->hw.conf.channel_type = NL80211_CHAN_NO_HT; } channels += sband->n_channels; if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; } local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + sizeof(void *) * channels, GFP_KERNEL); if (!local->int_scan_req) return -ENOMEM; /* if low-level driver supports AP, we also support VLAN */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); } /* mac80211 always supports monitor */ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); /* * mac80211 doesn't support more than 1 channel, and also not more * than one IBSS interface */ for (i = 0; i < hw->wiphy->n_iface_combinations; i++) { const struct ieee80211_iface_combination *c; int j; c = &hw->wiphy->iface_combinations[i]; if (c->num_different_channels > 1) return -EINVAL; for (j = 0; j < c->n_limits; j++) if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) && c->limits[j].max > 1) return -EINVAL; } #ifndef CONFIG_MAC80211_MESH /* mesh depends on Kconfig, but drivers should set it if they want */ local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); #endif /* if the underlying driver supports mesh, mac80211 will (at least) * provide routing of mesh authentication frames to userspace */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_MESH_POINT)) local->hw.wiphy->flags |= WIPHY_FLAG_MESH_AUTH; /* mac80211 supports control port protocol changing */ local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"); /* * Calculate scan IE length -- we need this to alloc * memory and to subtract from the driver limit. It * includes the DS Params, (extended) supported rates, and HT * information -- SSID is the driver's responsibility. */ local->scan_ies_len = 4 + max_bitrates /* (ext) supp rates */ + 3 /* DS Params */; if (supp_ht) local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ local->hw.wiphy->max_scan_ssids = 4; local->hw.wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; } /* * If the driver supports any scan IEs, then assume the * limit includes the IEs mac80211 will add, otherwise * leave it at zero and let the driver sort it out; we * still pass our IEs to the driver but userspace will * not be allowed to in that case. */ if (local->hw.wiphy->max_scan_ie_len) local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; /* Set up cipher suites unless driver already did */ if (!local->hw.wiphy->cipher_suites) { local->hw.wiphy->cipher_suites = cipher_suites; local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) local->hw.wiphy->n_cipher_suites--; } if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { if (local->hw.wiphy->cipher_suites == cipher_suites) { local->hw.wiphy->cipher_suites += 2; local->hw.wiphy->n_cipher_suites -= 2; } else { u32 *suites; int r, w = 0; /* Filter out WEP */ suites = kmemdup( local->hw.wiphy->cipher_suites, sizeof(u32) * local->hw.wiphy->n_cipher_suites, GFP_KERNEL); if (!suites) return -ENOMEM; for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { u32 suite = local->hw.wiphy->cipher_suites[r]; if (suite == WLAN_CIPHER_SUITE_WEP40 || suite == WLAN_CIPHER_SUITE_WEP104) continue; suites[w++] = suite; } local->hw.wiphy->cipher_suites = suites; local->hw.wiphy->n_cipher_suites = w; local->wiphy_ciphers_allocated = true; } } if (!local->ops->remain_on_channel) local->hw.wiphy->max_remain_on_channel_duration = 5000; if (local->ops->sched_scan_start) local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; result = wiphy_register(local->hw.wiphy); if (result < 0) goto fail_wiphy_register; /* * We use the number of queues for feature tests (QoS, HT) internally * so restrict them appropriately. */ if (hw->queues > IEEE80211_MAX_QUEUES) hw->queues = IEEE80211_MAX_QUEUES; local->workqueue = alloc_ordered_workqueue(wiphy_name(local->hw.wiphy), 0); if (!local->workqueue) { result = -ENOMEM; goto fail_workqueue; } /* * The hardware needs headroom for sending the frame, * and we need some headroom for passing the frame to monitor * interfaces, but never both at the same time. */ #ifndef __CHECKER__ BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != sizeof(struct ieee80211_tx_status_rtap_hdr)); #endif local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, sizeof(struct ieee80211_tx_status_rtap_hdr)); debugfs_hw_add(local); /* * if the driver doesn't specify a max listen interval we * use 5 which should be a safe default */ if (local->hw.max_listen_interval == 0) local->hw.max_listen_interval = 5; local->hw.conf.listen_interval = local->hw.max_listen_interval; local->dynamic_ps_forced_timeout = -1; result = ieee80211_wep_init(local); if (result < 0) wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", result); rtnl_lock(); result = ieee80211_init_rate_ctrl_alg(local, hw->rate_control_algorithm); if (result < 0) { wiphy_debug(local->hw.wiphy, "Failed to initialize rate control algorithm\n"); goto fail_rate; } /* add one default STA interface if supported */ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) { result = ieee80211_if_add(local, "wlan%d", NULL, NL80211_IFTYPE_STATION, NULL); if (result) wiphy_warn(local->hw.wiphy, "Failed to add default virtual iface\n"); } rtnl_unlock(); ieee80211_led_init(local); local->network_latency_notifier.notifier_call = ieee80211_max_network_latency; result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); if (result) { rtnl_lock(); goto fail_pm_qos; } #ifdef CONFIG_INET local->ifa_notifier.notifier_call = ieee80211_ifa_changed; result = register_inetaddr_notifier(&local->ifa_notifier); if (result) goto fail_ifa; #endif netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, local->hw.napi_weight); return 0; #ifdef CONFIG_INET fail_ifa: pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, &local->network_latency_notifier); rtnl_lock(); #endif fail_pm_qos: ieee80211_led_exit(local); ieee80211_remove_interfaces(local); fail_rate: rtnl_unlock(); ieee80211_wep_free(local); sta_info_stop(local); destroy_workqueue(local->workqueue); fail_workqueue: wiphy_unregister(local->hw.wiphy); fail_wiphy_register: if (local->wiphy_ciphers_allocated) kfree(local->hw.wiphy->cipher_suites); kfree(local->int_scan_req); return result; }
void ieee80211_napi_complete(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); napi_complete(&local->napi); }
int ieee80211_register_hw(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); const char *name; int result; /*result = wiphy_register(local->hw.wiphy); if (result < 0) return result; name = wiphy_dev(local->hw.wiphy)->driver->name; local->hw.workqueue = create_singlethread_workqueue(name); if (!local->hw.workqueue) { result = -ENOMEM; goto fail_workqueue; }*/ /* * The hardware needs headroom for sending the frame, * and we need some headroom for passing the frame to monitor * interfaces, but never both at the same time. */ local->tx_headroom = max(sizeof(unsigned int) , max(local->hw.extra_tx_headroom, sizeof(struct ieee80211_tx_status_rtap_hdr))); //debugfs_hw_add(local); local->hw.conf.beacon_int = 1000; local->wstats_flags |= local->hw.max_rssi ? IW_QUAL_LEVEL_UPDATED : IW_QUAL_LEVEL_INVALID; local->wstats_flags |= local->hw.max_signal ? IW_QUAL_QUAL_UPDATED : IW_QUAL_QUAL_INVALID; local->wstats_flags |= local->hw.max_noise ? IW_QUAL_NOISE_UPDATED : IW_QUAL_NOISE_INVALID; if (local->hw.max_rssi < 0 || local->hw.max_noise < 0) local->wstats_flags |= IW_QUAL_DBM; local->user_txpow = IEEE80211_MAX_TXPOWER; /*result = sta_info_start(local); if (result < 0) goto fail_sta_info; rtnl_lock(); result = dev_alloc_name(local->mdev, local->mdev->name); if (result < 0) goto fail_dev; memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN); SET_NETDEV_DEV(local->mdev, wiphy_dev(local->hw.wiphy)); result = register_netdevice(local->mdev); if (result < 0) goto fail_dev; ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); result = ieee80211_init_rate_ctrl_alg(local, hw->preferred_rate_control); if (result < 0) { printk(KERN_DEBUG "%s: Failed to initialize %s rate control " "algorithm\n", local->mdev->name, hw->preferred_rate_control ? hw->preferred_rate_control : "default"); goto fail_rate; }*/ /* result = ieee80211_wep_init(local); if (result < 0) { printk(KERN_DEBUG "%s: Failed to initialize wep\n", local->mdev->name); goto fail_wep; } ieee80211_install_qdisc(local->mdev); */ /* add one default STA interface */ /*result = ieee80211_if_add(local->mdev, "wlan%d", NULL, IEEE80211_IF_TYPE_STA); if (result) printk("%s: Failed to add default virtual iface\n", local->mdev->name);*/ (int)local->reg_state = 1;// IEEE80211_DEV_REGISTERED; // rtnl_unlock(); // ieee80211_led_init(local); return 0; fail_wep: //rate_control_deinitialize(local); fail_rate: // ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev)); //unregister_netdevice(local->mdev); fail_dev: //rtnl_unlock(); //sta_info_stop(local); fail_sta_info: //debugfs_hw_del(local); //destroy_workqueue(local->hw.workqueue); fail_workqueue: //wiphy_unregister(local->hw.wiphy); return result; }
/* * join the information into the hdr with the correct ABPS_info int ABPS_info_response(struct sock *sk, struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_status *status) */ int ABPS_info_response(struct sock *sk, struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, struct ieee80211_tx_info *info, struct ieee80211_sub_if_data *sdata) { int success = 0; u8 acked = -1; u8 retry_count = -1; unsigned long filtered_count = -1; struct ieee80211_local *local = hw_to_local(hw); struct ABPS_info *packet_info; int i; /* se era richiesto l'ack */ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { /* e l'ack e' arrivato */ if (info->flags & IEEE80211_TX_STAT_ACK) success=1; } /* VEDERE SE RIMETTERE A POSTO else { if (!(info->excessive_retries)) success=2; } */ if (info->flags & IEEE80211_TX_CTL_NO_ACK) { /* ack not required */ acked= ACK_NOT_REQ; } else if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { /* filtered frame */ acked= ACK_FILTERED; } else if (info->flags & IEEE80211_TX_STAT_ACK) { /* frame acked */ struct sta_info *sta; acked = ACK; retry_count = 0; /* modifiche per kernel da 2.6.27 in poi */ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { /* the HW cannot have attempted that rate */ if (i >= hw->max_rates) { ; } else retry_count += info->status.rates[i].count; } if (retry_count > 0) retry_count--; sta = sta_info_get(sdata, hdr->addr1); if (sta) filtered_count = sta->tx_filtered_count; else filtered_count = ACK_ERROR ; } else { /* frame not acked, ack not recieved */ struct sta_info *sta; acked = ACK_NOT; retry_count = 0; /* modifiche per kernel da 2.6.27 in poi */ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { /* the HW cannot have attempted that rate */ if (i >= hw->max_rates) { ; } else retry_count += info->status.rates[i].count; } if (retry_count > 0) retry_count--; sta = sta_info_get(sdata, hdr->addr1); if (sta) filtered_count = sta->tx_filtered_count; else filtered_count = ACK_ERROR; } packet_info = ABPS_info_search(hdr->seq_ctrl); if (packet_info != 0) { packet_info->datagram_info.acked = acked; packet_info->datagram_info.retry_count = retry_count; packet_info->rx_time = CURRENT_TIME; /* questa chiamata a funzione required ... potrebbe essere eliminata * perche' viene fatta gia' fuori prima */ /* mando la notifica al socket */ /*NOTA ABPS DIE KURO: adesso estrae solo data_len, offset e more_frags, comunque non potevo estrearre dati da udp in caso di frammentazione, l'indirizzo ip invece non e' invece mai propagato fino all'utente */ if(!packet_info->is_ipv6) { ip_local_error_notify(sk, success, packet_info->datagram_info.ip_id, packet_info->datagram_info.fragment_data_len, packet_info->datagram_info.fragment_offset, packet_info->datagram_info.more_fragment, packet_info->datagram_info.retry_count ); } else { ipv6_local_error_notify(sk,success,packet_info->datagram_info.ip_id,packet_info->datagram_info.retry_count); } printk(KERN_NOTICE "ip_local_error notify performed!. \n"); #ifdef ABPS_DEBUG ABPS_info_take_response(packet_info); #endif ABPS_info_remove(packet_info); return(1); } return(0); }