示例#1
0
static int rx_submit(struct usbpn_dev *pnd, struct urb *req, gfp_t gfp_flags)
{
	struct net_device *dev = pnd->dev;
	struct page *page;
	int err;

	page = __netdev_alloc_page(dev, gfp_flags);
	if (!page)
		return -ENOMEM;

	usb_fill_bulk_urb(req, pnd->usb, pnd->rx_pipe, page_address(page),
				PAGE_SIZE, rx_complete, dev);
	req->transfer_flags = 0;
	err = usb_submit_urb(req, gfp_flags);
	if (unlikely(err)) {
		dev_dbg(&dev->dev, "RX submit error (%d)\n", err);
		netdev_free_page(dev, page);
	}
	return err;
}
示例#2
0
static int rx_submit(struct usbsvn *svn, int dev_id, struct urb *req,
		gfp_t gfp_flags)
{
	struct net_device *dev = svn->netdev;
	struct usbsvn_devdata *devdata = &svn->devdata[dev_id];
	struct usbsvn_rx *svn_rx;
	struct page *page;
	int err;

	svn_rx = kzalloc(sizeof(struct usbsvn_rx), gfp_flags);
	if (!svn_rx)
		return -ENOMEM;

	page = __netdev_alloc_page(dev, gfp_flags);
	if (!page) {
		kfree(svn_rx);
		return -ENOMEM;
	}

	svn_rx->netdev = dev;
	svn_rx->dev_id = dev_id;

	usb_fill_bulk_urb(req, svn->usbdev, devdata->rx_pipe,
			page_address(page), PAGE_SIZE, rx_complete, svn_rx);
	req->transfer_flags = 0;

	err = usb_submit_urb(req, gfp_flags);
	if (unlikely(err)) {
		dev_err(&dev->dev, "RX submit error (%d)\n", err);
		kfree(svn_rx);
		netdev_free_page(dev, page);
	}
	usb_mark_last_busy(req->dev);

	return err;
}
示例#3
0
static int sipc4_hdlc_rx(struct sipc4_rx_data *data)
{
	int rest = data->size;
	char *buf = page_address(data->page);
	int len;
	int err = -ERANGE;

	if (rest <= 0)
		goto end;

	if (data->format == SIPC4_FMT)
		printk(KERN_DEBUG "IPC:RX size=%d\n", data->size);

next_frame:
	err = len = sipc4_check_header(data, buf, rest);
	if (err < 0)
		goto end;
	buf += len;
	rest -= len;
	if (rest <= 0)
		goto end;

	err = len = sipc4_check_data(data, buf, rest);
	if (err < 0)
		goto end;
	buf += len;
	rest -= len;
	if (rest <= 0)
		goto end;

	err = len = sipc4_check_hdlc_end(data, buf);
	if (err < 0)
		goto end;
	buf += len;
	rest -= len;
	if (rest < 0)
		goto end;

	err = sipc4_hdlc_format_rx(data);
	if (err < 0)
		goto end;
	memset(data->rx_hdr, 0x00, sizeof(struct sipc_rx_hdr));

	data->skb = NULL;

	if (rest)
		goto next_frame;

end:
	netdev_free_page(data->dev, data->page);

	if (rest < 0)
		err = -ERANGE;

	if (err < 0 && data->skb) {
		dev_kfree_skb_any(data->skb);
		data->skb = NULL;
	}

	return err;
}
示例#4
0
static void rx_complete(struct urb *req)
{
	struct net_device *dev = req->context;
	struct usbpn_dev *pnd = netdev_priv(dev);
	struct page *page = virt_to_page(req->transfer_buffer);
	struct sk_buff *skb;
	unsigned long flags;

	switch (req->status) {
	case 0:
		spin_lock_irqsave(&pnd->rx_lock, flags);
		skb = pnd->rx_skb;
		if (!skb) {
			skb = pnd->rx_skb = netdev_alloc_skb(dev, 12);
			if (likely(skb)) {
				/* Can't use pskb_pull() on page in IRQ */
				memcpy(skb_put(skb, 1), page_address(page), 1);
				skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
						page, 1, req->actual_length);
				page = NULL;
			}
		} else {
			skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
					page, 0, req->actual_length);
			page = NULL;
		}
		if (req->actual_length < PAGE_SIZE)
			pnd->rx_skb = NULL; /* Last fragment */
		else
			skb = NULL;
		spin_unlock_irqrestore(&pnd->rx_lock, flags);
		if (skb) {
			skb->protocol = htons(ETH_P_PHONET);
			skb_reset_mac_header(skb);
			__skb_pull(skb, 1);
			skb->dev = dev;
			dev->stats.rx_packets++;
			dev->stats.rx_bytes += skb->len;

			netif_rx(skb);
		}
		goto resubmit;

	case -ENOENT:
	case -ECONNRESET:
	case -ESHUTDOWN:
		req = NULL;
		break;

	case -EOVERFLOW:
		dev->stats.rx_over_errors++;
		dev_dbg(&dev->dev, "RX overflow\n");
		break;

	case -EILSEQ:
		dev->stats.rx_crc_errors++;
		break;
	}

	dev->stats.rx_errors++;
