int wl1251_hw_init_mem_config(struct wl1251 *wl) { int ret; ret = wl1251_acx_mem_cfg(wl); if (ret < 0) return ret; wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map), GFP_KERNEL); if (!wl->target_mem_map) { wl1251_error("couldn't allocate target memory map"); return -ENOMEM; } /* we now ask for the firmware built memory map */ ret = wl1251_acx_mem_map(wl, wl->target_mem_map, sizeof(struct wl1251_acx_mem_map)); if (ret < 0) { wl1251_error("couldn't retrieve firmware memory map"); kfree(wl->target_mem_map); wl->target_mem_map = NULL; return ret; } return 0; }
static struct wl1251 *ifname_to_wl1251(struct net *net, struct genl_info *info) { struct net_device *netdev; struct wireless_dev *wdev; struct wiphy *wiphy; struct ieee80211_hw *hw; netdev = ifname_to_netdev(net, info); if (netdev == NULL) { wl1251_error("Wrong interface"); return NULL; } wdev = netdev->ieee80211_ptr; if (wdev == NULL) { wl1251_error("ieee80211_ptr is NULL"); return NULL; } wiphy = wdev->wiphy; if (wiphy == NULL) { wl1251_error("wiphy is NULL"); return NULL; } hw = wiphy_priv(wiphy); if (hw == NULL) { wl1251_error("hw is NULL"); return NULL; } dev_put(netdev); return hw->priv; }
/** * read acx from firmware * * @wl: wl struct * @id: acx id * @buf: buffer for the response, including all headers, must work with dma * @len: length of buf */ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len) { struct acx_header *acx = buf; int ret; wl1251_debug(DEBUG_CMD, "cmd interrogate"); acx->id = id; /* payload length, does not include any headers */ acx->len = len - sizeof(*acx); ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); if (ret < 0) { wl1251_error("INTERROGATE command failed"); goto out; } /* the interrogate command got in, we can read the answer */ wl1251_mem_read(wl, wl->cmd_box_addr, buf, len); acx = buf; if (acx->cmd.status != CMD_STATUS_SUCCESS) wl1251_error("INTERROGATE command error: %d", acx->cmd.status); out: return ret; }
int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, struct ieee80211_channel *channels[], unsigned int n_channels, unsigned int n_probes) { struct wl1251_cmd_scan *cmd; int i, ret = 0; wl1251_debug(DEBUG_CMD, "cmd scan"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM; cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); cmd->params.scan_options = 0; cmd->params.num_channels = n_channels; cmd->params.num_probe_requests = n_probes; cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ cmd->params.tid_trigger = 0; for (i = 0; i < n_channels; i++) { cmd->channels[i].min_duration = cpu_to_le32(WL1251_SCAN_MIN_DURATION); cmd->channels[i].max_duration = cpu_to_le32(WL1251_SCAN_MAX_DURATION); memset(&cmd->channels[i].bssid_lsb, 0xff, 4); memset(&cmd->channels[i].bssid_msb, 0xff, 2); cmd->channels[i].early_termination = 0; cmd->channels[i].tx_power_att = 0; cmd->channels[i].channel = channels[i]->hw_value; } cmd->params.ssid_len = ssid_len; if (ssid) memcpy(cmd->params.ssid, ssid, ssid_len); ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); if (ret < 0) { wl1251_error("cmd scan failed: %d", ret); goto out; } wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); if (cmd->header.status != CMD_STATUS_SUCCESS) { wl1251_error("cmd scan status wasn't success: %d", cmd->header.status); ret = -EIO; goto out; } out: kfree(cmd); return ret; }
static int wl1251_nl_reg_read(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; u32 addr, val; int ret = 0; struct sk_buff *msg; void *hdr; if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) return -EINVAL; msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); if (!msg) return -ENOMEM; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); return -EINVAL; } addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); mutex_lock(&wl->mutex); val = wl1251_reg_read32(wl, addr); mutex_unlock(&wl->mutex); hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ); if (IS_ERR(hdr)) { ret = PTR_ERR(hdr); goto nla_put_failure; } NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME, nla_data(info->attrs[WL1251_NL_ATTR_IFNAME])); NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, val); ret = genlmsg_end(msg, hdr); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } return genlmsg_reply(msg, info); nla_put_failure: nlmsg_free(msg); return ret; }
static int __init wl1251_sdio_init(void) { int err; err = platform_driver_register(&wl1251_platform_driver); if (err) { wl1251_error("failed to register platform driver: %d", err); return err; } err = sdio_register_driver(&wl1251_sdio_driver); if (err) wl1251_error("failed to register sdio driver: %d", err); return err; }
int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) { struct cmd_enabledisable_path *cmd; int ret; u16 cmd_rx, cmd_tx; wl1251_debug(DEBUG_CMD, "cmd data path"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } cmd->channel = channel; if (enable) { cmd_rx = CMD_ENABLE_RX; cmd_tx = CMD_ENABLE_TX; } else { cmd_rx = CMD_DISABLE_RX; cmd_tx = CMD_DISABLE_TX; } ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); if (ret < 0) { wl1251_error("rx %s cmd for channel %d failed", enable ? "start" : "stop", channel); goto out; } wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d", enable ? "start" : "stop", channel); ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); if (ret < 0) { wl1251_error("tx %s cmd for channel %d failed", enable ? "start" : "stop", channel); return ret; } wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", enable ? "start" : "stop", channel); out: kfree(cmd); return ret; }
static int wl1251_nl_set_plt_mode(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; u32 val; int ret; if (!info->attrs[WL1251_NL_ATTR_PLT_MODE]) return -EINVAL; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); return -EINVAL; } val = nla_get_u32(info->attrs[WL1251_NL_ATTR_PLT_MODE]); switch (val) { case 0: ret = wl1251_plt_stop(wl); break; case 1: ret = wl1251_plt_start(wl); break; default: ret = -EINVAL; break; } return ret; }
static int wl1251_nl_reg_write(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; u32 addr, val; if (!info->attrs[WL1251_NL_ATTR_REG_ADDR]) return -EINVAL; if (!info->attrs[WL1251_NL_ATTR_REG_VAL]) return -EINVAL; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); return -EINVAL; } addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]); val = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_VAL]); mutex_lock(&wl->mutex); wl1251_reg_write32(wl, addr, val); mutex_unlock(&wl->mutex); return 0; }
int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode) { struct wl1251_cmd_ps_params *ps_params = NULL; int ret = 0; wl1251_debug(DEBUG_CMD, "cmd set ps mode"); ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); if (!ps_params) { ret = -ENOMEM; goto out; } ps_params->ps_mode = ps_mode; ps_params->send_null_data = 1; ps_params->retries = 5; ps_params->hang_over_period = 128; ps_params->null_data_rate = 1; /* 1 Mbps */ ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params, sizeof(*ps_params)); if (ret < 0) { wl1251_error("cmd set_ps_mode failed"); goto out; } out: kfree(ps_params); return ret; }
/** * send test command to firmware * * @wl: wl struct * @buf: buffer containing the command, with all headers, must work with dma * @len: length of the buffer * @answer: is answer needed */ int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer) { int ret; wl1251_debug(DEBUG_CMD, "cmd test"); ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len); if (ret < 0) { wl1251_warning("TEST command failed"); return ret; } if (answer) { struct wl1251_command *cmd_answer; /* * The test command got in, we can read the answer. * The answer would be a wl1251_command, where the * parameter array contains the actual answer. */ wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len); cmd_answer = buf; if (cmd_answer->header.status != CMD_STATUS_SUCCESS) wl1251_error("TEST command answer error: %d", cmd_answer->header.status); } return 0; }
int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id) { struct acx_dot11_default_key *default_key; int ret; wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); default_key = kzalloc(sizeof(*default_key), GFP_KERNEL); if (!default_key) return -ENOMEM; default_key->id = key_id; ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY, default_key, sizeof(*default_key)); if (ret < 0) { wl1251_error("Couldn't set default key"); goto out; } wl->default_key = key_id; out: kfree(default_key); return ret; }
int wl1251_boot_soft_reset(struct wl1251 *wl) { unsigned long timeout; u32 boot_data; /* perform soft reset */ wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); /* SOFT_RESET is self clearing */ timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); while (1) { boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) break; if (time_after(jiffies, timeout)) { /* 1.2 check pWhalBus->uSelfClearTime if the * timeout was reached */ wl1251_error("soft reset timeout"); return -1; } udelay(SOFT_RESET_STALL_TIME); } /* disable Rx/Tx */ wl1251_reg_write32(wl, ENABLE, 0x0); /* disable auto calibration on start*/ wl1251_reg_write32(wl, SPARE_A2, 0xffff); return 0; }
int wl1251_boot_soft_reset(struct wl1251 *wl) { unsigned long timeout; u32 boot_data; /* */ wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); /* */ timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); while (1) { boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) break; if (time_after(jiffies, timeout)) { /* */ wl1251_error("soft reset timeout"); return -1; } udelay(SOFT_RESET_STALL_TIME); } /* */ wl1251_reg_write32(wl, ENABLE, 0x0); /* */ wl1251_reg_write32(wl, SPARE_A2, 0xffff); return 0; }
static int wl1251_event_ps_report(struct wl1251 *wl, struct event_mailbox *mbox) { int ret = 0; wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status); switch (mbox->ps_status) { case EVENT_ENTER_POWER_SAVE_FAIL: wl1251_debug(DEBUG_PSM, "PSM entry failed"); if (wl->station_mode != STATION_POWER_SAVE_MODE) { /* remain in active mode */ wl->psm_entry_retry = 0; break; } if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) { wl->psm_entry_retry++; ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); } else { wl1251_error("Power save entry failed, giving up"); wl->psm_entry_retry = 0; } break; case EVENT_ENTER_POWER_SAVE_SUCCESS: case EVENT_EXIT_POWER_SAVE_FAIL: case EVENT_EXIT_POWER_SAVE_SUCCESS: default: wl->psm_entry_retry = 0; break; } return 0; }
int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, u8 mgt_rate, u8 mgt_mod) { struct acx_fw_gen_frame_rates *rates; int ret; wl1251_debug(DEBUG_ACX, "acx frame rates"); rates = kzalloc(sizeof(*rates), GFP_KERNEL); if (!rates) return -ENOMEM; rates->tx_ctrl_frame_rate = ctrl_rate; rates->tx_ctrl_frame_mod = ctrl_mod; rates->tx_mgt_frame_rate = mgt_rate; rates->tx_mgt_frame_mod = mgt_mod; ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES, rates, sizeof(*rates)); if (ret < 0) { wl1251_error("Failed to set FW rates and modulation"); goto out; } out: kfree(rates); return ret; }
int wl1251_acx_feature_cfg(struct wl1251 *wl) { struct acx_feature_config *feature; int ret; wl1251_debug(DEBUG_ACX, "acx feature cfg"); feature = kzalloc(sizeof(*feature), GFP_KERNEL); if (!feature) return -ENOMEM; /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ feature->data_flow_options = 0; feature->options = 0; ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, feature, sizeof(*feature)); if (ret < 0) { wl1251_error("Couldn't set HW encryption"); goto out; } out: kfree(feature); return ret; }
static int wl1251_event_ps_report(struct wl1251 *wl, struct event_mailbox *mbox) { int ret = 0; wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status); switch (mbox->ps_status) { case ENTER_POWER_SAVE_FAIL: if (!wl->psm) { wl->ps_entry_retry = 0; break; } if (wl->ps_entry_retry < WL1251_PS_ENTRY_RETRIES) { ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); wl->ps_entry_retry++; } else { wl1251_error("Power save entry failed, giving up"); wl->ps_entry_retry = 0; } break; case ENTER_POWER_SAVE_SUCCESS: default: wl->ps_entry_retry = 0; break; } return 0; }
static void wl1251_spi_reset(struct wl1251 *wl) { u8 *cmd; struct spi_transfer t; struct spi_message m; cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { wl1251_error("could not allocate cmd for spi reset"); return; } memset(&t, 0, sizeof(t)); spi_message_init(&m); memset(cmd, 0xff, WSPI_INIT_CMD_LEN); t.tx_buf = cmd; t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); spi_sync(wl_to_spi(wl), &m); wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); }
int wl1251_ps_elp_wakeup(struct wl1251 *wl) { unsigned long timeout; u32 elp_reg; if (!wl->elp) return 0; wl1251_debug(DEBUG_PSM, "waking up chip from elp"); timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); while (!(elp_reg & ELPCTRL_WLAN_READY)) { if (time_after(jiffies, timeout)) { wl1251_error("elp wakeup timeout"); return -ETIMEDOUT; } msleep(1); elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); } wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", jiffies_to_msecs(jiffies) - (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT)); wl->elp = false; return 0; }
static int wl1251_nl_nvs_push(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; int ret = 0; if (!info->attrs[WL1251_NL_ATTR_NVS_BUFFER]) return -EINVAL; if (!info->attrs[WL1251_NL_ATTR_NVS_LEN]) return -EINVAL; wl = ifname_to_wl1251(&init_net, info); if (wl == NULL) { wl1251_error("wl1251 not found"); return -EINVAL; } mutex_lock(&wl->mutex); wl->nvs_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_NVS_LEN]); if (wl->nvs_len % 4) { wl1251_error("NVS size is not multiple of 32: %d", wl->nvs_len); ret = -EILSEQ; goto out; } /* If we already have an NVS, we should free it */ kfree(wl->nvs); wl->nvs = kzalloc(wl->nvs_len, GFP_KERNEL); if (wl->nvs == NULL) { wl1251_error("Can't allocate NVS"); ret = -ENOMEM; goto out; } memcpy(wl->nvs, nla_data(info->attrs[WL1251_NL_ATTR_NVS_BUFFER]), wl->nvs_len); wl1251_debug(DEBUG_NETLINK, "got NVS from userspace, %d bytes", wl->nvs_len); out: mutex_unlock(&wl->mutex); return ret; }
static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable) { int ret = 0; struct sdio_func *func = wl_to_func(wl); wl1251_enter(); if (enable) { if (wl->set_power) wl->set_power(true); ret = mmc_power_restore_host(func->card->host); if (ret) { wl1251_error("failed to restore host power"); goto out; } wl1251_debug(DEBUG_PSM, "sdio_claim_host"); sdio_claim_host(func); wl1251_debug(DEBUG_PSM, "sdio_enable_func"); sdio_enable_func(func); wl1251_debug(DEBUG_PSM, "sdio_release_host"); sdio_release_host(func); wl1251_debug(DEBUG_PSM, "sdio_done"); } else { wl1251_debug(DEBUG_PSM, "sdio_claim_host"); sdio_claim_host(func); wl1251_debug(DEBUG_PSM, "sdio_disable_func"); sdio_disable_func(func); wl1251_debug(DEBUG_PSM, "sdio_release_host"); sdio_release_host(func); wl1251_debug(DEBUG_PSM, "power_save_host"); ret = mmc_power_save_host(func->card->host); if (ret) { wl1251_error("failed to disable host power"); goto out; } wl1251_debug(DEBUG_PSM, "power_save done"); if (wl->set_power) wl->set_power(false); } out: wl1251_leave(); return ret; }
static int wl1251_chip_wakeup(struct wl1251 *wl) { int ret = 0; wl1251_power_on(wl); msleep(WL1251_POWER_ON_SLEEP); wl->if_ops->reset(wl); /* We don't need a real memory partition here, because we only want * to use the registers at this point. */ wl1251_set_partition(wl, 0x00000000, 0x00000000, REGISTERS_BASE, REGISTERS_DOWN_SIZE); /* ELP module wake up */ wl1251_fw_wakeup(wl); /* whal_FwCtrl_BootSm() */ /* 0. read chip id from CHIP_ID */ wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B); /* 1. check if chip id is valid */ switch (wl->chip_id) { case CHIP_ID_1251_PG12: wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", wl->chip_id); break; case CHIP_ID_1251_PG11: wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG11)", wl->chip_id); break; case CHIP_ID_1251_PG10: default: wl1251_error("unsupported chip id: 0x%x", wl->chip_id); ret = -ENODEV; goto out; } if (wl->fw == NULL) { ret = wl1251_fetch_firmware(wl); if (ret < 0) goto out; } /* No NVS from netlink, try to get it from the filesystem */ if (wl->nvs == NULL) { ret = wl1251_fetch_nvs(wl); if (ret < 0) goto out; } out: return ret; }
static int wl1251_platform_probe(struct platform_device *pdev) { if (pdev->id != -1) { wl1251_error("can only handle single device"); return -ENODEV; } wl12xx_board_data = pdev->dev.platform_data; return 0; }
static void wl1251_spi_wake(struct wl1251 *wl) { u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; struct spi_transfer t; struct spi_message m; cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); if (!cmd) { wl1251_error("could not allocate cmd for spi init"); return; } memset(crc, 0, sizeof(crc)); memset(&t, 0, sizeof(t)); spi_message_init(&m); /* * Set WSPI_INIT_COMMAND * the data is being send from the MSB to LSB */ cmd[2] = 0xff; cmd[3] = 0xff; cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; cmd[0] = 0; cmd[7] = 0; cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; else cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; crc[0] = cmd[1]; crc[1] = cmd[0]; crc[2] = cmd[7]; crc[3] = cmd[6]; crc[4] = cmd[5]; cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; cmd[4] |= WSPI_INIT_CMD_END; t.tx_buf = cmd; t.len = WSPI_INIT_CMD_LEN; spi_message_add_tail(&t, &m); spi_sync(wl_to_spi(wl), &m); wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); kfree(cmd); }
static void wl1251_rx_body(struct wl1251 *wl, struct wl1251_rx_descriptor *desc) { struct sk_buff *skb; struct ieee80211_rx_status status; u8 *rx_buffer, beacon = 0; u16 length, *fc; u32 curr_id, last_id_inc, rx_packet_ring_addr; length = WL1251_RX_ALIGN(desc->length - PLCP_HEADER_LENGTH); curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT; last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1); if (last_id_inc != curr_id) { wl1251_warning("curr ID:%d, last ID inc:%d", curr_id, last_id_inc); wl->rx_last_id = curr_id; } else { wl->rx_last_id = last_id_inc; } rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr + sizeof(struct wl1251_rx_descriptor) + 20; if (wl->rx_current_buffer) rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; skb = __dev_alloc_skb(length, GFP_KERNEL); if (!skb) { wl1251_error("Couldn't allocate RX frame"); return; } rx_buffer = skb_put(skb, length); wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); /* The actual length doesn't include the target's alignment */ skb_trim(skb, desc->length - PLCP_HEADER_LENGTH); fc = (u16 *)skb->data; if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) beacon = 1; wl1251_rx_status(wl, desc, &status, beacon); wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, beacon ? "beacon" : ""); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); ieee80211_rx_ni(wl->hw, skb); wl1251_update_rate(wl, length); }
int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, u16 beacon_interval, u8 dtim_interval) { struct cmd_join *join; int ret, i; u8 *bssid; join = kzalloc(sizeof(*join), GFP_KERNEL); if (!join) { ret = -ENOMEM; goto out; } wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d", bss_type == BSS_TYPE_IBSS ? " ibss" : "", channel, beacon_interval, dtim_interval); /* Reverse order BSSID */ bssid = (u8 *) &join->bssid_lsb; for (i = 0; i < ETH_ALEN; i++) bssid[i] = wl->bssid[ETH_ALEN - i - 1]; join->rx_config_options = wl->rx_config; join->rx_filter_options = wl->rx_filter; /* * FIXME: disable temporarily all filters because after commit * 9cef8737 "mac80211: fix managed mode BSSID handling" broke * association. The filter logic needs to be implemented properly * and once that is done, this hack can be removed. */ join->rx_config_options = 0; join->rx_filter_options = WL1251_DEFAULT_RX_FILTER; join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; join->beacon_interval = beacon_interval; join->dtim_interval = dtim_interval; join->bss_type = bss_type; join->channel = channel; join->ctrl = JOIN_CMD_CTRL_TX_FLUSH; ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); if (ret < 0) { wl1251_error("failed to initiate cmd join"); goto out; } out: kfree(join); return ret; }
static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val) { int ret = 0; struct sdio_func *func = wl_to_func(wl); sdio_claim_host(func); sdio_writeb(func, val, addr, &ret); sdio_release_host(func); if (ret) wl1251_error("sdio_writeb failed (%d)", ret); }
static void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) { int ret; struct sdio_func *func = wl_to_func(wl); sdio_claim_host(func); ret = sdio_memcpy_toio(func, addr, buf, len); if (ret) wl1251_error("sdio write failed (%d)", ret); sdio_release_host(func); }
static int __init wl1251_spi_init(void) { int ret; ret = spi_register_driver(&wl1251_spi_driver); if (ret < 0) { wl1251_error("failed to register spi driver: %d", ret); goto out; } out: return ret; }