1 /* 2 * Copyright (c) 2013-2018 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 == NULL) { 179 HIF_ERROR("%s: qdf_mem_malloc failed", __func__); 180 status = QDF_STATUS_E_NOMEM; 181 goto err; 182 } 183 send_context->new_alloc = true; 184 } 185 send_context->netbuf = buf; 186 send_context->hif_usb_device = hif_usb_device; 187 send_context->transfer_id = pipe_id; 188 send_context->head_data_len = head_data_len; 189 /* 190 * Copy data to head part of netbuf or head of allocated buffer. 191 * if buffer is new allocated, the last buffer should be copied also. 192 * It assume last fragment is internal buffer of netbuf 193 * sometime total length of fragments larger than nbytes 194 */ 195 data_ptr = (unsigned char *)send_context + 196 sizeof(struct hif_usb_send_context); 197 for (i = 0; 198 i < (send_context->new_alloc ? frag_count : frag_count - 1); i++) { 199 int frag_len = qdf_nbuf_get_frag_len(buf, i); 200 unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i); 201 202 qdf_mem_copy(data_ptr, frag_addr, frag_len); 203 data_ptr += frag_len; 204 } 205 /* Reset pData pointer and send out */ 206 data_ptr = (unsigned char *)send_context + 207 sizeof(struct hif_usb_send_context); 208 209 urb_context = usb_hif_alloc_urb_from_pipe(pipe); 210 if (NULL == urb_context) { 211 /* TODO : note, it is possible to run out of urbs if 2 212 * endpoints map to the same pipe ID 213 */ 214 HIF_ERROR("%s pipe:%d no urbs left. URB Cnt : %d", 215 __func__, pipe_id, pipe->urb_cnt); 216 status = QDF_STATUS_E_RESOURCES; 217 goto err; 218 } 219 urb_context->send_context = send_context; 220 urb = urb_context->urb; 221 urb_context->buf = buf; 222 data = data_ptr; 223 len = nbytes; 224 225 usb_fill_bulk_urb(urb, 226 device->udev, 227 pipe->usb_pipe_handle, 228 data, 229 (len % pipe->max_packet_size) == 230 0 ? (len + 1) : len, 231 usb_hif_usb_transmit_complete, urb_context); 232 233 if ((len % pipe->max_packet_size) == 0) 234 /* hit a max packet boundary on this pipe */ 235 236 HIF_DBG 237 ("athusb bulk send submit:%d, 0x%X (ep:0x%2.2X), %d bytes", 238 pipe->logical_pipe_num, pipe->usb_pipe_handle, 239 pipe->ep_address, nbytes); 240 241 usb_hif_enqueue_pending_transfer(pipe, urb_context); 242 usb_status = usb_submit_urb(urb, GFP_ATOMIC); 243 if (usb_status) { 244 if (send_context->new_alloc) 245 qdf_mem_free(send_context); 246 else 247 qdf_nbuf_pull_head(buf, head_data_len); 248 urb_context->buf = NULL; 249 HIF_ERROR("athusb : usb bulk transmit failed %d", 250 usb_status); 251 usb_hif_remove_pending_transfer(urb_context); 252 usb_hif_cleanup_transmit_urb(urb_context); 253 status = QDF_STATUS_E_FAILURE; 254 goto err; 255 } 256 257 err: 258 if (!QDF_IS_STATUS_SUCCESS(status) && 259 (status != QDF_STATUS_E_RESOURCES)) { 260 HIF_ERROR("athusb send failed %d", status); 261 } 262 263 HIF_DBG("-%s pipe : %d", __func__, pipe_id); 264 265 return status; 266 } 267 268 /** 269 * hif_send_head() - HIF routine exposed to upper layers to send data 270 * @scn: pointer to hif_opaque_softc structure 271 * @pipe_id: HIF pipe on which data is to be sent 272 * @transfer_id: endpoint ID on which data is to be sent 273 * @nbytes: number of bytes to be transmitted 274 * @wbuf: qdf_nbuf_t containing data to be transmitted 275 * @hdr_buf: any header buf to be prepended, currently ignored 276 * @data_attr: data_attr field from cvg_nbuf_cb of wbuf 277 * 278 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure 279 */ 280 QDF_STATUS hif_send_head(struct hif_opaque_softc *scn, uint8_t pipe_id, 281 uint32_t transfer_id, uint32_t nbytes, 282 qdf_nbuf_t wbuf, uint32_t data_attr) 283 { 284 QDF_STATUS status = QDF_STATUS_SUCCESS; 285 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 286 287 HIF_TRACE("+%s", __func__); 288 status = hif_send_internal(device, pipe_id, NULL, wbuf, nbytes); 289 HIF_TRACE("-%s", __func__); 290 return status; 291 } 292 293 /** 294 * hif_get_free_queue_number() - get # of free TX resources in a given HIF pipe 295 * @scn: pointer to hif_opaque_softc structure 296 * @pipe_id: HIF pipe which is being polled for free resources 297 * 298 * Return: # of free resources in pipe_id 299 */ 300 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *scn, 301 uint8_t pipe_id) 302 { 303 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 304 305 return device->pipes[pipe_id].urb_cnt; 306 } 307 308 /** 309 * hif_post_init() - copy HTC callbacks to HIF 310 * @scn: pointer to hif_opaque_softc structure 311 * @target: pointer to HTC_TARGET structure 312 * @callbacks: htc callbacks 313 * 314 * Return: none 315 */ 316 void hif_post_init(struct hif_opaque_softc *scn, void *target, 317 struct hif_msg_callbacks *callbacks) 318 { 319 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 320 321 qdf_mem_copy(&device->htc_callbacks, callbacks, 322 sizeof(device->htc_callbacks)); 323 } 324 325 /** 326 * hif_detach_htc() - remove HTC callbacks from HIF 327 * @scn: pointer to hif_opaque_softc structure 328 * 329 * Return: none 330 */ 331 void hif_detach_htc(struct hif_opaque_softc *scn) 332 { 333 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 334 335 usb_hif_flush_all(device); 336 qdf_mem_zero(&device->htc_callbacks, sizeof(device->htc_callbacks)); 337 } 338 339 /** 340 * hif_usb_device_deinit() - de- init HIF_DEVICE_USB, cleanup pipe resources 341 * @sc: pointer to hif_usb_softc structure 342 * 343 * Return: None 344 */ 345 void hif_usb_device_deinit(struct hif_usb_softc *sc) 346 { 347 struct HIF_DEVICE_USB *device = &sc->hif_hdl; 348 349 HIF_TRACE("+%s", __func__); 350 351 usb_hif_cleanup_pipe_resources(device); 352 353 usb_set_intfdata(device->interface, NULL); 354 355 if (device->diag_cmd_buffer != NULL) 356 qdf_mem_free(device->diag_cmd_buffer); 357 358 if (device->diag_resp_buffer != NULL) 359 qdf_mem_free(device->diag_resp_buffer); 360 361 HIF_TRACE("-%s", __func__); 362 } 363 364 /** 365 * hif_usb_device_init() - init HIF_DEVICE_USB, setup pipe resources 366 * @sc: pointer to hif_usb_softc structure 367 * 368 * Return: QDF_STATUS_SUCCESS on success or a QDF error 369 */ 370 QDF_STATUS hif_usb_device_init(struct hif_usb_softc *sc) 371 { 372 int i; 373 struct HIF_DEVICE_USB *device = &sc->hif_hdl; 374 struct usb_interface *interface = sc->interface; 375 struct usb_device *dev = interface_to_usbdev(interface); 376 QDF_STATUS status = QDF_STATUS_SUCCESS; 377 struct HIF_USB_PIPE *pipe; 378 379 HIF_TRACE("+%s", __func__); 380 381 do { 382 383 usb_set_intfdata(interface, device); 384 qdf_spinlock_create(&(device->cs_lock)); 385 qdf_spinlock_create(&(device->rx_lock)); 386 qdf_spinlock_create(&(device->tx_lock)); 387 device->udev = dev; 388 device->interface = interface; 389 390 HIF_ERROR("%s device %pK device->udev %pK device->interface %pK", 391 __func__, 392 device, 393 device->udev, 394 device->interface); 395 396 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 397 pipe = &device->pipes[i]; 398 399 HIF_USB_INIT_WORK(pipe); 400 skb_queue_head_init(&pipe->io_comp_queue); 401 } 402 403 device->diag_cmd_buffer = 404 qdf_mem_malloc(USB_CTRL_MAX_DIAG_CMD_SIZE); 405 if (NULL == device->diag_cmd_buffer) { 406 status = QDF_STATUS_E_NOMEM; 407 break; 408 } 409 device->diag_resp_buffer = 410 qdf_mem_malloc(USB_CTRL_MAX_DIAG_RESP_SIZE); 411 if (NULL == device->diag_resp_buffer) { 412 status = QDF_STATUS_E_NOMEM; 413 break; 414 } 415 416 status = usb_hif_setup_pipe_resources(device); 417 418 } while (false); 419 420 if (hif_is_supported_rx_ctrl_pipe(HIF_GET_SOFTC(sc))) 421 device->rx_ctrl_pipe_supported = 1; 422 423 if (status != QDF_STATUS_SUCCESS) 424 HIF_ERROR("%s: abnormal condition", __func__); 425 426 HIF_TRACE("+%s", __func__); 427 return status; 428 } 429 430 /** 431 * hif_start() - Enable HIF TX and RX 432 * @scn: pointer to hif_opaque_softc structure 433 * 434 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 435 */ 436 QDF_STATUS hif_start(struct hif_opaque_softc *scn) 437 { 438 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 439 int i; 440 441 HIF_TRACE("+%s", __func__); 442 usb_hif_prestart_recv_pipes(device); 443 444 /* set the TX resource avail threshold for each TX pipe */ 445 for (i = HIF_TX_CTRL_PIPE; i <= HIF_TX_DATA_HP_PIPE; i++) { 446 device->pipes[i].urb_cnt_thresh = 447 device->pipes[i].urb_alloc / 2; 448 } 449 450 HIF_TRACE("-%s", __func__); 451 return QDF_STATUS_SUCCESS; 452 } 453 454 /** 455 * hif_usb_stop_device() - Stop/flush all HIF communication 456 * @scn: pointer to hif_opaque_softc structure 457 * 458 * Return: none 459 */ 460 void hif_usb_stop_device(struct hif_softc *hif_sc) 461 { 462 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_sc); 463 464 HIF_TRACE("+%s", __func__); 465 466 usb_hif_flush_all(device); 467 468 HIF_TRACE("-%s", __func__); 469 } 470 471 /** 472 * hif_get_default_pipe() - get default pipes for HIF TX/RX 473 * @scn: pointer to hif_opaque_softc structure 474 * @ul_pipe: pointer to TX pipe 475 * @ul_pipe: pointer to TX pipe 476 * 477 * Return: none 478 */ 479 void hif_get_default_pipe(struct hif_opaque_softc *scn, uint8_t *ul_pipe, 480 uint8_t *dl_pipe) 481 { 482 *ul_pipe = HIF_TX_CTRL_PIPE; 483 *dl_pipe = HIF_RX_CTRL_PIPE; 484 } 485 486 #if defined(USB_MULTI_IN_TEST) || defined(USB_ISOC_TEST) 487 /** 488 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 489 * @scn: HIF context 490 * @svc_id: sevice index 491 * @ul_pipe: pointer to uplink pipe id 492 * @dl_pipe: pointer to down-linklink pipe id 493 * @ul_is_polled: if ul is polling based 494 * @ul_is_polled: if dl is polling based 495 * 496 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 497 */ 498 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id, 499 uint8_t *ul_pipe, uint8_t *dl_pipe, 500 int *ul_is_polled, int *dl_is_polled) 501 { 502 QDF_STATUS status = QDF_STATUS_SUCCESS; 503 504 switch (svc_id) { 505 case HTC_CTRL_RSVD_SVC: 506 case WMI_CONTROL_SVC: 507 case HTC_RAW_STREAMS_SVC: 508 *ul_pipe = HIF_TX_CTRL_PIPE; 509 *dl_pipe = HIF_RX_DATA_PIPE; 510 break; 511 case WMI_DATA_BE_SVC: 512 *ul_pipe = HIF_TX_DATA_LP_PIPE; 513 *dl_pipe = HIF_RX_DATA_PIPE; 514 break; 515 case WMI_DATA_BK_SVC: 516 *ul_pipe = HIF_TX_DATA_MP_PIPE; 517 *dl_pipe = HIF_RX_DATA2_PIPE; 518 break; 519 case WMI_DATA_VI_SVC: 520 *ul_pipe = HIF_TX_DATA_HP_PIPE; 521 *dl_pipe = HIF_RX_DATA_PIPE; 522 break; 523 case WMI_DATA_VO_SVC: 524 *ul_pipe = HIF_TX_DATA_LP_PIPE; 525 *dl_pipe = HIF_RX_DATA_PIPE; 526 break; 527 default: 528 status = QDF_STATUS_E_FAILURE; 529 break; 530 } 531 532 return status; 533 } 534 #else 535 536 #ifdef QCA_TX_HTT2_SUPPORT 537 #define USB_TX_CHECK_HTT2_SUPPORT 1 538 #else 539 #define USB_TX_CHECK_HTT2_SUPPORT 0 540 #endif 541 542 /** 543 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 544 * @scn: HIF context 545 * @svc_id: sevice index 546 * @ul_pipe: pointer to uplink pipe id 547 * @dl_pipe: pointer to down-linklink pipe id 548 * @ul_is_polled: if ul is polling based 549 * @ul_is_polled: if dl is polling based 550 * 551 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 552 */ 553 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id, 554 uint8_t *ul_pipe, uint8_t *dl_pipe, 555 int *ul_is_polled, int *dl_is_polled) 556 { 557 QDF_STATUS status = QDF_STATUS_SUCCESS; 558 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 559 560 switch (svc_id) { 561 case HTC_CTRL_RSVD_SVC: 562 case WMI_CONTROL_SVC: 563 *ul_pipe = HIF_TX_CTRL_PIPE; 564 if (device->rx_ctrl_pipe_supported) 565 *dl_pipe = HIF_RX_CTRL_PIPE; 566 else 567 *dl_pipe = HIF_RX_DATA_PIPE; 568 break; 569 case WMI_DATA_BE_SVC: 570 case WMI_DATA_BK_SVC: 571 *ul_pipe = HIF_TX_DATA_LP_PIPE; 572 if (hif_usb_disable_rxdata2) 573 *dl_pipe = HIF_RX_DATA_PIPE; 574 else 575 *dl_pipe = HIF_RX_DATA2_PIPE; 576 break; 577 case WMI_DATA_VI_SVC: 578 *ul_pipe = HIF_TX_DATA_MP_PIPE; 579 if (hif_usb_disable_rxdata2) 580 *dl_pipe = HIF_RX_DATA_PIPE; 581 else 582 *dl_pipe = HIF_RX_DATA2_PIPE; 583 break; 584 case WMI_DATA_VO_SVC: 585 *ul_pipe = HIF_TX_DATA_HP_PIPE; 586 if (hif_usb_disable_rxdata2) 587 *dl_pipe = HIF_RX_DATA_PIPE; 588 else 589 *dl_pipe = HIF_RX_DATA2_PIPE; 590 break; 591 case HTC_RAW_STREAMS_SVC: 592 *ul_pipe = HIF_TX_CTRL_PIPE; 593 *dl_pipe = HIF_RX_DATA_PIPE; 594 break; 595 case HTT_DATA_MSG_SVC: 596 *ul_pipe = HIF_TX_DATA_LP_PIPE; 597 if (hif_usb_disable_rxdata2) 598 *dl_pipe = HIF_RX_DATA_PIPE; 599 else 600 *dl_pipe = HIF_RX_DATA2_PIPE; 601 break; 602 case HTT_DATA2_MSG_SVC: 603 if (USB_TX_CHECK_HTT2_SUPPORT) { 604 *ul_pipe = HIF_TX_DATA_HP_PIPE; 605 if (hif_usb_disable_rxdata2) 606 *dl_pipe = HIF_RX_DATA_PIPE; 607 else 608 *dl_pipe = HIF_RX_DATA2_PIPE; 609 } 610 break; 611 default: 612 status = QDF_STATUS_E_FAILURE; 613 break; 614 } 615 616 return status; 617 } 618 #endif 619 620 /** 621 * hif_ctrl_msg_exchange() - send usb ctrl message and receive response 622 * @macp: pointer to HIF_DEVICE_USB 623 * @send_req_val: USB send message request value 624 * @send_msg: pointer to data to send 625 * @len: length in bytes of the data to send 626 * @response_req_val: USB response message request value 627 * @response_msg: pointer to response msg 628 * @response_len: length of the response message 629 * 630 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 631 */ 632 static QDF_STATUS hif_ctrl_msg_exchange(struct HIF_DEVICE_USB *macp, 633 uint8_t send_req_val, 634 uint8_t *send_msg, 635 uint32_t len, 636 uint8_t response_req_val, 637 uint8_t *response_msg, 638 uint32_t *response_len) 639 { 640 QDF_STATUS status; 641 642 do { 643 644 /* send command */ 645 status = usb_hif_submit_ctrl_out(macp, send_req_val, 0, 0, 646 send_msg, len); 647 648 if (!QDF_IS_STATUS_SUCCESS(status)) 649 break; 650 651 if (NULL == response_msg) { 652 /* no expected response */ 653 break; 654 } 655 656 /* get response */ 657 status = usb_hif_submit_ctrl_in(macp, response_req_val, 0, 0, 658 response_msg, *response_len); 659 660 if (!QDF_IS_STATUS_SUCCESS(status)) 661 break; 662 663 } while (false); 664 665 return status; 666 } 667 668 #ifdef WLAN_FEATURE_BMI 669 /** 670 * hif_exchange_bmi_msg() - send/recev ctrl message of type BMI_CMD/BMI_RESP 671 * @scn: pointer to hif_opaque_softc 672 * @bmi_request: pointer to data to send 673 * @request_length: length in bytes of the data to send 674 * @bmi_response: pointer to response msg 675 * @bmi_response_length: length of the response message 676 * @timeout_ms: timeout to wait for response (ignored in current implementation) 677 * 678 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 679 */ 680 681 QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *scn, 682 qdf_dma_addr_t cmd, qdf_dma_addr_t rsp, 683 uint8_t *bmi_request, 684 uint32_t request_length, 685 uint8_t *bmi_response, 686 uint32_t *bmi_response_lengthp, 687 uint32_t timeout_ms) 688 { 689 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 690 691 return hif_ctrl_msg_exchange(macp, 692 USB_CONTROL_REQ_SEND_BMI_CMD, 693 bmi_request, 694 request_length, 695 USB_CONTROL_REQ_RECV_BMI_RESP, 696 bmi_response, bmi_response_lengthp); 697 } 698 #endif /* WLAN_FEATURE_BMI */ 699 700 /** 701 * hif_diag_read_access() - Read data from target memory or register 702 * @scn: pointer to hif_opaque_softc 703 * @address: register address to read from 704 * @data: pointer to buffer to store the value read from the register 705 * 706 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 707 */ 708 QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *scn, uint32_t address, 709 uint32_t *data) 710 { 711 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 712 QDF_STATUS status; 713 USB_CTRL_DIAG_CMD_READ *cmd; 714 uint32_t respLength; 715 716 cmd = (USB_CTRL_DIAG_CMD_READ *) macp->diag_cmd_buffer; 717 718 qdf_mem_zero(cmd, sizeof(*cmd)); 719 cmd->Cmd = USB_CTRL_DIAG_CC_READ; 720 cmd->Address = address; 721 respLength = sizeof(USB_CTRL_DIAG_RESP_READ); 722 723 status = hif_ctrl_msg_exchange(macp, 724 USB_CONTROL_REQ_DIAG_CMD, 725 (uint8_t *) cmd, 726 sizeof(*cmd), 727 USB_CONTROL_REQ_DIAG_RESP, 728 macp->diag_resp_buffer, &respLength); 729 730 if (QDF_IS_STATUS_SUCCESS(status)) { 731 USB_CTRL_DIAG_RESP_READ *pResp = 732 (USB_CTRL_DIAG_RESP_READ *) macp->diag_resp_buffer; 733 *data = pResp->ReadValue; 734 status = QDF_STATUS_SUCCESS; 735 } else { 736 status = QDF_STATUS_E_FAILURE; 737 } 738 739 return status; 740 } 741 742 /** 743 * hif_diag_write_access() - write data to target memory or register 744 * @scn: pointer to hif_opaque_softc 745 * @address: register address to write to 746 * @data: value to be written to the address 747 * 748 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 749 */ 750 QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *scn, 751 uint32_t address, 752 uint32_t data) 753 { 754 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 755 USB_CTRL_DIAG_CMD_WRITE *cmd; 756 757 cmd = (USB_CTRL_DIAG_CMD_WRITE *) macp->diag_cmd_buffer; 758 759 qdf_mem_zero(cmd, sizeof(*cmd)); 760 cmd->Cmd = USB_CTRL_DIAG_CC_WRITE; 761 cmd->Address = address; 762 cmd->Value = data; 763 764 return hif_ctrl_msg_exchange(macp, 765 USB_CONTROL_REQ_DIAG_CMD, 766 (uint8_t *) cmd, 767 sizeof(*cmd), 0, NULL, 0); 768 } 769 770 /** 771 * hif_dump_info() - dump info about all HIF pipes and endpoints 772 * @scn: pointer to hif_opaque_softc 773 * 774 * Return: none 775 */ 776 void hif_dump_info(struct hif_opaque_softc *scn) 777 { 778 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 779 struct HIF_USB_PIPE *pipe = NULL; 780 struct usb_host_interface *iface_desc = NULL; 781 struct usb_endpoint_descriptor *ep_desc; 782 uint8_t i = 0; 783 784 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 785 pipe = &device->pipes[i]; 786 HIF_ERROR("PipeIndex : %d URB Cnt : %d PipeHandle : %x", 787 i, pipe->urb_cnt, 788 pipe->usb_pipe_handle); 789 if (usb_pipeisoc(pipe->usb_pipe_handle)) 790 HIF_INFO("Pipe Type ISOC"); 791 else if (usb_pipebulk(pipe->usb_pipe_handle)) 792 HIF_INFO("Pipe Type BULK"); 793 else if (usb_pipeint(pipe->usb_pipe_handle)) 794 HIF_INFO("Pipe Type INT"); 795 else if (usb_pipecontrol(pipe->usb_pipe_handle)) 796 HIF_INFO("Pipe Type control"); 797 } 798 799 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { 800 ep_desc = &iface_desc->endpoint[i].desc; 801 if (ep_desc) { 802 HIF_INFO( 803 "ep_desc : %pK Index : %d: DescType : %d Addr : %d Maxp : %d Atrrib : %d", 804 ep_desc, i, ep_desc->bDescriptorType, 805 ep_desc->bEndpointAddress, 806 ep_desc->wMaxPacketSize, 807 ep_desc->bmAttributes); 808 if ((ep_desc) && (usb_endpoint_type(ep_desc) == 809 USB_ENDPOINT_XFER_ISOC)) { 810 HIF_INFO("ISOC EP Detected"); 811 } 812 } 813 } 814 815 } 816 817 /** 818 * hif_flush_surprise_remove() - Cleanup residual buffers for device shutdown 819 * @scn: HIF context 820 * 821 * Not applicable to USB bus 822 * 823 * Return: none 824 */ 825 void hif_flush_surprise_remove(struct hif_opaque_softc *scn) 826 { 827 /* TO DO... */ 828 } 829 830 /** 831 * hif_diag_read_mem() -read nbytes of data from target memory or register 832 * @scn: pointer to hif_opaque_softc 833 * @address: register address to read from 834 * @data: buffer to store the value read 835 * @nbytes: number of bytes to be read from 'address' 836 * 837 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 838 */ 839 QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *scn, 840 uint32_t address, uint8_t *data, 841 int nbytes) 842 { 843 QDF_STATUS status = QDF_STATUS_SUCCESS; 844 845 HIF_TRACE("+%s", __func__); 846 847 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 848 return QDF_STATUS_E_IO; 849 850 while ((nbytes >= 4) && 851 QDF_IS_STATUS_SUCCESS(status = 852 hif_diag_read_access(scn, 853 address, 854 (uint32_t *)data))) { 855 856 nbytes -= sizeof(uint32_t); 857 address += sizeof(uint32_t); 858 data += sizeof(uint32_t); 859 860 } 861 HIF_TRACE("-%s", __func__); 862 return status; 863 } 864 qdf_export_symbol(hif_diag_read_mem); 865 866 /** 867 * hif_diag_write_mem() -write nbytes of data to target memory or register 868 * @scn: pointer to hif_opaque_softc 869 * @address: register address to write to 870 * @data: buffer containing data to be written 871 * @nbytes: number of bytes to be written 872 * 873 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 874 */ 875 QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *scn, 876 uint32_t address, 877 uint8_t *data, int nbytes) 878 { 879 QDF_STATUS status = QDF_STATUS_SUCCESS; 880 881 HIF_TRACE("+%s", __func__); 882 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 883 return QDF_STATUS_E_IO; 884 885 while (nbytes >= 4 && 886 QDF_IS_STATUS_SUCCESS(status = 887 hif_diag_write_access(scn, 888 address, 889 *((uint32_t *)data)))) { 890 891 nbytes -= sizeof(uint32_t); 892 address += sizeof(uint32_t); 893 data += sizeof(uint32_t); 894 895 } 896 HIF_TRACE("-%s", __func__); 897 return status; 898 } 899 900 void hif_send_complete_check(struct hif_opaque_softc *scn, 901 uint8_t PipeID, int force) 902 { 903 /* NO-OP*/ 904 } 905 906 /* diagnostic command defnitions */ 907 #define USB_CTRL_DIAG_CC_READ 0 908 #define USB_CTRL_DIAG_CC_WRITE 1 909 #define USB_CTRL_DIAG_CC_WARM_RESET 2 910 911 void hif_suspend_wow(struct hif_opaque_softc *scn) 912 { 913 HIF_INFO("HIFsuspendwow - TODO"); 914 } 915 916 /** 917 * hif_usb_set_bundle_mode() - enable bundling and set default rx bundle cnt 918 * @scn: pointer to hif_opaque_softc structure 919 * @enabled: flag to enable/disable bundling 920 * @rx_bundle_cnt: bundle count to be used for RX 921 * 922 * Return: none 923 */ 924 void hif_usb_set_bundle_mode(struct hif_softc *scn, 925 bool enabled, int rx_bundle_cnt) 926 { 927 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 928 929 device->is_bundle_enabled = enabled; 930 device->rx_bundle_cnt = rx_bundle_cnt; 931 if (device->is_bundle_enabled && (device->rx_bundle_cnt == 0)) 932 device->rx_bundle_cnt = 1; 933 934 device->rx_bundle_buf_len = device->rx_bundle_cnt * 935 HIF_USB_RX_BUNDLE_ONE_PKT_SIZE; 936 937 HIF_DBG("athusb bundle %s cnt %d", enabled ? "enabled" : "disabled", 938 rx_bundle_cnt); 939 } 940 941 /** 942 * hif_is_supported_rx_ctrl_pipe() - return true if device supports exclusive 943 * control pipe in the RX direction. 944 * @scn: hif context 945 * 946 * Return: true if device supports RX control pipe. 947 */ 948 bool hif_is_supported_rx_ctrl_pipe(struct hif_softc *scn) 949 { 950 struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn); 951 struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl); 952 953 switch (tgt_info->target_type) { 954 case TARGET_TYPE_QCN7605: 955 return true; 956 default: 957 return false; 958 } 959 } 960