WorkStruct: make allyesconfig
[safe/jmp/linux-2.6] / drivers / usb / atm / ueagle-atm.c
index 7d2a679..e39bb09 100644 (file)
 #include <linux/ctype.h>
 #include <linux/kthread.h>
 #include <linux/version.h>
+#include <linux/mutex.h>
 #include <asm/unaligned.h>
 
 #include "usbatm.h"
 
-#define EAGLEUSBVERSION "ueagle 1.1"
+#define EAGLEUSBVERSION "ueagle 1.4"
 
 
 /*
                        dev_dbg(&(usb_dev)->dev, \
                                "[ueagle-atm dbg] %s: " format, \
                                        __FUNCTION__, ##args); \
-       } while (0)
+       } while (0)
 
 #define uea_vdbg(usb_dev, format, args...)     \
        do { \
                if (debug >= 2) \
                        dev_dbg(&(usb_dev)->dev, \
                                "[ueagle-atm vdbg]  " format, ##args); \
-       } while (0)
+       } while (0)
 
 #define uea_enters(usb_dev) \
        uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__)
@@ -217,8 +218,8 @@ enum {
 #define UEA_CHIP_VERSION(x) \
        ((x)->driver_info & 0xf)
 
-#define IS_ISDN(sc) \
-       (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80)
+#define IS_ISDN(usb_dev) \
+       (le16_to_cpu((usb_dev)->descriptor.bcdDevice) & 0x80)
 
 #define INS_TO_USBDEV(ins) ins->usb_dev
 
@@ -242,7 +243,7 @@ enum {
 #define BULK_TIMEOUT 300
 #define CTRL_TIMEOUT 1000
 
-#define ACK_TIMEOUT msecs_to_jiffies(1500)
+#define ACK_TIMEOUT msecs_to_jiffies(3000)
 
 #define UEA_INTR_IFACE_NO      0
 #define UEA_US_IFACE_NO                1
@@ -313,6 +314,10 @@ struct cmv {
         ((d) & 0xff) << 16 |                                           \
         ((a) & 0xff) << 8  |                                           \
         ((b) & 0xff))
+#define GETSA1(a) ((a >> 8) & 0xff)
+#define GETSA2(a) (a & 0xff)
+#define GETSA3(a) ((a >> 24) & 0xff)
+#define GETSA4(a) ((a >> 16) & 0xff)
 
 #define SA_CNTL MAKESA('C', 'N', 'T', 'L')
 #define SA_DIAG MAKESA('D', 'I', 'A', 'G')
@@ -358,16 +363,19 @@ struct intr_pkt {
 #define INTR_PKT_SIZE 28
 
 static struct usb_driver uea_driver;
-static DECLARE_MUTEX(uea_semaphore);
+static DEFINE_MUTEX(uea_mutex);
 static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"};
 
 static int modem_index;
 static unsigned int debug;
+static int use_iso[NB_MODEM] = {[0 ... (NB_MODEM - 1)] = 1};
 static int sync_wait[NB_MODEM];
 static char *cmv_file[NB_MODEM];
 
 module_param(debug, uint, 0644);
 MODULE_PARM_DESC(debug, "module debug level (0=off,1=on,2=verbose)");
+module_param_array(use_iso, bool, NULL, 0644);
+MODULE_PARM_DESC(use_iso, "use isochronous usb pipe for incoming traffic");
 module_param_array(sync_wait, bool, NULL, 0644);
 MODULE_PARM_DESC(sync_wait, "wait the synchronisation before starting ATM");
 module_param_array(cmv_file, charp, NULL, 0644);
@@ -617,19 +625,18 @@ static int request_dsp(struct uea_softc *sc)
        char *dsp_name;
 
        if (UEA_CHIP_VERSION(sc) == ADI930) {
-               if (IS_ISDN(sc))
+               if (IS_ISDN(sc->usb_dev))
                        dsp_name = FW_DIR "DSP9i.bin";
                else
                        dsp_name = FW_DIR "DSP9p.bin";
        } else {
-               if (IS_ISDN(sc))
+               if (IS_ISDN(sc->usb_dev))
                        dsp_name = FW_DIR "DSPei.bin";
                else
                        dsp_name = FW_DIR "DSPep.bin";
        }
 
-       ret = request_firmware(&sc->dsp_firm,
-                               dsp_name, &sc->usb_dev->dev);
+       ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev);
        if (ret < 0) {
                uea_err(INS_TO_USBDEV(sc),
                       "requesting firmware %s failed with error %d\n",
@@ -651,9 +658,9 @@ static int request_dsp(struct uea_softc *sc)
 /*
  * The uea_load_page() function must be called within a process context
  */
