]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/uwb/i1480/i1480u-wlp/tx.c
Merge tag 'v2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / uwb / i1480 / i1480u-wlp / tx.c
diff --git a/drivers/uwb/i1480/i1480u-wlp/tx.c b/drivers/uwb/i1480/i1480u-wlp/tx.c
deleted file mode 100644 (file)
index 3c117a3..0000000
+++ /dev/null
@@ -1,584 +0,0 @@
-/*
- * WUSB Wire Adapter: WLP interface
- * Deal with TX (massaging data to transmit, handling it)
- *
- * Copyright (C) 2005-2006 Intel Corporation
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- *
- * Transmission engine. Get an skb, create from that a WLP transmit
- * context, add a WLP TX header (which we keep prefilled in the
- * device's instance), fill out the target-specific fields and
- * fire it.
- *
- * ROADMAP:
- *
- *   Entry points:
- *
- *     i1480u_tx_release(): called by i1480u_disconnect() to release
- *                          pending tx contexts.
- *
- *     i1480u_tx_cb(): callback for TX contexts (USB URBs)
- *       i1480u_tx_destroy():
- *
- *     i1480u_tx_timeout(): called for timeout handling from the
- *                          network stack.
- *
- *     i1480u_hard_start_xmit(): called for transmitting an skb from
- *                               the network stack. Will interact with WLP
- *                               substack to verify and prepare frame.
- *       i1480u_xmit_frame(): actual transmission on hardware
- *
- *         i1480u_tx_create()      Creates TX context
- *            i1480u_tx_create_1()    For packets in 1 fragment
- *            i1480u_tx_create_n()    For packets in >1 fragments
- *
- * TODO:
- *
- * - FIXME: rewrite using usb_sg_*(), add asynch support to
- *          usb_sg_*(). It might not make too much sense as most of
- *          the times the MTU will be smaller than one page...
- */
-
-#include <linux/slab.h>
-#include "i1480u-wlp.h"
-
-enum {
-       /* This is only for Next and Last TX packets */
-       i1480u_MAX_PL_SIZE = i1480u_MAX_FRG_SIZE
-               - sizeof(struct untd_hdr_rst),
-};
-
-/* Free resources allocated to a i1480u tx context. */
-static
-void i1480u_tx_free(struct i1480u_tx *wtx)
-{
-       kfree(wtx->buf);
-       if (wtx->skb)
-               dev_kfree_skb_irq(wtx->skb);
-       usb_free_urb(wtx->urb);
-       kfree(wtx);
-}
-
-static
-void i1480u_tx_destroy(struct i1480u *i1480u, struct i1480u_tx *wtx)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);        /* not active any more */
-       list_del(&wtx->list_node);
-       i1480u_tx_free(wtx);
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-}
-
-static
-void i1480u_tx_unlink_urbs(struct i1480u *i1480u)
-{
-       unsigned long flags;
-       struct i1480u_tx *wtx, *next;
-
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-       list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) {
-               usb_unlink_urb(wtx->urb);
-       }
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-}
-
-
-/*
- * Callback for a completed tx USB URB.
- *
- * TODO:
- *
- * - FIXME: recover errors more gracefully
- * - FIXME: handle NAKs (I dont think they come here) for flow ctl
- */
-static
-void i1480u_tx_cb(struct urb *urb)
-{
-       struct i1480u_tx *wtx = urb->context;
-       struct i1480u *i1480u = wtx->i1480u;
-       struct net_device *net_dev = i1480u->net_dev;
-       struct device *dev = &i1480u->usb_iface->dev;
-       unsigned long flags;
-
-       switch (urb->status) {
-       case 0:
-               spin_lock_irqsave(&i1480u->lock, flags);
-               net_dev->stats.tx_packets++;
-               net_dev->stats.tx_bytes += urb->actual_length;
-               spin_unlock_irqrestore(&i1480u->lock, flags);
-               break;
-       case -ECONNRESET:       /* Not an error, but a controlled situation; */
-       case -ENOENT:           /* (we killed the URB)...so, no broadcast */
-               dev_dbg(dev, "notif endp: reset/noent %d\n", urb->status);
-               netif_stop_queue(net_dev);
-               break;
-       case -ESHUTDOWN:        /* going away! */
-               dev_dbg(dev, "notif endp: down %d\n", urb->status);
-               netif_stop_queue(net_dev);
-               break;
-       default:
-               dev_err(dev, "TX: unknown URB status %d\n", urb->status);
-               if (edc_inc(&i1480u->tx_errors, EDC_MAX_ERRORS,
-                                       EDC_ERROR_TIMEFRAME)) {
-                       dev_err(dev, "TX: max acceptable errors exceeded."
-                                       "Reset device.\n");
-                       netif_stop_queue(net_dev);
-                       i1480u_tx_unlink_urbs(i1480u);
-                       wlp_reset_all(&i1480u->wlp);
-               }
-               break;
-       }
-       i1480u_tx_destroy(i1480u, wtx);
-       if (atomic_dec_return(&i1480u->tx_inflight.count)
-           <= i1480u->tx_inflight.threshold
-           && netif_queue_stopped(net_dev)
-           && i1480u->tx_inflight.threshold != 0) {
-               netif_start_queue(net_dev);
-               atomic_inc(&i1480u->tx_inflight.restart_count);
-       }
-       return;
-}
-
-
-/*
- * Given a buffer that doesn't fit in a single fragment, create an
- * scatter/gather structure for delivery to the USB pipe.
- *
- * Implements functionality of i1480u_tx_create().
- *
- * @wtx:       tx descriptor
- * @skb:       skb to send
- * @gfp_mask:  gfp allocation mask
- * @returns:    Pointer to @wtx if ok, NULL on error.
- *
- * Sorry, TOO LONG a function, but breaking it up is kind of hard
- *
- * This will break the buffer in chunks smaller than
- * i1480u_MAX_FRG_SIZE (including the header) and add proper headers
- * to each:
- *
- *   1st header           \
- *   i1480 tx header      |  fragment 1
- *   fragment data        /
- *   nxt header           \  fragment 2
- *   fragment data        /
- *   ..
- *   ..
- *   last header          \  fragment 3
- *   last fragment data   /
- *
- * This does not fill the i1480 TX header, it is left up to the
- * caller to do that; you can get it from @wtx->wlp_tx_hdr.
- *
- * This function consumes the skb unless there is an error.
- */
-static
-int i1480u_tx_create_n(struct i1480u_tx *wtx, struct sk_buff *skb,
-                      gfp_t gfp_mask)
-{
-       int result;
-       void *pl;
-       size_t pl_size;
-
-       void *pl_itr, *buf_itr;
-       size_t pl_size_left, frgs, pl_size_1st, frg_pl_size = 0;
-       struct untd_hdr_1st *untd_hdr_1st;
-       struct wlp_tx_hdr *wlp_tx_hdr;
-       struct untd_hdr_rst *untd_hdr_rst;
-
-       wtx->skb = NULL;
-       pl = skb->data;
-       pl_itr = pl;
-       pl_size = skb->len;
-       pl_size_left = pl_size; /* payload size */
-       /* First fragment; fits as much as i1480u_MAX_FRG_SIZE minus
-        * the headers */
-       pl_size_1st = i1480u_MAX_FRG_SIZE
-               - sizeof(struct untd_hdr_1st) - sizeof(struct wlp_tx_hdr);
-       BUG_ON(pl_size_1st > pl_size);
-       pl_size_left -= pl_size_1st;
-       /* The rest have an smaller header (no i1480 TX header). We
-        * need to break up the payload in blocks smaller than
-        * i1480u_MAX_PL_SIZE (payload excluding header). */
-       frgs = (pl_size_left + i1480u_MAX_PL_SIZE - 1) / i1480u_MAX_PL_SIZE;
-       /* Allocate space for the new buffer. In this new buffer we'll
-        * place the headers followed by the data fragment, headers,
-        * data fragments, etc..
-        */
-       result = -ENOMEM;
-       wtx->buf_size = sizeof(*untd_hdr_1st)
-               + sizeof(*wlp_tx_hdr)
-               + frgs * sizeof(*untd_hdr_rst)
-               + pl_size;
-       wtx->buf = kmalloc(wtx->buf_size, gfp_mask);
-       if (wtx->buf == NULL)
-               goto error_buf_alloc;
-
-       buf_itr = wtx->buf;             /* We got the space, let's fill it up */
-       /* Fill 1st fragment */
-       untd_hdr_1st = buf_itr;
-       buf_itr += sizeof(*untd_hdr_1st);
-       untd_hdr_set_type(&untd_hdr_1st->hdr, i1480u_PKT_FRAG_1ST);
-       untd_hdr_set_rx_tx(&untd_hdr_1st->hdr, 0);
-       untd_hdr_1st->hdr.len = cpu_to_le16(pl_size + sizeof(*wlp_tx_hdr));
-       untd_hdr_1st->fragment_len =
-               cpu_to_le16(pl_size_1st + sizeof(*wlp_tx_hdr));
-       memset(untd_hdr_1st->padding, 0, sizeof(untd_hdr_1st->padding));
-       /* Set up i1480 header info */
-       wlp_tx_hdr = wtx->wlp_tx_hdr = buf_itr;
-       buf_itr += sizeof(*wlp_tx_hdr);
-       /* Copy the first fragment */
-       memcpy(buf_itr, pl_itr, pl_size_1st);
-       pl_itr += pl_size_1st;
-       buf_itr += pl_size_1st;
-
-       /* Now do each remaining fragment */
-       result = -EINVAL;
-       while (pl_size_left > 0) {
-               if (buf_itr + sizeof(*untd_hdr_rst) - wtx->buf
-                   > wtx->buf_size) {
-                       printk(KERN_ERR "BUG: no space for header\n");
-                       goto error_bug;
-               }
-               untd_hdr_rst = buf_itr;
-               buf_itr += sizeof(*untd_hdr_rst);
-               if (pl_size_left > i1480u_MAX_PL_SIZE) {
-                       frg_pl_size = i1480u_MAX_PL_SIZE;
-                       untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_NXT);
-               } else {
-                       frg_pl_size = pl_size_left;
-                       untd_hdr_set_type(&untd_hdr_rst->hdr, i1480u_PKT_FRAG_LST);
-               }
-               untd_hdr_set_rx_tx(&untd_hdr_rst->hdr, 0);
-               untd_hdr_rst->hdr.len = cpu_to_le16(frg_pl_size);
-               untd_hdr_rst->padding = 0;
-               if (buf_itr + frg_pl_size - wtx->buf
-                   > wtx->buf_size) {
-                       printk(KERN_ERR "BUG: no space for payload\n");
-                       goto error_bug;
-               }
-               memcpy(buf_itr, pl_itr, frg_pl_size);
-               buf_itr += frg_pl_size;
-               pl_itr += frg_pl_size;
-               pl_size_left -= frg_pl_size;
-       }
-       dev_kfree_skb_irq(skb);
-       return 0;
-
-error_bug:
-       printk(KERN_ERR
-              "BUG: skb %u bytes\n"
-              "BUG: frg_pl_size %zd i1480u_MAX_FRG_SIZE %u\n"
-              "BUG: buf_itr %zu buf_size %zu pl_size_left %zu\n",
-              skb->len,
-              frg_pl_size, i1480u_MAX_FRG_SIZE,
-              buf_itr - wtx->buf, wtx->buf_size, pl_size_left);
-
-       kfree(wtx->buf);
-error_buf_alloc:
-       return result;
-}
-
-
-/*
- * Given a buffer that fits in a single fragment, fill out a @wtx
- * struct for transmitting it down the USB pipe.
- *
- * Uses the fact that we have space reserved in front of the skbuff
- * for hardware headers :]
- *
- * This does not fill the i1480 TX header, it is left up to the
- * caller to do that; you can get it from @wtx->wlp_tx_hdr.
- *
- * @pl:                pointer to payload data
- * @pl_size:    size of the payuload
- *
- * This function does not consume the @skb.
- */
-static
-int i1480u_tx_create_1(struct i1480u_tx *wtx, struct sk_buff *skb,
-                      gfp_t gfp_mask)
-{
-       struct untd_hdr_cmp *untd_hdr_cmp;
-       struct wlp_tx_hdr *wlp_tx_hdr;
-
-       wtx->buf = NULL;
-       wtx->skb = skb;
-       BUG_ON(skb_headroom(skb) < sizeof(*wlp_tx_hdr));
-       wlp_tx_hdr = (void *) __skb_push(skb, sizeof(*wlp_tx_hdr));
-       wtx->wlp_tx_hdr = wlp_tx_hdr;
-       BUG_ON(skb_headroom(skb) < sizeof(*untd_hdr_cmp));
-       untd_hdr_cmp = (void *) __skb_push(skb, sizeof(*untd_hdr_cmp));
-
-       untd_hdr_set_type(&untd_hdr_cmp->hdr, i1480u_PKT_FRAG_CMP);
-       untd_hdr_set_rx_tx(&untd_hdr_cmp->hdr, 0);
-       untd_hdr_cmp->hdr.len = cpu_to_le16(skb->len - sizeof(*untd_hdr_cmp));
-       untd_hdr_cmp->padding = 0;
-       return 0;
-}
-
-
-/*
- * Given a skb to transmit, massage it to become palatable for the TX pipe
- *
- * This will break the buffer in chunks smaller than
- * i1480u_MAX_FRG_SIZE and add proper headers to each.
- *
- *   1st header           \
- *   i1480 tx header      |  fragment 1
- *   fragment data        /
- *   nxt header           \  fragment 2
- *   fragment data        /
- *   ..
- *   ..
- *   last header          \  fragment 3
- *   last fragment data   /
- *
- * Each fragment will be always smaller or equal to i1480u_MAX_FRG_SIZE.
- *
- * If the first fragment is smaller than i1480u_MAX_FRG_SIZE, then the
- * following is composed:
- *
- *   complete header      \
- *   i1480 tx header      | single fragment
- *   packet data          /
- *
- * We were going to use s/g support, but because the interface is
- * synch and at the end there is plenty of overhead to do it, it
- * didn't seem that worth for data that is going to be smaller than
- * one page.
- */
-static
-struct i1480u_tx *i1480u_tx_create(struct i1480u *i1480u,
-                                  struct sk_buff *skb, gfp_t gfp_mask)
-{
-       int result;
-       struct usb_endpoint_descriptor *epd;
-       int usb_pipe;
-       unsigned long flags;
-
-       struct i1480u_tx *wtx;
-       const size_t pl_max_size =
-               i1480u_MAX_FRG_SIZE - sizeof(struct untd_hdr_cmp)
-               - sizeof(struct wlp_tx_hdr);
-
-       wtx = kmalloc(sizeof(*wtx), gfp_mask);
-       if (wtx == NULL)
-               goto error_wtx_alloc;
-       wtx->urb = usb_alloc_urb(0, gfp_mask);
-       if (wtx->urb == NULL)
-               goto error_urb_alloc;
-       epd = &i1480u->usb_iface->cur_altsetting->endpoint[2].desc;
-       usb_pipe = usb_sndbulkpipe(i1480u->usb_dev, epd->bEndpointAddress);
-       /* Fits in a single complete packet or need to split? */
-       if (skb->len > pl_max_size) {
-               result = i1480u_tx_create_n(wtx, skb, gfp_mask);
-               if (result < 0)
-                       goto error_create;
-               usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe,
-                                 wtx->buf, wtx->buf_size, i1480u_tx_cb, wtx);
-       } else {
-               result = i1480u_tx_create_1(wtx, skb, gfp_mask);
-               if (result < 0)
-                       goto error_create;
-               usb_fill_bulk_urb(wtx->urb, i1480u->usb_dev, usb_pipe,
-                                 skb->data, skb->len, i1480u_tx_cb, wtx);
-       }
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-       list_add(&wtx->list_node, &i1480u->tx_list);
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-       return wtx;
-
-error_create:
-       kfree(wtx->urb);
-error_urb_alloc:
-       kfree(wtx);
-error_wtx_alloc:
-       return NULL;
-}
-
-/*
- * Actual fragmentation and transmission of frame
- *
- * @wlp:  WLP substack data structure
- * @skb:  To be transmitted
- * @dst:  Device address of destination
- * @returns: 0 on success, <0 on failure
- *
- * This function can also be called directly (not just from
- * hard_start_xmit), so we also check here if the interface is up before
- * taking sending anything.
- */
-int i1480u_xmit_frame(struct wlp *wlp, struct sk_buff *skb,
-                     struct uwb_dev_addr *dst)
-{
-       int result = -ENXIO;
-       struct i1480u *i1480u = container_of(wlp, struct i1480u, wlp);
-       struct device *dev = &i1480u->usb_iface->dev;
-       struct net_device *net_dev = i1480u->net_dev;
-       struct i1480u_tx *wtx;
-       struct wlp_tx_hdr *wlp_tx_hdr;
-       static unsigned char dev_bcast[2] = { 0xff, 0xff };
-
-       BUG_ON(i1480u->wlp.rc == NULL);
-       if ((net_dev->flags & IFF_UP) == 0)
-               goto out;
-       result = -EBUSY;
-       if (atomic_read(&i1480u->tx_inflight.count) >= i1480u->tx_inflight.max) {
-               netif_stop_queue(net_dev);
-               goto error_max_inflight;
-       }
-       result = -ENOMEM;
-       wtx = i1480u_tx_create(i1480u, skb, GFP_ATOMIC);
-       if (unlikely(wtx == NULL)) {
-               if (printk_ratelimit())
-                       dev_err(dev, "TX: no memory for WLP TX URB,"
-                               "dropping packet (in flight %d)\n",
-                               atomic_read(&i1480u->tx_inflight.count));
-               netif_stop_queue(net_dev);
-               goto error_wtx_alloc;
-       }
-       wtx->i1480u = i1480u;
-       /* Fill out the i1480 header; @i1480u->def_tx_hdr read without
-        * locking. We do so because they are kind of orthogonal to
-        * each other (and thus not changed in an atomic batch).
-        * The ETH header is right after the WLP TX header. */
-       wlp_tx_hdr = wtx->wlp_tx_hdr;
-       *wlp_tx_hdr = i1480u->options.def_tx_hdr;
-       wlp_tx_hdr->dstaddr = *dst;
-       if (!memcmp(&wlp_tx_hdr->dstaddr, dev_bcast, sizeof(dev_bcast))
-           && (wlp_tx_hdr_delivery_id_type(wlp_tx_hdr) & WLP_DRP)) {
-               /*Broadcast message directed to DRP host. Send as best effort
-                * on PCA. */
-               wlp_tx_hdr_set_delivery_id_type(wlp_tx_hdr, i1480u->options.pca_base_priority);
-       }
-
-       result = usb_submit_urb(wtx->urb, GFP_ATOMIC);          /* Go baby */
-       if (result < 0) {
-               dev_err(dev, "TX: cannot submit URB: %d\n", result);
-               /* We leave the freeing of skb to calling function */
-               wtx->skb = NULL;
-               goto error_tx_urb_submit;
-       }
-       atomic_inc(&i1480u->tx_inflight.count);
-       net_dev->trans_start = jiffies;
-       return result;
-
-error_tx_urb_submit:
-       i1480u_tx_destroy(i1480u, wtx);
-error_wtx_alloc:
-error_max_inflight:
-out:
-       return result;
-}
-
-
-/*
- * Transmit an skb  Called when an skbuf has to be transmitted
- *
- * The skb is first passed to WLP substack to ensure this is a valid
- * frame. If valid the device address of destination will be filled and
- * the WLP header prepended to the skb. If this step fails we fake sending
- * the frame, if we return an error the network stack will just keep trying.
- *
- * Broadcast frames inside a WSS needs to be treated special as multicast is
- * not supported. A broadcast frame is sent as unicast to each member of the
- * WSS - this is done by the WLP substack when it finds a broadcast frame.
- * So, we test if the WLP substack took over the skb and only transmit it
- * if it has not (been taken over).
- *
- * @net_dev->xmit_lock is held
- */
-netdev_tx_t i1480u_hard_start_xmit(struct sk_buff *skb,
-                                        struct net_device *net_dev)
-{
-       int result;
-       struct i1480u *i1480u = netdev_priv(net_dev);
-       struct device *dev = &i1480u->usb_iface->dev;
-       struct uwb_dev_addr dst;
-
-       if ((net_dev->flags & IFF_UP) == 0)
-               goto error;
-       result = wlp_prepare_tx_frame(dev, &i1480u->wlp, skb, &dst);
-       if (result < 0) {
-               dev_err(dev, "WLP verification of TX frame failed (%d). "
-                       "Dropping packet.\n", result);
-               goto error;
-       } else if (result == 1) {
-               /* trans_start time will be set when WLP actually transmits
-                * the frame */
-               goto out;
-       }
-       result = i1480u_xmit_frame(&i1480u->wlp, skb, &dst);
-       if (result < 0) {
-               dev_err(dev, "Frame TX failed (%d).\n", result);
-               goto error;
-       }
-       return NETDEV_TX_OK;
-error:
-       dev_kfree_skb_any(skb);
-       net_dev->stats.tx_dropped++;
-out:
-       return NETDEV_TX_OK;
-}
-
-
-/*
- * Called when a pkt transmission doesn't complete in a reasonable period
- * Device reset may sleep - do it outside of interrupt context (delayed)
- */
-void i1480u_tx_timeout(struct net_device *net_dev)
-{
-       struct i1480u *i1480u = netdev_priv(net_dev);
-
-       wlp_reset_all(&i1480u->wlp);
-}
-
-
-void i1480u_tx_release(struct i1480u *i1480u)
-{
-       unsigned long flags;
-       struct i1480u_tx *wtx, *next;
-       int count = 0, empty;
-
-       spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-       list_for_each_entry_safe(wtx, next, &i1480u->tx_list, list_node) {
-               count++;
-               usb_unlink_urb(wtx->urb);
-       }
-       spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-       count = count*10; /* i1480ut 200ms per unlinked urb (intervals of 20ms) */
-       /*
-        * We don't like this sollution too much (dirty as it is), but
-        * it is cheaper than putting a refcount on each i1480u_tx and
-        * i1480uting for all of them to go away...
-        *
-        * Called when no more packets can be added to tx_list
-        * so can i1480ut for it to be empty.
-        */
-       while (1) {
-               spin_lock_irqsave(&i1480u->tx_list_lock, flags);
-               empty = list_empty(&i1480u->tx_list);
-               spin_unlock_irqrestore(&i1480u->tx_list_lock, flags);
-               if (empty)
-                       break;
-               count--;
-               BUG_ON(count == 0);
-               msleep(20);
-       }
-}