int fwd_module_init(void) { HTC_DRVREG_CALLBACKS cb = {0}; adf_os_print("FWD:loaded\n"); /* Parse load time parameters */ fwd_parse_params(&fwd_params); cb.deviceInsertedHandler = fwd_device_inserted; cb.deviceRemovedHandler = fwd_device_removed; if (mdio_boot_enable==1) { adf_os_print("FWD:loaded1 \n"); mdio_boot_init(0); adf_os_print("FWD:loaded1 \n"); if (0 == mdio_start_handshake(0)) { int start_time, end_time; start_time=jiffies; mdio_block_send(0, (void*)zcFwGmacImage, fw_gmac_load_addr , zcFwGmacImageSize, fw_gmac_exec_addr ); end_time=jiffies; printk("total transfer time in jiffies %d\n", adf_os_ticks_to_msecs(end_time - start_time)); } /* Pass the load the parameters */ mdio_write_block(0, (unsigned char*)&fwd_params, sizeof(struct hif_gmac_params)); adf_os_print("\nHIF GMAC parametrs sent\n"); } adf_os_print("\n"); HIF_register(&cb); return A_OK; }
void dfs_set_nol(struct ath_dfs *dfs, struct dfsreq_nolelem *dfs_nol, int nchan) { #define TIME_IN_MS 1000 u_int32_t nol_time_left_ms; struct ieee80211_channel chan; int i; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); return; } for (i = 0; i < nchan; i++) { nol_time_left_ms = adf_os_ticks_to_msecs(adf_os_ticks() - dfs_nol[i].nol_start_ticks); if (nol_time_left_ms < dfs_nol[i].nol_timeout_ms) { chan.ic_freq = dfs_nol[i].nol_freq; chan.ic_flags= 0; chan.ic_flagext = 0; nol_time_left_ms = (dfs_nol[i].nol_timeout_ms - nol_time_left_ms); dfs_nol_addchan(dfs, &chan, (nol_time_left_ms / TIME_IN_MS)); } } #undef TIME_IN_MS dfs_nol_update(dfs); }
/* * Delete the given frequency/chwidth from the NOL. */ static void dfs_nol_delete(struct ath_dfs *dfs, u_int16_t delfreq, u_int16_t delchwidth) { struct dfs_nolelem *nol,**prev_next; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS, "%s: sc_dfs is NULL\n", __func__); return; } DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: remove channel=%d/%d MHz from NOL\n", __func__, delfreq, delchwidth); prev_next = &(dfs->dfs_nol); nol = dfs->dfs_nol; while (nol != NULL) { if (nol->nol_freq == delfreq && nol->nol_chwidth == delchwidth) { *prev_next = nol->nol_next; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s removing channel %d/%dMHz from NOL tstamp=%d\n", __func__, nol->nol_freq, nol->nol_chwidth, (adf_os_ticks_to_msecs(adf_os_ticks()) / 1000)); OS_CANCEL_TIMER(&nol->nol_timer); OS_FREE(nol); nol = NULL; nol = *prev_next; /* Update the NOL counter */ dfs->dfs_nol_count--; /* Be paranoid! */ if (dfs->dfs_nol_count < 0) { DFS_PRINTK("%s: dfs_nol_count < 0; eek!\n", __func__); dfs->dfs_nol_count = 0; } } else { prev_next = &(nol->nol_next); nol = nol->nol_next; } } }
void dfs_print_nol(struct ath_dfs *dfs) { struct dfs_nolelem *nol; int i = 0; uint32_t diff_ms, remaining_sec; if (dfs == NULL) { DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: sc_dfs is NULL\n", __func__); return; } nol = dfs->dfs_nol; DFS_DPRINTK(dfs, ATH_DEBUG_DFS_NOL, "%s: NOL\n", __func__); while (nol != NULL) { diff_ms = adf_os_ticks_to_msecs(adf_os_ticks() - nol->nol_start_ticks); diff_ms = (nol->nol_timeout_ms - diff_ms); remaining_sec = diff_ms / 1000; /* convert to seconds */ printk("nol:%d channel=%d MHz width=%d MHz time left=%u seconds nol starttick=%llu \n", i++, nol->nol_freq, nol->nol_chwidth, remaining_sec, (unsigned long long)nol->nol_start_ticks); nol = nol->nol_next; } }
adf_nbuf_t ol_rx_pn_check_base( struct ol_txrx_vdev_t *vdev, struct ol_txrx_peer_t *peer, unsigned tid, adf_nbuf_t msdu_list) { struct ol_txrx_pdev_t *pdev = vdev->pdev; union htt_rx_pn_t *last_pn; adf_nbuf_t out_list_head = NULL; adf_nbuf_t out_list_tail = NULL; adf_nbuf_t mpdu; int index; /* unicast vs. multicast */ int pn_len; void *rx_desc; int last_pn_valid; /* Make sure host pn check is not redundant */ if ((adf_os_atomic_read(&peer->fw_pn_check)) || (vdev->opmode == wlan_op_mode_ibss)) { return msdu_list; } /* First, check whether the PN check applies */ rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, msdu_list); adf_os_assert(htt_rx_msdu_has_wlan_mcast_flag(pdev->htt_pdev, rx_desc)); index = htt_rx_msdu_is_wlan_mcast(pdev->htt_pdev, rx_desc) ? txrx_sec_mcast : txrx_sec_ucast; pn_len = pdev->rx_pn[peer->security[index].sec_type].len; if (pn_len == 0) { return msdu_list; } last_pn_valid = peer->tids_last_pn_valid[tid]; last_pn = &peer->tids_last_pn[tid]; mpdu = msdu_list; while (mpdu) { adf_nbuf_t mpdu_tail, next_mpdu; union htt_rx_pn_t new_pn; int pn_is_replay = 0; rx_desc = htt_rx_msdu_desc_retrieve(pdev->htt_pdev, mpdu); /* * Find the last MSDU within this MPDU, and * the find the first MSDU within the next MPDU. */ ol_rx_mpdu_list_next(pdev, mpdu, &mpdu_tail, &next_mpdu); /* Don't check the PN replay for non-encrypted frames */ if (!htt_rx_mpdu_is_encrypted(pdev->htt_pdev, rx_desc)) { ADD_MPDU_TO_LIST(out_list_head, out_list_tail, mpdu, mpdu_tail); mpdu = next_mpdu; continue; } /* retrieve PN from rx descriptor */ htt_rx_mpdu_desc_pn(pdev->htt_pdev, rx_desc, &new_pn, pn_len); /* if there was no prior PN, there's nothing to check */ if (last_pn_valid) { pn_is_replay = pdev->rx_pn[peer->security[index].sec_type].cmp( &new_pn, last_pn, index == txrx_sec_ucast, vdev->opmode); } else { last_pn_valid = peer->tids_last_pn_valid[tid] = 1; } if (pn_is_replay) { adf_nbuf_t msdu; static u_int32_t last_pncheck_print_time = 0; int log_level; u_int32_t current_time_ms; /* * This MPDU failed the PN check: * 1. Notify the control SW of the PN failure * (so countermeasures can be taken, if necessary) * 2. Discard all the MSDUs from this MPDU. */ msdu = mpdu; current_time_ms = adf_os_ticks_to_msecs(adf_os_ticks()); if (TXRX_PN_CHECK_FAILURE_PRINT_PERIOD_MS < (current_time_ms - last_pncheck_print_time)) { last_pncheck_print_time = current_time_ms; log_level = TXRX_PRINT_LEVEL_WARN; } else { log_level = TXRX_PRINT_LEVEL_INFO2; } TXRX_PRINT(log_level, "PN check failed - TID %d, peer %p " "(%02x:%02x:%02x:%02x:%02x:%02x) %s\n" " old PN (u64 x2)= 0x%08llx %08llx (LSBs = %lld)\n" " new PN (u64 x2)= 0x%08llx %08llx (LSBs = %lld)\n" " new seq num = %d\n", tid, peer, peer->mac_addr.raw[0], peer->mac_addr.raw[1], peer->mac_addr.raw[2], peer->mac_addr.raw[3], peer->mac_addr.raw[4], peer->mac_addr.raw[5], (index == txrx_sec_ucast) ? "ucast" : "mcast", last_pn->pn128[1], last_pn->pn128[0], last_pn->pn128[0] & 0xffffffffffffULL, new_pn.pn128[1], new_pn.pn128[0], new_pn.pn128[0] & 0xffffffffffffULL, htt_rx_mpdu_desc_seq_num(pdev->htt_pdev, rx_desc)); #if defined(ENABLE_RX_PN_TRACE) ol_rx_pn_trace_display(pdev, 1); #endif /* ENABLE_RX_PN_TRACE */ ol_rx_err( pdev->ctrl_pdev, vdev->vdev_id, peer->mac_addr.raw, tid, htt_rx_mpdu_desc_tsf32(pdev->htt_pdev, rx_desc), OL_RX_ERR_PN, mpdu, NULL, 0); /* free all MSDUs within this MPDU */ do { adf_nbuf_t next_msdu; OL_RX_ERR_STATISTICS_1(pdev, vdev, peer, rx_desc, OL_RX_ERR_PN); next_msdu = adf_nbuf_next(msdu); htt_rx_desc_frame_free(pdev->htt_pdev, msdu); if (msdu == mpdu_tail) { break; } else { msdu = next_msdu; } } while (1); } else { ADD_MPDU_TO_LIST(out_list_head, out_list_tail, mpdu, mpdu_tail); /* * Remember the new PN. * For simplicity, just do 2 64-bit word copies to cover the worst * case (WAPI), regardless of the length of the PN. * This is more efficient than doing a conditional branch to copy * only the relevant portion. */ last_pn->pn128[0] = new_pn.pn128[0]; last_pn->pn128[1] = new_pn.pn128[1]; OL_RX_PN_TRACE_ADD(pdev, peer, tid, rx_desc); } mpdu = next_mpdu; } /* make sure the list is null-terminated */ if (out_list_tail) { adf_nbuf_set_next(out_list_tail, NULL); } return out_list_head; }