]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Mar 2010 23:47:04 +0000 (16:47 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Mar 2010 23:47:04 +0000 (16:47 -0700)
* 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds:
  leds: Fix race between LED device uevent and actual attributes creation
  leds-gpio: fix default state handling on OF platforms
  leds: Add Dell Business Class Netbook LED driver
  leds: Kconfig cleanup
  leds: led-class.c - Quiet boot messages
  leds: make PCI device id constant
  leds: ALIX2: Add dependency to !GPIO_CS5335

63 files changed:
Documentation/networking/Makefile
Documentation/networking/timestamping/Makefile
Documentation/networking/timestamping/timestamping.c
MAINTAINERS
drivers/atm/lanai.c
drivers/base/memory.c
drivers/char/hpet.c
drivers/isdn/gigaset/capi.c
drivers/isdn/gigaset/common.c
drivers/isdn/gigaset/dummyll.c
drivers/isdn/gigaset/ev-layer.c
drivers/isdn/gigaset/gigaset.h
drivers/isdn/gigaset/i4l.c
drivers/isdn/gigaset/interface.c
drivers/isdn/hardware/eicon/message.c
drivers/isdn/hardware/mISDN/hfcmulti.c
drivers/isdn/hysdn/hysdn_boot.c
drivers/net/benet/be_cmds.c
drivers/net/bnx2x_main.c
drivers/net/davinci_emac.c
drivers/net/e100.c
drivers/net/irda/w83977af_ir.c
drivers/net/ksz884x.c
drivers/net/myri10ge/myri10ge.c
drivers/net/ne.c
drivers/net/pppol2tp.c
drivers/net/s2io.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/hso.c
drivers/net/usb/smsc75xx.c [new file with mode: 0644]
drivers/net/usb/smsc75xx.h [new file with mode: 0644]
drivers/net/usb/smsc95xx.c
drivers/pcmcia/i82092.c
drivers/pcmcia/i82365.h
drivers/pcmcia/pcmcia_resource.c
drivers/pcmcia/pd6729.c
drivers/pcmcia/ti113x.h
drivers/pcmcia/vrc4171_card.c
drivers/pcmcia/yenta_socket.c
drivers/s390/char/sclp_cmd.c
drivers/scsi/pcmcia/nsp_cs.c
drivers/serial/sunsab.c
drivers/video/Kconfig
fs/jffs2/readinode.c
fs/ntfs/super.c
fs/xfs/linux-2.6/xfs_aops.c
fs/xfs/linux-2.6/xfs_buf.c
include/linux/memory.h
mm/page_cgroup.c
net/bridge/br_device.c
net/bridge/br_forward.c
net/bridge/br_input.c
net/bridge/br_multicast.c
net/bridge/br_private.h
net/core/netpoll.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/proto.c
net/ipv4/route.c
net/phonet/pn_dev.c
net/phonet/pn_netlink.c
net/tipc/ref.c

index 6d8af1ac56c410f11d0e85863a180884082c21ee..5aba7a33aeeb7bacedb28a596e4cdaed848d0162 100644 (file)
@@ -6,3 +6,5 @@ hostprogs-y := ifenslave
 
 # Tell kbuild to always build the programs
 always := $(hostprogs-y)
+
+obj-m := timestamping/
index 2a1489fdc0361b8e6b134981645800ba05e7e628..e79973443e9fdcbe096445f4a13b102435a20ac6 100644 (file)
@@ -1,6 +1,13 @@
-CPPFLAGS = -I../../../include
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+obj- := dummy.o
 
-timestamping: timestamping.c
+# List of programs to build
+hostprogs-y := timestamping
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
+
+HOSTCFLAGS_timestamping.o += -I$(objtree)/usr/include
 
 clean:
        rm -f timestamping
index bab619a482145e9a08ecc62f674d9c6bb05110cc..8ba82bfe6a33c57d54adcde8d7c3e1977926d565 100644 (file)
@@ -41,9 +41,9 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 
-#include "asm/types.h"
-#include "linux/net_tstamp.h"
-#include "linux/errqueue.h"
+#include <asm/types.h>
+#include <linux/net_tstamp.h>
+#include <linux/errqueue.h>
 
 #ifndef SO_TIMESTAMPING
 # define SO_TIMESTAMPING         37
@@ -164,7 +164,7 @@ static void printpacket(struct msghdr *msg, int res,
 
        gettimeofday(&now, 0);
 
-       printf("%ld.%06ld: received %s data, %d bytes from %s, %d bytes control messages\n",
+       printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
               (long)now.tv_sec, (long)now.tv_usec,
               (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
               res,
@@ -173,7 +173,7 @@ static void printpacket(struct msghdr *msg, int res,
        for (cmsg = CMSG_FIRSTHDR(msg);
             cmsg;
             cmsg = CMSG_NXTHDR(msg, cmsg)) {
-               printf("   cmsg len %d: ", cmsg->cmsg_len);
+               printf("   cmsg len %zu: ", cmsg->cmsg_len);
                switch (cmsg->cmsg_level) {
                case SOL_SOCKET:
                        printf("SOL_SOCKET ");
index 47cc449d89d89746b1dba3cda6aae88afe1bf990..382eaa4d0068540f624ce77c88b266003f2a082a 100644 (file)
@@ -5214,6 +5214,21 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
 S:     Maintained
 F:     arch/sparc/
 
+SPARC SERIAL DRIVERS
+M:     "David S. Miller" <davem@davemloft.net>
+L:     sparclinux@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
+S:     Maintained
+F:     drivers/serial/suncore.c
+F:     drivers/serial/suncore.h
+F:     drivers/serial/sunhv.c
+F:     drivers/serial/sunsab.c
+F:     drivers/serial/sunsab.h
+F:     drivers/serial/sunsu.c
+F:     drivers/serial/sunzilog.c
+F:     drivers/serial/sunzilog.h
+
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
 M:     Roger Wolff <R.E.Wolff@BitWizard.nl>
 S:     Supported
index 7fe7c324e7ef5213fa5cd616024ed8d58a84f508..23d95054705be2f2671555a144d889cf8aaa2e02 100644 (file)
@@ -306,11 +306,10 @@ static void vci_bitfield_iterate(struct lanai_dev *lanai,
        const unsigned long *lp,
        void (*func)(struct lanai_dev *,vci_t vci))
 {
-       vci_t vci = find_first_bit(lp, NUM_VCI);
-       while (vci < NUM_VCI) {
+       vci_t vci;
+
+       for_each_set_bit(vci, lp, NUM_VCI)
                func(lanai, vci);
-               vci = find_next_bit(lp, NUM_VCI, vci + 1);
-       }
 }
 
 /* -------------------- BUFFER  UTILITIES: */
index 2f8691511190f921e1e6a75beab9581d123d68d7..db0848e54cc639f7ad63d7673cd48e90d570fb34 100644 (file)
@@ -429,12 +429,16 @@ static inline int memory_fail_init(void)
  * differentiation between which *physical* devices each
  * section belongs to...
  */
+int __weak arch_get_memory_phys_device(unsigned long start_pfn)
+{
+       return 0;
+}
 
 static int add_memory_block(int nid, struct mem_section *section,
-                       unsigned long state, int phys_device,
-                       enum mem_add_context context)
+                       unsigned long state, enum mem_add_context context)
 {
        struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+       unsigned long start_pfn;
        int ret = 0;
 
        if (!mem)
@@ -443,7 +447,8 @@ static int add_memory_block(int nid, struct mem_section *section,
        mem->phys_index = __section_nr(section);
        mem->state = state;
        mutex_init(&mem->state_mutex);
-       mem->phys_device = phys_device;
+       start_pfn = section_nr_to_pfn(mem->phys_index);
+       mem->phys_device = arch_get_memory_phys_device(start_pfn);
 
        ret = register_memory(mem, section);
        if (!ret)
@@ -515,7 +520,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section,
  */
 int register_new_memory(int nid, struct mem_section *section)
 {
-       return add_memory_block(nid, section, MEM_OFFLINE, 0, HOTPLUG);
+       return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG);
 }
 
 int unregister_memory_section(struct mem_section *section)
@@ -548,7 +553,7 @@ int __init memory_dev_init(void)
                if (!present_section_nr(i))
                        continue;
                err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
-                                       0, BOOT);
+                                      BOOT);
                if (!ret)
                        ret = err;
        }
index e481c5938badeb19c2ea9d518e9340c4dc93edd3..9c5eea3ea4deb22b7cb215184b3dd3a9b8a69152 100644 (file)
@@ -215,9 +215,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
        else
                v &= ~0xffff;
 
-       for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
-               irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
-
+       for_each_set_bit(irq, &v, HPET_MAX_IRQ) {
                if (irq >= nr_irqs) {
                        irq = HPET_MAX_IRQ;
                        break;
index 6643d6533ccb98d9a8a49502d8ae3f69f68a9693..0220c19351d92ced75c5669ea6d1cf0d77a323ea 100644 (file)
@@ -1301,7 +1301,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
        }
 
        /* check parameter: CIP Value */
-       if (cmsg->CIPValue > ARRAY_SIZE(cip2bchlc) ||
+       if (cmsg->CIPValue >= ARRAY_SIZE(cip2bchlc) ||
            (cmsg->CIPValue > 0 && cip2bchlc[cmsg->CIPValue].bc == NULL)) {
                dev_notice(cs->dev, "%s: unknown CIP value %d\n",
                           "CONNECT_REQ", cmsg->CIPValue);
@@ -2191,36 +2191,24 @@ static const struct file_operations gigaset_proc_fops = {
        .release        = single_release,
 };
 
-static struct capi_driver capi_driver_gigaset = {
-       .name           = "gigaset",
-       .revision       = "1.0",
-};
-
 /**
- * gigaset_isdn_register() - register to LL
+ * gigaset_isdn_regdev() - register device to LL
  * @cs:                device descriptor structure.
  * @isdnid:    device name.
  *
- * Called by main module to register the device with the LL.
- *
  * Return value: 1 for success, 0 for failure
  */
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
 {
        struct gigaset_capi_ctr *iif;
        int rc;
 
-       pr_info("Kernel CAPI interface\n");
-
        iif = kmalloc(sizeof(*iif), GFP_KERNEL);
        if (!iif) {
                pr_err("%s: out of memory\n", __func__);
                return 0;
        }
 
-       /* register driver with CAPI (ToDo: what for?) */
-       register_capi_driver(&capi_driver_gigaset);
-
        /* prepare controller structure */
        iif->ctr.owner         = THIS_MODULE;
        iif->ctr.driverdata    = cs;
@@ -2241,7 +2229,6 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
        rc = attach_capi_ctr(&iif->ctr);
        if (rc) {
                pr_err("attach_capi_ctr failed (%d)\n", rc);
-               unregister_capi_driver(&capi_driver_gigaset);
                kfree(iif);
                return 0;
        }
@@ -2252,17 +2239,36 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
 }
 
 /**
- * gigaset_isdn_unregister() - unregister from LL
+ * gigaset_isdn_unregdev() - unregister device from LL
  * @cs:                device descriptor structure.
- *
- * Called by main module to unregister the device from the LL.
  */
-void gigaset_isdn_unregister(struct cardstate *cs)
+void gigaset_isdn_unregdev(struct cardstate *cs)
 {
        struct gigaset_capi_ctr *iif = cs->iif;
 
        detach_capi_ctr(&iif->ctr);
        kfree(iif);
        cs->iif = NULL;
+}
+
+static struct capi_driver capi_driver_gigaset = {
+       .name           = "gigaset",
+       .revision       = "1.0",
+};
+
+/**
+ * gigaset_isdn_regdrv() - register driver to LL
+ */
+void gigaset_isdn_regdrv(void)
+{
+       pr_info("Kernel CAPI interface\n");
+       register_capi_driver(&capi_driver_gigaset);
+}
+
+/**
+ * gigaset_isdn_unregdrv() - unregister driver from LL
+ */
+void gigaset_isdn_unregdrv(void)
+{
        unregister_capi_driver(&capi_driver_gigaset);
 }
index 85de3399a2f2dfb005cba5f0c0d89d6af491bab1..bdc01cb9f0ab247960bc786fad05820c910fd532 100644 (file)
@@ -507,7 +507,7 @@ void gigaset_freecs(struct cardstate *cs)
        case 2: /* error in initcshw */
                /* Deregister from LL */
                make_invalid(cs, VALID_ID);
-               gigaset_isdn_unregister(cs);
+               gigaset_isdn_unregdev(cs);
 
                /* fall through */
        case 1: /* error when registering to LL */
@@ -769,7 +769,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
        cs->cmdbytes = 0;
 
        gig_dbg(DEBUG_INIT, "setting up iif");
-       if (!gigaset_isdn_register(cs, modulename)) {
+       if (!gigaset_isdn_regdev(cs, modulename)) {
                pr_err("error registering ISDN device\n");
                goto error;
        }
@@ -1205,11 +1205,13 @@ static int __init gigaset_init_module(void)
                gigaset_debuglevel = DEBUG_DEFAULT;
 
        pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n");
+       gigaset_isdn_regdrv();
        return 0;
 }
 
 static void __exit gigaset_exit_module(void)
 {
+       gigaset_isdn_unregdrv();
 }
 
 module_init(gigaset_init_module);
index 5b27c996af6db6ffaa9c42ae32346f3f52b2f42f..bd0b1eaa7572bf785368d7e9fa013c9b93cc10ae 100644 (file)
@@ -57,12 +57,20 @@ void gigaset_isdn_stop(struct cardstate *cs)
 {
 }
 
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
 {
-       pr_info("no ISDN subsystem interface\n");
        return 1;
 }
 
-void gigaset_isdn_unregister(struct cardstate *cs)
+void gigaset_isdn_unregdev(struct cardstate *cs)
+{
+}
+
+void gigaset_isdn_regdrv(void)
+{
+       pr_info("no ISDN subsystem interface\n");
+}
+
+void gigaset_isdn_unregdrv(void)
 {
 }
index c8f89b78b233525267a7cfba0d34ced7a7595a1e..206c380c52358c724aa72a06ce6c7405d9ff7164 100644 (file)
@@ -1258,14 +1258,10 @@ static void do_action(int action, struct cardstate *cs,
                 * note that bcs may be NULL if no B channel is free
                 */
                at_state2->ConState = 700;
-               kfree(at_state2->str_var[STR_NMBR]);
-               at_state2->str_var[STR_NMBR] = NULL;
-               kfree(at_state2->str_var[STR_ZCPN]);
-               at_state2->str_var[STR_ZCPN] = NULL;
-               kfree(at_state2->str_var[STR_ZBC]);
-               at_state2->str_var[STR_ZBC] = NULL;
-               kfree(at_state2->str_var[STR_ZHLC]);
-               at_state2->str_var[STR_ZHLC] = NULL;
+               for (i = 0; i < STR_NUM; ++i) {
+                       kfree(at_state2->str_var[i]);
+                       at_state2->str_var[i] = NULL;
+               }
                at_state2->int_var[VAR_ZCTP] = -1;
 
                spin_lock_irqsave(&cs->lock, flags);
index 1875ab80b3355c16e8e836655276919dd5ca1b10..cdd144ecdc5f462c972425b11ce1d978bb588eb8 100644 (file)
@@ -675,8 +675,10 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size);
  */
 
 /* Called from common.c for setting up/shutting down with the ISDN subsystem */
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid);
-void gigaset_isdn_unregister(struct cardstate *cs);
+void gigaset_isdn_regdrv(void);
+void gigaset_isdn_unregdrv(void);
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid);
+void gigaset_isdn_unregdev(struct cardstate *cs);
 
 /* Called from hardware module to indicate completion of an skb */
 void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb);
index f0acb9dc9e33cb1725f98f6c9da6fde57315b418..c22e5ace8276a99fe39188eb13941e56f6b07cb4 100644 (file)
@@ -592,15 +592,13 @@ void gigaset_isdn_stop(struct cardstate *cs)
 }
 
 /**
- * gigaset_isdn_register() - register to LL
+ * gigaset_isdn_regdev() - register to LL
  * @cs:                device descriptor structure.
  * @isdnid:    device name.
  *
- * Called by main module to register the device with the LL.
- *
  * Return value: 1 for success, 0 for failure
  */
-int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
+int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid)
 {
        isdn_if *iif;
 
@@ -650,15 +648,29 @@ int gigaset_isdn_register(struct cardstate *cs, const char *isdnid)
 }
 
 /**
- * gigaset_isdn_unregister() - unregister from LL
+ * gigaset_isdn_unregdev() - unregister device from LL
  * @cs:                device descriptor structure.
- *
- * Called by main module to unregister the device from the LL.
  */
-void gigaset_isdn_unregister(struct cardstate *cs)
+void gigaset_isdn_unregdev(struct cardstate *cs)
 {
        gig_dbg(DEBUG_CMD, "sending UNLOAD");
        gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD);
        kfree(cs->iif);
        cs->iif = NULL;
 }
+
+/**
+ * gigaset_isdn_regdrv() - register driver to LL
+ */
+void gigaset_isdn_regdrv(void)
+{
+       /* nothing to do */
+}
+
+/**
+ * gigaset_isdn_unregdrv() - unregister driver from LL
+ */
+void gigaset_isdn_unregdrv(void)
+{
+       /* nothing to do */
+}
index a1bcbc21ff718c493a8cbc2256d801083e34cbeb..f0dc6c9cc283634c358a4604bb78141bcb71cf57 100644 (file)
@@ -628,7 +628,6 @@ void gigaset_if_receive(struct cardstate *cs,
        if (tty == NULL)
                gig_dbg(DEBUG_IF, "receive on closed device");
        else {
-               tty_buffer_request_room(tty, len);
                tty_insert_flip_string(tty, buffer, len);
                tty_flip_buffer_push(tty);
        }
index ae89fb89da64ae4d0a286ed7fe237f8e227f59fd..341ef17c22acb279848ced2d08747189cf128bc2 100644 (file)
@@ -2754,7 +2754,7 @@ static byte connect_b3_req(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
                     for (i = 0; i < w; i++)
                       ((T30_INFO   *)(plci->fax_connect_info_buffer))->station_id[i] = fax_parms[4].info[1+i];
                     ((T30_INFO   *)(plci->fax_connect_info_buffer))->head_line_len = 0;
-                    len = offsetof(T30_INFO, station_id) + 20;
+                    len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
                     w = fax_parms[5].length;
                     if (w > 20)
                       w = 20;
@@ -2892,7 +2892,7 @@ static byte connect_b3_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_ENABLE_NSF)
     && (plci->nsf_control_bits & T30_NSF_CONTROL_BIT_NEGOTIATE_RESP))
    {
-            len = offsetof(T30_INFO, station_id) + 20;
+            len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
             if (plci->fax_connect_info_length < len)
             {
               ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
@@ -3802,7 +3802,7 @@ static byte manufacturer_res(dword Id, word Number, DIVA_CAPI_ADAPTER *a,
       break;
     }
     ncpi = &m_parms[1];
-    len = offsetof(T30_INFO, station_id) + 20;
+    len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
     if (plci->fax_connect_info_length < len)
     {
       ((T30_INFO *)(plci->fax_connect_info_buffer))->station_id_len = 0;
@@ -6830,7 +6830,7 @@ static void nl_ind(PLCI *plci)
         if(((T30_INFO   *)plci->NL.RBuffer->P)->station_id_len)
         {
           plci->ncpi_buffer[len] = 20;
-          for (i = 0; i < 20; i++)
+          for (i = 0; i < T30_MAX_STATION_ID_LENGTH; i++)
             plci->ncpi_buffer[++len] = ((T30_INFO   *)plci->NL.RBuffer->P)->station_id[i];
         }
         if (((plci->NL.Ind & 0x0f) == N_DISC) || ((plci->NL.Ind & 0x0f) == N_DISC_ACK))
@@ -6844,7 +6844,7 @@ static void nl_ind(PLCI *plci)
         if ((plci->requested_options_conn | plci->requested_options | a->requested_options_table[plci->appl->Id-1])
           & ((1L << PRIVATE_FAX_SUB_SEP_PWD) | (1L << PRIVATE_FAX_NONSTANDARD)))
         {
-          i = offsetof(T30_INFO, station_id) + 20 + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
+          i = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + ((T30_INFO   *)plci->NL.RBuffer->P)->head_line_len;
           while (i < plci->NL.RBuffer->length)
             plci->ncpi_buffer[++len] = plci->NL.RBuffer->P[i++];
         }
@@ -8400,7 +8400,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp)
         }
       }
       /* copy station id to NLC */
-      for(i=0; i<20; i++)
+      for(i=0; i < T30_MAX_STATION_ID_LENGTH; i++)
       {
         if(i<b3_config_parms[2].length)
         {
@@ -8411,29 +8411,29 @@ static word add_b23(PLCI *plci, API_PARSE *bp)
           ((T30_INFO *)&nlc[1])->station_id[i] = ' ';
         }
       }
-      ((T30_INFO *)&nlc[1])->station_id_len = 20;
+      ((T30_INFO *)&nlc[1])->station_id_len = T30_MAX_STATION_ID_LENGTH;
       /* copy head line to NLC */
       if(b3_config_parms[3].length)
       {
 
-        pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[20])));
+        pos = (byte)(fax_head_line_time (&(((T30_INFO *)&nlc[1])->station_id[T30_MAX_STATION_ID_LENGTH])));
         if (pos != 0)
         {
           if (CAPI_MAX_DATE_TIME_LENGTH + 2 + b3_config_parms[3].length > CAPI_MAX_HEAD_LINE_SPACE)
             pos = 0;
           else
           {
-            ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
-            ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
+            nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
+            nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
             len = (byte)b3_config_parms[2].length;
             if (len > 20)
               len = 20;
             if (CAPI_MAX_DATE_TIME_LENGTH + 2 + len + 2 + b3_config_parms[3].length <= CAPI_MAX_HEAD_LINE_SPACE)
             {
               for (i = 0; i < len; i++)
-                ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
-              ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
-              ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ' ';
+                nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ((byte   *)b3_config_parms[2].info)[1+i];
+              nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
+              nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] = ' ';
             }
           }
         }
