- Update to 2.6.22.8-rc1
authorGreg Kroah-Hartman <gregkh@suse.de>
Mon, 24 Sep 2007 17:57:57 +0000 (17:57 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 24 Sep 2007 17:57:57 +0000 (17:57 +0000)
  - metric boatload of bugfixes (50 to be exact.)
  - removed one duplicate patch:
- patches.fixes/fix_futex_compat_bug.patch: Delete.
- Update config files.

suse-commit: ae8e5521e7af257227b9c29a1295e4233c1f10f8

53 files changed:
Documentation/dvb/get_dvb_firmware
arch/powerpc/kernel/process.c
arch/sparc64/kernel/pci.c
block/ll_rw_blk.c
crypto/blkcipher.c
drivers/acpi/tables/tbutils.c
drivers/block/DAC960.c
drivers/block/DAC960.h
drivers/firewire/fw-ohci.c
drivers/hwmon/lm78.c
drivers/hwmon/w83781d.c
drivers/ieee1394/ieee1394_core.c
drivers/ieee1394/ohci1394.c
drivers/media/dvb/b2c2/flexcop-i2c.c
drivers/media/video/cx88/cx88-mpeg.c
drivers/media/video/ivtv/ivtv-ioctl.c
drivers/media/video/pwc/pwc-if.c
drivers/mtd/Makefile
drivers/mtd/mtdpart.c
drivers/mtd/mtdsuper.c
drivers/net/forcedeth.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/bcm43xx/bcm43xx_main.h
drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c
drivers/scsi/3w-9xxx.c
drivers/usb/core/driver.c
fs/afs/mntpt.c
fs/ext3/namei.c
fs/ext4/namei.c
fs/jffs2/fs.c
fs/locks.c
fs/nfs/super.c
fs/splice.c
include/linux/Kbuild
init/Kconfig
kernel/futex_compat.c
kernel/signal.c
kernel/sys.c
net/8021q/vlan_dev.c
net/bridge/br_netfilter.c
net/core/datagram.c
net/core/pktgen.c
net/decnet/dn_dev.c
net/ipv4/ah4.c
net/ipv4/devinet.c
net/ipv4/inet_diag.c
net/ipv4/tcp_input.c
net/ipv6/addrconf.c
net/ipv6/ip6_output.c
net/ipv6/ndisc.c
net/ipv6/raw.c
net/sunrpc/svcsock.c
scripts/kconfig/conf.c

index 4820366..6cb3080 100644 (file)
@@ -56,7 +56,7 @@ syntax();
 
 sub sp8870 {
     my $sourcefile = "tt_Premium_217g.zip";
-    my $url = "http://www.technotrend.de/new/217g/$sourcefile";
+    my $url = "http://www.softwarepatch.pl/9999ccd06a4813cb827dbb0005071c71/$sourcefile";
     my $hash = "53970ec17a538945a6d8cb608a7b3899";
     my $outfile = "dvb-fe-sp8870.fw";
     my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
@@ -110,21 +110,21 @@ sub tda10045 {
 }
 
 sub tda10046 {
-    my $sourcefile = "tt_budget_217g.zip";
-    my $url = "http://www.technotrend.de/new/217g/$sourcefile";
-    my $hash = "6a7e1e2f2644b162ff0502367553c72d";
-    my $outfile = "dvb-fe-tda10046.fw";
-    my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
+       my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip";
+       my $url = "http://technotrend-online.com/download/software/219/$sourcefile";
+       my $hash = "6a7e1e2f2644b162ff0502367553c72d";
+       my $outfile = "dvb-fe-tda10046.fw";
+       my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
 
-    checkstandard();
+       checkstandard();
 
-    wgetfile($sourcefile, $url);
-    unzip($sourcefile, $tmpdir);
-    extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp");
-    verify("$tmpdir/fwtmp", $hash);
-    copy("$tmpdir/fwtmp", $outfile);
+       wgetfile($sourcefile, $url);
+       unzip($sourcefile, $tmpdir);
+       extract("$tmpdir/TT_PCI_2.19h_28_11_2006/software/OEM/PCI/App/ttlcdacc.dll", 0x65389, 24478, "$tmpdir/fwtmp");
+       verify("$tmpdir/fwtmp", $hash);
+       copy("$tmpdir/fwtmp", $outfile);
 
-    $outfile;
+       $outfile;
 }
 
 sub tda10046lifeview {
index 6e2f035..87c474d 100644 (file)
@@ -83,7 +83,7 @@ void flush_fp_to_thread(struct task_struct *tsk)
                         */
                        BUG_ON(tsk != current);
 #endif
-                       giveup_fpu(current);
+                       giveup_fpu(tsk);
                }
                preempt_enable();
        }
@@ -143,7 +143,7 @@ void flush_altivec_to_thread(struct task_struct *tsk)
 #ifdef CONFIG_SMP
                        BUG_ON(tsk != current);
 #endif
-                       giveup_altivec(current);
+                       giveup_altivec(tsk);
                }
                preempt_enable();
        }
@@ -182,7 +182,7 @@ void flush_spe_to_thread(struct task_struct *tsk)
 #ifdef CONFIG_SMP
                        BUG_ON(tsk != current);
 #endif
-                       giveup_spe(current);
+                       giveup_spe(tsk);
                }
                preempt_enable();
        }
index 3bc136a..154f10e 100644 (file)
@@ -751,7 +751,7 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
 {
        struct device_node *child;
        const u32 *reg;
-       int reglen, devfn;
+       int reglen, devfn, prev_devfn;
        struct pci_dev *dev;
 
        if (ofpci_verbose)
@@ -759,14 +759,25 @@ static void __devinit pci_of_scan_bus(struct pci_pbm_info *pbm,
                       node->full_name, bus->number);
 
        child = NULL;
+       prev_devfn = -1;
        while ((child = of_get_next_child(node, child)) != NULL) {
                if (ofpci_verbose)
                        printk("  * %s\n", child->full_name);
                reg = of_get_property(child, "reg", &reglen);
                if (reg == NULL || reglen < 20)
                        continue;
+
                devfn = (reg[0] >> 8) & 0xff;
 
+               /* This is a workaround for some device trees
+                * which list PCI devices twice.  On the V100
+                * for example, device number 3 is listed twice.
+                * Once as "pm" and once again as "lomp".
+                */
+               if (devfn == prev_devfn)
+                       continue;
+               prev_devfn = devfn;
+
                /* create a new pci_dev for this device */
                dev = of_create_pci_dev(pbm, child, bus, devfn, 0);
                if (!dev)
index c99b463..4369ff2 100644 (file)
@@ -1081,12 +1081,6 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
                 */
                return;
 
-       if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
-               printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
-                      __FUNCTION__, tag);
-               return;
-       }
-
        list_del_init(&rq->queuelist);
        rq->cmd_flags &= ~REQ_QUEUED;
        rq->tag = -1;
@@ -1096,6 +1090,13 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
                       __FUNCTION__, tag);
 
        bqt->tag_index[tag] = NULL;