-static void uea_load_page(void *xsc)
+static void uea_load_page(struct work_struct *work)
 {
-       struct uea_softc *sc = xsc;
+       struct uea_softc *sc = container_of(work, struct uea_softc, task);
        u16 pageno = sc->pageno;
        u16 ovl = sc->ovl;
        struct block_info bi;
@@ -725,26 +732,29 @@ bad2:
        uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", i);
        return;
 bad1:
-       uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n",pageno);
+       uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno);
 }
 
 static inline void wake_up_cmv_ack(struct uea_softc *sc)
 {
+       BUG_ON(sc->cmv_ack);
        sc->cmv_ack = 1;
        wake_up(&sc->cmv_ack_wait);
 }
 
 static inline int wait_cmv_ack(struct uea_softc *sc)
 {
-       int ret = wait_event_timeout(sc->cmv_ack_wait,
+       int ret = wait_event_interruptible_timeout(sc->cmv_ack_wait,
                                                   sc->cmv_ack, ACK_TIMEOUT);
        sc->cmv_ack = 0;
 
+       uea_dbg(INS_TO_USBDEV(sc), "wait_event_timeout : %d ms\n",
+                       jiffies_to_msecs(ret));
+
        if (ret < 0)
                return ret;
 
        return (ret == 0) ? -ETIMEDOUT : 0;
-
 }
 
 #define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
@@ -789,6 +799,12 @@ static int uea_cmv(struct uea_softc *sc,
        struct cmv cmv;
        int ret;
 
+       uea_enters(INS_TO_USBDEV(sc));
+       uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, "
+                       "offset : 0x%04x, data : 0x%08x\n",
+                       FUNCTION_TYPE(function), FUNCTION_SUBTYPE(function),
+                       GETSA1(address), GETSA2(address), GETSA3(address),
+                       GETSA4(address), offset, data);
        /* we send a request, but we expect a reply */
        sc->cmv_function = function | 0x2;
        sc->cmv_idx++;
@@ -806,7 +822,9 @@ static int uea_cmv(struct uea_softc *sc,
        ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv);
        if (ret < 0)
                return ret;
-       return wait_cmv_ack(sc);
+       ret = wait_cmv_ack(sc);
+       uea_leaves(INS_TO_USBDEV(sc));
+       return ret;
 }
 
 static inline int uea_read_cmv(struct uea_softc *sc,
@@ -867,7 +885,8 @@ static int uea_stat(struct uea_softc *sc)
                break;
 
        case 3:         /* fail ... */
-               uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n");
+               uea_info(INS_TO_USBDEV(sc), "modem synchronization failed"
+                               " (may be try other cmv/dsp)\n");
                return -EAGAIN;
 
        case 4 ... 6:   /* test state */
@@ -895,12 +914,6 @@ static int uea_stat(struct uea_softc *sc)
                        release_firmware(sc->dsp_firm);
                        sc->dsp_firm = NULL;
                }
-
-               ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);
-               if (ret < 0)
-                       return ret;
-               uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",
-                               sc->stats.phy.firmid);
        }
 
        /* always update it as atm layer could not be init when we switch to
@@ -920,7 +933,7 @@ static int uea_stat(struct uea_softc *sc)
         * we check the status again in order to detect the failure earlier
         */
        if (sc->stats.phy.flags) {
-               uea_dbg(INS_TO_USBDEV(sc), "Stat flag = %d\n",
+               uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n",
                       sc->stats.phy.flags);
                return 0;
        }
@@ -935,6 +948,7 @@ static int uea_stat(struct uea_softc *sc)
         * ADI930 don't support it (-EPIPE error).
         */
        if (UEA_CHIP_VERSION(sc) != ADI930
+                   && !use_iso[sc->modem_index]
                    && sc->stats.phy.dsrate != (data >> 16) * 32) {
                /* Original timming from ADI(used in windows driver)
                 * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits
@@ -1010,13 +1024,13 @@ static int request_cmvs(struct uea_softc *sc,
        int ret, size;
        u8 *data;
        char *file;
-       static char cmv_name[256] = FW_DIR;
+       char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */
 
        if (cmv_file[sc->modem_index] == NULL) {
                if (UEA_CHIP_VERSION(sc) == ADI930)
-                       file = (IS_ISDN(sc)) ? "CMV9i.bin" : "CMV9p.bin";
+                       file = (IS_ISDN(sc->usb_dev)) ? "CMV9i.bin" : "CMV9p.bin";
                else
-                       file = (IS_ISDN(sc)) ? "CMVei.bin" : "CMVep.bin";
+                       file = (IS_ISDN(sc->usb_dev)) ? "CMVei.bin" : "CMVep.bin";
        } else
                file = cmv_file[sc->modem_index];
 
@@ -1060,7 +1074,13 @@ static int uea_start_reset(struct uea_softc *sc)
        uea_enters(INS_TO_USBDEV(sc));
        uea_info(INS_TO_USBDEV(sc), "(re)booting started\n");
 
+       /* mask interrupt */
        sc->booting = 1;
+       /* We need to set this here because, a ack timeout could have occured,
+        * but before we start the reboot, the ack occurs and set this to 1.
+        * So we will failed to wait Ready CMV.
+        */
+       sc->cmv_ack = 0;
        UPDATE_ATM_STAT(signal, ATM_PHY_SIG_LOST);
 
        /* reset statistics */
@@ -1086,6 +1106,7 @@ static int uea_start_reset(struct uea_softc *sc)
 
        msleep(1000);
        sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY);
+       /* demask interrupt */
        sc->booting = 0;
 
        /* start loading DSP */
@@ -1098,11 +1119,20 @@ static int uea_start_reset(struct uea_softc *sc)
        if (ret < 0)
                return ret;
 
+       uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n");
+
        /* Enter in R-IDLE (cmv) until instructed otherwise */
        ret = uea_write_cmv(sc, SA_CNTL, 0, 1);
        if (ret < 0)
                return ret;
 
+       /* Dump firmware version */
+       ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid);
+       if (ret < 0)
+               return ret;
+       uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n",
+                       sc->stats.phy.firmid);
+
        /* get options */
        ret = len = request_cmvs(sc, &cmvs, &cmvs_fw);
        if (ret < 0)
@@ -1118,6 +1148,9 @@ static int uea_start_reset(struct uea_softc *sc)
        }
        /* Enter in R-ACT-REQ */
        ret = uea_write_cmv(sc, SA_CNTL, 0, 2);
+       uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n");
+       uea_info(INS_TO_USBDEV(sc), "Modem started, "
+               "waiting synchronization\n");
 out:
        release_firmware(cmvs_fw);
        sc->reset = 0;
@@ -1143,7 +1176,10 @@ static int uea_kthread(void *data)
                if (!ret)
                        ret = uea_stat(sc);
                if (ret != -EAGAIN)
-                       msleep(1000);
+                       msleep_interruptible(1000);
+               if (try_to_freeze())
+                       uea_err(INS_TO_USBDEV(sc), "suspend/resume not supported, "
+                               "please unplug/replug your modem\n");
        }
        uea_leaves(INS_TO_USBDEV(sc));
        return ret;
@@ -1184,8 +1220,7 @@ static int load_XILINX_firmware(struct uea_softc *sc)
                }
        }
 