@@ -8444,9 +8444,8 @@ static word add_b23(PLCI *plci, API_PARSE *bp)
         ((T30_INFO *)&nlc[1])->head_line_len = (byte)(pos + len);
         nlc[0] += (byte)(pos + len);
         for (i = 0; i < len; i++)
-          ((T30_INFO *)&nlc[1])->station_id[20 + pos++] = ((byte   *)b3_config_parms[3].info)[1+i];
-        }
-      else
+          nlc[1 + offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH + pos++] =  ((byte   *)b3_config_parms[3].info)[1+i];
+      } else
         ((T30_INFO *)&nlc[1])->head_line_len = 0;
 
       plci->nsf_control_bits = 0;
@@ -8473,7 +8472,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp)
             fax_control_bits |= T30_CONTROL_BIT_ACCEPT_SEL_POLLING;
           }
             len = nlc[0];
-          pos = offsetof(T30_INFO, station_id) + 20;
+          pos = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
    if (pos < plci->fax_connect_info_length)
    {
      for (i = 1 + plci->fax_connect_info_buffer[pos]; i != 0; i--)
@@ -8525,7 +8524,7 @@ static word add_b23(PLCI *plci, API_PARSE *bp)
       }
 
       PUT_WORD(&(((T30_INFO *)&nlc[1])->control_bits_low), fax_control_bits);
-      len = offsetof(T30_INFO, station_id) + 20;
+      len = offsetof(T30_INFO, station_id) + T30_MAX_STATION_ID_LENGTH;
       for (i = 0; i < len; i++)
         plci->fax_connect_info_buffer[i] = nlc[1+i];
       ((T30_INFO   *) plci->fax_connect_info_buffer)->head_line_len = 0;
index ad36df9b759ca614a922a893e85c9e43aabf1806..8affba3e569d888dfea0518d3610280e1ac6bb09 100644 (file)
@@ -5265,6 +5265,8 @@ static const struct hm_map hfcm_map[] = {
 /*31*/ {VENDOR_CCD, "XHFC-4S Speech Design", 5, 4, 0, 0, 0, 0,
                HFC_IO_MODE_EMBSD, XHFC_IRQ},
 /*32*/ {VENDOR_JH, "HFC-8S (junghanns)", 8, 8, 1, 0, 0, 0, 0, 0},
+/*33*/ {VENDOR_BN, "HFC-2S Beronet Card PCIe", 4, 2, 1, 3, 0, DIP_4S, 0, 0},
+/*34*/ {VENDOR_BN, "HFC-4S Beronet Card PCIe", 4, 4, 1, 2, 0, DIP_4S, 0, 0},
 };
 
 #undef H
@@ -5300,6 +5302,10 @@ static struct pci_device_id hfmultipci_ids[] __devinitdata = {
                PCI_SUBDEVICE_ID_CCD_OV4S, 0, 0, H(28)}, /* OpenVox 4 */
        { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
                PCI_SUBDEVICE_ID_CCD_OV2S, 0, 0, H(29)}, /* OpenVox 2 */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               0xb761, 0, 0, H(33)}, /* BN2S PCIe */
+       { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC4S, PCI_VENDOR_ID_CCD,
+               0xb762, 0, 0, H(34)}, /* BN4S PCIe */
 
        /* Cards with HFC-8S Chip */
        { PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_HFC8S, PCI_VENDOR_ID_CCD,
index be787e16bb79b99b7e501aca2e395b09e235fa86..4f541ef14f9efd845ba953faadab303478125a24 100644 (file)
@@ -143,7 +143,7 @@ pof_handle_data(hysdn_card * card, int datlen)
                                             (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA",
                                             datlen, boot->pof_recoffset);
 
-                       if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0))
+                       if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen)) < 0)
                                return (boot->last_error);      /* error writing data */
 
                        if (boot->pof_recoffset + datlen >= boot->pof_reclen)
index c59215361f4ee29a2a265f5277a40c05b5e2c0ef..50e6259b50e4db0489d443715252aa8c6a3b754a 100644 (file)
@@ -673,7 +673,7 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
        be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                        OPCODE_COMMON_MCC_CREATE, sizeof(*req));
 
-       req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
+       req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
 
        AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1);
        AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt,
index ed785a30e98bbcadaa0de666d6763c0608f221fc..6c042a72d6ccb0ef460bf5ad0700e3aedf7ff7ed 100644 (file)
@@ -893,7 +893,6 @@ static inline u16 bnx2x_tx_avail(struct bnx2x_fastpath *fp)
        u16 prod;
        u16 cons;
 
-       barrier(); /* Tell compiler that prod and cons can change */
        prod = fp->tx_bd_prod;
        cons = fp->tx_bd_cons;
 
@@ -963,7 +962,7 @@ static int bnx2x_tx_int(struct bnx2x_fastpath *fp)
         * start_xmit() will miss it and cause the queue to be stopped
         * forever.
         */
