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 42 #if defined(WLAN_DEBUG) || defined(DEBUG) 43 static ATH_DEBUG_MASK_DESCRIPTION g_hif_debug_description[] = { 44 {USB_HIF_DEBUG_CTRL_TRANS, "Control Transfers"}, 45 {USB_HIF_DEBUG_BULK_IN, "BULK In Transfers"}, 46 {USB_HIF_DEBUG_BULK_OUT, "BULK Out Transfers"}, 47 {USB_HIF_DEBUG_DUMP_DATA, "Dump data"}, 48 {USB_HIF_DEBUG_ENUM, "Enumeration"}, 49 }; 50 51 ATH_DEBUG_INSTANTIATE_MODULE_VAR(hif, 52 "hif", 53 "USB Host Interface", 54 ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO | 55 USB_HIF_DEBUG_ENUM, 56 ATH_DEBUG_DESCRIPTION_COUNT 57 (g_hif_debug_description), 58 g_hif_debug_description); 59 60 #endif 61 62 #ifdef USB_ISOC_SUPPORT 63 unsigned int hif_usb_isoch_vo = 1; 64 #else 65 unsigned int hif_usb_isoch_vo; 66 #endif 67 unsigned int hif_usb_disable_rxdata2 = 1; 68 69 /** 70 * usb_hif_usb_transmit_complete() - completion routing for tx urb's 71 * @urb: pointer to urb for which tx completion is called 72 * 73 * Return: none 74 */ 75 static void usb_hif_usb_transmit_complete(struct urb *urb) 76 { 77 HIF_URB_CONTEXT *urb_context = (HIF_URB_CONTEXT *) urb->context; 78 qdf_nbuf_t buf; 79 HIF_USB_PIPE *pipe = urb_context->pipe; 80 struct hif_usb_send_context *send_context; 81 82 HIF_DBG("+%s: pipe: %d, stat:%d, len:%d", __func__, 83 pipe->logical_pipe_num, urb->status, urb->actual_length); 84 85 /* this urb is not pending anymore */ 86 usb_hif_remove_pending_transfer(urb_context); 87 88 if (urb->status != 0) { 89 HIF_ERROR("%s: pipe: %d, failed:%d", 90 __func__, pipe->logical_pipe_num, urb->status); 91 } 92 93 buf = urb_context->buf; 94 send_context = urb_context->send_context; 95 96 if (send_context->new_alloc) 97 qdf_mem_free(send_context); 98 else 99 qdf_nbuf_pull_head(buf, send_context->head_data_len); 100 101 urb_context->buf = NULL; 102 usb_hif_cleanup_transmit_urb(urb_context); 103 104 /* note: queue implements a lock */ 105 skb_queue_tail(&pipe->io_comp_queue, buf); 106 HIF_USB_SCHEDULE_WORK(pipe) 107 108 HIF_DBG("-%s", __func__); 109 } 110 111 /** 112 * hif_send_internal() - HIF internal routine to prepare and submit tx urbs 113 * @hif_usb_device: pointer to HIF_DEVICE_USB structure 114 * @pipe_id: HIF pipe on which data is to be sent 115 * @hdr_buf: any header buf to be prepended, currently ignored 116 * @buf: qdf_nbuf_t containing data to be transmitted 117 * @nbytes: number of bytes to be transmitted 118 * 119 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure 120 */ 121 static QDF_STATUS hif_send_internal(HIF_DEVICE_USB *hif_usb_device, 122 uint8_t pipe_id, 123 qdf_nbuf_t hdr_buf, 124 qdf_nbuf_t buf, unsigned int nbytes) 125 { 126 QDF_STATUS status = QDF_STATUS_SUCCESS; 127 HIF_DEVICE_USB *device = hif_usb_device; 128 HIF_USB_PIPE *pipe = &device->pipes[pipe_id]; 129 HIF_URB_CONTEXT *urb_context; 130 uint8_t *data; 131 uint32_t len; 132 struct urb *urb; 133 int usb_status; 134 int i; 135 struct hif_usb_send_context *send_context; 136 uint8_t frag_count; 137 uint32_t head_data_len, tmp_frag_count = 0; 138 unsigned char *data_ptr; 139 140 HIF_DBG("+%s pipe : %d, buf:0x%pK nbytes %u", 141 __func__, pipe_id, buf, nbytes); 142 143 frag_count = qdf_nbuf_get_num_frags(buf); 144 if (frag_count == 1) { 145 /* 146 * | hif_usb_send_context | netbuf->data 147 */ 148 head_data_len = sizeof(struct hif_usb_send_context); 149 } else if ((frag_count - 1) <= QDF_NBUF_CB_TX_MAX_EXTRA_FRAGS) { 150 /* 151 * means have extra fragment buf in skb 152 * header data length should be total sending length substract 153 * internal data length of netbuf 154 * | hif_usb_send_context | fragments except internal buffer | 155 * netbuf->data 156 */ 157 head_data_len = sizeof(struct hif_usb_send_context); 158 while (tmp_frag_count < (frag_count - 1)) { 159 head_data_len = 160 head_data_len + qdf_nbuf_get_frag_len(buf, 161 tmp_frag_count); 162 tmp_frag_count = tmp_frag_count + 1; 163 } 164 } else { 165 /* Extra fragments overflow */ 166 HIF_ERROR("%s Extra fragments count overflow : %d\n", 167 __func__, frag_count); 168 status = QDF_STATUS_E_RESOURCES; 169 goto err; 170 } 171 172 /* Check whether head room is enough to save extra head data */ 173 if (head_data_len <= qdf_nbuf_headroom(buf)) { 174 send_context = (struct hif_usb_send_context *) 175 qdf_nbuf_push_head(buf, head_data_len); 176 send_context->new_alloc = false; 177 } else { 178 send_context = 179 qdf_mem_malloc(sizeof(struct hif_usb_send_context) 180 + head_data_len + nbytes); 181 if (send_context == NULL) { 182 HIF_ERROR("%s: qdf_mem_malloc failed", __func__); 183 status = QDF_STATUS_E_NOMEM; 184 goto err; 185 } 186 send_context->new_alloc = true; 187 } 188 send_context->netbuf = buf; 189 send_context->hif_usb_device = hif_usb_device; 190 send_context->transfer_id = pipe_id; 191 send_context->head_data_len = head_data_len; 192 /* 193 * Copy data to head part of netbuf or head of allocated buffer. 194 * if buffer is new allocated, the last buffer should be copied also. 195 * It assume last fragment is internal buffer of netbuf 196 * sometime total length of fragments larger than nbytes 197 */ 198 data_ptr = (unsigned char *)send_context + 199 sizeof(struct hif_usb_send_context); 200 for (i = 0; 201 i < (send_context->new_alloc ? frag_count : frag_count - 1); i++) { 202 int frag_len = qdf_nbuf_get_frag_len(buf, i); 203 unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i); 204 205 qdf_mem_copy(data_ptr, frag_addr, frag_len); 206 data_ptr += frag_len; 207 } 208 /* Reset pData pointer and send out */ 209 data_ptr = (unsigned char *)send_context + 210 sizeof(struct hif_usb_send_context); 211 212 urb_context = usb_hif_alloc_urb_from_pipe(pipe); 213 if (NULL == urb_context) { 214 /* TODO : note, it is possible to run out of urbs if 2 215 * endpoints map to the same pipe ID 216 */ 217 HIF_ERROR("%s pipe:%d no urbs left. URB Cnt : %d", 218 __func__, pipe_id, pipe->urb_cnt); 219 status = QDF_STATUS_E_RESOURCES; 220 goto err; 221 } 222 urb_context->send_context = send_context; 223 urb = urb_context->urb; 224 urb_context->buf = buf; 225 data = data_ptr; 226 len = nbytes; 227 228 usb_fill_bulk_urb(urb, 229 device->udev, 230 pipe->usb_pipe_handle, 231 data, 232 (len % pipe->max_packet_size) == 233 0 ? (len + 1) : len, 234 usb_hif_usb_transmit_complete, urb_context); 235 236 if ((len % pipe->max_packet_size) == 0) 237 /* hit a max packet boundary on this pipe */ 238 239 HIF_DBG 240 ("athusb bulk send submit:%d, 0x%X (ep:0x%2.2X), %d bytes", 241 pipe->logical_pipe_num, pipe->usb_pipe_handle, 242 pipe->ep_address, nbytes); 243 244 usb_hif_enqueue_pending_transfer(pipe, urb_context); 245 usb_status = usb_submit_urb(urb, GFP_ATOMIC); 246 if (usb_status) { 247 if (send_context->new_alloc) 248 qdf_mem_free(send_context); 249 else 250 qdf_nbuf_pull_head(buf, head_data_len); 251 urb_context->buf = NULL; 252 HIF_ERROR("athusb : usb bulk transmit failed %d", 253 usb_status); 254 usb_hif_remove_pending_transfer(urb_context); 255 usb_hif_cleanup_transmit_urb(urb_context); 256 status = QDF_STATUS_E_FAILURE; 257 goto err; 258 } 259 260 err: 261 if (!QDF_IS_STATUS_SUCCESS(status) && 262 (status != QDF_STATUS_E_RESOURCES)) { 263 HIF_ERROR("athusb send failed %d", status); 264 } 265 266 HIF_DBG("-%s pipe : %d", __func__, pipe_id); 267 268 return status; 269 } 270 271 /** 272 * hif_send_head() - HIF routine exposed to upper layers to send data 273 * @scn: pointer to hif_opaque_softc structure 274 * @pipe_id: HIF pipe on which data is to be sent 275 * @transfer_id: endpoint ID on which data is to be sent 276 * @nbytes: number of bytes to be transmitted 277 * @wbuf: qdf_nbuf_t containing data to be transmitted 278 * @hdr_buf: any header buf to be prepended, currently ignored 279 * @data_attr: data_attr field from cvg_nbuf_cb of wbuf 280 * 281 * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure 282 */ 283 QDF_STATUS hif_send_head(struct hif_opaque_softc *scn, uint8_t pipe_id, 284 uint32_t transfer_id, uint32_t nbytes, 285 qdf_nbuf_t wbuf, uint32_t data_attr) 286 { 287 QDF_STATUS status = QDF_STATUS_SUCCESS; 288 HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 289 290 HIF_TRACE("+%s", __func__); 291 status = hif_send_internal(device, pipe_id, NULL, wbuf, nbytes); 292 HIF_TRACE("-%s", __func__); 293 return status; 294 } 295 296 /** 297 * hif_get_free_queue_number() - get # of free TX resources in a given HIF pipe 298 * @scn: pointer to hif_opaque_softc structure 299 * @pipe_id: HIF pipe which is being polled for free resources 300 * 301 * Return: # of free resources in pipe_id 302 */ 303 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *scn, 304 uint8_t pipe_id) 305 { 306 HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 307 308 return device->pipes[pipe_id].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 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 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 HIF_DEVICE_USB *device = &sc->hif_hdl; 351 352 HIF_TRACE("+%s", __func__); 353 354 usb_hif_cleanup_pipe_resources(device); 355 356 usb_set_intfdata(device->interface, NULL); 357 358 if (device->diag_cmd_buffer != NULL) 359 qdf_mem_free(device->diag_cmd_buffer); 360 361 if (device->diag_resp_buffer != NULL) 362 qdf_mem_free(device->diag_resp_buffer); 363 364 HIF_TRACE("-%s", __func__); 365 } 366 367 /** 368 * hif_usb_device_init() - init HIF_DEVICE_USB, setup pipe resources 369 * @sc: pointer to hif_usb_softc structure 370 * 371 * Return: QDF_STATUS_SUCCESS on success or a QDF error 372 */ 373 QDF_STATUS hif_usb_device_init(struct hif_usb_softc *sc) 374 { 375 int i; 376 HIF_DEVICE_USB *device = &sc->hif_hdl; 377 struct usb_interface *interface = sc->interface; 378 struct usb_device *dev = interface_to_usbdev(interface); 379 QDF_STATUS status = QDF_STATUS_SUCCESS; 380 HIF_USB_PIPE *pipe; 381 382 HIF_TRACE("+%s", __func__); 383 384 do { 385 386 usb_set_intfdata(interface, device); 387 qdf_spinlock_create(&(device->cs_lock)); 388 qdf_spinlock_create(&(device->rx_lock)); 389 qdf_spinlock_create(&(device->tx_lock)); 390 device->udev = dev; 391 device->interface = interface; 392 393 HIF_ERROR("%s device %pK device->udev %pK device->interface %pK", 394 __func__, 395 device, 396 device->udev, 397 device->interface); 398 399 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 400 pipe = &device->pipes[i]; 401 402 HIF_USB_INIT_WORK(pipe); 403 skb_queue_head_init(&pipe->io_comp_queue); 404 } 405 406 device->diag_cmd_buffer = 407 qdf_mem_malloc(USB_CTRL_MAX_DIAG_CMD_SIZE); 408 if (NULL == device->diag_cmd_buffer) { 409 status = QDF_STATUS_E_NOMEM; 410 break; 411 } 412 device->diag_resp_buffer = 413 qdf_mem_malloc(USB_CTRL_MAX_DIAG_RESP_SIZE); 414 if (NULL == device->diag_resp_buffer) { 415 status = QDF_STATUS_E_NOMEM; 416 break; 417 } 418 419 status = usb_hif_setup_pipe_resources(device); 420 421 } while (false); 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 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 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 559 switch (svc_id) { 560 case HTC_CTRL_RSVD_SVC: 561 case WMI_CONTROL_SVC: 562 *ul_pipe = HIF_TX_CTRL_PIPE; 563 *dl_pipe = HIF_RX_DATA_PIPE; 564 break; 565 case WMI_DATA_BE_SVC: 566 case WMI_DATA_BK_SVC: 567 *ul_pipe = HIF_TX_DATA_LP_PIPE; 568 if (hif_usb_disable_rxdata2) 569 *dl_pipe = HIF_RX_DATA_PIPE; 570 else 571 *dl_pipe = HIF_RX_DATA2_PIPE; 572 break; 573 case WMI_DATA_VI_SVC: 574 *ul_pipe = HIF_TX_DATA_MP_PIPE; 575 if (hif_usb_disable_rxdata2) 576 *dl_pipe = HIF_RX_DATA_PIPE; 577 else 578 *dl_pipe = HIF_RX_DATA2_PIPE; 579 break; 580 case WMI_DATA_VO_SVC: 581 *ul_pipe = HIF_TX_DATA_HP_PIPE; 582 if (hif_usb_disable_rxdata2) 583 *dl_pipe = HIF_RX_DATA_PIPE; 584 else 585 *dl_pipe = HIF_RX_DATA2_PIPE; 586 break; 587 case HTC_RAW_STREAMS_SVC: 588 *ul_pipe = HIF_TX_CTRL_PIPE; 589 *dl_pipe = HIF_RX_DATA_PIPE; 590 break; 591 case HTT_DATA_MSG_SVC: 592 *ul_pipe = HIF_TX_DATA_LP_PIPE; 593 if (hif_usb_disable_rxdata2) 594 *dl_pipe = HIF_RX_DATA_PIPE; 595 else 596 *dl_pipe = HIF_RX_DATA2_PIPE; 597 break; 598 case HTT_DATA2_MSG_SVC: 599 if (USB_TX_CHECK_HTT2_SUPPORT) { 600 *ul_pipe = HIF_TX_DATA_HP_PIPE; 601 if (hif_usb_disable_rxdata2) 602 *dl_pipe = HIF_RX_DATA_PIPE; 603 else 604 *dl_pipe = HIF_RX_DATA2_PIPE; 605 } 606 break; 607 default: 608 status = QDF_STATUS_E_FAILURE; 609 break; 610 } 611 612 return status; 613 } 614 #endif 615 616 /** 617 * hif_ctrl_msg_exchange() - send usb ctrl message and receive response 618 * @macp: pointer to HIF_DEVICE_USB 619 * @send_req_val: USB send message request value 620 * @send_msg: pointer to data to send 621 * @len: length in bytes of the data to send 622 * @response_req_val: USB response message request value 623 * @response_msg: pointer to response msg 624 * @response_len: length of the response message 625 * 626 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 627 */ 628 static QDF_STATUS hif_ctrl_msg_exchange(HIF_DEVICE_USB *macp, 629 uint8_t send_req_val, 630 uint8_t *send_msg, 631 uint32_t len, 632 uint8_t response_req_val, 633 uint8_t *response_msg, 634 uint32_t *response_len) 635 { 636 QDF_STATUS status; 637 638 do { 639 640 /* send command */ 641 status = usb_hif_submit_ctrl_out(macp, send_req_val, 0, 0, 642 send_msg, len); 643 644 if (!QDF_IS_STATUS_SUCCESS(status)) 645 break; 646 647 if (NULL == response_msg) { 648 /* no expected response */ 649 break; 650 } 651 652 /* get response */ 653 status = usb_hif_submit_ctrl_in(macp, response_req_val, 0, 0, 654 response_msg, *response_len); 655 656 if (!QDF_IS_STATUS_SUCCESS(status)) 657 break; 658 659 } while (false); 660 661 return status; 662 } 663 664 /** 665 * hif_exchange_bmi_msg() - send/recev ctrl message of type BMI_CMD/BMI_RESP 666 * @scn: pointer to hif_opaque_softc 667 * @bmi_request: pointer to data to send 668 * @request_length: length in bytes of the data to send 669 * @bmi_response: pointer to response msg 670 * @bmi_response_length: length of the response message 671 * @timeout_ms: timeout to wait for response (ignored in current implementation) 672 * 673 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 674 */ 675 676 QDF_STATUS hif_exchange_bmi_msg(struct hif_opaque_softc *scn, 677 qdf_dma_addr_t cmd, qdf_dma_addr_t rsp, 678 uint8_t *bmi_request, 679 uint32_t request_length, 680 uint8_t *bmi_response, 681 uint32_t *bmi_response_lengthp, 682 uint32_t timeout_ms) 683 { 684 HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 685 686 return hif_ctrl_msg_exchange(macp, 687 USB_CONTROL_REQ_SEND_BMI_CMD, 688 bmi_request, 689 request_length, 690 USB_CONTROL_REQ_RECV_BMI_RESP, 691 bmi_response, bmi_response_lengthp); 692 } 693 694 /** 695 * hif_diag_read_access() - Read data from target memory or register 696 * @scn: pointer to hif_opaque_softc 697 * @address: register address to read from 698 * @data: pointer to buffer to store the value read from the register 699 * 700 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 701 */ 702 QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *scn, uint32_t address, 703 uint32_t *data) 704 { 705 HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 706 QDF_STATUS status; 707 USB_CTRL_DIAG_CMD_READ *cmd; 708 uint32_t respLength; 709 710 cmd = (USB_CTRL_DIAG_CMD_READ *) macp->diag_cmd_buffer; 711 712 qdf_mem_zero(cmd, sizeof(*cmd)); 713 cmd->Cmd = USB_CTRL_DIAG_CC_READ; 714 cmd->Address = address; 715 respLength = sizeof(USB_CTRL_DIAG_RESP_READ); 716 717 status = hif_ctrl_msg_exchange(macp, 718 USB_CONTROL_REQ_DIAG_CMD, 719 (uint8_t *) cmd, 720 sizeof(*cmd), 721 USB_CONTROL_REQ_DIAG_RESP, 722 macp->diag_resp_buffer, &respLength); 723 724 if (QDF_IS_STATUS_SUCCESS(status)) { 725 USB_CTRL_DIAG_RESP_READ *pResp = 726 (USB_CTRL_DIAG_RESP_READ *) macp->diag_resp_buffer; 727 *data = pResp->ReadValue; 728 status = QDF_STATUS_SUCCESS; 729 } else { 730 status = QDF_STATUS_E_FAILURE; 731 } 732 733 return status; 734 } 735 736 /** 737 * hif_diag_write_access() - write data to target memory or register 738 * @scn: pointer to hif_opaque_softc 739 * @address: register address to write to 740 * @data: value to be written to the address 741 * 742 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 743 */ 744 QDF_STATUS hif_diag_write_access(struct hif_opaque_softc *scn, 745 uint32_t address, 746 uint32_t data) 747 { 748 HIF_DEVICE_USB *macp = HIF_GET_USB_DEVICE(scn); 749 USB_CTRL_DIAG_CMD_WRITE *cmd; 750 751 cmd = (USB_CTRL_DIAG_CMD_WRITE *) macp->diag_cmd_buffer; 752 753 qdf_mem_zero(cmd, sizeof(*cmd)); 754 cmd->Cmd = USB_CTRL_DIAG_CC_WRITE; 755 cmd->Address = address; 756 cmd->Value = data; 757 758 return hif_ctrl_msg_exchange(macp, 759 USB_CONTROL_REQ_DIAG_CMD, 760 (uint8_t *) cmd, 761 sizeof(*cmd), 0, NULL, 0); 762 } 763 764 /** 765 * hif_dump_info() - dump info about all HIF pipes and endpoints 766 * @scn: pointer to hif_opaque_softc 767 * 768 * Return: none 769 */ 770 void hif_dump_info(struct hif_opaque_softc *scn) 771 { 772 HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 773 HIF_USB_PIPE *pipe = NULL; 774 struct usb_host_interface *iface_desc = NULL; 775 struct usb_endpoint_descriptor *ep_desc; 776 uint8_t i = 0; 777 778 for (i = 0; i < HIF_USB_PIPE_MAX; i++) { 779 pipe = &device->pipes[i]; 780 HIF_ERROR("PipeIndex : %d URB Cnt : %d PipeHandle : %x", 781 i, pipe->urb_cnt, 782 pipe->usb_pipe_handle); 783 if (usb_pipeisoc(pipe->usb_pipe_handle)) 784 HIF_INFO("Pipe Type ISOC"); 785 else if (usb_pipebulk(pipe->usb_pipe_handle)) 786 HIF_INFO("Pipe Type BULK"); 787 else if (usb_pipeint(pipe->usb_pipe_handle)) 788 HIF_INFO("Pipe Type INT"); 789 else if (usb_pipecontrol(pipe->usb_pipe_handle)) 790 HIF_INFO("Pipe Type control"); 791 } 792 793 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { 794 ep_desc = &iface_desc->endpoint[i].desc; 795 if (ep_desc) { 796 HIF_INFO( 797 "ep_desc : %pK Index : %d: DescType : %d Addr : %d Maxp : %d Atrrib : %d", 798 ep_desc, i, ep_desc->bDescriptorType, 799 ep_desc->bEndpointAddress, 800 ep_desc->wMaxPacketSize, 801 ep_desc->bmAttributes); 802 if ((ep_desc) && (usb_endpoint_type(ep_desc) == 803 USB_ENDPOINT_XFER_ISOC)) { 804 HIF_INFO("ISOC EP Detected"); 805 } 806 } 807 } 808 809 } 810 811 /** 812 * hif_flush_surprise_remove() - Cleanup residual buffers for device shutdown 813 * @scn: HIF context 814 * 815 * Not applicable to USB bus 816 * 817 * Return: none 818 */ 819 void hif_flush_surprise_remove(struct hif_opaque_softc *scn) 820 { 821 /* TO DO... */ 822 } 823 824 /** 825 * hif_diag_read_mem() -read nbytes of data from target memory or register 826 * @scn: pointer to hif_opaque_softc 827 * @address: register address to read from 828 * @data: buffer to store the value read 829 * @nbytes: number of bytes to be read from 'address' 830 * 831 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 832 */ 833 QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *scn, 834 uint32_t address, uint8_t *data, 835 int nbytes) 836 { 837 QDF_STATUS status = QDF_STATUS_SUCCESS; 838 839 HIF_TRACE("+%s", __func__); 840 841 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 842 return QDF_STATUS_E_IO; 843 844 while ((nbytes >= 4) && 845 QDF_IS_STATUS_SUCCESS(status = 846 hif_diag_read_access(scn, 847 address, 848 (uint32_t *)data))) { 849 850 nbytes -= sizeof(uint32_t); 851 address += sizeof(uint32_t); 852 data += sizeof(uint32_t); 853 854 } 855 HIF_TRACE("-%s", __func__); 856 return status; 857 } 858 qdf_export_symbol(hif_diag_read_mem); 859 860 /** 861 * hif_diag_write_mem() -write nbytes of data to target memory or register 862 * @scn: pointer to hif_opaque_softc 863 * @address: register address to write to 864 * @data: buffer containing data to be written 865 * @nbytes: number of bytes to be written 866 * 867 * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error 868 */ 869 QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *scn, 870 uint32_t address, 871 uint8_t *data, int nbytes) 872 { 873 QDF_STATUS status = QDF_STATUS_SUCCESS; 874 875 HIF_TRACE("+%s", __func__); 876 if ((address & 0x3) || ((uintptr_t)data & 0x3)) 877 return QDF_STATUS_E_IO; 878 879 while (nbytes >= 4 && 880 QDF_IS_STATUS_SUCCESS(status = 881 hif_diag_write_access(scn, 882 address, 883 *((uint32_t *)data)))) { 884 885 nbytes -= sizeof(uint32_t); 886 address += sizeof(uint32_t); 887 data += sizeof(uint32_t); 888 889 } 890 HIF_TRACE("-%s", __func__); 891 return status; 892 } 893 894 void hif_send_complete_check(struct hif_opaque_softc *scn, 895 uint8_t PipeID, int force) 896 { 897 /* NO-OP*/ 898 } 899 900 /* diagnostic command defnitions */ 901 #define USB_CTRL_DIAG_CC_READ 0 902 #define USB_CTRL_DIAG_CC_WRITE 1 903 #define USB_CTRL_DIAG_CC_WARM_RESET 2 904 905 void hif_suspend_wow(struct hif_opaque_softc *scn) 906 { 907 HIF_INFO("HIFsuspendwow - TODO"); 908 } 909 910 /** 911 * hif_usb_set_bundle_mode() - enable bundling and set default rx bundle cnt 912 * @scn: pointer to hif_opaque_softc structure 913 * @enabled: flag to enable/disable bundling 914 * @rx_bundle_cnt: bundle count to be used for RX 915 * 916 * Return: none 917 */ 918 void hif_usb_set_bundle_mode(struct hif_softc *scn, 919 bool enabled, int rx_bundle_cnt) 920 { 921 HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(scn); 922 923 device->is_bundle_enabled = enabled; 924 device->rx_bundle_cnt = rx_bundle_cnt; 925 if (device->is_bundle_enabled && (device->rx_bundle_cnt == 0)) 926 device->rx_bundle_cnt = 1; 927 928 device->rx_bundle_buf_len = device->rx_bundle_cnt * 929 HIF_USB_RX_BUNDLE_ONE_PKT_SIZE; 930 931 HIF_DBG("athusb bundle %s cnt %d", enabled ? "enabled" : "disabled", 932 rx_bundle_cnt); 933 } 934