提交 cf614297 编写于 作者: E Emmanuel Grumbach 提交者: Wey-Yi Guy

iwlwifi: consolidate the start_device flow

Now there is only one transport function that launch a specific fw:
trans_ops->start_fw. This one replaces trans_ops->start_device and
trans_ops->kick_nic. The code that actually loads the fw to the
device has been moved to the transport specific code.
Signed-off-by: NEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: NWey-Yi Guy <wey-yi.w.guy@intel.com>
上级 d48e2074
...@@ -1130,11 +1130,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -1130,11 +1130,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
isr_stats->tx++; isr_stats->tx++;
handled |= CSR_INT_BIT_FH_TX; handled |= CSR_INT_BIT_FH_TX;
/* Wake up uCode load routine, now that load is complete */ /* Wake up uCode load routine, now that load is complete */
#ifdef CONFIG_IWLWIFI_IDI
trans->shrd->trans->ucode_write_complete = 1;
#else
trans->ucode_write_complete = 1; trans->ucode_write_complete = 1;
#endif
wake_up(&trans->shrd->wait_command_queue); wake_up(&trans->shrd->wait_command_queue);
} }
......
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#include <linux/pci-aspm.h> #include <linux/pci-aspm.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/sched.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/gfp.h> #include <linux/gfp.h>
...@@ -895,7 +896,79 @@ static const u8 iwlagn_pan_ac_to_queue[] = { ...@@ -895,7 +896,79 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
7, 6, 5, 4, 7, 6, 5, 4,
}; };
static int iwl_trans_pcie_start_device(struct iwl_trans *trans) /*
* ucode
*/
static int iwl_load_section(struct iwl_trans *trans, const char *name,
struct fw_desc *image, u32 dst_addr)
{
dma_addr_t phy_addr = image->p_addr;
u32 byte_cnt = image->len;
int ret;
trans->ucode_write_complete = 0;
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
iwl_write_direct32(trans,
FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr);
iwl_write_direct32(trans,
FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
iwl_write_direct32(trans,
FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
(iwl_get_dma_hi_addr(phy_addr)
<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name);
ret = wait_event_timeout(trans->shrd->wait_command_queue,
trans->ucode_write_complete, 5 * HZ);
if (!ret) {
IWL_ERR(trans, "Could not load the %s uCode section\n",
name);
return -ETIMEDOUT;
}
return 0;
}
static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image)
{
int ret = 0;
ret = iwl_load_section(trans, "INST", &image->code,
IWLAGN_RTC_INST_LOWER_BOUND);
if (ret)
return ret;
ret = iwl_load_section(trans, "DATA", &image->data,
IWLAGN_RTC_DATA_LOWER_BOUND);
if (ret)
return ret;
/* Remove all resets to allow NIC to operate */
iwl_write32(trans, CSR_RESET, 0);
return 0;
}
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
{ {
int ret; int ret;
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie =
...@@ -951,6 +1024,9 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans) ...@@ -951,6 +1024,9 @@ static int iwl_trans_pcie_start_device(struct iwl_trans *trans)
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
iwl_load_given_ucode(trans, fw);
return 0; return 0;
} }
...@@ -1353,12 +1429,6 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, ...@@ -1353,12 +1429,6 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
return 0; return 0;
} }
static void iwl_trans_pcie_kick_nic(struct iwl_trans *trans)
{
/* Remove all resets to allow NIC to operate */
iwl_write32(trans, CSR_RESET, 0);
}
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = struct iwl_trans_pcie *trans_pcie =
...@@ -2086,7 +2156,7 @@ const struct iwl_trans_ops trans_ops_pcie = { ...@@ -2086,7 +2156,7 @@ const struct iwl_trans_ops trans_ops_pcie = {
.start_hw = iwl_trans_pcie_start_hw, .start_hw = iwl_trans_pcie_start_hw,
.stop_hw = iwl_trans_pcie_stop_hw, .stop_hw = iwl_trans_pcie_stop_hw,
.fw_alive = iwl_trans_pcie_fw_alive, .fw_alive = iwl_trans_pcie_fw_alive,
.start_device = iwl_trans_pcie_start_device, .start_fw = iwl_trans_pcie_start_fw,
.stop_device = iwl_trans_pcie_stop_device, .stop_device = iwl_trans_pcie_stop_device,
.wake_any_queue = iwl_trans_pcie_wake_any_queue, .wake_any_queue = iwl_trans_pcie_wake_any_queue,
...@@ -2100,8 +2170,6 @@ const struct iwl_trans_ops trans_ops_pcie = { ...@@ -2100,8 +2170,6 @@ const struct iwl_trans_ops trans_ops_pcie = {
.tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc, .tx_agg_alloc = iwl_trans_pcie_tx_agg_alloc,
.tx_agg_setup = iwl_trans_pcie_tx_agg_setup, .tx_agg_setup = iwl_trans_pcie_tx_agg_setup,
.kick_nic = iwl_trans_pcie_kick_nic,
.free = iwl_trans_pcie_free, .free = iwl_trans_pcie_free,
.stop_queue = iwl_trans_pcie_stop_queue, .stop_queue = iwl_trans_pcie_stop_queue,
......
...@@ -131,13 +131,25 @@ struct iwl_host_cmd { ...@@ -131,13 +131,25 @@ struct iwl_host_cmd {
u8 id; u8 id;
}; };
/* one for each uCode image (inst/data, boot/init/runtime) */
struct fw_desc {
dma_addr_t p_addr; /* hardware address */
void *v_addr; /* software address */
u32 len; /* size in bytes */
};
struct fw_img {
struct fw_desc code; /* firmware code image */
struct fw_desc data; /* firmware data image */
};
/** /**
* struct iwl_trans_ops - transport specific operations * struct iwl_trans_ops - transport specific operations
* @start_hw: starts the HW- from that point on, the HW can send interrupts * @start_hw: starts the HW- from that point on, the HW can send interrupts
* @stop_hw: stops the HW- from that point on, the HW will be in low power but * @stop_hw: stops the HW- from that point on, the HW will be in low power but
* will still issue interrupt if the HW RF kill is triggered. * will still issue interrupt if the HW RF kill is triggered.
* @start_device: allocates and inits all the resources for the transport * @start_fw: allocates and inits all the resources for the transport
* layer. * layer. Also kick a fw image. This handler may sleep.
* @fw_alive: called when the fw sends alive notification * @fw_alive: called when the fw sends alive notification
* @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
* @stop_device:stops the whole device (embedded CPU put to reset) * @stop_device:stops the whole device (embedded CPU put to reset)
...@@ -148,7 +160,6 @@ struct iwl_host_cmd { ...@@ -148,7 +160,6 @@ struct iwl_host_cmd {
* @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is * @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
* ready and a successful ADDBA response has been received. * ready and a successful ADDBA response has been received.
* @tx_agg_disable: de-configure a Tx queue to send AMPDUs * @tx_agg_disable: de-configure a Tx queue to send AMPDUs
* @kick_nic: remove the RESET from the embedded CPU and let it run
* @free: release all the ressource for the transport layer itself such as * @free: release all the ressource for the transport layer itself such as
* irq, tasklet etc... * irq, tasklet etc...
* @stop_queue: stop a specific queue * @stop_queue: stop a specific queue
...@@ -166,7 +177,7 @@ struct iwl_trans_ops { ...@@ -166,7 +177,7 @@ struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans); int (*start_hw)(struct iwl_trans *iwl_trans);
void (*stop_hw)(struct iwl_trans *iwl_trans); void (*stop_hw)(struct iwl_trans *iwl_trans);
int (*start_device)(struct iwl_trans *trans); int (*start_fw)(struct iwl_trans *trans, struct fw_img *fw);
void (*fw_alive)(struct iwl_trans *trans); void (*fw_alive)(struct iwl_trans *trans);
void (*stop_device)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans);
...@@ -191,8 +202,6 @@ struct iwl_trans_ops { ...@@ -191,8 +202,6 @@ struct iwl_trans_ops {
enum iwl_rxon_context_id ctx, int sta_id, int tid, enum iwl_rxon_context_id ctx, int sta_id, int tid,
int frame_limit, u16 ssn); int frame_limit, u16 ssn);
void (*kick_nic)(struct iwl_trans *trans);
void (*free)(struct iwl_trans *trans); void (*free)(struct iwl_trans *trans);
void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg); void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg);
...@@ -209,18 +218,6 @@ struct iwl_trans_ops { ...@@ -209,18 +218,6 @@ struct iwl_trans_ops {
u32 (*read32)(struct iwl_trans *trans, u32 ofs); u32 (*read32)(struct iwl_trans *trans, u32 ofs);
}; };
/* one for each uCode image (inst/data, boot/init/runtime) */
struct fw_desc {
dma_addr_t p_addr; /* hardware address */
void *v_addr; /* software address */
u32 len; /* size in bytes */
};
struct fw_img {
struct fw_desc code; /* firmware code image */
struct fw_desc data; /* firmware data image */
};
/* Opaque calibration results */ /* Opaque calibration results */
struct iwl_calib_result { struct iwl_calib_result {
struct list_head list; struct list_head list;
...@@ -284,9 +281,11 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans) ...@@ -284,9 +281,11 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
trans->ops->fw_alive(trans); trans->ops->fw_alive(trans);
} }
static inline int iwl_trans_start_device(struct iwl_trans *trans) static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
{ {
return trans->ops->start_device(trans); might_sleep();
return trans->ops->start_fw(trans, fw);
} }
static inline void iwl_trans_stop_device(struct iwl_trans *trans) static inline void iwl_trans_stop_device(struct iwl_trans *trans)
...@@ -347,11 +346,6 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans, ...@@ -347,11 +346,6 @@ static inline void iwl_trans_tx_agg_setup(struct iwl_trans *trans,
trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn); trans->ops->tx_agg_setup(trans, ctx, sta_id, tid, frame_limit, ssn);
} }
static inline void iwl_trans_kick_nic(struct iwl_trans *trans)
{
trans->ops->kick_nic(trans);
}
static inline void iwl_trans_free(struct iwl_trans *trans) static inline void iwl_trans_free(struct iwl_trans *trans)
{ {
trans->ops->free(trans); trans->ops->free(trans);
......
...@@ -120,58 +120,6 @@ int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc, ...@@ -120,58 +120,6 @@ int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
return 0; return 0;
} }
/*
* ucode
*/
static int iwl_load_section(struct iwl_trans *trans, const char *name,
struct fw_desc *image, u32 dst_addr)
{
dma_addr_t phy_addr = image->p_addr;
u32 byte_cnt = image->len;
int ret;
trans->ucode_write_complete = 0;
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
iwl_write_direct32(trans,
FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr);
iwl_write_direct32(trans,
FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL),
phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK);
iwl_write_direct32(trans,
FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
(iwl_get_dma_hi_addr(phy_addr)
<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL),
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM |
1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX |
FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID);
iwl_write_direct32(trans,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name);
ret = wait_event_timeout(trans->shrd->wait_command_queue,
trans->ucode_write_complete, 5 * HZ);
if (!ret) {
IWL_ERR(trans, "Could not load the %s uCode section\n",
name);
return -ETIMEDOUT;
}
return 0;
}
static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
enum iwl_ucode_type ucode_type) enum iwl_ucode_type ucode_type)
{ {
...@@ -188,28 +136,6 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans, ...@@ -188,28 +136,6 @@ static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
return NULL; return NULL;
} }
static int iwl_load_given_ucode(struct iwl_trans *trans,
enum iwl_ucode_type ucode_type)
{
int ret = 0;
struct fw_img *image = iwl_get_ucode_image(trans, ucode_type);
if (!image) {
IWL_ERR(trans, "Invalid ucode requested (%d)\n",
ucode_type);
return -EINVAL;
}
ret = iwl_load_section(trans, "INST", &image->code,
IWLAGN_RTC_INST_LOWER_BOUND);
if (ret)
return ret;
return iwl_load_section(trans, "DATA", &image->data,
IWLAGN_RTC_DATA_LOWER_BOUND);
}
/* /*
* Calibration * Calibration
*/ */
...@@ -646,28 +572,27 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans, ...@@ -646,28 +572,27 @@ int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
{ {
struct iwl_notification_wait alive_wait; struct iwl_notification_wait alive_wait;
struct iwl_alive_data alive_data; struct iwl_alive_data alive_data;
struct fw_img *fw;
int ret; int ret;
enum iwl_ucode_type old_type; enum iwl_ucode_type old_type;
ret = iwl_trans_start_device(trans);
if (ret)
return ret;
iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE, iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE,
iwl_alive_fn, &alive_data); iwl_alive_fn, &alive_data);
old_type = trans->shrd->ucode_type; old_type = trans->shrd->ucode_type;
trans->shrd->ucode_type = ucode_type; trans->shrd->ucode_type = ucode_type;
fw = iwl_get_ucode_image(trans, ucode_type);
ret = iwl_load_given_ucode(trans, ucode_type); if (!fw)
return -EINVAL;
ret = iwl_trans_start_fw(trans, fw);
if (ret) { if (ret) {
trans->shrd->ucode_type = old_type; trans->shrd->ucode_type = old_type;
iwl_remove_notification(trans->shrd, &alive_wait); iwl_remove_notification(trans->shrd, &alive_wait);
return ret; return ret;
} }
iwl_trans_kick_nic(trans);
/* /*
* Some things may run in the background now, but we * Some things may run in the background now, but we
* just wait for the ALIVE notification here. * just wait for the ALIVE notification here.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册