-       smp_wmb();
+       smp_mb();
 
        /* TBD need a thresh? */
        if (unlikely(netif_tx_queue_stopped(txq))) {
@@ -11429,9 +11428,12 @@ static netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (unlikely(bnx2x_tx_avail(fp) < MAX_SKB_FRAGS + 3)) {
                netif_tx_stop_queue(txq);
-               /* We want bnx2x_tx_int to "see" the updated tx_bd_prod
-                  if we put Tx into XOFF state. */
+
+               /* paired memory barrier is in bnx2x_tx_int(), we have to keep
+                * ordering of set_bit() in netif_tx_stop_queue() and read of
+                * fp->bd_tx_cons */
                smp_mb();
+
                fp->eth_q_stats.driver_xoff++;
                if (bnx2x_tx_avail(fp) >= MAX_SKB_FRAGS + 3)
                        netif_tx_wake_queue(txq);
index 8bd086aee56dc02144ba68b4ab2d958a7783c5c8..2b8edd2efbf608994946f1a1cb9ae40f71938ae7 100644 (file)
  *     PHY layer usage
  */
 
-/** Pending Items in this driver:
- * 1. Use Linux cache infrastcture for DMA'ed memory (dma_xxx functions)
- */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -504,12 +500,6 @@ static unsigned long mdio_max_freq;
 
 /* Cache macros - Packet buffers would be from skb pool which is cached */
 #define EMAC_VIRT_NOCACHE(addr) (addr)
-#define EMAC_CACHE_INVALIDATE(addr, size) \
-       dma_cache_maint((void *)addr, size, DMA_FROM_DEVICE)
-#define EMAC_CACHE_WRITEBACK(addr, size) \
-       dma_cache_maint((void *)addr, size, DMA_TO_DEVICE)
-#define EMAC_CACHE_WRITEBACK_INVALIDATE(addr, size) \
-       dma_cache_maint((void *)addr, size, DMA_BIDIRECTIONAL)
 
 /* DM644x does not have BD's in cached memory - so no cache functions */
 #define BD_CACHE_INVALIDATE(addr, size)
@@ -1235,6 +1225,10 @@ static void emac_txch_teardown(struct emac_priv *priv, u32 ch)
        if (1 == txch->queue_active) {
                curr_bd = txch->active_queue_head;
                while (curr_bd != NULL) {
+                       dma_unmap_single(emac_dev, curr_bd->buff_ptr,
+                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
+                               DMA_TO_DEVICE);
+
                        emac_net_tx_complete(priv, (void __force *)
                                        &curr_bd->buf_token, 1, ch);
                        if (curr_bd != txch->active_queue_tail)
@@ -1327,6 +1321,11 @@ static int emac_tx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
                                txch->queue_active = 0; /* end of queue */
                        }
                }
+
+               dma_unmap_single(emac_dev, curr_bd->buff_ptr,
+                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
+                               DMA_TO_DEVICE);
+
                *tx_complete_ptr = (u32) curr_bd->buf_token;
                ++tx_complete_ptr;
                ++tx_complete_cnt;
@@ -1387,8 +1386,8 @@ static int emac_send(struct emac_priv *priv, struct emac_netpktobj *pkt, u32 ch)
 
        txch->bd_pool_head = curr_bd->next;
        curr_bd->buf_token = buf_list->buf_token;
-       /* FIXME buff_ptr = dma_map_single(... data_ptr ...) */
-       curr_bd->buff_ptr = virt_to_phys(buf_list->data_ptr);
+       curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buf_list->data_ptr,
+                       buf_list->length, DMA_TO_DEVICE);
        curr_bd->off_b_len = buf_list->length;
        curr_bd->h_next = 0;
        curr_bd->next = NULL;
@@ -1468,7 +1467,6 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
        tx_buf.length = skb->len;
        tx_buf.buf_token = (void *)skb;
        tx_buf.data_ptr = skb->data;
-       EMAC_CACHE_WRITEBACK((unsigned long)skb->data, skb->len);
        ndev->trans_start = jiffies;
        ret_code = emac_send(priv, &tx_packet, EMAC_DEF_TX_CH);
        if (unlikely(ret_code != 0)) {
@@ -1543,7 +1541,6 @@ static void *emac_net_alloc_rx_buf(struct emac_priv *priv, int buf_size,
        p_skb->dev = ndev;
        skb_reserve(p_skb, NET_IP_ALIGN);
        *data_token = (void *) p_skb;
-       EMAC_CACHE_WRITEBACK_INVALIDATE((unsigned long)p_skb->data, buf_size);
        return p_skb->data;
 }
 
@@ -1612,8 +1609,8 @@ static int emac_init_rxch(struct emac_priv *priv, u32 ch, char *param)
                /* populate the hardware descriptor */
                curr_bd->h_next = emac_virt_to_phys(rxch->active_queue_head,
                                priv);
-               /* FIXME buff_ptr = dma_map_single(... data_ptr ...) */
-               curr_bd->buff_ptr = virt_to_phys(curr_bd->data_ptr);
+               curr_bd->buff_ptr = dma_map_single(emac_dev, curr_bd->data_ptr,
+                               rxch->buf_size, DMA_FROM_DEVICE);
                curr_bd->off_b_len = rxch->buf_size;
                curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
 
@@ -1697,6 +1694,12 @@ static void emac_cleanup_rxch(struct emac_priv *priv, u32 ch)
                curr_bd = rxch->active_queue_head;
                while (curr_bd) {
                        if (curr_bd->buf_token) {
+                               dma_unmap_single(&priv->ndev->dev,
+                                       curr_bd->buff_ptr,
+                                       curr_bd->off_b_len
+                                               & EMAC_RX_BD_BUF_SIZE,
+                                       DMA_FROM_DEVICE);
+
                                dev_kfree_skb_any((struct sk_buff *)\
                                                  curr_bd->buf_token);
                        }
@@ -1871,8 +1874,8 @@ static void emac_addbd_to_rx_queue(struct emac_priv *priv, u32 ch,
 
        /* populate the hardware descriptor */
        curr_bd->h_next = 0;
-       /* FIXME buff_ptr = dma_map_single(... buffer ...) */
-       curr_bd->buff_ptr = virt_to_phys(buffer);
+       curr_bd->buff_ptr = dma_map_single(&priv->ndev->dev, buffer,
+                               rxch->buf_size, DMA_FROM_DEVICE);
        curr_bd->off_b_len = rxch->buf_size;
        curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
        curr_bd->next = NULL;
@@ -1927,7 +1930,6 @@ static int emac_net_rx_cb(struct emac_priv *priv,
        p_skb = (struct sk_buff *)net_pkt_list->pkt_token;
        /* set length of packet */
        skb_put(p_skb, net_pkt_list->pkt_length);
-       EMAC_CACHE_INVALIDATE((unsigned long)p_skb->data, p_skb->len);
        p_skb->protocol = eth_type_trans(p_skb, priv->ndev);
        netif_receive_skb(p_skb);
        priv->net_dev_stats.rx_bytes += net_pkt_list->pkt_length;
@@ -1990,6 +1992,11 @@ static int emac_rx_bdproc(struct emac_priv *priv, u32 ch, u32 budget)
                rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr;
                rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE;
                rx_buf_obj->buf_token = curr_bd->buf_token;
+
+               dma_unmap_single(&priv->ndev->dev, curr_bd->buff_ptr,
+                               curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE,
+                               DMA_FROM_DEVICE);
+
                curr_pkt->pkt_token = curr_pkt->buf_list->buf_token;
                curr_pkt->num_bufs = 1;
                curr_pkt->pkt_length =
@@ -2820,31 +2827,37 @@ static int __devexit davinci_emac_remove(struct platform_device *pdev)
        return 0;
 }
 
-static
-int davinci_emac_suspend(struct platform_device *pdev, pm_message_t state)
+static int davinci_emac_suspend(struct device *dev)
 {
-       struct net_device *dev = platform_get_drvdata(pdev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct net_device *ndev = platform_get_drvdata(pdev);
 
-       if (netif_running(dev))
-               emac_dev_stop(dev);
+       if (netif_running(ndev))
+               emac_dev_stop(ndev);
 
        clk_disable(emac_clk);
 
        return 0;
 }
 
-static int davinci_emac_resume(struct platform_device *pdev)
+static int davinci_emac_resume(struct device *dev)
 {
-       struct net_device *dev = platform_get_drvdata(pdev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct net_device *ndev = platform_get_drvdata(pdev);
 
        clk_enable(emac_clk);
 
-       if (netif_running(dev))
-               emac_dev_open(dev);
+       if (netif_running(ndev))
+               emac_dev_open(ndev);
 
        return 0;
 }
 
+static const struct dev_pm_ops davinci_emac_pm_ops = {
+       .suspend        = davinci_emac_suspend,
+       .resume         = davinci_emac_resume,
+};
+
 /**
  * davinci_emac_driver: EMAC platform driver structure
  */
@@ -2852,11 +2865,10 @@ static struct platform_driver davinci_emac_driver = {
        .driver = {
                .name    = "davinci_emac",
                .owner   = THIS_MODULE,
+               .pm      = &davinci_emac_pm_ops,
        },
        .probe = davinci_emac_probe,
        .remove = __devexit_p(davinci_emac_remove),
-       .suspend = davinci_emac_suspend,
-       .resume = davinci_emac_resume,
 };
 
 /**
index a26ccab057d56fe305c760eb4e64ac4744c3e4e2..b997e578e58f21295e1f01129aa27bc7815a07d0 100644 (file)
@@ -2858,7 +2858,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
        }
        nic->cbs_pool = pci_pool_create(netdev->name,
                           nic->pdev,
-                          nic->params.cbs.count * sizeof(struct cb),
+                          nic->params.cbs.max * sizeof(struct cb),
                           sizeof(u32),
                           0);
        DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n",
index 551810fd29760ccbd8f52345a0d7feb49fb4b1d2..980625feb2c09b3f5fd38ad608ad5d01a688cee9 100644 (file)
@@ -65,7 +65,6 @@
 #undef  CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */
 #define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */
 #endif
-#undef  CONFIG_USE_INTERNAL_TIMER  /* Just cannot make that timer work */
 #define CONFIG_USE_W977_PNP        /* Currently needed */
 #define PIO_MAX_SPEED       115200 
 
@@ -533,25 +532,6 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb,
                self->tx_buff.len = skb->len;
                
                mtt = irda_get_mtt(skb);
-#ifdef CONFIG_USE_INTERNAL_TIMER
-               if (mtt > 50) {
-                       /* Adjust for timer resolution */
-                       mtt /= 1000+1;
-
-                       /* Setup timer */
-                       switch_bank(iobase, SET4);
-                       outb(mtt & 0xff, iobase+TMRL);
-                       outb((mtt >> 8) & 0x0f, iobase+TMRH);
-                       
-                       /* Start timer */
-                       outb(IR_MSL_EN_TMR, iobase+IR_MSL);
-                       self->io.direction = IO_XMIT;
-                       
-                       /* Enable timer interrupt */
-                       switch_bank(iobase, SET0);
-                       outb(ICR_ETMRI, iobase+ICR);
-               } else {
-#endif
                        IRDA_DEBUG(4, "%s(%ld), mtt=%d\n", __func__ , jiffies, mtt);
                        if (mtt)
                                udelay(mtt);
@@ -560,9 +540,6 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb,
                        switch_bank(iobase, SET0);
                        outb(ICR_EDMAI, iobase+ICR);
                        w83977af_dma_write(self, iobase);
-#ifdef CONFIG_USE_INTERNAL_TIMER
-               }
-#endif
        } else {
                self->tx_buff.data = self->tx_buff.head;
                self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, 
@@ -876,20 +853,7 @@ static int w83977af_dma_receive_complete(struct w83977af_ir *self)
                        /* Check if we have transferred all data to memory */
                        switch_bank(iobase, SET0);
                        if (inb(iobase+USR) & USR_RDR) {
-#ifdef CONFIG_USE_INTERNAL_TIMER
-                               /* Put this entry back in fifo */
-                               st_fifo->head--;
-                               st_fifo->len++;
-                               st_fifo->entries[st_fifo->head].status = status;
-                               st_fifo->entries[st_fifo->head].len = len;
-                               
-                               /* Restore set register */
-                               outb(set, iobase+SSR);
-                       
-                               return FALSE;   /* I'll be back! */
-#else
                                udelay(80); /* Should be enough!? */
-#endif
                        }
                                                
                        skb = dev_alloc_skb(len+1);
index 7264a3e5c2c0880316576a00680815634da25ad5..0f59099ee72f8d504d314ef41af592d377f58795 100644 (file)
@@ -4899,8 +4899,10 @@ static int netdev_tx(struct sk_buff *skb, struct net_device *dev)
                        struct sk_buff *org_skb = skb;
 
                        skb = dev_alloc_skb(org_skb->len);
-                       if (!skb)
-                               return NETDEV_TX_BUSY;
+                       if (!skb) {
+                               rc = NETDEV_TX_BUSY;
+                               goto unlock;
+                       }
                        skb_copy_and_csum_dev(org_skb, skb->data);
                        org_skb->ip_summed = 0;
                        skb->len = org_skb->len;
@@ -4914,7 +4916,7 @@ static int netdev_tx(struct sk_buff *skb, struct net_device *dev)
                netif_stop_queue(dev);
                rc = NETDEV_TX_BUSY;
        }
-
+unlock:
        spin_unlock_irq(&hw_priv->hwlock);
 
        return rc;
index 676c513e12fc486eae515e6d539a7d95db4c8852..e84dd3ee9c5aa72fa227b4afca14c4a59dd76c40 100644 (file)
@@ -3687,7 +3687,6 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)
        if (status != 0) {
                dev_err(&mgp->pdev->dev, "failed reset\n");
                goto abort_with_fw;
-               return;
        }
 
        mgp->max_intr_slots = cmd.data0 / sizeof(struct mcp_slot);
index 992dbfffdb05ece983205f5ffe71d5e6073af208..f4347f88b6f2c62d73754bbee75adc416ecf8462 100644 (file)
@@ -142,7 +142,7 @@ bad_clone_list[] __initdata = {
     {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
     {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
 #ifdef CONFIG_MACH_TX49XX
-    {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
+    {"RBHMA4X00-RTL8019", "RBHMA4X00-RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
 #endif
     {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
     {NULL,}
index 9fbb2eba9a06747ea6aeb98c37506d49e149b895..449a9825200d5775d8bf221a36657ec87588f8fc 100644 (file)
@@ -756,6 +756,7 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
 
        /* Try to dequeue as many skbs from reorder_q as we can. */
        pppol2tp_recv_dequeue(session);
+       sock_put(sock);
 
        return 0;
 
@@ -772,6 +773,7 @@ discard_bad_csum:
        UDP_INC_STATS_USER(&init_net, UDP_MIB_INERRORS, 0);
        tunnel->stats.rx_errors++;
        kfree_skb(skb);
+       sock_put(sock);
 
        return 0;
 
@@ -1180,7 +1182,8 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
        /* Calculate UDP checksum if configured to do so */
        if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
                skb->ip_summed = CHECKSUM_NONE;
-       else if (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) {
+       else if ((skb_dst(skb) && skb_dst(skb)->dev) &&
+                (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) {
                skb->ip_summed = CHECKSUM_COMPLETE;
                csum = skb_checksum(skb, 0, udp_len, 0);
                uh->check = csum_tcpudp_magic(inet->inet_saddr,
@@ -1661,6 +1664,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
                if (tunnel_sock == NULL)
                        goto end;
 
+               sock_hold(tunnel_sock);
                tunnel = tunnel_sock->sk_user_data;
        } else {
                tunnel = pppol2tp_tunnel_find(sock_net(sk), sp->pppol2tp.s_tunnel);
index df70657260dd8805a3a383208f4c392ba9474691..2eb7f8a0d926a1a1e20ce3d1f82c071882308629 100644 (file)
@@ -5819,10 +5819,8 @@ static void s2io_vpd_read(struct s2io_nic *nic)
                }
        }
 
-       if ((!fail) && (vpd_data[1] < VPD_STRING_LEN)) {
-               memset(nic->product_name, 0, vpd_data[1]);
+       if ((!fail) && (vpd_data[1] < VPD_STRING_LEN))
                memcpy(nic->product_name, &vpd_data[3], vpd_data[1]);
-       }
        kfree(vpd_data);
        swstats->mem_freed += 256;
 }
index 32d93564a74d4839207fef67859c7bc1f967e3e7..ba56ce4382d9246969d672c299cb7f61dea45abd 100644 (file)
@@ -204,6 +204,14 @@ config USB_NET_DM9601
          This option adds support for Davicom DM9601 based USB 1.1
          10/100 Ethernet adapters.
 
+config USB_NET_SMSC75XX
+       tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
+       depends on USB_USBNET
+       select CRC32
+       help
+         This option adds support for SMSC LAN95XX based USB 2.0
+         Gigabit Ethernet adapters.
+
 config USB_NET_SMSC95XX
        tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
        depends on USB_USBNET
index e17afb78f37220df2c8c6a13eb420aa14280fd09..82ea62955b56e5188b272bdb071decc44c5da06c 100644 (file)
@@ -11,6 +11,7 @@ obj-$(CONFIG_USB_NET_AX8817X) += asix.o
 obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
 obj-$(CONFIG_USB_NET_CDC_EEM)  += cdc_eem.o
 obj-$(CONFIG_USB_NET_DM9601)   += dm9601.o
+obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o
 obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
 obj-$(CONFIG_USB_NET_GL620A)   += gl620a.o
 obj-$(CONFIG_USB_NET_NET1080)  += net1080.o
index 6895f15312380b146925d9ba17e71961ef177508..be0cc99e881a6c4c41c8b8f502d0392f4be343e5 100644 (file)
@@ -1155,9 +1155,6 @@ static void _hso_serial_set_termios(struct tty_struct *tty,
 static void hso_resubmit_rx_bulk_urb(struct hso_serial *serial, struct urb *urb)
 {
        int result;
-#ifdef CONFIG_HSO_AUTOPM
-       usb_mark_last_busy(urb->dev);
-#endif
        /* We are done with this URB, resubmit it. Prep the USB to wait for
         * another frame */
        usb_fill_bulk_urb(urb, serial->parent->usb,
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
new file mode 100644 (file)
index 0000000..300e3e7
--- /dev/null
@@ -0,0 +1,1288 @@
+ /***************************************************************************
+ *
+ * Copyright (C) 2007-2010 SMSC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/usbnet.h>
+#include "smsc75xx.h"
+
+#define SMSC_CHIPNAME                  "smsc75xx"
+#define SMSC_DRIVER_VERSION            "1.0.0"
+#define HS_USB_PKT_SIZE                        (512)
+#define FS_USB_PKT_SIZE                        (64)
+#define DEFAULT_HS_BURST_CAP_SIZE      (16 * 1024 + 5 * HS_USB_PKT_SIZE)
+#define DEFAULT_FS_BURST_CAP_SIZE      (6 * 1024 + 33 * FS_USB_PKT_SIZE)
+#define DEFAULT_BULK_IN_DELAY          (0x00002000)
+#define MAX_SINGLE_PACKET_SIZE         (9000)
+#define LAN75XX_EEPROM_MAGIC           (0x7500)
+#define EEPROM_MAC_OFFSET              (0x01)
+#define DEFAULT_TX_CSUM_ENABLE         (true)
+#define DEFAULT_RX_CSUM_ENABLE         (true)
+#define DEFAULT_TSO_ENABLE             (true)
+#define SMSC75XX_INTERNAL_PHY_ID       (1)
+#define SMSC75XX_TX_OVERHEAD           (8)
+#define MAX_RX_FIFO_SIZE               (20 * 1024)
+#define MAX_TX_FIFO_SIZE               (12 * 1024)
+#define USB_VENDOR_ID_SMSC             (0x0424)
+#define USB_PRODUCT_ID_LAN7500         (0x7500)
+#define USB_PRODUCT_ID_LAN7505         (0x7505)
+
+#define check_warn(ret, fmt, args...) \
+       ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
+
+#define check_warn_return(ret, fmt, args...) \
+       ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
+
+#define check_warn_goto_done(ret, fmt, args...) \
+       ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
+
+struct smsc75xx_priv {
+       struct usbnet *dev;
+       u32 rfe_ctl;
+       u32 multicast_hash_table[DP_SEL_VHF_HASH_LEN];
+       bool use_rx_csum;
+       struct mutex dataport_mutex;
+       spinlock_t rfe_ctl_lock;
+       struct work_struct set_multicast;
+};
+
+struct usb_context {
+       struct usb_ctrlrequest req;
+       struct usbnet *dev;
+};
+
+static int turbo_mode = true;
+module_param(turbo_mode, bool, 0644);
+MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
+
+static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
+                                         u32 *data)
+{
+       u32 *buf = kmalloc(4, GFP_KERNEL);
+       int ret;
+
+       BUG_ON(!dev);
+
+       if (!buf)
+               return -ENOMEM;
+
+       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+               USB_VENDOR_REQUEST_READ_REGISTER,
+               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+
+       if (unlikely(ret < 0))
+               netdev_warn(dev->net,
+                       "Failed to read register index 0x%08x", index);
+
+       le32_to_cpus(buf);
+       *data = *buf;
+       kfree(buf);
+
+       return ret;
+}
+
+static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
+                                          u32 data)
+{
+       u32 *buf = kmalloc(4, GFP_KERNEL);
+       int ret;
+
+       BUG_ON(!dev);
+
+       if (!buf)
+               return -ENOMEM;
+
+       *buf = data;
+       cpu_to_le32s(buf);
+
+       ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+               USB_VENDOR_REQUEST_WRITE_REGISTER,
+               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+               00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+
+       if (unlikely(ret < 0))
+               netdev_warn(dev->net,
+                       "Failed to write register index 0x%08x", index);
+
+       kfree(buf);
+
+       return ret;
+}
+
+/* Loop until the read is completed with timeout
+ * called with phy_mutex held */
+static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
+{
+       unsigned long start_time = jiffies;
+       u32 val;
+       int ret;
+
+       do {
+               ret = smsc75xx_read_reg(dev, MII_ACCESS, &val);
+               check_warn_return(ret, "Error reading MII_ACCESS");
+
+               if (!(val & MII_ACCESS_BUSY))
+                       return 0;
+       } while (!time_after(jiffies, start_time + HZ));
+
+       return -EIO;
+}
+
+static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       u32 val, addr;
+       int ret;
+
+       mutex_lock(&dev->phy_mutex);
+
+       /* confirm MII not busy */
+       ret = smsc75xx_phy_wait_not_busy(dev);
+       check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_read");
+
+       /* set the address, index & direction (read from PHY) */
+       phy_id &= dev->mii.phy_id_mask;
+       idx &= dev->mii.reg_num_mask;
+       addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
+               | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
+               | MII_ACCESS_READ;
+       ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
+       check_warn_goto_done(ret, "Error writing MII_ACCESS");
+
+       ret = smsc75xx_phy_wait_not_busy(dev);
+       check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
+
+       ret = smsc75xx_read_reg(dev, MII_DATA, &val);
+       check_warn_goto_done(ret, "Error reading MII_DATA");
+
+       ret = (u16)(val & 0xFFFF);
+
+done:
+       mutex_unlock(&dev->phy_mutex);
+       return ret;
+}
+
+static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+                               int regval)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       u32 val, addr;
+       int ret;
+
+       mutex_lock(&dev->phy_mutex);
+
+       /* confirm MII not busy */
+       ret = smsc75xx_phy_wait_not_busy(dev);
+       check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_write");
+
+       val = regval;
+       ret = smsc75xx_write_reg(dev, MII_DATA, val);
+       check_warn_goto_done(ret, "Error writing MII_DATA");
+
+       /* set the address, index & direction (write to PHY) */
+       phy_id &= dev->mii.phy_id_mask;
+       idx &= dev->mii.reg_num_mask;
+       addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
+               | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
+               | MII_ACCESS_WRITE;
+       ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
+       check_warn_goto_done(ret, "Error writing MII_ACCESS");
+
+       ret = smsc75xx_phy_wait_not_busy(dev);
+       check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+
+done:
+       mutex_unlock(&dev->phy_mutex);
+}
+
+static int smsc75xx_wait_eeprom(struct usbnet *dev)
+{
+       unsigned long start_time = jiffies;
+       u32 val;
+       int ret;
+
+       do {
+               ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
+               check_warn_return(ret, "Error reading E2P_CMD");
+
+               if (!(val & E2P_CMD_BUSY) || (val & E2P_CMD_TIMEOUT))
+                       break;
+               udelay(40);
+       } while (!time_after(jiffies, start_time + HZ));
+
+       if (val & (E2P_CMD_TIMEOUT | E2P_CMD_BUSY)) {
+               netdev_warn(dev->net, "EEPROM read operation timeout");
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
+{
+       unsigned long start_time = jiffies;
+       u32 val;
+       int ret;
+
+       do {
+               ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
+               check_warn_return(ret, "Error reading E2P_CMD");
+
+               if (!(val & E2P_CMD_BUSY))
+                       return 0;
+
+               udelay(40);
+       } while (!time_after(jiffies, start_time + HZ));
+
+       netdev_warn(dev->net, "EEPROM is busy");
+       return -EIO;
+}
+
+static int smsc75xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
+                               u8 *data)
+{
+       u32 val;
+       int i, ret;
+
+       BUG_ON(!dev);
+       BUG_ON(!data);
+
+       ret = smsc75xx_eeprom_confirm_not_busy(dev);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < length; i++) {
+               val = E2P_CMD_BUSY | E2P_CMD_READ | (offset & E2P_CMD_ADDR);
+               ret = smsc75xx_write_reg(dev, E2P_CMD, val);
+               check_warn_return(ret, "Error writing E2P_CMD");
+
+               ret = smsc75xx_wait_eeprom(dev);
+               if (ret < 0)
+                       return ret;
+
+               ret = smsc75xx_read_reg(dev, E2P_DATA, &val);
+               check_warn_return(ret, "Error reading E2P_DATA");
+
+               data[i] = val & 0xFF;
+               offset++;
+       }
+
+       return 0;
+}
+
+static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
+                                u8 *data)
+{
+       u32 val;
+       int i, ret;
+
+       BUG_ON(!dev);
+       BUG_ON(!data);
+
+       ret = smsc75xx_eeprom_confirm_not_busy(dev);
+       if (ret)
+               return ret;
+
+       /* Issue write/erase enable command */
+       val = E2P_CMD_BUSY | E2P_CMD_EWEN;
+       ret = smsc75xx_write_reg(dev, E2P_CMD, val);
+       check_warn_return(ret, "Error writing E2P_CMD");
+
+       ret = smsc75xx_wait_eeprom(dev);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < length; i++) {
+
+               /* Fill data register */
+               val = data[i];
+               ret = smsc75xx_write_reg(dev, E2P_DATA, val);
+               check_warn_return(ret, "Error writing E2P_DATA");
+
+               /* Send "write" command */
+               val = E2P_CMD_BUSY | E2P_CMD_WRITE | (offset & E2P_CMD_ADDR);
+               ret = smsc75xx_write_reg(dev, E2P_CMD, val);
+               check_warn_return(ret, "Error writing E2P_CMD");
+
+               ret = smsc75xx_wait_eeprom(dev);
+               if (ret < 0)
+                       return ret;
+
+               offset++;
+       }
+
+       return 0;
+}
+
+static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
+{
+       int i, ret;
+
+       for (i = 0; i < 100; i++) {
+               u32 dp_sel;
+               ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
+               check_warn_return(ret, "Error reading DP_SEL");
+
+               if (dp_sel & DP_SEL_DPRDY)
+                       return 0;
+
+               udelay(40);
+       }
+
+       netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out");
+
+       return -EIO;
+}
+
+static int smsc75xx_dataport_write(struct usbnet *dev, u32 ram_select, u32 addr,
+                                  u32 length, u32 *buf)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u32 dp_sel;
+       int i, ret;
+
+       mutex_lock(&pdata->dataport_mutex);
+
+       ret = smsc75xx_dataport_wait_not_busy(dev);
+       check_warn_goto_done(ret, "smsc75xx_dataport_write busy on entry");
+
+       ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
+       check_warn_goto_done(ret, "Error reading DP_SEL");
+
+       dp_sel &= ~DP_SEL_RSEL;
+       dp_sel |= ram_select;
+       ret = smsc75xx_write_reg(dev, DP_SEL, dp_sel);
+       check_warn_goto_done(ret, "Error writing DP_SEL");
+
+       for (i = 0; i < length; i++) {
+               ret = smsc75xx_write_reg(dev, DP_ADDR, addr + i);
+               check_warn_goto_done(ret, "Error writing DP_ADDR");
+
+               ret = smsc75xx_write_reg(dev, DP_DATA, buf[i]);
+               check_warn_goto_done(ret, "Error writing DP_DATA");
+
+               ret = smsc75xx_write_reg(dev, DP_CMD, DP_CMD_WRITE);
+               check_warn_goto_done(ret, "Error writing DP_CMD");
+
+               ret = smsc75xx_dataport_wait_not_busy(dev);
+               check_warn_goto_done(ret, "smsc75xx_dataport_write timeout");
+       }
+
+done:
+       mutex_unlock(&pdata->dataport_mutex);
+       return ret;
+}
+
+/* returns hash bit number for given MAC address */
+static u32 smsc75xx_hash(char addr[ETH_ALEN])
+{
+       return (ether_crc(ETH_ALEN, addr) >> 23) & 0x1ff;
+}
+
+static void smsc75xx_deferred_multicast_write(struct work_struct *param)
+{
+       struct smsc75xx_priv *pdata =
+               container_of(param, struct smsc75xx_priv, set_multicast);
+       struct usbnet *dev = pdata->dev;
+       int ret;
+
+       netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x",
+               pdata->rfe_ctl);
+
+       smsc75xx_dataport_write(dev, DP_SEL_VHF, DP_SEL_VHF_VLAN_LEN,
+               DP_SEL_VHF_HASH_LEN, pdata->multicast_hash_table);
+
+       ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+       check_warn(ret, "Error writing RFE_CRL");
+}
+
+static void smsc75xx_set_multicast(struct net_device *netdev)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
+
+       pdata->rfe_ctl &=
+               ~(RFE_CTL_AU | RFE_CTL_AM | RFE_CTL_DPF | RFE_CTL_MHF);
+       pdata->rfe_ctl |= RFE_CTL_AB;
+
+       for (i = 0; i < DP_SEL_VHF_HASH_LEN; i++)
+               pdata->multicast_hash_table[i] = 0;
+
+       if (dev->net->flags & IFF_PROMISC) {
+               netif_dbg(dev, drv, dev->net, "promiscuous mode enabled");
+               pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_AU;
+       } else if (dev->net->flags & IFF_ALLMULTI) {
+               netif_dbg(dev, drv, dev->net, "receive all multicast enabled");
+               pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_DPF;
+       } else if (!netdev_mc_empty(dev->net)) {
+               struct dev_mc_list *mc_list;
+
+               netif_dbg(dev, drv, dev->net, "receive multicast hash filter");
+
+               pdata->rfe_ctl |= RFE_CTL_MHF | RFE_CTL_DPF;
+
+               netdev_for_each_mc_addr(mc_list, netdev) {
+                       u32 bitnum = smsc75xx_hash(mc_list->dmi_addr);
+                       pdata->multicast_hash_table[bitnum / 32] |=
+                               (1 << (bitnum % 32));
+               }
+       } else {
+               netif_dbg(dev, drv, dev->net, "receive own packets only");
+               pdata->rfe_ctl |= RFE_CTL_DPF;
+       }
+
+       spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);
+
+       /* defer register writes to a sleepable context */
+       schedule_work(&pdata->set_multicast);
+}
+
+static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex,
+                                           u16 lcladv, u16 rmtadv)
+{
+       u32 flow = 0, fct_flow = 0;
+       int ret;
+
+       if (duplex == DUPLEX_FULL) {
+               u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+
+               if (cap & FLOW_CTRL_TX) {
+                       flow = (FLOW_TX_FCEN | 0xFFFF);
+                       /* set fct_flow thresholds to 20% and 80% */
+                       fct_flow = (8 << 8) | 32;
+               }
+
+               if (cap & FLOW_CTRL_RX)
+                       flow |= FLOW_RX_FCEN;
+
+               netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s",
+                       (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+                       (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+       } else {
+               netif_dbg(dev, link, dev->net, "half duplex");
+       }
+
+       ret = smsc75xx_write_reg(dev, FLOW, flow);
+       check_warn_return(ret, "Error writing FLOW");
+
+       ret = smsc75xx_write_reg(dev, FCT_FLOW, fct_flow);
+       check_warn_return(ret, "Error writing FCT_FLOW");
+
+       return 0;
+}
+
+static int smsc75xx_link_reset(struct usbnet *dev)
+{
+       struct mii_if_info *mii = &dev->mii;
+       struct ethtool_cmd ecmd;
+       u16 lcladv, rmtadv;
+       int ret;
+
+       /* clear interrupt status */
+       ret = smsc75xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
+       check_warn_return(ret, "Error reading PHY_INT_SRC");
+
+       ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
+       check_warn_return(ret, "Error writing INT_STS");
+
+       mii_check_media(mii, 1, 1);
+       mii_ethtool_gset(&dev->mii, &ecmd);
+       lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
+       rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
+
+       netif_dbg(dev, link, dev->net, "speed: %d duplex: %d lcladv: %04x"
+               " rmtadv: %04x", ecmd.speed, ecmd.duplex, lcladv, rmtadv);
+
+       return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
+}
+
+static void smsc75xx_status(struct usbnet *dev, struct urb *urb)
+{
+       u32 intdata;
+
+       if (urb->actual_length != 4) {
+               netdev_warn(dev->net,
+                       "unexpected urb length %d", urb->actual_length);
+               return;
+       }
+
+       memcpy(&intdata, urb->transfer_buffer, 4);
+       le32_to_cpus(&intdata);
+
+       netif_dbg(dev, link, dev->net, "intdata: 0x%08X", intdata);
+
+       if (intdata & INT_ENP_PHY_INT)
+               usbnet_defer_kevent(dev, EVENT_LINK_RESET);
+       else
+               netdev_warn(dev->net,
+                       "unexpected interrupt, intdata=0x%08X", intdata);
+}
+
+/* Enable or disable Rx checksum offload engine */
+static int smsc75xx_set_rx_csum_offload(struct usbnet *dev)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&pdata->rfe_ctl_lock, flags);
+
+       if (pdata->use_rx_csum)
+               pdata->rfe_ctl |= RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM;
+       else
+               pdata->rfe_ctl &= ~(RFE_CTL_TCPUDP_CKM | RFE_CTL_IP_CKM);
+
+       spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);
+
+       ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+       check_warn_return(ret, "Error writing RFE_CTL");
+
+       return 0;
+}
+
+static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net)
+{
+       return MAX_EEPROM_SIZE;
+}
+
+static int smsc75xx_ethtool_get_eeprom(struct net_device *netdev,
+                                      struct ethtool_eeprom *ee, u8 *data)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+
+       ee->magic = LAN75XX_EEPROM_MAGIC;
+
+       return smsc75xx_read_eeprom(dev, ee->offset, ee->len, data);
+}
+
+static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev,
+                                      struct ethtool_eeprom *ee, u8 *data)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+
+       if (ee->magic != LAN75XX_EEPROM_MAGIC) {
+               netdev_warn(dev->net,
+                       "EEPROM: magic value mismatch: 0x%x", ee->magic);
+               return -EINVAL;
+       }
+
+       return smsc75xx_write_eeprom(dev, ee->offset, ee->len, data);
+}
+
+static u32 smsc75xx_ethtool_get_rx_csum(struct net_device *netdev)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+
+       return pdata->use_rx_csum;
+}
+
+static int smsc75xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+
+       pdata->use_rx_csum = !!val;
+
+       return smsc75xx_set_rx_csum_offload(dev);
+}
+
+static int smsc75xx_ethtool_set_tso(struct net_device *netdev, u32 data)
+{
+       if (data)
+               netdev->features |= NETIF_F_TSO | NETIF_F_TSO6;
+       else
+               netdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
+
+       return 0;
+}
+
+static const struct ethtool_ops smsc75xx_ethtool_ops = {
+       .get_link       = usbnet_get_link,
+       .nway_reset     = usbnet_nway_reset,
+       .get_drvinfo    = usbnet_get_drvinfo,
+       .get_msglevel   = usbnet_get_msglevel,
+       .set_msglevel   = usbnet_set_msglevel,
+       .get_settings   = usbnet_get_settings,
+       .set_settings   = usbnet_set_settings,
+       .get_eeprom_len = smsc75xx_ethtool_get_eeprom_len,
+       .get_eeprom     = smsc75xx_ethtool_get_eeprom,
+       .set_eeprom     = smsc75xx_ethtool_set_eeprom,
+       .get_tx_csum    = ethtool_op_get_tx_csum,
+       .set_tx_csum    = ethtool_op_set_tx_hw_csum,
+       .get_rx_csum    = smsc75xx_ethtool_get_rx_csum,
+       .set_rx_csum    = smsc75xx_ethtool_set_rx_csum,
+       .get_tso        = ethtool_op_get_tso,
+       .set_tso        = smsc75xx_ethtool_set_tso,
+};
+
+static int smsc75xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+
+       if (!netif_running(netdev))
+               return -EINVAL;
+
+       return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL);
+}
+
+static void smsc75xx_init_mac_address(struct usbnet *dev)
+{
+       /* try reading mac address from EEPROM */
+       if (smsc75xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
+                       dev->net->dev_addr) == 0) {
+               if (is_valid_ether_addr(dev->net->dev_addr)) {
+                       /* eeprom values are valid so use them */
+                       netif_dbg(dev, ifup, dev->net,
+                               "MAC address read from EEPROM");
+                       return;
+               }
+       }
+
+       /* no eeprom, or eeprom values are invalid. generate random MAC */
+       random_ether_addr(dev->net->dev_addr);
+       netif_dbg(dev, ifup, dev->net, "MAC address set to random_ether_addr");
+}
+
+static int smsc75xx_set_mac_address(struct usbnet *dev)
+{
+       u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 |
+               dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24;
+       u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
+
+       int ret = smsc75xx_write_reg(dev, RX_ADDRH, addr_hi);
+       check_warn_return(ret, "Failed to write RX_ADDRH: %d", ret);
+
+       ret = smsc75xx_write_reg(dev, RX_ADDRL, addr_lo);
+       check_warn_return(ret, "Failed to write RX_ADDRL: %d", ret);
+
+       addr_hi |= ADDR_FILTX_FB_VALID;
+       ret = smsc75xx_write_reg(dev, ADDR_FILTX, addr_hi);
+       check_warn_return(ret, "Failed to write ADDR_FILTX: %d", ret);
+
+       ret = smsc75xx_write_reg(dev, ADDR_FILTX + 4, addr_lo);
+       check_warn_return(ret, "Failed to write ADDR_FILTX+4: %d", ret);
+
+       return 0;
+}
+
+static int smsc75xx_phy_initialize(struct usbnet *dev)
+{
+       int bmcr, timeout = 0;
+
+       /* Initialize MII structure */
+       dev->mii.dev = dev->net;
+       dev->mii.mdio_read = smsc75xx_mdio_read;
+       dev->mii.mdio_write = smsc75xx_mdio_write;
+       dev->mii.phy_id_mask = 0x1f;
+       dev->mii.reg_num_mask = 0x1f;
+       dev->mii.phy_id = SMSC75XX_INTERNAL_PHY_ID;
+
+       /* reset phy and wait for reset to complete */
+       smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+
+       do {
+               msleep(10);
+               bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
+               check_warn_return(bmcr, "Error reading MII_BMCR");
+               timeout++;
+       } while ((bmcr & MII_BMCR) && (timeout < 100));
+
+       if (timeout >= 100) {
+               netdev_warn(dev->net, "timeout on PHY Reset");
+               return -EIO;
+       }
+
+       smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+               ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
+               ADVERTISE_PAUSE_ASYM);
+
+       /* read to clear */
+       smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
+       check_warn_return(bmcr, "Error reading PHY_INT_SRC");
+
+       smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
+               PHY_INT_MASK_DEFAULT);
+       mii_nway_restart(&dev->mii);
+
+       netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+       return 0;
+}
+
+static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
+{
+       int ret = 0;
+       u32 buf;
+       bool rxenabled;
+
+       ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
+       check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+
+       rxenabled = ((buf & MAC_RX_RXEN) != 0);
+
+       if (rxenabled) {
+               buf &= ~MAC_RX_RXEN;
+               ret = smsc75xx_write_reg(dev, MAC_RX, buf);
+               check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+       }
+
+       /* add 4 to size for FCS */
+       buf &= ~MAC_RX_MAX_SIZE;
+       buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT) & MAC_RX_MAX_SIZE);
+
+       ret = smsc75xx_write_reg(dev, MAC_RX, buf);
+       check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+
+       if (rxenabled) {
+               buf |= MAC_RX_RXEN;
+               ret = smsc75xx_write_reg(dev, MAC_RX, buf);
+               check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+       }
+
+       return 0;
+}
+
+static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
+{
+       struct usbnet *dev = netdev_priv(netdev);
+
+       int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
+       check_warn_return(ret, "Failed to set mac rx frame length");
+
+       return usbnet_change_mtu(netdev, new_mtu);
+}
+
+static int smsc75xx_reset(struct usbnet *dev)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u32 buf;
+       int ret = 0, timeout;
+
+       netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset");
+
+       ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
+       check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+
+       buf |= HW_CFG_LRST;
+
+       ret = smsc75xx_write_reg(dev, HW_CFG, buf);
+       check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+
+       timeout = 0;
+       do {
+               msleep(10);
+               ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
+               check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+               timeout++;
+       } while ((buf & HW_CFG_LRST) && (timeout < 100));
+
+       if (timeout >= 100) {
+               netdev_warn(dev->net, "timeout on completion of Lite Reset");
+               return -EIO;
+       }
+
+       netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY");
+
+       ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
+       check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+
+       buf |= PMT_CTL_PHY_RST;
+
+       ret = smsc75xx_write_reg(dev, PMT_CTL, buf);
+       check_warn_return(ret, "Failed to write PMT_CTL: %d", ret);
+
+       timeout = 0;
+       do {
+               msleep(10);
+               ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
+               check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+               timeout++;
+       } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100));
+
+       if (timeout >= 100) {
+               netdev_warn(dev->net, "timeout waiting for PHY Reset");
+               return -EIO;
+       }
+
+       netif_dbg(dev, ifup, dev->net, "PHY reset complete");
+
+       smsc75xx_init_mac_address(dev);
+
+       ret = smsc75xx_set_mac_address(dev);
+       check_warn_return(ret, "Failed to set mac address");
+
+       netif_dbg(dev, ifup, dev->net, "MAC Address: %pM", dev->net->dev_addr);
+
+       ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
+       check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x", buf);
+
+       buf |= HW_CFG_BIR;
+
+       ret = smsc75xx_write_reg(dev, HW_CFG, buf);
+       check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+
+       ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
+       check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after "
+                       "writing HW_CFG_BIR: 0x%08x", buf);
+
+       if (!turbo_mode) {
+               buf = 0;
+               dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
+       } else if (dev->udev->speed == USB_SPEED_HIGH) {
+               buf = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
+               dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
+       } else {
+               buf = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
+               dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
+       }
+
+       netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld",
+               (ulong)dev->rx_urb_size);
+
+       ret = smsc75xx_write_reg(dev, BURST_CAP, buf);
+       check_warn_return(ret, "Failed to write BURST_CAP: %d", ret);
+
+       ret = smsc75xx_read_reg(dev, BURST_CAP, &buf);
+       check_warn_return(ret, "Failed to read BURST_CAP: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net,
+               "Read Value from BURST_CAP after writing: 0x%08x", buf);
+
+       ret = smsc75xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
+       check_warn_return(ret, "Failed to write BULK_IN_DLY: %d", ret);
+
+       ret = smsc75xx_read_reg(dev, BULK_IN_DLY, &buf);
+       check_warn_return(ret, "Failed to read BULK_IN_DLY: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net,
+               "Read Value from BULK_IN_DLY after writing: 0x%08x", buf);
+
+       if (turbo_mode) {
+               ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
+               check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+
+               netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+
+               buf |= (HW_CFG_MEF | HW_CFG_BCE);
+
+               ret = smsc75xx_write_reg(dev, HW_CFG, buf);
+               check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+
+               ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
+               check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+
+               netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+       }
+
+       /* set FIFO sizes */
+       buf = (MAX_RX_FIFO_SIZE - 512) / 512;
+       ret = smsc75xx_write_reg(dev, FCT_RX_FIFO_END, buf);
+       check_warn_return(ret, "Failed to write FCT_RX_FIFO_END: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x", buf);
+
+       buf = (MAX_TX_FIFO_SIZE - 512) / 512;
+       ret = smsc75xx_write_reg(dev, FCT_TX_FIFO_END, buf);
+       check_warn_return(ret, "Failed to write FCT_TX_FIFO_END: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x", buf);
+
+       ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
+       check_warn_return(ret, "Failed to write INT_STS: %d", ret);
+
+       ret = smsc75xx_read_reg(dev, ID_REV, &buf);
+       check_warn_return(ret, "Failed to read ID_REV: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x", buf);
+
+       /* Configure GPIO pins as LED outputs */
+       ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf);
+       check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret);
+
+       buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL);
+       buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL;
+
+       ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf);
+       check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret);
+
+       ret = smsc75xx_write_reg(dev, FLOW, 0);
+       check_warn_return(ret, "Failed to write FLOW: %d", ret);
+
+       ret = smsc75xx_write_reg(dev, FCT_FLOW, 0);
+       check_warn_return(ret, "Failed to write FCT_FLOW: %d", ret);
+
+       /* Don't need rfe_ctl_lock during initialisation */
+       ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
+       check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+
+       pdata->rfe_ctl |= RFE_CTL_AB | RFE_CTL_DPF;
+
+       ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+       check_warn_return(ret, "Failed to write RFE_CTL: %d", ret);
+
+       ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
+       check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x", pdata->rfe_ctl);
+
+       /* Enable or disable checksum offload engines */
+       ethtool_op_set_tx_hw_csum(dev->net, DEFAULT_TX_CSUM_ENABLE);
+       ret = smsc75xx_set_rx_csum_offload(dev);
+       check_warn_return(ret, "Failed to set rx csum offload: %d", ret);
+
+       smsc75xx_ethtool_set_tso(dev->net, DEFAULT_TSO_ENABLE);
+
+       smsc75xx_set_multicast(dev->net);
+
+       ret = smsc75xx_phy_initialize(dev);
+       check_warn_return(ret, "Failed to initialize PHY: %d", ret);
+
+       ret = smsc75xx_read_reg(dev, INT_EP_CTL, &buf);
+       check_warn_return(ret, "Failed to read INT_EP_CTL: %d", ret);
+
+       /* enable PHY interrupts */
+       buf |= INT_ENP_PHY_INT;
+
+       ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf);
+       check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret);
+
+       ret = smsc75xx_read_reg(dev, MAC_TX, &buf);
+       check_warn_return(ret, "Failed to read MAC_TX: %d", ret);
+
+       buf |= MAC_TX_TXEN;
+
+       ret = smsc75xx_write_reg(dev, MAC_TX, buf);
+       check_warn_return(ret, "Failed to write MAC_TX: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x", buf);
+
+       ret = smsc75xx_read_reg(dev, FCT_TX_CTL, &buf);
+       check_warn_return(ret, "Failed to read FCT_TX_CTL: %d", ret);
+
+       buf |= FCT_TX_CTL_EN;
+
+       ret = smsc75xx_write_reg(dev, FCT_TX_CTL, buf);
+       check_warn_return(ret, "Failed to write FCT_TX_CTL: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x", buf);
+
+       ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
+       check_warn_return(ret, "Failed to set max rx frame length");
+
+       ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
+       check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+
+       buf |= MAC_RX_RXEN;
+
+       ret = smsc75xx_write_reg(dev, MAC_RX, buf);
+       check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x", buf);
+
+       ret = smsc75xx_read_reg(dev, FCT_RX_CTL, &buf);
+       check_warn_return(ret, "Failed to read FCT_RX_CTL: %d", ret);
+
+       buf |= FCT_RX_CTL_EN;
+
+       ret = smsc75xx_write_reg(dev, FCT_RX_CTL, buf);
+       check_warn_return(ret, "Failed to write FCT_RX_CTL: %d", ret);
+
+       netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x", buf);
+
+       netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0");
+       return 0;
+}
+
+static const struct net_device_ops smsc75xx_netdev_ops = {
+       .ndo_open               = usbnet_open,
+       .ndo_stop               = usbnet_stop,
+       .ndo_start_xmit         = usbnet_start_xmit,
+       .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_change_mtu         = smsc75xx_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_do_ioctl           = smsc75xx_ioctl,
+       .ndo_set_multicast_list = smsc75xx_set_multicast,
+};
+
+static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct smsc75xx_priv *pdata = NULL;
+       int ret;
+
+       printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
+
+       ret = usbnet_get_endpoints(dev, intf);
+       check_warn_return(ret, "usbnet_get_endpoints failed: %d", ret);
+
+       dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc75xx_priv),
+               GFP_KERNEL);
+
+       pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       if (!pdata) {
+               netdev_warn(dev->net, "Unable to allocate smsc75xx_priv");
+               return -ENOMEM;
+       }
+
+       pdata->dev = dev;
+
+       spin_lock_init(&pdata->rfe_ctl_lock);
+       mutex_init(&pdata->dataport_mutex);
+
+       INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write);
+
+       pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE;
+
+       /* We have to advertise SG otherwise TSO cannot be enabled */
+       dev->net->features |= NETIF_F_SG;
+
+       /* Init all registers */
+       ret = smsc75xx_reset(dev);
+
+       dev->net->netdev_ops = &smsc75xx_netdev_ops;
+       dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
+       dev->net->flags |= IFF_MULTICAST;
+       dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
+       return 0;
+}
+
+static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       if (pdata) {
+               netif_dbg(dev, ifdown, dev->net, "free pdata");
+               kfree(pdata);
+               pdata = NULL;
+               dev->data[0] = 0;
+       }
+}
+
+static void smsc75xx_rx_csum_offload(struct sk_buff *skb, u32 rx_cmd_a,
+                                    u32 rx_cmd_b)
+{
+       if (unlikely(rx_cmd_a & RX_CMD_A_LCSM)) {
+               skb->ip_summed = CHECKSUM_NONE;
+       } else {
+               skb->csum = ntohs((u16)(rx_cmd_b >> RX_CMD_B_CSUM_SHIFT));
+               skb->ip_summed = CHECKSUM_COMPLETE;
+       }
+}
+
+static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+
+       while (skb->len > 0) {
+               u32 rx_cmd_a, rx_cmd_b, align_count, size;
+               struct sk_buff *ax_skb;
+               unsigned char *packet;
+
+               memcpy(&rx_cmd_a, skb->data, sizeof(rx_cmd_a));
+               le32_to_cpus(&rx_cmd_a);
+               skb_pull(skb, 4);
+
+               memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b));
+               le32_to_cpus(&rx_cmd_b);
+               skb_pull(skb, 4 + NET_IP_ALIGN);
+
+               packet = skb->data;
+
+               /* get the packet length */
+               size = (rx_cmd_a & RX_CMD_A_LEN) - NET_IP_ALIGN;
+               align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
+
+               if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                               "Error rx_cmd_a=0x%08x", rx_cmd_a);
+                       dev->net->stats.rx_errors++;
+                       dev->net->stats.rx_dropped++;
+
+                       if (rx_cmd_a & RX_CMD_A_FCS)
+                               dev->net->stats.rx_crc_errors++;
+                       else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT))
+                               dev->net->stats.rx_frame_errors++;
+               } else {
+                       /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
+                       if (unlikely(size > (ETH_FRAME_LEN + 12))) {
+                               netif_dbg(dev, rx_err, dev->net,
+                                       "size err rx_cmd_a=0x%08x", rx_cmd_a);
+                               return 0;
+                       }
+
+                       /* last frame in this batch */
+                       if (skb->len == size) {
+                               if (pdata->use_rx_csum)
+                                       smsc75xx_rx_csum_offload(skb, rx_cmd_a,
+                                               rx_cmd_b);
+                               else
+                                       skb->ip_summed = CHECKSUM_NONE;
+
+                               skb_trim(skb, skb->len - 4); /* remove fcs */
+                               skb->truesize = size + sizeof(struct sk_buff);
+
+                               return 1;
+                       }
+
+                       ax_skb = skb_clone(skb, GFP_ATOMIC);
+                       if (unlikely(!ax_skb)) {
+                               netdev_warn(dev->net, "Error allocating skb");
+                               return 0;
+                       }
+
+                       ax_skb->len = size;
+                       ax_skb->data = packet;
+                       skb_set_tail_pointer(ax_skb, size);
+
+                       if (pdata->use_rx_csum)
+                               smsc75xx_rx_csum_offload(ax_skb, rx_cmd_a,
+                                       rx_cmd_b);
+                       else
+                               ax_skb->ip_summed = CHECKSUM_NONE;
+
+                       skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
+                       ax_skb->truesize = size + sizeof(struct sk_buff);
+
+                       usbnet_skb_return(dev, ax_skb);
+               }
+
+               skb_pull(skb, size);
+
+               /* padding bytes before the next frame starts */
+               if (skb->len)
+                       skb_pull(skb, align_count);
+       }
+
+       if (unlikely(skb->len < 0)) {
+               netdev_warn(dev->net, "invalid rx length<0 %d", skb->len);
+               return 0;
+       }
+
+       return 1;
+}
+
+static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev,
+                                        struct sk_buff *skb, gfp_t flags)
+{
+       u32 tx_cmd_a, tx_cmd_b;
+
+       skb_linearize(skb);
+
+       if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) {
+               struct sk_buff *skb2 =
+                       skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags);
+               dev_kfree_skb_any(skb);
+               skb = skb2;
+               if (!skb)
+                       return NULL;
+       }
+
+       tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN) | TX_CMD_A_FCS;
+
+       if (skb->ip_summed == CHECKSUM_PARTIAL)
+               tx_cmd_a |= TX_CMD_A_IPE | TX_CMD_A_TPE;
+
+       if (skb_is_gso(skb)) {
+               u16 mss = max(skb_shinfo(skb)->gso_size, TX_MSS_MIN);
+               tx_cmd_b = (mss << TX_CMD_B_MSS_SHIFT) & TX_CMD_B_MSS;
+
+               tx_cmd_a |= TX_CMD_A_LSO;
+       } else {
+               tx_cmd_b = 0;
+       }
+
+       skb_push(skb, 4);
+       cpu_to_le32s(&tx_cmd_b);
+       memcpy(skb->data, &tx_cmd_b, 4);
+
+       skb_push(skb, 4);
+       cpu_to_le32s(&tx_cmd_a);
+       memcpy(skb->data, &tx_cmd_a, 4);
+
+       return skb;
+}
+
+static const struct driver_info smsc75xx_info = {
+       .description    = "smsc75xx USB 2.0 Gigabit Ethernet",
+       .bind           = smsc75xx_bind,
+       .unbind         = smsc75xx_unbind,
+       .link_reset     = smsc75xx_link_reset,
+       .reset          = smsc75xx_reset,
+       .rx_fixup       = smsc75xx_rx_fixup,
+       .tx_fixup       = smsc75xx_tx_fixup,
+       .status         = smsc75xx_status,
+       .flags          = FLAG_ETHER | FLAG_SEND_ZLP,
+};
+
+static const struct usb_device_id products[] = {
+       {
+               /* SMSC7500 USB Gigabit Ethernet Device */
+               USB_DEVICE(USB_VENDOR_ID_SMSC, USB_PRODUCT_ID_LAN7500),
+               .driver_info = (unsigned long) &smsc75xx_info,
+       },
+       {
+               /* SMSC7500 USB Gigabit Ethernet Device */
+               USB_DEVICE(USB_VENDOR_ID_SMSC, USB_PRODUCT_ID_LAN7505),
+               .driver_info = (unsigned long) &smsc75xx_info,
+       },
+       { },            /* END */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver smsc75xx_driver = {
+       .name           = SMSC_CHIPNAME,
+       .id_table       = products,
+       .probe          = usbnet_probe,
+       .suspend        = usbnet_suspend,
+       .resume         = usbnet_resume,
+       .disconnect     = usbnet_disconnect,
+};
+
+static int __init smsc75xx_init(void)
+{
+       return usb_register(&smsc75xx_driver);
+}
+module_init(smsc75xx_init);
+
+static void __exit smsc75xx_exit(void)
+{
+       usb_deregister(&smsc75xx_driver);
+}
+module_exit(smsc75xx_exit);
+
+MODULE_AUTHOR("Nancy Lin");
+MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>");
+MODULE_DESCRIPTION("SMSC75XX USB 2.0 Gigabit Ethernet Devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/usb/smsc75xx.h b/drivers/net/usb/smsc75xx.h
new file mode 100644 (file)
index 0000000..16e98c7
--- /dev/null
@@ -0,0 +1,421 @@
+ /***************************************************************************
+ *
+ * Copyright (C) 2007-2010 SMSC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *****************************************************************************/
+
+#ifndef _SMSC75XX_H
+#define _SMSC75XX_H
+
+/* Tx command words */
+#define TX_CMD_A_LSO                   (0x08000000)
+#define TX_CMD_A_IPE                   (0x04000000)
+#define TX_CMD_A_TPE                   (0x02000000)
+#define TX_CMD_A_IVTG                  (0x01000000)
+#define TX_CMD_A_RVTG                  (0x00800000)
+#define TX_CMD_A_FCS                   (0x00400000)
+#define TX_CMD_A_LEN                   (0x000FFFFF)
+
+#define TX_CMD_B_MSS                   (0x3FFF0000)
+#define TX_CMD_B_MSS_SHIFT             (16)
+#define TX_MSS_MIN                     ((u16)8)
+#define TX_CMD_B_VTAG                  (0x0000FFFF)
+
+/* Rx command words */
+#define RX_CMD_A_ICE                   (0x80000000)
+#define RX_CMD_A_TCE                   (0x40000000)
+#define RX_CMD_A_IPV                   (0x20000000)
+#define RX_CMD_A_PID                   (0x18000000)
+#define RX_CMD_A_PID_NIP               (0x00000000)
+#define RX_CMD_A_PID_TCP               (0x08000000)
+#define RX_CMD_A_PID_UDP               (0x10000000)
+#define RX_CMD_A_PID_PP                        (0x18000000)
+#define RX_CMD_A_PFF                   (0x04000000)
+#define RX_CMD_A_BAM                   (0x02000000)
+#define RX_CMD_A_MAM                   (0x01000000)
+#define RX_CMD_A_FVTG                  (0x00800000)
+#define RX_CMD_A_RED                   (0x00400000)
+#define RX_CMD_A_RWT                   (0x00200000)
+#define RX_CMD_A_RUNT                  (0x00100000)
+#define RX_CMD_A_LONG                  (0x00080000)
+#define RX_CMD_A_RXE                   (0x00040000)
+#define RX_CMD_A_DRB                   (0x00020000)
+#define RX_CMD_A_FCS                   (0x00010000)
+#define RX_CMD_A_UAM                   (0x00008000)
+#define RX_CMD_A_LCSM                  (0x00004000)
+#define RX_CMD_A_LEN                   (0x00003FFF)
+
+#define RX_CMD_B_CSUM                  (0xFFFF0000)
+#define RX_CMD_B_CSUM_SHIFT            (16)
+#define RX_CMD_B_VTAG                  (0x0000FFFF)
+
+/* SCSRs */
+#define ID_REV                         (0x0000)
+
+#define FPGA_REV                       (0x0004)
+
+#define BOND_CTL                       (0x0008)
+
+#define INT_STS                                (0x000C)
+#define INT_STS_RDFO_INT               (0x00400000)
+#define INT_STS_TXE_INT                        (0x00200000)
+#define INT_STS_MACRTO_INT             (0x00100000)
+#define INT_STS_TX_DIS_INT             (0x00080000)
+#define INT_STS_RX_DIS_INT             (0x00040000)
+#define INT_STS_PHY_INT_               (0x00020000)
+#define INT_STS_MAC_ERR_INT            (0x00008000)
+#define INT_STS_TDFU                   (0x00004000)
+#define INT_STS_TDFO                   (0x00002000)
+#define INT_STS_GPIOS                  (0x00000FFF)
+#define INT_STS_CLEAR_ALL              (0xFFFFFFFF)
+
+#define HW_CFG                         (0x0010)
+#define HW_CFG_SMDET_STS               (0x00008000)
+#define HW_CFG_SMDET_EN                        (0x00004000)
+#define HW_CFG_EEM                     (0x00002000)
+#define HW_CFG_RST_PROTECT             (0x00001000)
+#define HW_CFG_PORT_SWAP               (0x00000800)
+#define HW_CFG_PHY_BOOST               (0x00000600)
+#define HW_CFG_PHY_BOOST_NORMAL                (0x00000000)
+#define HW_CFG_PHY_BOOST_4             (0x00002000)
+#define HW_CFG_PHY_BOOST_8             (0x00004000)
+#define HW_CFG_PHY_BOOST_12            (0x00006000)
+#define HW_CFG_LEDB                    (0x00000100)
+#define HW_CFG_BIR                     (0x00000080)
+#define HW_CFG_SBP                     (0x00000040)
+#define HW_CFG_IME                     (0x00000020)
+#define HW_CFG_MEF                     (0x00000010)
+#define HW_CFG_ETC                     (0x00000008)
+#define HW_CFG_BCE                     (0x00000004)
+#define HW_CFG_LRST                    (0x00000002)
+#define HW_CFG_SRST                    (0x00000001)
+
+#define PMT_CTL                                (0x0014)
+#define PMT_CTL_PHY_PWRUP              (0x00000400)
+#define PMT_CTL_RES_CLR_WKP_EN         (0x00000100)
+#define PMT_CTL_DEV_RDY                        (0x00000080)
+#define PMT_CTL_SUS_MODE               (0x00000060)
+#define PMT_CTL_SUS_MODE_0             (0x00000000)
+#define PMT_CTL_SUS_MODE_1             (0x00000020)
+#define PMT_CTL_SUS_MODE_2             (0x00000040)
+#define PMT_CTL_SUS_MODE_3             (0x00000060)
+#define PMT_CTL_PHY_RST                        (0x00000010)
+#define PMT_CTL_WOL_EN                 (0x00000008)
+#define PMT_CTL_ED_EN                  (0x00000004)
+#define PMT_CTL_WUPS                   (0x00000003)
+#define PMT_CTL_WUPS_NO                        (0x00000000)
+#define PMT_CTL_WUPS_ED                        (0x00000001)
+#define PMT_CTL_WUPS_WOL               (0x00000002)
+#define PMT_CTL_WUPS_MULTI             (0x00000003)
+
+#define LED_GPIO_CFG                   (0x0018)
+#define LED_GPIO_CFG_LED2_FUN_SEL      (0x80000000)
+#define LED_GPIO_CFG_LED10_FUN_SEL     (0x40000000)
+#define LED_GPIO_CFG_LEDGPIO_EN                (0x0000F000)
+#define LED_GPIO_CFG_LEDGPIO_EN_0      (0x00001000)
+#define LED_GPIO_CFG_LEDGPIO_EN_1      (0x00002000)
+#define LED_GPIO_CFG_LEDGPIO_EN_2      (0x00004000)
+#define LED_GPIO_CFG_LEDGPIO_EN_3      (0x00008000)
+#define LED_GPIO_CFG_GPBUF             (0x00000F00)
+#define LED_GPIO_CFG_GPBUF_0           (0x00000100)
+#define LED_GPIO_CFG_GPBUF_1           (0x00000200)
+#define LED_GPIO_CFG_GPBUF_2           (0x00000400)
+#define LED_GPIO_CFG_GPBUF_3           (0x00000800)
+#define LED_GPIO_CFG_GPDIR             (0x000000F0)
+#define LED_GPIO_CFG_GPDIR_0           (0x00000010)
+#define LED_GPIO_CFG_GPDIR_1           (0x00000020)
+#define LED_GPIO_CFG_GPDIR_2           (0x00000040)
+#define LED_GPIO_CFG_GPDIR_3           (0x00000080)
+#define LED_GPIO_CFG_GPDATA            (0x0000000F)
+#define LED_GPIO_CFG_GPDATA_0          (0x00000001)
+#define LED_GPIO_CFG_GPDATA_1          (0x00000002)
+#define LED_GPIO_CFG_GPDATA_2          (0x00000004)
+#define LED_GPIO_CFG_GPDATA_3          (0x00000008)
+
+#define GPIO_CFG                       (0x001C)
+#define GPIO_CFG_SHIFT                 (24)
+#define GPIO_CFG_GPEN                  (0xFF000000)
+#define GPIO_CFG_GPBUF                 (0x00FF0000)
+#define GPIO_CFG_GPDIR                 (0x0000FF00)
+#define GPIO_CFG_GPDATA                        (0x000000FF)
+
+#define GPIO_WAKE                      (0x0020)
+#define GPIO_WAKE_PHY_LINKUP_EN                (0x80000000)
+#define GPIO_WAKE_POL                  (0x0FFF0000)
+#define GPIO_WAKE_POL_SHIFT            (16)
+#define GPIO_WAKE_WK                   (0x00000FFF)
+
+#define DP_SEL                         (0x0024)
+#define DP_SEL_DPRDY                   (0x80000000)
+#define DP_SEL_RSEL                    (0x0000000F)
+#define DP_SEL_URX                     (0x00000000)
+#define DP_SEL_VHF                     (0x00000001)
+#define DP_SEL_VHF_HASH_LEN            (16)
+#define DP_SEL_VHF_VLAN_LEN            (128)
+#define DP_SEL_LSO_HEAD                        (0x00000002)
+#define DP_SEL_FCT_RX                  (0x00000003)
+#define DP_SEL_FCT_TX                  (0x00000004)
+#define DP_SEL_DESCRIPTOR              (0x00000005)
+#define DP_SEL_WOL                     (0x00000006)
+
+#define DP_CMD                         (0x0028)
+#define DP_CMD_WRITE                   (0x01)
+#define DP_CMD_READ                    (0x00)
+
+#define DP_ADDR                                (0x002C)
+
+#define DP_DATA                                (0x0030)
+
+#define BURST_CAP                      (0x0034)
+#define BURST_CAP_MASK                 (0x0000000F)
+
+#define INT_EP_CTL                     (0x0038)
+#define INT_EP_CTL_INTEP_ON            (0x80000000)
+#define INT_EP_CTL_RDFO_EN             (0x00400000)
+#define INT_EP_CTL_TXE_EN              (0x00200000)
+#define INT_EP_CTL_MACROTO_EN          (0x00100000)
+#define INT_EP_CTL_TX_DIS_EN           (0x00080000)
+#define INT_EP_CTL_RX_DIS_EN           (0x00040000)
+#define INT_EP_CTL_PHY_EN_             (0x00020000)
+#define INT_EP_CTL_MAC_ERR_EN          (0x00008000)
+#define INT_EP_CTL_TDFU_EN             (0x00004000)
+#define INT_EP_CTL_TDFO_EN             (0x00002000)
+#define INT_EP_CTL_RX_FIFO_EN          (0x00001000)
+#define INT_EP_CTL_GPIOX_EN            (0x00000FFF)
+
+#define BULK_IN_DLY                    (0x003C)
+#define BULK_IN_DLY_MASK               (0xFFFF)
+
+#define E2P_CMD                                (0x0040)
+#define E2P_CMD_BUSY                   (0x80000000)
+#define E2P_CMD_MASK                   (0x70000000)
+#define E2P_CMD_READ                   (0x00000000)
+#define E2P_CMD_EWDS                   (0x10000000)
+#define E2P_CMD_EWEN                   (0x20000000)
+#define E2P_CMD_WRITE                  (0x30000000)
+#define E2P_CMD_WRAL                   (0x40000000)
+#define E2P_CMD_ERASE                  (0x50000000)
+#define E2P_CMD_ERAL                   (0x60000000)
+#define E2P_CMD_RELOAD                 (0x70000000)
+#define E2P_CMD_TIMEOUT                        (0x00000400)
+#define E2P_CMD_LOADED                 (0x00000200)
+#define E2P_CMD_ADDR                   (0x000001FF)
+
+#define MAX_EEPROM_SIZE                        (512)
+
+#define E2P_DATA                       (0x0044)
+#define E2P_DATA_MASK_                 (0x000000FF)
+
+#define RFE_CTL                                (0x0060)
+#define RFE_CTL_TCPUDP_CKM             (0x00001000)
+#define RFE_CTL_IP_CKM                 (0x00000800)
+#define RFE_CTL_AB                     (0x00000400)
+#define RFE_CTL_AM                     (0x00000200)
+#define RFE_CTL_AU                     (0x00000100)
+#define RFE_CTL_VS                     (0x00000080)
+#define RFE_CTL_UF                     (0x00000040)
+#define RFE_CTL_VF                     (0x00000020)
+#define RFE_CTL_SPF                    (0x00000010)
+#define RFE_CTL_MHF                    (0x00000008)
+#define RFE_CTL_DHF                    (0x00000004)
+#define RFE_CTL_DPF                    (0x00000002)
+#define RFE_CTL_RST_RF                 (0x00000001)
+
+#define VLAN_TYPE                      (0x0064)
+#define VLAN_TYPE_MASK                 (0x0000FFFF)
+
+#define FCT_RX_CTL                     (0x0090)
+#define FCT_RX_CTL_EN                  (0x80000000)
+#define FCT_RX_CTL_RST                 (0x40000000)
+#define FCT_RX_CTL_SBF                 (0x02000000)
+#define FCT_RX_CTL_OVERFLOW            (0x01000000)
+#define FCT_RX_CTL_FRM_DROP            (0x00800000)
+#define FCT_RX_CTL_RX_NOT_EMPTY                (0x00400000)
+#define FCT_RX_CTL_RX_EMPTY            (0x00200000)
+#define FCT_RX_CTL_RX_DISABLED         (0x00100000)
+#define FCT_RX_CTL_RXUSED              (0x0000FFFF)
+
+#define FCT_TX_CTL                     (0x0094)
+#define FCT_TX_CTL_EN                  (0x80000000)
+#define FCT_TX_CTL_RST                 (0x40000000)
+#define FCT_TX_CTL_TX_NOT_EMPTY                (0x00400000)
+#define FCT_TX_CTL_TX_EMPTY            (0x00200000)
+#define FCT_TX_CTL_TX_DISABLED         (0x00100000)
+#define FCT_TX_CTL_TXUSED              (0x0000FFFF)
+
+#define FCT_RX_FIFO_END                        (0x0098)
+#define FCT_RX_FIFO_END_MASK           (0x0000007F)
+
+#define FCT_TX_FIFO_END                        (0x009C)
+#define FCT_TX_FIFO_END_MASK           (0x0000003F)
+
+#define FCT_FLOW                       (0x00A0)
+#define FCT_FLOW_THRESHOLD_OFF         (0x00007F00)
+#define FCT_FLOW_THRESHOLD_OFF_SHIFT   (8)
+#define FCT_FLOW_THRESHOLD_ON          (0x0000007F)
+
+/* MAC CSRs */
+#define MAC_CR                         (0x100)
+#define MAC_CR_ADP                     (0x00002000)
+#define MAC_CR_ADD                     (0x00001000)
+#define MAC_CR_ASD                     (0x00000800)
+#define MAC_CR_INT_LOOP                        (0x00000400)
+#define MAC_CR_BOLMT                   (0x000000C0)
+#define MAC_CR_FDPX                    (0x00000008)
+#define MAC_CR_CFG                     (0x00000006)
+#define MAC_CR_CFG_10                  (0x00000000)
+#define MAC_CR_CFG_100                 (0x00000002)
+#define MAC_CR_CFG_1000                        (0x00000004)
+#define MAC_CR_RST                     (0x00000001)
+
+#define MAC_RX                         (0x104)
+#define MAC_RX_MAX_SIZE                        (0x3FFF0000)
+#define MAC_RX_MAX_SIZE_SHIFT          (16)
+#define MAC_RX_FCS_STRIP               (0x00000010)
+#define MAC_RX_FSE                     (0x00000004)
+#define MAC_RX_RXD                     (0x00000002)
+#define MAC_RX_RXEN                    (0x00000001)
+
+#define MAC_TX                         (0x108)
+#define MAC_TX_BFCS                    (0x00000004)
+#define MAC_TX_TXD                     (0x00000002)
+#define MAC_TX_TXEN                    (0x00000001)
+
+#define FLOW                           (0x10C)
+#define FLOW_FORCE_FC                  (0x80000000)
+#define FLOW_TX_FCEN                   (0x40000000)
+#define FLOW_RX_FCEN                   (0x20000000)
+#define FLOW_FPF                       (0x10000000)
+#define FLOW_PAUSE_TIME                        (0x0000FFFF)
+
+#define RAND_SEED                      (0x110)
+#define RAND_SEED_MASK                 (0x0000FFFF)
+
+#define ERR_STS                                (0x114)
+#define ERR_STS_FCS_ERR                        (0x00000100)
+#define ERR_STS_LFRM_ERR               (0x00000080)
+#define ERR_STS_RUNT_ERR               (0x00000040)
+#define ERR_STS_COLLISION_ERR          (0x00000010)
+#define ERR_STS_ALIGN_ERR              (0x00000008)
+#define ERR_STS_URUN_ERR               (0x00000004)
+
+#define RX_ADDRH                       (0x118)
+#define RX_ADDRH_MASK                  (0x0000FFFF)
+
+#define RX_ADDRL                       (0x11C)
+
+#define MII_ACCESS                     (0x120)
+#define MII_ACCESS_PHY_ADDR            (0x0000F800)
+#define MII_ACCESS_PHY_ADDR_SHIFT      (11)
+#define MII_ACCESS_REG_ADDR            (0x000007C0)
+#define MII_ACCESS_REG_ADDR_SHIFT      (6)
+#define MII_ACCESS_READ                        (0x00000000)
+#define MII_ACCESS_WRITE               (0x00000002)
+#define MII_ACCESS_BUSY                        (0x00000001)
+
+#define MII_DATA                       (0x124)
+#define MII_DATA_MASK                  (0x0000FFFF)
+
+#define WUCSR                          (0x140)
+#define WUCSR_PFDA_FR                  (0x00000080)
+#define WUCSR_WUFR                     (0x00000040)
+#define WUCSR_MPR                      (0x00000020)
+#define WUCSR_BCAST_FR                 (0x00000010)
+#define WUCSR_PFDA_EN                  (0x00000008)
+#define WUCSR_WUEN                     (0x00000004)
+#define WUCSR_MPEN                     (0x00000002)
+#define WUCSR_BCST_EN                  (0x00000001)
+
+#define WUF_CFGX                       (0x144)
+#define WUF_CFGX_EN                    (0x80000000)
+#define WUF_CFGX_ATYPE                 (0x03000000)
+#define WUF_CFGX_ATYPE_UNICAST         (0x00000000)
+#define WUF_CFGX_ATYPE_MULTICAST       (0x02000000)
+#define WUF_CFGX_ATYPE_ALL             (0x03000000)
+#define WUF_CFGX_PATTERN_OFFSET                (0x007F0000)
+#define WUF_CFGX_PATTERN_OFFSET_SHIFT  (16)
+#define WUF_CFGX_CRC16                 (0x0000FFFF)
+#define WUF_NUM                                (8)
+
+#define WUF_MASKX                      (0x170)
+#define WUF_MASKX_AVALID               (0x80000000)
+#define WUF_MASKX_ATYPE                        (0x40000000)
+
+#define ADDR_FILTX                     (0x300)
+#define ADDR_FILTX_FB_VALID            (0x80000000)
+#define ADDR_FILTX_FB_TYPE             (0x40000000)
+#define ADDR_FILTX_FB_ADDRHI           (0x0000FFFF)
+#define ADDR_FILTX_SB_ADDRLO           (0xFFFFFFFF)
+
+#define WUCSR2                         (0x500)
+#define WUCSR2_NS_RCD                  (0x00000040)
+#define WUCSR2_ARP_RCD                 (0x00000020)
+#define WUCSR2_TCPSYN_RCD              (0x00000010)
+#define WUCSR2_NS_OFFLOAD              (0x00000004)
+#define WUCSR2_ARP_OFFLOAD             (0x00000002)
+#define WUCSR2_TCPSYN_OFFLOAD          (0x00000001)
+
+#define WOL_FIFO_STS                   (0x504)
+
+#define IPV6_ADDRX                     (0x510)
+
+#define IPV4_ADDRX                     (0x590)
+
+
+/* Vendor-specific PHY Definitions */
+
+/* Mode Control/Status Register */
+#define PHY_MODE_CTRL_STS              (17)
+#define MODE_CTRL_STS_EDPWRDOWN                ((u16)0x2000)
+#define MODE_CTRL_STS_ENERGYON         ((u16)0x0002)
+
+#define PHY_INT_SRC                    (29)
+#define PHY_INT_SRC_ENERGY_ON          ((u16)0x0080)
+#define PHY_INT_SRC_ANEG_COMP          ((u16)0x0040)
+#define PHY_INT_SRC_REMOTE_FAULT       ((u16)0x0020)
+#define PHY_INT_SRC_LINK_DOWN          ((u16)0x0010)
+
+#define PHY_INT_MASK                   (30)
+#define PHY_INT_MASK_ENERGY_ON         ((u16)0x0080)
+#define PHY_INT_MASK_ANEG_COMP         ((u16)0x0040)
+#define PHY_INT_MASK_REMOTE_FAULT      ((u16)0x0020)
+#define PHY_INT_MASK_LINK_DOWN         ((u16)0x0010)
+#define PHY_INT_MASK_DEFAULT           (PHY_INT_MASK_ANEG_COMP | \
+                                        PHY_INT_MASK_LINK_DOWN)
+
+#define PHY_SPECIAL                    (31)
+#define PHY_SPECIAL_SPD                        ((u16)0x001C)
+#define PHY_SPECIAL_SPD_10HALF         ((u16)0x0004)
+#define PHY_SPECIAL_SPD_10FULL         ((u16)0x0014)
+#define PHY_SPECIAL_SPD_100HALF                ((u16)0x0008)
+#define PHY_SPECIAL_SPD_100FULL                ((u16)0x0018)
+
+/* USB Vendor Requests */
+#define USB_VENDOR_REQUEST_WRITE_REGISTER      0xA0
+#define USB_VENDOR_REQUEST_READ_REGISTER       0xA1
+#define USB_VENDOR_REQUEST_GET_STATS           0xA2
+
+/* Interrupt Endpoint status word bitfields */
+#define INT_ENP_RDFO_INT               ((u32)BIT(22))
+#define INT_ENP_TXE_INT                        ((u32)BIT(21))
+#define INT_ENP_TX_DIS_INT             ((u32)BIT(19))
+#define INT_ENP_RX_DIS_INT             ((u32)BIT(18))
+#define INT_ENP_PHY_INT                        ((u32)BIT(17))
+#define INT_ENP_MAC_ERR_INT            ((u32)BIT(15))
+#define INT_ENP_RX_FIFO_DATA_INT       ((u32)BIT(12))
+
+#endif /* _SMSC75XX_H */
index df9179a1c93bfb22c1f104ea27233a036da3f49a..d222d7e2527392a79990de49f909e0330483c871 100644 (file)
@@ -709,6 +709,8 @@ static void smsc95xx_start_rx_path(struct usbnet *dev)
 
 static int smsc95xx_phy_initialize(struct usbnet *dev)
 {
+       int bmcr, timeout = 0;
+
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
        dev->mii.mdio_read = smsc95xx_mdio_read;
@@ -717,7 +719,20 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
        dev->mii.reg_num_mask = 0x1f;
        dev->mii.phy_id = SMSC95XX_INTERNAL_PHY_ID;
 
+       /* reset phy and wait for reset to complete */
        smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
+
+       do {
+               msleep(10);
+               bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
+               timeout++;
+       } while ((bmcr & MII_BMCR) && (timeout < 100));
+
+       if (timeout >= 100) {
+               netdev_warn(dev->net, "timeout on PHY Reset");
+               return -EIO;
+       }
+
        smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
                ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP |
                ADVERTISE_PAUSE_ASYM);
index a04f21c8170f38257c2c46545500c42e0c95bcb8..f5da6265331331a5209f9a938d32b1d3989f430f 100644 (file)
@@ -133,6 +133,7 @@ static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_de
                sockets[i].socket.map_size = 0x1000;
                sockets[i].socket.irq_mask = 0;
                sockets[i].socket.pci_irq  = dev->irq;
+               sockets[i].socket.cb_dev  = dev;
                sockets[i].socket.owner = THIS_MODULE;
 
                sockets[i].number = i;
index 849ef1b5d687c7683244cb32d89cd29663144dde..3f84d7a2dc84fad3ee64d020268712df618c82f4 100644 (file)
@@ -95,6 +95,7 @@
 #define I365_CSC_DETECT        0x08
 #define I365_CSC_ANY   0x0F
 #define I365_CSC_GPI   0x10
+#define I365_CSC_IRQ_MASK      0xF0
 
 /* Flags for I365_ADDRWIN */
 #define I365_ENA_IO(map)       (0x40 << (map))
index b2df04199a2197b353ab074cd3a682f65cb7dfa7..c4612c52e4cbb6a0b572e6dfde98d91f5c5a5ccf 100644 (file)
@@ -256,6 +256,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
 {
        struct pcmcia_socket *s;
        config_t *c;
+       int ret;
 
        s = p_dev->socket;
 
@@ -264,13 +265,13 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
 
        if (!(s->state & SOCKET_PRESENT)) {
                dev_dbg(&s->dev, "No card present\n");
-               mutex_unlock(&s->ops_mutex);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto unlock;
        }
        if (!(c->state & CONFIG_LOCKED)) {
                dev_dbg(&s->dev, "Configuration isnt't locked\n");
-               mutex_unlock(&s->ops_mutex);
-               return -EACCES;
+               ret = -EACCES;
+               goto unlock;
        }
 
        if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {
@@ -286,7 +287,8 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
 
        if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
                dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
 
        /* We only allow changing Vpp1 and Vpp2 to the same value */
@@ -294,21 +296,21 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
            (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
                if (mod->Vpp1 != mod->Vpp2) {
                        dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
-                       mutex_unlock(&s->ops_mutex);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto unlock;
                }
                s->socket.Vpp = mod->Vpp1;
                if (s->ops->set_socket(s, &s->socket)) {
-                       mutex_unlock(&s->ops_mutex);
                        dev_printk(KERN_WARNING, &s->dev,
                                   "Unable to set VPP\n");
-                       return -EIO;
+                       ret = -EIO;
+                       goto unlock;
                }
        } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
                   (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
                dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
-               mutex_unlock(&s->ops_mutex);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
 
        if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
@@ -332,9 +334,11 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                        s->ops->set_io_map(s, &io_on);
                }
        }
+       ret = 0;
+unlock:
        mutex_unlock(&s->ops_mutex);
 
-       return 0;
+       return ret;
 } /* modify_configuration */
 EXPORT_SYMBOL(pcmcia_modify_configuration);
 
@@ -752,14 +756,6 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
 
 #ifdef CONFIG_PCMCIA_PROBE
 
-#ifdef IRQ_NOAUTOEN
-       /* if the underlying IRQ infrastructure allows for it, only allocate
-        * the IRQ, but do not enable it
-        */
-       if (!(req->Handler))
-               type |= IRQ_NOAUTOEN;
-#endif /* IRQ_NOAUTOEN */
-
        if (s->irq.AssignedIRQ != 0) {
                /* If the interrupt is already assigned, it must be the same */
                irq = s->irq.AssignedIRQ;
index 7c204910a77742980cf7cdbb448110f65f763611..7ba57a565cd72500d01a6666fde4d64ec4610fd7 100644 (file)
@@ -671,6 +671,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
                socket[i].socket.map_size = 0x1000;
                socket[i].socket.irq_mask = mask;
                socket[i].socket.pci_irq  = dev->irq;
+               socket[i].socket.cb_dev = dev;
                socket[i].socket.owner = THIS_MODULE;
 
                socket[i].number = i;
index aaa70227bfb05ee4df811a00fc11df5670d8d50c..9ffa97d0b16c3655469deb0f4895694034ff3182 100644 (file)
@@ -296,7 +296,7 @@ static int ti_init(struct yenta_socket *socket)
        u8 new, reg = exca_readb(socket, I365_INTCTL);
 
        new = reg & ~I365_INTR_ENA;
-       if (socket->cb_irq)
+       if (socket->dev->irq)
                new |= I365_INTR_ENA;
        if (new != reg)
                exca_writeb(socket, I365_INTCTL, new);
@@ -316,14 +316,47 @@ static int ti_override(struct yenta_socket *socket)
        return 0;
 }
 
+static void ti113x_use_isa_irq(struct yenta_socket *socket)
+{
+       int isa_irq = -1;
+       u8 intctl;
+       u32 isa_irq_mask = 0;
+
+       if (!isa_probe)
+               return;
+
+       /* get a free isa int */
+       isa_irq_mask = yenta_probe_irq(socket, isa_interrupts);
+       if (!isa_irq_mask)
+               return; /* no useable isa irq found */
+
+       /* choose highest available */
+       for (; isa_irq_mask; isa_irq++)
+               isa_irq_mask >>= 1;
+       socket->cb_irq = isa_irq;
+
+       exca_writeb(socket, I365_CSCINT, (isa_irq << 4));
+
+       intctl = exca_readb(socket, I365_INTCTL);
+       intctl &= ~(I365_INTR_ENA | I365_IRQ_MASK);     /* CSC Enable */
+       exca_writeb(socket, I365_INTCTL, intctl);
+
+       dev_info(&socket->dev->dev,
+               "Yenta TI113x: using isa irq %d for CardBus\n", isa_irq);
+}
+
+
 static int ti113x_override(struct yenta_socket *socket)
 {
        u8 cardctl;
 
        cardctl = config_readb(socket, TI113X_CARD_CONTROL);
        cardctl &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
-       if (socket->cb_irq)
+       if (socket->dev->irq)
                cardctl |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
+       else
+               ti113x_use_isa_irq(socket);
+
        config_writeb(socket, TI113X_CARD_CONTROL, cardctl);
 
        return ti_override(socket);
index c9fcbdc164eabcd812d12e808b310417795603f7..aaccdb9f4ba170672a1de284769a03e4f361212d 100644 (file)
@@ -105,6 +105,7 @@ typedef struct vrc4171_socket {
        char name[24];
        int csc_irq;
        int io_irq;
+       spinlock_t lock;
 } vrc4171_socket_t;
 
 static vrc4171_socket_t vrc4171_sockets[CARD_MAX_SLOTS];
@@ -327,7 +328,7 @@ static int pccard_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
        slot = sock->sock;
        socket = &vrc4171_sockets[slot];
 
-       spin_lock_irq(&sock->lock);
+       spin_lock_irq(&socket->lock);
 
        voltage = set_Vcc_value(state->Vcc);
        exca_write_byte(slot, CARD_VOLTAGE_SELECT, voltage);
@@ -370,7 +371,7 @@ static int pccard_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
                cscint |= I365_CSC_DETECT;
         exca_write_byte(slot, I365_CSCINT, cscint);
 
-       spin_unlock_irq(&sock->lock);
+       spin_unlock_irq(&socket->lock);
 
        return 0;
 }
index 967c766f53ba63a0c8939ce236862ae86971204c..418988ab6edf336892675a39241aec7b9111910f 100644 (file)
@@ -42,6 +42,18 @@ module_param_string(o2_speedup, o2_speedup, sizeof(o2_speedup), 0444);
 MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' "
        "or 'default' (uses recommended behaviour for the detected bridge)");
 
