#define RTL8152_MAX_TX         10
 #define RTL8152_MAX_RX         10
+#define INTBUFSIZE             2
+
+#define INTR_LINK              0x0004
 
 #define RTL8152_REQT_READ      0xc0
 #define RTL8152_REQT_WRITE     0x40
 enum rtl8152_flags {
        RTL8152_UNPLUG = 0,
        RTL8152_SET_RX_MODE,
-       WORK_ENABLE
+       WORK_ENABLE,
+       RTL8152_LINK_CHG,
 };
 
 /* Define these values to match your device */
        unsigned long flags;
        struct usb_device *udev;
        struct tasklet_struct tl;
+       struct usb_interface *intf;
        struct net_device *netdev;
+       struct urb *intr_urb;
        struct tx_agg tx_info[RTL8152_MAX_TX];
        struct rx_agg rx_info[RTL8152_MAX_RX];
        struct list_head rx_done, tx_free;
        spinlock_t rx_lock, tx_lock;
        struct delayed_work schedule;
        struct mii_if_info mii;
+       int intr_interval;
        u32 msg_enable;
        u16 ocp_base;
+       u8 *intr_buff;
        u8 version;
        u8 speed;
 };
                tasklet_schedule(&tp->tl);
 }
 
+static void intr_callback(struct urb *urb)
+{
+       struct r8152 *tp;
+       __u16 *d;
+       int status = urb->status;
+       int res;
+
+       tp = urb->context;
+       if (!tp)
+               return;
+
+       if (!test_bit(WORK_ENABLE, &tp->flags))
+               return;
+
+       if (test_bit(RTL8152_UNPLUG, &tp->flags))
+               return;
+
+       switch (status) {
+       case 0:                 /* success */
+               break;
+       case -ECONNRESET:       /* unlink */
+       case -ESHUTDOWN:
+               netif_device_detach(tp->netdev);
+       case -ENOENT:
+               return;
+       case -EOVERFLOW:
+               netif_info(tp, intr, tp->netdev, "intr status -EOVERFLOW\n");
+               goto resubmit;
+       /* -EPIPE:  should clear the halt */
+       default:
+               netif_info(tp, intr, tp->netdev, "intr status %d\n", status);
+               goto resubmit;
+       }
+
+       d = urb->transfer_buffer;
+       if (INTR_LINK & __le16_to_cpu(d[0])) {
+               if (!(tp->speed & LINK_STATUS)) {
+                       set_bit(RTL8152_LINK_CHG, &tp->flags);
+                       schedule_delayed_work(&tp->schedule, 0);
+               }
+       } else {
+               if (tp->speed & LINK_STATUS) {
+                       set_bit(RTL8152_LINK_CHG, &tp->flags);
+                       schedule_delayed_work(&tp->schedule, 0);
+               }
+       }
+
+resubmit:
+       res = usb_submit_urb(urb, GFP_ATOMIC);
+       if (res == -ENODEV)
+               netif_device_detach(tp->netdev);
+       else if (res)
+               netif_err(tp, intr, tp->netdev,
+                       "can't resubmit intr, status %d\n", res);
+}
+
 static inline void *rx_agg_align(void *data)
 {
        return (void *)ALIGN((uintptr_t)data, 8);
                        tp->tx_info[i].head = NULL;
                }
        }
+
+       if (tp->intr_urb) {
+               usb_free_urb(tp->intr_urb);
+               tp->intr_urb = NULL;
+       }
+
+       if (tp->intr_buff) {
+               kfree(tp->intr_buff);
+               tp->intr_buff = NULL;
+       }
 }
 
 static int alloc_all_mem(struct r8152 *tp)
 {
        struct net_device *netdev = tp->netdev;
+       struct usb_interface *intf = tp->intf;
+       struct usb_host_interface *alt = intf->cur_altsetting;
+       struct usb_host_endpoint *ep_intr = alt->endpoint + 2;
        struct urb *urb;
        int node, i;
        u8 *buf;
                list_add_tail(&tp->tx_info[i].list, &tp->tx_free);
        }
 
