1 /* 2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <qdf_time.h> 20 #include <qdf_lock.h> 21 #include <qdf_mem.h> 22 #include <qdf_util.h> 23 #include <qdf_defer.h> 24 #include <qdf_atomic.h> 25 #include <qdf_nbuf.h> 26 #include "qdf_net_types.h" 27 #include <hif_usb_internal.h> 28 #include <htc_services.h> 29 #include <hif_debug.h> 30 #define ATH_MODULE_NAME hif 31 #include <a_debug.h> 32 #include "qdf_module.h" 33 #include "hif_usb_internal.h" 34 #include "if_usb.h" 35 #include "usb_api.h" 36 #include "target_type.h" 37 38 #if defined(WLAN_DEBUG) || defined(DEBUG) 39 static ATH_DEBUG_MASK_DESCRIPTION g_hif_debug_description[] = { 40 {USB_HIF_DEBUG_CTRL_TRANS, "Control Transfers"}, 41 {USB_HIF_DEBUG_BULK_IN, "BULK In Transfers"}, 42 {USB_HIF_DEBUG_BULK_OUT, "BULK Out Transfers"}, 43 {USB_HIF_DEBUG_DUMP_DATA, "Dump data"}, 44 {USB_HIF_DEBUG_ENUM, "Enumeration"}, 45 }; 46 47 ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, 48 "hif", 49 "USB Host Interface", 50 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO | 51 USB_HIF_DEBUG_ENUM, 52 ATH_DEBUG_DESCRIPTION_COUNT 53 (g_hif_debug_description), 54 g_hif_debug_description); 55 56 #endif 57 58 #ifdef USB_ISOC_SUPPORT 59 unsigned int hif_usb_isoch_vo = 1; 60 #else 61 unsigned int hif_usb_isoch_vo; 62 #endif 63 unsigned int hif_usb_disable_rxdata2 = 1; 64 65 /** 66 * usb_hif_usb_transmit_complete() - completion routing for tx urb's 67 * @urb: pointer to urb for which tx completion is called 68 * 69 * Return: none 70 */ 71 static void usb_hif_usb_transmit_complete(struct urb *urb) 72 { 73 struct HIF_URB_CONTEXT *urb_context = 74 (struct HIF_URB_CONTEXT *)urb->context; 75 qdf_nbuf_t buf; 76 struct HIF_USB_PIPE *pipe = urb_context->pipe; 77 struct hif_usb_send_context *send_context; 78 79 HIF_DBG("+%s: pipe: %d, stat:%d, len:%d", __func__, 80 pipe->logical_pipe_num, urb->status, urb->actual_length); 81 82 /* this urb is not pending anymore */ 83 usb_hif_remove_pending_transfer(urb_context); 84 85 if (urb->status != 0) { 86 HIF_ERROR("%s: pipe: %d, failed:%d", 87 __func__, pipe->logical_pipe_num, urb->status); 88 } 89 90 buf = urb_context->buf; 91 send_context = urb_context->send_context; 92 93 if (send_context->new_alloc) 94 qdf_mem_free(send_context); 95 else 96 qdf_nbuf_pull_head(buf, send_context->head_data_len); 97 98 urb_context->buf = NULL; 99 usb_hif_cleanup_transmit_urb(urb_context); 100 101 /* note: queue implements a lock */ 102 skb_queue_tail(&pipe->io_comp_queue, buf); 103 HIF_USB_SCHEDULE_WORK(pipe); 104 105 HIF_DBG("-%s", __func__); 106 } 107 108 /** 109 * hif_send_internal() - HIF internal routine to prepare and submit tx urbs 110 * @hif_usb_device: pointer to HIF_DEVICE_USB structure 111 * @pipe_id: HIF pipe on which data is to be sent 112 * @hdr_buf: any header buf to be prepended, currently ignored 113 * @buf: qdf_nbuf_t containing data to be transmitted 114 * @nbytes: number of bytes to be transmitted 115 * 116 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure 117 */ 118 static QDF_STATUS hif_send_internal(struct HIF_DEVICE_USB *hif_usb_device, 119 uint8_t pipe_id, 120 qdf_nbuf_t hdr_buf, 121 qdf_nbuf_t buf, unsigned int nbytes) 122 { 123 QDF_STATUS status = QDF_STATUS_SUCCESS; 124 struct HIF_DEVICE_USB *device = hif_usb_device; 125 struct HIF_USB_PIPE *pipe = &device->pipes[pipe_id]; 126 struct HIF_URB_CONTEXT *urb_context; 127 uint8_t *data; 128 uint32_t len; 129 struct urb *urb; 130 int usb_status; 131 int i; 132 struct hif_usb_send_context *send_context; 133 uint8_t frag_count; 134 uint32_t head_data_len, tmp_frag_count = 0; 135 unsigned char *data_ptr; 136 137 HIF_DBG("+%s pipe : %d, buf:0x%pK nbytes %u", 138 __func__, pipe_id, buf, nbytes); 139 140 frag_count = qdf_nbuf_get_num_frags(buf); 141 if (frag_count == 1) { 142 /* 143 * | hif_usb_send_context | netbuf->data 144 */ 145 head_data_len = sizeof(struct hif_usb_send_context); 146 } else if ((frag_count - 1) <= QDF_NBUF_CB_TX_MAX_EXTRA_FRAGS) { 147 /* 148 * means have extra fragment buf in skb 149 * header data length should be total sending length subtract 150 * internal data length of netbuf 151 * | hif_usb_send_context | fragments except internal buffer | 152 * netbuf->data 153 */ 154 head_data_len = sizeof(struct hif_usb_send_context); 155 while (tmp_frag_count < (frag_count - 1)) { 156 head_data_len = 157 head_data_len + qdf_nbuf_get_frag_len(buf, 158 tmp_frag_count); 159 tmp_frag_count = tmp_frag_count + 1; 160 } 161 } else { 162 /* Extra fragments overflow */ 163 HIF_ERROR("%s Extra fragments count overflow : %d\n", 164 __func__, frag_count); 165 status = QDF_STATUS_E_RESOURCES; 166 goto err; 167 } 168 169 /* Check whether head room is enough to save extra head data */ 170 if (head_data_len <= qdf_nbuf_headroom(buf)) { 171 send_context = (struct hif_usb_send_context *) 172 qdf_nbuf_push_head(buf, head_data_len); 173 send_context->new_alloc = false; 174 } else { 175 send_context = 176 qdf_mem_malloc(sizeof(struct hif_usb_send_context) 177 + head_data_len + nbytes); 178 if (!send_context) { 179 status = QDF_STATUS_E_NOMEM; 180 goto err; 181 } 182 send_context->new_alloc = true; 183 } 184 send_context->netbuf = buf; 185 send_context->hif_usb_device = hif_usb_device; 186 send_context->transfer_id = pipe_id; 187 send_context->head_data_len = head_data_len; 188 /* 189 * Copy data to head part of netbuf or head of allocated buffer. 190 * if buffer is new allocated, the last buffer should be copied also. 191 * It assume last fragment is internal buffer of netbuf 192 * sometime total length of fragments larger than nbytes 193 */ 194 data_ptr = (unsigned char *)send_context + 195 sizeof(struct hif_usb_send_context); 196 for (i = 0; 197 i < (send_context->new_alloc ? frag_count : frag_count - 1); i++) { 198 int frag_len = qdf_nbuf_get_frag_len(buf, i); 199 unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i); 200 201 qdf_mem_copy(data_ptr, frag_addr, frag_len); 202 data_ptr += frag_len; 203 } 204 /* Reset pData pointer and send out */ 205 data_ptr = (unsigned char *)send_context + 206 sizeof(struct hif_usb_send_context); 207 208 urb_context = usb_hif_alloc_urb_from_pipe(pipe); 209 if (!urb_context) { 210 /* TODO : note, it is possible to run out of urbs if 2 211 * endpoints map to the same pipe ID 212 */ 213 HIF_ERROR("%s pipe:%d no urbs left. URB Cnt : %d", 214 __func__, pipe_id, pipe->urb_cnt); 215 status = QDF_STATUS_E_RESOURCES; 216 goto err; 217 } 218 urb_context->send_context = send_context; 219 urb = urb_context->urb; 220 urb_context->buf = buf; 221 data = data_ptr; 222 len = nbytes; 223 224 usb_fill_bulk_urb(urb, 225 device->udev, 226 pipe->usb_pipe_handle, 227 data, 228 (len % pipe->max_packet_size) == 229 0 ? (len + 1) : len, 230 usb_hif_usb_transmit_complete, urb_context); 231 232 if ((len % pipe->max_packet_size) == 0) 233 /* hit a max packet boundary on this pipe */ 234 235 HIF_DBG 236 ("athusb bulk send submit:%d, 0x%X (ep:0x%2.2X), %d bytes", 237 pipe->logical_pipe_num, pipe->usb_pipe_handle, 238 pipe->ep_address, nbytes); 239 240 usb_hif_enqueue_pending_transfer(pipe, urb_context); 241 usb_status = usb_submit_urb(urb, GFP_ATOMIC); 242 if (usb_status) { 243 if (send_context->new_alloc) 244 qdf_mem_free(send_context); 245 else 246 qdf_nbuf_pull_head(buf, head_data_len); 247 urb_context->buf = NULL; 248 HIF_ERROR("athusb : usb bulk transmit failed %d", 249 usb_status); 250 usb_hif_remove_pending_transfer(urb_context); 251 usb_hif_cleanup_transmit_urb(urb_context); 252 status = QDF_STATUS_E_FAILURE; 253 goto err; 254 } 255 256 err: 257 if (!QDF_IS_STATUS_SUCCESS(status) && 258 (status != QDF_STATUS_E_RESOURCES)) { 259 HIF_ERROR("athusb send failed %d", status); 260 } 261 262 HIF_DBG("-%s pipe : %d", __func__, pipe_id); 263 264 return status; 265 } 266 267 /** 268 * hif_send_head() - HIF routine exposed to upper layers to send data 269 * @scn: pointer to hif_opaque_softc structure 270 * @pipe_id: HIF pipe on which data is to be sent 271 * @transfer_id: endpoint ID on which data is to be sent 272 * @nbytes: number of bytes to be transmitted 273 * @wbuf: qdf_nbuf_t containing data to be transmitted 274 * @hdr_buf: any header buf to be prepended, currently ignored 275 * @data_attr: data_attr field from cvg_nbuf_cb of wbuf 276 * 277 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure 278 */ 279 QDF_STATUS hif_send_head(struct hif_opaque_softc *scn, uint8_t pipe_id, 280 uint32_t transfer_id, uint32_t nbytes, 281 qdf_nbuf_t wbuf, uint32_t data_attr) 282 { 283 QDF_STATUS status = QDF_STATUS_SUCCESS; 284 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 285 286 status = hif_send_internal(device, pipe_id, NULL, wbuf, nbytes); 287 return status; 288 } 289 290 /** 291 * hif_get_free_queue_number() - get # of free TX resources in a given HIF pipe 292 * @scn: pointer to hif_opaque_softc structure 293 * @pipe_id: HIF pipe which is being polled for free resources 294 * 295 * Return: # of free resources in pipe_id 296 */ 297 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *scn, 298 uint8_t pipe_id) 299 { 300 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 301 struct HIF_USB_PIPE *pipe = &device->pipes[pipe_id]; 302 u16 urb_cnt; 303 304 qdf_spin_lock_irqsave(&pipe->device->cs_lock); 305 urb_cnt = pipe->urb_cnt; 306 qdf_spin_unlock_irqrestore(&pipe->device->cs_lock); 307 308 return urb_cnt; 309 } 310 311 /** 312 * hif_post_init() - copy HTC callbacks to HIF 313 * @scn: pointer to hif_opaque_softc structure 314 * @target: pointer to HTC_TARGET structure 315 * @callbacks: htc callbacks 316 * 317 * Return: none 318 */ 319 void hif_post_init(struct hif_opaque_softc *scn, void *target, 320 struct hif_msg_callbacks *callbacks) 321 { 322 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 323 324 qdf_mem_copy(&device->htc_callbacks, callbacks, 325 sizeof(device->htc_callbacks)); 326 } 327 328 /** 329 * hif_detach_htc() - remove HTC callbacks from HIF 330 * @scn: pointer to hif_opaque_softc structure 331 * 332 * Return: none 333 */ 334 void hif_detach_htc(struct hif_opaque_softc *scn) 335 { 336 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 337 338 usb_hif_flush_all(device); 339 qdf_mem_zero(&device->htc_callbacks, sizeof(device->htc_callbacks)); 340 } 341 342 /** 343 * hif_usb_device_deinit() - de- init HIF_DEVICE_USB, cleanup pipe resources 344 * @sc: pointer to hif_usb_softc structure 345 * 346 * Return: None 347 */ 348 void hif_usb_device_deinit(struct hif_usb_softc *sc) 349 { 350 struct HIF_DEVICE_USB *device = &sc->hif_hdl; 351 352 HIF_TRACE("+%s", __func__); 353 354 usb_hif_cleanup_pipe_resources(device); 355 356 if (device->diag_cmd_buffer) 357 qdf_mem_free(device->diag_cmd_buffer); 358 359 if (device->diag_resp_buffer) 360 qdf_mem_free(device->diag_resp_buffer); 361 362 HIF_TRACE("-%s", __func__); 363 } 364 365 /** 366 * hif_usb_device_init() - init HIF_DEVICE_USB, setup pipe resources 367 * @sc: pointer to hif_usb_softc structure 368 * 369 * Return: QDF_STATUS_SUCCESS on success or a QDF error 370 */ 371 QDF_STATUS hif_usb_device_init(struct hif_usb_softc *sc) 372 { 373 int i; 374 struct HIF_DEVICE_USB *device = &sc->hif_hdl; 375 struct usb_interface *interface = sc->interface; 376 struct usb_device *dev = interface_to_usbdev(interface); 377 QDF_STATUS status = QDF_STATUS_SUCCESS; 378 struct HIF_USB_PIPE *pipe; 379 380 HIF_TRACE("+%s", __func__); 381 382 do { 383 384 qdf_spinlock_create(&(device->cs_lock)); 385 qdf_spinlock_create(&(device->rx_lock)); 386 qdf_spinlock_create(&(device->tx_lock)); 387 qdf_spinlock_create(&device->rx_prestart_lock); 388 device->udev = dev; 389 device->interface = interface; 390 391 HIF_ERROR("%s device %pK device->udev %pK device->interface %pK", 392 __func__, 393 device, 394 device->udev, 395 device->interface); 396 397 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 398 pipe = &device->pipes[i]; 399 400 HIF_USB_INIT_WORK(pipe); 401 skb_queue_head_init(&pipe->io_comp_queue); 402 } 403 404 device->diag_cmd_buffer = 405 qdf_mem_malloc(USB_CTRL_MAX_DIAG_CMD_SIZE); 406 if (!device->diag_cmd_buffer) { 407 status = QDF_STATUS_E_NOMEM; 408 break; 409 } 410 device->diag_resp_buffer = 411 qdf_mem_malloc(USB_CTRL_MAX_DIAG_RESP_SIZE); 412 if (!device->diag_resp_buffer) { 413 status = QDF_STATUS_E_NOMEM; 414 break; 415 } 416 417 status = usb_hif_setup_pipe_resources(device); 418 419 } while (false); 420 421 if (hif_is_supported_rx_ctrl_pipe(HIF_GET_SOFTC(sc))) 422 device->rx_ctrl_pipe_supported = 1; 423 424 if (status != QDF_STATUS_SUCCESS) 425 HIF_ERROR("%s: abnormal condition", __func__); 426 427 HIF_TRACE("+%s", __func__); 428 return status; 429 } 430 431 /** 432 * hif_start() - Enable HIF TX and RX 433 * @scn: pointer to hif_opaque_softc structure 434 * 435 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 436 */ 437 QDF_STATUS hif_start(struct hif_opaque_softc *scn) 438 { 439 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 440 int i; 441 442 HIF_TRACE("+%s", __func__); 443 usb_hif_prestart_recv_pipes(device); 444 445 /* set the TX resource avail threshold for each TX pipe */ 446 for (i = HIF_TX_CTRL_PIPE; i <= HIF_TX_DATA_HP_PIPE; i++) { 447 device->pipes[i].urb_cnt_thresh = 448 device->pipes[i].urb_alloc / 2; 449 } 450 451 HIF_TRACE("-%s", __func__); 452 return QDF_STATUS_SUCCESS; 453 } 454 455 /** 456 * hif_usb_stop_device() - Stop/flush all HIF communication 457 * @scn: pointer to hif_opaque_softc structure 458 * 459 * Return: none 460 */ 461 void hif_usb_stop_device(struct hif_softc *hif_sc) 462 { 463 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_sc); 464 465 HIF_TRACE("+%s", __func__); 466 467 usb_hif_flush_all(device); 468 469 HIF_TRACE("-%s", __func__); 470 } 471 472 /** 473 * hif_get_default_pipe() - get default pipes for HIF TX/RX 474 * @scn: pointer to hif_opaque_softc structure 475 * @ul_pipe: pointer to TX pipe 476 * @ul_pipe: pointer to TX pipe 477 * 478 * Return: none 479 */ 480 void hif_get_default_pipe(struct hif_opaque_softc *scn, uint8_t *ul_pipe, 481 uint8_t *dl_pipe) 482 { 483 *ul_pipe = HIF_TX_CTRL_PIPE; 484 *dl_pipe = HIF_RX_CTRL_PIPE; 485 } 486 487 #if defined(USB_MULTI_IN_TEST) || defined(USB_ISOC_TEST) 488 /** 489 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 490 * @scn: HIF context 491 * @svc_id: sevice index 492 * @ul_pipe: pointer to uplink pipe id 493 * @dl_pipe: pointer to down-linklink pipe id 494 * @ul_is_polled: if ul is polling based 495 * @ul_is_polled: if dl is polling based 496 * 497 * Return: status 498 */ 499 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id, 500 uint8_t *ul_pipe, uint8_t *dl_pipe, 501 int *ul_is_polled, int *dl_is_polled) 502 { 503 QDF_STATUS status = QDF_STATUS_SUCCESS; 504 505 switch (svc_id) { 506 case HTC_CTRL_RSVD_SVC: 507 case WMI_CONTROL_SVC: 508 case HTC_RAW_STREAMS_SVC: 509 *ul_pipe = HIF_TX_CTRL_PIPE; 510 *dl_pipe = HIF_RX_DATA_PIPE; 511 break; 512 case WMI_DATA_BE_SVC: 513 *ul_pipe = HIF_TX_DATA_LP_PIPE; 514 *dl_pipe = HIF_RX_DATA_PIPE; 515 break; 516 case WMI_DATA_BK_SVC: 517 *ul_pipe = HIF_TX_DATA_MP_PIPE; 518 *dl_pipe = HIF_RX_DATA2_PIPE; 519 break; 520 case WMI_DATA_VI_SVC: 521 *ul_pipe = HIF_TX_DATA_HP_PIPE; 522 *dl_pipe = HIF_RX_DATA_PIPE; 523 break; 524 case WMI_DATA_VO_SVC: 525 *ul_pipe = HIF_TX_DATA_LP_PIPE; 526 *dl_pipe = HIF_RX_DATA_PIPE; 527 break; 528 default: 529 status = QDF_STATUS_E_FAILURE; 530 break; 531 } 532 533 return qdf_status_to_os_return(status); 534 } 535 #else 536 537 #ifdef QCA_TX_HTT2_SUPPORT 538 #define USB_TX_CHECK_HTT2_SUPPORT 1 539 #else 540 #define USB_TX_CHECK_HTT2_SUPPORT 0 541 #endif 542 543 /** 544 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 545 * @scn: HIF context 546 * @svc_id: sevice index 547 * @ul_pipe: pointer to uplink pipe id 548 * @dl_pipe: pointer to down-linklink pipe id 549 * @ul_is_polled: if ul is polling based 550 * @ul_is_polled: if dl is polling based 551 * 552 * Return: status 553 */ 554 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id, 555 uint8_t *ul_pipe, uint8_t *dl_pipe, 556 int *ul_is_polled, int *dl_is_polled) 557 { 558 QDF_STATUS status = QDF_STATUS_SUCCESS; 559 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 560 561 switch (svc_id) { 562 case HTC_CTRL_RSVD_SVC: 563 case WMI_CONTROL_SVC: 564 *ul_pipe = HIF_TX_CTRL_PIPE; 565 if (device->rx_ctrl_pipe_supported) 566 *dl_pipe = HIF_RX_CTRL_PIPE; 567 else 568 *dl_pipe = HIF_RX_DATA_PIPE; 569 break; 570 case WMI_DATA_BE_SVC: 571 case WMI_DATA_BK_SVC: 572 *ul_pipe = HIF_TX_DATA_LP_PIPE; 573 if (hif_usb_disable_rxdata2) 574 *dl_pipe = HIF_RX_DATA_PIPE; 575 else 576 *dl_pipe = HIF_RX_DATA2_PIPE; 577 break; 578 case WMI_DATA_VI_SVC: 579 *ul_pipe = HIF_TX_DATA_MP_PIPE; 580 if (hif_usb_disable_rxdata2) 581 *dl_pipe = HIF_RX_DATA_PIPE; 582 else 583 *dl_pipe = HIF_RX_DATA2_PIPE; 584 break; 585 case WMI_DATA_VO_SVC: 586 *ul_pipe = HIF_TX_DATA_HP_PIPE; 587 if (hif_usb_disable_rxdata2) 588 *dl_pipe = HIF_RX_DATA_PIPE; 589 else 590 *dl_pipe = HIF_RX_DATA2_PIPE; 591 break; 592 case HTC_RAW_STREAMS_SVC: 593 *ul_pipe = HIF_TX_CTRL_PIPE; 594 *dl_pipe = HIF_RX_DATA_PIPE; 595 break; 596 case HTT_DATA_MSG_SVC: 597 *ul_pipe = HIF_TX_DATA_LP_PIPE; 598 if (hif_usb_disable_rxdata2) 599 *dl_pipe = HIF_RX_DATA_PIPE; 600 else 601 *dl_pipe = HIF_RX_DATA2_PIPE; 602 break; 603 case HTT_DATA2_MSG_SVC: 604 if (USB_TX_CHECK_HTT2_SUPPORT) { 605 *ul_pipe = HIF_TX_DATA_HP_PIPE; 606 if (hif_usb_disable_rxdata2) 607 *dl_pipe = HIF_RX_DATA_PIPE; 608 else 609 *dl_pipe = HIF_RX_DATA2_PIPE; 610 } 611 break; 612 default: 613 status = QDF_STATUS_E_FAILURE; 614 break; 615 } 616 617 return qdf_status_to_os_return(status); 618 } 619 #endif 620 621 /** 622 * hif_ctrl_msg_exchange() - send usb ctrl message and receive response 623 * @macp: pointer to HIF_DEVICE_USB 624 * @send_req_val: USB send message request value 625 * @send_msg: pointer to data to send 626 * @len: length in bytes of the data to send 627 * @response_req_val: USB response message request value 628 * @response_msg: pointer to response msg 629 * @response_len: length of the response message 630 * 631 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 632 */ 633 static QDF_STATUS hif_ctrl_msg_exchange(struct HIF_DEVICE_USB *macp, 634 uint8_t send_req_val, 635 uint8_t *send_msg, 636 uint32_t len, 637 uint8_t response_req_val, 638 uint8_t *response_msg, 639 uint32_t *response_len) 640 { 641 QDF_STATUS status; 642 643 do { 644 645 /* send command */ 646 status = usb_hif_submit_ctrl_out(macp, send_req_val, 0, 0, 647 send_msg, len); 648 649 if (!QDF_IS_STATUS_SUCCESS(status)) 650 break; 651 652 if (!response_msg) { 653 /* no expected response */ 654 break; 655 } 656 657 /* get response */ 658 status = usb_hif_submit_ctrl_in(macp, response_req_val, 0, 0, 659 response_msg, *response_len); 660 661 if (!QDF_IS_STATUS_SUCCESS(status)) 662 break; 663 664 } while (false); 665 666 return status; 667 } 668 669 #ifdef WLAN_FEATURE_BMI 670 /** 671 * hif_exchange_bmi_msg() - send/recev ctrl message of type BMI_CMD/BMI_RESP 672 * @scn: pointer to hif_opaque_softc 673 * @bmi_request: pointer to data to send 674 * @request_length: length in bytes of the data to send 675 * @bmi_response: pointer to response msg 676 * @bmi_response_length: length of the response message 677 * @timeout_ms: timeout to wait for response (ignored in current implementation) 678 * 679 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 680 */ 681 682 QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *scn, 683 qdf_dma_addr_t cmd, qdf_dma_addr_t rsp, 684 uint8_t *bmi_request, 685 uint32_t request_length, 686 uint8_t *bmi_response, 687 uint32_t *bmi_response_lengthp, 688 uint32_t timeout_ms) 689 { 690 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 691 692 return hif_ctrl_msg_exchange(macp, 693 USB_CONTROL_REQ_SEND_BMI_CMD, 694 bmi_request, 695 request_length, 696 USB_CONTROL_REQ_RECV_BMI_RESP, 697 bmi_response, bmi_response_lengthp); 698 } 699 700 void hif_register_bmi_callbacks(struct hif_opaque_softc *hif_ctx) 701 { 702 } 703 #endif /* WLAN_FEATURE_BMI */ 704 705 /** 706 * hif_diag_read_access() - Read data from target memory or register 707 * @scn: pointer to hif_opaque_softc 708 * @address: register address to read from 709 * @data: pointer to buffer to store the value read from the register 710 * 711 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 712 */ 713 QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *scn, uint32_t address, 714 uint32_t *data) 715 { 716 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 717 QDF_STATUS status; 718 USB_CTRL_DIAG_CMD_READ *cmd; 719 uint32_t respLength; 720 721 cmd = (USB_CTRL_DIAG_CMD_READ *) macp->diag_cmd_buffer; 722 723 qdf_mem_zero(cmd, sizeof(*cmd)); 724 cmd->Cmd = USB_CTRL_DIAG_CC_READ; 725 cmd->Address = address; 726 respLength = sizeof(USB_CTRL_DIAG_RESP_READ); 727 728 status = hif_ctrl_msg_exchange(macp, 729 USB_CONTROL_REQ_DIAG_CMD, 730 (uint8_t *) cmd, 731 sizeof(*cmd), 732 USB_CONTROL_REQ_DIAG_RESP, 733 macp->diag_resp_buffer, &respLength); 734 735 if (QDF_IS_STATUS_SUCCESS(status)) { 736 USB_CTRL_DIAG_RESP_READ *pResp = 737 (USB_CTRL_DIAG_RESP_READ *) macp->diag_resp_buffer; 738 *data = pResp->ReadValue; 739 status = QDF_STATUS_SUCCESS; 740 } else { 741 status = QDF_STATUS_E_FAILURE; 742 } 743 744 return status; 745 } 746 747 /** 748 * hif_diag_write_access() - write data to target memory or register 749 * @scn: pointer to hif_opaque_softc 750 * @address: register address to write to 751 * @data: value to be written to the address 752 * 753 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 754 */ 755 QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *scn, 756 uint32_t address, 757 uint32_t data) 758 { 759 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 760 USB_CTRL_DIAG_CMD_WRITE *cmd; 761 762 cmd = (USB_CTRL_DIAG_CMD_WRITE *) macp->diag_cmd_buffer; 763 764 qdf_mem_zero(cmd, sizeof(*cmd)); 765 cmd->Cmd = USB_CTRL_DIAG_CC_WRITE; 766 cmd->Address = address; 767 cmd->Value = data; 768 769 return hif_ctrl_msg_exchange(macp, 770 USB_CONTROL_REQ_DIAG_CMD, 771 (uint8_t *) cmd, 772 sizeof(*cmd), 0, NULL, 0); 773 } 774 775 /** 776 * hif_dump_info() - dump info about all HIF pipes and endpoints 777 * @scn: pointer to hif_opaque_softc 778 * 779 * Return: none 780 */ 781 void hif_dump_info(struct hif_opaque_softc *scn) 782 { 783 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 784 struct HIF_USB_PIPE *pipe = NULL; 785 struct usb_host_interface *iface_desc = NULL; 786 struct usb_endpoint_descriptor *ep_desc; 787 uint8_t i = 0; 788 789 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 790 pipe = &device->pipes[i]; 791 HIF_ERROR("PipeIndex : %d URB Cnt : %d PipeHandle : %x", 792 i, pipe->urb_cnt, 793 pipe->usb_pipe_handle); 794 if (usb_pipeisoc(pipe->usb_pipe_handle)) 795 HIF_INFO("Pipe Type ISOC"); 796 else if (usb_pipebulk(pipe->usb_pipe_handle)) 797 HIF_INFO("Pipe Type BULK"); 798 else if (usb_pipeint(pipe->usb_pipe_handle)) 799 HIF_INFO("Pipe Type INT"); 800 else if (usb_pipecontrol(pipe->usb_pipe_handle)) 801 HIF_INFO("Pipe Type control"); 802 } 803 804 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { 805 ep_desc = &iface_desc->endpoint[i].desc; 806 if (ep_desc) { 807 HIF_INFO( 808 "ep_desc : %pK Index : %d: DescType : %d Addr : %d Maxp : %d Atrrib : %d", 809 ep_desc, i, ep_desc->bDescriptorType, 810 ep_desc->bEndpointAddress, 811 ep_desc->wMaxPacketSize, 812 ep_desc->bmAttributes); 813 if ((ep_desc) && (usb_endpoint_type(ep_desc) == 814 USB_ENDPOINT_XFER_ISOC)) { 815 HIF_INFO("ISOC EP Detected"); 816 } 817 } 818 } 819 820 } 821 822 /** 823 * hif_flush_surprise_remove() - Cleanup residual buffers for device shutdown 824 * @scn: HIF context 825 * 826 * Not applicable to USB bus 827 * 828 * Return: none 829 */ 830 void hif_flush_surprise_remove(struct hif_opaque_softc *scn) 831 { 832 /* TO DO... */ 833 } 834 835 /** 836 * hif_diag_read_mem() -read nbytes of data from target memory or register 837 * @scn: pointer to hif_opaque_softc 838 * @address: register address to read from 839 * @data: buffer to store the value read 840 * @nbytes: number of bytes to be read from 'address' 841 * 842 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 843 */ 844 QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *scn, 845 uint32_t address, uint8_t *data, 846 int nbytes) 847 { 848 QDF_STATUS status = QDF_STATUS_SUCCESS; 849 850 HIF_TRACE("+%s", __func__); 851 852 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 853 return QDF_STATUS_E_IO; 854 855 while ((nbytes >= 4) && 856 QDF_IS_STATUS_SUCCESS(status = 857 hif_diag_read_access(scn, 858 address, 859 (uint32_t *)data))) { 860 861 nbytes -= sizeof(uint32_t); 862 address += sizeof(uint32_t); 863 data += sizeof(uint32_t); 864 865 } 866 HIF_TRACE("-%s", __func__); 867 return status; 868 } 869 qdf_export_symbol(hif_diag_read_mem); 870 871 /** 872 * hif_diag_write_mem() -write nbytes of data to target memory or register 873 * @scn: pointer to hif_opaque_softc 874 * @address: register address to write to 875 * @data: buffer containing data to be written 876 * @nbytes: number of bytes to be written 877 * 878 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 879 */ 880 QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *scn, 881 uint32_t address, 882 uint8_t *data, int nbytes) 883 { 884 QDF_STATUS status = QDF_STATUS_SUCCESS; 885 886 HIF_TRACE("+%s", __func__); 887 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 888 return QDF_STATUS_E_IO; 889 890 while (nbytes >= 4 && 891 QDF_IS_STATUS_SUCCESS(status = 892 hif_diag_write_access(scn, 893 address, 894 *((uint32_t *)data)))) { 895 896 nbytes -= sizeof(uint32_t); 897 address += sizeof(uint32_t); 898 data += sizeof(uint32_t); 899 900 } 901 HIF_TRACE("-%s", __func__); 902 return status; 903 } 904 905 void hif_send_complete_check(struct hif_opaque_softc *scn, 906 uint8_t PipeID, int force) 907 { 908 /* NO-OP*/ 909 } 910 911 /* diagnostic command defnitions */ 912 #define USB_CTRL_DIAG_CC_READ 0 913 #define USB_CTRL_DIAG_CC_WRITE 1 914 #define USB_CTRL_DIAG_CC_WARM_RESET 2 915 916 void hif_suspend_wow(struct hif_opaque_softc *scn) 917 { 918 HIF_INFO("HIFsuspendwow - TODO"); 919 } 920 921 /** 922 * hif_usb_set_bundle_mode() - enable bundling and set default rx bundle cnt 923 * @scn: pointer to hif_opaque_softc structure 924 * @enabled: flag to enable/disable bundling 925 * @rx_bundle_cnt: bundle count to be used for RX 926 * 927 * Return: none 928 */ 929 void hif_usb_set_bundle_mode(struct hif_softc *scn, 930 bool enabled, int rx_bundle_cnt) 931 { 932 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 933 934 device->is_bundle_enabled = enabled; 935 device->rx_bundle_cnt = rx_bundle_cnt; 936 if (device->is_bundle_enabled && (device->rx_bundle_cnt == 0)) 937 device->rx_bundle_cnt = 1; 938 939 device->rx_bundle_buf_len = device->rx_bundle_cnt * 940 HIF_USB_RX_BUNDLE_ONE_PKT_SIZE; 941 942 HIF_DBG("athusb bundle %s cnt %d", enabled ? "enabled" : "disabled", 943 rx_bundle_cnt); 944 } 945 946 /** 947 * hif_is_supported_rx_ctrl_pipe() - return true if device supports exclusive 948 * control pipe in the RX direction. 949 * @scn: hif context 950 * 951 * Return: true if device supports RX control pipe. 952 */ 953 bool hif_is_supported_rx_ctrl_pipe(struct hif_softc *scn) 954 { 955 struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn); 956 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl); 957 958 switch (tgt_info->target_type) { 959 case TARGET_TYPE_QCN7605: 960 return true; 961 default: 962 return false; 963 } 964 } 965