-       /* finish to send the fpga
-        */
+       /* finish to send the fpga */
        ret = uea_request(sc, 0xe, 1, 0, NULL);
        if (ret < 0) {
                uea_err(INS_TO_USBDEV(sc),
@@ -1193,9 +1228,7 @@ static int load_XILINX_firmware(struct uea_softc *sc)
                goto err1;
        }
 
-       /*
-        * Tell the modem we finish : de-assert reset
-        */
+       /* Tell the modem we finish : de-assert reset */
        value = 0;
        ret = uea_send_modem_cmd(sc->usb_dev, 0xe, 1, &value);
        if (ret < 0)
@@ -1209,6 +1242,7 @@ err0:
        return ret;
 }
 
+/* The modem send us an ack. First with check if it right */
 static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
 {
        uea_enters(INS_TO_USBDEV(sc));
@@ -1234,6 +1268,7 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
 
        if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) {
                wake_up_cmv_ack(sc);
+               uea_leaves(INS_TO_USBDEV(sc));
                return;
        }
 
@@ -1248,6 +1283,7 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv)
        sc->data = sc->data << 16 | sc->data >> 16;
 
        wake_up_cmv_ack(sc);
+       uea_leaves(INS_TO_USBDEV(sc));
        return;
 
 bad2:
@@ -1255,36 +1291,34 @@ bad2:
                        "Function : %d, Subfunction : %d\n",
                        FUNCTION_TYPE(cmv->bFunction),
                        FUNCTION_SUBTYPE(cmv->bFunction));
+       uea_leaves(INS_TO_USBDEV(sc));
        return;
 
 bad1:
        uea_err(INS_TO_USBDEV(sc), "invalid cmv received, "
                        "wPreamble %d, bDirection %d\n",
                        le16_to_cpu(cmv->wPreamble), cmv->bDirection);
+       uea_leaves(INS_TO_USBDEV(sc));
 }
 
 /*
  * interrupt handler
  */
-static void uea_intr(struct urb *urb, struct pt_regs *regs)
+static void uea_intr(struct urb *urb)
 {
-       struct uea_softc *sc = (struct uea_softc *)urb->context;
-       struct intr_pkt *intr;
+       struct uea_softc *sc = urb->context;
+       struct intr_pkt *intr = urb->transfer_buffer;
        uea_enters(INS_TO_USBDEV(sc));
 
-       if (urb->status < 0) {
+       if (unlikely(urb->status < 0)) {
                uea_err(INS_TO_USBDEV(sc), "uea_intr() failed with %d\n",
                       urb->status);
                return;
        }
 
-       intr = (struct intr_pkt *) urb->transfer_buffer;
-
        /* device-to-host interrupt */
        if (intr->bType != 0x08 || sc->booting) {
-               uea_err(INS_TO_USBDEV(sc), "wrong intr\n");
-               // rebooting ?
-               // sc->reset = 1;
+               uea_err(INS_TO_USBDEV(sc), "wrong interrupt\n");
                goto resubmit;
        }
 
@@ -1300,7 +1334,7 @@ static void uea_intr(struct urb *urb, struct pt_regs *regs)
                break;
 
        default:
-               uea_err(INS_TO_USBDEV(sc), "unknown intr %u\n",
+               uea_err(INS_TO_USBDEV(sc), "unknown interrupt %u\n",
                       le16_to_cpu(intr->wInterrupt));
        }
 
@@ -1318,7 +1352,7 @@ static int uea_boot(struct uea_softc *sc)
 
        uea_enters(INS_TO_USBDEV(sc));
 
-       INIT_WORK(&sc->task, uea_load_page, sc);
+       INIT_WORK(&sc->task, uea_load_page);
        init_waitqueue_head(&sc->sync_q);
        init_waitqueue_head(&sc->cmv_ack_wait);
 
@@ -1349,7 +1383,7 @@ static int uea_boot(struct uea_softc *sc)
        if (ret < 0) {
                uea_err(INS_TO_USBDEV(sc),
                       "urb submition failed with error %d\n", ret);
-               goto err1;
+               goto err;
        }
 
        sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
@@ -1363,10 +1397,10 @@ static int uea_boot(struct uea_softc *sc)
 
 err2:
        usb_kill_urb(sc->urb_int);
-err1:
-       kfree(intr);
 err:
        usb_free_urb(sc->urb_int);
+       sc->urb_int = NULL;
+       kfree(intr);
        uea_leaves(INS_TO_USBDEV(sc));
        return -ENOMEM;
 }
@@ -1379,7 +1413,7 @@ static void uea_stop(struct uea_softc *sc)
        int ret;
        uea_enters(INS_TO_USBDEV(sc));
        ret = kthread_stop(sc->kthread);
-       uea_info(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
+       uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);
 
        /* stop any pending boot process */
        flush_scheduled_work();
@@ -1418,13 +1452,13 @@ static ssize_t read_status(struct device *dev, struct device_attribute *attr,
        int ret = -ENODEV;
        struct uea_softc *sc;
 
-       down(&uea_semaphore);
+       mutex_lock(&uea_mutex);
        sc = dev_to_uea(dev);
        if (!sc)
                goto out;
        ret = snprintf(buf, 10, "%08x\n", sc->stats.phy.state);
 out:
-       up(&uea_semaphore);
+       mutex_unlock(&uea_mutex);
        return ret;
 }
 
@@ -1434,14 +1468,14 @@ static ssize_t reboot(struct device *dev, struct device_attribute *attr,
        int ret = -ENODEV;
        struct uea_softc *sc;
 
-       down(&uea_semaphore);
+       mutex_lock(&uea_mutex);
        sc = dev_to_uea(dev);
        if (!sc)
                goto out;
        sc->reset = 1;
        ret = count;
 out:
-       up(&uea_semaphore);
+       mutex_unlock(&uea_mutex);
        return ret;
 }
 
@@ -1453,7 +1487,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at
        int ret = -ENODEV;
        struct uea_softc *sc;
 
-       down(&uea_semaphore);
+       mutex_lock(&uea_mutex);
        sc = dev_to_uea(dev);
        if (!sc)
                goto out;
@@ -1473,7 +1507,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at
                break;
        }
 out:
-       up(&uea_semaphore);
+       mutex_unlock(&uea_mutex);
        return ret;
 }
 
@@ -1485,7 +1519,7 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
        int ret = -ENODEV;
        struct uea_softc *sc;
 
-       down(&uea_semaphore);
+       mutex_lock(&uea_mutex);
        sc = dev_to_uea(dev);
        if (!sc)
                goto out;
@@ -1497,7 +1531,7 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr,
        else
                ret = sprintf(buf, "GOOD\n");
 out:
-       up(&uea_semaphore);
+       mutex_unlock(&uea_mutex);
        return ret;
 }
 
@@ -1511,7 +1545,7 @@ static ssize_t read_##name(struct device *dev,                    \
        int ret = -ENODEV;                                      \
        struct uea_softc *sc;                                   \
                                                                \
-       down(&uea_semaphore);                                   \
+       mutex_lock(&uea_mutex);                                 \
        sc = dev_to_uea(dev);                                   \
        if (!sc)                                                \
                goto out;                                       \
@@ -1519,7 +1553,7 @@ static ssize_t read_##name(struct device *dev,                    \
        if (reset)                                              \
                sc->stats.phy.name = 0;                         \
 out:                                                           \
-       up(&uea_semaphore);                                     \
+       mutex_unlock(&uea_mutex);                               \
        return ret;                                             \
 }                                                              \
                                                                \
@@ -1539,6 +1573,7 @@ UEA_ATTR(uscorr, 0);
 UEA_ATTR(dscorr, 0);
 UEA_ATTR(usunc, 0);
 UEA_ATTR(dsunc, 0);
+UEA_ATTR(firmid, 0);
 
 /* Retrieve the device End System Identifier (MAC) */
 