+/*
+ * Only probe "regular" interrupts, don't
+ * touch dangerous spots like the mouse irq,
+ * because there are mice that apparently
+ * get really confused if they get fondled
+ * too intimately.
+ *
+ * Default to 11, 10, 9, 7, 6, 5, 4, 3.
+ */
+static u32 isa_interrupts = 0x0ef8;
+
+
 #define debug(x, s, args...) dev_dbg(&s->dev->dev, x, ##args)
 
 /* Don't ask.. */
@@ -54,6 +66,8 @@ MODULE_PARM_DESC(o2_speedup, "Use prefetch/burst for O2-bridges: 'on', 'off' "
  */
 #ifdef CONFIG_YENTA_TI
 static int yenta_probe_cb_irq(struct yenta_socket *socket);
+static unsigned int yenta_probe_irq(struct yenta_socket *socket,
+                               u32 isa_irq_mask);
 #endif
 
 
@@ -329,8 +343,8 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
                /* ISA interrupt control? */
                intr = exca_readb(socket, I365_INTCTL);
                intr = (intr & ~0xf);
-               if (!socket->cb_irq) {
-                       intr |= state->io_irq;
+               if (!socket->dev->irq) {
+                       intr |= socket->cb_irq ? socket->cb_irq : state->io_irq;
                        bridge |= CB_BRIDGE_INTR;
                }
                exca_writeb(socket, I365_INTCTL, intr);
@@ -340,7 +354,7 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
                reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA);
                reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
                reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
-               if (state->io_irq != socket->cb_irq) {
+               if (state->io_irq != socket->dev->irq) {
                        reg |= state->io_irq;
                        bridge |= CB_BRIDGE_INTR;
                }
@@ -356,7 +370,9 @@ static int yenta_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
                        exca_writeb(socket, I365_POWER, reg);
 
                /* CSC interrupt: no ISA irq for CSC */
-               reg = I365_CSC_DETECT;
+               reg = exca_readb(socket, I365_CSCINT);
+               reg &= I365_CSC_IRQ_MASK;
+               reg |= I365_CSC_DETECT;
                if (state->flags & SS_IOCARD) {
                        if (state->csc_mask & SS_STSCHG)
                                reg |= I365_CSC_STSCHG;
@@ -896,22 +912,12 @@ static struct cardbus_type cardbus_type[] = {
 };
 
 
-/*
- * Only probe "regular" interrupts, don't
- * touch dangerous spots like the mouse irq,
- * because there are mice that apparently
- * get really confused if they get fondled
- * too intimately.
- *
- * Default to 11, 10, 9, 7, 6, 5, 4, 3.
- */
-static u32 isa_interrupts = 0x0ef8;
-
 static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask)
 {
        int i;
        unsigned long val;
        u32 mask;
+       u8 reg;
 
        /*
         * Probe for usable interrupts using the force
@@ -919,6 +925,7 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
         */
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
+       reg = exca_readb(socket, I365_CSCINT);
        exca_writeb(socket, I365_CSCINT, 0);
        val = probe_irq_on() & isa_irq_mask;
        for (i = 1; i < 16; i++) {
@@ -930,7 +937,7 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
                cb_writel(socket, CB_SOCKET_EVENT, -1);
        }
        cb_writel(socket, CB_SOCKET_MASK, 0);
-       exca_writeb(socket, I365_CSCINT, 0);
+       exca_writeb(socket, I365_CSCINT, reg);
 
        mask = probe_irq_mask(val) & 0xffff;
 
@@ -967,6 +974,8 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id)
 /* probes the PCI interrupt, use only on override functions */
 static int yenta_probe_cb_irq(struct yenta_socket *socket)
 {
+       u8 reg;
+
        if (!socket->cb_irq)
                return -1;
 
@@ -979,7 +988,8 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
        }
 
        /* generate interrupt, wait */
-       exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG);
+       reg = exca_readb(socket, I365_CSCINT);
+       exca_writeb(socket, I365_CSCINT, reg | I365_CSC_STSCHG);
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
        cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
@@ -988,7 +998,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
 
        /* disable interrupts */
        cb_writel(socket, CB_SOCKET_MASK, 0);
-       exca_writeb(socket, I365_CSCINT, 0);
+       exca_writeb(socket, I365_CSCINT, reg);
        cb_writel(socket, CB_SOCKET_EVENT, -1);
        exca_readb(socket, I365_CSC);
 
index b3beab610da445334be1818b4f8ae05e81e941ba..fc7ae05ce48ae262374b0becc3373a1b42d00690 100644 (file)
@@ -704,6 +704,13 @@ int sclp_chp_deconfigure(struct chp_id chpid)
        return do_chp_configure(SCLP_CMDW_DECONFIGURE_CHPATH | chpid.id << 8);
 }
 
