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