CTC++ Coverage Report - Execution Profile    #732/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/usb/net/catc.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/349)

Start/ End/    
True False - Line Source

  1 /*
  2  *  Copyright (c) 2001 Vojtech Pavlik
  3  *
  4  *  CATC EL1210A NetMate USB Ethernet driver
  5  *
  6  *  Sponsored by SuSE
  7  *
  8  *  Based on the work of
  9  *      Donald Becker
  10  * 
  11  *  Old chipset support added by Simon Evans <spse@secret.org.uk> 2002
  12  *    - adds support for Belkin F5U011
  13  */
  14 
  15 /*
  16  * This program is free software; you can redistribute it and/or modify
  17  * it under the terms of the GNU General Public License as published by
  18  * the Free Software Foundation; either version 2 of the License, or 
  19  * (at your option) any later version.
  20  * 
  21  * This program is distributed in the hope that it will be useful,
  22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24  * GNU General Public License for more details.
  25  * 
  26  * You should have received a copy of the GNU General Public License
  27  * along with this program; if not, write to the Free Software
  28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  29  * 
  30  * Should you need to contact me, the author, you can do so either by
  31  * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
  32  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
  33  */
  34 
  35 #include <linux/init.h>
  36 #include <linux/module.h>
  37 #include <linux/kernel.h>
  38 #include <linux/string.h>
  39 #include <linux/slab.h>
  40 #include <linux/netdevice.h>
  41 #include <linux/etherdevice.h>
  42 #include <linux/skbuff.h>
  43 #include <linux/spinlock.h>
  44 #include <linux/ethtool.h>
  45 #include <linux/crc32.h>
  46 #include <linux/bitops.h>
  47 #include <asm/uaccess.h>
  48 
  49 #undef DEBUG
  50 
  51 #include <linux/usb.h>
  52 
  53 /*
  54  * Version information.
  55  */
  56 
  57 #define DRIVER_VERSION "v2.8"
  58 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>"
  59 #define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver"
  60 #define SHORT_DRIVER_DESC "EL1210A NetMate USB Ethernet"
  61 
  62 MODULE_AUTHOR(DRIVER_AUTHOR);
  63 MODULE_DESCRIPTION(DRIVER_DESC);
  64 MODULE_LICENSE("GPL");
  65 
  66 static const char driver_name[] = "catc";
  67 
  68 /*
  69  * Some defines.
  70  */ 
  71 
  72 #define STATS_UPDATE      (HZ)   /* Time between stats updates */
  73 #define TX_TIMEOUT      (5*HZ)   /* Max time the queue can be stopped */
  74 #define PKT_SZ         1536   /* Max Ethernet packet size */
  75 #define RX_MAX_BURST      15   /* Max packets per rx buffer (> 0, < 16) */
  76 #define TX_MAX_BURST      15   /* Max full sized packets per tx buffer (> 0) */
  77 #define CTRL_QUEUE      16   /* Max control requests in flight (power of two) */
  78 #define RX_PKT_SZ      1600   /* Max size of receive packet for F5U011 */
  79 
  80 /*
  81  * Control requests.
  82  */
  83 
  84 enum control_requests {
  85    ReadMem =   0xf1,
  86    GetMac =   0xf2,
  87    Reset =      0xf4,
  88    SetMac =   0xf5,
  89    SetRxMode =     0xf5,  /* F5U011 only */
  90    WriteROM =   0xf8,
  91    SetReg =   0xfa,
  92    GetReg =   0xfb,
  93    WriteMem =   0xfc,
  94    ReadROM =   0xfd,
  95 };
  96 
  97 /*
  98  * Registers.
  99  */
  100 
  101 enum register_offsets {
  102    TxBufCount =   0x20,
  103    RxBufCount =   0x21,
  104    OpModes =   0x22,
  105    TxQed =      0x23,
  106    RxQed =      0x24,
  107    MaxBurst =   0x25,
  108    RxUnit =   0x60,
  109    EthStatus =   0x61,
  110    StationAddr0 =   0x67,
  111    EthStats =   0x69,
  112    LEDCtrl =   0x81,
  113 };
  114 
  115 enum eth_stats {
  116    TxSingleColl =   0x00,
  117         TxMultiColl =   0x02,
  118         TxExcessColl =   0x04,
  119         RxFramErr =   0x06,
  120 };
  121 
  122 enum op_mode_bits {
  123    Op3MemWaits =   0x03,
  124    OpLenInclude =   0x08,
  125    OpRxMerge =   0x10,
  126    OpTxMerge =   0x20,
  127    OpWin95bugfix =   0x40,
  128    OpLoopback =   0x80,
  129 };
  130 
  131 enum rx_filter_bits {
  132    RxEnable =   0x01,
  133    RxPolarity =   0x02,
  134    RxForceOK =   0x04,
  135    RxMultiCast =   0x08,
  136    RxPromisc =   0x10,
  137    AltRxPromisc =  0x20, /* F5U011 uses different bit */
  138 };
  139 
  140 enum led_values {
  141    LEDFast =    0x01,
  142    LEDSlow =   0x02,
  143    LEDFlash =   0x03,
  144    LEDPulse =   0x04,
  145    LEDLink =   0x08,
  146 };
  147 
  148 enum link_status {
  149    LinkNoChange = 0,
  150    LinkGood     = 1,
  151    LinkBad      = 2
  152 };
  153 
  154 /*
  155  * The catc struct.
  156  */
  157 
  158 #define CTRL_RUNNING   0
  159 #define RX_RUNNING   1
  160 #define TX_RUNNING   2
  161 
  162 struct catc {
  163    struct net_device *netdev;
  164    struct usb_device *usbdev;
  165 
  166    struct net_device_stats stats;
  167    unsigned long flags;
  168 
  169    unsigned int tx_ptr, tx_idx;
  170    unsigned int ctrl_head, ctrl_tail;
  171    spinlock_t tx_lock, ctrl_lock;
  172 
  173    u8 tx_buf[2][TX_MAX_BURST * (PKT_SZ + 2)];
  174    u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)];
  175    u8 irq_buf[2];
  176    u8 ctrl_buf[64];
  177    struct usb_ctrlrequest ctrl_dr;
  178 
  179    struct timer_list timer;
  180    u8 stats_buf[8];
  181    u16 stats_vals[4];
  182    unsigned long last_stats;
  183 
  184    u8 multicast[64];
  185 
  186    struct ctrl_queue {
  187       u8 dir;
  188       u8 request;
  189       u16 value;
  190       u16 index;
  191       void *buf;
  192       int len;
  193       void (*callback)(struct catc *catc, struct ctrl_queue *q);
  194    } ctrl_queue[CTRL_QUEUE];
  195 
  196    struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb;
  197 
  198    u8 is_f5u011;   /* Set if device is an F5U011 */
  199    u8 rxmode[2];   /* Used for F5U011 */
  200    atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */
  201 };
  202 
  203 /*
  204  * Useful macros.
  205  */
  206 
  207 #define catc_get_mac(catc, mac)            catc_ctrl_msg(catc, USB_DIR_IN,  GetMac, 0, 0, mac,  6)
  208 #define catc_reset(catc)            catc_ctrl_msg(catc, USB_DIR_OUT, Reset, 0, 0, NULL, 0)
  209 #define catc_set_reg(catc, reg, val)         catc_ctrl_msg(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0)
  210 #define catc_get_reg(catc, reg, buf)         catc_ctrl_msg(catc, USB_DIR_IN,  GetReg, 0, reg, buf, 1)
  211 #define catc_write_mem(catc, addr, buf, size)      catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size)
  212 #define catc_read_mem(catc, addr, buf, size)      catc_ctrl_msg(catc, USB_DIR_IN,  ReadMem, 0, addr, buf, size)
  213 
  214 #define f5u011_rxmode(catc, rxmode)         catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2)
  215 #define f5u011_rxmode_async(catc, rxmode)      catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL)
  216 #define f5u011_mchash_async(catc, hash)         catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL)
  217 
  218 #define catc_set_reg_async(catc, reg, val)      catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL)
  219 #define catc_get_reg_async(catc, reg, cb)      catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb)
  220 #define catc_write_mem_async(catc, addr, buf, size)   catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL)
  221 
  222 /*
  223  * Receive routines.
  224  */
  225 
 