+
+       if (unlikely(!test_and_clear_bit(tag, bqt->tag_map))) {
+               printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
+                      __FUNCTION__, tag);
+               return;
+       }
+
        bqt->busy--;
 }
 
index 8edf40c..cce9236 100644 (file)
@@ -59,11 +59,13 @@ static inline void blkcipher_unmap_dst(struct blkcipher_walk *walk)
        scatterwalk_unmap(walk->dst.virt.addr, 1);
 }
 
+/* Get a spot of the specified length that does not straddle a page.
+ * The caller needs to ensure that there is enough space for this operation.
+ */
 static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len)
 {
-       if (offset_in_page(start + len) < len)
-               return (u8 *)((unsigned long)(start + len) & PAGE_MASK);
-       return start;
+       u8 *end_page = (u8 *)(((unsigned long)(start + len - 1)) & PAGE_MASK);
+       return start > end_page ? start : end_page;
 }
 
 static inline unsigned int blkcipher_done_slow(struct crypto_blkcipher *tfm,
@@ -155,7 +157,8 @@ static inline int blkcipher_next_slow(struct blkcipher_desc *desc,
        if (walk->buffer)
                goto ok;
 
-       n = bsize * 2 + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
+       n = bsize * 3 - (alignmask + 1) +
+           (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
        walk->buffer = kmalloc(n, GFP_ATOMIC);
        if (!walk->buffer)
                return blkcipher_walk_done(desc, walk, -ENOMEM);
index 1da64b4..8cc9492 100644 (file)
@@ -51,6 +51,65 @@ ACPI_MODULE_NAME("tbutils")
 static acpi_physical_address
 acpi_tb_get_root_table_entry(u8 * table_entry,
                             acpi_native_uint table_entry_size);
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_tb_check_xsdt
+ *
+ * PARAMETERS:  address                    - Pointer to the XSDT
+ *
+ * RETURN:      status
+ *             AE_OK - XSDT is okay
+ *             AE_NO_MEMORY - can't map XSDT
+ *             AE_INVALID_TABLE_LENGTH - invalid table length
+ *             AE_NULL_ENTRY - XSDT has NULL entry
+ *
+ * DESCRIPTION: validate XSDT
+******************************************************************************/
+
+static acpi_status
+acpi_tb_check_xsdt(acpi_physical_address address)
+{
+       struct acpi_table_header *table;
+       u32 length;
+       u64 xsdt_entry_address;
+       u8 *table_entry;
+       u32 table_count;
+       int i;
+
+       table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
+       if (!table)
+               return AE_NO_MEMORY;
+
+       length = table->length;
+       acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
+       if (length < sizeof(struct acpi_table_header))
+               return AE_INVALID_TABLE_LENGTH;
+
+       table = acpi_os_map_memory(address, length);
+       if (!table)
+               return AE_NO_MEMORY;
+
+       /* Calculate the number of tables described in XSDT */
+       table_count =
+               (u32) ((table->length -
+               sizeof(struct acpi_table_header)) / sizeof(u64));
+       table_entry =
+               ACPI_CAST_PTR(u8, table) + sizeof(struct acpi_table_header);
+       for (i = 0; i < table_count; i++) {
+               ACPI_MOVE_64_TO_64(&xsdt_entry_address, table_entry);
+               if (!xsdt_entry_address) {
+                       /* XSDT has NULL entry */
+                       break;
+               }
+               table_entry += sizeof(u64);
+       }
+       acpi_os_unmap_memory(table, length);
+
+       if (i < table_count)
+               return AE_NULL_ENTRY;
+       else
+               return AE_OK;
+}
 
 /*******************************************************************************
  *
@@ -341,6 +400,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
        u32 table_count;
        struct acpi_table_header *table;
        acpi_physical_address address;
+       acpi_physical_address rsdt_address;
        u32 length;
        u8 *table_entry;
        acpi_status status;
@@ -369,6 +429,8 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
                 */
                address = (acpi_physical_address) rsdp->xsdt_physical_address;
                table_entry_size = sizeof(u64);
+               rsdt_address = (acpi_physical_address)
+                                       rsdp->rsdt_physical_address;
        } else {
                /* Root table is an RSDT (32-bit physical addresses) */
 
@@ -382,6 +444,15 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
         */
        acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
 
+       if (table_entry_size == sizeof(u64)) {
+               if (acpi_tb_check_xsdt(address) == AE_NULL_ENTRY) {
+                       /* XSDT has NULL entry, RSDT is used */
+                       address = rsdt_address;
+                       table_entry_size = sizeof(u32);
+                       ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry,"
+                                       "using RSDT"));
+               }
+       }
        /* Map the RSDT/XSDT table header to get the full table length */
 
        table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
index 92bf868..84d6aa5 100644 (file)
@@ -17,8 +17,8 @@
 */
 
 
-#define DAC960_DriverVersion                   "2.5.48"
-#define DAC960_DriverDate                      "14 May 2006"
+#define DAC960_DriverVersion                   "2.5.49"
+#define DAC960_DriverDate                      "21 Aug 2007"
 
 
 #include <linux/module.h>
@@ -31,6 +31,7 @@
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/blkpg.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
@@ -1165,9 +1166,9 @@ static bool DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
   int i;
 
   
-  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask))
+  if (pci_set_dma_mask(Controller->PCIDevice, DMA_32BIT_MASK))
        return DAC960_Failure(Controller, "DMA mask out of range");
-  Controller->BounceBufferLimit = DAC690_V1_PciDmaMask;
+  Controller->BounceBufferLimit = DMA_32BIT_MASK;
 
   if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) {
     CommandMailboxesSize =  0;
@@ -1368,9 +1369,12 @@ static bool DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
   dma_addr_t   CommandMailboxDMA;
   DAC960_V2_CommandStatus_T CommandStatus;
 
-  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V2_PciDmaMask))
-       return DAC960_Failure(Controller, "DMA mask out of range");
-  Controller->BounceBufferLimit = DAC690_V2_PciDmaMask;
+       if (!pci_set_dma_mask(Controller->PCIDevice, DMA_64BIT_MASK))
+               Controller->BounceBufferLimit = DMA_64BIT_MASK;
+       else if (!pci_set_dma_mask(Controller->PCIDevice, DMA_32BIT_MASK))
+               Controller->BounceBufferLimit = DMA_32BIT_MASK;
+       else
+               return DAC960_Failure(Controller, "DMA mask out of range");
 
   /* This is a temporary dma mapping, used only in the scope of this function */
   CommandMailbox = pci_alloc_consistent(PCI_Device,
index f5e2436..85fa9bb 100644 (file)
 #define DAC960_V2_MaxPhysicalDevices           272
 
 /*
-  Define the pci dma mask supported by DAC960 V1 and V2 Firmware Controlers
- */
-
-#define DAC690_V1_PciDmaMask   0xffffffff
-#define DAC690_V2_PciDmaMask   0xffffffffffffffffULL
-
-/*
   Define a 32/64 bit I/O Address data type.
 */
 
index 05a5ff1..f1cd9d3 100644 (file)
@@ -1934,14 +1934,12 @@ static int pci_suspend(struct pci_dev *pdev, pm_message_t state)
        free_irq(pdev->irq, ohci);
        err = pci_save_state(pdev);
        if (err) {
-               fw_error("pci_save_state failed with %d", err);
+               fw_error("pci_save_state failed with %d\n", err);
                return err;
        }
        err = pci_set_power_state(pdev, pci_choose_state(pdev, state));
-       if (err) {
-               fw_error("pci_set_power_state failed with %d", err);
-               return err;
-       }
+       if (err)
+               fw_error("pci_set_power_state failed with %d\n", err);
 
        return 0;
 }