+int arch_get_memory_phys_device(unsigned long start_pfn)
+{
+       if (!rzm)
+               return 0;
+       return PFN_PHYS(start_pfn) / rzm;
+}
+
 struct chp_info_sccb {
        struct sccb_header header;
        u8 recognized[SCLP_CHP_INFO_MASK_SIZE];
index c2341af587a3111e1920678400f75be246afb017..02124645487215aa7b02d7da572d66798aa5f0e6 100644 (file)
@@ -1717,6 +1717,7 @@ static int nsp_cs_config(struct pcmcia_device *link)
        cfg_mem->data = data;
 
        ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+       if (ret)
                goto cs_failed;
 
        if (link->conf.Attributes & CONF_ENABLE_IRQ) {
index d514e28d07557b7516de0ecd7478d1cb9401f619..d2e0321049e2e1e3952244f35300da0bc887aff2 100644 (file)
@@ -474,7 +474,7 @@ static void sunsab_stop_rx(struct uart_port *port)
 {
        struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
 
-       up->interrupt_mask0 |= SAB82532_ISR0_TCD;
+       up->interrupt_mask0 |= SAB82532_IMR0_TCD;
        writeb(up->interrupt_mask1, &up->regs->w.imr0);
 }
 
index dabe804ba575ecdd714873795ee7c081d474cc28..feaff4f04b5820b6dfd24ab7584728970b065cc4 100644 (file)
@@ -914,7 +914,7 @@ config FB_XVR2500
 
 config FB_XVR1000
        bool "Sun XVR-1000 support"
-       depends on SPARC64
+       depends on (FB = y) && SPARC64
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index e22de8397b7430f3e48bcd2ae32ca0af70fe0a12..d32ee9412cb991a82ba04b0d1eb1abcec98d570d 100644 (file)
@@ -567,7 +567,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list)
                        else BUG();
                }
        }
