/** Finalizes setting up the SKB and delivers it * * We first pass the incoming frame to WLP substack for verification. It * may also be a WLP association frame in which case WLP will take over the * processing. If WLP does not take it over it will still verify it, if the * frame is invalid the skb will be freed by WLP and we will not continue * parsing. * */ static void i1480u_skb_deliver(struct i1480u *i1480u) { int should_parse; struct net_device *net_dev = i1480u->net_dev; struct device *dev = &i1480u->usb_iface->dev; d_printf(6, dev, "RX delivered pre skb(%p), %u bytes\n", i1480u->rx_skb, i1480u->rx_skb->len); d_dump(7, dev, i1480u->rx_skb->data, i1480u->rx_skb->len); should_parse = wlp_receive_frame(dev, &i1480u->wlp, i1480u->rx_skb, &i1480u->rx_srcaddr); if (!should_parse) goto out; i1480u->rx_skb->protocol = eth_type_trans(i1480u->rx_skb, net_dev); d_printf(5, dev, "RX delivered skb(%p), %u bytes\n", i1480u->rx_skb, i1480u->rx_skb->len); d_dump(7, dev, i1480u->rx_skb->data, i1480u->rx_skb->len > 72 ? 72 : i1480u->rx_skb->len); i1480u->stats.rx_packets++; i1480u->stats.rx_bytes += i1480u->rx_untd_pkt_size; net_dev->last_rx = jiffies; /* FIXME: flow control: check netif_rx() retval */ netif_rx(i1480u->rx_skb); /* deliver */ out: i1480u->rx_skb = NULL; i1480u->rx_untd_pkt_size = 0; }
/* * i2400m_net_erx - pass a network packet to the stack (extended version) * * @i2400m: device descriptor * @skb: the skb where the packet is - the skb should be set to point * at the IP packet; this function will add ethernet headers if * needed. * @cs: packet type * * This is only used now for firmware >= v1.4. Note it is quite * similar to i2400m_net_rx() (used only for v1.3 firmware). * * 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. */ void i2400m_net_erx(struct i2400m *i2400m, struct sk_buff *skb, enum i2400m_cs cs) { struct net_device *net_dev = i2400m->wimax_dev.net_dev; struct device *dev = i2400m_dev(i2400m); int protocol; d_fnstart(2, dev, "(i2400m %p skb %p [%u] cs %d)\n", i2400m, skb, skb->len, cs); switch(cs) { case I2400M_CS_IPV4_0: case I2400M_CS_IPV4: protocol = ETH_P_IP; 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 += skb->len; break; default: dev_err(dev, "ERX: BUG? CS type %u unsupported\n", cs); goto error; } d_printf(3, dev, "ERX: receiving %d bytes to the network stack\n", skb->len); d_dump(4, dev, skb->data, skb->len); netif_rx_ni(skb); /* see notes in function header */ error: d_fnend(2, dev, "(i2400m %p skb %p [%u] cs %d) = void\n", i2400m, skb, skb->len, cs); }
/* * Get the next TX message in the TX FIFO and send it to the device * * Note we exit the loop if i2400mu_tx() fails; that funtion only * fails on hard error (failing to tx a buffer not being one of them, * see its doc). * * Return: 0 */ static int i2400mu_txd(void *_i2400mu) { int result = 0; 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; d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); while (1) { d_printf(2, dev, "TX: waiting for messages\n"); tx_msg = NULL; wait_event_interruptible( i2400mu->tx_wq, (kthread_should_stop() /* check this first! */ || (tx_msg = i2400m_tx_msg_get(i2400m, &tx_msg_size))) ); if (kthread_should_stop()) break; WARN_ON(tx_msg == NULL); /* should not happen...*/ d_printf(2, dev, "TX: submitting %zu bytes\n", tx_msg_size); d_dump(5, dev, tx_msg, tx_msg_size); /* Yeah, we ignore errors ... not much we can do */ i2400mu_tx(i2400mu, tx_msg, tx_msg_size); i2400m_tx_msg_sent(i2400m); /* ack it, advance the FIFO */ if (result < 0) break; } d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result); return result; }
int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) { struct device *dev = wimax_dev_to_dev(wimax_dev); void *msg = skb->data; size_t size = skb->len; might_sleep(); d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); d_dump(2, dev, msg, size); genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); d_printf(1, dev, "CTX: genl multicast done\n"); return 0; }
ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *i2400m, const struct i2400m_bootrom_header *_cmd, size_t cmd_size, int flags) { ssize_t result; struct device *dev = i2400m_dev(i2400m); struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m); int opcode = _cmd == NULL ? -1 : i2400m_brh_get_opcode(_cmd); struct i2400m_bootrom_header *cmd; size_t cmd_size_a = ALIGN(cmd_size, I2400MS_BLK_SIZE); d_fnstart(5, dev, "(i2400m %p cmd %p size %zu)\n", i2400m, _cmd, cmd_size); result = -E2BIG; if (cmd_size > I2400M_BM_CMD_BUF_SIZE) goto error_too_big; if (_cmd != i2400m->bm_cmd_buf) memmove(i2400m->bm_cmd_buf, _cmd, cmd_size); cmd = i2400m->bm_cmd_buf; if (cmd_size_a > cmd_size) memset(i2400m->bm_cmd_buf + cmd_size, 0, cmd_size_a - cmd_size); if ((flags & I2400M_BM_CMD_RAW) == 0) { if (WARN_ON(i2400m_brh_get_response_required(cmd) == 0)) dev_warn(dev, "SW BUG: response_required == 0\n"); i2400m_bm_cmd_prepare(cmd); } d_printf(4, dev, "BM cmd %d: %zu bytes (%zu padded)\n", opcode, cmd_size, cmd_size_a); d_dump(5, dev, cmd, cmd_size); sdio_claim_host(i2400ms->func); result = sdio_memcpy_toio(i2400ms->func, I2400MS_DATA_ADDR, i2400m->bm_cmd_buf, cmd_size_a); sdio_release_host(i2400ms->func); if (result < 0) { dev_err(dev, "BM cmd %d: cannot send: %ld\n", opcode, (long) result); goto error_cmd_send; } result = cmd_size; error_cmd_send: error_too_big: d_fnend(5, dev, "(i2400m %p cmd %p size %zu) = %d\n", i2400m, _cmd, cmd_size, (int) result); return result; }
/** * wimax_msg_send - Send a pre-allocated message to user space * * @wimax_dev: WiMAX device descriptor * * @skb: &struct sk_buff returned by wimax_msg_alloc(). Note the * ownership of @skb is transferred to this function. * * Returns: 0 if ok, < 0 errno code on error * * Description: * * Sends a free-form message that was preallocated with * wimax_msg_alloc() and filled up. * * Assumes that once you pass an skb to this function for sending, it * owns it and will release it when done (on success). * * IMPORTANT: * * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as * wimax_msg_send() depends on skb->data being placed at the * beginning of the user message. */ int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb) { int result; struct device *dev = wimax_dev->net_dev->dev.parent; void *msg = skb->data; size_t size = skb->len; might_sleep(); d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size); d_dump(2, dev, msg, size); result = genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL); d_printf(1, dev, "CTX: genl multicast result %d\n", result); if (result == -ESRCH) /* Nobody connected, ignore it */ result = 0; /* btw, the skb is freed already */ return result; }
/* * 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 (!i2400m->wake_tx_skb) { 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 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; }
/* * 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); }
/** * i2400m_msg_to_dev - Send a control message to the device and get a response * * @i2400m: device descriptor * * @msg_skb: an skb * * * @buf: pointer to the buffer containing the message to be sent; it * has to start with a &struct i2400M_l3l4_hdr and then * followed by the payload. Once this function returns, the * buffer can be reused. * * @buf_len: buffer size * * Returns: * * Pointer to skb containing the ack message. You need to check the * pointer with IS_ERR(), as it might be an error code. Error codes * could happen because: * * - the message wasn't formatted correctly * - couldn't send the message * - failed waiting for a response * - the ack message wasn't formatted correctly * * The returned skb has been allocated with wimax_msg_to_user_alloc(), * it contains the response in a netlink attribute and is ready to be * passed up to user space with wimax_msg_to_user_send(). To access * the payload and its length, use wimax_msg_{data,len}() on the skb. * * The skb has to be freed with kfree_skb() once done. * * Description: * * This function delivers a message/command to the device and waits * for an ack to be received. The format is described in * linux/wimax/i2400m.h. In summary, a command/get/set is followed by an * ack. * * This function will not check the ack status, that's left up to the * caller. Once done with the ack skb, it has to be kfree_skb()ed. * * The i2400m handles only one message at the same time, thus we need * the mutex to exclude other players. * * We write the message and then wait for an answer to come back. The * RX path intercepts control messages and handles them in * i2400m_rx_ctl(). Reports (notifications) are (maybe) processed * locally and then forwarded (as needed) to user space on the WiMAX * stack message pipe. Acks are saved and passed back to us through an * skb in i2400m->ack_skb which is ready to be given to generic * netlink if need be. */ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, const void *buf, size_t buf_len) { int result; struct device *dev = i2400m_dev(i2400m); const struct i2400m_l3l4_hdr *msg_l3l4_hdr; struct sk_buff *ack_skb; const struct i2400m_l3l4_hdr *ack_l3l4_hdr; size_t ack_len; int ack_timeout; unsigned msg_type; unsigned long flags; d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n", i2400m, buf, buf_len); rmb(); /* Make sure we see what i2400m_dev_reset_handle() */ if (i2400m->boot_mode) return ERR_PTR(-EL3RST); msg_l3l4_hdr = buf; /* Check msg & payload consistency */ result = i2400m_msg_size_check(i2400m, msg_l3l4_hdr, buf_len); if (result < 0) goto error_bad_msg; msg_type = le16_to_cpu(msg_l3l4_hdr->type); d_printf(1, dev, "CMD/GET/SET 0x%04x %zu bytes\n", msg_type, buf_len); d_dump(2, dev, buf, buf_len); /* Setup the completion, ack_skb ("we are waiting") and send * the message to the device */ mutex_lock(&i2400m->msg_mutex); spin_lock_irqsave(&i2400m->rx_lock, flags); i2400m->ack_skb = ERR_PTR(-EINPROGRESS); spin_unlock_irqrestore(&i2400m->rx_lock, flags); init_completion(&i2400m->msg_completion); result = i2400m_tx(i2400m, buf, buf_len, I2400M_PT_CTRL); if (result < 0) { dev_err(dev, "can't send message 0x%04x: %d\n", le16_to_cpu(msg_l3l4_hdr->type), result); goto error_tx; } /* Some commands take longer to execute because of crypto ops, * so we give them some more leeway on timeout */ switch (msg_type) { case I2400M_MT_GET_TLS_OPERATION_RESULT: case I2400M_MT_CMD_SEND_EAP_RESPONSE: ack_timeout = 5 * HZ; break; default: ack_timeout = HZ; } if (unlikely(i2400m->trace_msg_from_user)) wimax_msg(&i2400m->wimax_dev, "echo", buf, buf_len, GFP_KERNEL); /* The RX path in rx.c will put any response for this message * in i2400m->ack_skb and wake us up. If we cancel the wait, * we need to change the value of i2400m->ack_skb to something * not -EINPROGRESS so RX knows there is no one waiting. */ result = wait_for_completion_interruptible_timeout( &i2400m->msg_completion, ack_timeout); if (result == 0) { dev_err(dev, "timeout waiting for reply to message 0x%04x\n", msg_type); result = -ETIMEDOUT; i2400m_msg_to_dev_cancel_wait(i2400m, result); goto error_wait_for_completion; } else if (result < 0) { dev_err(dev, "error waiting for reply to message 0x%04x: %d\n", msg_type, result); i2400m_msg_to_dev_cancel_wait(i2400m, result); goto error_wait_for_completion; } /* Pull out the ack data from i2400m->ack_skb -- see if it is * an error and act accordingly */ spin_lock_irqsave(&i2400m->rx_lock, flags); ack_skb = i2400m->ack_skb; if (IS_ERR(ack_skb)) result = PTR_ERR(ack_skb); else result = 0; i2400m->ack_skb = NULL; spin_unlock_irqrestore(&i2400m->rx_lock, flags); if (result < 0) goto error_ack_status; ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len); /* Check the ack and deliver it if it is ok */ if (unlikely(i2400m->trace_msg_from_user)) wimax_msg(&i2400m->wimax_dev, "echo", ack_l3l4_hdr, ack_len, GFP_KERNEL); result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len); if (result < 0) { dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n", msg_type, result); goto error_bad_ack_len; } if (msg_type != le16_to_cpu(ack_l3l4_hdr->type)) { dev_err(dev, "HW BUG? bad reply 0x%04x to message 0x%04x\n", le16_to_cpu(ack_l3l4_hdr->type), msg_type); result = -EIO; goto error_bad_ack_type; } i2400m_msg_ack_hook(i2400m, ack_l3l4_hdr, ack_len); mutex_unlock(&i2400m->msg_mutex); d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %p\n", i2400m, buf, buf_len, ack_skb); return ack_skb; error_bad_ack_type: error_bad_ack_len: kfree_skb(ack_skb); error_ack_status: error_wait_for_completion: error_tx: mutex_unlock(&i2400m->msg_mutex); error_bad_msg: d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %d\n", i2400m, buf, buf_len, result); return ERR_PTR(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; }
/** * i2400m_bootrom_init - Reboots a powered device into boot mode * * @i2400m: device descriptor * @flags: * I2400M_BRI_SOFT: a reboot barker has been seen * already, so don't wait for it. * * I2400M_BRI_NO_REBOOT: Don't send a reboot command, but wait * for a reboot barker notification. This is a one shot; if * the state machine needs to send a reboot command it will. * * Returns: * * < 0 errno code on error, 0 if ok. * * Description: * * Tries hard enough to put the device in boot-mode. There are two * main phases to this: * * a. (1) send a reboot command and (2) get a reboot barker * * b. (1) echo/ack the reboot sending the reboot barker back and (2) * getting an ack barker in return * * We want to skip (a) in some cases [soft]. The state machine is * horrible, but it is basically: on each phase, send what has to be * sent (if any), wait for the answer and act on the answer. We might * have to backtrack and retry, so we keep a max tries counter for * that. * * It sucks because we don't know ahead of time which is going to be * the reboot barker (the device might send different ones depending * on its EEPROM config) and once the device reboots and waits for the * echo/ack reboot barker being sent back, it doesn't understand * anything else. So we can be left at the point where we don't know * what to send to it -- cold reset and bus reset seem to have little * effect. So the function iterates (in this case) through all the * known barkers and tries them all until an ACK is * received. Otherwise, it gives up. * * If we get a timeout after sending a warm reset, we do it again. */ int i2400m_bootrom_init(struct i2400m *i2400m, enum i2400m_bri flags) { int result; struct device *dev = i2400m_dev(i2400m); struct i2400m_bootrom_header *cmd; struct i2400m_bootrom_header ack; int count = i2400m->bus_bm_retries; int ack_timeout_cnt = 1; unsigned i; BUILD_BUG_ON(sizeof(*cmd) != sizeof(i2400m_barker_db[0].data)); BUILD_BUG_ON(sizeof(ack) != sizeof(i2400m_ACK_BARKER)); d_fnstart(4, dev, "(i2400m %p flags 0x%08x)\n", i2400m, flags); result = -ENOMEM; cmd = i2400m->bm_cmd_buf; if (flags & I2400M_BRI_SOFT) goto do_reboot_ack; do_reboot: ack_timeout_cnt = 1; if (--count < 0) goto error_timeout; d_printf(4, dev, "device reboot: reboot command [%d # left]\n", count); if ((flags & I2400M_BRI_NO_REBOOT) == 0) i2400m_reset(i2400m, I2400M_RT_WARM); result = i2400m_bm_cmd(i2400m, NULL, 0, &ack, sizeof(ack), I2400M_BM_CMD_RAW); flags &= ~I2400M_BRI_NO_REBOOT; switch (result) { case -ERESTARTSYS: /* * at this point, i2400m_bm_cmd(), through * __i2400m_bm_ack_process(), has updated * i2400m->barker and we are good to go. */ d_printf(4, dev, "device reboot: got reboot barker\n"); break; case -EISCONN: /* we don't know how it got here...but we follow it */ d_printf(4, dev, "device reboot: got ack barker - whatever\n"); goto do_reboot; case -ETIMEDOUT: /* * Device has timed out, we might be in boot mode * already and expecting an ack; if we don't know what * the barker is, we just send them all. Cold reset * and bus reset don't work. Beats me. */ if (i2400m->barker != NULL) { dev_err(dev, "device boot: reboot barker timed out, " "trying (set) %08x echo/ack\n", le32_to_cpu(i2400m->barker->data[0])); goto do_reboot_ack; } for (i = 0; i < i2400m_barker_db_used; i++) { struct i2400m_barker_db *barker = &i2400m_barker_db[i]; memcpy(cmd, barker->data, sizeof(barker->data)); result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), &ack, sizeof(ack), I2400M_BM_CMD_RAW); if (result == -EISCONN) { dev_warn(dev, "device boot: got ack barker " "after sending echo/ack barker " "#%d/%08x; rebooting j.i.c.\n", i, le32_to_cpu(barker->data[0])); flags &= ~I2400M_BRI_NO_REBOOT; goto do_reboot; } } dev_err(dev, "device boot: tried all the echo/acks, could " "not get device to respond; giving up"); result = -ESHUTDOWN; case -EPROTO: case -ESHUTDOWN: /* dev is gone */ case -EINTR: /* user cancelled */ goto error_dev_gone; default: dev_err(dev, "device reboot: error %d while waiting " "for reboot barker - rebooting\n", result); d_dump(1, dev, &ack, result); goto do_reboot; } /* At this point we ack back with 4 REBOOT barkers and expect * 4 ACK barkers. This is ugly, as we send a raw command -- * hence the cast. _bm_cmd() will catch the reboot ack * notification and report it as -EISCONN. */ do_reboot_ack: d_printf(4, dev, "device reboot ack: sending ack [%d # left]\n", count); memcpy(cmd, i2400m->barker->data, sizeof(i2400m->barker->data)); result = i2400m_bm_cmd(i2400m, cmd, sizeof(*cmd), &ack, sizeof(ack), I2400M_BM_CMD_RAW); switch (result) { case -ERESTARTSYS: d_printf(4, dev, "reboot ack: got reboot barker - retrying\n"); if (--count < 0) goto error_timeout; goto do_reboot_ack; case -EISCONN: d_printf(4, dev, "reboot ack: got ack barker - good\n"); break; case -ETIMEDOUT: /* no response, maybe it is the other type? */ if (ack_timeout_cnt-- < 0) { d_printf(4, dev, "reboot ack timedout: retrying\n"); goto do_reboot_ack; } else { dev_err(dev, "reboot ack timedout too long: " "trying reboot\n"); goto do_reboot; } break; case -EPROTO: case -ESHUTDOWN: /* dev is gone */ goto error_dev_gone; default: dev_err(dev, "device reboot ack: error %d while waiting for " "reboot ack barker - rebooting\n", result); goto do_reboot; } d_printf(2, dev, "device reboot ack: got ack barker - boot done\n"); result = 0; exit_timeout: error_dev_gone: d_fnend(4, dev, "(i2400m %p flags 0x%08x) = %d\n", i2400m, flags, result); return result; error_timeout: dev_err(dev, "Timed out waiting for reboot ack\n"); result = -ETIMEDOUT; goto exit_timeout; }
struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m, const void *buf, size_t buf_len) { int result; struct device *dev = i2400m_dev(i2400m); const struct i2400m_l3l4_hdr *msg_l3l4_hdr; struct sk_buff *ack_skb; const struct i2400m_l3l4_hdr *ack_l3l4_hdr; size_t ack_len; int ack_timeout; unsigned msg_type; unsigned long flags; d_fnstart(3, dev, "(i2400m %p buf %p len %zu)\n", i2400m, buf, buf_len); rmb(); if (i2400m->boot_mode) return ERR_PTR(-EL3RST); msg_l3l4_hdr = buf; result = i2400m_msg_size_check(i2400m, msg_l3l4_hdr, buf_len); if (result < 0) goto error_bad_msg; msg_type = le16_to_cpu(msg_l3l4_hdr->type); d_printf(1, dev, "CMD/GET/SET 0x%04x %zu bytes\n", msg_type, buf_len); d_dump(2, dev, buf, buf_len); mutex_lock(&i2400m->msg_mutex); spin_lock_irqsave(&i2400m->rx_lock, flags); i2400m->ack_skb = ERR_PTR(-EINPROGRESS); spin_unlock_irqrestore(&i2400m->rx_lock, flags); init_completion(&i2400m->msg_completion); result = i2400m_tx(i2400m, buf, buf_len, I2400M_PT_CTRL); if (result < 0) { dev_err(dev, "can't send message 0x%04x: %d\n", le16_to_cpu(msg_l3l4_hdr->type), result); goto error_tx; } switch (msg_type) { case I2400M_MT_GET_TLS_OPERATION_RESULT: case I2400M_MT_CMD_SEND_EAP_RESPONSE: ack_timeout = 5 * HZ; break; default: ack_timeout = HZ; } if (unlikely(i2400m->trace_msg_from_user)) wimax_msg(&i2400m->wimax_dev, "echo", buf, buf_len, GFP_KERNEL); result = wait_for_completion_interruptible_timeout( &i2400m->msg_completion, ack_timeout); if (result == 0) { dev_err(dev, "timeout waiting for reply to message 0x%04x\n", msg_type); result = -ETIMEDOUT; i2400m_msg_to_dev_cancel_wait(i2400m, result); goto error_wait_for_completion; } else if (result < 0) { dev_err(dev, "error waiting for reply to message 0x%04x: %d\n", msg_type, result); i2400m_msg_to_dev_cancel_wait(i2400m, result); goto error_wait_for_completion; } spin_lock_irqsave(&i2400m->rx_lock, flags); ack_skb = i2400m->ack_skb; if (IS_ERR(ack_skb)) result = PTR_ERR(ack_skb); else result = 0; i2400m->ack_skb = NULL; spin_unlock_irqrestore(&i2400m->rx_lock, flags); if (result < 0) goto error_ack_status; ack_l3l4_hdr = wimax_msg_data_len(ack_skb, &ack_len); if (unlikely(i2400m->trace_msg_from_user)) wimax_msg(&i2400m->wimax_dev, "echo", ack_l3l4_hdr, ack_len, GFP_KERNEL); result = i2400m_msg_size_check(i2400m, ack_l3l4_hdr, ack_len); if (result < 0) { dev_err(dev, "HW BUG? reply to message 0x%04x: %d\n", msg_type, result); goto error_bad_ack_len; } if (msg_type != le16_to_cpu(ack_l3l4_hdr->type)) { dev_err(dev, "HW BUG? bad reply 0x%04x to message 0x%04x\n", le16_to_cpu(ack_l3l4_hdr->type), msg_type); result = -EIO; goto error_bad_ack_type; } i2400m_msg_ack_hook(i2400m, ack_l3l4_hdr, ack_len); mutex_unlock(&i2400m->msg_mutex); d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %p\n", i2400m, buf, buf_len, ack_skb); return ack_skb; error_bad_ack_type: error_bad_ack_len: kfree_skb(ack_skb); error_ack_status: error_wait_for_completion: error_tx: mutex_unlock(&i2400m->msg_mutex); error_bad_msg: d_fnend(3, dev, "(i2400m %p buf %p len %zu) = %d\n", i2400m, buf, buf_len, result); return ERR_PTR(result); }