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

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


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

Start/ End/    
True False - Line Source

  1 /****************************************************************
  2  *
  3  *     kaweth.c - driver for KL5KUSB101 based USB->Ethernet
  4  *
  5  *     (c) 2000 Interlan Communications
  6  *     (c) 2000 Stephane Alnet
  7  *     (C) 2001 Brad Hards
  8  *     (C) 2002 Oliver Neukum
  9  *
  10  *     Original author: The Zapman <zapman@interlan.net>
  11  *     Inspired by, and much credit goes to Michael Rothwell
  12  *     <rothwell@interlan.net> for the test equipment, help, and patience
  13  *     Based off of (and with thanks to) Petko Manolov's pegaus.c driver.
  14  *     Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki
  15  *     for providing the firmware and driver resources.
  16  *
  17  *     This program is free software; you can redistribute it and/or
  18  *     modify it under the terms of the GNU General Public License as
  19  *     published by the Free Software Foundation; either version 2, or
  20  *     (at your option) any later version.
  21  *
  22  *     This program is distributed in the hope that it will be useful,
  23  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  24  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  25  *     GNU General Public License for more details.
  26  *
  27  *     You should have received a copy of the GNU General Public License
  28  *     along with this program; if not, write to the Free Software Foundation,
  29  *     Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  30  *
  31  ****************************************************************/
  32 
  33 /* TODO:
  34  * Fix in_interrupt() problem
  35  * Develop test procedures for USB net interfaces
  36  * Run test procedures
  37  * Fix bugs from previous two steps
  38  * Snoop other OSs for any tricks we're not doing
  39  * SMP locking
  40  * Reduce arbitrary timeouts
  41  * Smart multicast support
  42  * Temporary MAC change support
  43  * Tunable SOFs parameter - ioctl()?
  44  * Ethernet stats collection
  45  * Code formatting improvements
  46  */
  47 
  48 #include <linux/module.h>
  49 #include <linux/sched.h>
  50 #include <linux/slab.h>
  51 #include <linux/string.h>
  52 #include <linux/init.h>
  53 #include <linux/delay.h>
  54 #include <linux/netdevice.h>
  55 #include <linux/etherdevice.h>
  56 #include <linux/usb.h>
  57 #include <linux/types.h>
  58 #include <linux/ethtool.h>
  59 #include <linux/pci.h>
  60 #include <linux/dma-mapping.h>
  61 #include <linux/wait.h>
  62 #include <asm/uaccess.h>
  63 #include <asm/semaphore.h>
  64 #include <asm/byteorder.h>
  65 
  66 #undef DEBUG
  67 
  68 #ifdef DEBUG
  69 #define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg)
  70 #else
  71 #define kaweth_dbg(format, arg...) do {} while (0)
  72 #endif
  73 #define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg)
  74 #define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg)
  75 #define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg)
  76 
  77 
  78 #include "kawethfw.h"
  79 
  80 #define KAWETH_MTU         1514
  81 #define KAWETH_BUF_SIZE         1664
  82 #define KAWETH_TX_TIMEOUT      (5 * HZ)
  83 #define KAWETH_SCRATCH_SIZE      32
  84 #define KAWETH_FIRMWARE_BUF_SIZE   4096
  85 #define KAWETH_CONTROL_TIMEOUT      (30 * HZ)
  86 
  87 #define KAWETH_STATUS_BROKEN      0x0000001
  88 #define KAWETH_STATUS_CLOSING      0x0000002
  89 
  90 #define KAWETH_PACKET_FILTER_PROMISCUOUS   0x01
  91 #define KAWETH_PACKET_FILTER_ALL_MULTICAST   0x02
  92 #define KAWETH_PACKET_FILTER_DIRECTED      0x04
  93 #define KAWETH_PACKET_FILTER_BROADCAST      0x08
  94 #define KAWETH_PACKET_FILTER_MULTICAST      0x10
  95 
  96 /* Table 7 */
  97 #define KAWETH_COMMAND_GET_ETHERNET_DESC   0x00
  98 #define KAWETH_COMMAND_MULTICAST_FILTERS        0x01
  99 #define KAWETH_COMMAND_SET_PACKET_FILTER   0x02
  100 #define KAWETH_COMMAND_STATISTICS               0x03
  101 #define KAWETH_COMMAND_SET_TEMP_MAC        0x06
  102 #define KAWETH_COMMAND_GET_TEMP_MAC             0x07
  103 #define KAWETH_COMMAND_SET_URB_SIZE      0x08
  104 #define KAWETH_COMMAND_SET_SOFS_WAIT      0x09
  105 #define KAWETH_COMMAND_SCAN         0xFF
  106 
  107 #define KAWETH_SOFS_TO_WAIT         0x05
  108 
  109 #define INTBUFFERSIZE            4
  110 
  111 #define STATE_OFFSET            0
  112 #define STATE_MASK            0x40
  113 #define   STATE_SHIFT            5
  114 
  115 
  116 MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr>, Brad Hards <bhards@bigpond.net.au> and Oliver Neukum <oliver@neukum.org>");
  117 MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
  118 MODULE_LICENSE("GPL");
  119 
  120 static const char driver_name[] = "kaweth";
  121 
  122 static int kaweth_probe(
  123       struct usb_interface *intf,
  124       const struct usb_device_id *id   /* from id_table */
  125    );
  126 static void kaweth_disconnect(struct usb_interface *intf);
  127 static int kaweth_internal_control_msg(struct usb_device *usb_dev,
  128                    unsigned int pipe,
  129                    struct usb_ctrlrequest *cmd, void *data,
  130                    int len, int timeout);
  131 
  132 /****************************************************************
  133  *     usb_device_id
  134  ****************************************************************/
  135 static struct usb_device_id usb_klsi_table[] = {
  136    { USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */
  137    { USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */
  138    { USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */
  139    { USB_DEVICE(0x0506, 0x11f8) }, /* 3Com 3C460 */
  140    { USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */
  141    { USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */
  142    { USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */
  143    { USB_DEVICE(0x0565, 0x0003) }, /* Optus@Home UEP1045A */
  144    { USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */
  145    { USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */
  146    { USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */
  147    { USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */
  148    { USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */
  149    { USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */
  150    { USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */
  151    { USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */
  152    { USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */
  153    { USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */
  154    { USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */
  155    { USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */
  156    { USB_DEVICE(0x085a, 0x0009) }, /* PortGear Ethernet Adapter */
  157    { USB_DEVICE(0x087d, 0x5704) }, /* Jaton USB Ethernet Device Adapter */
  158    { USB_DEVICE(0x0951, 0x0008) }, /* Kingston Technology USB Ethernet Adapter */
  159    { USB_DEVICE(0x095a, 0x3003) }, /* Portsmith Express Ethernet Adapter */
  160    { USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */
  161    { USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */
  162    { USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */
  163    { USB_DEVICE(0x1485, 0x0001) },   /* Silicom U2E */
  164    { USB_DEVICE(0x1485, 0x0002) }, /* Psion Dacom Gold Port Ethernet */
  165    { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */
  166    { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */
  167    { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */
  168    { USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */
  169    {} /* Null terminator */
  170 };
  171 
  172 MODULE_DEVICE_TABLE (usb, usb_klsi_table);
  173 
  174 /****************************************************************
  175  *     kaweth_driver
  176  ****************************************************************/
  177 static struct usb_driver kaweth_driver = {
  178    .name =      driver_name,
  179    .probe =   kaweth_probe,
  180    .disconnect =   kaweth_disconnect,
  181    .id_table =     usb_klsi_table,
  182 };
  183 
  184 typedef __u8 eth_addr_t[6];
  185 
  186 /****************************************************************
  187  *     usb_eth_dev
  188  ****************************************************************/
  189 struct usb_eth_dev {
  190    char *name;
  191    __u16 vendor;
  192    __u16 device;
  193    void *pdata;
  194 };
  195 
  196 /****************************************************************
  197  *     kaweth_ethernet_configuration
  198  *     Refer Table 8
  199  ****************************************************************/
  200 struct kaweth_ethernet_configuration
  201 {
  202    __u8 size;
  203    __u8 reserved1;
  204    __u8 reserved2;
  205    eth_addr_t hw_addr;
  206    __u32 statistics_mask;
  207    __le16 segment_size;
  208    __u16 max_multicast_filters;
  209    __u8 reserved3;
  210 } __attribute__ ((packed));
  211 
  212 /****************************************************************
  213  *     kaweth_device
  214  ****************************************************************/
  215 struct kaweth_device
  216 {
  217    spinlock_t device_lock;
  218 
  219    __u32 status;
  220    int end;
  221    int suspend_lowmem_rx;
  222    int suspend_lowmem_ctrl;
  223    int linkstate;
  224    struct work_struct lowmem_work;
  225 
  226    struct usb_device *dev;
  227    struct net_device *net;
  228    wait_queue_head_t term_wait;
  229 
  230    struct urb *rx_urb;
  231    struct urb *tx_urb;
  232    struct urb *irq_urb;
  233 
  234    dma_addr_t intbufferhandle;
  235    __u8 *intbuffer;
  236    dma_addr_t rxbufferhandle;
  237    __u8 *rx_buf;
  238 
  239    
  240    struct sk_buff *tx_skb;
  241 
  242    __u8 *firmware_buf;
  243    __u8 scratch[KAWETH_SCRATCH_SIZE];
  244    __u16 packet_filter_bitmap;
  245 
  246    struct kaweth_ethernet_configuration configuration;
  247 
  248    struct net_device_stats stats;
  249 };
  250 
  251 
  252 /****************************************************************
  253  *     kaweth_control
  254  ****************************************************************/
 
- 255 static int kaweth_control(struct kaweth_device *kaweth,
  256            unsigned int pipe,
  257            __u8 request,
  258            __u8 requesttype,
  259            __u16 value,
  260            __u16 index,
  261            void *data,
  262            __u16 size,
  263            int timeout)
  264 {
  265    struct usb_ctrlrequest *dr;
  266 
    267    kaweth_dbg("kaweth_control()");
- 267 do-while (0)
  268 
- 269    if(in_interrupt()) {
    270       kaweth_dbg("in_interrupt()");
- 270   do-while (0)
 - 271       return -EBUSY;
  272    }
  273 
  274    dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
  275 
- 276    if (!dr) {
    277       kaweth_dbg("kmalloc() failed");
- 277   do-while (0)
 - 278       return -ENOMEM;
  279    }
  280 
  281    dr->bRequestType= requesttype;
  282    dr->bRequest = request;
  283    dr->wValue = cpu_to_le16p(&value);
  284    dr->wIndex = cpu_to_le16p(&index);
  285    dr->wLength = cpu_to_le16p(&size);
  286 
  287    return kaweth_internal_control_msg(kaweth->dev,
  288                pipe,
  289                dr,
  290                data,
  291                size,
 - 292                timeout);
  293 }
  294 
  295 /****************************************************************
  296  *     kaweth_read_configuration
  297  ****************************************************************/
 
- 298 static int kaweth_read_configuration(struct kaweth_device *kaweth)
  299 {
  300    int retval;
  301 
    302    kaweth_dbg("Reading kaweth configuration");
- 302 do-while (0)
  303 
  304    retval = kaweth_control(kaweth,
  305             usb_rcvctrlpipe(kaweth->dev, 0),
  306             KAWETH_COMMAND_GET_ETHERNET_DESC,
  307             USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE,
  308             0,
  309             0,
  310             (void *)&kaweth->configuration,
  311             sizeof(kaweth->configuration),
  312             KAWETH_CONTROL_TIMEOUT);
  313 
 - 314    return retval;
  315 }
  316 
  317 /****************************************************************
  318  *     kaweth_set_urb_size
  319  ****************************************************************/
 
- 320 static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size)
  321 {
  322    int retval;
  323 
    324    kaweth_dbg("Setting URB size to %d", (unsigned)urb_size);
- 324 do-while (0)
  325 
  326    retval = kaweth_control(kaweth,
  327             usb_sndctrlpipe(kaweth->dev, 0),
  328             KAWETH_COMMAND_SET_URB_SIZE,
  329             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
  330             urb_size,
  331             0,
  332             (void *)&kaweth->scratch,
  333             0,
  334             KAWETH_CONTROL_TIMEOUT);
  335 
 - 336    return retval;
  337 }
  338 
  339 /****************************************************************
  340  *     kaweth_set_sofs_wait
  341  ****************************************************************/
 
- 342 static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait)
  343 {
  344    int retval;
  345 
    346    kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait);
- 346 do-while (0)
  347 
  348    retval = kaweth_control(kaweth,
  349             usb_sndctrlpipe(kaweth->dev, 0),
  350             KAWETH_COMMAND_SET_SOFS_WAIT,
  351             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
  352             sofs_wait,
  353             0,
  354             (void *)&kaweth->scratch,
  355             0,
  356             KAWETH_CONTROL_TIMEOUT);
  357 
 - 358    return retval;
  359 }
  360 
  361 /****************************************************************
  362  *     kaweth_set_receive_filter
  363  ****************************************************************/
 
- 364 static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
  365                  __u16 receive_filter)
  366 {
  367    int retval;
  368 
    369    kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter);
- 369 do-while (0)
  370 
  371    retval = kaweth_control(kaweth,
  372             usb_sndctrlpipe(kaweth->dev, 0),
  373             KAWETH_COMMAND_SET_PACKET_FILTER,
  374             USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
  375             receive_filter,
  376             0,
  377             (void *)&kaweth->scratch,
  378             0,
  379             KAWETH_CONTROL_TIMEOUT);
  380 
 - 381    return retval;
  382 }
  383 
  384 /****************************************************************
  385  *     kaweth_download_firmware
  386  ****************************************************************/
 
- 387 static int kaweth_download_firmware(struct kaweth_device *kaweth,
  388                 __u8 *data,
  389                 __u16 data_len,
  390                 __u8 interrupt,
  391                 __u8 type)
  392 {
- 393    if(data_len > KAWETH_FIRMWARE_BUF_SIZE)   {
  394       kaweth_err("Firmware too big: %d", data_len);
 - 395       return -ENOSPC;
  396    }
  397 
  398    memcpy(kaweth->firmware_buf, data, data_len);
  399 
  400    kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
  401    kaweth->firmware_buf[3] = data_len >> 8;
  402    kaweth->firmware_buf[4] = type;
  403    kaweth->firmware_buf[5] = interrupt;
  404 
    405    kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3],
- 405 do-while (0)
  406          kaweth->firmware_buf[2]);
  407 
    408    kaweth_dbg("Downloading firmware at %p to kaweth device at %p",
- 408 do-while (0)
  409        data,
  410        kaweth);
    411    kaweth_dbg("Firmware length: %d", data_len);
- 411 do-while (0)
  412 
  413    return kaweth_control(kaweth,
  414                     usb_sndctrlpipe(kaweth->dev, 0),
  415                KAWETH_COMMAND_SCAN,
  416                USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
  417                0,
  418                0,
  419                (void *)kaweth->firmware_buf,
  420                data_len,
 - 421                KAWETH_CONTROL_TIMEOUT);
  422 }
  423 
  424 /****************************************************************
  425  *     kaweth_trigger_firmware
  426  ****************************************************************/
 
- 427 static int kaweth_trigger_firmware(struct kaweth_device *kaweth,
  428                __u8 interrupt)
  429 {
  430    kaweth->firmware_buf[0] = 0xB6;
  431    kaweth->firmware_buf[1] = 0xC3;
  432    kaweth->firmware_buf[2] = 0x01;
  433    kaweth->firmware_buf[3] = 0x00;
  434    kaweth->firmware_buf[4] = 0x06;
  435    kaweth->firmware_buf[5] = interrupt;
  436    kaweth->firmware_buf[6] = 0x00;
  437    kaweth->firmware_buf[7] = 0x00;
  438 
    439    kaweth_dbg("Triggering firmware");
- 439 do-while (0)
  440 
  441    return kaweth_control(kaweth,
  442                usb_sndctrlpipe(kaweth->dev, 0),
  443                KAWETH_COMMAND_SCAN,
  444                USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
  445                0,
  446                0,
  447                (void *)kaweth->firmware_buf,
  448                8,
 - 449                KAWETH_CONTROL_TIMEOUT);
  450 }
  451 
  452 /****************************************************************
  453  *     kaweth_reset
  454  ****************************************************************/
 
- 455 static int kaweth_reset(struct kaweth_device *kaweth)
  456 {
  457    int result;
  458 
    459    kaweth_dbg("kaweth_reset(%p)", kaweth);
- 459 do-while (0)
  460    result = kaweth_control(kaweth,
  461             usb_sndctrlpipe(kaweth->dev, 0),
  462             USB_REQ_SET_CONFIGURATION,
  463             0,
  464             kaweth->dev->config[0].desc.bConfigurationValue,
  465             0,
  466             NULL,
  467             0,
  468             KAWETH_CONTROL_TIMEOUT);
  469 
    470    mdelay(10);
- 470 ternary-?: ( __builtin_constant_p ( 10 ) && ( ..
- 470 ternary-?: __builtin_constant_p ( ( 10 ) * 100..
- 470 ternary-?: ( ( 10 ) * 1000 ) > 20000
  471 
    472    kaweth_dbg("kaweth_reset() returns %d.",result);
- 472 do-while (0)
  473 
 - 474    return result;
  475 }
  476 
  477 static void kaweth_usb_receive(struct urb *, struct pt_regs *regs);
  478 static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t);
  479 
  480 /****************************************************************
  481    int_callback
  482 *****************************************************************/
  483 
 
- 484 static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf)
  485 {
  486    int status;
  487 
  488    status = usb_submit_urb (kaweth->irq_urb, mf);
- 489    if (unlikely(status == -ENOMEM)) {
  490       kaweth->suspend_lowmem_ctrl = 1;
  491       schedule_delayed_work(&kaweth->lowmem_work, HZ/4);
    492    } else {
  493       kaweth->suspend_lowmem_ctrl = 0;
  494    }
  495 
- 496    if (status)
  497       err ("can't resubmit intr, %s-%s, status %d",
  498             kaweth->dev->bus->bus_name,
  499             kaweth->dev->devpath, status);
  500 }
  501 
 
- 502 static void int_callback(struct urb *u, struct pt_regs *regs)
  503 {
  504    struct kaweth_device *kaweth = u->context;
  505    int act_state;
  506 
    507    switch (u->status) {
 - 508    case 0:         /* success */
 - 509       break;
 - 510    case -ECONNRESET:   /* unlink */
 - 511    case -ENOENT:
 - 512    case -ESHUTDOWN:
 - 513       return;
  514    /* -EPIPE:  should clear the halt */
 - 515    default:      /* error */
 - 516       goto resubmit;
  517    }
  518 
  519    /* we check the link state to report changes */
- 520    if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) {
- 521       if (act_state)
  522          netif_carrier_on(kaweth->net);
    523       else
  524          netif_carrier_off(kaweth->net);
  525 
  526       kaweth->linkstate = act_state;
  527    }
  528 resubmit:
  529    kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC);
  530 }
  531 
 
- 532 static void kaweth_resubmit_tl(void *d)
  533 {
  534    struct kaweth_device *kaweth = (struct kaweth_device *)d;
  535 
- 536    if (kaweth->status | KAWETH_STATUS_CLOSING)
 - 537       return;
  538 
- 539    if (kaweth->suspend_lowmem_rx)
  540       kaweth_resubmit_rx_urb(kaweth, GFP_NOIO);
  541 
- 542    if (kaweth->suspend_lowmem_ctrl)
  543       kaweth_resubmit_int_urb(kaweth, GFP_NOIO);
  544 }
  545 
  546 
  547 /****************************************************************
  548  *     kaweth_resubmit_rx_urb
  549  ****************************************************************/
 
- 550 static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth,
  551     &nbs