Commit a572ac1a authored by Luciano Coelho's avatar Luciano Coelho

Merge branch 'wl12xx-next' into for-linville

parents 6bcfe67f 680c6055
This diff is collapsed.
......@@ -32,25 +32,21 @@ enum {
/* numbers of bits the length field takes (add 1 for the actual number) */
#define WL18XX_HOST_IF_LEN_SIZE_FIELD 15
#define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_INIT_COMPLETE | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_CMD_COMPLETE | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \
WL1271_ACX_SW_INTR_WATCHDOG)
#define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA)
#define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \
WL1271_ACX_SW_INTR_WATCHDOG)
#define WL18XX_ACX_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_INIT_COMPLETE | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_CMD_COMPLETE | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA | \
WL1271_ACX_SW_INTR_WATCHDOG)
#define WL18XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \
WL1271_ACX_INTR_EVENT_A | \
WL1271_ACX_INTR_EVENT_B | \
WL1271_ACX_INTR_HW_AVAILABLE | \
WL1271_ACX_INTR_DATA | \
WL1271_ACX_SW_INTR_WATCHDOG)
struct wl18xx_acx_host_config_bitmap {
struct acx_header header;
......
......@@ -24,37 +24,52 @@
#include "io.h"
void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
{
u32 tmp;
int ret;
if (WARN_ON(addr % 2))
return;
return -EINVAL;
if ((addr % 4) == 0) {
tmp = wl1271_read32(wl, addr);
ret = wlcore_read32(wl, addr, &tmp);
if (ret < 0)
goto out;
tmp = (tmp & 0xffff0000) | val;
wl1271_write32(wl, addr, tmp);
ret = wlcore_write32(wl, addr, tmp);
} else {
tmp = wl1271_read32(wl, addr - 2);
ret = wlcore_read32(wl, addr - 2, &tmp);
if (ret < 0)
goto out;
tmp = (tmp & 0xffff) | (val << 16);
wl1271_write32(wl, addr - 2, tmp);
ret = wlcore_write32(wl, addr - 2, tmp);
}
out:
return ret;
}
u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr)
int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out)
{
u32 val;
int ret;
if (WARN_ON(addr % 2))
return 0;
return -EINVAL;
if ((addr % 4) == 0) {
/* address is 4-bytes aligned */
val = wl1271_read32(wl, addr);
return val & 0xffff;
ret = wlcore_read32(wl, addr, &val);
if (ret >= 0 && out)
*out = val & 0xffff;
} else {
val = wl1271_read32(wl, addr - 2);
return (val & 0xffff0000) >> 16;
ret = wlcore_read32(wl, addr - 2, &val);
if (ret >= 0 && out)
*out = (val & 0xffff0000) >> 16;
}
return ret;
}
......@@ -22,7 +22,7 @@
#ifndef __WL18XX_IO_H__
#define __WL18XX_IO_H__
void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val);
u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr);
int __must_check wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val);
int __must_check wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out);
#endif /* __WL18XX_IO_H__ */
This diff is collapsed.
......@@ -33,16 +33,22 @@
#include "rx.h"
#include "hw_ops.h"
static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
{
u32 cpu_ctrl;
int ret;
/* 10.5.0 run the firmware (I) */
cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL);
ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl);
if (ret < 0)
goto out;
/* 10.5.1 run the firmware (II) */
cpu_ctrl |= flag;
wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
ret = wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
out:
return ret;
}
static int wlcore_boot_parse_fw_ver(struct wl1271 *wl,
......@@ -87,7 +93,9 @@ static int wlcore_boot_static_data(struct wl1271 *wl)
goto out;
}
wl1271_read(wl, wl->cmd_box_addr, static_data, len, false);
ret = wlcore_read(wl, wl->cmd_box_addr, static_data, len, false);
if (ret < 0)
goto out_free;
ret = wlcore_boot_parse_fw_ver(wl, static_data);
if (ret < 0)
......@@ -109,6 +117,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() */
......@@ -130,7 +139,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition));
partition.mem.start = dest;
wlcore_set_partition(wl, &partition);
ret = wlcore_set_partition(wl, &partition);
if (ret < 0)
return ret;
/* 10.1 set partition limit and chunk num */
chunk_num = 0;
......@@ -144,7 +155,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
partition_limit = chunk_num * CHUNK_SIZE +
wl->ptable[PART_DOWN].mem.size;
partition.mem.start = addr;
wlcore_set_partition(wl, &partition);
ret = wlcore_set_partition(wl, &partition);
if (ret < 0)
return ret;
}
/* 10.3 upload the chunk */
......@@ -153,7 +166,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++;
}
......@@ -164,10 +179,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)
......@@ -210,6 +226,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");
......@@ -307,7 +324,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT,
"nvs burst write 0x%x: 0x%x",
dest_addr, val);
wl1271_write32(wl, dest_addr, val);
ret = wlcore_write32(wl, dest_addr, val);
if (ret < 0)
return ret;
nvs_ptr += 4;
dest_addr += 4;
......@@ -333,7 +352,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl)
nvs_len -= nvs_ptr - (u8 *)wl->nvs;
/* Now we must set the partition correctly */
wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
if (ret < 0)
return ret;
/* Copy the NVS tables to a new block to ensure alignment */
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
......@@ -341,11 +362,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");
......@@ -359,11 +380,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
u32 chip_id, intr;
/* Make sure we have the boot partition */
wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
if (ret < 0)
return ret;
wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
if (ret < 0)
return ret;
chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B);
ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id);
if (ret < 0)
return ret;
wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
......@@ -376,7 +403,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
loop = 0;
while (loop++ < INIT_LOOP) {
udelay(INIT_LOOP_DELAY);
intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
if (ret < 0)
return ret;
if (intr == 0xffffffff) {
wl1271_error("error reading hardware complete "
......@@ -385,8 +414,10 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* check that ACX_INTR_INIT_COMPLETE is enabled */
else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
wlcore_write_reg(wl, REG_INTERRUPT_ACK,
WL1271_ACX_INTR_INIT_COMPLETE);
ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK,
WL1271_ACX_INTR_INIT_COMPLETE);
if (ret < 0)
return ret;
break;
}
}
......@@ -398,12 +429,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* get hardware config command mail box */
wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR);
ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr);
if (ret < 0)
return ret;
wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr);
/* get hardware config event mail box */
wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR);
ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]);
if (ret < 0)
return ret;
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x",
......@@ -445,9 +481,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl)
}
/* set the working partition to its "running" mode offset */
wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
/* firmware startup completed */
return 0;
return ret;
}
EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware);
......@@ -65,17 +65,24 @@ 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);
intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
if (ret < 0)
goto fail;
while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
if (time_after(jiffies, timeout)) {
wl1271_error("command complete timeout");
......@@ -89,13 +96,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
else
msleep(1);
intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
if (ret < 0)
goto fail;
}
/* read back the status code of the command */
if (res_len == 0)
res_len = sizeof(struct wl1271_cmd_header);
wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false);
ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false);
if (ret < 0)
goto fail;
status = le16_to_cpu(cmd->status);
if (status != CMD_STATUS_SUCCESS) {
......@@ -104,11 +116,14 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
goto fail;
}
wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE);
ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK,
WL1271_ACX_INTR_CMD_COMPLETE);
if (ret < 0)
goto fail;
return 0;
fail:
WARN_ON(1);
wl12xx_queue_recovery_work(wl);
return ret;
}
......@@ -117,35 +132,45 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
* Poll the mailbox event field until any of the bits in the mask is set or a
* timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
*/
static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl,
u32 mask, bool *timeout)
{
u32 *events_vector;
u32 event;
unsigned long timeout;
unsigned long timeout_time;
int ret = 0;
*timeout = false;
events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA);
if (!events_vector)
return -ENOMEM;
timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
do {
if (time_after(jiffies, timeout)) {
if (time_after(jiffies, timeout_time)) {
wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
(int)mask);
ret = -ETIMEDOUT;
*timeout = true;
goto out;
}
msleep(1);
/* read from both event fields */
wl1271_read(wl, wl->mbox_ptr[0], events_vector,
sizeof(*events_vector), false);
ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector,
sizeof(*events_vector), false);
if (ret < 0)
goto out;
event = *events_vector & mask;
wl1271_read(wl, wl->mbox_ptr[1], events_vector,
sizeof(*events_vector), false);
ret = wlcore_read(wl, wl->mbox_ptr[1], events_vector,
sizeof(*events_vector), false);
if (ret < 0)
goto out;
event |= *events_vector & mask;
} while (!event);
......@@ -157,9 +182,10 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
{
int ret;
bool timeout = false;
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
if (ret != 0) {
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout);
if (ret != 0 || timeout) {
wl12xx_queue_recovery_work(wl);
return ret;
}
......@@ -1412,6 +1438,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
{
struct wl12xx_cmd_remove_peer *cmd;
int ret;
bool timeout = false;
wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid);
......@@ -1432,12 +1459,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
goto out_free;
}
ret = wl1271_cmd_wait_for_event_or_timeout(wl,
PEER_REMOVE_COMPLETE_EVENT_ID,
&timeout);
/*
* We are ok with a timeout here. The event is sometimes not sent
* due to a firmware bug.
* due to a firmware bug. In case of another error (like SDIO timeout)
* queue a recovery.
*/
wl1271_cmd_wait_for_event_or_timeout(wl,
PEER_REMOVE_COMPLETE_EVENT_ID);
if (ret)
wl12xx_queue_recovery_work(wl);
out_free:
kfree(cmd);
......@@ -1754,7 +1785,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);
......
......@@ -38,6 +38,8 @@
/* ms */
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
#define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE))
/* debugfs macros idea from mac80211 */
int wl1271_format_buffer(char __user *userbuf, size_t count,
loff_t *ppos, char *fmt, ...)
......@@ -1025,6 +1027,195 @@ static const struct file_operations sleep_auth_ops = {
.llseek = default_llseek,
};
static ssize_t dev_mem_read(struct file *file,
char __user *user_buf, size_t count,
loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
struct wlcore_partition_set part, old_part;
size_t bytes = count;
int ret;
char *buf;
/* only requests of dword-aligned size and offset are supported */
if (bytes % 4)
return -EINVAL;
if (*ppos % 4)
return -EINVAL;
/* function should return in reasonable time */
bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
if (bytes == 0)
return -EINVAL;
memset(&part, 0, sizeof(part));
part.mem.start = file->f_pos;
part.mem.size = bytes;
buf = kmalloc(bytes, GFP_KERNEL);
if (!buf)
return -ENOMEM;
mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) {
ret = -EFAULT;
goto skip_read;
}
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto skip_read;
/* store current partition and switch partition */
memcpy(&old_part, &wl->curr_part, sizeof(old_part));
ret = wlcore_set_partition(wl, &part);
if (ret < 0)
goto part_err;
ret = wlcore_raw_read(wl, 0, buf, bytes, false);
if (ret < 0)
goto read_err;
read_err:
/* recover partition */
ret = wlcore_set_partition(wl, &old_part);
if (ret < 0)
goto part_err;
part_err:
wl1271_ps_elp_sleep(wl);
skip_read:
mutex_unlock(&wl->mutex);
if (ret == 0) {
ret = copy_to_user(user_buf, buf, bytes);
if (ret < bytes) {
bytes -= ret;
*ppos += bytes;
ret = 0;
} else {
ret = -EFAULT;
}
}
kfree(buf);
return ((ret == 0) ? bytes : ret);
}
static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct wl1271 *wl = file->private_data;
struct wlcore_partition_set part, old_part;
size_t bytes = count;
int ret;
char *buf;
/* only requests of dword-aligned size and offset are supported */
if (bytes % 4)
return -EINVAL;
if (*ppos % 4)
return -EINVAL;
/* function should return in reasonable time */
bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE);
if (bytes == 0)
return -EINVAL;
memset(&part, 0, sizeof(part));
part.mem.start = file->f_pos;
part.mem.size = bytes;
buf = kmalloc(bytes, GFP_KERNEL);
if (!buf)
return -ENOMEM;
ret = copy_from_user(buf, user_buf, bytes);
if (ret) {
ret = -EFAULT;
goto err_out;
}
mutex_lock(&wl->mutex);
if (wl->state == WL1271_STATE_OFF) {
ret = -EFAULT;
goto skip_write;
}
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto skip_write;
/* store current partition and switch partition */
memcpy(&old_part, &wl->curr_part, sizeof(old_part));
ret = wlcore_set_partition(wl, &part);
if (ret < 0)
goto part_err;
ret = wlcore_raw_write(wl, 0, buf, bytes, false);
if (ret < 0)
goto write_err;
write_err:
/* recover partition */
ret = wlcore_set_partition(wl, &old_part);
if (ret < 0)
goto part_err;
part_err:
wl1271_ps_elp_sleep(wl);
skip_write:
mutex_unlock(&wl->mutex);
if (ret == 0)
*ppos += bytes;
err_out:
kfree(buf);
return ((ret == 0) ? bytes : ret);
}
static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig)
{
loff_t ret;
/* only requests of dword-aligned size and offset are supported */
if (offset % 4)
return -EINVAL;
switch (orig) {
case SEEK_SET:
file->f_pos = offset;
ret = file->f_pos;
break;
case SEEK_CUR:
file->f_pos += offset;
ret = file->f_pos;
break;
default:
ret = -EINVAL;
}
return ret;
}
static const struct file_operations dev_mem_ops = {
.open = simple_open,
.read = dev_mem_read,
.write = dev_mem_write,
.llseek = dev_mem_seek,
};
static int wl1271_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
......@@ -1059,6 +1250,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming);
DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming);
DEBUGFS_ADD_PREFIX(dev, mem, rootdir);
return 0;
......
......@@ -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;
}
/*
......@@ -301,8 +304,10 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
return -EINVAL;
/* first we read the mbox descriptor */
wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox,
sizeof(*wl->mbox), false);
ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox,
sizeof(*wl->mbox), false);
if (ret < 0)
return ret;
/* process the descriptor */
ret = wl1271_event_process(wl);
......@@ -313,7 +318,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
* TODO: we just need this because one bit is in a different
* place. Is there any better way?
*/
wl->ops->ack_event(wl);
ret = wl->ops->ack_event(wl);
return 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
......@@ -81,10 +83,12 @@ wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len)
return wl->ops->get_rx_packet_len(wl, rx_data, data_len);
}
static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl)
static inline int wlcore_hw_tx_delayed_compl(struct wl1271 *wl)
{
if (wl->ops->tx_delayed_compl)
wl->ops->tx_delayed_compl(wl);
return wl->ops->tx_delayed_compl(wl);
return 0;
}
static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl)
......
......@@ -48,6 +48,12 @@ void wlcore_disable_interrupts(struct wl1271 *wl)
}
EXPORT_SYMBOL_GPL(wlcore_disable_interrupts);
void wlcore_disable_interrupts_nosync(struct wl1271 *wl)
{
disable_irq_nosync(wl->irq);
}
EXPORT_SYMBOL_GPL(wlcore_disable_interrupts_nosync);
void wlcore_enable_interrupts(struct wl1271 *wl)
{
enable_irq(wl->irq);
......@@ -122,9 +128,11 @@ EXPORT_SYMBOL_GPL(wlcore_translate_addr);
* | |
*
*/
void wlcore_set_partition(struct wl1271 *wl,
const struct wlcore_partition_set *p)
int wlcore_set_partition(struct wl1271 *wl,
const struct wlcore_partition_set *p)
{
int ret;
/* copy partition info */
memcpy(&wl->curr_part, p, sizeof(*p));
......@@ -137,28 +145,41 @@ void wlcore_set_partition(struct wl1271 *wl,
wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X",
p->mem3.start, p->mem3.size);
wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
ret = wlcore_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
if (ret < 0)
goto out;
ret = wlcore_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
if (ret < 0)
goto out;
ret = wlcore_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
if (ret < 0)
goto out;
ret = wlcore_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
if (ret < 0)
goto out;
ret = wlcore_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
if (ret < 0)
goto out;
ret = wlcore_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
if (ret < 0)
goto out;
/*
* We don't need the size of the last partition, as it is
* automatically calculated based on the total memory size and
* the sizes of the previous partitions.
*/
wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
}
EXPORT_SYMBOL_GPL(wlcore_set_partition);
ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
void wlcore_select_partition(struct wl1271 *wl, u8 part)
{
wl1271_debug(DEBUG_IO, "setting partition %d", part);
wlcore_set_partition(wl, &wl->ptable[part]);
out:
return ret;
}
EXPORT_SYMBOL_GPL(wlcore_select_partition);
EXPORT_SYMBOL_GPL(wlcore_set_partition);
void wl1271_io_reset(struct wl1271 *wl)
{
......
......@@ -45,6 +45,7 @@
struct wl1271;
void wlcore_disable_interrupts(struct wl1271 *wl);
void wlcore_disable_interrupts_nosync(struct wl1271 *wl);
void wlcore_enable_interrupts(struct wl1271 *wl);
void wl1271_io_reset(struct wl1271 *wl);
......@@ -52,79 +53,113 @@ void wl1271_io_init(struct wl1271 *wl);
int wlcore_translate_addr(struct wl1271 *wl, int addr);
/* Raw target IO, address is not translated */
static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
void *buf, size_t len,
bool fixed)
{
wl->if_ops->write(wl->dev, addr, buf, len, fixed);
int ret;
if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags))
return -EIO;
ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed);
if (ret)
set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags);
return ret;
}
static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
void *buf, size_t len,
bool fixed)
{
wl->if_ops->read(wl->dev, addr, buf, len, fixed);
int ret;
if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags))
return -EIO;
ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed);
if (ret)
set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags);
return ret;
}
static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed)
static inline int __must_check wlcore_raw_read_data(struct wl1271 *wl, int reg,
void *buf, size_t len,
bool fixed)
{
wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed);
return wlcore_raw_read(wl, wl->rtable[reg], buf, len, fixed);
}
static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed)
static inline int __must_check wlcore_raw_write_data(struct wl1271 *wl, int reg,
void *buf, size_t len,
bool fixed)
{
wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed);
return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed);
}
static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr,
u32 *val)
{
wl1271_raw_read(wl, addr, &wl->buffer_32,
sizeof(wl->buffer_32), false);
int ret;
ret = wlcore_raw_read(wl, addr, &wl->buffer_32,
sizeof(wl->buffer_32), false);
if (ret < 0)
return ret;
if (val)
*val = le32_to_cpu(wl->buffer_32);
return le32_to_cpu(wl->buffer_32);
return 0;
}
static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr,
u32 val)
{
wl->buffer_32 = cpu_to_le32(val);
wl1271_raw_write(wl, addr, &wl->buffer_32,
sizeof(wl->buffer_32), false);
return wlcore_raw_write(wl, addr, &wl->buffer_32,
sizeof(wl->buffer_32), false);
}
static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf,
size_t len, bool fixed)
static inline int __must_check wlcore_read(struct wl1271 *wl, int addr,
void *buf, size_t len, bool fixed)
{
int physical;
physical = wlcore_translate_addr(wl, addr);
wl1271_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,
size_t len, bool fixed)
static inline int __must_check wlcore_write(struct wl1271 *wl, int addr,
void *buf, size_t len, bool fixed)
{
int physical;
physical = wlcore_translate_addr(wl, addr);
wl1271_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 __must_check 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 void wlcore_read_data(struct wl1271 *wl, int reg, void *buf,
size_t len, bool fixed)
static inline int __must_check wlcore_read_data(struct wl1271 *wl, int reg,
void *buf, size_t len,
bool fixed)
{
wl1271_read(wl, wl->rtable[reg], buf, len, fixed);
return wlcore_read(wl, wl->rtable[reg], buf, len, fixed);
}
static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
void *buf, size_t len, bool fixed)
static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr,
void *buf, size_t len,
bool fixed)
{
int physical;
int addr;
......@@ -134,34 +169,47 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
physical = wlcore_translate_addr(wl, addr);
wl1271_raw_read(wl, physical, buf, len, fixed);
return wlcore_raw_read(wl, physical, buf, len, fixed);
}
static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
static inline int __must_check wlcore_read32(struct wl1271 *wl, int addr,
u32 *val)
{
return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr));
return wlcore_raw_read32(wl, wlcore_translate_addr(wl, addr), val);
}
static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
static inline int __must_check wlcore_write32(struct wl1271 *wl, int addr,
u32 val)
{
wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
return wlcore_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
}
static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg)
static inline int __must_check wlcore_read_reg(struct wl1271 *wl, int reg,
u32 *val)
{
return wl1271_raw_read32(wl,
wlcore_translate_addr(wl, wl->rtable[reg]));
return wlcore_raw_read32(wl,
wlcore_translate_addr(wl, wl->rtable[reg]),
val);
}
static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val)
static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg,
u32 val)
{
wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val);
return wlcore_raw_write32(wl,
wlcore_translate_addr(wl, wl->rtable[reg]),
val);
}
static inline void wl1271_power_off(struct wl1271 *wl)
{
wl->if_ops->power(wl->dev, false);
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
int ret;
if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags))
return;
ret = wl->if_ops->power(wl->dev, false);
if (!ret)
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}
static inline int wl1271_power_on(struct wl1271 *wl)
......@@ -173,8 +221,8 @@ static inline int wl1271_power_on(struct wl1271 *wl)
return ret;
}
void wlcore_set_partition(struct wl1271 *wl,
const struct wlcore_partition_set *p);
int wlcore_set_partition(struct wl1271 *wl,
const struct wlcore_partition_set *p);
bool wl1271_set_block_size(struct wl1271 *wl);
......@@ -182,6 +230,4 @@ bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl);
void wlcore_select_partition(struct wl1271 *wl, u8 part);
#endif
This diff is collapsed.
......@@ -35,6 +35,7 @@ void wl1271_elp_work(struct work_struct *work)
struct delayed_work *dwork;
struct wl1271 *wl;
struct wl12xx_vif *wlvif;
int ret;
dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, elp_work);
......@@ -63,7 +64,12 @@ void wl1271_elp_work(struct work_struct *work)
}
wl1271_debug(DEBUG_PSM, "chip to elp");
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
if (ret < 0) {
wl12xx_queue_recovery_work(wl);
goto out;
}
set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
out:
......@@ -135,7 +141,11 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
wl->elp_compl = &compl;
spin_unlock_irqrestore(&wl->wl_lock, flags);
wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
if (ret < 0) {
wl12xx_queue_recovery_work(wl);
goto err;
}
if (!pending) {
ret = wait_for_completion_timeout(
......
......@@ -200,7 +200,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
return is_data;
}
void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
{
unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
u32 buf_size;
......@@ -211,6 +211,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
u32 pkt_offset, des;
u8 hlid;
enum wl_rx_buf_align rx_align;
int ret = 0;
while (drv_rx_counter != fw_rx_counter) {
buf_size = 0;
......@@ -234,9 +235,14 @@ void wl12xx_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);
wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
buf_size, true);
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);
if (ret < 0)
goto out;
/* Split data into separate packets */
pkt_offset = 0;
......@@ -273,11 +279,17 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status)
* Write the driver's packet counter to the FW. This is only required
* for older hardware revisions
*/
if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER,
wl->rx_counter);
if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) {
ret = wlcore_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER,
wl->rx_counter);
if (ret < 0)
goto out;
}
wl12xx_rearm_rx_streaming(wl, active_hlids);
out:
return ret;
}
#ifdef CONFIG_PM
......@@ -306,14 +318,19 @@ int wl1271_rx_filter_enable(struct wl1271 *wl,
return 0;
}
void wl1271_rx_filter_clear_all(struct wl1271 *wl)
int wl1271_rx_filter_clear_all(struct wl1271 *wl)
{
int i;
int i, ret = 0;
for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) {
if (!wl->rx_filter_enabled[i])
continue;
wl1271_rx_filter_enable(wl, i, 0, NULL);
ret = wl1271_rx_filter_enable(wl, i, 0, NULL);
if (ret)
goto out;
}
out:
return ret;
}
#endif /* CONFIG_PM */
......@@ -143,11 +143,11 @@ struct wl1271_rx_descriptor {
u8 reserved;
} __packed;
void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status);
int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
int wl1271_rx_filter_enable(struct wl1271 *wl,
int index, bool enable,
struct wl12xx_rx_filter *filter);
void wl1271_rx_filter_clear_all(struct wl1271 *wl);
int wl1271_rx_filter_clear_all(struct wl1271 *wl);
#endif
......@@ -71,8 +71,8 @@ static void wl1271_sdio_set_block_size(struct device *child,
sdio_release_host(func);
}
static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
size_t len, bool fixed)
static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
int ret;
struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
......@@ -103,12 +103,14 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
sdio_release_host(func);
if (ret)
if (WARN_ON(ret))
dev_err(child->parent, "sdio read failed (%d)\n", ret);
return ret;
}
static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
size_t len, bool fixed)
static int __must_check wl12xx_sdio_raw_write(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
int ret;
struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
......@@ -139,25 +141,30 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
sdio_release_host(func);
if (ret)
if (WARN_ON(ret))
dev_err(child->parent, "sdio write failed (%d)\n", ret);
return ret;
}
static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
{
int ret;
struct sdio_func *func = dev_to_sdio_func(glue->dev);
struct mmc_card *card = func->card;
/* If enabled, tell runtime PM not to power off the card */
if (pm_runtime_enabled(&func->dev)) {
ret = pm_runtime_get_sync(&func->dev);
if (ret < 0)
goto out;
} else {
/* Runtime PM is disabled: power up the card manually */
ret = mmc_power_restore_host(func->card->host);
if (ret < 0)
ret = pm_runtime_get_sync(&card->dev);
if (ret) {
/*
* Runtime PM might be temporarily disabled, or the device
* might have a positive reference counter. Make sure it is
* really powered on.
*/
ret = mmc_power_restore_host(card->host);
if (ret < 0) {
pm_runtime_put_sync(&card->dev);
goto out;
}
}
sdio_claim_host(func);
......@@ -172,20 +179,21 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
{
int ret;
struct sdio_func *func = dev_to_sdio_func(glue->dev);
struct mmc_card *card = func->card;
sdio_claim_host(func);
sdio_disable_func(func);
sdio_release_host(func);
/* Power off the card manually, even if runtime PM is enabled. */
ret = mmc_power_save_host(func->card->host);
/* Power off the card manually in case it wasn't powered off above */
ret = mmc_power_save_host(card->host);
if (ret < 0)
return ret;
goto out;
/* If enabled, let runtime PM know the card is powered off */
if (pm_runtime_enabled(&func->dev))
ret = pm_runtime_put_sync(&func->dev);
/* Let runtime PM know the card is powered off */
pm_runtime_put_sync(&card->dev);
out:
return ret;
}
......
......@@ -193,8 +193,8 @@ static int wl12xx_spi_read_busy(struct device *child)
return -ETIMEDOUT;
}
static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
size_t len, bool fixed)
static int __must_check wl12xx_spi_raw_read(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
struct wl1271 *wl = dev_get_drvdata(child);
......@@ -238,7 +238,7 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) &&
wl12xx_spi_read_busy(child)) {
memset(buf, 0, chunk_len);
return;
return 0;
}
spi_message_init(&m);
......@@ -256,10 +256,12 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf,
buf += chunk_len;
len -= chunk_len;
}
return 0;
}
static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf,
size_t len, bool fixed)
static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
......@@ -304,6 +306,8 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf,
}
spi_sync(to_spi_device(glue->dev), &m);
return 0;
}
static struct wl1271_if_operations spi_ops = {
......
......@@ -352,8 +352,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
bool is_dummy;
bool is_gem = false;
if (!skb)
if (!skb) {
wl1271_error("discarding null skb");
return -EINVAL;
}
info = IEEE80211_SKB_CB(skb);
......@@ -662,7 +664,17 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids)
}
}
void wl1271_tx_work_locked(struct wl1271 *wl)
/*
* Returns failure values only in case of failed bus ops within this function.
* wl1271_prepare_tx_frame retvals won't be returned in order to avoid
* triggering recovery by higher layers when not necessary.
* In case a FW command fails within wl1271_prepare_tx_frame fails a recovery
* will be queued in wl1271_cmd_send. -EAGAIN/-EBUSY from prepare_tx_frame
* can occur and are legitimate so don't propagate. -EINVAL will emit a WARNING
* within prepare_tx_frame code but there's nothing we should do about those
* as well.
*/
int wlcore_tx_work_locked(struct wl1271 *wl)
{
struct wl12xx_vif *wlvif;
struct sk_buff *skb;
......@@ -670,10 +682,11 @@ 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;
int bus_ret = 0;
if (unlikely(wl->state == WL1271_STATE_OFF))
return;
return 0;
while ((skb = wl1271_skb_dequeue(wl))) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
......@@ -694,8 +707,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);
bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA,
wl->aggr_buf, buf_offset, true);
if (bus_ret < 0)
goto out;
sent_packets = true;
buf_offset = 0;
continue;
......@@ -731,8 +747,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);
bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
buf_offset, true);
if (bus_ret < 0)
goto out;
sent_packets = true;
}
if (sent_packets) {
......@@ -740,13 +759,19 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
* Interrupt the firmware with the new packets. This is only
* required for older hardware revisions
*/
if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
wl1271_write32(wl, WL12XX_HOST_WR_ACCESS,
wl->tx_packets_count);
if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) {
bus_ret = wlcore_write32(wl, WL12XX_HOST_WR_ACCESS,
wl->tx_packets_count);
if (bus_ret < 0)
goto out;
}
wl1271_handle_tx_low_watermark(wl);
}
wl12xx_rearm_rx_streaming(wl, active_hlids);
out:
return bus_ret;
}
void wl1271_tx_work(struct work_struct *work)
......@@ -759,7 +784,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:
......@@ -881,22 +910,28 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
}
/* Called upon reception of a TX complete interrupt */
void wl1271_tx_complete(struct wl1271 *wl)
int wlcore_tx_complete(struct wl1271 *wl)
{
struct wl1271_acx_mem_map *memmap =
(struct wl1271_acx_mem_map *)wl->target_mem_map;
u32 count, fw_counter;
u32 i;
int ret;
/* read the tx results from the chipset */
wl1271_read(wl, le32_to_cpu(memmap->tx_result),
wl->tx_res_if, sizeof(*wl->tx_res_if), false);
ret = wlcore_read(wl, le32_to_cpu(memmap->tx_result),
wl->tx_res_if, sizeof(*wl->tx_res_if), false);
if (ret < 0)
goto out;
fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter);
/* write host counter to chipset (to ack) */
wl1271_write32(wl, le32_to_cpu(memmap->tx_result) +
offsetof(struct wl1271_tx_hw_res_if,
tx_result_host_counter), fw_counter);
ret = wlcore_write32(wl, le32_to_cpu(memmap->tx_result) +
offsetof(struct wl1271_tx_hw_res_if,
tx_result_host_counter), fw_counter);
if (ret < 0)
goto out;
count = fw_counter - wl->tx_results_count;
wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
......@@ -916,8 +951,11 @@ void wl1271_tx_complete(struct wl1271 *wl)
wl->tx_results_count++;
}
out:
return ret;
}
EXPORT_SYMBOL(wl1271_tx_complete);
EXPORT_SYMBOL(wlcore_tx_complete);
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
{
......
......@@ -234,8 +234,8 @@ 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);
void wl1271_tx_complete(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);
void wl1271_tx_flush(struct wl1271 *wl);
......
......@@ -41,9 +41,9 @@ 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);
void (*ack_event)(struct wl1271 *wl);
int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
void *buf, size_t len);
int (*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,
struct wl1271_tx_hw_descr *desc,
......@@ -53,17 +53,17 @@ 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);
void (*tx_delayed_compl)(struct wl1271 *wl);
int (*tx_delayed_compl)(struct wl1271 *wl);
void (*tx_immediate_compl)(struct wl1271 *wl);
int (*hw_init)(struct wl1271 *wl);
int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
struct wl12xx_vif *wlvif);
s8 (*get_pg_ver)(struct wl1271 *wl);
void (*get_mac)(struct wl1271 *wl);
int (*get_pg_ver)(struct wl1271 *wl, s8 *ver);
int (*get_mac)(struct wl1271 *wl);
void (*set_tx_desc_csum)(struct wl1271 *wl,
struct wl1271_tx_hw_descr *desc,
struct sk_buff *skb);
......
......@@ -209,10 +209,10 @@ struct wl1271_scan {
};
struct wl1271_if_operations {
void (*read)(struct device *child, int addr, void *buf, size_t len,
bool fixed);
void (*write)(struct device *child, int addr, void *buf, size_t len,
bool fixed);
int __must_check (*read)(struct device *child, int addr, void *buf,
size_t len, bool fixed);
int __must_check (*write)(struct device *child, int addr, void *buf,
size_t len, bool fixed);
void (*reset)(struct device *child);
void (*init)(struct device *child);
int (*power)(struct device *child, bool enable);
......@@ -247,6 +247,7 @@ enum wl12xx_flags {
WL1271_FLAG_RECOVERY_IN_PROGRESS,
WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
WL1271_FLAG_INTENDED_FW_RECOVERY,
WL1271_FLAG_SDIO_FAILED,
};
enum wl12xx_vif_flags {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment