Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / usb / misc / usbtest.c
index 3104f28..ccc5e82 100644 (file)
@@ -1,7 +1,4 @@
 #include <linux/config.h>
-#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
-#   define DEBUG
-#endif
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -9,7 +6,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
 
 #include <linux/usb.h>
 
@@ -381,22 +378,29 @@ alloc_sglist (int nents, int max, int vary)
        sg = kmalloc (nents * sizeof *sg, SLAB_KERNEL);
        if (!sg)
                return NULL;
-       memset (sg, 0, nents * sizeof *sg);
 
        for (i = 0; i < nents; i++) {
                char            *buf;
+               unsigned        j;
 
-               buf = kmalloc (size, SLAB_KERNEL);
+               buf = kzalloc (size, SLAB_KERNEL);
                if (!buf) {
                        free_sglist (sg, i);
                        return NULL;
                }
-               memset (buf, 0, size);
 
                /* kmalloc pages are always physically contiguous! */
-               sg [i].page = virt_to_page (buf);
-               sg [i].offset = offset_in_page (buf);
-               sg [i].length = size;
+               sg_init_one(&sg[i], buf, size);
+
+               switch (pattern) {
+               case 0:
+                       /* already zeroed */
+                       break;
+               case 1:
+                       for (j = 0; j < size; j++)
+                               *buf++ = (u8) (j % 63);
+                       break;
+               }
 
                if (vary) {
                        size += vary;
@@ -432,6 +436,8 @@ static int perform_sglist (
                usb_sg_wait (req);
                retval = req->status;
 
+               /* FIXME check resulting data pattern */
+
                /* FIXME if endpoint halted, clear halt (and log) */
        }
 
@@ -461,7 +467,7 @@ static int perform_sglist (
 
 static unsigned realworld = 1;
 module_param (realworld, uint, 0);
-MODULE_PARM_DESC (realworld, "clear to demand stricter ch9 compliance");
+MODULE_PARM_DESC (realworld, "clear to demand stricter spec compliance");
 
 static int get_altsetting (struct usbtest_dev *dev)
 {
@@ -604,9 +610,8 @@ static int ch9_postconfig (struct usbtest_dev *dev)
                                USB_DIR_IN | USB_RECIP_DEVICE,
                                0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
                if (retval != 1 || dev->buf [0] != expected) {
-                       dev_dbg (&iface->dev,
-                               "get config --> %d (%d)\n", retval,
-                               expected);
+                       dev_dbg (&iface->dev, "get config --> %d %d (1 %d)\n",
+                               retval, dev->buf[0], expected);
                        return (retval < 0) ? retval : -EDOM;
                }
        }
@@ -849,10 +854,9 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
         * as with bulk/intr sglists, sglen is the queue depth; it also
         * controls which subtests run (more tests than sglen) or rerun.
         */
-       urb = kmalloc (param->sglen * sizeof (struct urb *), SLAB_KERNEL);
+       urb = kcalloc(param->sglen, sizeof(struct urb *), SLAB_KERNEL);
        if (!urb)
                return -ENOMEM;
-       memset (urb, 0, param->sglen * sizeof (struct urb *));
        for (i = 0; i < param->sglen; i++) {
                int                     pipe = usb_rcvctrlpipe (udev, 0);
                unsigned                len;
@@ -984,10 +988,10 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
                reqp->number = i % NUM_SUBCASES;
                reqp->expected = expected;
                u->setup_packet = (char *) &reqp->setup;
+               u->transfer_flags |= URB_NO_SETUP_DMA_MAP;
 
                u->context = &context;
                u->complete = ctrl_complete;
-               u->transfer_flags |= URB_ASYNC_UNLINK;
        }
 
        /* queue the urbs */
@@ -1053,7 +1057,6 @@ static int unlink1 (struct usbtest_dev *dev, int pipe, int size, int async)
        urb = simple_alloc_urb (testdev_to_usbdev (dev), pipe, size);
        if (!urb)
                return -ENOMEM;
-       urb->transfer_flags |= URB_ASYNC_UNLINK;
        urb->context = &completion;
        urb->complete = unlink1_callback;
 
@@ -1243,7 +1246,7 @@ static int ctrl_out (struct usbtest_dev *dev,
        char                    *what = "?";
        struct usb_device       *udev;
        
-       if (length > 0xffff || vary >= length)
+       if (length < 1 || length > 0xffff || vary >= length)
                return -EINVAL;
 
        buf = kmalloc(length, SLAB_KERNEL);
@@ -1266,6 +1269,11 @@ static int ctrl_out (struct usbtest_dev *dev,
                                0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
                if (retval != len) {
                        what = "write";
+                       if (retval >= 0) {
+                               INFO(dev, "ctrl_out, wlen %d (expected %d)\n",
+                                               retval, len);
+                               retval = -EBADMSG;
+                       }
                        break;
                }
 
@@ -1275,6 +1283,11 @@ static int ctrl_out (struct usbtest_dev *dev,
                                0, 0, buf, len, USB_CTRL_GET_TIMEOUT);
                if (retval != len) {
                        what = "read";
+                       if (retval >= 0) {
+                               INFO(dev, "ctrl_out, rlen %d (expected %d)\n",
+                                               retval, len);
+                               retval = -EBADMSG;
+                       }
                        break;
                }
 
@@ -1293,8 +1306,13 @@ static int ctrl_out (struct usbtest_dev *dev,
                }
 
                len += vary;
+
+               /* [real world] the "zero bytes IN" case isn't really used.
+                * hardware can easily trip up in this wierd case, since its
+                * status stage is IN, not OUT like other ep0in transfers.
+                */
                if (len > length)
-                       len = 0;
+                       len = realworld ? 1 : 0;
        }
 
        if (retval < 0)
@@ -1519,6 +1537,11 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
        if (down_interruptible (&dev->sem))
                return -ERESTARTSYS;
 
+       if (intf->dev.power.power_state.event != PM_EVENT_ON) {
+               up (&dev->sem);
+               return -EHOSTUNREACH;
+       }
+
        /* some devices, like ez-usb default devices, need a non-default
         * altsetting to have any active endpoints.  some tests change
         * altsettings; force a default so most tests don't need to check.
@@ -1762,8 +1785,10 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
        case 14:
                if (!dev->info->ctrl_out)
                        break;
-               dev_dbg (&intf->dev, "TEST 14:  %d ep0out, 0..%d vary %d\n",
-                               param->iterations, param->length, param->vary);
+               dev_dbg (&intf->dev, "TEST 14:  %d ep0out, %d..%d vary %d\n",
+                               param->iterations,
+                               realworld ? 1 : 0, param->length,
+                               param->vary);
                retval = ctrl_out (dev, param->iterations, 
                                param->length, param->vary);
                break;
@@ -1851,10 +1876,9 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
        }
 #endif
 
-       dev = kmalloc (sizeof *dev, SLAB_KERNEL);
+       dev = kzalloc(sizeof(*dev), SLAB_KERNEL);
        if (!dev)
                return -ENOMEM;
-       memset (dev, 0, sizeof *dev);
        info = (struct usbtest_info *) id->driver_info;
        dev->info = info;
        init_MUTEX (&dev->sem);
@@ -1927,6 +1951,17 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
        return 0;
 }
 
+static int usbtest_suspend (struct usb_interface *intf, pm_message_t message)
+{
+       return 0;
+}
+
+static int usbtest_resume (struct usb_interface *intf)
+{
+       return 0;
+}
+
+
 static void usbtest_disconnect (struct usb_interface *intf)
 {
        struct usbtest_dev      *dev = usb_get_intfdata (intf);
@@ -2109,12 +2144,13 @@ static struct usb_device_id id_table [] = {
 MODULE_DEVICE_TABLE (usb, id_table);
 
 static struct usb_driver usbtest_driver = {
-       .owner =        THIS_MODULE,
        .name =         "usbtest",
        .id_table =     id_table,
        .probe =        usbtest_probe,
        .ioctl =        usbtest_ioctl,
        .disconnect =   usbtest_disconnect,
+       .suspend =      usbtest_suspend,
+       .resume =       usbtest_resume,
 };
 
 /*-------------------------------------------------------------------------*/