qcacmn: Introduce hif_bus_configure

Need to make hif_enable bus agnostic

Change-Id: If9bff722b32afb46efdf854bfbaa08304d77e780
CRs-Fixed: 967250
This commit is contained in:
Houston Hoffman
2016-03-14 21:11:24 -07:00
committed by Vishwajith Upendra
parent 70f8b6e32c
commit 108da40074
5 changed files with 249 additions and 104 deletions

View File

@@ -1827,9 +1827,9 @@ done:
* This function passes the con_mode and CE configuration to
* platform driver to enable wlan.
*
* Return: void
* Return: linux error code
*/
static int hif_wlan_enable(struct hif_softc *scn)
int hif_wlan_enable(struct hif_softc *scn)
{
struct icnss_wlan_enable_cfg cfg;
enum icnss_driver_mode mode;
@@ -1855,26 +1855,15 @@ static int hif_wlan_enable(struct hif_softc *scn)
return icnss_wlan_enable(&cfg, mode, QWLAN_VERSIONSTR);
}
/*
* Called from PCI layer whenever a new PCI device is probed.
* Initializes per-device HIF state and notifies the main
* driver that a new HIF device is present.
/**
* hif_ce_prepare_config() - load the correct static tables.
* @scn: hif context
*
* Epping uses different static attribute tables than mission mode.
*/
int hif_config_ce(struct hif_softc *scn)
void hif_ce_prepare_config(struct hif_softc *scn)
{
struct HIF_CE_pipe_info *pipe_info;
int pipe_num;
uint32_t mode = hif_get_conparam(scn);
#ifdef ADRASTEA_SHADOW_REGISTERS
int i;
#endif
QDF_STATUS rv = QDF_STATUS_SUCCESS;
int ret;
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
struct icnss_soc_info soc_info;
struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl);
/* if epping is enabled we need to use the epping configuration. */
if (WLAN_IS_EPPING_ENABLED(mode)) {
if (WLAN_IS_EPPING_IRQ(mode))
@@ -1888,28 +1877,86 @@ int hif_config_ce(struct hif_softc *scn)
target_service_to_ce_map_sz =
sizeof(target_service_to_ce_map_wlan_epping);
}
}
ret = hif_wlan_enable(scn);
if (ret) {
HIF_ERROR("%s: hif_wlan_enable error = %d", __func__, ret);
return QDF_STATUS_NOT_INITIALIZED;
}
scn->notice_send = true;
qdf_mem_zero(&soc_info, sizeof(soc_info));
ret = icnss_get_soc_info(scn, &soc_info);
if (ret < 0) {
HIF_ERROR("%s: icnss_get_soc_info error = %d", __func__, ret);
return QDF_STATUS_NOT_INITIALIZED;
}
scn->mem = soc_info.v_addr;
scn->mem_pa = soc_info.p_addr;
tgt_info->soc_version = soc_info.version;
/**
* hif_ce_open() - do ce specific allocations
* @hif_sc: pointer to hif context
*
* return: 0 for success or QDF_STATUS_E_NOMEM
*/
QDF_STATUS hif_ce_open(struct hif_softc *hif_sc)
{
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc);
qdf_spinlock_create(&hif_state->keep_awake_lock);
return QDF_STATUS_SUCCESS;
}
/**
* hif_ce_close() - do ce specific free
* @hif_sc: pointer to hif context
*/
void hif_ce_close(struct hif_softc *hif_sc)
{
}
/**
* hif_unconfig_ce() - ensure resources from hif_config_ce are freed
* @hif_sc: hif context
*
* uses state variables to support cleaning up when hif_config_ce fails.
*/
void hif_unconfig_ce(struct hif_softc *hif_sc)
{
int pipe_num;
struct HIF_CE_pipe_info *pipe_info;
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc);
for (pipe_num = 0; pipe_num < hif_sc->ce_count; pipe_num++) {
pipe_info = &hif_state->pipe_info[pipe_num];
if (pipe_info->ce_hdl) {
ce_unregister_irq(hif_state, (1 << pipe_num));
hif_sc->request_irq_done = false;
ce_fini(pipe_info->ce_hdl);
pipe_info->ce_hdl = NULL;
pipe_info->buf_sz = 0;
}
}
if (hif_state->sleep_timer_init) {
qdf_timer_stop(&hif_state->sleep_timer);
qdf_timer_free(&hif_state->sleep_timer);
hif_state->sleep_timer_init = false;
}
if (hif_sc->athdiag_procfs_inited) {
athdiag_procfs_remove();
hif_sc->athdiag_procfs_inited = false;
}
}
/**
* hif_config_ce() - configure copy engines
* @scn: hif context
*
* Prepares fw, copy engine hardware and host sw according
* to the attributes selected by hif_ce_prepare_config.
*
* also calls athdiag_procfs_init
*
* return: 0 for success nonzero for failure.
*/
int hif_config_ce(struct hif_softc *scn)
{
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
struct HIF_CE_pipe_info *pipe_info;
int pipe_num;
#ifdef ADRASTEA_SHADOW_REGISTERS
int i;
#endif
QDF_STATUS rv = QDF_STATUS_SUCCESS;
scn->notice_send = true;
hif_state->keep_awake_count = 0;
@@ -1920,6 +1967,7 @@ int hif_config_ce(struct hif_softc *scn)
QDF_TIMER_TYPE_WAKE_APPS);
hif_state->sleep_timer_init = true;
hif_state->fw_indicator_address = FW_INDICATOR_ADDRESS;
#ifdef HIF_PCI
#if CONFIG_ATH_PCIE_MAX_PERF || CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD
/* Force AWAKE forever/till the driver is loaded */
@@ -1932,7 +1980,6 @@ int hif_config_ce(struct hif_softc *scn)
/* During CE initializtion */
scn->ce_count = HOST_CE_COUNT;
A_TARGET_ACCESS_LIKELY(scn);
for (pipe_num = 0; pipe_num < scn->ce_count; pipe_num++) {
struct CE_attr *attr;
@@ -1975,32 +2022,9 @@ int hif_config_ce(struct hif_softc *scn)
}
scn->athdiag_procfs_inited = true;
/*
* Initially, establish CE completion handlers for use with BMI.
* These are overwritten with generic handlers after we exit BMI phase.
*/
pipe_info = &hif_state->pipe_info[BMI_CE_NUM_TO_TARG];
#ifdef HIF_PCI
ce_send_cb_register(
pipe_info->ce_hdl, hif_bmi_send_done, pipe_info, 0);
#ifndef BMI_RSP_POLLING
pipe_info = &hif_state->pipe_info[BMI_CE_NUM_TO_HOST];
ce_recv_cb_register(
pipe_info->ce_hdl, hif_bmi_recv_data, pipe_info, 0);
#endif
#endif
HIF_INFO_MED("%s: ce_init done", __func__);
rv = hif_set_hia(scn);
HIF_INFO_MED("%s: hif_set_hia done", __func__);
A_TARGET_ACCESS_UNLIKELY(scn);
if (rv != QDF_STATUS_SUCCESS)
goto err;
else
init_tasklet_workers(hif_hdl);
init_tasklet_workers(hif_hdl);
HIF_TRACE("%s: X, ret = %d\n", __func__, rv);
@@ -2013,38 +2037,15 @@ int hif_config_ce(struct hif_softc *scn)
}
#endif
return rv != QDF_STATUS_SUCCESS;
err:
/* Failure, so clean up */
for (pipe_num = 0; pipe_num < scn->ce_count; pipe_num++) {
pipe_info = &hif_state->pipe_info[pipe_num];
if (pipe_info->ce_hdl) {
ce_unregister_irq(hif_state, (1 << pipe_num));
scn->request_irq_done = false;
ce_fini(pipe_info->ce_hdl);
pipe_info->ce_hdl = NULL;
pipe_info->buf_sz = 0;
}
}
if (hif_state->sleep_timer_init) {
qdf_timer_stop(&hif_state->sleep_timer);
qdf_timer_free(&hif_state->sleep_timer);
hif_state->sleep_timer_init = false;
}
athdiag_procfs_remove();
scn->athdiag_procfs_inited = false;
hif_unconfig_ce(scn);
HIF_TRACE("%s: X, ret = %d\n", __func__, rv);
return QDF_STATUS_SUCCESS != QDF_STATUS_E_FAILURE;
}
#ifdef IPA_OFFLOAD
/**
* hif_ipa_get_ce_resource() - get uc resource on hif

View File

@@ -556,12 +556,13 @@ QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev,
if (ADRASTEA_BU)
hif_vote_link_up(hif_ctx);
if (hif_config_ce(scn)) {
if (hif_bus_configure(scn)) {
HIF_ERROR("%s: Target probe failed.", __func__);
hif_disable_bus(scn);
status = QDF_STATUS_E_FAILURE;
return status;
}
/*
* Flag to avoid potential unallocated memory access from MSI
* interrupt handler which could get scheduled as soon as MSI
@@ -570,15 +571,6 @@ QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev,
* in interrupt handlers, is allocated.
*/
#ifdef HIF_PCI
status = hif_configure_irq(scn);
if (status < 0) {
HIF_ERROR("%s: ERROR - configure_IRQ_and_CE failed, status = %d",
__func__, status);
return QDF_STATUS_E_FAILURE;
}
#endif
scn->hif_init_done = true;
HIF_TRACE("%s: X OK", __func__);