resubmit:
	if (page)
		netdev_free_page(dev, page);
	if (req)
		rx_submit(pnd, req, GFP_ATOMIC);
}
示例#5
0
static void rx_complete(struct urb *req)
{
	struct usbsvn_rx *svn_rx = req->context;
	struct net_device *dev = svn_rx->netdev;
	struct usbsvn *svn = netdev_priv(dev);
	struct page *page = virt_to_page(req->transfer_buffer);
	struct sipc4_rx_data rx_data;
	int dev_id = svn_rx->dev_id;
	int flags = 0;
	int err;

	usb_mark_last_busy(svn->usbdev);

	switch (req->status) {
	case -ENOENT:
		if (req->actual_length == 0) {
			req = NULL;
			break;
		}
		printk(KERN_DEBUG "%s: Rx ENOENT", __func__);

	case 0:
		if (!svn->driver_info)
			flags |= SIPC4_RX_HDLC;
		if (req->actual_length < PAGE_SIZE)
			flags |= SIPC4_RX_LAST;

		rx_data.dev = dev;
		rx_data.skb = svn->devdata[dev_id].rx_skb;
		rx_data.page = page;
		rx_data.size = req->actual_length;
		rx_data.format = dev_id;
		rx_data.flags = flags;
		rx_data.rx_hdr = &svn->devdata[dev_id].rx_hdr;

		page = NULL;

		if (rx_debug) {
			char *buf = req->transfer_buffer;
			int i;

			printk(KERN_DEBUG "[RX] dev_id: %d, size: %d\n", dev_id,
					req->actual_length);
			for (i = 0; i < req->actual_length; i++)
				printk(KERN_DEBUG "%x ", *(buf + i));
		}

		if (dev_id == SIPC4_CMD)
			err = usbsvn_cmd_rx(&rx_data, svn);
		else
			err = sipc4_rx(&rx_data);
		if (err < 0) {
			svn->devdata[dev_id].rx_skb = NULL;
			break;
		}
		svn->devdata[dev_id].rx_skb = rx_data.skb;

		if (dev_id == SIPC4_RAW)
			wake_lock_timeout_data(svn);

		goto resubmit;

	case -ECONNRESET:
	case -ESHUTDOWN:
		if (!svn->suspended)
			printk(KERN_DEBUG "%s: RX complete Status(%d)\n",
				__func__, req->status);
		req = NULL;
		break;

	case -EOVERFLOW:
		dev->stats.rx_over_errors++;
		dev_err(&dev->dev, "RX overflow\n");
		break;

	case -EILSEQ:
		dev->stats.rx_crc_errors++;
		break;
	}

	dev->stats.rx_errors++;

resubmit:
	kfree(svn_rx);

	if (page)
		netdev_free_page(dev, page);
	if (req && req->status != -ENOENT) {
		rx_submit(svn, dev_id, req, GFP_ATOMIC);
	}
}
示例#6
0
static int sipc4_hdlc_rx(struct sipc4_rx_data *data)
{
	int rest = data->size;
	char *buf = page_address(data->page);
	int len;
	int err;

	static __be16 protocol;
	int ch;

	char *ptr = buf;
	int size = rest;
	int pos = 0;
	int retrycnt = 0;

	if (rest <= 0)
		goto end;

next_frame:
	err = len = sipc4_check_header(data, buf, rest);
	if (err < 0) {
		_debug_sipc4_print(data, ptr, pos);
		goto end;
	}

	buf += len;
	rest -= len;
	pos += len;

	if (rest == 0)
		goto end;

	if (rest < 0) {
		pr_err("err - r:%d, l:%d, t: %d (%d)\n",
				rest, len, retrycnt, __LINE__);
		_debug_sipc4_print(data, ptr, pos);
		goto end;
	}

	if (data->format == SIPC4_RAW && len != 0) {
		ch = sipc4_get_hdlc_ch(data->skb->data, data->format);
		if (ch >= (CHID_PSD_DATA1) && ch <= CHID_PSD_DATA15) {
			if ((*buf & 0xF0) == 0x60)
				protocol = htons(ETH_P_IPV6);
			else if ((*buf & 0xF0) == 0x40)
				protocol = htons(ETH_P_IP);
			else {
				err = -EINVAL;
				pr_err("err - ip ver\n");
				_debug_sipc4_print(data, ptr, pos);
				goto end;
			}
		}
	}

	err = len = sipc4_check_data(data, buf, rest, protocol);
	if (err < 0) {
		pr_err("err - sipc4 data\n");
		_debug_sipc4_print(data, ptr, pos);
		goto end;
	}
	buf += len;
	rest -= len;
	pos += len;
	if (rest == 0)	/* this packet is splitted */
		goto end;

	if (rest < 0) {
		pr_err("err - r:%d, l:%d, t: %d (%d)\n",
				rest, len, retrycnt, __LINE__);
		_debug_sipc4_print(data, ptr, pos);
		goto end;
	}

	err = len = sipc4_check_hdlc_end(data, buf, size);
	if (err < 0) {
		pr_err("err - r:%d, l:%d, t: %d (%d)\n",
				rest, len, retrycnt, __LINE__);
		_debug_sipc4_print(data, ptr, pos);
		goto end;
	}
	buf += len;
	rest -= len;
	pos += len;
	if (rest < 0) {
		pr_err("err - r:%d, l:%d, t: %d (%d)\n",
				rest, len, retrycnt, __LINE__);
		_debug_sipc4_print(data, ptr, pos);
		goto end;
	}

	err = sipc4_hdlc_format_rx(data, protocol);
	if (err < 0) {
		pr_err("err - hdlc rx\n");
		_debug_sipc4_print(data, ptr, pos);
		goto end;
	}

	data->skb = NULL;

	if (rest) {
		retrycnt++;
		goto next_frame;
	}

end:
	netdev_free_page(data->dev, data->page);

	if (rest < 0)
		err = -ERANGE;

	if (err < 0 && data->skb) {
		dev_kfree_skb_any(data->skb);
		data->skb = NULL;
	}

	return err;
}