/** * wimax_report_rfkill_hw - Reports changes in the hardware RF switch * * @wimax_dev: WiMAX device descriptor * * @state: New state of the RF Kill switch. %WIMAX_RF_ON radio on, * %WIMAX_RF_OFF radio off. * * When the device detects a change in the state of thehardware RF * switch, it must call this function to let the WiMAX kernel stack * know that the state has changed so it can be properly propagated. * * The WiMAX stack caches the state (the driver doesn't need to). As * well, as the change is propagated it will come back as a request to * change the software state to mirror the hardware state. * * If the device doesn't have a hardware kill switch, just report * it on initialization as always on (%WIMAX_RF_ON, radio on). */ void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev, enum wimax_rf_state state) { int result; struct device *dev = wimax_dev_to_dev(wimax_dev); enum wimax_st wimax_state; d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); BUG_ON(state == WIMAX_RF_QUERY); BUG_ON(state != WIMAX_RF_ON && state != WIMAX_RF_OFF); mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); if (result < 0) goto error_not_ready; if (state != wimax_dev->rf_hw) { wimax_dev->rf_hw = state; if (wimax_dev->rf_hw == WIMAX_RF_ON && wimax_dev->rf_sw == WIMAX_RF_ON) wimax_state = WIMAX_ST_READY; else wimax_state = WIMAX_ST_RADIO_OFF; result = rfkill_set_hw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF); __wimax_state_change(wimax_dev, wimax_state); } error_not_ready: mutex_unlock(&wimax_dev->mutex); d_fnend(3, dev, "(wimax_dev %p state %u) = void [%d]\n", wimax_dev, state, result); }
/** * wimax_rfkill - Set the software RF switch state for a WiMAX device * * @wimax_dev: WiMAX device descriptor * * @state: New RF state. * * Returns: * * >= 0 toggle state if ok, < 0 errno code on error. The toggle state * is returned as a bitmap, bit 0 being the hardware RF state, bit 1 * the software RF state. * * 0 means disabled (%WIMAX_RF_ON, radio on), 1 means enabled radio * off (%WIMAX_RF_OFF). * * Description: * * Called by the user when he wants to request the WiMAX radio to be * switched on (%WIMAX_RF_ON) or off (%WIMAX_RF_OFF). With * %WIMAX_RF_QUERY, just the current state is returned. * * NOTE: * * This call will block until the operation is complete. */ int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state) { int result; struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); if (result < 0) { /* While initializing, < 1.4.3 wimax-tools versions use * this call to check if the device is a valid WiMAX * device; so we allow it to proceed always, * considering the radios are all off. */ if (result == -ENOMEDIUM && state == WIMAX_RF_QUERY) result = WIMAX_RF_OFF << 1 | WIMAX_RF_OFF; goto error_not_ready; } switch (state) { case WIMAX_RF_ON: case WIMAX_RF_OFF: result = __wimax_rf_toggle_radio(wimax_dev, state); if (result < 0) goto error; rfkill_set_sw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF); break; case WIMAX_RF_QUERY: break; default: result = -EINVAL; goto error; } result = wimax_dev->rf_sw << 1 | wimax_dev->rf_hw; error: error_not_ready: mutex_unlock(&wimax_dev->mutex); d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n", wimax_dev, state, result); return result; }
int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state) { int result; struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); if (result < 0) { /* */ if (result == -ENOMEDIUM && state == WIMAX_RF_QUERY) result = WIMAX_RF_OFF << 1 | WIMAX_RF_OFF; goto error_not_ready; } switch (state) { case WIMAX_RF_ON: case WIMAX_RF_OFF: result = __wimax_rf_toggle_radio(wimax_dev, state); if (result < 0) goto error; rfkill_set_sw_state(wimax_dev->rfkill, state == WIMAX_RF_OFF); break; case WIMAX_RF_QUERY: break; default: result = -EINVAL; goto error; } result = wimax_dev->rf_sw << 1 | wimax_dev->rf_hw; error: error_not_ready: mutex_unlock(&wimax_dev->mutex); d_fnend(3, dev, "(wimax_dev %p state %u) = %d\n", wimax_dev, state, result); return result; }
static int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; struct wimax_dev *wimax_dev; struct device *dev; struct nlmsghdr *nlh = info->nlhdr; char *pipe_name; void *msg_buf; size_t msg_len; might_sleep(); d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); result = -ENODEV; if (info->attrs[WIMAX_GNL_MSG_IFIDX] == NULL) { printk(KERN_ERR "WIMAX_GNL_MSG_FROM_USER: can't find IFIDX " "attribute\n"); goto error_no_wimax_dev; } ifindex = nla_get_u32(info->attrs[WIMAX_GNL_MSG_IFIDX]); wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); if (wimax_dev == NULL) goto error_no_wimax_dev; dev = wimax_dev_to_dev(wimax_dev); /* */ result = -EINVAL; if (info->attrs[WIMAX_GNL_MSG_DATA] == NULL) { dev_err(dev, "WIMAX_GNL_MSG_FROM_USER: can't find MSG_DATA " "attribute\n"); goto error_no_data; } msg_buf = nla_data(info->attrs[WIMAX_GNL_MSG_DATA]); msg_len = nla_len(info->attrs[WIMAX_GNL_MSG_DATA]); if (info->attrs[WIMAX_GNL_MSG_PIPE_NAME] == NULL) pipe_name = NULL; else { struct nlattr *attr = info->attrs[WIMAX_GNL_MSG_PIPE_NAME]; size_t attr_len = nla_len(attr); /* */ result = -ENOMEM; pipe_name = kstrndup(nla_data(attr), attr_len + 1, GFP_KERNEL); if (pipe_name == NULL) goto error_alloc; pipe_name[attr_len] = 0; } mutex_lock(&wimax_dev->mutex); result = wimax_dev_is_ready(wimax_dev); if (result == -ENOMEDIUM) result = 0; if (result < 0) goto error_not_ready; result = -ENOSYS; if (wimax_dev->op_msg_from_user == NULL) goto error_noop; d_printf(1, dev, "CRX: nlmsghdr len %u type %u flags 0x%04x seq 0x%x pid %u\n", nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags, nlh->nlmsg_seq, nlh->nlmsg_pid); d_printf(1, dev, "CRX: wimax message %zu bytes\n", msg_len); d_dump(2, dev, msg_buf, msg_len); result = wimax_dev->op_msg_from_user(wimax_dev, pipe_name, msg_buf, msg_len, info); error_noop: error_not_ready: mutex_unlock(&wimax_dev->mutex); error_alloc: kfree(pipe_name); error_no_data: dev_put(wimax_dev->net_dev); error_no_wimax_dev: d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result); return result; }