- 226 static void catc_rx_done(struct urb *urb, struct pt_regs *regs)
  227 {
  228    struct catc *catc = urb->context;
  229    u8 *pkt_start = urb->transfer_buffer;
  230    struct sk_buff *skb;
  231    int pkt_len, pkt_offset = 0;
  232 
- 233    if (!catc->is_f5u011) {
  234       clear_bit(RX_RUNNING, &catc->flags);
  235       pkt_offset = 2;
  236    }
  237 
- 238    if (urb->status) {
    239       dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
- 239   do-while (0)
 - 240       return;
  241    }
  242 
    243    do {
- 244       if(!catc->is_f5u011) {
  245          pkt_len = le16_to_cpup((__le16*)pkt_start);
- 246          if (pkt_len > urb->actual_length) {
  247             catc->stats.rx_length_errors++;
  248             catc->stats.rx_errors++;
 - 249             break;
  250          }
    251       } else {
  252          pkt_len = urb->actual_length;
  253       }
  254 
- 255       if (!(skb = dev_alloc_skb(pkt_len)))
 - 256          return;
  257 
  258       skb->dev = catc->netdev;
  259       eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0);
  260       skb_put(skb, pkt_len);
  261 
  262       skb->protocol = eth_type_trans(skb, catc->netdev);
  263       netif_rx(skb);
  264 
  265       catc->stats.rx_packets++;
  266       catc->stats.rx_bytes += pkt_len;
  267 
  268       /* F5U011 only does one packet per RX */
- 269       if (catc->is_f5u011)
 - 270          break;
  271       pkt_start += (((pkt_len + 1) >> 6) + 1) << 6;
  272 
- 273    } while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
  274 
  275    catc->netdev->last_rx = jiffies;
  276 