-       list->rb_node = NULL;
+       *list = RB_ROOT;
 }
 
 static void jffs2_free_full_dirent_list(struct jffs2_full_dirent *fd)
index 1cf39dfaee7a7395f89763528bf63eb957fec106..0de1db6cddbfee225bde0314669fbcde82cc70c2 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/vfs.h>
 #include <linux/moduleparam.h>
 #include <linux/smp_lock.h>
+#include <linux/bitmap.h>
 
 #include "sysctl.h"
 #include "logfile.h"
@@ -2458,7 +2459,6 @@ static void ntfs_put_super(struct super_block *sb)
 static s64 get_nr_free_clusters(ntfs_volume *vol)
 {
        s64 nr_free = vol->nr_clusters;
-       u32 *kaddr;
        struct address_space *mapping = vol->lcnbmp_ino->i_mapping;
        struct page *page;
        pgoff_t index, max_index;
@@ -2477,7 +2477,8 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
        ntfs_debug("Reading $Bitmap, max_index = 0x%lx, max_size = 0x%lx.",
                        max_index, PAGE_CACHE_SIZE / 4);
        for (index = 0; index < max_index; index++) {
-               unsigned int i;
+               unsigned long *kaddr;
+
                /*
                 * Read the page from page cache, getting it from backing store
                 * if necessary, and increment the use count.
@@ -2490,16 +2491,16 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
                        nr_free -= PAGE_CACHE_SIZE * 8;
                        continue;
                }
-               kaddr = (u32*)kmap_atomic(page, KM_USER0);
+               kaddr = kmap_atomic(page, KM_USER0);
                /*
-                * For each 4 bytes, subtract the number of set bits. If this
+                * Subtract the number of set bits. If this
                 * is the last page and it is partial we don't really care as
                 * it just means we do a little extra work but it won't affect
                 * the result as all out of range bytes are set to zero by
                 * ntfs_readpage().
                 */
-               for (i = 0; i < PAGE_CACHE_SIZE / 4; i++)
-                       nr_free -= (s64)hweight32(kaddr[i]);
+               nr_free -= bitmap_weight(kaddr,
+                                       PAGE_CACHE_SIZE * BITS_PER_BYTE);
                kunmap_atomic(kaddr, KM_USER0);
                page_cache_release(page);
        }
@@ -2538,7 +2539,6 @@ static s64 get_nr_free_clusters(ntfs_volume *vol)
 static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
                s64 nr_free, const pgoff_t max_index)
 {
-       u32 *kaddr;
        struct address_space *mapping = vol->mftbmp_ino->i_mapping;
        struct page *page;
        pgoff_t index;
@@ -2548,7 +2548,8 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
        ntfs_debug("Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = "
                        "0x%lx.", max_index, PAGE_CACHE_SIZE / 4);
        for (index = 0; index < max_index; index++) {
-               unsigned int i;
+               unsigned long *kaddr;
+
                /*
                 * Read the page from page cache, getting it from backing store
                 * if necessary, and increment the use count.
@@ -2561,16 +2562,16 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol,
                        nr_free -= PAGE_CACHE_SIZE * 8;
                        continue;
                }
-               kaddr = (u32*)kmap_atomic(page, KM_USER0);
+               kaddr = kmap_atomic(page, KM_USER0);
                /*
-                * For each 4 bytes, subtract the number of set bits. If this
+                * Subtract the number of set bits. If this
                 * is the last page and it is partial we don't really care as
                 * it just means we do a little extra work but it won't affect
                 * the result as all out of range bytes are set to zero by
                 * ntfs_readpage().
                 */
-               for (i = 0; i < PAGE_CACHE_SIZE / 4; i++)
-                       nr_free -= (s64)hweight32(kaddr[i]);
+               nr_free -= bitmap_weight(kaddr,
+                                       PAGE_CACHE_SIZE * BITS_PER_BYTE);
                kunmap_atomic(kaddr, KM_USER0);
                page_cache_release(page);
        }
index 9083357f9e444170b5b95124e936bb0e0d430c7f..99628508cb11f640abd9bb9e919a17699e1c4e11 100644 (file)
@@ -932,6 +932,9 @@ xfs_aops_discard_page(
        if (!xfs_is_delayed_page(page, IOMAP_DELAY))
                goto out_invalidate;
 
+       if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+               goto out_invalidate;
+
        xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
                "page discard on page %p, inode 0x%llx, offset %llu.",
                        page, ip->i_ino, offset);
@@ -964,8 +967,10 @@ xfs_aops_discard_page(
 
                if (error) {
                        /* something screwed, just bail */
-                       xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
-                       "page discard failed delalloc mapping lookup.");
+                       if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+                               "page discard failed delalloc mapping lookup.");
+                       }
                        break;
                }
                if (!nimaps) {
@@ -991,8 +996,10 @@ xfs_aops_discard_page(
                ASSERT(!flist.xbf_count && !flist.xbf_first);
                if (error) {
                        /* something screwed, just bail */
-                       xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+                       if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) {
+                               xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
                        "page discard unable to remove delalloc mapping.");
+                       }
                        break;
                }
 next_buffer:
