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:
Ido Yariv 2012-06-18 13:21:55 +03:00 committed by Luciano Coelho
parent 045b9b5f41
commit eb96f841b9
12 changed files with 102 additions and 46 deletions

View File

@ -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_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin"
#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.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) { if (wl->chip.id != CHIP_ID_1283_PG20) {
struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
struct wl127x_rx_mem_pool_addr rx_mem_addr; 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; rx_mem_addr.addr_extra = rx_mem_addr.addr + 4;
wl1271_write(wl, WL1271_SLV_REG_DATA, ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr,
&rx_mem_addr, sizeof(rx_mem_addr), false); sizeof(rx_mem_addr), false);
if (ret < 0)
return ret;
} }
return 0;
} }
static int wl12xx_identify_chip(struct wl1271 *wl) static int wl12xx_identify_chip(struct wl1271 *wl)
@ -1073,11 +1079,18 @@ static int wl12xx_boot(struct wl1271 *wl)
return ret; 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) 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); wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
return ret;
} }
static void wl12xx_ack_event(struct wl1271 *wl) static void wl12xx_ack_event(struct wl1271 *wl)

View File

@ -720,10 +720,11 @@ static void wl18xx_pre_upload(struct wl1271 *wl)
tmp = wl1271_read32(wl, WL18XX_SCR_PAD2); 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; struct wl18xx_priv *priv = wl->priv;
size_t len; size_t len;
int ret;
/* the parameters struct is smaller for PG1 */ /* the parameters struct is smaller for PG1 */
if (wl->chip.id == CHIP_ID_185x_PG10) 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); len = sizeof(struct wl18xx_mac_and_phy_params);
wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]);
wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len, ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy,
false); len, false);
return ret;
} }
static void wl18xx_enable_interrupts(struct wl1271 *wl) static void wl18xx_enable_interrupts(struct wl1271 *wl)
@ -769,7 +772,9 @@ static int wl18xx_boot(struct wl1271 *wl)
if (ret < 0) if (ret < 0)
goto out; 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); ret = wlcore_boot_run_firmware(wl);
if (ret < 0) if (ret < 0)
@ -781,7 +786,7 @@ static int wl18xx_boot(struct wl1271 *wl)
return ret; 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) void *buf, size_t len)
{ {
struct wl18xx_priv *priv = wl->priv; 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); memcpy(priv->cmd_buf, buf, len);
memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - 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, return wlcore_write(wl, cmd_box_addr, priv->cmd_buf,
false); WL18XX_CMD_MAX_SIZE, false);
} }
static void wl18xx_ack_event(struct wl1271 *wl) static void wl18xx_ack_event(struct wl1271 *wl)

View File

@ -111,6 +111,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
struct wlcore_partition_set partition; struct wlcore_partition_set partition;
int addr, chunk_num, partition_limit; int addr, chunk_num, partition_limit;
u8 *p, *chunk; u8 *p, *chunk;
int ret;
/* whal_FwCtrl_LoadFwImageSm() */ /* whal_FwCtrl_LoadFwImageSm() */
@ -155,7 +156,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(chunk, p, CHUNK_SIZE); memcpy(chunk, p, CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
p, addr); 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++; 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); memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
fw_data_len % CHUNK_SIZE, p, addr); 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); kfree(chunk);
return 0; return ret;
} }
int wlcore_boot_upload_firmware(struct wl1271 *wl) int wlcore_boot_upload_firmware(struct wl1271 *wl)
@ -212,6 +216,7 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
int i; int i;
u32 dest_addr, val; u32 dest_addr, val;
u8 *nvs_ptr, *nvs_aligned; u8 *nvs_ptr, *nvs_aligned;
int ret;
if (wl->nvs == NULL) { if (wl->nvs == NULL) {
wl1271_error("NVS file is needed during boot"); wl1271_error("NVS file is needed during boot");
@ -343,11 +348,11 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
return -ENOMEM; return -ENOMEM;
/* And finally we upload the NVS tables */ /* And finally we upload the NVS tables */
wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len,
nvs_aligned, nvs_len, false); false);
kfree(nvs_aligned); kfree(nvs_aligned);
return 0; return ret;
out_badnvs: out_badnvs:
wl1271_error("nvs data is malformed"); wl1271_error("nvs data is malformed");

View File

