Beispiel #1
0
static void brcmf_usb_rx_complete(struct urb *urb)
{
	struct brcmf_usbreq  *req = (struct brcmf_usbreq *)urb->context;
	struct brcmf_usbdev_info *devinfo = req->devinfo;
	struct sk_buff *skb;

	brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
	brcmf_usb_del_fromq(devinfo, req);
	skb = req->skb;
	req->skb = NULL;

	/* zero lenght packets indicate usb "failure". Do not refill */
	if (urb->status != 0 || !urb->actual_length) {
		brcmu_pkt_buf_free_skb(skb);
		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
		return;
	}

	if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
		skb_put(skb, urb->actual_length);
		brcmf_rx_frame(devinfo->dev, skb);
		brcmf_usb_rx_refill(devinfo, req);
	} else {
		brcmu_pkt_buf_free_skb(skb);
		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
	}
	return;

}
Beispiel #2
0
static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
				struct brcmf_usbreq  *req)
{
	struct sk_buff *skb;
	int ret;

	if (!req || !devinfo)
		return;

	skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
	if (!skb) {
		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
		return;
	}
	req->skb = skb;

	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
			  skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
			  req);
	req->devinfo = devinfo;
	brcmf_usb_enq(devinfo, &devinfo->rx_postq, req, NULL);

	ret = usb_submit_urb(req->urb, GFP_ATOMIC);
	if (ret) {
		brcmf_usb_del_fromq(devinfo, req);
		brcmu_pkt_buf_free_skb(req->skb);
		req->skb = NULL;
		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL);
	}
	return;
}
Beispiel #3
0
static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
                                struct brcmf_usbreq  *req)
{
    struct sk_buff *skb;
    int ret;

    if (!req || !devinfo)
        return;

    skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
    if (!skb) {
        brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
        return;
    }
    req->skb = skb;

    usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
                      skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
                      req);
    req->urb->transfer_flags |= URB_ZERO_PACKET;
    req->devinfo = devinfo;

    ret = usb_submit_urb(req->urb, GFP_ATOMIC);
    if (ret == 0) {
        brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
    } else {
        dev_kfree_skb(req->skb);
        req->skb = NULL;
        brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
    }
    return;
}
Beispiel #4
0
static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
{
	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
	struct brcmf_usbreq  *req;
	int ret;

	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
		/* TODO: handle suspend/resume */
		return -EIO;
	}

	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);
	if (!req) {
		brcmu_pkt_buf_free_skb(skb);
		brcmf_dbg(ERROR, "no req to send\n");
		return -ENOMEM;
	}

	req->skb = skb;
	req->devinfo = devinfo;
	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
			  skb->data, skb->len, brcmf_usb_tx_complete, req);
	req->urb->transfer_flags |= URB_ZERO_PACKET;
	brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
	ret = usb_submit_urb(req->urb, GFP_ATOMIC);
	if (ret) {
		brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
		brcmf_usb_del_fromq(devinfo, req);
		brcmu_pkt_buf_free_skb(req->skb);
		req->skb = NULL;
		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
	}

	return ret;
}
Beispiel #5
0
static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
{
	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
	struct brcmf_usbreq  *req;
	int ret;
	unsigned long flags;

	brcmf_dbg(USB, "Enter, skb=%p\n", skb);
	if (devinfo->bus_pub.state != BRCMFMAC_USB_STATE_UP) {
		ret = -EIO;
		goto fail;
	}

	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq,
					&devinfo->tx_freecount);
	if (!req) {
		brcmf_err("no req to send\n");
		ret = -ENOMEM;
		goto fail;
	}

	req->skb = skb;
	req->devinfo = devinfo;
	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
			  skb->data, skb->len, brcmf_usb_tx_complete, req);
	req->urb->transfer_flags |= URB_ZERO_PACKET;
	brcmf_usb_enq(devinfo, &devinfo->tx_postq, req, NULL);
	ret = usb_submit_urb(req->urb, GFP_ATOMIC);
	if (ret) {
		brcmf_err("brcmf_usb_tx usb_submit_urb FAILED\n");
		brcmf_usb_del_fromq(devinfo, req);
		req->skb = NULL;
		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req,
			      &devinfo->tx_freecount);
		goto fail;
	}

	spin_lock_irqsave(&devinfo->tx_flowblock_lock, flags);
	if (devinfo->tx_freecount < devinfo->tx_low_watermark &&
	    !devinfo->tx_flowblock) {
		brcmf_txflowblock(dev, true);
		devinfo->tx_flowblock = true;
	}
	spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags);
	return 0;

fail:
	return ret;
}
Beispiel #6
0
static void brcmf_usb_rx_complete(struct urb *urb)
{
	struct brcmf_usbreq  *req = (struct brcmf_usbreq *)urb->context;
	struct brcmf_usbdev_info *devinfo = req->devinfo;
	struct sk_buff *skb;
	int ifidx = 0;

	brcmf_usb_del_fromq(devinfo, req);
	skb = req->skb;
	req->skb = NULL;

	if (urb->status == 0) {
		devinfo->bus_pub.bus->dstats.rx_packets++;
	} else {
		devinfo->bus_pub.bus->dstats.rx_errors++;
		brcmu_pkt_buf_free_skb(skb);
		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
		return;
	}

	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
		skb_put(skb, urb->actual_length);
		if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
			brcmf_dbg(ERROR, "rx protocol error\n");
			brcmu_pkt_buf_free_skb(skb);
			brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
			devinfo->bus_pub.bus->dstats.rx_errors++;
		} else {
			brcmf_rx_packet(devinfo->dev, ifidx, skb);
			brcmf_usb_rx_refill(devinfo, req);
		}
	} else {
		brcmu_pkt_buf_free_skb(skb);
		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
	}
	return;

}
Beispiel #7
0
static void brcmf_usb_tx_complete(struct urb *urb)
{
    struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
    struct brcmf_usbdev_info *devinfo = req->devinfo;

    brcmf_usb_del_fromq(devinfo, req);
    if (urb->status == 0)
        devinfo->bus_pub.bus->dstats.tx_packets++;
    else
        devinfo->bus_pub.bus->dstats.tx_errors++;

    dev_kfree_skb(req->skb);
    req->skb = NULL;
    brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);

}
Beispiel #8
0
static void brcmf_usb_tx_complete(struct urb *urb)
{
	struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
	struct brcmf_usbdev_info *devinfo = req->devinfo;
	unsigned long flags;

	brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status,
		  req->skb);
	brcmf_usb_del_fromq(devinfo, req);

	brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0);
	req->skb = NULL;
	brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount);
	spin_lock_irqsave(&devinfo->tx_flowblock_lock, flags);
	if (devinfo->tx_freecount > devinfo->tx_high_watermark &&
		devinfo->tx_flowblock) {
		brcmf_txflowblock(devinfo->dev, false);
		devinfo->tx_flowblock = false;
	}
	spin_unlock_irqrestore(&devinfo->tx_flowblock_lock, flags);
}