@@ -1955,7 +1953,7 @@ static int pci_resume(struct pci_dev *pdev)
        pci_restore_state(pdev);
        err = pci_enable_device(pdev);
        if (err) {
-               fw_error("pci_enable_device failed with %d", err);
+               fw_error("pci_enable_device failed with %d\n", err);
                return err;
        }
 
index 9fb572f..3507113 100644 (file)
@@ -882,7 +882,7 @@ static int __init lm78_isa_device_add(unsigned short address)
 {
        struct resource res = {
                .start  = address,
-               .end    = address + LM78_EXTENT,
+               .end    = address + LM78_EXTENT - 1,
                .name   = "lm78",
                .flags  = IORESOURCE_IO,
        };
index c95909c..dcc941a 100644 (file)
@@ -1746,7 +1746,7 @@ w83781d_isa_device_add(unsigned short address)
 {
        struct resource res = {
                .start  = address,
-               .end    = address + W83781D_EXTENT,
+               .end    = address + W83781D_EXTENT - 1,
                .name   = "w83781d",
                .flags  = IORESOURCE_IO,
        };
index 8f71b6a..ac07a05 100644 (file)
@@ -1279,7 +1279,7 @@ static void __exit ieee1394_cleanup(void)
        unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
 }
 
-fs_initcall(ieee1394_init); /* same as ohci1394 */
+module_init(ieee1394_init);
 module_exit(ieee1394_cleanup);
 
 /* Exported symbols */
index 5dadfd2..e65760f 100644 (file)
@@ -3773,7 +3773,5 @@ static int __init ohci1394_init(void)
        return pci_register_driver(&ohci1394_pci_driver);
 }
 
-/* Register before most other device drivers.
- * Useful for remote debugging via physical DMA, e.g. using firescope. */
-fs_initcall(ohci1394_init);
+module_init(ohci1394_init);
 module_exit(ohci1394_cleanup);
index 02a0ea6..6bf858a 100644 (file)
@@ -135,6 +135,13 @@ static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs
        struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
        int i, ret = 0;
 
+       /* Some drivers use 1 byte or 0 byte reads as probes, which this
+        * driver doesn't support.  These probes will always fail, so this
+        * hack makes them always succeed.  If one knew how, it would of
+        * course be better to actually do the read.  */
+       if (num == 1 && msgs[0].flags == I2C_M_RD && msgs[0].len <= 1)
+               return 1;
+
        if (mutex_lock_interruptible(&fc->i2c_mutex))
                return -ERESTARTSYS;
 
index 543b05e..c36e2b7 100644 (file)
@@ -580,7 +580,7 @@ struct cx8802_dev * cx8802_get_device(struct inode *inode)
 
        list_for_each(list,&cx8802_devlist) {
                h = list_entry(list, struct cx8802_dev, devlist);
-               if (h->mpeg_dev->minor == minor)
+               if (h->mpeg_dev && h->mpeg_dev->minor == minor)
                        return h;
        }
 
index 57af176..dcfbaa9 100644 (file)
@@ -1183,6 +1183,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
                itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
                itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0;
                itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
+               ivtv_set_osd_alpha(itv);
                break;
        }
 
index cd3d001..5227978 100644 (file)
@@ -1243,7 +1243,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
                                PWC_ERROR("Failed to power down camera (%d)\n", i);
                }
                pdev->vopen--;
-               PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", i);
+               PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
        } else {
                pwc_cleanup(pdev);
                /* Free memory (don't set pdev to 0 just yet) */
index 451adcc..6d958a4 100644 (file)
@@ -3,9 +3,9 @@
 #
 
 # Core functionality.
+obj-$(CONFIG_MTD)              += mtd.o
 mtd-y                          := mtdcore.o mtdsuper.o
 mtd-$(CONFIG_MTD_PARTITIONS)   += mtdpart.o
-obj-$(CONFIG_MTD)              += $(mtd-y)
 
 obj-$(CONFIG_MTD_CONCAT)       += mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
index 9c62368..6174a97 100644 (file)
@@ -560,7 +560,3 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
 EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 EXPORT_SYMBOL_GPL(register_mtd_parser);
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
-MODULE_DESCRIPTION("Generic support for partitioning of MTD devices");
index aca3319..9b430f2 100644 (file)
@@ -70,6 +70,8 @@ static int get_sb_mtd_aux(struct file_system_type *fs_type, int flags,
        DEBUG(1, "MTDSB: New superblock for device %d (\"%s\")\n",
              mtd->index, mtd->name);
 
+       sb->s_flags = flags;
+
        ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
        if (ret < 0) {
                up_write(&sb->s_umount);
index 4a7b5f4..765fb75 100644 (file)
@@ -551,7 +551,7 @@ union ring_type {
 #define PHY_OUI_MARVELL        0x5043
 #define PHY_OUI_CICADA 0x03f1
 #define PHY_OUI_VITESSE        0x01c1
-#define PHY_OUI_REALTEK        0x01c1
+#define PHY_OUI_REALTEK        0x0732
 #define PHYID1_OUI_MASK        0x03ff
 #define PHYID1_OUI_SHFT        6
 #define PHYID2_OUI_MASK        0xfc00
index ef6b253..dadee85 100644 (file)
@@ -3183,6 +3183,9 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
        unsigned long orig_trans_start = 0;
 
        mutex_lock(&bcm->mutex);
+       /* keep from doing and rearming periodic work if shutting down */
+       if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT)
+               goto unlock_mutex;
        if (unlikely(bcm->periodic_state % 60 == 0)) {
                /* Periodic work will take a long time, so we want it to
                 * be preemtible.
@@ -3228,14 +3231,10 @@ static void bcm43xx_periodic_work_handler(struct work_struct *work)
        mmiowb();
        bcm->periodic_state++;
        spin_unlock_irqrestore(&bcm->irq_lock, flags);
+unlock_mutex:
        mutex_unlock(&bcm->mutex);
 }
 
-void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm)
-{
-       cancel_rearming_delayed_work(&bcm->periodic_work);
-}
-
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm)
 {
        struct delayed_work *work = &bcm->periodic_work;
@@ -3285,6 +3284,14 @@ static int bcm43xx_rng_init(struct bcm43xx_private *bcm)
        return err;
 }
 
+void bcm43xx_cancel_work(struct bcm43xx_private *bcm)
+{
+       /* The system must be unlocked when this routine is entered.
+        * If not, the next 2 steps may deadlock */
+       cancel_work_sync(&bcm->restart_work);
+       cancel_rearming_delayed_work(&bcm->periodic_work);
+}
+
 static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm)
 {
        int ret = 0;
@@ -3321,7 +3328,12 @@ static void bcm43xx_free_board(struct bcm43xx_private *bcm)
 {
        bcm43xx_rng_exit(bcm);
        bcm43xx_sysfs_unregister(bcm);
-       bcm43xx_periodic_tasks_delete(bcm);
+
+       mutex_lock(&(bcm)->mutex);
+       bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT);
+       mutex_unlock(&(bcm)->mutex);
+
+       bcm43xx_cancel_work(bcm);
 
        mutex_lock(&(bcm)->mutex);
        bcm43xx_shutdown_all_wireless_cores(bcm);
@@ -4018,7 +4030,7 @@ static int bcm43xx_net_stop(struct net_device *net_dev)
        err = bcm43xx_disable_interrupts_sync(bcm);
        assert(!err);
        bcm43xx_free_board(bcm);
-       flush_scheduled_work();
+       bcm43xx_cancel_work(bcm);
 
        return 0;
 }
@@ -4150,9 +4162,9 @@ static void bcm43xx_chip_reset(struct work_struct *work)
        struct bcm43xx_phyinfo *phy;
        int err = -ENODEV;
 
+       bcm43xx_cancel_work(bcm);
        mutex_lock(&(bcm)->mutex);
        if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) {
-               bcm43xx_periodic_tasks_delete(bcm);
                phy = bcm43xx_current_phy(bcm);
                err = bcm43xx_select_wireless_core(bcm, phy->type);
                if (!err)
index c8f3c53..14cfbeb 100644 (file)
@@ -122,7 +122,7 @@ void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy);
 void bcm43xx_mac_suspend(struct bcm43xx_private *bcm);
 void bcm43xx_mac_enable(struct bcm43xx_private *bcm);
 
-void bcm43xx_periodic_tasks_delete(struct bcm43xx_private *bcm);
+void bcm43xx_cancel_work(struct bcm43xx_private *bcm);
 void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm);
 
 void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason);
