| /* |
| * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| /* |
| * NB: Inappropriate references to "HTC" are used in this (and other) |
| * HIF implementations. HTC is typically the calling layer, but it |
| * theoretically could be some alternative. |
| */ |
| |
| /* |
| * This holds all state needed to process a pending send/recv interrupt. |
| * The information is saved here as soon as the interrupt occurs (thus |
| * allowing the underlying CE to re-use the ring descriptor). The |
| * information here is eventually processed by a completion processing |
| * thread. |
| */ |
| |
| #include <adf_os_atomic.h> /* adf_os_atomic_read */ |
| #include "vos_lock.h" |
| struct HIF_CE_completion_state { |
| struct HIF_CE_completion_state *next; |
| int send_or_recv; |
| struct CE_handle *copyeng; |
| void *ce_context; |
| void *transfer_context; |
| CE_addr_t data; |
| unsigned int nbytes; |
| unsigned int transfer_id; |
| unsigned int flags; |
| }; |
| |
| /* compl_state.send_or_recv */ |
| #define HIF_CE_COMPLETE_FREE 0 |
| #define HIF_CE_COMPLETE_SEND 1 |
| #define HIF_CE_COMPLETE_RECV 2 |
| |
| enum ol_ath_hif_pkt_ecodes { |
| HIF_PIPE_NO_RESOURCE=0 |
| }; |
| |
| struct HIF_CE_state ; |
| |
| #define HIF_CE_COMPLETE_STATE_NUM 18 /* 56 * 18 + 4/8 = 1012/1016 bytes */ |
| struct HIF_CE_completion_state_list { |
| struct HIF_CE_completion_state_list *next; |
| }; |
| /* Per-pipe state. */ |
| struct HIF_CE_pipe_info { |
| /* Handle of underlying Copy Engine */ |
| struct CE_handle *ce_hdl; |
| |
| /* Our pipe number; facilitiates use of pipe_info ptrs. */ |
| A_UINT8 pipe_num; |
| |
| /* Convenience back pointer to HIF_CE_state. */ |
| struct HIF_CE_state *HIF_CE_state; |
| |
| /* Instantaneous number of receive buffers that should be posted */ |
| atomic_t recv_bufs_needed; |
| adf_os_size_t buf_sz; |
| adf_os_spinlock_t recv_bufs_needed_lock; |
| |
| adf_os_spinlock_t completion_freeq_lock; |
| /* Limit the number of outstanding send requests. */ |
| int num_sends_allowed; |
| struct HIF_CE_completion_state_list *completion_space_list; |
| struct HIF_CE_completion_state *completion_freeq_head; |
| struct HIF_CE_completion_state *completion_freeq_tail; |
| /* adding three counts for debugging ring buffer errors */ |
| uint32_t nbuf_alloc_err_count; |
| uint32_t nbuf_dma_err_count; |
| uint32_t nbuf_ce_enqueue_err_count; |
| } ; |
| |
| struct HIF_CE_state { |
| struct hif_pci_softc *sc; |
| A_BOOL started; |
| |
| adf_os_spinlock_t keep_awake_lock; |
| adf_os_spinlock_t suspend_lock; |
| unsigned int keep_awake_count; |
| A_BOOL verified_awake; |
| A_BOOL fake_sleep; |
| adf_os_timer_t sleep_timer; |
| unsigned long sleep_ticks; |
| |
| //struct task_struct *pci_dev_inserted_thread; |
| //struct completion pci_dev_inserted_thread_done; |
| |
| //wait_queue_head_t replenish_recv_buf_waitq; |
| //atomic_t replenish_recv_buf_flag; |
| //struct task_struct *replenish_thread; |
| //struct completion post_recv_bufs_thread_done; |
| |
| adf_os_spinlock_t completion_pendingq_lock; |
| /* Queue of send/recv completions that need to be processed */ |
| struct HIF_CE_completion_state *completion_pendingq_head; |
| struct HIF_CE_completion_state *completion_pendingq_tail; |
| atomic_t fw_event_pending; |
| adf_os_atomic_t hif_thread_idle; |
| |
| //wait_queue_head_t service_waitq; |
| //struct task_struct *compl_thread; |
| //struct completion compl_thread_done; |
| |
| /* Per-pipe state. */ |
| struct HIF_CE_pipe_info pipe_info[CE_COUNT_MAX]; |
| |
| MSG_BASED_HIF_CALLBACKS msg_callbacks_pending; /* to be activated after BMI_DONE */ |
| MSG_BASED_HIF_CALLBACKS msg_callbacks_current; /* current msg callbacks in use */ |
| |
| void *claimedContext; |
| |
| /* Target address used to signal a pending firmware event */ |
| u_int32_t fw_indicator_address; |
| |
| /* Copy Engine used for Diagnostic Accesses */ |
| struct CE_handle *ce_diag; |
| |
| /* For use with A_TARGET_ API */ |
| A_target_id_t targid; |
| }; |
| |
| void priv_start_agc(struct hif_pci_softc *sc); |
| void priv_dump_agc(struct hif_pci_softc *sc); |
| void priv_start_cap_chaninfo(struct hif_pci_softc *sc); |
| void priv_dump_chaninfo(struct hif_pci_softc *sc); |
| void priv_dump_bbwatchdog(struct hif_pci_softc *sc); |
| void hif_dump_pipe_debug_count(HIF_DEVICE *hif_device); |
| |
| #ifdef FEATURE_RUNTIME_PM |
| #include <linux/pm_runtime.h> |
| void hif_pci_runtime_pm_timeout_fn(unsigned long data); |
| void hif_pci_runtime_pm_warn(struct hif_pci_softc *, const char *); |
| void hif_pm_ssr_runtime_allow_suspend(struct hif_pci_softc *, void *); |
| |
| /** |
| * Runtime PM Context for wakelocks |
| */ |
| struct hif_pm_runtime_context { |
| struct list_head list; |
| bool active; |
| uint32_t timeout; |
| const char *name; |
| }; |
| |
| #ifdef WLAN_OPEN_SOURCE |
| static inline int hif_pm_request_resume(struct device *dev) |
| { |
| return pm_request_resume(dev); |
| } |
| static inline int __hif_pm_runtime_get(struct device *dev) |
| { |
| return pm_runtime_get(dev); |
| } |
| |
| static inline int hif_pm_runtime_put_auto(struct device *dev) |
| { |
| return pm_runtime_put_autosuspend(dev); |
| } |
| |
| static inline void hif_pm_runtime_mark_last_busy(struct device *dev) |
| { |
| pm_runtime_mark_last_busy(dev); |
| } |
| |
| static inline int hif_pm_runtime_resume(struct device *dev) |
| { |
| return pm_runtime_resume(dev); |
| } |
| #else |
| static inline int hif_pm_request_resume(struct device *dev) |
| { |
| return vos_pm_runtime_request(dev, CNSS_PM_REQUEST_RESUME); |
| } |
| |
| static inline int __hif_pm_runtime_get(struct device *dev) |
| { |
| return vos_pm_runtime_request(dev, CNSS_PM_RUNTIME_GET); |
| } |
| |
| static inline int hif_pm_runtime_put_auto(struct device *dev) |
| { |
| return vos_pm_runtime_request(dev, CNSS_PM_RUNTIME_PUT_AUTO); |
| } |
| |
| static inline void hif_pm_runtime_mark_last_busy(struct device *dev) |
| { |
| vos_pm_runtime_request(dev, CNSS_PM_RUNTIME_MARK_LAST_BUSY); |
| } |
| static inline int hif_pm_runtime_resume(struct device *dev) |
| { |
| return vos_pm_runtime_request(dev, CNSS_PM_RUNTIME_RESUME); |
| } |
| #endif /* WLAN_OPEN_SOURCE */ |
| #else /* FEATURE_RUNTIME_PM */ |
| static inline void |
| hif_pm_runtime_mark_last_busy(struct device *dev) { } |
| static inline void |
| hif_pci_runtime_pm_warn(struct hif_pci_softc *sc, const char *name) { } |
| static inline void |
| hif_pm_ssr_runtime_allow_suspend(struct hif_pci_softc *sc, void *ctx) { } |
| #endif |
| |
| #define CE_HTT_T2H_MSG 1 |
| #define CE_HTT_H2T_MSG 4 |