int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len) { struct acx_revision *rev; int ret; wl1251_debug(DEBUG_ACX, "acx fw rev"); rev = kzalloc(sizeof(*rev), GFP_KERNEL); if (!rev) return -ENOMEM; ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); if (ret < 0) { wl1251_warning("ACX_FW_REV interrogate failed"); goto out; } /* be careful with the buffer sizes */ strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); /* * if the firmware version string is exactly * sizeof(rev->fw_version) long or fw_len is less than * sizeof(rev->fw_version) it won't be null terminated */ buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; out: kfree(rev); return ret; }
int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime) { struct acx_tsf_info *tsf_info; int ret; tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); if (!tsf_info) { ret = -ENOMEM; goto out; } ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO, tsf_info, sizeof(*tsf_info)); if (ret < 0) { wl1251_warning("ACX_FW_REV interrogate failed"); goto out; } *mactime = tsf_info->current_tsf_lsb | (tsf_info->current_tsf_msb << 31); out: kfree(tsf_info); return ret; }
int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map, size_t len) { int ret; wl1251_debug(DEBUG_ACX, "acx mem map"); ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); if (ret < 0) return ret; return 0; }
int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats) { int ret; wl1251_debug(DEBUG_ACX, "acx statistics"); ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats, sizeof(*stats)); if (ret < 0) { wl1251_warning("acx statistics failed: %d", ret); return -ENOMEM; } return 0; }
int wl1251_acx_data_path_params(struct wl1251 *wl, struct acx_data_path_params_resp *resp) { struct acx_data_path_params *params; int ret; wl1251_debug(DEBUG_ACX, "acx data path params"); params = kzalloc(sizeof(*params), GFP_KERNEL); if (!params) { ret = -ENOMEM; goto out; } params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM; params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM; params->tx_complete_threshold = 1; params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE; params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT; ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS, params, sizeof(*params)); if (ret < 0) goto out; /* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */ ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS, resp, sizeof(*resp)); if (ret < 0) { wl1251_warning("failed to read data path parameters: %d", ret); goto out; } else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) { wl1251_warning("data path parameter acx status failed"); ret = -EIO; goto out; } out: kfree(params); return ret; }
static int wl1251_nl_interrogate(struct sk_buff *skb, struct genl_info *info) { struct wl1251 *wl; struct sk_buff *msg; int ret = -ENOBUFS, cmd_ie, cmd_ie_len; struct wl1251_command *cmd; void *hdr; if (!info->attrs[WL1251_NL_ATTR_CMD_IE]) return -EINVAL; if (!info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM; 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"); ret = -EINVAL; goto nla_put_failure; } /* acx id */ cmd_ie = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE]); /* maximum length of acx, including all headers */ cmd_ie_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_CMD_IE_LEN]); wl1251_debug(DEBUG_NETLINK, "Getting IE 0x%x (len %d)", cmd_ie, cmd_ie_len); mutex_lock(&wl->mutex); ret = wl1251_cmd_interrogate(wl, cmd_ie, cmd, cmd_ie_len); mutex_unlock(&wl->mutex); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &wl1251_nl_family, 0, WL1251_NL_CMD_INTERROGATE); 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(msg, WL1251_NL_ATTR_CMD_IE_ANSWER, cmd_ie_len, cmd); ret = genlmsg_end(msg, hdr); if (ret < 0) { wl1251_error("%s() failed", __func__); goto nla_put_failure; } kfree(cmd); return genlmsg_reply(msg, info); nla_put_failure: kfree(cmd); nlmsg_free(msg); return ret; }