/* * Read data from the device (when in normal) * * Allocate an SKB of the right size, read the data in and then * deliver it to the generic layer. * * We also check for a reboot barker. That means the device died and * we have to reboot it. */ static void i2400ms_rx(struct i2400ms *i2400ms) { int ret; struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; struct i2400m *i2400m = &i2400ms->i2400m; struct sk_buff *skb; ssize_t rx_size; d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); rx_size = __i2400ms_rx_get_size(i2400ms); if (rx_size < 0) { ret = rx_size; goto error_get_size; } ret = -ENOMEM; skb = alloc_skb(rx_size, GFP_ATOMIC); if (NULL == skb) { dev_err(dev, "RX: unable to alloc skb\n"); goto error_alloc_skb; } ret = sdio_memcpy_fromio(func, skb->data, I2400MS_DATA_ADDR, rx_size); if (ret < 0) { dev_err(dev, "RX: SDIO data read failed: %d\n", ret); goto error_memcpy_fromio; } rmb(); /* make sure we get boot_mode from dev_reset_handle */ if (i2400m->boot_mode == 1) { spin_lock(&i2400m->rx_lock); i2400ms->bm_ack_size = rx_size; spin_unlock(&i2400m->rx_lock); memcpy(i2400m->bm_ack_buf, skb->data, rx_size); wake_up(&i2400ms->bm_wfa_wq); dev_err(dev, "RX: SDIO boot mode message\n"); kfree_skb(skb); } else if (unlikely(!memcmp(skb->data, i2400m_NBOOT_BARKER, sizeof(i2400m_NBOOT_BARKER)) || !memcmp(skb->data, i2400m_SBOOT_BARKER, sizeof(i2400m_SBOOT_BARKER)))) { ret = i2400m_dev_reset_handle(i2400m); dev_err(dev, "RX: SDIO reboot barker\n"); kfree_skb(skb); } else { skb_put(skb, rx_size); i2400m_rx(i2400m, skb); } d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); return; error_memcpy_fromio: kfree_skb(skb); error_alloc_skb: error_get_size: d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); return; }
/* * Read data from the device (when in normal) * * Allocate an SKB of the right size, read the data in and then * deliver it to the generic layer. * * We also check for a reboot barker. That means the device died and * we have to reboot it. */ static void i2400ms_rx(struct i2400ms *i2400ms) { int ret; struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; struct i2400m *i2400m = &i2400ms->i2400m; struct sk_buff *skb; ssize_t rx_size; d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); rx_size = __i2400ms_rx_get_size(i2400ms); if (rx_size < 0) { ret = rx_size; goto error_get_size; } ret = -ENOMEM; skb = alloc_skb(rx_size, GFP_ATOMIC); if (NULL == skb) { dev_err(dev, "RX: unable to alloc skb\n"); goto error_alloc_skb; } ret = sdio_memcpy_fromio(func, skb->data, I2400MS_DATA_ADDR, rx_size); if (ret < 0) { dev_err(dev, "RX: SDIO data read failed: %d\n", ret); goto error_memcpy_fromio; } /* Check if device has reset */ if (!memcmp(skb->data, i2400m_NBOOT_BARKER, sizeof(i2400m_NBOOT_BARKER)) || !memcmp(skb->data, i2400m_SBOOT_BARKER, sizeof(i2400m_SBOOT_BARKER))) { ret = i2400m_dev_reset_handle(i2400m); kfree_skb(skb); } else { skb_put(skb, rx_size); i2400m_rx(i2400m, skb); } d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); return; error_memcpy_fromio: kfree_skb(skb); error_alloc_skb: error_get_size: d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); return; }
/* * Kernel thread for USB reception of data * * This thread waits for a kick; once kicked, it will allocate an skb * and receive a single message to it from USB (using * i2400mu_rx()). Once received, it is passed to the generic i2400m RX * code for processing. * * When done processing, it runs some dirty statistics to verify if * the last 100 messages received were smaller than half of the * current RX buffer size. In that case, the RX buffer size is * halved. This will helps lowering the pressure on the memory * allocator. * * Hard errors force the thread to exit. */ static int i2400mu_rxd(void *_i2400mu) { int result = 0; struct i2400mu *i2400mu = _i2400mu; struct i2400m *i2400m = &i2400mu->i2400m; struct device *dev = &i2400mu->usb_iface->dev; struct net_device *net_dev = i2400m->wimax_dev.net_dev; size_t pending; int rx_size; struct sk_buff *rx_skb; unsigned long flags; d_fnstart(4, dev, "(i2400mu %p)\n", i2400mu); spin_lock_irqsave(&i2400m->rx_lock, flags); BUG_ON(i2400mu->rx_kthread != NULL); i2400mu->rx_kthread = current; spin_unlock_irqrestore(&i2400m->rx_lock, flags); while (1) { d_printf(2, dev, "RX: waiting for messages\n"); pending = 0; wait_event_interruptible( i2400mu->rx_wq, (kthread_should_stop() /* check this first! */ || (pending = atomic_read(&i2400mu->rx_pending_count))) ); if (kthread_should_stop()) break; if (pending == 0) continue; rx_size = i2400mu->rx_size; d_printf(2, dev, "RX: reading up to %d bytes\n", rx_size); rx_skb = __netdev_alloc_skb(net_dev, rx_size, GFP_KERNEL); if (rx_skb == NULL) { dev_err(dev, "RX: can't allocate skb [%d bytes]\n", rx_size); msleep(50); /* give it some time? */ continue; } /* Receive the message with the payloads */ rx_skb = i2400mu_rx(i2400mu, rx_skb); result = PTR_ERR(rx_skb); if (IS_ERR(rx_skb)) goto out; atomic_dec(&i2400mu->rx_pending_count); if (rx_skb == NULL || rx_skb->len == 0) { /* some "ignorable" condition */ kfree_skb(rx_skb); continue; } /* Deliver the message to the generic i2400m code */ i2400mu->rx_size_cnt++; i2400mu->rx_size_acc += rx_skb->len; result = i2400m_rx(i2400m, rx_skb); if (result == -EIO && edc_inc(&i2400mu->urb_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { goto error_reset; } /* Maybe adjust RX buffer size */ i2400mu_rx_size_maybe_shrink(i2400mu); } result = 0; out: spin_lock_irqsave(&i2400m->rx_lock, flags); i2400mu->rx_kthread = NULL; spin_unlock_irqrestore(&i2400m->rx_lock, flags); d_fnend(4, dev, "(i2400mu %p) = %d\n", i2400mu, result); return result; error_reset: dev_err(dev, "RX: maximum errors in received buffer exceeded; " "resetting device\n"); usb_queue_reset_device(i2400mu->usb_iface); goto out; }
static void i2400ms_rx(struct i2400ms *i2400ms) { int ret; struct sdio_func *func = i2400ms->func; struct device *dev = &func->dev; struct i2400m *i2400m = &i2400ms->i2400m; struct sk_buff *skb; ssize_t rx_size; d_fnstart(7, dev, "(i2400ms %p)\n", i2400ms); rx_size = __i2400ms_rx_get_size(i2400ms); if (rx_size < 0) { ret = rx_size; goto error_get_size; } sdio_writeb(func, 1, I2400MS_INTR_CLEAR_ADDR, &ret); ret = -ENOMEM; skb = alloc_skb(rx_size, GFP_ATOMIC); if (NULL == skb) { dev_err(dev, "RX: unable to alloc skb\n"); goto error_alloc_skb; } ret = sdio_memcpy_fromio(func, skb->data, I2400MS_DATA_ADDR, rx_size); if (ret < 0) { dev_err(dev, "RX: SDIO data read failed: %d\n", ret); goto error_memcpy_fromio; } rmb(); if (unlikely(i2400m->boot_mode == 1)) { spin_lock(&i2400m->rx_lock); i2400ms->bm_ack_size = rx_size; spin_unlock(&i2400m->rx_lock); memcpy(i2400m->bm_ack_buf, skb->data, rx_size); wake_up(&i2400ms->bm_wfa_wq); d_printf(5, dev, "RX: SDIO boot mode message\n"); kfree_skb(skb); goto out; } ret = -EIO; if (unlikely(rx_size < sizeof(__le32))) { dev_err(dev, "HW BUG? only %zu bytes received\n", rx_size); goto error_bad_size; } if (likely(i2400m_is_d2h_barker(skb->data))) { skb_put(skb, rx_size); i2400m_rx(i2400m, skb); } else if (unlikely(i2400m_is_boot_barker(i2400m, skb->data, rx_size))) { ret = i2400m_dev_reset_handle(i2400m, "device rebooted"); dev_err(dev, "RX: SDIO reboot barker\n"); kfree_skb(skb); } else { i2400m_unknown_barker(i2400m, skb->data, rx_size); kfree_skb(skb); } out: d_fnend(7, dev, "(i2400ms %p) = void\n", i2400ms); return; error_memcpy_fromio: kfree_skb(skb); error_alloc_skb: error_get_size: error_bad_size: d_fnend(7, dev, "(i2400ms %p) = %d\n", i2400ms, ret); }