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 37 #if defined(WLAN_DEBUG) || defined(DEBUG) 38 static ATH_DEBUG_MASK_DESCRIPTION g_hif_debug_description[] = { 39 {USB_HIF_DEBUG_CTRL_TRANS, "Control Transfers"}, 40 {USB_HIF_DEBUG_BULK_IN, "BULK In Transfers"}, 41 {USB_HIF_DEBUG_BULK_OUT, "BULK Out Transfers"}, 42 {USB_HIF_DEBUG_DUMP_DATA, "Dump data"}, 43 {USB_HIF_DEBUG_ENUM, "Enumeration"}, 44 }; 45 46 ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, 47 "hif", 48 "USB Host Interface", 49 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO | 50 USB_HIF_DEBUG_ENUM, 51 ATH_DEBUG_DESCRIPTION_COUNT 52 (g_hif_debug_description), 53 g_hif_debug_description); 54 55 #endif 56 57 #ifdef USB_ISOC_SUPPORT 58 unsigned int hif_usb_isoch_vo = 1; 59 #else 60 unsigned int hif_usb_isoch_vo; 61 #endif 62 unsigned int hif_usb_disable_rxdata2 = 1; 63 64 /** 65 * usb_hif_usb_transmit_complete() - completion routing for tx urb's 66 * @urb: pointer to urb for which tx completion is called 67 * 68 * Return: none 69 */ 70 static void usb_hif_usb_transmit_complete(struct urb *urb) 71 { 72 struct HIF_URB_CONTEXT *urb_context = 73 (struct HIF_URB_CONTEXT *)urb->context; 74 qdf_nbuf_t buf; 75 struct HIF_USB_PIPE *pipe = urb_context->pipe; 76 struct hif_usb_send_context *send_context; 77 78 HIF_DBG("+%s: pipe: %d, stat:%d, len:%d", __func__, 79 pipe->logical_pipe_num, urb->status, urb->actual_length); 80 81 /* this urb is not pending anymore */ 82 usb_hif_remove_pending_transfer(urb_context); 83 84 if (urb->status != 0) { 85 HIF_ERROR("%s: pipe: %d, failed:%d", 86 __func__, pipe->logical_pipe_num, urb->status); 87 } 88 89 buf = urb_context->buf; 90 send_context = urb_context->send_context; 91 92 if (send_context->new_alloc) 93 qdf_mem_free(send_context); 94 else 95 qdf_nbuf_pull_head(buf, send_context->head_data_len); 96 97 urb_context->buf = NULL; 98 usb_hif_cleanup_transmit_urb(urb_context); 99 100 /* note: queue implements a lock */ 101 skb_queue_tail(&pipe->io_comp_queue, buf); 102 HIF_USB_SCHEDULE_WORK(pipe); 103 104 HIF_DBG("-%s", __func__); 105 } 106 107 /** 108 * hif_send_internal() - HIF internal routine to prepare and submit tx urbs 109 * @hif_usb_device: pointer to HIF_DEVICE_USB structure 110 * @pipe_id: HIF pipe on which data is to be sent 111 * @hdr_buf: any header buf to be prepended, currently ignored 112 * @buf: qdf_nbuf_t containing data to be transmitted 113 * @nbytes: number of bytes to be transmitted 114 * 115 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure 116 */ 117 static QDF_STATUS hif_send_internal(struct HIF_DEVICE_USB *hif_usb_device, 118 uint8_t pipe_id, 119 qdf_nbuf_t hdr_buf, 120 qdf_nbuf_t buf, unsigned int nbytes) 121 { 122 QDF_STATUS status = QDF_STATUS_SUCCESS; 123 struct HIF_DEVICE_USB *device = hif_usb_device; 124 struct HIF_USB_PIPE *pipe = &device->pipes[pipe_id]; 125 struct HIF_URB_CONTEXT *urb_context; 126 uint8_t *data; 127 uint32_t len; 128 struct urb *urb; 129 int usb_status; 130 int i; 131 struct hif_usb_send_context *send_context; 132 uint8_t frag_count; 133 uint32_t head_data_len, tmp_frag_count = 0; 134 unsigned char *data_ptr; 135 136 HIF_DBG("+%s pipe : %d, buf:0x%pK nbytes %u", 137 __func__, pipe_id, buf, nbytes); 138 139 frag_count = qdf_nbuf_get_num_frags(buf); 140 if (frag_count == 1) { 141 /* 142 * | hif_usb_send_context | netbuf->data 143 */ 144 head_data_len = sizeof(struct hif_usb_send_context); 145 } else if ((frag_count - 1) <= QDF_NBUF_CB_TX_MAX_EXTRA_FRAGS) { 146 /* 147 * means have extra fragment buf in skb 148 * header data length should be total sending length subtract 149 * internal data length of netbuf 150 * | hif_usb_send_context | fragments except internal buffer | 151 * netbuf->data 152 */ 153 head_data_len = sizeof(struct hif_usb_send_context); 154 while (tmp_frag_count < (frag_count - 1)) { 155 head_data_len = 156 head_data_len + qdf_nbuf_get_frag_len(buf, 157 tmp_frag_count); 158 tmp_frag_count = tmp_frag_count + 1; 159 } 160 } else { 161 /* Extra fragments overflow */ 162 HIF_ERROR("%s Extra fragments count overflow : %d\n", 163 __func__, frag_count); 164 status = QDF_STATUS_E_RESOURCES; 165 goto err; 166 } 167 168 /* Check whether head room is enough to save extra head data */ 169 if (head_data_len <= qdf_nbuf_headroom(buf)) { 170 send_context = (struct hif_usb_send_context *) 171 qdf_nbuf_push_head(buf, head_data_len); 172 send_context->new_alloc = false; 173 } else { 174 send_context = 175 qdf_mem_malloc(sizeof(struct hif_usb_send_context) 176 + head_data_len + nbytes); 177 if (send_context == NULL) { 178 HIF_ERROR("%s: qdf_mem_malloc failed", __func__); 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 (NULL == 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 HIF_TRACE("+%s", __func__); 287 status = hif_send_internal(device, pipe_id, NULL, wbuf, nbytes); 288 HIF_TRACE("-%s", __func__); 289 return status; 290 } 291 292 /** 293 * hif_get_free_queue_number() - get # of free TX resources in a given HIF pipe 294 * @scn: pointer to hif_opaque_softc structure 295 * @pipe_id: HIF pipe which is being polled for free resources 296 * 297 * Return: # of free resources in pipe_id 298 */ 299 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *scn, 300 uint8_t pipe_id) 301 { 302 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 303 304 return device->pipes[pipe_id].urb_cnt; 305 } 306 307 /** 308 * hif_post_init() - copy HTC callbacks to HIF 309 * @scn: pointer to hif_opaque_softc structure 310 * @target: pointer to HTC_TARGET structure 311 * @callbacks: htc callbacks 312 * 313 * Return: none 314 */ 315 void hif_post_init(struct hif_opaque_softc *scn, void *target, 316 struct hif_msg_callbacks *callbacks) 317 { 318 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 319 320 qdf_mem_copy(&device->htc_callbacks, callbacks, 321 sizeof(device->htc_callbacks)); 322 } 323 324 /** 325 * hif_detach_htc() - remove HTC callbacks from HIF 326 * @scn: pointer to hif_opaque_softc structure 327 * 328 * Return: none 329 */ 330 void hif_detach_htc(struct hif_opaque_softc *scn) 331 { 332 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 333 334 usb_hif_flush_all(device); 335 qdf_mem_zero(&device->htc_callbacks, sizeof(device->htc_callbacks)); 336 } 337 338 /** 339 * hif_usb_device_deinit() - de- init HIF_DEVICE_USB, cleanup pipe resources 340 * @sc: pointer to hif_usb_softc structure 341 * 342 * Return: None 343 */ 344 void hif_usb_device_deinit(struct hif_usb_softc *sc) 345 { 346 struct HIF_DEVICE_USB *device = &sc->hif_hdl; 347 348 HIF_TRACE("+%s", __func__); 349 350 usb_hif_cleanup_pipe_resources(device); 351 352 usb_set_intfdata(device->interface, NULL); 353 354 if (device->diag_cmd_buffer != NULL) 355 qdf_mem_free(device->diag_cmd_buffer); 356 357 if (device->diag_resp_buffer != NULL) 358 qdf_mem_free(device->diag_resp_buffer); 359 360 HIF_TRACE("-%s", __func__); 361 } 362 363 /** 364 * hif_usb_device_init() - init HIF_DEVICE_USB, setup pipe resources 365 * @sc: pointer to hif_usb_softc structure 366 * 367 * Return: QDF_STATUS_SUCCESS on success or a QDF error 368 */ 369 QDF_STATUS hif_usb_device_init(struct hif_usb_softc *sc) 370 { 371 int i; 372 struct HIF_DEVICE_USB *device = &sc->hif_hdl; 373 struct usb_interface *interface = sc->interface; 374 struct usb_device *dev = interface_to_usbdev(interface); 375 QDF_STATUS status = QDF_STATUS_SUCCESS; 376 struct HIF_USB_PIPE *pipe; 377 378 HIF_TRACE("+%s", __func__); 379 380 do { 381 382 usb_set_intfdata(interface, device); 383 qdf_spinlock_create(&(device->cs_lock)); 384 qdf_spinlock_create(&(device->rx_lock)); 385 qdf_spinlock_create(&(device->tx_lock)); 386 device->udev = dev; 387 device->interface = interface; 388 389 HIF_ERROR("%s device %pK device->udev %pK device->interface %pK", 390 __func__, 391 device, 392 device->udev, 393 device->interface); 394 395 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 396 pipe = &device->pipes[i]; 397 398 HIF_USB_INIT_WORK(pipe); 399 skb_queue_head_init(&pipe->io_comp_queue); 400 } 401 402 device->diag_cmd_buffer = 403 qdf_mem_malloc(USB_CTRL_MAX_DIAG_CMD_SIZE); 404 if (NULL == device->diag_cmd_buffer) { 405 status = QDF_STATUS_E_NOMEM; 406 break; 407 } 408 device->diag_resp_buffer = 409 qdf_mem_malloc(USB_CTRL_MAX_DIAG_RESP_SIZE); 410 if (NULL == device->diag_resp_buffer) { 411 status = QDF_STATUS_E_NOMEM; 412 break; 413 } 414 415 status = usb_hif_setup_pipe_resources(device); 416 417 } while (false); 418 419 if (status != QDF_STATUS_SUCCESS) 420 HIF_ERROR("%s: abnormal condition", __func__); 421 422 HIF_TRACE("+%s", __func__); 423 return status; 424 } 425 426 /** 427 * hif_start() - Enable HIF TX and RX 428 * @scn: pointer to hif_opaque_softc structure 429 * 430 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 431 */ 432 QDF_STATUS hif_start(struct hif_opaque_softc *scn) 433 { 434 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 435 int i; 436 437 HIF_TRACE("+%s", __func__); 438 usb_hif_prestart_recv_pipes(device); 439 440 /* set the TX resource avail threshold for each TX pipe */ 441 for (i = HIF_TX_CTRL_PIPE; i <= HIF_TX_DATA_HP_PIPE; i++) { 442 device->pipes[i].urb_cnt_thresh = 443 device->pipes[i].urb_alloc / 2; 444 } 445 446 HIF_TRACE("-%s", __func__); 447 return QDF_STATUS_SUCCESS; 448 } 449 450 /** 451 * hif_usb_stop_device() - Stop/flush all HIF communication 452 * @scn: pointer to hif_opaque_softc structure 453 * 454 * Return: none 455 */ 456 void hif_usb_stop_device(struct hif_softc *hif_sc) 457 { 458 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_sc); 459 460 HIF_TRACE("+%s", __func__); 461 462 usb_hif_flush_all(device); 463 464 HIF_TRACE("-%s", __func__); 465 } 466 467 /** 468 * hif_get_default_pipe() - get default pipes for HIF TX/RX 469 * @scn: pointer to hif_opaque_softc structure 470 * @ul_pipe: pointer to TX pipe 471 * @ul_pipe: pointer to TX pipe 472 * 473 * Return: none 474 */ 475 void hif_get_default_pipe(struct hif_opaque_softc *scn, uint8_t *ul_pipe, 476 uint8_t *dl_pipe) 477 { 478 *ul_pipe = HIF_TX_CTRL_PIPE; 479 *dl_pipe = HIF_RX_CTRL_PIPE; 480 } 481 482 #if defined(USB_MULTI_IN_TEST) || defined(USB_ISOC_TEST) 483 /** 484 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 485 * @scn: HIF context 486 * @svc_id: sevice index 487 * @ul_pipe: pointer to uplink pipe id 488 * @dl_pipe: pointer to down-linklink pipe id 489 * @ul_is_polled: if ul is polling based 490 * @ul_is_polled: if dl is polling based 491 * 492 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 493 */ 494 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id, 495 uint8_t *ul_pipe, uint8_t *dl_pipe, 496 int *ul_is_polled, int *dl_is_polled) 497 { 498 QDF_STATUS status = QDF_STATUS_SUCCESS; 499 500 switch (svc_id) { 501 case HTC_CTRL_RSVD_SVC: 502 case WMI_CONTROL_SVC: 503 case HTC_RAW_STREAMS_SVC: 504 *ul_pipe = HIF_TX_CTRL_PIPE; 505 *dl_pipe = HIF_RX_DATA_PIPE; 506 break; 507 case WMI_DATA_BE_SVC: 508 *ul_pipe = HIF_TX_DATA_LP_PIPE; 509 *dl_pipe = HIF_RX_DATA_PIPE; 510 break; 511 case WMI_DATA_BK_SVC: 512 *ul_pipe = HIF_TX_DATA_MP_PIPE; 513 *dl_pipe = HIF_RX_DATA2_PIPE; 514 break; 515 case WMI_DATA_VI_SVC: 516 *ul_pipe = HIF_TX_DATA_HP_PIPE; 517 *dl_pipe = HIF_RX_DATA_PIPE; 518 break; 519 case WMI_DATA_VO_SVC: 520 *ul_pipe = HIF_TX_DATA_LP_PIPE; 521 *dl_pipe = HIF_RX_DATA_PIPE; 522 break; 523 default: 524 status = QDF_STATUS_E_FAILURE; 525 break; 526 } 527 528 return status; 529 } 530 #else 531 532 #ifdef QCA_TX_HTT2_SUPPORT 533 #define USB_TX_CHECK_HTT2_SUPPORT 1 534 #else 535 #define USB_TX_CHECK_HTT2_SUPPORT 0 536 #endif 537 538 /** 539 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 540 * @scn: HIF context 541 * @svc_id: sevice index 542 * @ul_pipe: pointer to uplink pipe id 543 * @dl_pipe: pointer to down-linklink pipe id 544 * @ul_is_polled: if ul is polling based 545 * @ul_is_polled: if dl is polling based 546 * 547 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 548 */ 549 int hif_map_service_to_pipe(struct hif_opaque_softc *scn, uint16_t svc_id, 550 uint8_t *ul_pipe, uint8_t *dl_pipe, 551 int *ul_is_polled, int *dl_is_polled) 552 { 553 QDF_STATUS status = QDF_STATUS_SUCCESS; 554 555 switch (svc_id) { 556 case HTC_CTRL_RSVD_SVC: 557 case WMI_CONTROL_SVC: 558 *ul_pipe = HIF_TX_CTRL_PIPE; 559 *dl_pipe = HIF_RX_DATA_PIPE; 560 break; 561 case WMI_DATA_BE_SVC: 562 case WMI_DATA_BK_SVC: 563 *ul_pipe = HIF_TX_DATA_LP_PIPE; 564 if (hif_usb_disable_rxdata2) 565 *dl_pipe = HIF_RX_DATA_PIPE; 566 else 567 *dl_pipe = HIF_RX_DATA2_PIPE; 568 break; 569 case WMI_DATA_VI_SVC: 570 *ul_pipe = HIF_TX_DATA_MP_PIPE; 571 if (hif_usb_disable_rxdata2) 572 *dl_pipe = HIF_RX_DATA_PIPE; 573 else 574 *dl_pipe = HIF_RX_DATA2_PIPE; 575 break; 576 case WMI_DATA_VO_SVC: 577 *ul_pipe = HIF_TX_DATA_HP_PIPE; 578 if (hif_usb_disable_rxdata2) 579 *dl_pipe = HIF_RX_DATA_PIPE; 580 else 581 *dl_pipe = HIF_RX_DATA2_PIPE; 582 break; 583 case HTC_RAW_STREAMS_SVC: 584 *ul_pipe = HIF_TX_CTRL_PIPE; 585 *dl_pipe = HIF_RX_DATA_PIPE; 586 break; 587 case HTT_DATA_MSG_SVC: 588 *ul_pipe = HIF_TX_DATA_LP_PIPE; 589 if (hif_usb_disable_rxdata2) 590 *dl_pipe = HIF_RX_DATA_PIPE; 591 else 592 *dl_pipe = HIF_RX_DATA2_PIPE; 593 break; 594 case HTT_DATA2_MSG_SVC: 595 if (USB_TX_CHECK_HTT2_SUPPORT) { 596 *ul_pipe = HIF_TX_DATA_HP_PIPE; 597 if (hif_usb_disable_rxdata2) 598 *dl_pipe = HIF_RX_DATA_PIPE; 599 else 600 *dl_pipe = HIF_RX_DATA2_PIPE; 601 } 602 break; 603 default: 604 status = QDF_STATUS_E_FAILURE; 605 break; 606 } 607 608 return status; 609 } 610 #endif 611 612 /** 613 * hif_ctrl_msg_exchange() - send usb ctrl message and receive response 614 * @macp: pointer to HIF_DEVICE_USB 615 * @send_req_val: USB send message request value 616 * @send_msg: pointer to data to send 617 * @len: length in bytes of the data to send 618 * @response_req_val: USB response message request value 619 * @response_msg: pointer to response msg 620 * @response_len: length of the response message 621 * 622 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 623 */ 624 static QDF_STATUS hif_ctrl_msg_exchange(struct HIF_DEVICE_USB *macp, 625 uint8_t send_req_val, 626 uint8_t *send_msg, 627 uint32_t len, 628 uint8_t response_req_val, 629 uint8_t *response_msg, 630 uint32_t *response_len) 631 { 632 QDF_STATUS status; 633 634 do { 635 636 /* send command */ 637 status = usb_hif_submit_ctrl_out(macp, send_req_val, 0, 0, 638 send_msg, len); 639 640 if (!QDF_IS_STATUS_SUCCESS(status)) 641 break; 642 643 if (NULL == response_msg) { 644 /* no expected response */ 645 break; 646 } 647 648 /* get response */ 649 status = usb_hif_submit_ctrl_in(macp, response_req_val, 0, 0, 650 response_msg, *response_len); 651 652 if (!QDF_IS_STATUS_SUCCESS(status)) 653 break; 654 655 } while (false); 656 657 return status; 658 } 659 660 /** 661 * hif_exchange_bmi_msg() - send/recev ctrl message of type BMI_CMD/BMI_RESP 662 * @scn: pointer to hif_opaque_softc 663 * @bmi_request: pointer to data to send 664 * @request_length: length in bytes of the data to send 665 * @bmi_response: pointer to response msg 666 * @bmi_response_length: length of the response message 667 * @timeout_ms: timeout to wait for response (ignored in current implementation) 668 * 669 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 670 */ 671 672 QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *scn, 673 qdf_dma_addr_t cmd, qdf_dma_addr_t rsp, 674 uint8_t *bmi_request, 675 uint32_t request_length, 676 uint8_t *bmi_response, 677 uint32_t *bmi_response_lengthp, 678 uint32_t timeout_ms) 679 { 680 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 681 682 return hif_ctrl_msg_exchange(macp, 683 USB_CONTROL_REQ_SEND_BMI_CMD, 684 bmi_request, 685 request_length, 686 USB_CONTROL_REQ_RECV_BMI_RESP, 687 bmi_response, bmi_response_lengthp); 688 } 689 690 /** 691 * hif_diag_read_access() - Read data from target memory or register 692 * @scn: pointer to hif_opaque_softc 693 * @address: register address to read from 694 * @data: pointer to buffer to store the value read from the register 695 * 696 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 697 */ 698 QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *scn, uint32_t address, 699 uint32_t *data) 700 { 701 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 702 QDF_STATUS status; 703 USB_CTRL_DIAG_CMD_READ *cmd; 704 uint32_t respLength; 705 706 cmd = (USB_CTRL_DIAG_CMD_READ *) macp->diag_cmd_buffer; 707 708 qdf_mem_zero(cmd, sizeof(*cmd)); 709 cmd->Cmd = USB_CTRL_DIAG_CC_READ; 710 cmd->Address = address; 711 respLength = sizeof(USB_CTRL_DIAG_RESP_READ); 712 713 status = hif_ctrl_msg_exchange(macp, 714 USB_CONTROL_REQ_DIAG_CMD, 715 (uint8_t *) cmd, 716 sizeof(*cmd), 717 USB_CONTROL_REQ_DIAG_RESP, 718 macp->diag_resp_buffer, &respLength); 719 720 if (QDF_IS_STATUS_SUCCESS(status)) { 721 USB_CTRL_DIAG_RESP_READ *pResp = 722 (USB_CTRL_DIAG_RESP_READ *) macp->diag_resp_buffer; 723 *data = pResp->ReadValue; 724 status = QDF_STATUS_SUCCESS; 725 } else { 726 status = QDF_STATUS_E_FAILURE; 727 } 728 729 return status; 730 } 731 732 /** 733 * hif_diag_write_access() - write data to target memory or register 734 * @scn: pointer to hif_opaque_softc 735 * @address: register address to write to 736 * @data: value to be written to the address 737 * 738 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 739 */ 740 QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *scn, 741 uint32_t address, 742 uint32_t data) 743 { 744 struct HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 745 USB_CTRL_DIAG_CMD_WRITE *cmd; 746 747 cmd = (USB_CTRL_DIAG_CMD_WRITE *) macp->diag_cmd_buffer; 748 749 qdf_mem_zero(cmd, sizeof(*cmd)); 750 cmd->Cmd = USB_CTRL_DIAG_CC_WRITE; 751 cmd->Address = address; 752 cmd->Value = data; 753 754 return hif_ctrl_msg_exchange(macp, 755 USB_CONTROL_REQ_DIAG_CMD, 756 (uint8_t *) cmd, 757 sizeof(*cmd), 0, NULL, 0); 758 } 759 760 /** 761 * hif_dump_info() - dump info about all HIF pipes and endpoints 762 * @scn: pointer to hif_opaque_softc 763 * 764 * Return: none 765 */ 766 void hif_dump_info(struct hif_opaque_softc *scn) 767 { 768 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 769 struct HIF_USB_PIPE *pipe = NULL; 770 struct usb_host_interface *iface_desc = NULL; 771 struct usb_endpoint_descriptor *ep_desc; 772 uint8_t i = 0; 773 774 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 775 pipe = &device->pipes[i]; 776 HIF_ERROR("PipeIndex : %d URB Cnt : %d PipeHandle : %x", 777 i, pipe->urb_cnt, 778 pipe->usb_pipe_handle); 779 if (usb_pipeisoc(pipe->usb_pipe_handle)) 780 HIF_INFO("Pipe Type ISOC"); 781 else if (usb_pipebulk(pipe->usb_pipe_handle)) 782 HIF_INFO("Pipe Type BULK"); 783 else if (usb_pipeint(pipe->usb_pipe_handle)) 784 HIF_INFO("Pipe Type INT"); 785 else if (usb_pipecontrol(pipe->usb_pipe_handle)) 786 HIF_INFO("Pipe Type control"); 787 } 788 789 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { 790 ep_desc = &iface_desc->endpoint[i].desc; 791 if (ep_desc) { 792 HIF_INFO( 793 "ep_desc : %pK Index : %d: DescType : %d Addr : %d Maxp : %d Atrrib : %d", 794 ep_desc, i, ep_desc->bDescriptorType, 795 ep_desc->bEndpointAddress, 796 ep_desc->wMaxPacketSize, 797 ep_desc->bmAttributes); 798 if ((ep_desc) && (usb_endpoint_type(ep_desc) == 799 USB_ENDPOINT_XFER_ISOC)) { 800 HIF_INFO("ISOC EP Detected"); 801 } 802 } 803 } 804 805 } 806 807 /** 808 * hif_flush_surprise_remove() - Cleanup residual buffers for device shutdown 809 * @scn: HIF context 810 * 811 * Not applicable to USB bus 812 * 813 * Return: none 814 */ 815 void hif_flush_surprise_remove(struct hif_opaque_softc *scn) 816 { 817 /* TO DO... */ 818 } 819 820 /** 821 * hif_diag_read_mem() -read nbytes of data from target memory or register 822 * @scn: pointer to hif_opaque_softc 823 * @address: register address to read from 824 * @data: buffer to store the value read 825 * @nbytes: number of bytes to be read from 'address' 826 * 827 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 828 */ 829 QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *scn, 830 uint32_t address, uint8_t *data, 831 int nbytes) 832 { 833 QDF_STATUS status = QDF_STATUS_SUCCESS; 834 835 HIF_TRACE("+%s", __func__); 836 837 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 838 return QDF_STATUS_E_IO; 839 840 while ((nbytes >= 4) && 841 QDF_IS_STATUS_SUCCESS(status = 842 hif_diag_read_access(scn, 843 address, 844 (uint32_t *)data))) { 845 846 nbytes -= sizeof(uint32_t); 847 address += sizeof(uint32_t); 848 data += sizeof(uint32_t); 849 850 } 851 HIF_TRACE("-%s", __func__); 852 return status; 853 } 854 qdf_export_symbol(hif_diag_read_mem); 855 856 /** 857 * hif_diag_write_mem() -write nbytes of data to target memory or register 858 * @scn: pointer to hif_opaque_softc 859 * @address: register address to write to 860 * @data: buffer containing data to be written 861 * @nbytes: number of bytes to be written 862 * 863 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 864 */ 865 QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *scn, 866 uint32_t address, 867 uint8_t *data, int nbytes) 868 { 869 QDF_STATUS status = QDF_STATUS_SUCCESS; 870 871 HIF_TRACE("+%s", __func__); 872 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 873 return QDF_STATUS_E_IO; 874 875 while (nbytes >= 4 && 876 QDF_IS_STATUS_SUCCESS(status = 877 hif_diag_write_access(scn, 878 address, 879 *((uint32_t *)data)))) { 880 881 nbytes -= sizeof(uint32_t); 882 address += sizeof(uint32_t); 883 data += sizeof(uint32_t); 884 885 } 886 HIF_TRACE("-%s", __func__); 887 return status; 888 } 889 890 void hif_send_complete_check(struct hif_opaque_softc *scn, 891 uint8_t PipeID, int force) 892 { 893 /* NO-OP*/ 894 } 895 896 /* diagnostic command defnitions */ 897 #define USB_CTRL_DIAG_CC_READ 0 898 #define USB_CTRL_DIAG_CC_WRITE 1 899 #define USB_CTRL_DIAG_CC_WARM_RESET 2 900 901 void hif_suspend_wow(struct hif_opaque_softc *scn) 902 { 903 HIF_INFO("HIFsuspendwow - TODO"); 904 } 905 906 /** 907 * hif_usb_set_bundle_mode() - enable bundling and set default rx bundle cnt 908 * @scn: pointer to hif_opaque_softc structure 909 * @enabled: flag to enable/disable bundling 910 * @rx_bundle_cnt: bundle count to be used for RX 911 * 912 * Return: none 913 */ 914 void hif_usb_set_bundle_mode(struct hif_softc *scn, 915 bool enabled, int rx_bundle_cnt) 916 { 917 struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 918 919 device->is_bundle_enabled = enabled; 920 device->rx_bundle_cnt = rx_bundle_cnt; 921 if (device->is_bundle_enabled && (device->rx_bundle_cnt == 0)) 922 device->rx_bundle_cnt = 1; 923 924 device->rx_bundle_buf_len = device->rx_bundle_cnt * 925 HIF_USB_RX_BUNDLE_ONE_PKT_SIZE; 926 927 HIF_DBG("athusb bundle %s cnt %d", enabled ? "enabled" : "disabled", 928 rx_bundle_cnt); 929 } 930