1 /* 2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <qdf_types.h> 20 #include <qdf_status.h> 21 #include <qdf_timer.h> 22 #include <qdf_time.h> 23 #include <qdf_lock.h> 24 #include <qdf_mem.h> 25 #include <qdf_util.h> 26 #include <qdf_defer.h> 27 #include <qdf_atomic.h> 28 #include <qdf_nbuf.h> 29 #include <athdefs.h> 30 #include "qdf_net_types.h" 31 #include "a_types.h" 32 #include "athdefs.h" 33 #include "a_osapi.h" 34 #include <hif.h> 35 #include <htc_services.h> 36 #include <a_debug.h> 37 #include "hif_sdio_dev.h" 38 #include "if_sdio.h" 39 #include "regtable_sdio.h" 40 #include <transfer/transfer.h> 41 42 #define ATH_MODULE_NAME hif_sdio 43 44 /** 45 * hif_start() - start hif bus interface. 46 * @hif_ctx: HIF context 47 * 48 * Enables hif device interrupts 49 * 50 * Return: QDF_STATUS 51 */ 52 QDF_STATUS hif_start(struct hif_opaque_softc *hif_ctx) 53 { 54 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 55 struct hif_sdio_dev *hif_device = scn->hif_handle; 56 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device); 57 struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx); 58 int ret = 0; 59 60 HIF_ENTER(); 61 ret = hif_sdio_bus_configure(hif_sc); 62 if (ret) { 63 hif_err("hif_sdio_bus_configure failed"); 64 return QDF_STATUS_E_FAILURE; 65 } 66 67 hif_dev_enable_interrupts(htc_sdio_device); 68 HIF_EXIT(); 69 return QDF_STATUS_SUCCESS; 70 } 71 72 /** 73 * hif_flush_surprise_remove() - remove hif bus interface. 74 * @hif_ctx: HIF context 75 * 76 * 77 * Return: none 78 */ 79 void hif_flush_surprise_remove(struct hif_opaque_softc *hif_ctx) 80 { 81 82 } 83 84 /** 85 * hif_sdio_stop() - stop hif bus interface. 86 * @hif_ctx: HIF context 87 * 88 * Disable hif device interrupts and destroy hif context 89 * 90 * Return: none 91 */ 92 void hif_sdio_stop(struct hif_softc *hif_ctx) 93 { 94 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 95 struct hif_sdio_dev *hif_device = scn->hif_handle; 96 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device); 97 98 HIF_ENTER(); 99 if (htc_sdio_device) { 100 hif_dev_disable_interrupts(htc_sdio_device); 101 hif_dev_destroy(htc_sdio_device); 102 } 103 HIF_EXIT(); 104 } 105 106 /** 107 * hif_send_head() - send data on hif bus interface. 108 * @hif_ctx: HIF context 109 * 110 * send tx data on a given pipe id 111 * 112 * Return: QDF_STATUS 113 */ 114 QDF_STATUS hif_send_head(struct hif_opaque_softc *hif_ctx, uint8_t pipe, 115 uint32_t transfer_id, uint32_t nbytes, qdf_nbuf_t buf, 116 uint32_t data_attr) 117 { 118 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 119 struct hif_sdio_dev *hif_device = scn->hif_handle; 120 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device); 121 122 return hif_dev_send_buffer(htc_sdio_device, 123 transfer_id, pipe, 124 nbytes, buf); 125 } 126 127 /** 128 * hif_map_service_to_pipe() - maps ul/dl pipe to service id. 129 * @hif_ctx: HIF hdl 130 * @ServiceId: sevice index 131 * @ul_pipe: uplink pipe id 132 * @dl_pipe: down-linklink pipe id 133 * @ul_is_polled: if ul is polling based 134 * @ul_is_polled: if dl is polling based 135 * 136 * Return: int 137 */ 138 int hif_map_service_to_pipe(struct hif_opaque_softc *hif_hdl, 139 uint16_t service_id, uint8_t *ul_pipe, 140 uint8_t *dl_pipe, int *ul_is_polled, 141 int *dl_is_polled) 142 { 143 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_hdl); 144 struct hif_sdio_dev *hif_device = scn->hif_handle; 145 QDF_STATUS status; 146 147 status = hif_dev_map_service_to_pipe(hif_device, 148 service_id, ul_pipe, dl_pipe); 149 return qdf_status_to_os_return(status); 150 } 151 152 /** 153 * hif_get_default_pipe() - get default pipe 154 * @scn: HIF context 155 * @ul_pipe: uplink pipe id 156 * @dl_pipe: down-linklink pipe id 157 */ 158 void hif_get_default_pipe(struct hif_opaque_softc *scn, uint8_t *ul_pipe, 159 uint8_t *dl_pipe) 160 { 161 hif_map_service_to_pipe(scn, HTC_CTRL_RSVD_SVC, 162 ul_pipe, dl_pipe, NULL, NULL); 163 } 164 165 /** 166 * hif_post_init() - create hif device after probe. 167 * @hif_ctx: HIF context 168 * @target: HIF target 169 * @callbacks: htc callbacks 170 * 171 * 172 * Return: int 173 */ 174 void hif_post_init(struct hif_opaque_softc *hif_ctx, void *target, 175 struct hif_msg_callbacks *callbacks) 176 { 177 struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_ctx); 178 struct hif_sdio_dev *hif_device = scn->hif_handle; 179 struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device); 180 181 HIF_ENTER(); 182 183 if (!htc_sdio_device) 184 htc_sdio_device = hif_dev_create(hif_device, callbacks, target); 185 186 if (htc_sdio_device) 187 hif_dev_setup(htc_sdio_device); 188 189 HIF_EXIT(); 190 } 191 192 /** 193 * hif_get_free_queue_number() - create hif device after probe. 194 * @hif_ctx: HIF context 195 * @pipe: pipe id 196 * 197 * SDIO uses credit based flow control at the HTC layer 198 * so transmit resource checks are bypassed 199 * Return: int 200 */ 201 uint16_t hif_get_free_queue_number(struct hif_opaque_softc *hif_ctx, 202 uint8_t pipe) 203 { 204 uint16_t rv; 205 206 rv = 1; 207 return rv; 208 } 209 210 /** 211 * hif_send_complete_check() - check tx complete on a given pipe. 212 * @hif_ctx: HIF context 213 * @pipe: HIF target 214 * @force: check if need to pool for completion 215 * Decide whether to actually poll for completions, or just 216 * wait for a later chance. 217 * 218 * Return: int 219 */ 220 void hif_send_complete_check(struct hif_opaque_softc *hif_ctx, uint8_t pipe, 221 int force) 222 { 223 224 } 225 226