1 /* 2 * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /*======================================================================== 21 22 \file epping_txrx.c 23 24 \brief WLAN End Point Ping test tool implementation 25 26 ========================================================================*/ 27 28 /*-------------------------------------------------------------------------- 29 Include Files 30 ------------------------------------------------------------------------*/ 31 #include <cds_api.h> 32 #include <cds_sched.h> 33 #include <linux/etherdevice.h> 34 #include <linux/firmware.h> 35 #include <wni_api.h> 36 #include <wlan_ptt_sock_svc.h> 37 #include <linux/wireless.h> 38 #include <net/cfg80211.h> 39 #include <pld_common.h> 40 #include <linux/rtnetlink.h> 41 #include <linux/semaphore.h> 42 #include <linux/ctype.h> 43 #include "epping_main.h" 44 #include "epping_internal.h" 45 #include "qdf_net_if.h" 46 47 static int epping_start_adapter(epping_adapter_t *adapter); 48 static void epping_stop_adapter(epping_adapter_t *adapter); 49 50 static void epping_timer_expire(void *data) 51 { 52 struct net_device *dev = (struct net_device *)data; 53 epping_adapter_t *adapter; 54 55 if (!dev) { 56 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 57 "%s: netdev = NULL", __func__); 58 return; 59 } 60 61 adapter = netdev_priv(dev); 62 if (!adapter) { 63 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 64 "%s: adapter = NULL", __func__); 65 return; 66 } 67 adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; 68 epping_tx_timer_expire(adapter); 69 } 70 71 static int epping_ndev_open(struct net_device *dev) 72 { 73 epping_adapter_t *adapter; 74 int ret = 0; 75 76 adapter = netdev_priv(dev); 77 epping_start_adapter(adapter); 78 return ret; 79 } 80 81 static int epping_ndev_stop(struct net_device *dev) 82 { 83 epping_adapter_t *adapter; 84 int ret = 0; 85 86 adapter = netdev_priv(dev); 87 if (!adapter) { 88 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 89 "%s: EPPING adapter context is Null", __func__); 90 ret = -ENODEV; 91 goto end; 92 } 93 epping_stop_adapter(adapter); 94 end: 95 return ret; 96 } 97 98 static void epping_ndev_uninit(struct net_device *dev) 99 { 100 epping_adapter_t *adapter; 101 102 adapter = netdev_priv(dev); 103 if (!adapter) { 104 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 105 "%s: EPPING adapter context is Null", __func__); 106 goto end; 107 } 108 epping_stop_adapter(adapter); 109 end: 110 return; 111 } 112 113 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)) 114 static void epping_tx_queue_timeout(struct net_device *dev, 115 unsigned int txqueue) 116 #else 117 static void epping_tx_queue_timeout(struct net_device *dev) 118 #endif 119 { 120 epping_adapter_t *adapter; 121 122 adapter = netdev_priv(dev); 123 if (!adapter) { 124 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 125 "%s: EPPING adapter context is Null", __func__); 126 goto end; 127 } 128 129 EPPING_LOG(QDF_TRACE_LEVEL_ERROR, 130 "%s: Transmission timeout occurred, adapter->started= %d", 131 __func__, adapter->started); 132 133 /* Getting here implies we disabled the TX queues 134 * for too long. Since this is epping 135 * (not because of disassociation or low resource scenarios), 136 * try to restart the queue 137 */ 138 if (adapter->started) 139 netif_wake_queue(dev); 140 end: 141 return; 142 143 } 144 145 static netdev_tx_t epping_hard_start_xmit(struct sk_buff *skb, 146 struct net_device *dev) 147 { 148 epping_adapter_t *adapter; 149 int ret = 0; 150 151 adapter = netdev_priv(dev); 152 if (!adapter) { 153 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 154 "%s: EPPING adapter context is Null", __func__); 155 kfree_skb(skb); 156 ret = -ENODEV; 157 goto end; 158 } 159 qdf_net_buf_debug_acquire_skb(skb, __FILE__, __LINE__); 160 ret = epping_tx_send(skb, adapter); 161 end: 162 return NETDEV_TX_OK; 163 } 164 165 static struct net_device_stats *epping_get_stats(struct net_device *dev) 166 { 167 epping_adapter_t *adapter = netdev_priv(dev); 168 169 if (!adapter) { 170 EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: adapter = NULL", 171 __func__); 172 return NULL; 173 } 174 175 return &adapter->stats; 176 } 177 178 static int epping_ndev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 179 { 180 epping_adapter_t *adapter; 181 int ret = 0; 182 183 adapter = netdev_priv(dev); 184 if (!adapter) { 185 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 186 "%s: EPPING adapter context is Null", __func__); 187 ret = -ENODEV; 188 goto end; 189 } 190 if (dev != adapter->dev) { 191 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 192 "%s: HDD adapter/dev inconsistency", __func__); 193 ret = -ENODEV; 194 goto end; 195 } 196 197 if ((!ifr) || (!ifr->ifr_data)) { 198 ret = -EINVAL; 199 goto end; 200 } 201 202 switch (cmd) { 203 case (SIOCDEVPRIVATE + 1): 204 EPPING_LOG(QDF_TRACE_LEVEL_ERROR, 205 "%s: do not support ioctl %d (SIOCDEVPRIVATE + 1)", 206 __func__, cmd); 207 break; 208 default: 209 EPPING_LOG(QDF_TRACE_LEVEL_ERROR, "%s: unknown ioctl %d", 210 __func__, cmd); 211 ret = -EINVAL; 212 break; 213 } 214 215 end: 216 return ret; 217 } 218 219 static int epping_set_mac_address(struct net_device *dev, void *addr) 220 { 221 epping_adapter_t *adapter = netdev_priv(dev); 222 struct sockaddr *psta_mac_addr = addr; 223 qdf_mem_copy(&adapter->macAddressCurrent, 224 psta_mac_addr->sa_data, ETH_ALEN); 225 qdf_net_update_net_device_dev_addr(dev, psta_mac_addr->sa_data, 226 ETH_ALEN); 227 return 0; 228 } 229 230 static void epping_stop_adapter(epping_adapter_t *adapter) 231 { 232 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 233 234 if (!qdf_ctx) { 235 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 236 "%s: qdf_ctx is NULL\n", __func__); 237 return; 238 } 239 240 if (adapter && adapter->started) { 241 EPPING_LOG(LOG1, FL("Disabling queues")); 242 netif_tx_disable(adapter->dev); 243 netif_carrier_off(adapter->dev); 244 adapter->started = false; 245 pld_request_bus_bandwidth(qdf_ctx->dev, 246 PLD_BUS_WIDTH_LOW); 247 } 248 } 249 250 static int epping_start_adapter(epping_adapter_t *adapter) 251 { 252 qdf_device_t qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); 253 254 if (!qdf_ctx) { 255 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 256 "%s: qdf_ctx is NULL", __func__); 257 return -EINVAL; 258 } 259 260 if (!adapter) { 261 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 262 "%s: adapter= NULL\n", __func__); 263 return -EINVAL; 264 } 265 if (!adapter->started) { 266 pld_request_bus_bandwidth(qdf_ctx->dev, 267 PLD_BUS_WIDTH_HIGH); 268 netif_carrier_on(adapter->dev); 269 EPPING_LOG(LOG1, FL("Enabling queues")); 270 netif_tx_start_all_queues(adapter->dev); 271 adapter->started = true; 272 } else { 273 EPPING_LOG(QDF_TRACE_LEVEL_WARN, 274 "%s: adapter %pK already started\n", __func__, 275 adapter); 276 } 277 return 0; 278 } 279 280 static int epping_register_adapter(epping_adapter_t *adapter, bool rtnl_held) 281 { 282 int ret = 0; 283 284 if (!rtnl_held) 285 ret = register_netdev(adapter->dev); 286 else 287 ret = register_netdevice(adapter->dev); 288 if (ret != 0) { 289 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 290 "%s: unable to register device\n", 291 adapter->dev->name); 292 } else { 293 adapter->registered = true; 294 } 295 return ret; 296 } 297 298 static void epping_unregister_adapter(epping_adapter_t *adapter) 299 { 300 if (adapter) { 301 epping_stop_adapter(adapter); 302 if (adapter->registered) { 303 unregister_netdev(adapter->dev); 304 adapter->registered = false; 305 } 306 } else { 307 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 308 "%s: adapter = NULL, unable to unregister device\n", 309 __func__); 310 } 311 } 312 313 void epping_destroy_adapter(epping_adapter_t *adapter) 314 { 315 struct net_device *dev = NULL; 316 epping_context_t *pEpping_ctx; 317 318 if (!adapter || !adapter->pEpping_ctx) { 319 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 320 "%s: adapter = NULL\n", __func__); 321 return; 322 } 323 324 dev = adapter->dev; 325 pEpping_ctx = adapter->pEpping_ctx; 326 epping_unregister_adapter(adapter); 327 328 qdf_spinlock_destroy(&adapter->data_lock); 329 qdf_timer_free(&adapter->epping_timer); 330 adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; 331 332 while (qdf_nbuf_queue_len(&adapter->nodrop_queue)) { 333 qdf_nbuf_t tmp_nbuf = NULL; 334 tmp_nbuf = qdf_nbuf_queue_remove(&adapter->nodrop_queue); 335 if (tmp_nbuf) 336 qdf_nbuf_free(tmp_nbuf); 337 } 338 339 free_netdev(dev); 340 if (!pEpping_ctx) 341 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 342 "%s: pEpping_ctx = NULL\n", __func__); 343 else 344 pEpping_ctx->epping_adapter = NULL; 345 } 346 347 static struct net_device_ops epping_drv_ops = { 348 .ndo_open = epping_ndev_open, 349 .ndo_stop = epping_ndev_stop, 350 .ndo_uninit = epping_ndev_uninit, 351 .ndo_start_xmit = epping_hard_start_xmit, 352 .ndo_tx_timeout = epping_tx_queue_timeout, 353 .ndo_get_stats = epping_get_stats, 354 .ndo_do_ioctl = epping_ndev_ioctl, 355 .ndo_set_mac_address = epping_set_mac_address, 356 .ndo_select_queue = NULL, 357 }; 358 359 #define EPPING_TX_QUEUE_MAX_LEN 128 /* need to be power of 2 */ 360 361 epping_adapter_t *epping_add_adapter(epping_context_t *pEpping_ctx, 362 tSirMacAddr macAddr, 363 enum QDF_OPMODE device_mode, 364 bool rtnl_held) 365 { 366 struct net_device *dev; 367 epping_adapter_t *adapter; 368 369 dev = alloc_netdev(sizeof(epping_adapter_t), "wifi%d", 370 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) 371 NET_NAME_UNKNOWN, 372 #endif 373 ether_setup); 374 if (!dev) { 375 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 376 "%s: Cannot allocate epping_adapter_t\n", __func__); 377 return NULL; 378 } 379 380 adapter = netdev_priv(dev); 381 qdf_mem_zero(adapter, sizeof(*adapter)); 382 adapter->dev = dev; 383 adapter->pEpping_ctx = pEpping_ctx; 384 adapter->device_mode = device_mode; /* station, SAP, etc */ 385 qdf_net_update_net_device_dev_addr(dev, 386 (void *)macAddr, 387 sizeof(tSirMacAddr)); 388 qdf_mem_copy(adapter->macAddressCurrent.bytes, 389 macAddr, sizeof(tSirMacAddr)); 390 qdf_spinlock_create(&adapter->data_lock); 391 qdf_nbuf_queue_init(&adapter->nodrop_queue); 392 adapter->epping_timer_state = EPPING_TX_TIMER_STOPPED; 393 qdf_timer_init(epping_get_qdf_ctx(), &adapter->epping_timer, 394 epping_timer_expire, dev, QDF_TIMER_TYPE_SW); 395 dev->type = ARPHRD_IEEE80211; 396 dev->needed_headroom += 24; 397 dev->netdev_ops = &epping_drv_ops; 398 dev->watchdog_timeo = 5 * HZ; /* XXX */ 399 dev->tx_queue_len = EPPING_TXBUF - 1; /* 1 for mgmt frame */ 400 if (epping_register_adapter(adapter, rtnl_held) == 0) { 401 EPPING_LOG(LOG1, FL("Disabling queues")); 402 netif_tx_disable(dev); 403 netif_carrier_off(dev); 404 return adapter; 405 } else { 406 epping_destroy_adapter(adapter); 407 return NULL; 408 } 409 } 410 411 int epping_connect_service(epping_context_t *pEpping_ctx) 412 { 413 int status, i; 414 struct htc_service_connect_req connect; 415 struct htc_service_connect_resp response; 416 417 qdf_mem_zero(&connect, sizeof(connect)); 418 qdf_mem_zero(&response, sizeof(response)); 419 420 /* these fields are the same for all service endpoints */ 421 connect.EpCallbacks.pContext = pEpping_ctx; 422 connect.EpCallbacks.EpTxCompleteMultiple = NULL; 423 connect.EpCallbacks.EpRecv = epping_rx; 424 /* epping_tx_complete use Multiple version */ 425 connect.EpCallbacks.EpTxComplete = epping_tx_complete; 426 connect.MaxSendQueueDepth = 64; 427 428 #ifdef HIF_SDIO 429 connect.EpCallbacks.EpRecvRefill = epping_refill; 430 connect.EpCallbacks.EpSendFull = 431 epping_tx_queue_full /* ar6000_tx_queue_full */; 432 #elif defined(HIF_USB) || defined(HIF_PCI) || defined(HIF_SNOC) || \ 433 defined(HIF_IPCI) 434 connect.EpCallbacks.EpRecvRefill = NULL /* provided by HIF */; 435 connect.EpCallbacks.EpSendFull = NULL /* provided by HIF */; 436 /* disable flow control for hw flow control */ 437 connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL; 438 #endif 439 440 /* connect to service */ 441 connect.service_id = WMI_DATA_BE_SVC; 442 status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response); 443 if (QDF_IS_STATUS_ERROR(status)) { 444 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 445 "Failed to connect to Endpoint Ping BE service status:%d\n", 446 status); 447 return status; 448 } else { 449 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 450 "eppingtest BE endpoint:%d\n", response.Endpoint); 451 } 452 pEpping_ctx->EppingEndpoint[0] = response.Endpoint; 453 454 #if defined(HIF_PCI) || defined(HIF_USB) || defined(HIF_SNOC) || \ 455 defined(HIF_IPCI) 456 connect.service_id = WMI_DATA_BK_SVC; 457 status = htc_connect_service(pEpping_ctx->HTCHandle, &connect, &response); 458 if (QDF_IS_STATUS_ERROR(status)) { 459 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 460 "Failed to connect to Endpoint Ping BK service status:%d\n", 461 status); 462 return status; 463 } else { 464 EPPING_LOG(QDF_TRACE_LEVEL_FATAL, 465 "eppingtest BK endpoint:%d\n", response.Endpoint); 466 } 467 pEpping_ctx->EppingEndpoint[1] = response.Endpoint; 468 /* Since we do not create other two SVC use BK endpoint 469 * for rest ACs (2, 3) */ 470 for (i = 2; i < EPPING_MAX_NUM_EPIDS; i++) { 471 pEpping_ctx->EppingEndpoint[i] = response.Endpoint; 472 } 473 #else 474 /* we only use one endpoint for high latenance bus. 475 * Map all AC's EPIDs to the same endpoint ID returned by HTC */ 476 for (i = 0; i < EPPING_MAX_NUM_EPIDS; i++) { 477 pEpping_ctx->EppingEndpoint[i] = response.Endpoint; 478 } 479 #endif 480 return 0; 481 } 482