index 6f76ba85f193e724e8bba96d5c8cc07e40fb1c50..bd111b7e1daa5812b8b1d68907ecc390caecd8e0 100644 (file)
@@ -167,75 +167,6 @@ test_page_region(
        return (mask && (page_private(page) & mask) == mask);
 }
 
-/*
- *     Mapping of multi-page buffers into contiguous virtual space
- */
-
-typedef struct a_list {
-       void            *vm_addr;
-       struct a_list   *next;
-} a_list_t;
-
-static a_list_t                *as_free_head;
-static int             as_list_len;
-static DEFINE_SPINLOCK(as_lock);
-
-/*
- *     Try to batch vunmaps because they are costly.
- */
-STATIC void
-free_address(
-       void            *addr)
-{
-       a_list_t        *aentry;
-
-#ifdef CONFIG_XEN
-       /*
-        * Xen needs to be able to make sure it can get an exclusive
-        * RO mapping of pages it wants to turn into a pagetable.  If
-        * a newly allocated page is also still being vmap()ed by xfs,
-        * it will cause pagetable construction to fail.  This is a
-        * quick workaround to always eagerly unmap pages so that Xen
-        * is happy.
-        */
-       vunmap(addr);
-       return;
-#endif
-
-       aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
-       if (likely(aentry)) {
-               spin_lock(&as_lock);
-               aentry->next = as_free_head;
-               aentry->vm_addr = addr;
-               as_free_head = aentry;
-               as_list_len++;
-               spin_unlock(&as_lock);
-       } else {
-               vunmap(addr);
-       }
-}
-
-STATIC void
-purge_addresses(void)
-{
-       a_list_t        *aentry, *old;
-
-       if (as_free_head == NULL)
-               return;
-
-       spin_lock(&as_lock);
-       aentry = as_free_head;
-       as_free_head = NULL;
-       as_list_len = 0;
-       spin_unlock(&as_lock);
-
-       while ((old = aentry) != NULL) {
-               vunmap(aentry->vm_addr);
-               aentry = aentry->next;
-               kfree(old);
-       }
-}
-
 /*
  *     Internal xfs_buf_t object manipulation
  */
