wlcore: Propagate errors from wl1271_write
Propagate errors from wl1271_write and request for recovery when appropriate. Also rename prefixes of wlcore functions which their prototypes had to be changed. Signed-off-by: Ido Yariv <ido@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
This commit is contained in:
parent
045b9b5f41
commit
eb96f841b9
12 changed files with 102 additions and 46 deletions
|
@ -598,8 +598,10 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = {
|
|||
#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
|
||||
#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin"
|
||||
|
||||
static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
|
||||
static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (wl->chip.id != CHIP_ID_1283_PG20) {
|
||||
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
|
||||
struct wl127x_rx_mem_pool_addr rx_mem_addr;
|
||||
|
@ -616,9 +618,13 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
|
|||
|
||||
rx_mem_addr.addr_extra = rx_mem_addr.addr + 4;
|
||||
|
||||
wl1271_write(wl, WL1271_SLV_REG_DATA,
|
||||
&rx_mem_addr, sizeof(rx_mem_addr), false);
|
||||
ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr,
|
||||
sizeof(rx_mem_addr), false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl12xx_identify_chip(struct wl1271 *wl)
|
||||
|
@ -1073,11 +1079,18 @@ static int wl12xx_boot(struct wl1271 *wl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
|
||||
static int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
wl1271_write(wl, cmd_box_addr, buf, len, false);
|
||||
int ret;
|
||||
|
||||
ret = wlcore_write(wl, cmd_box_addr, buf, len, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wl12xx_ack_event(struct wl1271 *wl)
|
||||
|
|
|
@ -720,10 +720,11 @@ static void wl18xx_pre_upload(struct wl1271 *wl)
|
|||
tmp = wl1271_read32(wl, WL18XX_SCR_PAD2);
|
||||
}
|
||||
|
||||
static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
|
||||
static int wl18xx_set_mac_and_phy(struct wl1271 *wl)
|
||||
{
|
||||
struct wl18xx_priv *priv = wl->priv;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
/* the parameters struct is smaller for PG1 */
|
||||
if (wl->chip.id == CHIP_ID_185x_PG10)
|
||||
|
@ -732,8 +733,10 @@ static void wl18xx_set_mac_and_phy(struct wl1271 *wl)
|
|||
len = sizeof(struct wl18xx_mac_and_phy_params);
|
||||
|
||||
wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
|
||||
wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len,
|
||||
false);
|
||||
ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy,
|
||||
len, false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wl18xx_enable_interrupts(struct wl1271 *wl)
|
||||
|
@ -769,7 +772,9 @@ static int wl18xx_boot(struct wl1271 *wl)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wl18xx_set_mac_and_phy(wl);
|
||||
ret = wl18xx_set_mac_and_phy(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wlcore_boot_run_firmware(wl);
|
||||
if (ret < 0)
|
||||
|
@ -781,7 +786,7 @@ static int wl18xx_boot(struct wl1271 *wl)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
|
||||
static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
|
||||
void *buf, size_t len)
|
||||
{
|
||||
struct wl18xx_priv *priv = wl->priv;
|
||||
|
@ -789,8 +794,8 @@ static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
|
|||
memcpy(priv->cmd_buf, buf, len);
|
||||
memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len);
|
||||
|
||||
wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE,
|
||||
false);
|
||||
return wlcore_write(wl, cmd_box_addr, priv->cmd_buf,
|
||||
WL18XX_CMD_MAX_SIZE, false);
|
||||
}
|
||||
|
||||
static void wl18xx_ack_event(struct wl1271 *wl)
|
||||
|
|
|
@ -111,6 +111,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
|||
struct wlcore_partition_set partition;
|
||||
int addr, chunk_num, partition_limit;
|
||||
u8 *p, *chunk;
|
||||
int ret;
|
||||
|
||||
/* whal_FwCtrl_LoadFwImageSm() */
|
||||
|
||||
|
@ -155,7 +156,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
|||
memcpy(chunk, p, CHUNK_SIZE);
|
||||
wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
|
||||
p, addr);
|
||||
wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
|
||||
ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE, false);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
chunk_num++;
|
||||
}
|
||||
|
@ -166,10 +169,11 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
|||
memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
|
||||
wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
|
||||
fw_data_len % CHUNK_SIZE, p, addr);
|
||||
wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
|
||||
ret = wlcore_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
|
||||
|
||||
out:
|
||||
kfree(chunk);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wlcore_boot_upload_firmware(struct wl1271 *wl)
|
||||
|
@ -212,6 +216,7 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
|
|||
int i;
|
||||
u32 dest_addr, val;
|
||||
u8 *nvs_ptr, *nvs_aligned;
|
||||
int ret;
|
||||
|
||||
if (wl->nvs == NULL) {
|
||||
wl1271_error("NVS file is needed during boot");
|
||||
|
@ -343,11 +348,11 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
|
|||
return -ENOMEM;
|
||||
|
||||
/* And finally we upload the NVS tables */
|
||||
wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS,
|
||||
nvs_aligned, nvs_len, false);
|
||||
ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len,
|
||||
false);
|
||||
|
||||
kfree(nvs_aligned);
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
out_badnvs:
|
||||
wl1271_error("nvs data is malformed");
|
||||
|
|
|
@ -65,13 +65,17 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
|||
WARN_ON(len % 4 != 0);
|
||||
WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags));
|
||||
|
||||
wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
|
||||
ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* TODO: we just need this because one bit is in a different
|
||||
* place. Is there any better way?
|
||||
*/
|
||||
wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len);
|
||||
ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
|
||||
|
||||
|
@ -1764,7 +1768,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
|
|||
return -EINVAL;
|
||||
|
||||
/* flush all pending packets */
|
||||
wl1271_tx_work_locked(wl);
|
||||
ret = wlcore_tx_work_locked(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (test_bit(wlvif->dev_role_id, wl->roc_map)) {
|
||||
ret = wl12xx_croc(wl, wlvif->dev_role_id);
|
||||
|
|
|
@ -105,6 +105,7 @@ static int wl1271_event_process(struct wl1271 *wl)
|
|||
u32 vector;
|
||||
bool disconnect_sta = false;
|
||||
unsigned long sta_bitmap = 0;
|
||||
int ret;
|
||||
|
||||
wl1271_event_mbox_dump(mbox);
|
||||
|
||||
|
@ -228,7 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl)
|
|||
|
||||
if ((vector & DUMMY_PACKET_EVENT_ID)) {
|
||||
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
|
||||
wl1271_tx_dummy_packet(wl);
|
||||
ret = wl1271_tx_dummy_packet(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -65,11 +65,13 @@ wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
|
|||
return wl->ops->get_rx_buf_align(wl, rx_desc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline int
|
||||
wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
|
||||
{
|
||||
if (wl->ops->prepare_read)
|
||||
wl->ops->prepare_read(wl, rx_desc, len);
|
||||
return wl->ops->prepare_read(wl, rx_desc, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
|
|
|
@ -102,20 +102,20 @@ static inline int wlcore_read(struct wl1271 *wl, int addr, void *buf,
|
|||
return wlcore_raw_read(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
static inline int wlcore_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wlcore_translate_addr(wl, addr);
|
||||
|
||||
wlcore_raw_write(wl, physical, buf, len, fixed);
|
||||
return wlcore_raw_write(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf,
|
||||
size_t len, bool fixed)
|
||||
static inline int wlcore_write_data(struct wl1271 *wl, int reg, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
wl1271_write(wl, wl->rtable[reg], buf, len, fixed);
|
||||
return wlcore_write(wl, wl->rtable[reg], buf, len, fixed);
|
||||
}
|
||||
|
||||
static inline int wlcore_read_data(struct wl1271 *wl, int reg, void *buf,
|
||||
|
|
|
@ -587,7 +587,11 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
|
|||
* In order to avoid starvation of the TX path,
|
||||
* call the work function directly.
|
||||
*/
|
||||
wl1271_tx_work_locked(wl);
|
||||
ret = wlcore_tx_work_locked(wl);
|
||||
if (ret < 0) {
|
||||
wl12xx_queue_recovery_work(wl);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
spin_unlock_irqrestore(&wl->wl_lock, flags);
|
||||
}
|
||||
|
@ -1211,7 +1215,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl)
|
|||
|
||||
/* The FW is low on RX memory blocks, so send the dummy packet asap */
|
||||
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
|
||||
wl1271_tx_work_locked(wl);
|
||||
return wlcore_tx_work_locked(wl);
|
||||
|
||||
/*
|
||||
* If the FW TX is busy, TX work will be scheduled by the threaded
|
||||
|
@ -2513,7 +2517,10 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
|
|||
(wlvif->channel != channel) ||
|
||||
(wlvif->channel_type != conf->channel_type))) {
|
||||
/* send all pending packets */
|
||||
wl1271_tx_work_locked(wl);
|
||||
ret = wlcore_tx_work_locked(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wlvif->band = conf->channel->band;
|
||||
wlvif->channel = channel;
|
||||
wlvif->channel_type = conf->channel_type;
|
||||
|
|
|
@ -235,7 +235,9 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
|
|||
|
||||
/* Read all available packets at once */
|
||||
des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
|
||||
wlcore_hw_prepare_read(wl, des, buf_size);
|
||||
ret = wlcore_hw_prepare_read(wl, des, buf_size);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
|
||||
buf_size, true);
|
||||
|
|
|
@ -662,7 +662,7 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
|
|||
}
|
||||
}
|
||||
|
||||
void wl1271_tx_work_locked(struct wl1271 *wl)
|
||||
int wlcore_tx_work_locked(struct wl1271 *wl)
|
||||
{
|
||||
struct wl12xx_vif *wlvif;
|
||||
struct sk_buff *skb;
|
||||
|
@ -670,10 +670,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
|
|||
u32 buf_offset = 0, last_len = 0;
|
||||
bool sent_packets = false;
|
||||
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(wl->state == WL1271_STATE_OFF))
|
||||
return;
|
||||
return -EIO;
|
||||
|
||||
while ((skb = wl1271_skb_dequeue(wl))) {
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
@ -694,8 +694,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
|
|||
|
||||
buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset,
|
||||
last_len);
|
||||
wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
|
||||
buf_offset, true);
|
||||
ret = wlcore_write_data(wl, REG_SLV_MEM_DATA,
|
||||
wl->aggr_buf, buf_offset, true);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
sent_packets = true;
|
||||
buf_offset = 0;
|
||||
continue;
|
||||
|
@ -731,8 +734,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
|
|||
out_ack:
|
||||
if (buf_offset) {
|
||||
buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len);
|
||||
wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
|
||||
buf_offset, true);
|
||||
ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
|
||||
buf_offset, true);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
sent_packets = true;
|
||||
}
|
||||
if (sent_packets) {
|
||||
|
@ -747,6 +753,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
|
|||
wl1271_handle_tx_low_watermark(wl);
|
||||
}
|
||||
wl12xx_rearm_rx_streaming(wl, active_hlids);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void wl1271_tx_work(struct work_struct *work)
|
||||
|
@ -759,7 +768,11 @@ void wl1271_tx_work(struct work_struct *work)
|
|||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wl1271_tx_work_locked(wl);
|
||||
ret = wlcore_tx_work_locked(wl);
|
||||
if (ret < 0) {
|
||||
wl12xx_queue_recovery_work(wl);
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
|
|
|
@ -234,7 +234,7 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl)
|
|||
}
|
||||
|
||||
void wl1271_tx_work(struct work_struct *work);
|
||||
void wl1271_tx_work_locked(struct wl1271 *wl);
|
||||
int wlcore_tx_work_locked(struct wl1271 *wl);
|
||||
int wlcore_tx_complete(struct wl1271 *wl);
|
||||
void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
|
||||
void wl12xx_tx_reset(struct wl1271 *wl);
|
||||
|
|
|
@ -41,8 +41,8 @@ struct wlcore_ops {
|
|||
int (*identify_fw)(struct wl1271 *wl);
|
||||
int (*boot)(struct wl1271 *wl);
|
||||
int (*plt_init)(struct wl1271 *wl);
|
||||
void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
|
||||
void *buf, size_t len);
|
||||
int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
|
||||
void *buf, size_t len);
|
||||
void (*ack_event)(struct wl1271 *wl);
|
||||
u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks);
|
||||
void (*set_tx_desc_blocks)(struct wl1271 *wl,
|
||||
|
@ -53,7 +53,7 @@ struct wlcore_ops {
|
|||
struct sk_buff *skb);
|
||||
enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl,
|
||||
u32 rx_desc);
|
||||
void (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len);
|
||||
int (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len);
|
||||
u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data,
|
||||
u32 data_len);
|
||||
int (*tx_delayed_compl)(struct wl1271 *wl);
|
||||
|
|
Loading…
Reference in a new issue