@ -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(len % 4 != 0);
WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); 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 * TODO: we just need this because one bit is in a different
* place. Is there any better way? * 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); 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; return -EINVAL;
/* flush all pending packets */ /* 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)) { if (test_bit(wlvif->dev_role_id, wl->roc_map)) {
ret = wl12xx_croc(wl, wlvif->dev_role_id); ret = wl12xx_croc(wl, wlvif->dev_role_id);

View File

@ -105,6 +105,7 @@ static int wl1271_event_process(struct wl1271 *wl)
u32 vector; u32 vector;
bool disconnect_sta = false; bool disconnect_sta = false;
unsigned long sta_bitmap = 0; unsigned long sta_bitmap = 0;
int ret;
wl1271_event_mbox_dump(mbox); wl1271_event_mbox_dump(mbox);
@ -228,7 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl)
if ((vector & DUMMY_PACKET_EVENT_ID)) { if ((vector & DUMMY_PACKET_EVENT_ID)) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_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;
} }
/* /*

View File

@ -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); 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) wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
{ {
if (wl->ops->prepare_read) 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 static inline u32

View File

@ -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); return wlcore_raw_read(wl, physical, buf, len, fixed);
} }
static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, static inline int wlcore_write(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed) size_t len, bool fixed)
{ {
int physical; int physical;
physical = wlcore_translate_addr(wl, addr); 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, static inline int wlcore_write_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed) 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, static inline int wlcore_read_data(struct wl1271 *wl, int reg, void *buf,

View File

@ -587,7 +587,11 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
* In order to avoid starvation of the TX path, * In order to avoid starvation of the TX path,
* call the work function directly. * 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 { } else {
spin_unlock_irqrestore(&wl->wl_lock, flags); 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 */ /* The FW is low on RX memory blocks, so send the dummy packet asap */
if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) 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 * 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 != channel) ||
(wlvif->channel_type != conf->channel_type))) { (wlvif->channel_type != conf->channel_type))) {
/* send all pending packets */ /* 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->band = conf->channel->band;
wlvif->channel = channel; wlvif->channel = channel;
wlvif->channel_type = conf->channel_type; wlvif->channel_type = conf->channel_type;

View File

@ -235,7 +235,9 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
/* Read all available packets at once */ /* Read all available packets at once */
des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); 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, ret = wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
buf_size, true); buf_size, true);

View File

@ -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 wl12xx_vif *wlvif;
struct sk_buff *skb; struct sk_buff *skb;
@ -670,10 +670,10 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
u32 buf_offset = 0, last_len = 0; u32 buf_offset = 0, last_len = 0;
bool sent_packets = false; bool sent_packets = false;
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
int ret; int ret = 0;
if (unlikely(wl->state == WL1271_STATE_OFF)) if (unlikely(wl->state == WL1271_STATE_OFF))
return; return -EIO;
while ((skb = wl1271_skb_dequeue(wl))) { while ((skb = wl1271_skb_dequeue(wl))) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 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, buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset,
last_len); last_len);
wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, ret = wlcore_write_data(wl, REG_SLV_MEM_DATA,
buf_offset, true); wl->aggr_buf, buf_offset, true);
if (ret < 0)
goto out;
sent_packets = true; sent_packets = true;
buf_offset = 0; buf_offset = 0;
continue; continue;
@ -731,8 +734,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
out_ack: out_ack:
if (buf_offset) { if (buf_offset) {
buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len);
wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
buf_offset, true); buf_offset, true);
if (ret < 0)
goto out;
sent_packets = true; sent_packets = true;
} }
if (sent_packets) { if (sent_packets) {
@ -747,6 +753,9 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
wl1271_handle_tx_low_watermark(wl); wl1271_handle_tx_low_watermark(wl);
} }
wl12xx_rearm_rx_streaming(wl, active_hlids); wl12xx_rearm_rx_streaming(wl, active_hlids);
out:
return ret;
} }
void wl1271_tx_work(struct work_struct *work) void wl1271_tx_work(struct work_struct *work)
@ -759,7 +768,11 @@ void wl1271_tx_work(struct work_struct *work)
if (ret < 0) if (ret < 0)
goto out; 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); wl1271_ps_elp_sleep(wl);
out: out:

View File

@ -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(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); int wlcore_tx_complete(struct wl1271 *wl);
void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_tx_reset(struct wl1271 *wl); void wl12xx_tx_reset(struct wl1271 *wl);

View File

@ -41,7 +41,7 @@ struct wlcore_ops {
int (*identify_fw)(struct wl1271 *wl); int (*identify_fw)(struct wl1271 *wl);
int (*boot)(struct wl1271 *wl); int (*boot)(struct wl1271 *wl);
int (*plt_init)(struct wl1271 *wl); int (*plt_init)(struct wl1271 *wl);
void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
void *buf, size_t len); void *buf, size_t len);
void (*ack_event)(struct wl1271 *wl); void (*ack_event)(struct wl1271 *wl);
u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks);
@ -53,7 +53,7 @@ struct wlcore_ops {
struct sk_buff *skb); struct sk_buff *skb);
enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl,
u32 rx_desc); 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 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data,
u32 data_len); u32 data_len);
int (*tx_delayed_compl)(struct wl1271 *wl); int (*tx_delayed_compl)(struct wl1271 *wl);