index c71b998..8ab5f93 100644 (file)
@@ -327,7 +327,7 @@ static ssize_t bcm43xx_attr_phymode_store(struct device *dev,
                goto out;
        }
 
-       bcm43xx_periodic_tasks_delete(bcm);
+       bcm43xx_cancel_work(bcm);
        mutex_lock(&(bcm)->mutex);
        err = bcm43xx_select_wireless_core(bcm, phytype);
        if (!err)
index 76c0909..e957bbb 100644 (file)
@@ -4,7 +4,7 @@
    Written By: Adam Radford <linuxraid@amcc.com>
    Modifications By: Tom Couch <linuxraid@amcc.com>
 
-   Copyright (C) 2004-2006 Applied Micro Circuits Corporation.
+   Copyright (C) 2004-2007 Applied Micro Circuits Corporation.
 
    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
@@ -69,6 +69,7 @@
    2.26.02.008 - Free irq handler in __twa_shutdown().
                  Serialize reset code.
                  Add support for 9650SE controllers.
+   2.26.02.009 - Fix dma mask setting to fallback to 32-bit if 64-bit fails.
 */
 
 #include <linux/module.h>
@@ -92,7 +93,7 @@
 #include "3w-9xxx.h"
 
 /* Globals */
-#define TW_DRIVER_VERSION "2.26.02.008"
+#define TW_DRIVER_VERSION "2.26.02.009"
 static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
 static unsigned int twa_device_extension_count;
 static int twa_major = -1;
@@ -2002,11 +2003,14 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id
 
        pci_set_master(pdev);
 