- 277    if (catc->is_f5u011) {
- 278       if (atomic_read(&catc->recq_sz)) {
  279          int status;
  280          atomic_dec(&catc->recq_sz);
    281          dbg("getting extra packet");
- 281     do-while (0)
  282          urb->dev = catc->usbdev;
- 283          if ((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
    284             dbg("submit(rx_urb) status %d", status);
- 284       do-while (0)
  285          }
    286       } else {
  287          clear_bit(RX_RUNNING, &catc->flags);
  288       }
  289    }
  290 }
  291 
 
- 292 static void catc_irq_done(struct urb *urb, struct pt_regs *regs)
  293 {
  294    struct catc *catc = urb->context;
  295    u8 *data = urb->transfer_buffer;
  296    int status;
  297    unsigned int hasdata = 0, linksts = LinkNoChange;
  298 
- 299    if (!catc->is_f5u011) {
  300       hasdata = data[1] & 0x80;
- 301       if (data[1] & 0x40)
  302          linksts = LinkGood;
- 303       else if (data[1] & 0x20)
  304          linksts = LinkBad;
    305    } else {
  306       hasdata = (unsigned int)(be16_to_cpup((__be16*)data) & 0x0fff);
- 307       if (data[0] == 0x90)
  308          linksts = LinkGood;
- 309       else if (data[0] == 0xA0)
  310          linksts = LinkBad;
  311    }
  312 
    313    switch (urb->status) {
 - 314    case 0:         /* success */
 - 315       break;
 - 316    case -ECONNRESET:   /* unlink */
 - 317    case -ENOENT:
 - 318    case -ESHUTDOWN:
 - 319       return;
  320    /* -EPIPE:  should clear the halt */
 - 321    default:      /* error */
    322       dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
- 322   do-while (0)
 - 323       goto resubmit;
  324    }
  325 
- 326    if (linksts == LinkGood) {
  327       netif_carrier_on(catc->netdev);
    328       dbg("link ok");
- 328   do-while (0)
  329    }
  330 
- 331    if (linksts == LinkBad) {
  332       netif_carrier_off(catc->netdev);
    333       dbg("link bad");
- 333   do-while (0)
  334    }
  335 
- 336    if (hasdata) {
- 337       if (test_and_set_bit(RX_RUNNING, &catc->flags)) {
- 338          if (catc->is_f5u011)
  339             atomic_inc(&catc->recq_sz);
    340       } else {
  341          catc->rx_urb->dev = catc->usbdev;
- 342          if ((status = usb_submit_urb(catc->rx_urb, GFP_ATOMIC)) < 0) {
  343             err("submit(rx_urb) status %d", status);
  344          }
  345       } 
  346    }
  347 resubmit:
  348    status = usb_submit_urb (urb, SLAB_ATOMIC);
- 349    if (status)
  350       err ("can't resubmit intr, %s-%s, status %d",
  351             catc->usbdev->bus->bus_name,
  352             catc->usbdev->devpath, status);
  353 }
  354 
  355 /*
  356  * Transmit routines.
  357  */
  358 
 
