summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorninadm <ninadm@qti.qualcomm.com>2014-11-20 12:02:50 -0800
committerAnjaneeDevi Kapparapu <c_akappa@qti.qualcomm.com>2014-12-11 19:39:40 +0530
commit6acf251c85ba697b30293e905f5ad23633671b9c (patch)
tree8efc793fe4736df9f3785883c20f8b1935ac980d
parentc47aea74d499dcb8c7f693f857386c3d7c0ff0e2 (diff)
qcacld: hdd: Merge DSRC changes
- Add OCB mode of operation - Add new config parameter to enable OCB mode - Create new interface for OCB mode - Add new ioctl for OCB Set Schedule command Change-Id: I2e09676909780c5a4f52adf6f56c4e24ccc5e919 CRs-Fixed: 754373
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg.h14
-rw-r--r--CORE/HDD/inc/wlan_hdd_main.h6
-rw-r--r--CORE/HDD/inc/wlan_hdd_tx_rx.h4
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c11
-rwxr-xr-xCORE/HDD/src/wlan_hdd_main.c112
-rw-r--r--CORE/HDD/src/wlan_hdd_tx_rx.c38
-rw-r--r--CORE/HDD/src/wlan_hdd_wext.c397
-rw-r--r--CORE/VOSS/inc/vos_types.h1
-rw-r--r--CORE/VOSS/src/vos_api.c3
9 files changed, 547 insertions, 39 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 0cb804d64cdf..7cf14541f523 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -2703,6 +2703,17 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */
#define CFG_SAP_AUTH_OFL_KEY_DEFAULT ""
#endif /* SAP_AUTH_OFFLOAD */
+enum dot11p_mode {
+ WLAN_HDD_11P_DISABLED = 0,
+ WLAN_HDD_11P_STANDALONE,
+ WLAN_HDD_11P_CONCURRENT,
+};
+
+#define CFG_DOT11P_MODE_NAME "gDot11PMode"
+#define CFG_DOT11P_MODE_DEFAULT ( WLAN_HDD_11P_DISABLED )
+#define CFG_DOT11P_MODE_MIN ( WLAN_HDD_11P_DISABLED )
+#define CFG_DOT11P_MODE_MAX ( WLAN_HDD_11P_CONCURRENT )
+
/*---------------------------------------------------------------------------
Type declarations
-------------------------------------------------------------------------*/
@@ -3260,6 +3271,7 @@ typedef struct
uint32_t dhcp_client_start_ip;
v_U8_t dhcpServerIP[IPADDR_STRING_LENGTH];
#endif /* DHCP_SERVER_OFFLOAD */
+
bool enable_mac_spoofing;
#ifdef IPA_UC_STA_OFFLOAD
bool ipa_uc_sta_offload;
@@ -3289,6 +3301,8 @@ typedef struct
uint32_t sap_auth_offload_sec_type;
uint8_t sap_auth_offload_key[WLAN_PSK_STRING_LENGTH];
#endif /* SAP_AUTH_OFFLOAD */
+
+ uint8_t dot11p_mode;
} hdd_config_t;
#ifdef WLAN_FEATURE_MBSSID
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index 68ece7964842..955c89abd309 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -517,7 +517,8 @@ typedef enum device_mode
WLAN_HDD_MONITOR,
WLAN_HDD_FTM,
WLAN_HDD_IBSS,
- WLAN_HDD_P2P_DEVICE
+ WLAN_HDD_P2P_DEVICE,
+ WLAN_HDD_OCB
}device_mode_t;
typedef enum rem_on_channel_request_type
@@ -1095,6 +1096,9 @@ struct hdd_adapter_s
/* variable for temperature in Celsius */
int temperature;
+
+ /* 802.11p */
+ struct completion hdd_ocb_set_sched_req_var;
};
#define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
diff --git a/CORE/HDD/inc/wlan_hdd_tx_rx.h b/CORE/HDD/inc/wlan_hdd_tx_rx.h
index ae2a9e8d54cd..7f65dc9851e4 100644
--- a/CORE/HDD/inc/wlan_hdd_tx_rx.h
+++ b/CORE/HDD/inc/wlan_hdd_tx_rx.h
@@ -75,6 +75,10 @@
#define SME_QOS_UAPSD_CFG_VI_CHANGED_MASK 0xF4
#define SME_QOS_UAPSD_CFG_VO_CHANGED_MASK 0xF8
+#define HDD_ETH_HEADER_LEN 14
+#define HDD_OCB_TX_HEADER_LEN 16
+#define HDD_ETHERTYPE_OCB_TX 0x8151
+
/*---------------------------------------------------------------------------
Type declarations
-------------------------------------------------------------------------*/
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 680097c1ef4e..5695fddb43a4 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -3515,6 +3515,13 @@ REG_TABLE_ENTRY g_registry_table[] =
VAR_FLAGS_OPTIONAL,
(void *) CFG_SAP_AUTH_OFL_KEY_DEFAULT ),
#endif /* SAP_AUTH_OFFLOAD */
+
+ REG_VARIABLE(CFG_DOT11P_MODE_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, dot11p_mode,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_DOT11P_MODE_DEFAULT,
+ CFG_DOT11P_MODE_MIN,
+ CFG_DOT11P_MODE_MAX),
};
#ifdef WLAN_FEATURE_MBSSID
@@ -5960,6 +5967,10 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx )
smeConfig->csrConfig.is_sta_connection_in_5gz_enabled =
pHddCtx->cfg_ini->is_sta_connection_in_5gz_enabled;
+ /* Update 802.11p config */
+ smeConfig->csrConfig.enable_dot11p = (pHddCtx->cfg_ini->dot11p_mode !=
+ WLAN_HDD_11P_DISABLED);
+
halStatus = sme_UpdateConfig( pHddCtx->hHal, smeConfig);
if ( !HAL_STATUS_SUCCESS( halStatus ) )
{
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 75572214005a..db8ca30f6022 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -8980,6 +8980,7 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
/* fall through */
case WLAN_HDD_P2P_CLIENT:
case WLAN_HDD_P2P_DEVICE:
+ case WLAN_HDD_OCB:
{
pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
@@ -11424,6 +11425,21 @@ VOS_STATUS hdd_set_sme_chan_list(hdd_context_t *hdd_ctx)
hdd_ctx->reg.cc_src);
}
+/**
+ * hdd_set_dot11p_config() - Set 802.11p config flag
+ * @hdd_ctx: HDD Context pointer
+ *
+ * TODO-OCB: This has been temporarily added to ensure this paramter
+ * is set in CSR when we init the channel list. This should be removed
+ * once the 5.9 GHz channels are added to the regulatory domain.
+ */
+void hdd_set_dot11p_config(hdd_context_t *hdd_ctx)
+{
+ sme_set_dot11p_config(hdd_ctx->hHal,
+ hdd_ctx->cfg_ini->dot11p_mode !=
+ WLAN_HDD_11P_DISABLED);
+}
+
/**---------------------------------------------------------------------------
\brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
@@ -11658,6 +11674,7 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
#endif
tANI_U8 rtnl_lock_enable;
tANI_U8 reg_netdev_notifier_done = FALSE;
+ hdd_adapter_t *dot11_adapter = NULL;
ENTER();
@@ -11899,6 +11916,13 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
goto err_vosclose;
}
+ /* Set 802.11p config
+ * TODO-OCB: This has been temporarily added here to ensure this paramter
+ * is set in CSR when we init the channel list. This should be removed
+ * once the 5.9 GHz channels are added to the regulatory domain.
+ */
+ hdd_set_dot11p_config(pHddCtx);
+
if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
{
pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
@@ -12042,53 +12066,65 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
rtnl_lock_enable = FALSE;
#endif
- pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
- wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable );
+ if (pHddCtx->cfg_ini->dot11p_mode == WLAN_HDD_11P_STANDALONE) {
+ /* Create only 802.11p interface */
+ pAdapter = hdd_open_adapter(pHddCtx, WLAN_HDD_OCB,
+ "wlanocb%d", wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable);
+ } else {
+ pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
+ wlan_hdd_get_intf_addr(pHddCtx), rtnl_lock_enable );
#ifdef WLAN_OPEN_P2P_INTERFACE
- /* Open P2P device interface */
- if (pAdapter != NULL)
- {
- if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated)
- {
- vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
- pHddCtx->cfg_ini->intfMacAddr[0].bytes,
- sizeof(tSirMacAddr));
-
- /* Generate the P2P Device Address. This consists of the device's
- * primary MAC address with the locally administered bit set.
- */
- pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
- }
- else
- {
- tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
- if (p2p_dev_addr != NULL)
- {
- vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
- p2p_dev_addr, VOS_MAC_ADDR_SIZE);
+ /* Open P2P device interface */
+ if (pAdapter != NULL) {
+ if (pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated) {
+ vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
+ pHddCtx->cfg_ini->intfMacAddr[0].bytes,
+ sizeof(tSirMacAddr));
+
+ /* Generate the P2P Device Address. This consists of the device's
+ * primary MAC address with the locally administered bit set.
+ */
+ pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
+ } else {
+ uint8_t* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
+ if (p2p_dev_addr != NULL) {
+ vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
+ p2p_dev_addr, VOS_MAC_ADDR_SIZE);
+ } else {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ FL("Failed to allocate mac_address for p2p_device"));
+ goto err_close_adapter;
+ }
}
- else
- {
+
+ pP2pAdapter = hdd_open_adapter(pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
+ &pHddCtx->p2pDeviceAddress.bytes[0],
+ rtnl_lock_enable);
+
+ if (NULL == pP2pAdapter) {
hddLog(VOS_TRACE_LEVEL_FATAL,
- "%s: Failed to allocate mac_address for p2p_device",
- __func__);
+ FL("Failed to do hdd_open_adapter for P2P Device Interface"));
goto err_close_adapter;
}
}
-
- pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
- &pHddCtx->p2pDeviceAddress.bytes[0], rtnl_lock_enable );
-
- if ( NULL == pP2pAdapter )
- {
- hddLog(VOS_TRACE_LEVEL_FATAL,
- "%s: Failed to do hdd_open_adapter for P2P Device Interface",
- __func__);
- goto err_close_adapter;
+#endif /* WLAN_OPEN_P2P_INTERFACE */
+
+ /* Open 802.11p Interface */
+ if (pAdapter != NULL) {
+ if (pHddCtx->cfg_ini->dot11p_mode == WLAN_HDD_11P_CONCURRENT) {
+ dot11_adapter = hdd_open_adapter(pHddCtx, WLAN_HDD_OCB,
+ "wlanocb%d", wlan_hdd_get_intf_addr(pHddCtx),
+ rtnl_lock_enable);
+
+ if (dot11_adapter == NULL) {
+ hddLog(VOS_TRACE_LEVEL_FATAL,
+ FL("hdd_open_adapter() failed for 802.11p Interface"));
+ goto err_close_adapter;
+ }
+ }
}
}
-#endif
if( pAdapter == NULL )
{
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index a41dc0147bd1..f07843cd8eaf 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -713,6 +713,40 @@ void hdd_tx_resume_cb(void *adapter_context,
}
#endif /* QCA_LL_TX_FLOW_CT */
+/**
+ * hdd_remove_ocb_tx_header() - Function to check for OCB
+ * TX control header on a packet and extract it if present
+ *
+ * @skb: Pointer to OS packet (sk_buff)
+ */
+static void hdd_remove_ocb_tx_header(struct sk_buff *skb)
+{
+ struct ethhdr *eth_hdr_p;
+ struct ethhdr eth_hdr;
+
+ /* Check if TX control header is present */
+ eth_hdr_p = (struct ethhdr *) &skb->data[0];
+ if (eth_hdr_p->h_proto != htons(HDD_ETHERTYPE_OCB_TX)) {
+ /* TX control header is not present. Nothing to do.. */
+ return;
+ }
+
+ /* Copy and remove the ethernet header */
+ memcpy(&eth_hdr, eth_hdr_p, HDD_ETH_HEADER_LEN);
+ skb_pull(skb, HDD_ETH_HEADER_LEN);
+
+ /* Remove the TX control header */
+ skb_pull(skb, HDD_OCB_TX_HEADER_LEN);
+
+ /* Convert Ethernet header to 802.3 header by changing ethertype
+ field to length field */
+ eth_hdr.h_proto = htons(skb->len);
+
+ /* Push the now 802.3 header back */
+ skb_push(skb, HDD_ETH_HEADER_LEN);
+ memcpy(&skb->data[0], &eth_hdr, HDD_ETH_HEADER_LEN);
+}
+
/**============================================================================
@brief hdd_hard_start_xmit() - Function registered with the Linux OS for
transmitting packets. This version of the function directly passes the packet
@@ -776,6 +810,10 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
STAId = pHddStaCtx->conn_info.staId[0];
}
+ if (pAdapter->device_mode == WLAN_HDD_OCB) {
+ hdd_remove_ocb_tx_header(skb);
+ }
+
#ifdef QCA_LL_TX_FLOW_CT
if (VOS_FALSE ==
WLANTL_GetTxResource((WLAN_HDD_GET_CTX(pAdapter))->pvosContext,
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 0e0c0723c16d..5307a165cf5e 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -433,6 +433,9 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2},
#define WLAN_SET_POWER_PARAMS (SIOCIWFIRSTPRIV + 29)
+/* 802.11p IOCTL */
+#define WLAN_SET_DOT11P_CHANNEL_SCHED (SIOCIWFIRSTPRIV + 30)
+
#define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31)
/* Private ioctls and their sub-ioctls */
@@ -2997,6 +3000,399 @@ static int iw_get_linkspeed_priv(struct net_device *dev,
return 0;
}
+/* Structure definitions for WLAN_SET_DOT11P_CHANNEL_SCHED */
+#define NUM_AC (4)
+#define OCB_CHANNEL_MAX (5)
+#define DOT11P_TX_PWR_MAX (23)
+#define AIFSN_MIN (2)
+#define AIFSN_MAX (15)
+#define CW_MIN (1)
+#define CW_MAX (10)
+#define HDD_OCB_SET_SCHED_TIME_OUT (1500)
+
+#define NUM_DOT11P_CHANNELS 9
+static const uint32_t valid_dot11p_channels[NUM_DOT11P_CHANNELS] = {
+ 5860, 5870, 5880, 5890, 5900, 5910, 5920, 5875, 5905,
+};
+
+/**
+ * struct ocb_qos_params - QoS Parameters for each AC
+ * @aifsn: Arbitration Inter-Frame Spacing
+ * @cwmin: Contention Window (Min)
+ * @cwmax: Contention Window (Max)
+ */
+struct ocb_qos_params {
+ uint8_t aifsn;
+ uint8_t cwmin;
+ uint8_t cwmax;
+};
+
+/**
+ * struct ocb_channel - Parameters for each OCB channel
+ * @channel_freq: Channel Frequency (MHz)
+ * @duration: Channel Duration (ms)
+ * @start_guard_interval: Start Guard Interval (ms)
+ * @end_guard_interval: End Guard Interval (ms)
+ * @tx_power: Transmit Power (dBm)
+ * @tx_rate: Transmit Data Rate (mbit)
+ * @qos_params: Array of QoS Parameters
+ * @per_packet_rx_stats: Enable per packet RX statistics
+ */
+struct ocb_channel {
+ uint32_t channel_freq;
+ uint32_t duration;
+ uint32_t start_guard_interval;
+ uint32_t end_guard_interval;
+ uint32_t tx_power;
+ uint32_t tx_rate;
+ struct ocb_qos_params qos_params[NUM_AC];
+ uint32_t per_packet_rx_stats;
+};
+
+/**
+ * struct dot11p_channel_sched - OCB channel schedule
+ * @num_channels: Number of channels
+ * @channels: Array of channel parameters
+ * @off_channel_tx: Enable off channel TX
+ */
+struct dot11p_channel_sched {
+ uint32_t num_channels;
+ struct ocb_channel channels[OCB_CHANNEL_MAX];
+ uint32_t off_channel_tx;
+};
+
+/**
+ * dot11p_validate_channel() - Check if specified channel is valid
+ * @channel: Channel Frequency (MHz)
+ *
+ * Return: 0 on success. 1 on failure.
+ */
+static int dot11p_validate_channel(uint32_t channel)
+{
+ int i;
+
+ for (i = 0; i < NUM_DOT11P_CHANNELS; i++) {
+ if (channel == valid_dot11p_channels[i]) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/**
+ * dot11p_validate_qos_params() - Check if QoS parameters are valid
+ * @qos_params: Array of QoS parameters
+ *
+ * Return: 0 on success. 1 on failure.
+ */
+static int dot11p_validate_qos_params(struct ocb_qos_params qos_params[])
+{
+ int i;
+
+ for (i = 0; i < NUM_AC; i++) {
+ if ((!qos_params[i].aifsn) && (!qos_params[i].cwmin)
+ && (!qos_params[i].cwmax)) {
+ continue;
+ }
+
+ /* Validate AIFSN */
+ if ((qos_params[i].aifsn < AIFSN_MIN)
+ || (qos_params[i].aifsn > AIFSN_MAX)) {
+ return 1;
+ }
+
+ /* Validate CWMin */
+ if ((qos_params[i].cwmin < CW_MIN)
+ || (qos_params[i].cwmin > CW_MAX)) {
+ return 1;
+ }
+
+ /* Validate CWMax */
+ if ((qos_params[i].cwmax < CW_MIN)
+ || (qos_params[i].cwmax > CW_MAX)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * dot11p_validate_sched() - Check if schedule is valid
+ * @sched: OCB channel schedule
+ *
+ * Return: 0 on success. 1 on failure.
+ */
+int dot11p_validate_sched(struct dot11p_channel_sched *sched)
+{
+ int i;
+
+ if ((sched->num_channels > OCB_CHANNEL_MAX)
+ || (sched->num_channels == 0)) {
+ goto error;
+ }
+
+ for (i = 0; i < sched->num_channels; i++) {
+ /* Validate channel frequency */
+ if (dot11p_validate_channel(sched->channels[i].channel_freq)) {
+ goto error;
+ }
+
+ /* Validate TX Power */
+ if (sched->channels[i].tx_power > DOT11P_TX_PWR_MAX) {
+ goto error;
+ }
+
+ /* Validate TX Rate */
+ switch (sched->channels[i].tx_rate) {
+ case 0:
+ case 6:
+ case 9:
+ case 12:
+ case 18:
+ case 24:
+ case 36:
+ case 48:
+ case 54:
+ break;
+ default:
+ goto error;
+ }
+
+ /* Validate QoS Params */
+ if (dot11p_validate_qos_params(sched->channels[i].qos_params)) {
+ goto error;
+ }
+
+ if ((sched->channels[i].per_packet_rx_stats != 0)
+ && (sched->channels[i].per_packet_rx_stats != 1)) {
+ goto error;
+ }
+ }
+
+ return 0;
+
+error:
+ return 1;
+}
+
+/**
+ * hdd_ocb_register_sta() - Register station with Transport Layer
+ * @adapter: Pointer to HDD Adapter
+ *
+ * This function should be invoked in the OCB Set Schedule callback
+ * to enable the data path in the TL by calling RegisterSTAClient
+ *
+ * Return: 0 on success. -1 on failure.
+ */
+static int hdd_ocb_register_sta(hdd_adapter_t *adapter)
+{
+ VOS_STATUS vos_status = VOS_STATUS_E_FAILURE;
+ WLAN_STADescType sta_desc = {0};
+ hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ u_int8_t peer_id;
+ v_MACADDR_t wildcardBSSID = {
+ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+ };
+
+ vos_status = WLANTL_RegisterOCBPeer(hdd_ctx->pvosContext,
+ adapter->macAddressCurrent.bytes,
+ &peer_id);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
+ hddLog(LOGE, FL("Error registering OCB Self Peer!"));
+ return -1;
+ }
+
+ /* Register adapter for STA ID 0 */
+ /* TODO-OCB: This is for standalone 802.11p only. We need to change this
+ * for concurrent mode */
+ hdd_ctx->sta_to_adapter[0] = adapter;
+
+ sta_desc.ucSTAId = peer_id;
+ /* Fill in MAC addresses */
+ vos_copy_macaddr(&sta_desc.vSelfMACAddress, &adapter->macAddressCurrent);
+ vos_copy_macaddr(&sta_desc.vSTAMACAddress, &adapter->macAddressCurrent);
+ vos_copy_macaddr(&sta_desc.vBSSIDforIBSS, &wildcardBSSID);
+
+ sta_desc.wSTAType = WLAN_STA_OCB;
+ sta_desc.ucQosEnabled = 1;
+ sta_desc.ucInitState = WLANTL_STA_AUTHENTICATED;
+
+ vos_status = WLANTL_RegisterSTAClient(hdd_ctx->pvosContext,
+ hdd_rx_packet_cbk,
+ hdd_tx_complete_cbk,
+ hdd_tx_fetch_packet_cbk, &sta_desc,
+ 0);
+ if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
+ hddLog(LOGE, FL("WLANTL_RegisterSTAClient() failed to register. "
+ "Status= %d [0x%08X]"), vos_status, vos_status);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * hdd_ocb_set_sched_callback() - OCB Set Schedule callback functions
+ * @callback_context: Pointer to HDD Adapter
+ * @rsp: Pointer to response structure
+ *
+ * This function is registered as a callback with the lower layers
+ * and is used to respond with the status of a OCB Set Schedule command.
+ */
+static void hdd_ocb_set_sched_callback(sir_ocb_set_sched_response_t *resp)
+{
+ hdd_adapter_t *adapter;
+
+ if (resp == NULL) {
+ return;
+ }
+
+ adapter = (hdd_adapter_t *)resp->adapter;
+
+ if (resp->status) {
+ /* OCB Set Schedule command failed */
+ hddLog(VOS_TRACE_LEVEL_ERROR,
+ FL("OCB set schedule command failed! Status = %d"),
+ resp->status);
+ goto exit;
+ }
+
+ /* OCB Set Schedule command successful. Open TX data path */
+ if (hdd_ocb_register_sta(adapter)) {
+ resp->status = -1;
+ } else {
+ netif_carrier_on(adapter->dev);
+ netif_tx_start_all_queues(adapter->dev);
+ }
+
+exit:
+ complete(&adapter->hdd_ocb_set_sched_req_var);
+}
+
+/**
+ * iw_set_dot11p_channel_sched() - Handler for WLAN_SET_DOT11P_CHANNEL_SCHED
+ * ioctl
+ * @dev: Pointer to net_device structure
+ * @iw_request_info: IW Request Info
+ * @wrqu: IW Request Userspace Data Pointer
+ * @extra: IW Request Kernel Data Pointer
+ */
+static int iw_set_dot11p_channel_sched(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ int rc = 0;
+ eHalStatus halStatus;
+ struct dot11p_channel_sched *sched;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ sir_ocb_set_sched_request_t *sched_req = NULL;
+ sir_ocb_set_sched_response_t *sched_resp = NULL;
+ sir_ocb_sched_t *sched_ptr;
+ int i;
+
+ if (wlan_hdd_validate_context(WLAN_HDD_GET_CTX(adapter))) {
+ hddLog(LOGE, FL("HDD context is not valid"));
+ return -EINVAL;
+ }
+
+ if (adapter->device_mode != WLAN_HDD_OCB) {
+ hddLog(LOGE, FL("Device not in OCB mode!"));
+ return -EINVAL;
+ }
+
+ if (extra == NULL) {
+ hddLog(LOGE, FL("No data in IOCTL!"));
+ return -EINVAL;
+ }
+
+ sched = (struct dot11p_channel_sched *)extra;
+ if (dot11p_validate_sched(sched)) {
+ hddLog(LOGE, FL("OCB schedule validation failed!"));
+ return -EINVAL;
+ }
+
+ /*
+ * Currently we support only single channel operation.
+ * Hence, we will only use the first channel in the schedule regardless
+ * of the number of channels specified. All duration parameters will also
+ * be ignored.
+ */
+ sched_req = vos_mem_malloc(sizeof(sir_ocb_set_sched_request_t));
+ if (sched_req == NULL) {
+ hddLog(LOGE, FL("Failed to allocate memory!"));
+ return -ENOMEM;
+ }
+ vos_mem_set(sched_req, sizeof(*sched_req), 0);
+
+ sched_resp = vos_mem_malloc(sizeof(sir_ocb_set_sched_response_t));
+ if (sched_resp == NULL) {
+ hddLog(LOGE, FL("Failed to allocate memory!"));
+ rc = -ENOMEM;
+ goto exit;
+ }
+ vos_mem_set(sched_resp, sizeof(*sched_resp), 0);
+
+ sched_req->session_id = adapter->sessionId;
+
+ sched_ptr = &sched_req->sched;
+ sched_ptr->num_channels = 1;
+ sched_ptr->channels[0].chan_freq = sched->channels[0].channel_freq;
+ sched_ptr->channels[0].tx_power = sched->channels[0].tx_power;
+ sched_ptr->channels[0].tx_rate = sched->channels[0].tx_rate;
+ for (i = 0; i < NUM_AC; i++) {
+ sched_ptr->channels[0].qos_params[i].aifsn =
+ sched->channels[0].qos_params[i].aifsn;
+ sched_ptr->channels[0].qos_params[i].cwmin =
+ sched->channels[0].qos_params[i].cwmin;
+ sched_ptr->channels[0].qos_params[i].cwmax =
+ sched->channels[0].qos_params[i].cwmax;
+ }
+ sched_ptr->channels[0].rx_stats = sched->channels[0].per_packet_rx_stats;
+
+ sched_resp->adapter = (void *)adapter;
+ sched_req->resp = sched_resp;
+ sched_req->callback = hdd_ocb_set_sched_callback;
+
+ netif_tx_disable(adapter->dev);
+ netif_carrier_off(adapter->dev);
+
+ init_completion(&adapter->hdd_ocb_set_sched_req_var);
+ halStatus = sme_ocb_set_sched_req(sched_req);
+ if (halStatus != eHAL_STATUS_SUCCESS) {
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ rc = wait_for_completion_timeout(&adapter->hdd_ocb_set_sched_req_var,
+ msecs_to_jiffies(HDD_OCB_SET_SCHED_TIME_OUT));
+ if (!rc) {
+ hddLog(LOGE, FL("Timeout waiting for OCB set sched to complete"));
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ /* Check the status code */
+ if (sched_resp->status) {
+ hddLog(LOGE, FL("Error while setting OCB Schedule"));
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ rc = 0;
+
+exit:
+ if (sched_req) {
+ vos_mem_free(sched_req);
+ }
+ if (sched_resp) {
+ vos_mem_free(sched_resp);
+ }
+ return rc;
+}
+
+
/*
* Support for the RSSI & RSSI-APPROX private commands
* Per the WiFi framework the response must be of the form
@@ -9778,6 +10174,7 @@ static const iw_handler we_private[] = {
[WLAN_SET_POWER_PARAMS - SIOCIWFIRSTPRIV] = iw_set_power_params_priv,
[WLAN_GET_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_linkspeed_priv,
[WLAN_PRIV_SET_TWO_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_set_two_ints_getnone,
+ [WLAN_SET_DOT11P_CHANNEL_SCHED - SIOCIWFIRSTPRIV] = iw_set_dot11p_channel_sched,
};
/*Maximum command length can be only 15 */
diff --git a/CORE/VOSS/inc/vos_types.h b/CORE/VOSS/inc/vos_types.h
index 8082bb09b7b8..69f2abe41f61 100644
--- a/CORE/VOSS/inc/vos_types.h
+++ b/CORE/VOSS/inc/vos_types.h
@@ -146,6 +146,7 @@ typedef enum
VOS_FTM_MODE = 5,
VOS_IBSS_MODE,
VOS_P2P_DEVICE_MODE,
+ VOS_OCB_MODE,
VOS_MAX_NO_OF_MODE
} tVOS_CON_MODE;
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index da273fbb80c7..725b0eb28207 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -2337,6 +2337,9 @@ VOS_STATUS vos_get_vdev_types(tVOS_CON_MODE mode, tANI_U32 *type,
*type = WMI_VDEV_TYPE_AP;
*sub_type = WMI_UNIFIED_VDEV_SUBTYPE_P2P_GO;
break;
+ case VOS_OCB_MODE:
+ *type = WMI_VDEV_TYPE_OCB;
+ break;
default:
hddLog(VOS_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode);
status = VOS_STATUS_E_INVAL;