+       tp->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!tp->intr_urb)
+               goto err1;
+
+       tp->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL);
+       if (!tp->intr_buff)
+               goto err1;
+
+       tp->intr_interval = (int)ep_intr->desc.bInterval;
+       usb_fill_int_urb(tp->intr_urb, tp->udev, usb_rcvintpipe(tp->udev, 3),
+                    tp->intr_buff, INTBUFSIZE, intr_callback,
+                    tp, tp->intr_interval);
+
        return 0;
 
 err1:
 {
        struct r8152 *tp = netdev_priv(netdev);
 
-       if (tp->speed & LINK_STATUS)
+       if (tp->speed & LINK_STATUS) {
                set_bit(RTL8152_SET_RX_MODE, &tp->flags);
+               schedule_delayed_work(&tp->schedule, 0);
+       }
 }
 
 static void _rtl8152_set_rx_mode(struct net_device *netdev)
        r8152_mdio_write(tp, MII_BMCR, bmcr);
 
 out:
-       schedule_delayed_work(&tp->schedule, 5 * HZ);
 
        return ret;
 }
        struct net_device *netdev = tp->netdev;
        u8 speed;
 
+       clear_bit(RTL8152_LINK_CHG, &tp->flags);
        speed = rtl8152_get_speed(tp);
 
        if (speed & LINK_STATUS) {
        if (test_bit(RTL8152_UNPLUG, &tp->flags))
                goto out1;
 
-       set_carrier(tp);
+       if (test_bit(RTL8152_LINK_CHG, &tp->flags))
+               set_carrier(tp);
 
        if (test_bit(RTL8152_SET_RX_MODE, &tp->flags))
                _rtl8152_set_rx_mode(tp->netdev);
 
-       schedule_delayed_work(&tp->schedule, HZ);
-
 out1:
        return;
 }
        struct r8152 *tp = netdev_priv(netdev);
        int res = 0;
 
-       tp->speed = rtl8152_get_speed(tp);
-       if (tp->speed & LINK_STATUS) {
-               res = rtl8152_enable(tp);
-               if (res) {
-                       if (res == -ENODEV)
-                               netif_device_detach(tp->netdev);
-
-                       netif_err(tp, ifup, netdev,
-                                 "rtl8152_open failed: %d\n", res);
-                       return res;
-               }
-
-               netif_carrier_on(netdev);
-       } else {
-               netif_stop_queue(netdev);
-               netif_carrier_off(netdev);
+       res = usb_submit_urb(tp->intr_urb, GFP_KERNEL);
+       if (res) {
+               if (res == -ENODEV)
+                       netif_device_detach(tp->netdev);
+               netif_warn(tp, ifup, netdev,
+                       "intr_urb submit failed: %d\n", res);
+               return res;
        }
 
        rtl8152_set_speed(tp, AUTONEG_ENABLE, SPEED_100, DUPLEX_FULL);
+       tp->speed = 0;
+       netif_carrier_off(netdev);
        netif_start_queue(netdev);
        set_bit(WORK_ENABLE, &tp->flags);
-       schedule_delayed_work(&tp->schedule, 0);
 
        return res;
 }
        struct r8152 *tp = netdev_priv(netdev);
        int res = 0;
 
+       usb_kill_urb(tp->intr_urb);
        clear_bit(WORK_ENABLE, &tp->flags);
        cancel_delayed_work_sync(&tp->schedule);
        netif_stop_queue(netdev);
 
        if (netif_running(tp->netdev)) {
                clear_bit(WORK_ENABLE, &tp->flags);
+               usb_kill_urb(tp->intr_urb);
                cancel_delayed_work_sync(&tp->schedule);
                tasklet_disable(&tp->tl);
        }
        r8152b_init(tp);
        netif_device_attach(tp->netdev);
        if (netif_running(tp->netdev)) {
-               rtl8152_enable(tp);
+               rtl8152_set_speed(tp, AUTONEG_ENABLE, SPEED_100, DUPLEX_FULL);
+               tp->speed = 0;
+               netif_carrier_off(tp->netdev);
                set_bit(WORK_ENABLE, &tp->flags);
-               set_bit(RTL8152_SET_RX_MODE, &tp->flags);
-               schedule_delayed_work(&tp->schedule, 0);
+               usb_submit_urb(tp->intr_urb, GFP_KERNEL);
                tasklet_enable(&tp->tl);
        }
 
 
        tp->udev = udev;
        tp->netdev = netdev;
+       tp->intf = intf;
        netdev->netdev_ops = &rtl8152_netdev_ops;
        netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
 
        netdev->features |= NETIF_F_IP_CSUM;
        netdev->hw_features = NETIF_F_IP_CSUM;
        SET_ETHTOOL_OPS(netdev, &ops);
-       tp->speed = 0;
 
        tp->mii.dev = netdev;
        tp->mii.mdio_read = read_mii_word;