@@ -1570,7 +1605,7 @@ static int uea_heavy(struct usbatm_data *usbatm, struct usb_interface *intf)
 {
        struct uea_softc *sc = usbatm->driver_data;
 
-       wait_event(sc->sync_q, IS_OPERATIONAL(sc));
+       wait_event_interruptible(sc->sync_q, IS_OPERATIONAL(sc));
 
        return 0;
 
@@ -1594,30 +1629,33 @@ static int claim_interface(struct usb_device *usb_dev,
        return ret;
 }
 
-static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
-{
-       /* sysfs interface */
-       device_create_file(&intf->dev, &dev_attr_stat_status);
-       device_create_file(&intf->dev, &dev_attr_stat_mflags);
-       device_create_file(&intf->dev, &dev_attr_stat_human_status);
-       device_create_file(&intf->dev, &dev_attr_stat_delin);
-       device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
-       device_create_file(&intf->dev, &dev_attr_stat_usrate);
-       device_create_file(&intf->dev, &dev_attr_stat_dsrate);
-       device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
-       device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
-       device_create_file(&intf->dev, &dev_attr_stat_usmargin);
-       device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
-       device_create_file(&intf->dev, &dev_attr_stat_txflow);
-       device_create_file(&intf->dev, &dev_attr_stat_rxflow);
-       device_create_file(&intf->dev, &dev_attr_stat_uscorr);
-       device_create_file(&intf->dev, &dev_attr_stat_dscorr);
-       device_create_file(&intf->dev, &dev_attr_stat_usunc);
-       device_create_file(&intf->dev, &dev_attr_stat_dsunc);
-}
+static struct attribute *attrs[] = {
+       &dev_attr_stat_status.attr,
+       &dev_attr_stat_mflags.attr,
+       &dev_attr_stat_human_status.attr,
+       &dev_attr_stat_delin.attr,
+       &dev_attr_stat_vidcpe.attr,
+       &dev_attr_stat_usrate.attr,
+       &dev_attr_stat_dsrate.attr,
+       &dev_attr_stat_usattenuation.attr,
+       &dev_attr_stat_dsattenuation.attr,
+       &dev_attr_stat_usmargin.attr,
+       &dev_attr_stat_dsmargin.attr,
+       &dev_attr_stat_txflow.attr,
+       &dev_attr_stat_rxflow.attr,
+       &dev_attr_stat_uscorr.attr,
+       &dev_attr_stat_dscorr.attr,
+       &dev_attr_stat_usunc.attr,
+       &dev_attr_stat_dsunc.attr,
+       &dev_attr_stat_firmid.attr,
+       NULL,
+};
+static struct attribute_group attr_grp = {
+       .attrs = attrs,
+};
 
 static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
-                  const struct usb_device_id *id, int *heavy)
+                  const struct usb_device_id *id)
 {
        struct usb_device *usb = interface_to_usbdev(intf);
        struct uea_softc *sc;
@@ -1629,16 +1667,14 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
        if (ifnum != UEA_INTR_IFACE_NO)
                return -ENODEV;
 
-       *heavy = sync_wait[modem_index];
+       usbatm->flags = (sync_wait[modem_index] ? 0 : UDSL_SKIP_HEAVY_INIT);
 
        /* interface 1 is for outbound traffic */
        ret = claim_interface(usb, usbatm, UEA_US_IFACE_NO);
        if (ret < 0)
                return ret;
 
-       /* ADI930 has only 2 interfaces and inbound traffic
-        * is on interface 1
-        */
+       /* ADI930 has only 2 interfaces and inbound traffic is on interface 1 */
        if (UEA_CHIP_VERSION(id) != ADI930) {
                /* interface 2 is for inbound traffic */
                ret = claim_interface(usb, usbatm, UEA_DS_IFACE_NO);
@@ -1648,7 +1684,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
 
        sc = kzalloc(sizeof(struct uea_softc), GFP_KERNEL);
        if (!sc) {
-               uea_err(INS_TO_USBDEV(sc), "uea_init: not enough memory !\n");
+               uea_err(usb, "uea_init: not enough memory !\n");
                return -ENOMEM;
        }
 
@@ -1658,56 +1694,57 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
        sc->modem_index = (modem_index < NB_MODEM) ? modem_index++ : 0;
        sc->driver_info = id->driver_info;
 
-       ret = uea_boot(sc);
-       if (ret < 0) {
-               kfree(sc);
-               return ret;
+       /* ADI930 don't support iso */
+       if (UEA_CHIP_VERSION(id) != ADI930 && use_iso[sc->modem_index]) {
+               int i;
+
+               /* try set fastest alternate for inbound traffic interface */
+               for (i = FASTEST_ISO_INTF; i > 0; i--)
+                       if (usb_set_interface(usb, UEA_DS_IFACE_NO, i) == 0)
+                               break;
+
+               if (i > 0) {
+                       uea_dbg(usb, "set alternate %d for 2 interface\n", i);
+                       uea_info(usb, "using iso mode\n");
+                       usbatm->flags |= UDSL_USE_ISOC | UDSL_IGNORE_EILSEQ;
+               } else {
+                       uea_err(usb, "setting any alternate failed for "
+                                       "2 interface, using bulk mode\n");
+               }
        }
 
-       create_fs_entries(sc, intf);
-       return 0;
-}
+       ret = sysfs_create_group(&intf->dev.kobj, &attr_grp);
+       if (ret < 0)
+               goto error;
 
-static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
-{
-       /* sysfs interface */
-       device_remove_file(&intf->dev, &dev_attr_stat_status);
-       device_remove_file(&intf->dev, &dev_attr_stat_mflags);
-       device_remove_file(&intf->dev, &dev_attr_stat_human_status);
-       device_remove_file(&intf->dev, &dev_attr_stat_delin);
-       device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
-       device_remove_file(&intf->dev, &dev_attr_stat_usrate);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
-       device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
-       device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
-       device_remove_file(&intf->dev, &dev_attr_stat_txflow);
-       device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
-       device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
-       device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
-       device_remove_file(&intf->dev, &dev_attr_stat_usunc);
-       device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
+       ret = uea_boot(sc);
+       if (ret < 0)
+               goto error;
+
+       return 0;
+error:
+       kfree(sc);
+       return ret;
 }
 
 static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
 {
        struct uea_softc *sc = usbatm->driver_data;
 
-       destroy_fs_entries(sc, intf);
+       sysfs_remove_group(&intf->dev.kobj, &attr_grp);
        uea_stop(sc);
        kfree(sc);
 }
 
 static struct usbatm_driver uea_usbatm_driver = {
        .driver_name = "ueagle-atm",
-       .owner = THIS_MODULE,
        .bind = uea_bind,
        .atm_start = uea_atm_open,
        .unbind = uea_unbind,
        .heavy_init = uea_heavy,
-       .in = UEA_BULK_DATA_PIPE,
-       .out = UEA_BULK_DATA_PIPE,
+       .bulk_in = UEA_BULK_DATA_PIPE,
+       .bulk_out = UEA_BULK_DATA_PIPE,
+       .isoc_in = UEA_ISO_DATA_PIPE,
 };
 
 static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
@@ -1715,10 +1752,10 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
        struct usb_device *usb = interface_to_usbdev(intf);
 
        uea_enters(usb);
-       uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n",
+       uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s %s\n",
               le16_to_cpu(usb->descriptor.idVendor),
               le16_to_cpu(usb->descriptor.idProduct),
-              chip_name[UEA_CHIP_VERSION(id)]);
+              chip_name[UEA_CHIP_VERSION(id)], IS_ISDN(usb)?"isdn":"pots");
 
        usb_reset_device(usb);
 
@@ -1738,9 +1775,9 @@ static void uea_disconnect(struct usb_interface *intf)
         * Pre-firmware device has one interface
         */
        if (usb->config->desc.bNumInterfaces != 1 && ifnum == 0) {
-               down(&uea_semaphore);
+               mutex_lock(&uea_mutex);
                usbatm_usb_disconnect(intf);
-               up(&uea_semaphore);
+               mutex_unlock(&uea_mutex);
                uea_info(usb, "ADSL device removed\n");
        }