- 359 static void catc_tx_run(struct catc *catc)
  360 {
  361    int status;
  362 
- 363    if (catc->is_f5u011)
  364       catc->tx_ptr = (catc->tx_ptr + 63) & ~63;
  365 
  366    catc->tx_urb->transfer_buffer_length = catc->tx_ptr;
  367    catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx];
  368    catc->tx_urb->dev = catc->usbdev;
  369 
- 370    if ((status = usb_submit_urb(catc->tx_urb, GFP_ATOMIC)) < 0)
  371       err("submit(tx_urb), status %d", status);
  372 
  373    catc->tx_idx = !catc->tx_idx;
  374    catc->tx_ptr = 0;
  375 
  376    catc->netdev->trans_start = jiffies;
  377 }
  378 
 
- 379 static void catc_tx_done(struct urb *urb, struct pt_regs *regs)
  380 {
  381    struct catc *catc = urb->context;
  382    unsigned long flags;
  383 
- 384    if (urb->status == -ECONNRESET) {
    385       dbg("Tx Reset.");
- 385   do-while (0)
  386       urb->status = 0;
  387       catc->netdev->trans_start = jiffies;
  388       catc->stats.tx_errors++;
  389       clear_bit(TX_RUNNING, &catc->flags);
  390       netif_wake_queue(catc->netdev);
 - 391       return;
  392    }
  393 
- 394    if (urb->status) {
    395       dbg("tx_done, status %d, length %d", urb->status, urb->actual_length);
- 395   do-while (0)
 - 396       return;
  397    }
  398 
    399    spin_lock_irqsave(&catc->tx_lock, flags);
    399   do
    399     do
- 399     do-while (0)
- 399   do-while (0)
    399   do
    399     do
- 399     do-while (0)
- 399   do-while (0)
- 399 do-while (0)
  400 
- 401    if (catc->tx_ptr)
  402       catc_tx_run(catc);
    403    else
  404       clear_bit(TX_RUNNING, &catc->flags);
  405 
  406    netif_wake_queue(catc->netdev);
  407 
    408    spin_unlock_irqrestore(&catc->tx_lock, flags);
    408   do
    408     do
- 408     do-while (0)
- 408   do-while (0)
- 408 do-while (0)
  409 }
  410 
 