View File

@@ -153,7 +153,15 @@ void hif_dump_pipe_debug_count(struct hif_softc *scn);
bool hif_target_forced_awake(struct hif_softc *scn);
bool hif_max_num_receives_reached(struct hif_softc *scn, unsigned int count);
int hif_bus_configure(struct hif_softc *scn);
int hif_config_ce(struct hif_softc *scn);
void hif_unconfig_ce(struct hif_softc *scn);
void hif_ce_prepare_config(struct hif_softc *scn);
int hif_set_hia(struct hif_softc *scn);
QDF_STATUS hif_ce_open(struct hif_softc *scn);
void hif_ce_close(struct hif_softc *scn);
int hif_wlan_enable(struct hif_softc *scn);
void hif_wlan_disable(struct hif_softc *scn);
int athdiag_procfs_init(void *scn);
void athdiag_procfs_remove(void);
/* routine to modify the initial buffer count to be allocated on an os

View File

@@ -41,6 +41,7 @@
#include "ce_internal.h"
#include "ce_reg.h"
#include "bmi_msg.h" /* TARGET_TYPE_ */
#include "ce_bmi.h"
#include "regtable.h"
#include "ol_fw.h"
#include <linux/debugfs.h>
@@ -1202,7 +1203,92 @@ QDF_STATUS hif_bus_open(struct hif_softc *ol_sc, enum qdf_bus_type bus_type)
qdf_spinlock_create(&sc->irq_lock);
return QDF_STATUS_SUCCESS;
return hif_ce_open(ol_sc);
}
#ifdef BMI_RSP_POLLING
#define BMI_RSP_CB_REGISTER 0
#else
#define BMI_RSP_CB_REGISTER 1
#endif
/**
* hif_register_bmi_callbacks() - register bmi callbacks
* @hif_sc: hif context
*
* Bmi phase uses different copy complete callbacks than mission mode.
*/
static void hif_register_bmi_callbacks(struct hif_softc *hif_sc)
{
struct HIF_CE_pipe_info *pipe_info;
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc);
/*
* Initially, establish CE completion handlers for use with BMI.
* These are overwritten with generic handlers after we exit BMI phase.
*/
pipe_info = &hif_state->pipe_info[BMI_CE_NUM_TO_TARG];
ce_send_cb_register(pipe_info->ce_hdl, hif_bmi_send_done, pipe_info, 0);
if (BMI_RSP_CB_REGISTER) {
pipe_info = &hif_state->pipe_info[BMI_CE_NUM_TO_HOST];
ce_recv_cb_register(
pipe_info->ce_hdl, hif_bmi_recv_data, pipe_info, 0);
}
}
/**
* hif_bus_configure() - configure the pcie bus
* @hif_sc: pointer to the hif context.
*
* return: 0 for success. nonzero for failure.
*/
int hif_bus_configure(struct hif_softc *hif_sc)
{
int status = 0;
hif_ce_prepare_config(hif_sc);
if (ADRASTEA_BU) {
status = hif_wlan_enable(hif_sc);
if (status) {
HIF_ERROR("%s: hif_wlan_enable error = %d",
__func__, status);
return status;
}
}
A_TARGET_ACCESS_LIKELY(hif_sc);
status = hif_config_ce(hif_sc);
if (status)
goto disable_wlan;
status = hif_set_hia(hif_sc);
if (status)
goto unconfig_ce;
HIF_INFO_MED("%s: hif_set_hia done", __func__);
hif_register_bmi_callbacks(hif_sc);
status = hif_configure_irq(hif_sc);
if (status < 0)
goto unconfig_ce;
A_TARGET_ACCESS_UNLIKELY(hif_sc);
return status;
unconfig_ce:
hif_unconfig_ce(hif_sc);
disable_wlan:
A_TARGET_ACCESS_UNLIKELY(hif_sc);
if (ADRASTEA_BU)
hif_wlan_disable(hif_sc);
HIF_ERROR("%s: failed, status = %d", __func__, status);
return status;
}
/**
@@ -1210,11 +1296,13 @@ QDF_STATUS hif_bus_open(struct hif_softc *ol_sc, enum qdf_bus_type bus_type)
*
* Return: n/a
*/
void hif_bus_close(struct hif_softc *ol_sc)
void hif_bus_close(struct hif_softc *hif_sc)
{
struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(ol_sc);
struct hif_pci_softc *hif_pci_sc = HIF_GET_PCI_SOFTC(hif_sc);
hif_pm_runtime_close(sc);
hif_pm_runtime_close(hif_pci_sc);
hif_ce_close(hif_sc);
}
#define BAR_NUM 0
@@ -1952,7 +2040,7 @@ static void hif_runtime_pm_set_state_suspended(struct hif_softc *scn)
static inline struct hif_pci_softc *get_sc(void *hif_ctx)
{
struct hif_pci_softc *scn = HIF_GET_PCI_SOFTC(hif_ctx)
struct hif_pci_softc *scn = HIF_GET_PCI_SOFTC(hif_ctx);
if (NULL == scn) {
HIF_ERROR("%s: Could not disable ASPM scn is null",

View File

@@ -93,7 +93,7 @@ void hif_reset_soc(struct hif_opaque_softc *hif_ctx)
*/
void hif_disable_isr(struct hif_opaque_softc *hif_ctx)
{
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx)
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
hif_nointrs(scn);
ce_tasklet_kill(scn);
@@ -124,7 +124,7 @@ static void hif_dump_snoc_registers(struct hif_softc *scn)
int hif_dump_registers(struct hif_opaque_softc *hif_ctx)
{
int status;
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx)
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
status = hif_dump_ce_registers(scn);
if (status)
@@ -186,6 +186,7 @@ void hif_disable_aspm(struct hif_opaque_softc *hif_ctx)
*/
void hif_bus_close(struct hif_softc *scn)
{
hif_ce_close(scn);
}
/**
@@ -206,9 +207,64 @@ int hif_bus_get_context_size(void)
*/
QDF_STATUS hif_bus_open(struct hif_softc *scn, enum qdf_bus_type bus_type)
{
return hif_ce_open(scn);
}
/**
* hif_snoc_get_soc_info() - populates scn with hw info
*
* fills in the virtual and physical base address as well as
* soc version info.
*
* return 0 or QDF_STATUS_E_FAILURE
*/
static QDF_STATUS hif_snoc_get_soc_info(struct hif_softc *scn)
{
int ret;
struct icnss_soc_info soc_info;
cdf_mem_zero(&soc_info, sizeof(soc_info));
ret = icnss_get_soc_info(&soc_info);
if (ret < 0) {
HIF_ERROR("%s: icnss_get_soc_info error = %d", __func__, ret);
return QDF_STATUS_E_FAILURE;
}
scn->mem = soc_info.v_addr;
scn->mem_pa = soc_info.p_addr;
return QDF_STATUS_SUCCESS;
}
/**
* hif_bus_configure() - configure the snoc bus
* @scn: pointer to the hif context.
*
* return: 0 for success. nonzero for failure.
*/
int hif_bus_configure(struct hif_softc *scn)
{
int ret;
ret = hif_snoc_get_soc_info(scn);
if (ret)
return ret;
hif_ce_prepare_config(scn);
ret = hif_wlan_enable(scn);
if (ret) {
HIF_ERROR("%s: hif_wlan_enable error = %d",
__func__, ret);
return ret;
}
ret = hif_config_ce(scn);
if (ret)
hif_wlan_disable(scn);
return ret;
}
/**
* hif_get_target_type(): Get the target type
*