static void i2400m_report_state_hook(struct i2400m *i2400m, const struct i2400m_l3l4_hdr *l3l4_hdr, size_t size, const char *tag) { struct device *dev = i2400m_dev(i2400m); const struct i2400m_tlv_hdr *tlv; size_t tlv_size = le16_to_cpu(l3l4_hdr->length); d_fnstart(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s)\n", i2400m, l3l4_hdr, size, tag); tlv = NULL; while ((tlv = i2400m_tlv_buffer_walk(i2400m, &l3l4_hdr->pl, tlv_size, tlv))) i2400m_report_state_parse_tlv(i2400m, tlv, tag); d_fnend(4, dev, "(i2400m %p, l3l4_hdr %p, size %zu, %s) = void\n", i2400m, l3l4_hdr, size, tag); }
/* * TX an skb to an idle device * * When the device is in basestation-idle mode, we need to wake it up * and then TX. So we queue a work_struct for doing so. * * We need to get an extra ref for the skb (so it is not dropped), as * well as be careful not to queue more than one request (won't help * at all). If more than one request comes or there are errors, we * just drop the packets (see i2400m_hard_start_xmit()). */ static int i2400m_net_wake_tx(struct i2400m *i2400m, struct net_device *net_dev, struct sk_buff *skb) { int result; struct device *dev = i2400m_dev(i2400m); unsigned long flags; d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); if (net_ratelimit()) { d_printf(3, dev, "WAKE&NETTX: " "skb %p sending %d bytes to radio\n", skb, skb->len); d_dump(4, dev, skb->data, skb->len); } /* We hold a ref count for i2400m and skb, so when * stopping() the device, we need to cancel that work * and if pending, release those resources. */ result = 0; spin_lock_irqsave(&i2400m->tx_lock, flags); if (!work_pending(&i2400m->wake_tx_ws)) { netif_stop_queue(net_dev); i2400m_get(i2400m); i2400m->wake_tx_skb = skb_get(skb); /* transfer ref count */ i2400m_tx_prep_header(skb); result = schedule_work(&i2400m->wake_tx_ws); WARN_ON(result == 0); } spin_unlock_irqrestore(&i2400m->tx_lock, flags); if (result == 0) { /* Yes, this happens even if we stopped the * queue -- blame the queue disciplines that * queue without looking -- I guess there is a reason * for that. */ if (net_ratelimit()) d_printf(1, dev, "NETTX: device exiting idle, " "dropping skb %p, queue running %d\n", skb, netif_queue_stopped(net_dev)); result = -EBUSY; } d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result); return result; }
static int i2400m_open(struct net_device *net_dev) { int result; struct i2400m *i2400m = net_dev_to_i2400m(net_dev); struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(net_dev %p [i2400m %p])\n", net_dev, i2400m); /* Make sure we wait until init is complete... */ mutex_lock(&i2400m->init_mutex); if (i2400m->updown) result = 0; else result = -EBUSY; mutex_unlock(&i2400m->init_mutex); d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", net_dev, i2400m, result); return result; }
static int i2400mu_txd(void *_i2400mu) { struct i2400mu *i2400mu = _i2400mu; struct i2400m *i2400m = &i2400mu->i2400m; struct device *dev = &i2400mu->usb_iface->dev; struct i2400m_msg_hdr *tx_msg; size_t tx_msg_size; unsigned long flags; d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); spin_lock_irqsave(&i2400m->tx_lock, flags); BUG_ON(i2400mu->tx_kthread != NULL); i2400mu->tx_kthread = current; spin_unlock_irqrestore(&i2400m->tx_lock, flags); while (1) { d_printf(2, dev, "TX: waiting for messages\n"); tx_msg = NULL; wait_event_interruptible( i2400mu->tx_wq, (kthread_should_stop() /* */ || (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) ); if (kthread_should_stop()) break; WARN_ON(tx_msg == NULL); /* */ d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size); d_dump(5, dev, tx_msg, tx_msg_size); /* */ i2400mu_tx(i2400mu, tx_msg, tx_msg_size); i2400m_tx_msg_sent(i2400m); /* */ } spin_lock_irqsave(&i2400m->tx_lock, flags); i2400mu->tx_kthread = NULL; spin_unlock_irqrestore(&i2400m->tx_lock, flags); d_fnend(4, dev, "(i2400mu %p)\n", i2400mu); return 0; }
/* * Transmit a packet to the base station on behalf of the network stack. * * Returns: 0 if ok, < 0 errno code on error. * * We need to pull the ethernet header and add the hardware header, * which is currently set to all zeroes and reserved. */ static int i2400m_net_tx(struct i2400m *i2400m, struct net_device *net_dev, struct sk_buff *skb) { int result; struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(i2400m %p net_dev %p skb %p)\n", i2400m, net_dev, skb); /* FIXME: check eth hdr, only IPv4 is routed by the device as of now */ net_dev->trans_start = jiffies; i2400m_tx_prep_header(skb); d_printf(3, dev, "NETTX: skb %p sending %d bytes to radio\n", skb, skb->len); d_dump(4, dev, skb->data, skb->len); result = i2400m_tx(i2400m, skb->data, skb->len, I2400M_PT_DATA); d_fnend(3, dev, "(i2400m %p net_dev %p skb %p) = %d\n", i2400m, net_dev, skb, result); return result; }
/* * Send a Report State Change message (as created with _alloc). * * @report_skb: as returned by wimax_gnl_re_state_change_alloc() * @header: as returned by wimax_gnl_re_state_change_alloc() * * Returns: 0 if ok, < 0 errno code on error. * * If the message is NULL, pretend it didn't happen. */ static int wimax_gnl_re_state_change_send( struct wimax_dev *wimax_dev, struct sk_buff *report_skb, void *header) { int result = 0; struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n", wimax_dev, report_skb); if (report_skb == NULL) { result = -ENOMEM; goto out; } genlmsg_end(report_skb, header); genlmsg_multicast(&wimax_gnl_family, report_skb, 0, 0, GFP_KERNEL); out: d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n", wimax_dev, report_skb, result); return result; }
static int i2400mu_resume(struct usb_interface *iface) { int ret = 0; struct device *dev = &iface->dev; struct i2400mu *i2400mu = usb_get_intfdata(iface); struct i2400m *i2400m = &i2400mu->i2400m; d_fnstart(3, dev, "(iface %p)\n", iface); if (i2400m->updown == 0) { d_printf(1, dev, "fw was down, no resume neeed\n"); goto out; } d_printf(1, dev, "fw was up, resuming\n"); i2400mu_notification_setup(i2400mu); out: d_fnend(3, dev, "(iface %p) = %d\n", iface, ret); return ret; }
/** * i2400m_tx_msg_sent - indicate the transmission of a TX message * * @i2400m: device descriptor * * Called by the bus-specific driver when a message has been sent; * this pops it from the FIFO; and as there is space, start the queue * in case it was stopped. * * Should be called even if the message send failed and we are * dropping this TX message. */ void i2400m_tx_msg_sent(struct i2400m *i2400m) { unsigned n; unsigned long flags; struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(i2400m %p)\n", i2400m); spin_lock_irqsave(&i2400m->tx_lock, flags); i2400m->tx_out += i2400m->tx_msg_size; d_printf(2, dev, "TX: sent %zu b\n", (size_t) i2400m->tx_msg_size); i2400m->tx_msg_size = 0; BUG_ON(i2400m->tx_out > i2400m->tx_in); /* level them FIFO markers off */ n = i2400m->tx_out / I2400M_TX_BUF_SIZE; i2400m->tx_out %= I2400M_TX_BUF_SIZE; i2400m->tx_in -= n * I2400M_TX_BUF_SIZE; netif_start_queue(i2400m->wimax_dev.net_dev); spin_unlock_irqrestore(&i2400m->tx_lock, flags); d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); }
ssize_t i2400ms_bus_bm_wait_for_ack(struct i2400m *i2400m, struct i2400m_bootrom_header *ack, size_t ack_size) { ssize_t result; struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; int size; BUG_ON(sizeof(*ack) > ack_size); d_fnstart(5, dev, "(i2400m %p ack %p size %zu)\n", i2400m, ack, ack_size); result = wait_event_timeout(i2400ms->bm_wfa_wq, i2400ms->bm_ack_size != -EINPROGRESS, 2 * HZ); if (result == 0) { result = -ETIMEDOUT; dev_err(dev, "BM: error waiting for an ack\n"); goto error_timeout; } spin_lock(&i2400m->rx_lock); result = i2400ms->bm_ack_size; BUG_ON(result == -EINPROGRESS); if (result < 0) dev_err(dev, "BM: %s failed: %zd\n", __func__, result); else { size = min(ack_size, i2400ms->bm_ack_size); memcpy(ack, i2400m->bm_ack_buf, size); } i2400ms->bm_ack_size = -EINPROGRESS; spin_unlock(&i2400m->rx_lock); error_timeout: d_fnend(5, dev, "(i2400m %p ack %p size %zu) = %zd\n", i2400m, ack, ack_size, result); return result; }
/* * i2400m_net_rx - pass a network packet to the stack * * @i2400m: device instance * @skb_rx: the skb where the buffer pointed to by @buf is * @i: 1 if payload is the only one * @buf: pointer to the buffer containing the data * @len: buffer's length * * This is only used now for the v1.3 firmware. It will be deprecated * in >= 2.6.31. * * Note that due to firmware limitations, we don't have space to add * an ethernet header, so we need to copy each packet. Firmware * versions >= v1.4 fix this [see i2400m_net_erx()]. * * We just clone the skb and set it up so that it's skb->data pointer * points to "buf" and it's length. * * Note that if the payload is the last (or the only one) in a * multi-payload message, we don't clone the SKB but just reuse it. * * This function is normally run from a thread context. However, we * still use netif_rx() instead of netif_receive_skb() as was * recommended in the mailing list. Reason is in some stress tests * when sending/receiving a lot of data we seem to hit a softlock in * the kernel's TCP implementation [aroudn tcp_delay_timer()]. Using * netif_rx() took care of the issue. * * This is, of course, still open to do more research on why running * with netif_receive_skb() hits this softlock. FIXME. * * FIXME: currently we don't do any efforts at distinguishing if what * we got was an IPv4 or IPv6 header, to setup the protocol field * correctly. */ void i2400m_net_rx(struct i2400m *i2400m, struct sk_buff *skb_rx, unsigned i, const void *buf, int buf_len) { struct net_device *net_dev = i2400m->wimax_dev.net_dev; struct device *dev = i2400m_dev(i2400m); struct sk_buff *skb; d_fnstart(2, dev, "(i2400m %p buf %p buf_len %d)\n", i2400m, buf, buf_len); if (i) { skb = skb_get(skb_rx); d_printf(2, dev, "RX: reusing first payload skb %p\n", skb); skb_pull(skb, buf - (void *) skb->data); skb_trim(skb, (void *) skb_end_pointer(skb) - buf); } else { /* Yes, this is bad -- a lot of overhead -- see * comments at the top of the file */ skb = __netdev_alloc_skb(net_dev, buf_len, GFP_KERNEL); if (skb == NULL) { dev_err(dev, "NETRX: no memory to realloc skb\n"); net_dev->stats.rx_dropped++; goto error_skb_realloc; } memcpy(skb_put(skb, buf_len), buf, buf_len); } i2400m_rx_fake_eth_header(i2400m->wimax_dev.net_dev, skb->data - ETH_HLEN, cpu_to_be16(ETH_P_IP)); skb_set_mac_header(skb, -ETH_HLEN); skb->dev = i2400m->wimax_dev.net_dev; skb->protocol = htons(ETH_P_IP); net_dev->stats.rx_packets++; net_dev->stats.rx_bytes += buf_len; d_printf(3, dev, "NETRX: receiving %d bytes to network stack\n", buf_len); d_dump(4, dev, buf, buf_len); netif_rx_ni(skb); /* see notes in function header */ error_skb_realloc: d_fnend(2, dev, "(i2400m %p buf %p buf_len %d) = void\n", i2400m, buf, buf_len); }
static int i2400m_fw_bootstrap(struct i2400m *i2400m, const struct firmware *fw, enum i2400m_bri flags) { int ret; struct device *dev = i2400m_dev(i2400m); const struct i2400m_bcf_hdr *bcf; /* Firmware data */ d_fnstart(5, dev, "(i2400m %p)\n", i2400m); bcf = (void *) fw->data; ret = i2400m_fw_check(i2400m, bcf, fw->size); if (ret >= 0) ret = i2400m_fw_dnload(i2400m, bcf, fw->size, flags); if (ret < 0) dev_err(dev, "%s: cannot use: %d, skipping\n", i2400m->fw_name, ret); kfree(i2400m->fw_hdrs); i2400m->fw_hdrs = NULL; d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); return ret; }
/* * Translate from rfkill state to wimax state * * NOTE: Special state handling rules here * * Just pretend the call didn't happen if we are in a state where * we know for sure it cannot be handled (WIMAX_ST_DOWN or * __WIMAX_ST_QUIESCING). rfkill() needs it to register and * unregister, as it will run this path. * * NOTE: This call will block until the operation is completed. */ static int wimax_rfkill_set_radio_block(void *data, bool blocked) { int result; struct wimax_dev *wimax_dev = data; struct device *dev = wimax_dev_to_dev(wimax_dev); enum wimax_rf_state rf_state; d_fnstart(3, dev, "(wimax_dev %p blocked %u)\n", wimax_dev, blocked); rf_state = WIMAX_RF_ON; if (blocked) rf_state = WIMAX_RF_OFF; mutex_lock(&wimax_dev->mutex); if (wimax_dev->state <= __WIMAX_ST_QUIESCING) result = 0; else result = __wimax_rf_toggle_radio(wimax_dev, rf_state); mutex_unlock(&wimax_dev->mutex); d_fnend(3, dev, "(wimax_dev %p blocked %u) = %d\n", wimax_dev, blocked, result); return result; }
/* * Read the MAC addr * * The position this function reads is fixed in device memory and * always available, even without firmware. * * Note we specify we want to read only six bytes, but provide space * for 16, as we always get it rounded up. */ int i2400m_read_mac_addr(struct i2400m *i2400m) { int result; struct device *dev = i2400m_dev(i2400m); struct net_device *net_dev = i2400m->wimax_dev.net_dev; struct i2400m_bootrom_header *cmd; struct { struct i2400m_bootrom_header ack; u8 ack_pl[16]; } __packed ack_buf; d_fnstart(5, dev, "(i2400m %p)\n", i2400m); cmd = i2400m->bm_cmd_buf; cmd->command = i2400m_brh_command(I2400M_BRH_READ, 0, 1); cmd->target_addr = cpu_to_le32(0x00203fe8); cmd->data_size = cpu_to_le32(6); result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), &ack_buf.ack, sizeof(ack_buf), 0); if (result < 0) { dev_err(dev, "BM: read mac addr failed: %d\n", result); goto error_read_mac; } d_printf(2, dev, "mac addr is %pM\n", ack_buf.ack_pl); if (i2400m->bus_bm_mac_addr_impaired == 1) { ack_buf.ack_pl[0] = 0x00; ack_buf.ack_pl[1] = 0x16; ack_buf.ack_pl[2] = 0xd3; get_random_bytes(&ack_buf.ack_pl[3], 3); dev_err(dev, "BM is MAC addr impaired, faking MAC addr to " "mac addr is %pM\n", ack_buf.ack_pl); result = 0; } net_dev->addr_len = ETH_ALEN; memcpy(net_dev->perm_addr, ack_buf.ack_pl, ETH_ALEN); memcpy(net_dev->dev_addr, ack_buf.ack_pl, ETH_ALEN); error_read_mac: d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, result); return result; }
static void i2400ms_irq(struct sdio_func *func) { int ret; struct i2400ms *i2400ms = sdio_get_drvdata(func); struct device *dev = &func->dev; int val; d_fnstart(6, dev, "(i2400ms %p)\n", i2400ms); val = sdio_readb(func, I2400MS_INTR_STATUS_ADDR, &ret); if (ret < 0) { dev_err(dev, "RX: Can't read interrupt status: %d\n", ret); goto error_no_irq; } if (!val) { dev_err(dev, "RX: BUG? got IRQ but no interrupt ready?\n"); goto error_no_irq; } i2400ms_rx(i2400ms); error_no_irq: d_fnend(6, dev, "(i2400ms %p) = void\n", i2400ms); }
/* * Initialize a non signed boot * * This implies sending some magic values to the device's memory. Note * we convert the values to little endian in the same array * declaration. */ static int i2400m_dnload_init_nonsigned(struct i2400m *i2400m) { unsigned i = 0; int ret = 0; struct device *dev = i2400m_dev(i2400m); d_fnstart(5, dev, "(i2400m %p)\n", i2400m); if (i2400m->bus_bm_pokes_table) { while (i2400m->bus_bm_pokes_table[i].address) { ret = i2400m_download_chunk( i2400m, &i2400m->bus_bm_pokes_table[i].data, sizeof(i2400m->bus_bm_pokes_table[i].data), i2400m->bus_bm_pokes_table[i].address, 1, 1); if (ret < 0) break; i++; } } d_fnend(5, dev, "(i2400m %p) = %d\n", i2400m, ret); return ret; }
static int i2400mu_resume(struct usb_interface *iface) { int ret = 0; struct device *dev = &iface->dev; struct i2400mu *i2400mu = usb_get_intfdata(iface); struct i2400m *i2400m = &i2400mu->i2400m; d_fnstart(3, dev, "(iface %p)\n", iface); if (i2400m->updown == 0) { d_printf(1, dev, "fw was down, no resume neeed\n"); goto out; } d_printf(1, dev, "fw was up, resuming\n"); i2400mu_notification_setup(i2400mu); /* USB has flow control, so we don't need to give it time to * come back; otherwise, we'd use something like a get-state * command... */ out: d_fnend(3, dev, "(iface %p) = %d\n", iface, ret); return ret; }
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; }
/** * Get the IEs that a radio controller is sending in its beacon * * @uwb_rc: UWB Radio Controller * @returns: Size read from the system * * We don't need to lock the uwb_rc's mutex because we don't modify * anything. Once done with the iedata buffer, call * uwb_rc_ie_release(iedata). Don't call kfree on it. */ ssize_t uwb_rc_get_ie(struct uwb_rc *uwb_rc, struct uwb_rc_evt_get_ie **pget_ie) { ssize_t result; struct device *dev = &uwb_rc->uwb_dev.dev; struct uwb_rccb *cmd = NULL; struct uwb_rceb *reply = NULL; struct uwb_rc_evt_get_ie *get_ie; d_fnstart(3, dev, "(%p, %p)\n", uwb_rc, pget_ie); result = -ENOMEM; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (cmd == NULL) goto error_kzalloc; cmd->bCommandType = UWB_RC_CET_GENERAL; cmd->wCommand = cpu_to_le16(UWB_RC_CMD_GET_IE); result = uwb_rc_vcmd(uwb_rc, "GET_IE", cmd, sizeof(*cmd), UWB_RC_CET_GENERAL, UWB_RC_CMD_GET_IE, &reply); if (result < 0) goto error_cmd; get_ie = container_of(reply, struct uwb_rc_evt_get_ie, rceb); if (result < sizeof(*get_ie)) { dev_err(dev, "not enough data returned for decoding GET IE " "(%zu bytes received vs %zu needed)\n", result, sizeof(*get_ie)); result = -EINVAL; } else if (result < sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)) { dev_err(dev, "not enough data returned for decoding GET IE " "payload (%zu bytes received vs %zu needed)\n", result, sizeof(*get_ie) + le16_to_cpu(get_ie->wIELength)); result = -EINVAL; } else *pget_ie = get_ie; error_cmd: kfree(cmd); error_kzalloc: d_fnend(3, dev, "(%p, %p) = %d\n", uwb_rc, pget_ie, (int)result); return result; }
void i2400m_tx_msg_sent(struct i2400m *i2400m) { unsigned n; unsigned long flags; struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(i2400m %p)\n", i2400m); spin_lock_irqsave(&i2400m->tx_lock, flags); if (i2400m->tx_buf == NULL) goto out_unlock; i2400m->tx_out += i2400m->tx_msg_size; d_printf(2, dev, "TX: sent %zu b\n", (size_t) i2400m->tx_msg_size); i2400m->tx_msg_size = 0; BUG_ON(i2400m->tx_out > i2400m->tx_in); n = i2400m->tx_out / I2400M_TX_BUF_SIZE; i2400m->tx_out %= I2400M_TX_BUF_SIZE; i2400m->tx_in -= n * I2400M_TX_BUF_SIZE; out_unlock: spin_unlock_irqrestore(&i2400m->tx_lock, flags); d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); }
/* * Cleanup resources acquired during i2400m_net_wake_tx() * * This is called by __i2400m_dev_stop and means we have to make sure * the workqueue is flushed from any pending work. */ void i2400m_net_wake_stop(struct i2400m *i2400m) { struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(i2400m %p)\n", i2400m); /* See i2400m_hard_start_xmit(), references are taken there * and here we release them if the work was still * pending. Note we can't differentiate work not pending vs * never scheduled, so the NULL check does that. */ if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 && i2400m->wake_tx_skb != NULL) { unsigned long flags; struct sk_buff *wake_tx_skb; spin_lock_irqsave(&i2400m->tx_lock, flags); wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ i2400m->wake_tx_skb = NULL; /* compat help */ spin_unlock_irqrestore(&i2400m->tx_lock, flags); i2400m_put(i2400m); kfree_skb(wake_tx_skb); } d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); }
/* * Transmit a packet to the base station on behalf of the network stack * * * Returns: NETDEV_TX_OK (always, even in case of error) * * In case of error, we just drop it. Reasons: * * - we add a hw header to each skb, and if the network stack * retries, we have no way to know if that skb has it or not. * * - network protocols have their own drop-recovery mechanisms * * - there is not much else we can do * * If the device is idle, we need to wake it up; that is an operation * that will sleep. See i2400m_net_wake_tx() for details. */ static netdev_tx_t i2400m_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) { struct i2400m *i2400m = net_dev_to_i2400m(net_dev); struct device *dev = i2400m_dev(i2400m); int result; d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); if (skb_header_cloned(skb)) { /* * Make tcpdump/wireshark happy -- if they are * running, the skb is cloned and we will overwrite * the mac fields in i2400m_tx_prep_header. Expand * seems to fix this... */ result = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); if (result) { result = NETDEV_TX_BUSY; goto error_expand; } } if (i2400m->state == I2400M_SS_IDLE) result = i2400m_net_wake_tx(i2400m, net_dev, skb); else result = i2400m_net_tx(i2400m, net_dev, skb); if (result < 0) net_dev->stats.tx_dropped++; else { net_dev->stats.tx_packets++; net_dev->stats.tx_bytes += skb->len; } result = NETDEV_TX_OK; error_expand: kfree_skb(skb); d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result); return 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; }
/* * Setup SDIO RX * * Hooks up the IRQ handler and then enables IRQs. */ int i2400ms_rx_setup(struct i2400ms *i2400ms) { int result; struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; struct i2400m *i2400m = &i2400ms->i2400m; d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); init_waitqueue_head(&i2400ms->bm_wfa_wq); spin_lock(&i2400m->rx_lock); i2400ms->bm_wait_result = -EINPROGRESS; /* * Before we are about to enable the RX interrupt, make sure * bm_ack_size is cleared to -EINPROGRESS which indicates * no RX interrupt happened yet or the previous interrupt * has been handled, we are ready to take the new interrupt */ i2400ms->bm_ack_size = -EINPROGRESS; spin_unlock(&i2400m->rx_lock); sdio_claim_host(func); result = sdio_claim_irq(func, i2400ms_irq); if (result < 0) { dev_err(dev, "Cannot claim IRQ: %d\n", result); goto error_irq_claim; } result = 0; sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result); if (result < 0) { sdio_release_irq(func); dev_err(dev, "Failed to enable interrupts %d\n", result); } error_irq_claim: sdio_release_host(func); d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); return result; }
/* * Exporting to user space over generic netlink * * Parse the reset command from user space, return error code. * * No attributes. */ int wimax_gnl_doit_reset(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; struct wimax_dev *wimax_dev; d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); result = -ENODEV; if (info->attrs[WIMAX_GNL_RESET_IFIDX] == NULL) { printk(KERN_ERR "WIMAX_GNL_OP_RFKILL: can't find IFIDX " "attribute\n"); goto error_no_wimax_dev; } ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RESET_IFIDX]); wimax_dev = wimax_dev_get_by_genl_info(info, ifindex); if (wimax_dev == NULL) goto error_no_wimax_dev; /* Execute the operation and send the result back to user space */ result = wimax_reset(wimax_dev); 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; }
/** * wimax_reset - Reset a WiMAX device * * @wimax_dev: WiMAX device descriptor * * Returns: * * %0 if ok and a warm reset was done (the device still exists in * the system). * * -%ENODEV if a cold/bus reset had to be done (device has * disconnected and reconnected, so current handle is not valid * any more). * * -%EINVAL if the device is not even registered. * * Any other negative error code shall be considered as * non-recoverable. * * Description: * * Called when wanting to reset the device for any reason. Device is * taken back to power on status. * * This call blocks; on successful return, the device has completed the * reset process and is ready to operate. */ int wimax_reset(struct wimax_dev *wimax_dev) { int result = -EINVAL; struct device *dev = wimax_dev_to_dev(wimax_dev); enum wimax_st state; might_sleep(); d_fnstart(3, dev, "(wimax_dev %p)\n", wimax_dev); mutex_lock(&wimax_dev->mutex); dev_hold(wimax_dev->net_dev); state = wimax_dev->state; mutex_unlock(&wimax_dev->mutex); if (state >= WIMAX_ST_DOWN) { mutex_lock(&wimax_dev->mutex_reset); result = wimax_dev->op_reset(wimax_dev); mutex_unlock(&wimax_dev->mutex_reset); } dev_put(wimax_dev->net_dev); d_fnend(3, dev, "(wimax_dev %p) = %d\n", wimax_dev, result); return result; }
/* * Send a Report State Change message (as created with _alloc). * * @report_skb: as returned by wimax_gnl_re_state_change_alloc() * @header: as returned by wimax_gnl_re_state_change_alloc() * * Returns: 0 if ok, < 0 errno code on error. * * If the message is NULL, pretend it didn't happen. */ static int wimax_gnl_re_state_change_send( struct wimax_dev *wimax_dev, struct sk_buff *report_skb, void *header) { int result = 0; struct device *dev = wimax_dev_to_dev(wimax_dev); d_fnstart(3, dev, "(wimax_dev %p report_skb %p)\n", wimax_dev, report_skb); if (report_skb == NULL) goto out; genlmsg_end(report_skb, header); result = genlmsg_multicast(report_skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); if (result == -ESRCH) /* Nobody connected, ignore it */ result = 0; /* btw, the skb is freed already */ if (result < 0) { dev_err(dev, "RE_STCH: Error sending: %d\n", result); nlmsg_free(report_skb); } out: d_fnend(3, dev, "(wimax_dev %p report_skb %p) = %d\n", wimax_dev, report_skb, result); return result; }
/* * Setup SDIO RX * * Hooks up the IRQ handler and then enables IRQs. */ int i2400ms_rx_setup(struct i2400ms *i2400ms) { int result; struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; d_fnstart(5, dev, "(i2400ms %p)\n", i2400ms); sdio_claim_host(func); result = sdio_claim_irq(func, i2400ms_irq); if (result < 0) { dev_err(dev, "Cannot claim IRQ: %d\n", result); goto error_irq_claim; } result = 0; sdio_writeb(func, 1, I2400MS_INTR_ENABLE_ADDR, &result); if (result < 0) { sdio_release_irq(func); dev_err(dev, "Failed to enable interrupts %d\n", result); } error_irq_claim: sdio_release_host(func); d_fnend(5, dev, "(i2400ms %p) = %d\n", i2400ms, result); return result; }
/* * Parse and act on a TLV Media Status sent by the device * * @i2400m: device descriptor * @ms: validated Media Status TLV * * This will set the carrier up on down based on the device's link * report. This is done asides of what the WiMAX stack does based on * the device's state as sometimes we need to do a link-renew (the BS * wants us to renew a DHCP lease, for example). * * In fact, doc says that everytime we get a link-up, we should do a * DHCP negotiation... */ static void i2400m_report_tlv_media_status(struct i2400m *i2400m, const struct i2400m_tlv_media_status *ms) { struct device *dev = i2400m_dev(i2400m); struct wimax_dev *wimax_dev = &i2400m->wimax_dev; struct net_device *net_dev = wimax_dev->net_dev; enum i2400m_media_status status = le32_to_cpu(ms->media_status); d_fnstart(3, dev, "(i2400m %p ms %p [%u])\n", i2400m, ms, status); if (unlikely(i2400m->ready == 0)) /* act if up */ goto out; switch (status) { case I2400M_MEDIA_STATUS_LINK_UP: netif_carrier_on(net_dev); break; case I2400M_MEDIA_STATUS_LINK_DOWN: netif_carrier_off(net_dev); break; /* * This is the network telling us we need to retrain the DHCP * lease -- so far, we are trusting the WiMAX Network Service * in user space to pick this up and poke the DHCP client. */ case I2400M_MEDIA_STATUS_LINK_RENEW: netif_carrier_on(net_dev); break; default: dev_err(dev, "HW BUG? unknown media status %u\n", status); }; out: d_fnend(3, dev, "(i2400m %p ms %p [%u]) = void\n", i2400m, ms, status); }
static int wimax_gnl_doit_rfkill(struct sk_buff *skb, struct genl_info *info) { int result, ifindex; struct wimax_dev *wimax_dev; struct device *dev; enum wimax_rf_state new_state; d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info); result = -ENODEV; if (info->attrs[WIMAX_GNL_RFKILL_IFIDX] == NULL) { printk(KERN_ERR "WIMAX_GNL_OP_RFKILL: can't find IFIDX " "attribute\n"); goto error_no_wimax_dev; } ifindex = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_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_RFKILL_STATE] == NULL) { dev_err(dev, "WIMAX_GNL_RFKILL: can't find RFKILL_STATE " "attribute\n"); goto error_no_pid; } new_state = nla_get_u32(info->attrs[WIMAX_GNL_RFKILL_STATE]); /* Execute the operation and send the result back to user space */ result = wimax_rfkill(wimax_dev, new_state); error_no_pid: 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; }
/* * Transmit a packet to the base station on behalf of the network stack * * * Returns: NETDEV_TX_OK (always, even in case of error) * * In case of error, we just drop it. Reasons: * * - we add a hw header to each skb, and if the network stack * retries, we have no way to know if that skb has it or not. * * - network protocols have their own drop-recovery mechanisms * * - there is not much else we can do * * If the device is idle, we need to wake it up; that is an operation * that will sleep. See i2400m_net_wake_tx() for details. */ static int i2400m_hard_start_xmit(struct sk_buff *skb, struct net_device *net_dev) { int result; struct i2400m *i2400m = net_dev_to_i2400m(net_dev); struct device *dev = i2400m_dev(i2400m); d_fnstart(3, dev, "(skb %p net_dev %p)\n", skb, net_dev); if (i2400m->state == I2400M_SS_IDLE) result = i2400m_net_wake_tx(i2400m, net_dev, skb); else result = i2400m_net_tx(i2400m, net_dev, skb); if (result < 0) net_dev->stats.tx_dropped++; else { net_dev->stats.tx_packets++; net_dev->stats.tx_bytes += skb->len; } kfree_skb(skb); result = NETDEV_TX_OK; d_fnend(3, dev, "(skb %p net_dev %p) = %d\n", skb, net_dev, result); return result; }