- 411 static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
  412 {
  413    struct catc *catc = netdev_priv(netdev);
  414    unsigned long flags;
  415    char *tx_buf;
  416 
    417    spin_lock_irqsave(&catc->tx_lock, flags);
    417   do
    417     do
- 417     do-while (0)
- 417   do-while (0)
    417   do
    417     do
- 417     do-while (0)
- 417   do-while (0)
- 417 do-while (0)
  418 
  419    catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6;
  420    tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr;
    421    *((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len);
- 421 ternary-?: ( catc -> is_f5u011 )
- 421 ternary-?: __builtin_constant_p ( ( __u16 ) ( ..
  422    memcpy(tx_buf + 2, skb->data, skb->len);
  423    catc->tx_ptr += skb->len + 2;
  424 
- 425    if (!test_and_set_bit(TX_RUNNING, &catc->flags))
  426       catc_tx_run(catc);
  427 
  428    if ((catc->is_f5u011 && catc->tx_ptr)
- 429         || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2))))
 - 429   (T && T) || (_)
 - 429   (T && F) || (T)
 - 429   (F && _) || (T)
 - 429   (T && F) || (F)
 - 429   (F && _) || (F)
  430       netif_stop_queue(netdev);
  431 
    432    spin_unlock_irqrestore(&catc->tx_lock, flags);
    432   do
    432     do
- 432     do-while (0)
- 432   do-while (0)
- 432 do-while (0)
  433 
  434    catc->stats.tx_bytes += skb->len;
  435    catc->stats.tx_packets++;
  436 
  437    dev_kfree_skb(skb);
  438 
 - 439    return 0;
  440 }
  441 
 
- 442 static void catc_tx_timeout(struct net_device *netdev)
  443 {
  444    struct catc *catc = netdev_priv(netdev);
  445 
  446    warn("Transmit timed out.");
  447    usb_unlink_urb(catc->tx_urb);
  448 }
  449 
  450 /*
  451  * Control messages.
  452  */
  453 
 
- 454 static int catc_ctrl_msg(struct catc *catc, u8 dir, u8 request, u16 value, u16 index, void *buf, int len)
  455 {
  456         int retval = usb_control_msg(catc->usbdev,
    457       dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0),
- 457 ternary-?: dir
  458        request, 0x40 | dir, value, index, buf, len, 1000);
    459         return retval < 0 ? retval : 0;
- 459 ternary-?: retval < 0
 - 459 return retval < 0 ? retval : 0
  460 }
  461 
 
- 462 static void catc_ctrl_run(struct catc *catc)
  463 {
  464    struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail;
  465    struct usb_device *usbdev = catc->usbdev;
  466    struct urb *urb = catc->ctrl_urb;
  467    struct usb_ctrlrequest *dr = &catc->ctrl_dr;
  468    int status;
  469 
  470    dr->bRequest = q->request;
  471    dr->bRequestType = 0x40 | q->dir;
  472    dr->wValue = cpu_to_le16(q->value);
  473    dr->wIndex = cpu_to_le16(q->index);
  474    dr->wLength = cpu_to_le16(q->len);
  475 
    476         urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0);
- 476 ternary-?: q -> dir
  477    urb->transfer_buffer_length = q->len;
  478    urb->transfer_buffer = catc->ctrl_buf;
  479    urb->setup_packet = (void *) dr;
  480    urb->dev = usbdev;
  481 
- 482    if (!q->dir && q->buf && q->len)
 - 482   T && T && T
 - 482   T && T && F
 - 482   T && F && _
 - 482   F && _ && _
  483       memcpy(catc->ctrl_buf, q->buf, q->len);
  484 
- 485    if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL)))
  486       err("submit(ctrl_urb) status %d", status);
  487 }
  488 
 
- 489 static void catc_ctrl_done(struct urb *urb, struct pt_regs *regs)
  490 {
  491    struct catc *catc = urb->context;
  492    struct ctrl_queue *q;
  493    unsigned long flags;
  494 
- 495    if (urb->status)
    496       dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);
- 496   do-while (0)
  497 
    498    spin_lock_irqsave(&catc->ctrl_lock, flags);
    498