-       retval = pci_set_dma_mask(pdev, sizeof(dma_addr_t) > 4 ? DMA_64BIT_MASK : DMA_32BIT_MASK);
-       if (retval) {
-               TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
-               goto out_disable_device;
-       }
+       if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)
+           || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)
+                   || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+                       TW_PRINTK(host, TW_DRIVER, 0x23, "Failed to set dma mask");
+                       retval = -ENODEV;
+                       goto out_disable_device;
+               }
 
        host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
        if (!host) {
index 2619986..61699f7 100644 (file)
@@ -58,7 +58,7 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
        dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
 
        spin_lock(&dynids->lock);
-       list_add_tail(&dynids->list, &dynid->node);
+       list_add_tail(&dynid->node, &dynids->list);
        spin_unlock(&dynids->lock);
 
        if (get_driver(driver)) {
index a3684dc..6f8c96f 100644 (file)
@@ -235,8 +235,8 @@ static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd)
        err = do_add_mount(newmnt, nd, MNT_SHRINKABLE, &afs_vfsmounts);
        switch (err) {
        case 0:
-               mntput(nd->mnt);
                dput(nd->dentry);
+               mntput(nd->mnt);
                nd->mnt = newmnt;
                nd->dentry = dget(newmnt->mnt_root);
                schedule_delayed_work(&afs_mntpt_expiry_timer,
index c7198af..e188164 100644 (file)
@@ -141,7 +141,8 @@ struct dx_frame
 struct dx_map_entry
 {
        u32 hash;
-       u32 offs;
+       u16 offs;
+       u16 size;
 };
 
 #ifdef CONFIG_EXT3_INDEX
@@ -380,13 +381,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        entries = (struct dx_entry *) (((char *)&root->info) +
                                       root->info.info_length);
-       assert(dx_get_limit(entries) == dx_root_limit(dir,
-                                                     root->info.info_length));
+
+       if (dx_get_limit(entries) != dx_root_limit(dir,
+                                                  root->info.info_length)) {
+               ext3_warning(dir->i_sb, __FUNCTION__,
+                            "dx entry: limit != root limit");
+               brelse(bh);
+               *err = ERR_BAD_DX_DIR;
+               goto fail;
+       }
+
        dxtrace (printk("Look up %x", hash));
        while (1)
        {
                count = dx_get_count(entries);
-               assert (count && count <= dx_get_limit(entries));
+               if (!count || count > dx_get_limit(entries)) {
+                       ext3_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: no count or count > limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
+
                p = entries + 1;
                q = entries + count - 1;
                while (p <= q)
@@ -424,8 +440,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
                if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
                        goto fail2;
                at = entries = ((struct dx_node *) bh->b_data)->entries;
-               assert (dx_get_limit(entries) == dx_node_limit (dir));
+               if (dx_get_limit(entries) != dx_node_limit (dir)) {
+                       ext3_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: limit != node limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
                frame++;
+               frame->bh = NULL;
        }
 fail2:
        while (frame >= frame_in) {
@@ -433,6 +456,10 @@ fail2:
                frame--;
        }
 fail:
+       if (*err == ERR_BAD_DX_DIR)
+               ext3_warning(dir->i_sb, __FUNCTION__,
+                            "Corrupt dir inode %ld, running e2fsck is "
+                            "recommended.", dir->i_ino);
        return NULL;
 }
 
@@ -672,6 +699,10 @@ errout:
  * Directory block splitting, compacting
  */
 
+/*
+ * Create map of hash values, offsets, and sizes, stored at end of block.
+ * Returns number of entries mapped.
+ */
 static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
                        struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
 {
@@ -685,7 +716,8 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
                        ext3fs_dirhash(de->name, de->name_len, &h);
                        map_tail--;
                        map_tail->hash = h.hash;
-                       map_tail->offs = (u32) ((char *) de - base);
+                       map_tail->offs = (u16) ((char *) de - base);
+                       map_tail->size = le16_to_cpu(de->rec_len);
                        count++;
                        cond_resched();
                }
@@ -695,6 +727,7 @@ static int dx_make_map (struct ext3_dir_entry_2 *de, int size,
        return count;
 }
 
+/* Sort map by hash value */
 static void dx_sort_map (struct dx_map_entry *map, unsigned count)
 {
         struct dx_map_entry *p, *q, *top = map + count - 1;
@@ -1082,6 +1115,10 @@ static inline void ext3_set_de_type(struct super_block *sb,
 }
 
 #ifdef CONFIG_EXT3_INDEX
+/*
+ * Move count entries from end of map between two memory locations.
+ * Returns pointer to last entry moved.
+ */
 static struct ext3_dir_entry_2 *
 dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
 {
@@ -1100,6 +1137,10 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
        return (struct ext3_dir_entry_2 *) (to - rec_len);
 }
 
+/*
+ * Compact each dir entry in the range to the minimal rec_len.
+ * Returns pointer to last entry in range.
+ */
 static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
 {
        struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base;
@@ -1122,6 +1163,11 @@ static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size)
        return prev;
 }
 
+/*
+ * Split a full leaf block to make room for a new dir entry.
+ * Allocate a new block, and move entries so that they are approx. equally full.
+ * Returns pointer to de in block into which the new entry will be inserted.
+ */
 static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                        struct buffer_head **bh,struct dx_frame *frame,
                        struct dx_hash_info *hinfo, int *error)
@@ -1133,7 +1179,7 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        u32 hash2;
        struct dx_map_entry *map;
        char *data1 = (*bh)->b_data, *data2;
-       unsigned split;
+       unsigned split, move, size, i;
        struct ext3_dir_entry_2 *de = NULL, *de2;
        int     err = 0;
 
@@ -1161,8 +1207,19 @@ static struct ext3_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        count = dx_make_map ((struct ext3_dir_entry_2 *) data1,
                             blocksize, hinfo, map);
        map -= count;
-       split = count/2; // need to adjust to actual middle
        dx_sort_map (map, count);
+       /* Split the existing block in the middle, size-wise */
+       size = 0;
+       move = 0;
+       for (i = count-1; i >= 0; i--) {
+               /* is more than half of this entry in 2nd half of the block? */
+               if (size + map[i].size/2 > blocksize/2)
+                       break;
+               size += map[i].size;
+               move++;
+       }
+       /* map index at which we will split */
+       split = count - move;
        hash2 = map[split].hash;
        continued = hash2 == map[split - 1].hash;
        dxtrace(printk("Split block %i at %x, %i/%i\n",
index 2811e57..7bb8d7c 100644 (file)
@@ -140,7 +140,8 @@ struct dx_frame
 struct dx_map_entry
 {
        u32 hash;
-       u32 offs;
+       u16 offs;
+       u16 size;
 };
 
 #ifdef CONFIG_EXT4_INDEX
@@ -379,13 +380,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
 
        entries = (struct dx_entry *) (((char *)&root->info) +
                                       root->info.info_length);
-       assert(dx_get_limit(entries) == dx_root_limit(dir,
-                                                     root->info.info_length));
+
+       if (dx_get_limit(entries) != dx_root_limit(dir,
+                                                  root->info.info_length)) {
+               ext4_warning(dir->i_sb, __FUNCTION__,
+                            "dx entry: limit != root limit");
+               brelse(bh);
+               *err = ERR_BAD_DX_DIR;
+               goto fail;
+       }
+
        dxtrace (printk("Look up %x", hash));
        while (1)
        {
                count = dx_get_count(entries);
-               assert (count && count <= dx_get_limit(entries));
+               if (!count || count > dx_get_limit(entries)) {
+                       ext4_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: no count or count > limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
+
                p = entries + 1;
                q = entries + count - 1;
                while (p <= q)
@@ -423,8 +439,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
                if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
                        goto fail2;
                at = entries = ((struct dx_node *) bh->b_data)->entries;
-               assert (dx_get_limit(entries) == dx_node_limit (dir));
+               if (dx_get_limit(entries) != dx_node_limit (dir)) {
+                       ext4_warning(dir->i_sb, __FUNCTION__,
+                                    "dx entry: limit != node limit");
+                       brelse(bh);
+                       *err = ERR_BAD_DX_DIR;
+                       goto fail2;
+               }
                frame++;
+               frame->bh = NULL;
        }
 fail2:
        while (frame >= frame_in) {
@@ -432,6 +455,10 @@ fail2:
                frame--;
        }
 fail:
+       if (*err == ERR_BAD_DX_DIR)
+               ext4_warning(dir->i_sb, __FUNCTION__,
+                            "Corrupt dir inode %ld, running e2fsck is "
+                            "recommended.", dir->i_ino);
        return NULL;
 }
 
@@ -671,6 +698,10 @@ errout:
  * Directory block splitting, compacting
  */
 
+/*
+ * Create map of hash values, offsets, and sizes, stored at end of block.
+ * Returns number of entries mapped.
+ */
 static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
                        struct dx_hash_info *hinfo, struct dx_map_entry *map_tail)
 {
@@ -684,7 +715,8 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
                        ext4fs_dirhash(de->name, de->name_len, &h);
                        map_tail--;
                        map_tail->hash = h.hash;
-                       map_tail->offs = (u32) ((char *) de - base);
+                       map_tail->offs = (u16) ((char *) de - base);
+                       map_tail->size = le16_to_cpu(de->rec_len);
                        count++;
                        cond_resched();
                }
@@ -694,6 +726,7 @@ static int dx_make_map (struct ext4_dir_entry_2 *de, int size,
        return count;
 }
 
+/* Sort map by hash value */
 static void dx_sort_map (struct dx_map_entry *map, unsigned count)
 {
        struct dx_map_entry *p, *q, *top = map + count - 1;
@@ -1079,6 +1112,10 @@ static inline void ext4_set_de_type(struct super_block *sb,
 }
 
 #ifdef CONFIG_EXT4_INDEX
+/*
+ * Move count entries from end of map between two memory locations.
+ * Returns pointer to last entry moved.
+ */
 static struct ext4_dir_entry_2 *
 dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
 {
@@ -1097,6 +1134,10 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count)
        return (struct ext4_dir_entry_2 *) (to - rec_len);
 }
 
+/*
+ * Compact each dir entry in the range to the minimal rec_len.
+ * Returns pointer to last entry in range.
+ */
 static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
 {
        struct ext4_dir_entry_2 *next, *to, *prev, *de = (struct ext4_dir_entry_2 *) base;
@@ -1119,6 +1160,11 @@ static struct ext4_dir_entry_2* dx_pack_dirents(char *base, int size)
        return prev;
 }
 
+/*
+ * Split a full leaf block to make room for a new dir entry.
+ * Allocate a new block, and move entries so that they are approx. equally full.
+ * Returns pointer to de in block into which the new entry will be inserted.
+ */
 static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
                        struct buffer_head **bh,struct dx_frame *frame,
                        struct dx_hash_info *hinfo, int *error)
@@ -1130,7 +1176,7 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        u32 hash2;
        struct dx_map_entry *map;
        char *data1 = (*bh)->b_data, *data2;
-       unsigned split;
+       unsigned split, move, size, i;
        struct ext4_dir_entry_2 *de = NULL, *de2;
        int     err = 0;
 
@@ -1158,8 +1204,19 @@ static struct ext4_dir_entry_2 *do_split(handle_t *handle, struct inode *dir,
        count = dx_make_map ((struct ext4_dir_entry_2 *) data1,
                             blocksize, hinfo, map);
        map -= count;
-       split = count/2; // need to adjust to actual middle
        dx_sort_map (map, count);
+       /* Split the existing block in the middle, size-wise */
+       size = 0;
+       move = 0;
+       for (i = count-1; i >= 0; i--) {
+               /* is more than half of this entry in 2nd half of the block? */
+               if (size + map[i].size/2 > blocksize/2)
+                       break;
+               size += map[i].size;
+               move++;
+       }
+       /* map index at which we will split */
+       split = count - move;
        hash2 = map[split].hash;
        continued = hash2 == map[split - 1].hash;
        dxtrace(printk("Split block %i at %x, %i/%i\n",
index 1d3b7a9..8bc727b 100644 (file)
@@ -627,7 +627,7 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
        struct inode *inode = OFNI_EDONI_2SFFJ(f);
        struct page *pg;
 
-       pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT,
+       pg = read_cache_page_async(inode->i_mapping, offset >> PAGE_CACHE_SHIFT,
                             (void *)jffs2_do_readpage_unlock, inode);
        if (IS_ERR(pg))
                return (void *)pg;
index 431a8b8..6428605 100644 (file)
@@ -786,7 +786,7 @@ find_conflict:
        if (request->fl_flags & FL_ACCESS)
                goto out;
        locks_copy_lock(new_fl, request);
-       locks_insert_lock(&inode->i_flock, new_fl);
+       locks_insert_lock(before, new_fl);
        new_fl = NULL;
        error = 0;
 
index ca20d3c..6a5bd0d 100644 (file)
@@ -181,8 +181,8 @@ void __exit unregister_nfs_fs(void)
                remove_shrinker(acl_shrinker);
 #ifdef CONFIG_NFS_V4
        unregister_filesystem(&nfs4_fs_type);
-       nfs_unregister_sysctl();
 #endif
+       nfs_unregister_sysctl();
        unregister_filesystem(&nfs_fs_type);
 }
 
index c51636e..a47daa5 100644 (file)
@@ -1011,7 +1011,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
                max_read_len = min(len, (size_t)(PIPE_BUFFERS*PAGE_SIZE));
 
                ret = do_splice_to(in, ppos, pipe, max_read_len, flags);
-               if (unlikely(ret < 0))
+               if (unlikely(ret <= 0))
                        goto out_release;
 
                read_len = ret;
@@ -1023,7 +1023,7 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
                 */
                ret = do_splice_from(pipe, out, &out_off, read_len,
                                     flags & ~SPLICE_F_NONBLOCK);
-               if (unlikely(ret < 0))
+               if (unlikely(ret <= 0))
                        goto out_release;
 
                bytes += ret;
index b9c4d9e..d86711d 100644 (file)
@@ -7,6 +7,7 @@ header-y += raid/
 header-y += spi/
 header-y += sunrpc/
 header-y += tc_act/
+header-y += tc_ematch/
 header-y += netfilter/
 header-y += netfilter_arp/
 header-y += netfilter_bridge/
index 77160bf..8624c94 100644 (file)
@@ -509,6 +509,7 @@ config SIGNALFD
 config TIMERFD
        bool "Enable timerfd() system call" if EMBEDDED
        depends on ANON_INODES
+       depends on BROKEN
        default y
        help
          Enable the timerfd() system call that allows to receive timer
index 92af955..7e52eb0 100644 (file)
@@ -61,10 +61,10 @@ void compat_exit_robust_list(struct task_struct *curr)
        if (fetch_robust_entry(&upending, &pending,
                               &head->list_op_pending, &pip))
                return;
-       if (upending)
+       if (pending)
                handle_futex_death((void __user *)pending + futex_offset, curr, pip);
 
-       while (entry != (struct robust_list *) &head->list) {
+       while (entry != (struct robust_list __user *) &head->list) {
                /*
                 * A pending lock might already be on the list, so
                 * dont process it twice:
index 67a9c66..7717ad4 100644 (file)
@@ -1259,20 +1259,19 @@ struct sigqueue *sigqueue_alloc(void)
 void sigqueue_free(struct sigqueue *q)
 {
        unsigned long flags;
+       spinlock_t *lock = &current->sighand->siglock;
+
        BUG_ON(!(q->flags & SIGQUEUE_PREALLOC));
        /*
         * If the signal is still pending remove it from the
-        * pending queue.
+        * pending queue. We must hold ->siglock while testing
+        * q->list to serialize with collect_signal().
         */
-       if (unlikely(!list_empty(&q->list))) {
-               spinlock_t *lock = &current->sighand->siglock;
-               read_lock(&tasklist_lock);
-               spin_lock_irqsave(lock, flags);
-               if (!list_empty(&q->list))
-                       list_del_init(&q->list);
-               spin_unlock_irqrestore(lock, flags);
-               read_unlock(&tasklist_lock);
-       }
+       spin_lock_irqsave(lock, flags);
+       if (!list_empty(&q->list))
+               list_del_init(&q->list);
+       spin_unlock_irqrestore(lock, flags);
+
        q->flags &= ~SIGQUEUE_PREALLOC;
        __sigqueue_free(q);
 }
index 872271c..28e8364 100644 (file)
@@ -1428,7 +1428,6 @@ asmlinkage long sys_times(struct tms __user * tbuf)
  * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
  * LBT 04.03.94
  */
-
 asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
 {
        struct task_struct *p;
@@ -1456,7 +1455,7 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
        if (!thread_group_leader(p))
                goto out;
 
-       if (p->real_parent == group_leader) {
+       if (p->real_parent->tgid == group_leader->tgid) {
                err = -EPERM;
                if (task_session(p) != task_session(group_leader))
                        goto out;
index ec46084..0642694 100644 (file)
@@ -116,12 +116,22 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
                  struct packet_type* ptype, struct net_device *orig_dev)
 {
        unsigned char *rawp = NULL;
-       struct vlan_hdr *vhdr = (struct vlan_hdr *)(skb->data);
+       struct vlan_hdr *vhdr;
        unsigned short vid;
        struct net_device_stats *stats;
        unsigned short vlan_TCI;
        __be16 proto;
 
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               return -1;
+
+       if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) {
+               kfree_skb(skb);
+               return -1;
+       }
+
+       vhdr = (struct vlan_hdr *)(skb->data);
+
        /* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
        vlan_TCI = ntohs(vhdr->h_vlan_TCI);
 
index fa77987..3ee2022 100644 (file)
@@ -509,8 +509,14 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
                                      int (*okfn)(struct sk_buff *))
 {
        struct iphdr *iph;
-       __u32 len;
        struct sk_buff *skb = *pskb;
+       __u32 len = nf_bridge_encap_header_len(skb);
+
+       if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
+               return NF_STOLEN;
+
+       if (unlikely(!pskb_may_pull(skb, len)))
+               goto out;
 
        if (skb->protocol == htons(ETH_P_IPV6) || IS_VLAN_IPV6(skb) ||
            IS_PPPOE_IPV6(skb)) {
@@ -518,8 +524,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
                if (!brnf_call_ip6tables)
                        return NF_ACCEPT;
 #endif
-               if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
-                       goto out;
                nf_bridge_pull_encap_header_rcsum(skb);
                return br_nf_pre_routing_ipv6(hook, skb, in, out, okfn);
        }
@@ -532,8 +536,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
            !IS_PPPOE_IP(skb))
                return NF_ACCEPT;
 
-       if ((skb = skb_share_check(*pskb, GFP_ATOMIC)) == NULL)
-               goto out;
        nf_bridge_pull_encap_header_rcsum(skb);
 
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
index cb056f4..029b93e 100644 (file)
@@ -450,6 +450,9 @@ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
        __wsum csum;
        int chunk = skb->len - hlen;
 
+       if (!chunk)
+               return 0;
+
        /* Skip filled elements.
         * Pretty silly, look at memcpy_toiovec, though 8)
         */
index 9cd3a1c..33190c3 100644 (file)
  *
  * 802.1Q/Q-in-Q support by Francesco Fondelli (FF) <francesco.fondelli@gmail.com>
  *
+ * Fixed src_mac command to set source mac of packet to value specified in
+ * command by Adit Ranadive <adit.262@gmail.com>
+ *
  */
 #include <linux/sys.h>
 #include <linux/types.h>
@@ -1415,8 +1418,11 @@ static ssize_t pktgen_if_write(struct file *file,
        }
        if (!strcmp(name, "src_mac")) {
                char *v = valstr;
+               unsigned char old_smac[ETH_ALEN];
                unsigned char *m = pkt_dev->src_mac;
 
+               memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN);
+
                len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
                if (len < 0) {
                        return len;
@@ -1445,6 +1451,10 @@ static ssize_t pktgen_if_write(struct file *file,
                        }
                }
 
+               /* Set up Src MAC */
+               if (compare_ether_addr(old_smac, pkt_dev->src_mac))
+                       memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN);
+
                sprintf(pg_result, "OK: srcmac");
                return count;
        }
index ab41c18..d46e453 100644 (file)
@@ -815,7 +815,7 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
                for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
                     ifa = ifa->ifa_next, dn_idx++) {
                        if (dn_idx < skip_naddr)
-                               goto cont;
+                               continue;
 
                        if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
                                              cb->nlh->nlmsg_seq, RTM_NEWADDR,
index 6da8ff5..c79a24e 100644 (file)
@@ -46,7 +46,7 @@ static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr)
                        memcpy(daddr, optptr+optlen-4, 4);
                        /* Fall through */
                default:
-                       memset(optptr+2, 0, optlen-2);
+                       memset(optptr, 0, optlen);
                }
                l -= optlen;
                optptr += optlen;
index abf6352..0dcc245 100644 (file)
@@ -1194,7 +1194,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
                for (ifa = in_dev->ifa_list, ip_idx = 0; ifa;
                     ifa = ifa->ifa_next, ip_idx++) {
                        if (ip_idx < s_ip_idx)
-                               goto cont;
+                               continue;
                        if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
                                             cb->nlh->nlmsg_seq,
                                             RTM_NEWADDR, NLM_F_MULTI) <= 0)
index dbeacd8..def007e 100644 (file)
@@ -836,12 +836,16 @@ static int inet_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        return inet_diag_get_exact(skb, nlh);
 }
 
+static DEFINE_MUTEX(inet_diag_mutex);
+
 static void inet_diag_rcv(struct sock *sk, int len)
 {
        unsigned int qlen = 0;
 
        do {
+               mutex_lock(&inet_diag_mutex);
                netlink_run_queue(sk, &qlen, &inet_diag_rcv_msg);
+               mutex_unlock(&inet_diag_mutex);
        } while (qlen);
 }
 
index 13abf4e..5bfda70 100644 (file)
@@ -102,11 +102,14 @@ int sysctl_tcp_abc __read_mostly;
 #define FLAG_DATA_LOST         0x80 /* SACK detected data lossage.             */
 #define FLAG_SLOWPATH          0x100 /* Do not skip RFC checks for window update.*/
 #define FLAG_ONLY_ORIG_SACKED  0x200 /* SACKs only non-rexmit sent before RTO */
+#define FLAG_SND_UNA_ADVANCED  0x400 /* Snd_una was changed (!= FLAG_DATA_ACKED) */
+#define FLAG_DSACKING_ACK      0x800 /* SACK blocks contained DSACK info */
 
 #define FLAG_ACKED             (FLAG_DATA_ACKED|FLAG_SYN_ACKED)
 #define FLAG_NOT_DUP           (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED)
 #define FLAG_CA_ALERT          (FLAG_DATA_SACKED|FLAG_ECE)
 #define FLAG_FORWARD_PROGRESS  (FLAG_ACKED|FLAG_DATA_SACKED)
+#define FLAG_ANY_PROGRESS      (FLAG_FORWARD_PROGRESS|FLAG_SND_UNA_ADVANCED)
 
 #define IsReno(tp) ((tp)->rx_opt.sack_ok == 0)
 #define IsFack(tp) ((tp)->rx_opt.sack_ok & 2)
@@ -964,12 +967,14 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
 
        /* Check for D-SACK. */
        if (before(ntohl(sp[0].start_seq), TCP_SKB_CB(ack_skb)->ack_seq)) {
+               flag |= FLAG_DSACKING_ACK;
                found_dup_sack = 1;
                tp->rx_opt.sack_ok |= 4;
                NET_INC_STATS_BH(LINUX_MIB_TCPDSACKRECV);
        } else if (num_sacks > 1 &&
                        !after(ntohl(sp[0].end_seq), ntohl(sp[1].end_seq)) &&
                        !before(ntohl(sp[0].start_seq), ntohl(sp[1].start_seq))) {
+               flag |= FLAG_DSACKING_ACK;
                found_dup_sack = 1;
                tp->rx_opt.sack_ok |= 4;
                NET_INC_STATS_BH(LINUX_MIB_TCPDSACKOFORECV);
@@ -1856,7 +1861,7 @@ static void tcp_cwnd_down(struct sock *sk, int flag)
        struct tcp_sock *tp = tcp_sk(sk);
        int decr = tp->snd_cwnd_cnt + 1;
 
-       if ((flag&FLAG_FORWARD_PROGRESS) ||
+       if ((flag&(FLAG_ANY_PROGRESS|FLAG_DSACKING_ACK)) ||
            (IsReno(tp) && !(flag&FLAG_NOT_DUP))) {
                tp->snd_cwnd_cnt = decr&1;
                decr >>= 1;
@@ -2112,10 +2117,9 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
-       int is_dupack = (tp->snd_una == prior_snd_una &&
-                        (!(flag&FLAG_NOT_DUP) ||
-                         ((flag&FLAG_DATA_SACKED) &&
-                          (tp->fackets_out > tp->reordering))));
+       int is_dupack = !(flag&(FLAG_SND_UNA_ADVANCED|FLAG_NOT_DUP));
+       int do_lost = is_dupack || ((flag&FLAG_DATA_SACKED) &&
+                                   (tp->fackets_out > tp->reordering));
 
        /* Some technical things:
         * 1. Reno does not count dupacks (sacked_out) automatically. */
@@ -2199,7 +2203,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
                        int acked = prior_packets - tp->packets_out;
                        if (IsReno(tp))
                                tcp_remove_reno_sacks(sk, acked);
-                       is_dupack = tcp_try_undo_partial(sk, acked);
+                       do_lost = tcp_try_undo_partial(sk, acked);
                }
                break;
        case TCP_CA_Loss:
@@ -2264,7 +2268,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
                tcp_set_ca_state(sk, TCP_CA_Recovery);
        }
 
-       if (is_dupack || tcp_head_timedout(sk))
+       if (do_lost || tcp_head_timedout(sk))
                tcp_update_scoreboard(sk);
        tcp_cwnd_down(sk, flag);
        tcp_xmit_retransmit_queue(sk);
@@ -2774,6 +2778,9 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
        if (before(ack, prior_snd_una))
                goto old_ack;
 
+       if (after(ack, prior_snd_una))
+               flag |= FLAG_SND_UNA_ADVANCED;
+
        if (sysctl_tcp_abc) {
                if (icsk->icsk_ca_state < TCP_CA_CWR)
                        tp->bytes_acked += ack - prior_snd_una;
index 9342bb9..67b4032 100644 (file)
@@ -1021,7 +1021,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev,
                                hiscore.rule++;
                        }
                        if (ipv6_saddr_preferred(score.addr_type) ||
-                          (((ifa_result->flags &
+                          (((ifa->flags &
                            (IFA_F_DEPRECATED|IFA_F_OPTIMISTIC)) == 0))) {
                                score.attrs |= IPV6_SADDR_SCORE_PREFERRED;
                                if (!(hiscore.attrs & IPV6_SADDR_SCORE_PREFERRED)) {
index b9f9e93..4233a95 100644 (file)
@@ -1423,8 +1423,9 @@ void ip6_flush_pending_frames(struct sock *sk)
        struct sk_buff *skb;
 
        while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL) {
-               IP6_INC_STATS(ip6_dst_idev(skb->dst),
-                             IPSTATS_MIB_OUTDISCARDS);
+               if (skb->dst)
+                       IP6_INC_STATS(ip6_dst_idev(skb->dst),
+                                     IPSTATS_MIB_OUTDISCARDS);
                kfree_skb(skb);
        }
 
index 0358e60..73a894a 100644 (file)
@@ -736,7 +736,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
                                 * so fail our DAD process
                                 */
                                addrconf_dad_failure(ifp);
-                               goto out;
+                               return;
                        } else {
                                /*
                                 * This is not a dad solicitation.
index a58459a..fc5cb83 100644 (file)
@@ -858,11 +858,10 @@ back_from_confirm:
                        ip6_flush_pending_frames(sk);
                else if (!(msg->msg_flags & MSG_MORE))
                        err = rawv6_push_pending_frames(sk, &fl, rp);
+               release_sock(sk);
        }
 done:
        dst_release(dst);
-       if (!inet->hdrincl)
-               release_sock(sk);
 out:
        fl6_sock_release(flowlabel);
        return err<0?err:len;
index 5baf48d..80a0091 100644 (file)
@@ -1090,7 +1090,8 @@ svc_tcp_accept(struct svc_sock *svsk)
                                                   serv->sv_name);
                                printk(KERN_NOTICE
                                       "%s: last TCP connect from %s\n",
-                                      serv->sv_name, buf);
+                                      serv->sv_name, __svc_print_addr(sin,
+                                                       buf, sizeof(buf)));
                        }
                        /*
                         * Always select the oldest socket. It's not fair,
@@ -1572,7 +1573,8 @@ svc_age_temp_sockets(unsigned long closure)
 
                if (!test_and_set_bit(SK_OLD, &svsk->sk_flags))
                        continue;
-               if (atomic_read(&svsk->sk_inuse) || test_bit(SK_BUSY, &svsk->sk_flags))
+               if (atomic_read(&svsk->sk_inuse) > 1
+                   || test_bit(SK_BUSY, &svsk->sk_flags))
                        continue;
                atomic_inc(&svsk->sk_inuse);
                list_move(le, &to_be_aged);
index 1199baf..45550d2 100644 (file)
@@ -64,7 +64,7 @@ static void check_stdin(void)
        }
 }
 
-static void conf_askvalue(struct symbol *sym, const char *def)
+static int conf_askvalue(struct symbol *sym, const char *def)
 {
        enum symbol_type type = sym_get_type(sym);
        tristate val;
@@ -79,7 +79,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
                printf("%s\n", def);
                line[0] = '\n';
                line[1] = 0;
-               return;
+               return 0;
        }
 
        switch (input_mode) {
@@ -89,23 +89,23 @@ static void conf_askvalue(struct symbol *sym, const char *def)
        case set_random:
                if (sym_has_value(sym)) {
                        printf("%s\n", def);
-                       return;
+                       return 0;
                }
                break;
        case ask_new:
        case ask_silent:
                if (sym_has_value(sym)) {
                        printf("%s\n", def);
-                       return;
+                       return 0;
                }
                check_stdin();
        case ask_all:
                fflush(stdout);
                fgets(line, 128, stdin);
-               return;
+               return 1;
        case set_default:
                printf("%s\n", def);
-               return;
+               return 1;
        default:
                break;
        }
@@ -115,7 +115,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
        case S_HEX:
        case S_STRING:
                printf("%s\n", def);
-               return;
+               return 1;
        default:
                ;
        }
@@ -166,6 +166,7 @@ static void conf_askvalue(struct symbol *sym, const char *def)
                break;
        }
        printf("%s", line);
+       return 1;
 }
 
 int conf_string(struct menu *menu)
@@ -179,7 +180,8 @@ int conf_string(struct menu *menu)
                def = sym_get_string_value(sym);
                if (sym_get_string_value(sym))
                        printf("[%s] ", def);
-               conf_askvalue(sym, def);
+               if (!conf_askvalue(sym, def))
+                       return 0;
                switch (line[0]) {
                case '\n':
                        break;
@@ -236,7 +238,8 @@ static int conf_sym(struct menu *menu)
                if (sym->help)
                        printf("/?");
                printf("] ");
-               conf_askvalue(sym, sym_get_string_value(sym));
+               if (!conf_askvalue(sym, sym_get_string_value(sym)))
+                       return 0;
                strip(line);
 
                switch (line[0]) {