@@ -337,7 +268,8 @@ xfs_buf_free(
                uint            i;
 
                if (xfs_buf_is_vmapped(bp))
-                       free_address(bp->b_addr - bp->b_offset);
+                       vm_unmap_ram(bp->b_addr - bp->b_offset,
+                                       bp->b_page_count);
 
                for (i = 0; i < bp->b_page_count; i++) {
                        struct page     *page = bp->b_pages[i];
@@ -457,10 +389,8 @@ _xfs_buf_map_pages(
                bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;
                bp->b_flags |= XBF_MAPPED;
        } else if (flags & XBF_MAPPED) {
-               if (as_list_len > 64)
-                       purge_addresses();
-               bp->b_addr = vmap(bp->b_pages, bp->b_page_count,
-                                       VM_MAP, PAGE_KERNEL);
+               bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
+                                       -1, PAGE_KERNEL);
                if (unlikely(bp->b_addr == NULL))
                        return -ENOMEM;
                bp->b_addr += bp->b_offset;
@@ -1955,9 +1885,6 @@ xfsbufd(
                        xfs_buf_iostrategy(bp);
                        count++;
                }
-
-               if (as_list_len > 0)
-                       purge_addresses();
                if (count)
                        blk_run_address_space(target->bt_mapping);
 
index 1adfe779eb99123a91c4141bd1974654db8d5880..85582e1bcee900bd219c60169a708a2a38dca8e1 100644 (file)
@@ -36,6 +36,8 @@ struct memory_block {
        struct sys_device sysdev;
 };
 
+int arch_get_memory_phys_device(unsigned long start_pfn);
+
 /* These states are exposed to userspace as text strings in sysfs */
 #define        MEM_ONLINE              (1<<0) /* exposed to userspace */
 #define        MEM_GOING_OFFLINE       (1<<1) /* exposed to userspace */
index 3dd88539a0e6b47876ec87a91ee093533e1392c9..6c0081441a326a174f83ebd66485bd9cb961f88d 100644 (file)
@@ -284,6 +284,7 @@ static DEFINE_MUTEX(swap_cgroup_mutex);
 struct swap_cgroup_ctrl {
        struct page **map;
        unsigned long length;
+       spinlock_t      lock;
 };
 
 struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES];
@@ -353,16 +354,22 @@ unsigned short swap_cgroup_cmpxchg(swp_entry_t ent,
        struct swap_cgroup_ctrl *ctrl;
        struct page *mappage;
        struct swap_cgroup *sc;
+       unsigned long flags;
+       unsigned short retval;
 
        ctrl = &swap_cgroup_ctrl[type];
 
        mappage = ctrl->map[idx];
        sc = page_address(mappage);
        sc += pos;
-       if (cmpxchg(&sc->id, old, new) == old)
-               return old;
+       spin_lock_irqsave(&ctrl->lock, flags);
+       retval = sc->id;
+       if (retval == old)
+               sc->id = new;
        else
-               return 0;
+               retval = 0;
+       spin_unlock_irqrestore(&ctrl->lock, flags);
+       return retval;
 }
 
 /**
@@ -383,13 +390,17 @@ unsigned short swap_cgroup_record(swp_entry_t ent, unsigned short id)
        struct page *mappage;
        struct swap_cgroup *sc;
        unsigned short old;
+       unsigned long flags;
 
        ctrl = &swap_cgroup_ctrl[type];
 
        mappage = ctrl->map[idx];
        sc = page_address(mappage);
        sc += pos;
-       old = xchg(&sc->id, id);
+       spin_lock_irqsave(&ctrl->lock, flags);
+       old = sc->id;
+       sc->id = id;
+       spin_unlock_irqrestore(&ctrl->lock, flags);
 
        return old;
 }
@@ -441,6 +452,7 @@ int swap_cgroup_swapon(int type, unsigned long max_pages)
        mutex_lock(&swap_cgroup_mutex);
        ctrl->length = length;
        ctrl->map = array;
+       spin_lock_init(&ctrl->lock);
        if (swap_cgroup_prepare(type)) {
                /* memory shortage */
                ctrl->map = NULL;
index eb7062d2e9e5d28168fe2dcbdc3ec2f44bc9f4c9..90a9024e5c1eaf30713258c4d32151a89cc87c06 100644 (file)
@@ -40,7 +40,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
                        goto out;
 
                mdst = br_mdb_get(br, skb);
-               if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only)
+               if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb))
                        br_multicast_deliver(mdst, skb);
                else
                        br_flood_deliver(br, skb);
index d61e6f741125bbd510d20237a8e76e4292802b77..8dbec83e50ca2cd8b43fe466e578a68d6eb7c7b2 100644 (file)
 #include <linux/netfilter_bridge.h>
 #include "br_private.h"
 
+static int deliver_clone(const struct net_bridge_port *prev,
+                        struct sk_buff *skb,
+                        void (*__packet_hook)(const struct net_bridge_port *p,
+                                              struct sk_buff *skb));
+
 /* Don't forward packets to originating port or forwarding diasabled */
 static inline int should_deliver(const struct net_bridge_port *p,
                                 const struct sk_buff *skb)
@@ -94,17 +99,22 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
 }
 
 /* called with rcu_read_lock */
-void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
+void br_forward(const struct net_bridge_port *to, struct sk_buff *skb, struct sk_buff *skb0)
 {
        if (should_deliver(to, skb)) {
-               __br_forward(to, skb);
+               if (skb0)
+                       deliver_clone(to, skb, __br_forward);
+               else
+                       __br_forward(to, skb);
                return;
        }
 
-       kfree_skb(skb);
+       if (!skb0)
+               kfree_skb(skb);
 }
 
-static int deliver_clone(struct net_bridge_port *prev, struct sk_buff *skb,
+static int deliver_clone(const struct net_bridge_port *prev,
+                        struct sk_buff *skb,
                         void (*__packet_hook)(const struct net_bridge_port *p,
                                               struct sk_buff *skb))
 {
index 53b39851d87d475ecdbfbf9b94fa6eb8072d5f40..d74d570fc848537b437b24aa696285afef90543c 100644 (file)
@@ -70,7 +70,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
 
        if (is_multicast_ether_addr(dest)) {
                mdst = br_mdb_get(br, skb);
-               if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) {
+               if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
                        if ((mdst && !hlist_unhashed(&mdst->mglist)) ||
                            br_multicast_is_router(br))
                                skb2 = skb;
@@ -90,7 +90,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
 
        if (skb) {
                if (dst)
-                       br_forward(dst->dst, skb);
+                       br_forward(dst->dst, skb, skb2);
                else
                        br_flood_forward(br, skb, skb2);
        }
index fd96a8dc97f4b8c03bbeb67141d12669d817feb6..6980625537caa15e5f0a479eccca15c3341073a3 100644 (file)
@@ -49,22 +49,23 @@ static struct net_bridge_mdb_entry *__br_mdb_ip_get(
 static struct net_bridge_mdb_entry *br_mdb_ip_get(
        struct net_bridge_mdb_htable *mdb, __be32 dst)
 {
+       if (!mdb)
+               return NULL;
+
        return __br_mdb_ip_get(mdb, dst, br_ip_hash(mdb, dst));
 }
 
 struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
                                        struct sk_buff *skb)
 {
-       struct net_bridge_mdb_htable *mdb = br->mdb;
-
-       if (!mdb || br->multicast_disabled)
+       if (br->multicast_disabled)
                return NULL;
 
        switch (skb->protocol) {
        case htons(ETH_P_IP):
                if (BR_INPUT_SKB_CB(skb)->igmp)
                        break;
-               return br_mdb_ip_get(mdb, ip_hdr(skb)->daddr);
+               return br_mdb_ip_get(br->mdb, ip_hdr(skb)->daddr);
        }
 
        return NULL;
@@ -851,8 +852,8 @@ static int br_multicast_query(struct net_bridge *br,
                if (ih3->nsrcs)
                        goto out;
 
-               max_delay = ih3->code ? 1 :
-                           IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE);
+               max_delay = ih3->code ?
+                           IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
        }
 
        if (!group)
@@ -990,7 +991,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
 
                err = pskb_trim_rcsum(skb2, len);
                if (err)
-                       return err;
+                       goto err_out;
        }
 
        len -= ip_hdrlen(skb2);
@@ -1012,7 +1013,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
        case CHECKSUM_NONE:
                skb2->csum = 0;
                if (skb_checksum_complete(skb2))
-                       return -EINVAL;
+                       goto out;
        }
 
        err = 0;
@@ -1039,6 +1040,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
 
 out:
        __skb_push(skb2, offset);
+err_out:
        if (skb2 != skb)
                kfree_skb(skb2);
        return err;
index fef0384e3c0b78ad09074487200cb08747fc46b4..846d7d1e2075d1ffb7821c3244441203b0a8d726 100644 (file)
@@ -206,12 +206,20 @@ struct net_bridge
 
 struct br_input_skb_cb {
        struct net_device *brdev;
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
        int igmp;
        int mrouters_only;
+#endif
 };
 
 #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb)
 
+#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb)  (BR_INPUT_SKB_CB(__skb)->mrouters_only)
+#else
+# define BR_INPUT_SKB_CB_MROUTERS_ONLY(__skb)  (0)
+#endif
+
 extern struct notifier_block br_device_notifier;
 extern const u8 br_group_address[ETH_ALEN];
 
@@ -252,7 +260,7 @@ extern void br_deliver(const struct net_bridge_port *to,
                struct sk_buff *skb);
 extern int br_dev_queue_push_xmit(struct sk_buff *skb);
 extern void br_forward(const struct net_bridge_port *to,
-               struct sk_buff *skb);
+               struct sk_buff *skb, struct sk_buff *skb0);
 extern int br_forward_finish(struct sk_buff *skb);
 extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb);
 extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
index 7aa6972537658375031c81dd41e31171b0f69084..d4ec38fa64e6df2742c9c79e7551d6f996f9a600 100644 (file)
@@ -735,7 +735,7 @@ int netpoll_setup(struct netpoll *np)
                npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
                if (!npinfo) {
                        err = -ENOMEM;
-                       goto release;
+                       goto put;
                }
 
                npinfo->rx_flags = 0;
@@ -845,7 +845,7 @@ int netpoll_setup(struct netpoll *np)
 
                kfree(npinfo);
        }
-
+put:
        dev_put(ndev);
        return err;
 }
index b195c4feaa0ae3390fefad4d06e50d43f08acf83..4071eaf2b361225a846780fe44e12b77476323f4 100644 (file)
@@ -998,11 +998,11 @@ static struct inet_protosw dccp_v4_protosw = {
 
 static int __net_init dccp_v4_init_net(struct net *net)
 {
-       int err;
+       if (dccp_hashinfo.bhash == NULL)
+               return -ESOCKTNOSUPPORT;
 
-       err = inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET,
-                                  SOCK_DCCP, IPPROTO_DCCP, net);
-       return err;
+       return inet_ctl_sock_create(&net->dccp.v4_ctl_sk, PF_INET,
+                                   SOCK_DCCP, IPPROTO_DCCP, net);
 }
 
 static void __net_exit dccp_v4_exit_net(struct net *net)
index 1aec6349e8582e5f0d7e7110ec0f857419575e4e..af3394df63b7ea388922b2f33f04324be21421af 100644 (file)
@@ -1191,11 +1191,11 @@ static struct inet_protosw dccp_v6_protosw = {
 
 static int __net_init dccp_v6_init_net(struct net *net)
 {
-       int err;
+       if (dccp_hashinfo.bhash == NULL)
+               return -ESOCKTNOSUPPORT;
 
-       err = inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
-                                  SOCK_DCCP, IPPROTO_DCCP, net);
-       return err;
+       return inet_ctl_sock_create(&net->dccp.v6_ctl_sk, PF_INET6,
+                                   SOCK_DCCP, IPPROTO_DCCP, net);
 }
 
 static void __net_exit dccp_v6_exit_net(struct net *net)
index 0ef7061920c02ba08a124641322019a35cdaa195..aa4cef374fd0d49685731e7698f1f725363ddc9a 100644 (file)
@@ -1036,7 +1036,7 @@ static int __init dccp_init(void)
                     FIELD_SIZEOF(struct sk_buff, cb));
        rc = percpu_counter_init(&dccp_orphan_count, 0);
        if (rc)
-               goto out;
+               goto out_fail;
        rc = -ENOBUFS;
        inet_hashinfo_init(&dccp_hashinfo);
        dccp_hashinfo.bind_bucket_cachep =
@@ -1125,8 +1125,9 @@ static int __init dccp_init(void)
                goto out_sysctl_exit;
 
        dccp_timestamping_init();
-out:
-       return rc;
+
+       return 0;
+
 out_sysctl_exit:
        dccp_sysctl_exit();
 out_ackvec_exit:
@@ -1135,18 +1136,19 @@ out_free_dccp_mib:
        dccp_mib_exit();
 out_free_dccp_bhash:
        free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
-       dccp_hashinfo.bhash = NULL;
 out_free_dccp_locks:
        inet_ehash_locks_free(&dccp_hashinfo);
 out_free_dccp_ehash:
        free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order);
-       dccp_hashinfo.ehash = NULL;
 out_free_bind_bucket_cachep:
        kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
-       dccp_hashinfo.bind_bucket_cachep = NULL;
 out_free_percpu:
        percpu_counter_destroy(&dccp_orphan_count);
-       goto out;
+out_fail:
+       dccp_hashinfo.bhash = NULL;
+       dccp_hashinfo.ehash = NULL;
+       dccp_hashinfo.bind_bucket_cachep = NULL;
+       return rc;
 }
 
 static void __exit dccp_fini(void)
index d9b40248b97feb4a1e3e4dd01c9ec789b4494842..a770df2493d23652fa5640517b59d9e2f47e7893 100644 (file)
@@ -932,10 +932,8 @@ static void rt_secret_rebuild_oneshot(struct net *net)
 {
        del_timer_sync(&net->ipv4.rt_secret_timer);
        rt_cache_invalidate(net);
-       if (ip_rt_secret_interval) {
-               net->ipv4.rt_secret_timer.expires += ip_rt_secret_interval;
-               add_timer(&net->ipv4.rt_secret_timer);
-       }
+       if (ip_rt_secret_interval)
+               mod_timer(&net->ipv4.rt_secret_timer, jiffies + ip_rt_secret_interval);
 }
 
 static void rt_emergency_hash_rebuild(struct net *net)
@@ -3103,22 +3101,20 @@ static void rt_secret_reschedule(int old)
        rtnl_lock();
        for_each_net(net) {
                int deleted = del_timer_sync(&net->ipv4.rt_secret_timer);
+               long time;
 
                if (!new)
                        continue;
 
                if (deleted) {
-                       long time = net->ipv4.rt_secret_timer.expires - jiffies;
+                       time = net->ipv4.rt_secret_timer.expires - jiffies;
 
                        if (time <= 0 || (time += diff) <= 0)
                                time = 0;
-
-                       net->ipv4.rt_secret_timer.expires = time;
                } else
-                       net->ipv4.rt_secret_timer.expires = new;
+                       time = new;
 
-               net->ipv4.rt_secret_timer.expires += jiffies;
-               add_timer(&net->ipv4.rt_secret_timer);
+               mod_timer(&net->ipv4.rt_secret_timer, jiffies + time);
        }
        rtnl_unlock();
 }
index c597cc53a6fb2d3433c70beea0f05fdc982d5a21..5c6ae0c701c047866bae808b77db22e8fc8ddad0 100644 (file)
@@ -107,8 +107,7 @@ static void phonet_device_destroy(struct net_device *dev)
        if (pnd) {
                u8 addr;
 
-               for (addr = find_first_bit(pnd->addrs, 64); addr < 64;
-                       addr = find_next_bit(pnd->addrs, 64, 1+addr))
+               for_each_set_bit(addr, pnd->addrs, 64)
                        phonet_address_notify(RTM_DELADDR, dev, addr);
                kfree(pnd);
        }
index 2e6c7eb8e76add27fabc042825e8bda8f9886d06..fe2e7088ee07b10d387aa5db7b6bc9e7d369853a 100644 (file)
@@ -141,8 +141,7 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
                        continue;
 
                addr_idx = 0;
-               for (addr = find_first_bit(pnd->addrs, 64); addr < 64;
-                       addr = find_next_bit(pnd->addrs, 64, 1+addr)) {
+               for_each_set_bit(addr, pnd->addrs, 64) {
                        if (addr_idx++ < addr_start_idx)
                                continue;
 
index 414fc34b8bea5550198a01036f68191f06d2f475..8dea66500cf5ce65d6427aad77152f437e0c92ac 100644 (file)
@@ -153,11 +153,11 @@ void tipc_ref_table_stop(void)
 
 u32 tipc_ref_acquire(void *object, spinlock_t **lock)
 {
-       struct reference *entry;
        u32 index;
        u32 index_mask;
        u32 next_plus_upper;
        u32 ref;
+       struct reference *entry = NULL;
 
        if (!object) {
                err("Attempt to acquire reference to non-existent object\n");
@@ -175,30 +175,36 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
                index = tipc_ref_table.first_free;
                entry = &(tipc_ref_table.entries[index]);
                index_mask = tipc_ref_table.index_mask;
-               /* take lock in case a previous user of entry still holds it */
-               spin_lock_bh(&entry->lock);
                next_plus_upper = entry->ref;
                tipc_ref_table.first_free = next_plus_upper & index_mask;
                ref = (next_plus_upper & ~index_mask) + index;
-               entry->ref = ref;
-               entry->object = object;
-               *lock = &entry->lock;
        }
        else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
                index = tipc_ref_table.init_point++;
                entry = &(tipc_ref_table.entries[index]);
                spin_lock_init(&entry->lock);
-               spin_lock_bh(&entry->lock);
                ref = tipc_ref_table.start_mask + index;
-               entry->ref = ref;
-               entry->object = object;
-               *lock = &entry->lock;
        }
        else {
                ref = 0;
        }
        write_unlock_bh(&ref_table_lock);
 
+       /*
+        * Grab the lock so no one else can modify this entry
+        * While we assign its ref value & object pointer
+        */
+       if (entry) {
+               spin_lock_bh(&entry->lock);
+               entry->ref = ref;
+               entry->object = object;
+               *lock = &entry->lock;
+               /*
+                * keep it locked, the caller is responsible
+                * for unlocking this when they're done with it
+                */
+       }
+
        return ref;
 }