diff --git a/debian/changelog b/debian/changelog index 5a89f300f..5b0dc5664 100644 --- a/debian/changelog +++ b/debian/changelog @@ -13,6 +13,7 @@ linux-2.6 (2.6.27-1~experimental.1) UNRELEASED; urgency=low SCSI_DH_ALUA, MAC80211_HWSIM, USB_HSO. * [x86] set MOUSE_BCM5974. * [x86_64] set AMD_IOMMU, MTRR_SANITIZER. + * Add stable releases 2.6.27.1-2.6.27.6. [ Martin Michlmayr ] * [mips/r4k-ip22, mips/sb1-bcm91250a] Don't build in ISO9660. diff --git a/debian/patches/bugfix/all/stable/patch-2.6.27.1 b/debian/patches/bugfix/all/stable/patch-2.6.27.1 new file mode 100644 index 000000000..45ae16abc --- /dev/null +++ b/debian/patches/bugfix/all/stable/patch-2.6.27.1 @@ -0,0 +1,14 @@ +diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig +index 263e9e6..aa53fdd 100644 +--- a/kernel/trace/Kconfig ++++ b/kernel/trace/Kconfig +@@ -103,7 +103,8 @@ config CONTEXT_SWITCH_TRACER + all switching of tasks. + + config DYNAMIC_FTRACE +- bool "enable/disable ftrace tracepoints dynamically" ++ bool "enable/disable ftrace tracepoints dynamically (BROKEN)" ++ depends on BROKEN + depends on FTRACE + depends on HAVE_DYNAMIC_FTRACE + default y diff --git a/debian/patches/bugfix/all/stable/patch-2.6.27.2 b/debian/patches/bugfix/all/stable/patch-2.6.27.2 new file mode 100644 index 000000000..38bb75569 --- /dev/null +++ b/debian/patches/bugfix/all/stable/patch-2.6.27.2 @@ -0,0 +1,567 @@ +diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c +index 65a0c1b..f509cfc 100644 +--- a/arch/x86/kernel/alternative.c ++++ b/arch/x86/kernel/alternative.c +@@ -444,7 +444,7 @@ void __init alternative_instructions(void) + _text, _etext); + + /* Only switch to UP mode if we don't immediately boot others */ +- if (num_possible_cpus() == 1 || setup_max_cpus <= 1) ++ if (num_present_cpus() == 1 || setup_max_cpus <= 1) + alternatives_smp_switch(0); + } + #endif +diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c +index 4353cf5..6b839b1 100644 +--- a/arch/x86/kernel/early-quirks.c ++++ b/arch/x86/kernel/early-quirks.c +@@ -95,6 +95,52 @@ static void __init nvidia_bugs(int num, int slot, int func) + + } + ++static u32 ati_ixp4x0_rev(int num, int slot, int func) ++{ ++ u32 d; ++ u8 b; ++ ++ b = read_pci_config_byte(num, slot, func, 0xac); ++ b &= ~(1<<5); ++ write_pci_config_byte(num, slot, func, 0xac, b); ++ ++ d = read_pci_config(num, slot, func, 0x70); ++ d |= 1<<8; ++ write_pci_config(num, slot, func, 0x70, d); ++ ++ d = read_pci_config(num, slot, func, 0x8); ++ d &= 0xff; ++ return d; ++} ++ ++static void __init ati_bugs(int num, int slot, int func) ++{ ++#if defined(CONFIG_ACPI) && defined (CONFIG_X86_IO_APIC) ++ u32 d; ++ u8 b; ++ ++ if (acpi_use_timer_override) ++ return; ++ ++ d = ati_ixp4x0_rev(num, slot, func); ++ if (d < 0x82) ++ acpi_skip_timer_override = 1; ++ else { ++ /* check for IRQ0 interrupt swap */ ++ outb(0x72, 0xcd6); b = inb(0xcd7); ++ if (!(b & 0x2)) ++ acpi_skip_timer_override = 1; ++ } ++ ++ if (acpi_skip_timer_override) { ++ printk(KERN_INFO "SB4X0 revision 0x%x\n", d); ++ printk(KERN_INFO "Ignoring ACPI timer override.\n"); ++ printk(KERN_INFO "If you got timer trouble " ++ "try acpi_use_timer_override\n"); ++ } ++#endif ++} ++ + #define QFLAG_APPLY_ONCE 0x1 + #define QFLAG_APPLIED 0x2 + #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) +@@ -114,6 +160,8 @@ static struct chipset early_qrk[] __initdata = { + PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, + PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, ++ { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, ++ PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, + {} + }; + +diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c +index 09cddb5..bfd9fc5 100644 +--- a/arch/x86/kernel/io_apic_32.c ++++ b/arch/x86/kernel/io_apic_32.c +@@ -2314,6 +2314,9 @@ void __init setup_IO_APIC(void) + for (i = first_system_vector; i < NR_VECTORS; i++) + set_bit(i, used_vectors); + ++ /* Mark FIRST_DEVICE_VECTOR which is assigned to IRQ0 as used. */ ++ set_bit(FIRST_DEVICE_VECTOR, used_vectors); ++ + enable_IO_APIC(); + + io_apic_irqs = ~PIC_IRQS; +diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c +index d4b6e6a..d0975fc 100644 +--- a/arch/x86/mm/ioremap.c ++++ b/arch/x86/mm/ioremap.c +@@ -595,7 +595,7 @@ void __init *early_ioremap(unsigned long phys_addr, unsigned long size) + */ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; +- size = PAGE_ALIGN(last_addr) - phys_addr; ++ size = PAGE_ALIGN(last_addr + 1) - phys_addr; + + /* + * Mappings have to fit in the FIX_BTMAP area. +diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c +index e4dce87..0232485 100644 +--- a/drivers/char/tty_io.c ++++ b/drivers/char/tty_io.c +@@ -2996,7 +2996,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case TIOCSTI: + return tiocsti(tty, p); + case TIOCGWINSZ: +- return tiocgwinsz(tty, p); ++ return tiocgwinsz(real_tty, p); + case TIOCSWINSZ: + return tiocswinsz(tty, real_tty, p); + case TIOCCONS: +diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c +index 7685b99..9b60352 100644 +--- a/drivers/net/atl1e/atl1e_main.c ++++ b/drivers/net/atl1e/atl1e_main.c +@@ -2390,9 +2390,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, + } + + /* Init GPHY as early as possible due to power saving issue */ +- spin_lock(&adapter->mdio_lock); + atl1e_phy_init(&adapter->hw); +- spin_unlock(&adapter->mdio_lock); + /* reset the controller to + * put the device in a known good starting state */ + err = atl1e_reset_hw(&adapter->hw); +diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c +index e24b25c..b4be33a 100644 +--- a/drivers/net/sky2.c ++++ b/drivers/net/sky2.c +@@ -3034,7 +3034,8 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + +- if (wol->wolopts & ~sky2_wol_supported(sky2->hw)) ++ if ((wol->wolopts & ~sky2_wol_supported(sky2->hw)) ++ || !device_can_wakeup(&hw->pdev->dev)) + return -EOPNOTSUPP; + + sky2->wol = wol->wolopts; +@@ -3045,6 +3046,8 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) + sky2_write32(hw, B0_CTST, sky2->wol + ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); + ++ device_set_wakeup_enable(&hw->pdev->dev, sky2->wol); ++ + if (!netif_running(dev)) + sky2_wol_init(sky2); + return 0; +@@ -4166,18 +4169,6 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) + return err; + } + +-static int __devinit pci_wake_enabled(struct pci_dev *dev) +-{ +- int pm = pci_find_capability(dev, PCI_CAP_ID_PM); +- u16 value; +- +- if (!pm) +- return 0; +- if (pci_read_config_word(dev, pm + PCI_PM_CTRL, &value)) +- return 0; +- return value & PCI_PM_CTRL_PME_ENABLE; +-} +- + /* This driver supports yukon2 chipset only */ + static const char *sky2_name(u8 chipid, char *buf, int sz) + { +@@ -4238,7 +4229,7 @@ static int __devinit sky2_probe(struct pci_dev *pdev, + } + } + +- wol_default = pci_wake_enabled(pdev) ? WAKE_MAGIC : 0; ++ wol_default = device_may_wakeup(&pdev->dev) ? WAKE_MAGIC : 0; + + err = -ENOMEM; + hw = kzalloc(sizeof(*hw), GFP_KERNEL); +diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c +index 68e1f8c..8d5ff62 100644 +--- a/drivers/net/wireless/b43legacy/xmit.c ++++ b/drivers/net/wireless/b43legacy/xmit.c +@@ -626,7 +626,7 @@ void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev, + tmp = hw->count; + status.frame_count = (tmp >> 4); + status.rts_count = (tmp & 0x0F); +- tmp = hw->flags; ++ tmp = hw->flags << 1; + status.supp_reason = ((tmp & 0x1C) >> 2); + status.pm_indicated = !!(tmp & 0x80); + status.intermediate = !!(tmp & 0x40); +diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c +index bd32ac0..5bcf561 100644 +--- a/drivers/net/wireless/libertas/main.c ++++ b/drivers/net/wireless/libertas/main.c +@@ -1196,7 +1196,13 @@ void lbs_remove_card(struct lbs_private *priv) + cancel_delayed_work_sync(&priv->scan_work); + cancel_delayed_work_sync(&priv->assoc_work); + cancel_work_sync(&priv->mcast_work); ++ ++ /* worker thread destruction blocks on the in-flight command which ++ * should have been cleared already in lbs_stop_card(). ++ */ ++ lbs_deb_main("destroying worker thread\n"); + destroy_workqueue(priv->work_thread); ++ lbs_deb_main("done destroying worker thread\n"); + + if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { + priv->psmode = LBS802_11POWERMODECAM; +@@ -1314,14 +1320,26 @@ void lbs_stop_card(struct lbs_private *priv) + device_remove_file(&dev->dev, &dev_attr_lbs_rtap); + } + +- /* Flush pending command nodes */ ++ /* Delete the timeout of the currently processing command */ + del_timer_sync(&priv->command_timer); ++ ++ /* Flush pending command nodes */ + spin_lock_irqsave(&priv->driver_lock, flags); ++ lbs_deb_main("clearing pending commands\n"); + list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { + cmdnode->result = -ENOENT; + cmdnode->cmdwaitqwoken = 1; + wake_up_interruptible(&cmdnode->cmdwait_q); + } ++ ++ /* Flush the command the card is currently processing */ ++ if (priv->cur_cmd) { ++ lbs_deb_main("clearing current command\n"); ++ priv->cur_cmd->result = -ENOENT; ++ priv->cur_cmd->cmdwaitqwoken = 1; ++ wake_up_interruptible(&priv->cur_cmd->cmdwait_q); ++ } ++ lbs_deb_main("done clearing commands\n"); + spin_unlock_irqrestore(&priv->driver_lock, flags); + + unregister_netdev(dev); +diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h +index 8dfd6f2..0d22479 100644 +--- a/fs/cifs/cifsglob.h ++++ b/fs/cifs/cifsglob.h +@@ -309,6 +309,7 @@ struct cifs_search_info { + __u32 resume_key; + char *ntwrk_buf_start; + char *srch_entries_start; ++ char *last_entry; + char *presume_name; + unsigned int resume_name_len; + bool endOfSearch:1; +diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c +index 994de7c..77a0d1f 100644 +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -3636,6 +3636,8 @@ findFirstRetry: + le16_to_cpu(parms->SearchCount); + psrch_inf->index_of_last_entry = 2 /* skip . and .. */ + + psrch_inf->entries_in_buffer; ++ psrch_inf->last_entry = psrch_inf->srch_entries_start + ++ le16_to_cpu(parms->LastNameOffset); + *pnetfid = parms->SearchHandle; + } else { + cifs_buf_release(pSMB); +@@ -3751,6 +3753,8 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, + le16_to_cpu(parms->SearchCount); + psrch_inf->index_of_last_entry += + psrch_inf->entries_in_buffer; ++ psrch_inf->last_entry = psrch_inf->srch_entries_start + ++ le16_to_cpu(parms->LastNameOffset); + /* cFYI(1,("fnxt2 entries in buf %d index_of_last %d", + psrch_inf->entries_in_buffer, psrch_inf->index_of_last_entry)); */ + +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index 5f40ed3..765adf1 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -640,6 +640,70 @@ static int is_dir_changed(struct file *file) + + } + ++static int cifs_save_resume_key(const char *current_entry, ++ struct cifsFileInfo *cifsFile) ++{ ++ int rc = 0; ++ unsigned int len = 0; ++ __u16 level; ++ char *filename; ++ ++ if ((cifsFile == NULL) || (current_entry == NULL)) ++ return -EINVAL; ++ ++ level = cifsFile->srch_inf.info_level; ++ ++ if (level == SMB_FIND_FILE_UNIX) { ++ FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; ++ ++ filename = &pFindData->FileName[0]; ++ if (cifsFile->srch_inf.unicode) { ++ len = cifs_unicode_bytelen(filename); ++ } else { ++ /* BB should we make this strnlen of PATH_MAX? */ ++ len = strnlen(filename, PATH_MAX); ++ } ++ cifsFile->srch_inf.resume_key = pFindData->ResumeKey; ++ } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { ++ FILE_DIRECTORY_INFO *pFindData = ++ (FILE_DIRECTORY_INFO *)current_entry; ++ filename = &pFindData->FileName[0]; ++ len = le32_to_cpu(pFindData->FileNameLength); ++ cifsFile->srch_inf.resume_key = pFindData->FileIndex; ++ } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { ++ FILE_FULL_DIRECTORY_INFO *pFindData = ++ (FILE_FULL_DIRECTORY_INFO *)current_entry; ++ filename = &pFindData->FileName[0]; ++ len = le32_to_cpu(pFindData->FileNameLength); ++ cifsFile->srch_inf.resume_key = pFindData->FileIndex; ++ } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { ++ SEARCH_ID_FULL_DIR_INFO *pFindData = ++ (SEARCH_ID_FULL_DIR_INFO *)current_entry; ++ filename = &pFindData->FileName[0]; ++ len = le32_to_cpu(pFindData->FileNameLength); ++ cifsFile->srch_inf.resume_key = pFindData->FileIndex; ++ } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { ++ FILE_BOTH_DIRECTORY_INFO *pFindData = ++ (FILE_BOTH_DIRECTORY_INFO *)current_entry; ++ filename = &pFindData->FileName[0]; ++ len = le32_to_cpu(pFindData->FileNameLength); ++ cifsFile->srch_inf.resume_key = pFindData->FileIndex; ++ } else if (level == SMB_FIND_FILE_INFO_STANDARD) { ++ FIND_FILE_STANDARD_INFO *pFindData = ++ (FIND_FILE_STANDARD_INFO *)current_entry; ++ filename = &pFindData->FileName[0]; ++ /* one byte length, no name conversion */ ++ len = (unsigned int)pFindData->FileNameLength; ++ cifsFile->srch_inf.resume_key = pFindData->ResumeKey; ++ } else { ++ cFYI(1, ("Unknown findfirst level %d", level)); ++ return -EINVAL; ++ } ++ cifsFile->srch_inf.resume_name_len = len; ++ cifsFile->srch_inf.presume_name = filename; ++ return rc; ++} ++ + /* find the corresponding entry in the search */ + /* Note that the SMB server returns search entries for . and .. which + complicates logic here if we choose to parse for them and we do not +@@ -703,6 +767,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, + while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && + (rc == 0) && !cifsFile->srch_inf.endOfSearch) { + cFYI(1, ("calling findnext2")); ++ cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); + rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, + &cifsFile->srch_inf); + if (rc) +@@ -919,69 +984,6 @@ static int cifs_filldir(char *pfindEntry, struct file *file, + return rc; + } + +-static int cifs_save_resume_key(const char *current_entry, +- struct cifsFileInfo *cifsFile) +-{ +- int rc = 0; +- unsigned int len = 0; +- __u16 level; +- char *filename; +- +- if ((cifsFile == NULL) || (current_entry == NULL)) +- return -EINVAL; +- +- level = cifsFile->srch_inf.info_level; +- +- if (level == SMB_FIND_FILE_UNIX) { +- FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; +- +- filename = &pFindData->FileName[0]; +- if (cifsFile->srch_inf.unicode) { +- len = cifs_unicode_bytelen(filename); +- } else { +- /* BB should we make this strnlen of PATH_MAX? */ +- len = strnlen(filename, PATH_MAX); +- } +- cifsFile->srch_inf.resume_key = pFindData->ResumeKey; +- } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { +- FILE_DIRECTORY_INFO *pFindData = +- (FILE_DIRECTORY_INFO *)current_entry; +- filename = &pFindData->FileName[0]; +- len = le32_to_cpu(pFindData->FileNameLength); +- cifsFile->srch_inf.resume_key = pFindData->FileIndex; +- } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { +- FILE_FULL_DIRECTORY_INFO *pFindData = +- (FILE_FULL_DIRECTORY_INFO *)current_entry; +- filename = &pFindData->FileName[0]; +- len = le32_to_cpu(pFindData->FileNameLength); +- cifsFile->srch_inf.resume_key = pFindData->FileIndex; +- } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { +- SEARCH_ID_FULL_DIR_INFO *pFindData = +- (SEARCH_ID_FULL_DIR_INFO *)current_entry; +- filename = &pFindData->FileName[0]; +- len = le32_to_cpu(pFindData->FileNameLength); +- cifsFile->srch_inf.resume_key = pFindData->FileIndex; +- } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { +- FILE_BOTH_DIRECTORY_INFO *pFindData = +- (FILE_BOTH_DIRECTORY_INFO *)current_entry; +- filename = &pFindData->FileName[0]; +- len = le32_to_cpu(pFindData->FileNameLength); +- cifsFile->srch_inf.resume_key = pFindData->FileIndex; +- } else if (level == SMB_FIND_FILE_INFO_STANDARD) { +- FIND_FILE_STANDARD_INFO *pFindData = +- (FIND_FILE_STANDARD_INFO *)current_entry; +- filename = &pFindData->FileName[0]; +- /* one byte length, no name conversion */ +- len = (unsigned int)pFindData->FileNameLength; +- cifsFile->srch_inf.resume_key = pFindData->ResumeKey; +- } else { +- cFYI(1, ("Unknown findfirst level %d", level)); +- return -EINVAL; +- } +- cifsFile->srch_inf.resume_name_len = len; +- cifsFile->srch_inf.presume_name = filename; +- return rc; +-} + + int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) + { +diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c +index 986061a..36d5fcd 100644 +--- a/fs/xfs/linux-2.6/xfs_buf.c ++++ b/fs/xfs/linux-2.6/xfs_buf.c +@@ -1001,12 +1001,13 @@ xfs_buf_iodone_work( + * We can get an EOPNOTSUPP to ordered writes. Here we clear the + * ordered flag and reissue them. Because we can't tell the higher + * layers directly that they should not issue ordered I/O anymore, they +- * need to check if the ordered flag was cleared during I/O completion. ++ * need to check if the _XFS_BARRIER_FAILED flag was set during I/O completion. + */ + if ((bp->b_error == EOPNOTSUPP) && + (bp->b_flags & (XBF_ORDERED|XBF_ASYNC)) == (XBF_ORDERED|XBF_ASYNC)) { + XB_TRACE(bp, "ordered_retry", bp->b_iodone); + bp->b_flags &= ~XBF_ORDERED; ++ bp->b_flags |= _XFS_BARRIER_FAILED; + xfs_buf_iorequest(bp); + } else if (bp->b_iodone) + (*(bp->b_iodone))(bp); +diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h +index fe01099..456519a 100644 +--- a/fs/xfs/linux-2.6/xfs_buf.h ++++ b/fs/xfs/linux-2.6/xfs_buf.h +@@ -85,6 +85,14 @@ typedef enum { + * modifications being lost. + */ + _XBF_PAGE_LOCKED = (1 << 22), ++ ++ /* ++ * If we try a barrier write, but it fails we have to communicate ++ * this to the upper layers. Unfortunately b_error gets overwritten ++ * when the buffer is re-issued so we have to add another flag to ++ * keep this information. ++ */ ++ _XFS_BARRIER_FAILED = (1 << 23), + } xfs_buf_flags_t; + + typedef enum { +diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c +index 503ea89..0b02c64 100644 +--- a/fs/xfs/xfs_log.c ++++ b/fs/xfs/xfs_log.c +@@ -1033,11 +1033,12 @@ xlog_iodone(xfs_buf_t *bp) + l = iclog->ic_log; + + /* +- * If the ordered flag has been removed by a lower +- * layer, it means the underlyin device no longer supports ++ * If the _XFS_BARRIER_FAILED flag was set by a lower ++ * layer, it means the underlying device no longer supports + * barrier I/O. Warn loudly and turn off barriers. + */ +- if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ISORDERED(bp)) { ++ if (bp->b_flags & _XFS_BARRIER_FAILED) { ++ bp->b_flags &= ~_XFS_BARRIER_FAILED; + l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER; + xfs_fs_cmn_err(CE_WARN, l->l_mp, + "xlog_iodone: Barriers are no longer supported" +diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c +index 1113157..37f0721 100644 +--- a/kernel/sched_rt.c ++++ b/kernel/sched_rt.c +@@ -102,12 +102,12 @@ static void dequeue_rt_entity(struct sched_rt_entity *rt_se); + + static void sched_rt_rq_enqueue(struct rt_rq *rt_rq) + { ++ struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; + struct sched_rt_entity *rt_se = rt_rq->rt_se; + +- if (rt_se && !on_rt_rq(rt_se) && rt_rq->rt_nr_running) { +- struct task_struct *curr = rq_of_rt_rq(rt_rq)->curr; +- +- enqueue_rt_entity(rt_se); ++ if (rt_rq->rt_nr_running) { ++ if (rt_se && !on_rt_rq(rt_se)) ++ enqueue_rt_entity(rt_se); + if (rt_rq->highest_prio < curr->prio) + resched_task(curr); + } +diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c +index 8165df5..5c7bbe0 100644 +--- a/net/mac80211/debugfs_netdev.c ++++ b/net/mac80211/debugfs_netdev.c +@@ -537,6 +537,7 @@ static int netdev_notify(struct notifier_block *nb, + { + struct net_device *dev = ndev; + struct dentry *dir; ++ struct ieee80211_local *local; + struct ieee80211_sub_if_data *sdata; + char buf[10+IFNAMSIZ]; + +@@ -549,10 +550,19 @@ static int netdev_notify(struct notifier_block *nb, + if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid) + return 0; + +- sdata = IEEE80211_DEV_TO_SUB_IF(dev); ++ /* ++ * Do not use IEEE80211_DEV_TO_SUB_IF because that ++ * BUG_ONs for the master netdev which we need to ++ * handle here. ++ */ ++ sdata = netdev_priv(dev); + +- sprintf(buf, "netdev:%s", dev->name); + dir = sdata->debugfsdir; ++ ++ if (!dir) ++ return 0; ++ ++ sprintf(buf, "netdev:%s", dev->name); + if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) + printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " + "dir to %s\n", buf); +diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c +index 74aecc0..10b05ce 100644 +--- a/net/rfkill/rfkill.c ++++ b/net/rfkill/rfkill.c +@@ -117,6 +117,7 @@ static void rfkill_led_trigger_activate(struct led_classdev *led) + + static void notify_rfkill_state_change(struct rfkill *rfkill) + { ++ rfkill_led_trigger(rfkill, rfkill->state); + blocking_notifier_call_chain(&rfkill_notifier_list, + RFKILL_STATE_CHANGED, + rfkill); +@@ -204,10 +205,8 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, + rfkill->state = state; + } + +- if (force || rfkill->state != oldstate) { +- rfkill_led_trigger(rfkill, rfkill->state); ++ if (force || rfkill->state != oldstate) + notify_rfkill_state_change(rfkill); +- } + + return retval; + } diff --git a/debian/patches/bugfix/all/stable/patch-2.6.27.3 b/debian/patches/bugfix/all/stable/patch-2.6.27.3 new file mode 100644 index 000000000..67282b623 --- /dev/null +++ b/debian/patches/bugfix/all/stable/patch-2.6.27.3 @@ -0,0 +1,739 @@ +diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828 +index aa05e5b..d5cb4ea 100644 +--- a/Documentation/video4linux/CARDLIST.au0828 ++++ b/Documentation/video4linux/CARDLIST.au0828 +@@ -1,5 +1,5 @@ + 0 -> Unknown board (au0828) +- 1 -> Hauppauge HVR950Q (au0828) [2040:7200,2040:7210,2040:7217,2040:721b,2040:721f,2040:7280,0fd9:0008] ++ 1 -> Hauppauge HVR950Q (au0828) [2040:7200,2040:7210,2040:7217,2040:721b,2040:721e,2040:721f,2040:7280,0fd9:0008] + 2 -> Hauppauge HVR850 (au0828) [2040:7240] + 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620] + 4 -> Hauppauge HVR950Q rev xxF8 (au0828) [2040:7201,2040:7211,2040:7281] +diff --git a/drivers/base/core.c b/drivers/base/core.c +index d021c98..473c323 100644 +--- a/drivers/base/core.c ++++ b/drivers/base/core.c +@@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n) + * device_initialize - init device structure. + * @dev: device. + * +- * This prepares the device for use by other layers, +- * including adding it to the device hierarchy. ++ * This prepares the device for use by other layers by initializing ++ * its fields. + * It is the first half of device_register(), if called by +- * that, though it can also be called separately, so one +- * may use @dev's fields (e.g. the refcount). ++ * that function, though it can also be called separately, so one ++ * may use @dev's fields. In particular, get_device()/put_device() ++ * may be used for reference counting of @dev after calling this ++ * function. ++ * ++ * NOTE: Use put_device() to give up your reference instead of freeing ++ * @dev directly once you have called this function. + */ + void device_initialize(struct device *dev) + { +@@ -836,9 +841,13 @@ static void device_remove_sys_dev_entry(struct device *dev) + * This is part 2 of device_register(), though may be called + * separately _iff_ device_initialize() has been called separately. + * +- * This adds it to the kobject hierarchy via kobject_add(), adds it ++ * This adds @dev to the kobject hierarchy via kobject_add(), adds it + * to the global and sibling lists for the device, then + * adds it to the other relevant subsystems of the driver model. ++ * ++ * NOTE: _Never_ directly free @dev after calling this function, even ++ * if it returned an error! Always use put_device() to give up your ++ * reference instead. + */ + int device_add(struct device *dev) + { +@@ -965,6 +974,10 @@ done: + * I.e. you should only call the two helpers separately if + * have a clearly defined need to use and refcount the device + * before it is added to the hierarchy. ++ * ++ * NOTE: _Never_ directly free @dev after calling this function, even ++ * if it returned an error! Always use put_device() to give up the ++ * reference initialized in this function instead. + */ + int device_register(struct device *dev) + { +@@ -1243,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent, + return dev; + + error: +- kfree(dev); ++ put_device(dev); + return ERR_PTR(retval); + } + EXPORT_SYMBOL_GPL(device_create_vargs); +diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c +index 8897434..a219ae4 100644 +--- a/drivers/gpu/drm/i915/i915_dma.c ++++ b/drivers/gpu/drm/i915/i915_dma.c +@@ -836,7 +836,7 @@ struct drm_ioctl_desc i915_ioctls[] = { + DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), + DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ), + DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), +- DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH), ++ DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + }; + + int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); +diff --git a/drivers/md/md.c b/drivers/md/md.c +index deeac4b..fe6eccd 100644 +--- a/drivers/md/md.c ++++ b/drivers/md/md.c +@@ -2109,8 +2109,6 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) + + if (strict_strtoull(buf, 10, &size) < 0) + return -EINVAL; +- if (size < my_mddev->size) +- return -EINVAL; + if (my_mddev->pers && rdev->raid_disk >= 0) { + if (my_mddev->persistent) { + size = super_types[my_mddev->major_version]. +@@ -2121,9 +2119,9 @@ rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) + size = (rdev->bdev->bd_inode->i_size >> 10); + size -= rdev->data_offset/2; + } +- if (size < my_mddev->size) +- return -EINVAL; /* component must fit device */ + } ++ if (size < my_mddev->size) ++ return -EINVAL; /* component must fit device */ + + rdev->size = size; + if (size > oldsize && my_mddev->external) { +diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c +index 9da260f..6f9b773 100644 +--- a/drivers/media/dvb/siano/sms-cards.c ++++ b/drivers/media/dvb/siano/sms-cards.c +@@ -42,6 +42,10 @@ struct usb_device_id smsusb_id_table[] = { + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5510), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, ++ { USB_DEVICE(0x2040, 0x5520), ++ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, ++ { USB_DEVICE(0x2040, 0x5530), ++ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5580), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0x5590), +diff --git a/drivers/media/video/au0828/au0828-cards.c b/drivers/media/video/au0828/au0828-cards.c +index ed48908..6294938 100644 +--- a/drivers/media/video/au0828/au0828-cards.c ++++ b/drivers/media/video/au0828/au0828-cards.c +@@ -90,6 +90,7 @@ static void hauppauge_eeprom(struct au0828_dev *dev, u8 *eeprom_data) + case 72221: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ + case 72231: /* WinTV-HVR950q (OEM, IR, ATSC/QAM and basic analog video */ + case 72241: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM and basic analog video */ ++ case 72251: /* WinTV-HVR950q (Retail, IR, ATSC/QAM and basic analog video */ + case 72301: /* WinTV-HVR850 (Retail, IR, ATSC and basic analog video */ + case 72500: /* WinTV-HVR950q (OEM, No IR, ATSC/QAM */ + break; +@@ -198,6 +199,8 @@ struct usb_device_id au0828_usb_id_table [] = { + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, + { USB_DEVICE(0x2040, 0x721b), + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, ++ { USB_DEVICE(0x2040, 0x721e), ++ .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, + { USB_DEVICE(0x2040, 0x721f), + .driver_info = AU0828_BOARD_HAUPPAUGE_HVR950Q }, + { USB_DEVICE(0x2040, 0x7280), +diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c +index 463680b..b59e472 100644 +--- a/drivers/media/video/tvaudio.c ++++ b/drivers/media/video/tvaudio.c +@@ -1792,7 +1792,7 @@ static int chip_command(struct i2c_client *client, + break; + case VIDIOC_S_FREQUENCY: + chip->mode = 0; /* automatic */ +- if (desc->checkmode) { ++ if (desc->checkmode && desc->setmode) { + desc->setmode(chip,V4L2_TUNER_MODE_MONO); + if (chip->prevmode != V4L2_TUNER_MODE_MONO) + chip->prevmode = -1; /* reset previous mode */ +diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h +index 2f84093..88f4cc3 100644 +--- a/drivers/net/wireless/ath9k/core.h ++++ b/drivers/net/wireless/ath9k/core.h +@@ -316,7 +316,7 @@ void ath_descdma_cleanup(struct ath_softc *sc, + #define ATH_RX_TIMEOUT 40 /* 40 milliseconds */ + #define WME_NUM_TID 16 + #define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ +-#define IEEE80211_BAR_CTL_TID_S 2 /* tid shift */ ++#define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */ + + enum ATH_RX_TYPE { + ATH_RX_NON_CONSUMED = 0, +diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c +index acebdf1..b4c7174 100644 +--- a/drivers/net/wireless/ath9k/main.c ++++ b/drivers/net/wireless/ath9k/main.c +@@ -1007,6 +1007,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, + return ret; + } + ++static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value) ++{ ++ return -EOPNOTSUPP; ++} ++ + static struct ieee80211_ops ath9k_ops = { + .tx = ath9k_tx, + .start = ath9k_start, +@@ -1031,7 +1036,8 @@ static struct ieee80211_ops ath9k_ops = { + .get_tsf = ath9k_get_tsf, + .reset_tsf = ath9k_reset_tsf, + .tx_last_beacon = NULL, +- .ampdu_action = ath9k_ampdu_action ++ .ampdu_action = ath9k_ampdu_action, ++ .set_frag_threshold = ath9k_no_fragmentation, + }; + + void ath_get_beaconconfig(struct ath_softc *sc, +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 8ab389d..706f3e6 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -81,6 +81,10 @@ + + /*-------------------------------------------------------------------------*/ + ++/* Keep track of which host controller drivers are loaded */ ++unsigned long usb_hcds_loaded; ++EXPORT_SYMBOL_GPL(usb_hcds_loaded); ++ + /* host controllers we manage */ + LIST_HEAD (usb_bus_list); + EXPORT_SYMBOL_GPL (usb_bus_list); +diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h +index e710ce0..2dcde61 100644 +--- a/drivers/usb/core/hcd.h ++++ b/drivers/usb/core/hcd.h +@@ -482,4 +482,10 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, + */ + extern struct rw_semaphore ehci_cf_port_reset_rwsem; + ++/* Keep track of which host controller drivers are loaded */ ++#define USB_UHCI_LOADED 0 ++#define USB_OHCI_LOADED 1 ++#define USB_EHCI_LOADED 2 ++extern unsigned long usb_hcds_loaded; ++ + #endif /* __KERNEL__ */ +diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c +index 29d13eb..48f51b1 100644 +--- a/drivers/usb/gadget/s3c2410_udc.c ++++ b/drivers/usb/gadget/s3c2410_udc.c +@@ -1651,7 +1651,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) + return -EBUSY; + + if (!driver->bind || !driver->setup +- || driver->speed != USB_SPEED_FULL) { ++ || driver->speed < USB_SPEED_FULL) { + printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n", + driver->bind, driver->setup, driver->speed); + return -EINVAL; +diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c +index 3791e62..38a55af 100644 +--- a/drivers/usb/gadget/u_ether.c ++++ b/drivers/usb/gadget/u_ether.c +@@ -873,6 +873,13 @@ struct net_device *gether_connect(struct gether *link) + spin_lock(&dev->lock); + dev->port_usb = link; + link->ioport = dev; ++ if (netif_running(dev->net)) { ++ if (link->open) ++ link->open(link); ++ } else { ++ if (link->close) ++ link->close(link); ++ } + spin_unlock(&dev->lock); + + netif_carrier_on(dev->net); +diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c +index 8409e07..86e38b0 100644 +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -1049,6 +1049,12 @@ static int __init ehci_hcd_init(void) + { + int retval = 0; + ++ set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); ++ if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || ++ test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) ++ printk(KERN_WARNING "Warning! ehci_hcd should always be loaded" ++ " before uhci_hcd and ohci_hcd, not after\n"); ++ + pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", + hcd_name, + sizeof(struct ehci_qh), sizeof(struct ehci_qtd), +@@ -1056,8 +1062,10 @@ static int __init ehci_hcd_init(void) + + #ifdef DEBUG + ehci_debug_root = debugfs_create_dir("ehci", NULL); +- if (!ehci_debug_root) +- return -ENOENT; ++ if (!ehci_debug_root) { ++ retval = -ENOENT; ++ goto err_debug; ++ } + #endif + + #ifdef PLATFORM_DRIVER +@@ -1104,7 +1112,9 @@ clean0: + #ifdef DEBUG + debugfs_remove(ehci_debug_root); + ehci_debug_root = NULL; ++err_debug: + #endif ++ clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + return retval; + } + module_init(ehci_hcd_init); +@@ -1126,6 +1136,7 @@ static void __exit ehci_hcd_cleanup(void) + #ifdef DEBUG + debugfs_remove(ehci_debug_root); + #endif ++ clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); + } + module_exit(ehci_hcd_cleanup); + +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index 8990196..8bec02c 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -1098,6 +1098,7 @@ static int __init ohci_hcd_mod_init(void) + printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name); + pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name, + sizeof (struct ed), sizeof (struct td)); ++ set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); + + #ifdef DEBUG + ohci_debug_root = debugfs_create_dir("ohci", NULL); +@@ -1184,6 +1185,7 @@ static int __init ohci_hcd_mod_init(void) + error_debug: + #endif + ++ clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); + return retval; + } + module_init(ohci_hcd_mod_init); +@@ -1214,6 +1216,7 @@ static void __exit ohci_hcd_mod_exit(void) + #ifdef DEBUG + debugfs_remove(ohci_debug_root); + #endif ++ clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); + } + module_exit(ohci_hcd_mod_exit); + +diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c +index 7ea9a7b..32bbce9 100644 +--- a/drivers/usb/host/ohci-hub.c ++++ b/drivers/usb/host/ohci-hub.c +@@ -359,21 +359,24 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd) + + /* Carry out polling-, autostop-, and autoresume-related state changes */ + static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, +- int any_connected) ++ int any_connected, int rhsc_status) + { + int poll_rh = 1; +- int rhsc; ++ int rhsc_enable; + +- rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; +- switch (ohci->hc_control & OHCI_CTRL_HCFS) { ++ /* Some broken controllers never turn off RHCS in the interrupt ++ * status register. For their sake we won't re-enable RHSC ++ * interrupts if the interrupt bit is already active. ++ */ ++ rhsc_enable = ohci_readl(ohci, &ohci->regs->intrenable) & ++ OHCI_INTR_RHSC; + ++ switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: +- /* If no status changes are pending, enable status-change +- * interrupts. +- */ +- if (!rhsc && !changed) { +- rhsc = OHCI_INTR_RHSC; +- ohci_writel(ohci, rhsc, &ohci->regs->intrenable); ++ /* If no status changes are pending, enable RHSC interrupts. */ ++ if (!rhsc_enable && !rhsc_status && !changed) { ++ rhsc_enable = OHCI_INTR_RHSC; ++ ohci_writel(ohci, rhsc_enable, &ohci->regs->intrenable); + } + + /* Keep on polling until we know a device is connected +@@ -383,7 +386,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, + if (any_connected || + !device_may_wakeup(&ohci_to_hcd(ohci) + ->self.root_hub->dev)) { +- if (rhsc) ++ if (rhsc_enable) + poll_rh = 0; + } else { + ohci->autostop = 1; +@@ -396,34 +399,45 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, + ohci->autostop = 0; + ohci->next_statechange = jiffies + + STATECHANGE_DELAY; +- } else if (rhsc && time_after_eq(jiffies, ++ } else if (time_after_eq(jiffies, + ohci->next_statechange) + && !ohci->ed_rm_list + && !(ohci->hc_control & + OHCI_SCHED_ENABLES)) { + ohci_rh_suspend(ohci, 1); +- poll_rh = 0; ++ if (rhsc_enable) ++ poll_rh = 0; + } + } + break; + +- /* if there is a port change, autostart or ask to be resumed */ + case OHCI_USB_SUSPEND: + case OHCI_USB_RESUME: ++ /* if there is a port change, autostart or ask to be resumed */ + if (changed) { + if (ohci->autostop) + ohci_rh_resume(ohci); + else + usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); +- } else { +- if (!rhsc && (ohci->autostop || +- ohci_to_hcd(ohci)->self.root_hub-> +- do_remote_wakeup)) +- ohci_writel(ohci, OHCI_INTR_RHSC, +- &ohci->regs->intrenable); + +- /* everything is idle, no need for polling */ ++ /* If remote wakeup is disabled, stop polling */ ++ } else if (!ohci->autostop && ++ !ohci_to_hcd(ohci)->self.root_hub-> ++ do_remote_wakeup) { + poll_rh = 0; ++ ++ } else { ++ /* If no status changes are pending, ++ * enable RHSC interrupts ++ */ ++ if (!rhsc_enable && !rhsc_status) { ++ rhsc_enable = OHCI_INTR_RHSC; ++ ohci_writel(ohci, rhsc_enable, ++ &ohci->regs->intrenable); ++ } ++ /* Keep polling until RHSC is enabled */ ++ if (rhsc_enable) ++ poll_rh = 0; + } + break; + } +@@ -441,18 +455,22 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci) + * autostop isn't used when CONFIG_PM is turned off. + */ + static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, +- int any_connected) ++ int any_connected, int rhsc_status) + { + /* If RHSC is enabled, don't poll */ + if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) + return 0; + +- /* If no status changes are pending, enable status-change interrupts */ +- if (!changed) { +- ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); +- return 0; +- } +- return 1; ++ /* If status changes are pending, continue polling. ++ * Conversely, if no status changes are pending but the RHSC ++ * status bit was set, then RHSC may be broken so continue polling. ++ */ ++ if (changed || rhsc_status) ++ return 1; ++ ++ /* It's safe to re-enable RHSC interrupts */ ++ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); ++ return 0; + } + + #endif /* CONFIG_PM */ +@@ -467,6 +485,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int i, changed = 0, length = 1; + int any_connected = 0; ++ int rhsc_status; + unsigned long flags; + + spin_lock_irqsave (&ohci->lock, flags); +@@ -492,12 +511,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) + length++; + } + +- /* Some broken controllers never turn off RHCS in the interrupt +- * status register. For their sake we won't re-enable RHSC +- * interrupts if the flag is already set. +- */ +- if (ohci_readl(ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) +- changed = 1; ++ /* Clear the RHSC status flag before reading the port statuses */ ++ ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrstatus); ++ rhsc_status = ohci_readl(ohci, &ohci->regs->intrstatus) & ++ OHCI_INTR_RHSC; + + /* look at each port */ + for (i = 0; i < ohci->num_ports; i++) { +@@ -517,7 +534,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) + } + + hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed, +- any_connected); ++ any_connected, rhsc_status); + + done: + spin_unlock_irqrestore (&ohci->lock, flags); +diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c +index 3a7bfe7..59bed3c 100644 +--- a/drivers/usb/host/uhci-hcd.c ++++ b/drivers/usb/host/uhci-hcd.c +@@ -953,6 +953,7 @@ static int __init uhci_hcd_init(void) + + printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION "%s\n", + ignore_oc ? ", overcurrent ignored" : ""); ++ set_bit(USB_UHCI_LOADED, &usb_hcds_loaded); + + if (usb_disabled()) + return -ENODEV; +@@ -988,6 +989,7 @@ debug_failed: + + errbuf_failed: + ++ clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); + return retval; + } + +@@ -997,6 +999,7 @@ static void __exit uhci_hcd_cleanup(void) + kmem_cache_destroy(uhci_up_cachep); + debugfs_remove(uhci_debugfs_root); + kfree(errbuf); ++ clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded); + } + + module_init(uhci_hcd_init); +diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig +index 58b2b8f..4b9542b 100644 +--- a/drivers/usb/musb/Kconfig ++++ b/drivers/usb/musb/Kconfig +@@ -33,10 +33,6 @@ config USB_MUSB_SOC + default y if ARCH_DAVINCI + default y if ARCH_OMAP2430 + default y if ARCH_OMAP34XX +- help +- Use a static file to describe how the +- controller is configured (endpoints, mechanisms, etc) on the +- current iteration of a given system-on-chip. + + comment "DaVinci 644x USB support" + depends on USB_MUSB_HDRC && ARCH_DAVINCI +diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h +index fc5216b..729b407 100644 +--- a/drivers/usb/musb/cppi_dma.h ++++ b/drivers/usb/musb/cppi_dma.h +@@ -119,8 +119,8 @@ struct cppi { + void __iomem *mregs; /* Mentor regs */ + void __iomem *tibase; /* TI/CPPI regs */ + +- struct cppi_channel tx[MUSB_C_NUM_EPT - 1]; +- struct cppi_channel rx[MUSB_C_NUM_EPR - 1]; ++ struct cppi_channel tx[4]; ++ struct cppi_channel rx[4]; + + struct dma_pool *pool; + +diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c +index 75baf18..dfb3bcb 100644 +--- a/drivers/usb/musb/davinci.c ++++ b/drivers/usb/musb/davinci.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -39,7 +40,7 @@ + #include "musb_core.h" + + #ifdef CONFIG_MACH_DAVINCI_EVM +-#include ++#define GPIO_nVBUS_DRV 87 + #endif + + #include "davinci.h" +@@ -138,7 +139,6 @@ static int vbus_state = -1; + /* VBUS SWITCHING IS BOARD-SPECIFIC */ + + #ifdef CONFIG_MACH_DAVINCI_EVM +-#ifndef CONFIG_MACH_DAVINCI_EVM_OTG + + /* I2C operations are always synchronous, and require a task context. + * With unloaded systems, using the shared workqueue seems to suffice +@@ -146,12 +146,11 @@ static int vbus_state = -1; + */ + static void evm_deferred_drvvbus(struct work_struct *ignored) + { +- davinci_i2c_expander_op(0x3a, USB_DRVVBUS, vbus_state); ++ gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); + vbus_state = !vbus_state; + } + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); + +-#endif /* modified board */ + #endif /* EVM */ + + static void davinci_source_power(struct musb *musb, int is_on, int immediate) +@@ -165,21 +164,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) + + #ifdef CONFIG_MACH_DAVINCI_EVM + if (machine_is_davinci_evm()) { +-#ifdef CONFIG_MACH_DAVINCI_EVM_OTG +- /* modified EVM board switching VBUS with GPIO(6) not I2C +- * NOTE: PINMUX0.RGB888 (bit23) must be clear +- */ +- if (is_on) +- gpio_set(GPIO(6)); +- else +- gpio_clear(GPIO(6)); +- immediate = 1; +-#else + if (immediate) +- davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on); ++ gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); + else + schedule_work(&evm_vbus_work); +-#endif + } + #endif + if (immediate) +diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c +index 128e949..5c5bc1a 100644 +--- a/drivers/usb/musb/musb_core.c ++++ b/drivers/usb/musb/musb_core.c +@@ -82,9 +82,9 @@ + /* + * This gets many kinds of configuration information: + * - Kconfig for everything user-configurable +- * - for SOC or family details + * - platform_device for addressing, irq, and platform_data + * - platform_data is mostly for board-specific informarion ++ * (plus recentrly, SOC or family details) + * + * Most of the conditional compilation will (someday) vanish. + */ +@@ -974,9 +974,9 @@ static void musb_shutdown(struct platform_device *pdev) + /* + * The silicon either has hard-wired endpoint configurations, or else + * "dynamic fifo" sizing. The driver has support for both, though at this +- * writing only the dynamic sizing is very well tested. We use normal +- * idioms to so both modes are compile-tested, but dead code elimination +- * leaves only the relevant one in the object file. ++ * writing only the dynamic sizing is very well tested. Since we switched ++ * away from compile-time hardware parameters, we can no longer rely on ++ * dead code elimination to leave only the relevant one in the object file. + * + * We don't currently use dynamic fifo setup capability to do anything + * more than selecting one of a bunch of predefined configurations. +diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c +index 8b4be01..13205fe 100644 +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -108,7 +108,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, + /* + * Clear TX fifo. Needed to avoid BABBLE errors. + */ +-static inline void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) ++static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) + { + void __iomem *epio = ep->regs; + u16 csr; +@@ -436,7 +436,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb, + } + } + +-static inline u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) ++static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) + { + /* we don't want fifo to fill itself again; + * ignore dma (various models), +@@ -1005,7 +1005,7 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) + + /* + * Handle default endpoint interrupt as host. Only called in IRQ time +- * from the LinuxIsr() interrupt service routine. ++ * from musb_interrupt(). + * + * called with controller irqlocked + */ +diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c +index 9cbff84..038ea62 100644 +--- a/drivers/video/console/fbcon.c ++++ b/drivers/video/console/fbcon.c +@@ -2996,8 +2996,8 @@ static void fbcon_set_all_vcs(struct fb_info *info) + p = &fb_display[vc->vc_num]; + set_blitting_type(vc, info); + var_to_display(p, &info->var, info); +- cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres); +- rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres); ++ cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); ++ rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; + vc_resize(vc, cols, rows); +diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c +index 18d3c84..cbdf97d 100644 +--- a/fs/xfs/linux-2.6/xfs_super.c ++++ b/fs/xfs/linux-2.6/xfs_super.c +@@ -1323,7 +1323,7 @@ xfs_fs_remount( + "XFS: mount option \"%s\" not supported for remount\n", p); + return -EINVAL; + #else +- return 0; ++ break; + #endif + } + } +diff --git a/kernel/module.c b/kernel/module.c +index 9db1191..d5fcd24 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -1173,7 +1173,7 @@ static void free_notes_attrs(struct module_notes_attrs *notes_attrs, + while (i-- > 0) + sysfs_remove_bin_file(notes_attrs->dir, + ¬es_attrs->attrs[i]); +- kobject_del(notes_attrs->dir); ++ kobject_put(notes_attrs->dir); + } + kfree(notes_attrs); + } +diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c +index 34fa8ed..48db9bb 100644 +--- a/net/mac80211/wext.c ++++ b/net/mac80211/wext.c +@@ -804,7 +804,7 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev, + * configure it here */ + + if (local->ops->set_frag_threshold) +- local->ops->set_frag_threshold( ++ return local->ops->set_frag_threshold( + local_to_hw(local), + local->fragmentation_threshold); + diff --git a/debian/patches/bugfix/all/stable/patch-2.6.27.4 b/debian/patches/bugfix/all/stable/patch-2.6.27.4 new file mode 100644 index 000000000..3d8eb5c32 --- /dev/null +++ b/debian/patches/bugfix/all/stable/patch-2.6.27.4 @@ -0,0 +1,855 @@ +diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c +index 426e5d9..c44cd6d 100644 +--- a/arch/x86/kernel/acpi/sleep.c ++++ b/arch/x86/kernel/acpi/sleep.c +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include "realmode/wakeup.h" + #include "sleep.h" +@@ -98,6 +99,8 @@ int acpi_save_state_mem(void) + header->trampoline_segment = setup_trampoline() >> 4; + #ifdef CONFIG_SMP + stack_start.sp = temp_stack + 4096; ++ early_gdt_descr.address = ++ (unsigned long)get_cpu_gdt_table(smp_processor_id()); + #endif + initial_code = (unsigned long)wakeup_long64; + saved_magic = 0x123456789abcdef0; +diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c +index a69cc0f..bccd0ef 100644 +--- a/arch/x86/kernel/amd_iommu_init.c ++++ b/arch/x86/kernel/amd_iommu_init.c +@@ -210,7 +210,7 @@ static void __init iommu_set_exclusion_range(struct amd_iommu *iommu) + /* Programs the physical address of the device table into the IOMMU hardware */ + static void __init iommu_set_device_table(struct amd_iommu *iommu) + { +- u32 entry; ++ u64 entry; + + BUG_ON(iommu->mmio_base == NULL); + +diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c +index dba3cfb..ecb6ace 100644 +--- a/drivers/acpi/hardware/hwsleep.c ++++ b/drivers/acpi/hardware/hwsleep.c +@@ -78,19 +78,17 @@ acpi_set_firmware_waking_vector(acpi_physical_address physical_address) + return_ACPI_STATUS(status); + } + +- /* Set the vector */ ++ /* ++ * According to the ACPI specification 2.0c and later, the 64-bit ++ * waking vector should be cleared and the 32-bit waking vector should ++ * be used, unless we want the wake-up code to be called by the BIOS in ++ * Protected Mode. Some systems (for example HP dv5-1004nr) are known ++ * to fail to resume if the 64-bit vector is used. ++ */ ++ if (facs->version >= 1) ++ facs->xfirmware_waking_vector = 0; + +- if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { +- /* +- * ACPI 1.0 FACS or short table or optional X_ field is zero +- */ +- facs->firmware_waking_vector = (u32) physical_address; +- } else { +- /* +- * ACPI 2.0 FACS with valid X_ field +- */ +- facs->xfirmware_waking_vector = physical_address; +- } ++ facs->firmware_waking_vector = (u32)physical_address; + + return_ACPI_STATUS(AE_OK); + } +@@ -134,20 +132,7 @@ acpi_get_firmware_waking_vector(acpi_physical_address * physical_address) + } + + /* Get the vector */ +- +- if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) { +- /* +- * ACPI 1.0 FACS or short table or optional X_ field is zero +- */ +- *physical_address = +- (acpi_physical_address) facs->firmware_waking_vector; +- } else { +- /* +- * ACPI 2.0 FACS with valid X_ field +- */ +- *physical_address = +- (acpi_physical_address) facs->xfirmware_waking_vector; +- } ++ *physical_address = (acpi_physical_address)facs->firmware_waking_vector; + + return_ACPI_STATUS(AE_OK); + } +diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c +index d13194a..4751909 100644 +--- a/drivers/acpi/sleep/main.c ++++ b/drivers/acpi/sleep/main.c +@@ -200,6 +200,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) + break; + } + ++ /* If ACPI is not enabled by the BIOS, we need to enable it here. */ ++ acpi_enable(); + /* Reprogram control registers and execute _BFS */ + acpi_leave_sleep_state_prep(acpi_state); + +@@ -296,6 +298,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), + }, + }, ++ { ++ .callback = init_old_suspend_ordering, ++ .ident = "HP xw4600 Workstation", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), ++ }, ++ }, + {}, + }; + #endif /* CONFIG_SUSPEND */ +diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c +index fd64137..f2e4caf 100644 +--- a/drivers/char/hvc_console.c ++++ b/drivers/char/hvc_console.c +@@ -367,13 +367,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) + spin_lock_irqsave(&hp->lock, flags); + + if (--hp->count == 0) { +- if (hp->ops->notifier_del) +- hp->ops->notifier_del(hp, hp->data); +- + /* We are done with the tty pointer now. */ + hp->tty = NULL; + spin_unlock_irqrestore(&hp->lock, flags); + ++ if (hp->ops->notifier_del) ++ hp->ops->notifier_del(hp, hp->data); ++ + /* + * Chain calls chars_in_buffer() and returns immediately if + * there is no buffered data otherwise sleeps on a wait queue +@@ -416,11 +416,11 @@ static void hvc_hangup(struct tty_struct *tty) + hp->n_outbuf = 0; + hp->tty = NULL; + ++ spin_unlock_irqrestore(&hp->lock, flags); ++ + if (hp->ops->notifier_del) + hp->ops->notifier_del(hp, hp->data); + +- spin_unlock_irqrestore(&hp->lock, flags); +- + while(temp_open_count) { + --temp_open_count; + kref_put(&hp->kref, destroy_hvc_struct); +diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c +index 0e024fe..887072f 100644 +--- a/drivers/edac/cell_edac.c ++++ b/drivers/edac/cell_edac.c +@@ -142,7 +142,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) + csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT; + csrow->last_page = csrow->first_page + csrow->nr_pages - 1; + csrow->mtype = MEM_XDR; +- csrow->edac_mode = EDAC_FLAG_EC | EDAC_FLAG_SECDED; ++ csrow->edac_mode = EDAC_SECDED; + dev_dbg(mci->dev, + "Initialized on node %d, chanmask=0x%x," + " first_page=0x%lx, nr_pages=0x%x\n", +diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c +index 8d29405..59f6ad8 100644 +--- a/drivers/gpio/gpiolib.c ++++ b/drivers/gpio/gpiolib.c +@@ -1020,7 +1020,7 @@ int gpio_get_value_cansleep(unsigned gpio) + + might_sleep_if(extra_checks); + chip = gpio_to_chip(gpio); +- return chip->get(chip, gpio - chip->base); ++ return chip->get ? chip->get(chip, gpio - chip->base) : 0; + } + EXPORT_SYMBOL_GPL(gpio_get_value_cansleep); + +diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c +index 996802b..8f15353 100644 +--- a/drivers/md/dm-kcopyd.c ++++ b/drivers/md/dm-kcopyd.c +@@ -268,6 +268,17 @@ static void push(struct list_head *jobs, struct kcopyd_job *job) + spin_unlock_irqrestore(&kc->job_lock, flags); + } + ++ ++static void push_head(struct list_head *jobs, struct kcopyd_job *job) ++{ ++ unsigned long flags; ++ struct dm_kcopyd_client *kc = job->kc; ++ ++ spin_lock_irqsave(&kc->job_lock, flags); ++ list_add(&job->list, jobs); ++ spin_unlock_irqrestore(&kc->job_lock, flags); ++} ++ + /* + * These three functions process 1 item from the corresponding + * job list. +@@ -398,7 +409,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc, + * We couldn't service this job ATM, so + * push this job back onto the list. + */ +- push(jobs, job); ++ push_head(jobs, job); + break; + } + +diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c +index 6e5528a..4ed9b7a 100644 +--- a/drivers/md/dm-snap.c ++++ b/drivers/md/dm-snap.c +@@ -824,8 +824,10 @@ static struct bio *put_pending_exception(struct dm_snap_pending_exception *pe) + * the bios for the original write to the origin. + */ + if (primary_pe && +- atomic_dec_and_test(&primary_pe->ref_count)) ++ atomic_dec_and_test(&primary_pe->ref_count)) { + origin_bios = bio_list_get(&primary_pe->origin_bios); ++ free_pending_exception(primary_pe); ++ } + + /* + * Free the pe if it's not linked to an origin write or if +@@ -834,12 +836,6 @@ static struct bio *put_pending_exception(struct dm_snap_pending_exception *pe) + if (!primary_pe || primary_pe != pe) + free_pending_exception(pe); + +- /* +- * Free the primary pe if nothing references it. +- */ +- if (primary_pe && !atomic_read(&primary_pe->ref_count)) +- free_pending_exception(primary_pe); +- + return origin_bios; + } + +diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c +index f051c6a..7412258 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c ++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c +@@ -60,7 +60,6 @@ static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = NULL}; + static DEFINE_MUTEX(pvr2_unit_mtx); + + static int ctlchg; +-static int initusbreset = 1; + static int procreload; + static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 }; + static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 }; +@@ -71,8 +70,6 @@ module_param(ctlchg, int, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value"); + module_param(init_pause_msec, int, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay"); +-module_param(initusbreset, int, S_IRUGO|S_IWUSR); +-MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe"); + module_param(procreload, int, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(procreload, + "Attempt init failure recovery with firmware reload"); +@@ -1698,9 +1695,6 @@ static void pvr2_hdw_setup_low(struct pvr2_hdw *hdw) + } + hdw->fw1_state = FW1_STATE_OK; + +- if (initusbreset) { +- pvr2_hdw_device_reset(hdw); +- } + if (!pvr2_hdw_dev_ok(hdw)) return; + + for (idx = 0; idx < hdw->hdw_desc->client_modules.cnt; idx++) { +diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c +index 54defec..87a68d2 100644 +--- a/drivers/pci/hotplug/cpqphp_core.c ++++ b/drivers/pci/hotplug/cpqphp_core.c +@@ -435,7 +435,7 @@ static int ctrl_slot_setup(struct controller *ctrl, + slot->number, ctrl->slot_device_offset, + slot_number); + result = pci_hp_register(hotplug_slot, +- ctrl->pci_dev->subordinate, ++ ctrl->pci_dev->bus, + slot->device); + if (result) { + err("pci_hp_register failed with error %d\n", result); +diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c +index 6e2f130..d576d4c 100644 +--- a/drivers/scsi/device_handler/scsi_dh_rdac.c ++++ b/drivers/scsi/device_handler/scsi_dh_rdac.c +@@ -590,6 +590,8 @@ static const struct scsi_dh_devlist rdac_dev_list[] = { + {"STK", "OPENstorage D280"}, + {"SUN", "CSM200_R"}, + {"SUN", "LCSM100_F"}, ++ {"DELL", "MD3000"}, ++ {"DELL", "MD3000i"}, + {NULL, NULL}, + }; + +diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c +index 76fce44..3e86240 100644 +--- a/drivers/usb/atm/speedtch.c ++++ b/drivers/usb/atm/speedtch.c +@@ -722,6 +722,16 @@ static void speedtch_atm_stop(struct usbatm_data *usbatm, struct atm_dev *atm_de + flush_scheduled_work(); + } + ++static int speedtch_pre_reset(struct usb_interface *intf) ++{ ++ return 0; ++} ++ ++static int speedtch_post_reset(struct usb_interface *intf) ++{ ++ return 0; ++} ++ + + /********** + ** USB ** +@@ -740,6 +750,8 @@ static struct usb_driver speedtch_usb_driver = { + .name = speedtch_driver_name, + .probe = speedtch_usb_probe, + .disconnect = usbatm_usb_disconnect, ++ .pre_reset = speedtch_pre_reset, ++ .post_reset = speedtch_post_reset, + .id_table = speedtch_usb_ids + }; + +diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c +index c257453..d996a61 100644 +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -849,9 +849,10 @@ static void acm_write_buffers_free(struct acm *acm) + { + int i; + struct acm_wb *wb; ++ struct usb_device *usb_dev = interface_to_usbdev(acm->control); + + for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { +- usb_buffer_free(acm->dev, acm->writesize, wb->buf, wb->dmah); ++ usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah); + } + } + +diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c +index 7e8e123..023a4e9 100644 +--- a/drivers/usb/class/cdc-wdm.c ++++ b/drivers/usb/class/cdc-wdm.c +@@ -42,6 +42,8 @@ static struct usb_device_id wdm_ids[] = { + { } + }; + ++MODULE_DEVICE_TABLE (usb, wdm_ids); ++ + #define WDM_MINOR_BASE 176 + + +diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c +index 5a7fa6f..9f42cb8 100644 +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -1609,7 +1609,8 @@ int usb_external_resume_device(struct usb_device *udev) + status = usb_resume_both(udev); + udev->last_busy = jiffies; + usb_pm_unlock(udev); +- do_unbind_rebind(udev, DO_REBIND); ++ if (status == 0) ++ do_unbind_rebind(udev, DO_REBIND); + + /* Now that the device is awake, we can start trying to autosuspend + * it again. */ +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index d999638..875de9a 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -3424,7 +3424,7 @@ int usb_reset_device(struct usb_device *udev) + USB_INTERFACE_BOUND) + rebind = 1; + } +- if (rebind) ++ if (ret == 0 && rebind) + usb_rebind_intf(cintf); + } + } +diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c +index 765adf1..58d5729 100644 +--- a/fs/cifs/readdir.c ++++ b/fs/cifs/readdir.c +@@ -762,14 +762,15 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon, + rc)); + return rc; + } ++ cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); + } + + while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && + (rc == 0) && !cifsFile->srch_inf.endOfSearch) { + cFYI(1, ("calling findnext2")); +- cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); + rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, + &cifsFile->srch_inf); ++ cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); + if (rc) + return -ENOENT; + } +diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c +index a78c6b4..11a49ce 100644 +--- a/fs/ext2/dir.c ++++ b/fs/ext2/dir.c +@@ -103,7 +103,7 @@ static int ext2_commit_chunk(struct page *page, loff_t pos, unsigned len) + return err; + } + +-static void ext2_check_page(struct page *page) ++static void ext2_check_page(struct page *page, int quiet) + { + struct inode *dir = page->mapping->host; + struct super_block *sb = dir->i_sb; +@@ -146,10 +146,10 @@ out: + /* Too bad, we had an error */ + + Ebadsize: +- ext2_error(sb, "ext2_check_page", +- "size of directory #%lu is not a multiple of chunk size", +- dir->i_ino +- ); ++ if (!quiet) ++ ext2_error(sb, __func__, ++ "size of directory #%lu is not a multiple " ++ "of chunk size", dir->i_ino); + goto fail; + Eshort: + error = "rec_len is smaller than minimal"; +@@ -166,32 +166,36 @@ Espan: + Einumber: + error = "inode out of bounds"; + bad_entry: +- ext2_error (sb, "ext2_check_page", "bad entry in directory #%lu: %s - " +- "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", +- dir->i_ino, error, (page->index<inode), +- rec_len, p->name_len); ++ if (!quiet) ++ ext2_error(sb, __func__, "bad entry in directory #%lu: : %s - " ++ "offset=%lu, inode=%lu, rec_len=%d, name_len=%d", ++ dir->i_ino, error, (page->index<inode), ++ rec_len, p->name_len); + goto fail; + Eend: +- p = (ext2_dirent *)(kaddr + offs); +- ext2_error (sb, "ext2_check_page", +- "entry in directory #%lu spans the page boundary" +- "offset=%lu, inode=%lu", +- dir->i_ino, (page->index<inode)); ++ if (!quiet) { ++ p = (ext2_dirent *)(kaddr + offs); ++ ext2_error(sb, "ext2_check_page", ++ "entry in directory #%lu spans the page boundary" ++ "offset=%lu, inode=%lu", ++ dir->i_ino, (page->index<inode)); ++ } + fail: + SetPageChecked(page); + SetPageError(page); + } + +-static struct page * ext2_get_page(struct inode *dir, unsigned long n) ++static struct page * ext2_get_page(struct inode *dir, unsigned long n, ++ int quiet) + { + struct address_space *mapping = dir->i_mapping; + struct page *page = read_mapping_page(mapping, n, NULL); + if (!IS_ERR(page)) { + kmap(page); + if (!PageChecked(page)) +- ext2_check_page(page); ++ ext2_check_page(page, quiet); + if (PageError(page)) + goto fail; + } +@@ -292,7 +296,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) + for ( ; n < npages; n++, offset = 0) { + char *kaddr, *limit; + ext2_dirent *de; +- struct page *page = ext2_get_page(inode, n); ++ struct page *page = ext2_get_page(inode, n, 0); + + if (IS_ERR(page)) { + ext2_error(sb, __func__, +@@ -361,6 +365,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, + struct page *page = NULL; + struct ext2_inode_info *ei = EXT2_I(dir); + ext2_dirent * de; ++ int dir_has_error = 0; + + if (npages == 0) + goto out; +@@ -374,7 +379,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, + n = start; + do { + char *kaddr; +- page = ext2_get_page(dir, n); ++ page = ext2_get_page(dir, n, dir_has_error); + if (!IS_ERR(page)) { + kaddr = page_address(page); + de = (ext2_dirent *) kaddr; +@@ -391,7 +396,9 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, + de = ext2_next_entry(de); + } + ext2_put_page(page); +- } ++ } else ++ dir_has_error = 1; ++ + if (++n >= npages) + n = 0; + /* next page is past the blocks we've got */ +@@ -414,7 +421,7 @@ found: + + struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p) + { +- struct page *page = ext2_get_page(dir, 0); ++ struct page *page = ext2_get_page(dir, 0, 0); + ext2_dirent *de = NULL; + + if (!IS_ERR(page)) { +@@ -487,7 +494,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) + for (n = 0; n <= npages; n++) { + char *dir_end; + +- page = ext2_get_page(dir, n); ++ page = ext2_get_page(dir, n, 0); + err = PTR_ERR(page); + if (IS_ERR(page)) + goto out; +@@ -655,14 +662,17 @@ int ext2_empty_dir (struct inode * inode) + { + struct page *page = NULL; + unsigned long i, npages = dir_pages(inode); ++ int dir_has_error = 0; + + for (i = 0; i < npages; i++) { + char *kaddr; + ext2_dirent * de; +- page = ext2_get_page(inode, i); ++ page = ext2_get_page(inode, i, dir_has_error); + +- if (IS_ERR(page)) ++ if (IS_ERR(page)) { ++ dir_has_error = 1; + continue; ++ } + + kaddr = page_address(page); + de = (ext2_dirent *)kaddr; +diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c +index 2eea96e..1b80f1c 100644 +--- a/fs/ext3/dir.c ++++ b/fs/ext3/dir.c +@@ -102,6 +102,7 @@ static int ext3_readdir(struct file * filp, + int err; + struct inode *inode = filp->f_path.dentry->d_inode; + int ret = 0; ++ int dir_has_error = 0; + + sb = inode->i_sb; + +@@ -148,9 +149,12 @@ static int ext3_readdir(struct file * filp, + * of recovering data when there's a bad sector + */ + if (!bh) { +- ext3_error (sb, "ext3_readdir", +- "directory #%lu contains a hole at offset %lu", +- inode->i_ino, (unsigned long)filp->f_pos); ++ if (!dir_has_error) { ++ ext3_error(sb, __func__, "directory #%lu " ++ "contains a hole at offset %lld", ++ inode->i_ino, filp->f_pos); ++ dir_has_error = 1; ++ } + /* corrupt size? Maybe no more blocks to read */ + if (filp->f_pos > inode->i_blocks << 9) + break; +diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c +index ec8e33b..d1d6487 100644 +--- a/fs/ext4/dir.c ++++ b/fs/ext4/dir.c +@@ -102,6 +102,7 @@ static int ext4_readdir(struct file * filp, + int err; + struct inode *inode = filp->f_path.dentry->d_inode; + int ret = 0; ++ int dir_has_error = 0; + + sb = inode->i_sb; + +@@ -148,9 +149,13 @@ static int ext4_readdir(struct file * filp, + * of recovering data when there's a bad sector + */ + if (!bh) { +- ext4_error (sb, "ext4_readdir", +- "directory #%lu contains a hole at offset %lu", +- inode->i_ino, (unsigned long)filp->f_pos); ++ if (!dir_has_error) { ++ ext4_error(sb, __func__, "directory #%lu " ++ "contains a hole at offset %Lu", ++ inode->i_ino, ++ (unsigned long long) filp->f_pos); ++ dir_has_error = 1; ++ } + /* corrupt size? Maybe no more blocks to read */ + if (filp->f_pos > inode->i_blocks << 9) + break; +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 73d1891..f3ada04 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -198,11 +198,8 @@ static int do_maps_open(struct inode *inode, struct file *file, + return ret; + } + +-static int show_map(struct seq_file *m, void *v) ++static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) + { +- struct proc_maps_private *priv = m->private; +- struct task_struct *task = priv->task; +- struct vm_area_struct *vma = v; + struct mm_struct *mm = vma->vm_mm; + struct file *file = vma->vm_file; + int flags = vma->vm_flags; +@@ -210,9 +207,6 @@ static int show_map(struct seq_file *m, void *v) + dev_t dev = 0; + int len; + +- if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) +- return -EACCES; +- + if (file) { + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; + dev = inode->i_sb->s_dev; +@@ -257,6 +251,18 @@ static int show_map(struct seq_file *m, void *v) + } + } + seq_putc(m, '\n'); ++} ++ ++static int show_map(struct seq_file *m, void *v) ++{ ++ struct vm_area_struct *vma = v; ++ struct proc_maps_private *priv = m->private; ++ struct task_struct *task = priv->task; ++ ++ if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) ++ return -EACCES; ++ ++ show_map_vma(m, vma); + + if (m->count < m->size) /* vma is copied successfully */ + m->version = (vma != get_gate_vma(task))? vma->vm_start: 0; +@@ -367,23 +373,25 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, + + static int show_smap(struct seq_file *m, void *v) + { ++ struct proc_maps_private *priv = m->private; ++ struct task_struct *task = priv->task; + struct vm_area_struct *vma = v; + struct mem_size_stats mss; +- int ret; + struct mm_walk smaps_walk = { + .pmd_entry = smaps_pte_range, + .mm = vma->vm_mm, + .private = &mss, + }; + ++ if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ)) ++ return -EACCES; ++ + memset(&mss, 0, sizeof mss); + mss.vma = vma; + if (vma->vm_mm && !is_vm_hugetlb_page(vma)) + walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); + +- ret = show_map(m, v); +- if (ret) +- return ret; ++ show_map_vma(m, vma); + + seq_printf(m, + "Size: %8lu kB\n" +@@ -405,7 +413,9 @@ static int show_smap(struct seq_file *m, void *v) + mss.referenced >> 10, + mss.swap >> 10); + +- return ret; ++ if (m->count < m->size) /* vma is copied successfully */ ++ m->version = (vma != get_gate_vma(task)) ? vma->vm_start : 0; ++ return 0; + } + + static const struct seq_operations proc_pid_smaps_op = { +diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h +index 8385d43..81365b3 100644 +--- a/kernel/sched_stats.h ++++ b/kernel/sched_stats.h +@@ -9,7 +9,7 @@ + static int show_schedstat(struct seq_file *seq, void *v) + { + int cpu; +- int mask_len = NR_CPUS/32 * 9; ++ int mask_len = (NR_CPUS/32 + 1) * 9; + char *mask_str = kmalloc(mask_len, GFP_KERNEL); + + if (mask_str == NULL) +diff --git a/mm/rmap.c b/mm/rmap.c +index 0383acf..e8d639b 100644 +--- a/mm/rmap.c ++++ b/mm/rmap.c +@@ -55,7 +55,33 @@ + + struct kmem_cache *anon_vma_cachep; + +-/* This must be called under the mmap_sem. */ ++/** ++ * anon_vma_prepare - attach an anon_vma to a memory region ++ * @vma: the memory region in question ++ * ++ * This makes sure the memory mapping described by 'vma' has ++ * an 'anon_vma' attached to it, so that we can associate the ++ * anonymous pages mapped into it with that anon_vma. ++ * ++ * The common case will be that we already have one, but if ++ * if not we either need to find an adjacent mapping that we ++ * can re-use the anon_vma from (very common when the only ++ * reason for splitting a vma has been mprotect()), or we ++ * allocate a new one. ++ * ++ * Anon-vma allocations are very subtle, because we may have ++ * optimistically looked up an anon_vma in page_lock_anon_vma() ++ * and that may actually touch the spinlock even in the newly ++ * allocated vma (it depends on RCU to make sure that the ++ * anon_vma isn't actually destroyed). ++ * ++ * As a result, we need to do proper anon_vma locking even ++ * for the new allocation. At the same time, we do not want ++ * to do any locking for the common case of already having ++ * an anon_vma. ++ * ++ * This must be called with the mmap_sem held for reading. ++ */ + int anon_vma_prepare(struct vm_area_struct *vma) + { + struct anon_vma *anon_vma = vma->anon_vma; +@@ -63,20 +89,17 @@ int anon_vma_prepare(struct vm_area_struct *vma) + might_sleep(); + if (unlikely(!anon_vma)) { + struct mm_struct *mm = vma->vm_mm; +- struct anon_vma *allocated, *locked; ++ struct anon_vma *allocated; + + anon_vma = find_mergeable_anon_vma(vma); +- if (anon_vma) { +- allocated = NULL; +- locked = anon_vma; +- spin_lock(&locked->lock); +- } else { ++ allocated = NULL; ++ if (!anon_vma) { + anon_vma = anon_vma_alloc(); + if (unlikely(!anon_vma)) + return -ENOMEM; + allocated = anon_vma; +- locked = NULL; + } ++ spin_lock(&anon_vma->lock); + + /* page_table_lock to protect against threads */ + spin_lock(&mm->page_table_lock); +@@ -87,8 +110,7 @@ int anon_vma_prepare(struct vm_area_struct *vma) + } + spin_unlock(&mm->page_table_lock); + +- if (locked) +- spin_unlock(&locked->lock); ++ spin_unlock(&anon_vma->lock); + if (unlikely(allocated)) + anon_vma_free(allocated); + } +diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +index 5a955c4..7eb0b61 100644 +--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c ++++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +@@ -150,10 +150,12 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) + { ++#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE) + /* Previously seen (loopback)? Ignore. Do this before + fragment check. */ + if (skb->nfct) + return NF_ACCEPT; ++#endif + + /* Gather fragments. */ + if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) { +diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c +index ffeaffc..8303e4b 100644 +--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c ++++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c +@@ -742,6 +742,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, + *obj = kmalloc(sizeof(struct snmp_object) + len, + GFP_ATOMIC); + if (*obj == NULL) { ++ kfree(p); + kfree(id); + if (net_ratelimit()) + printk("OOM in bsalg (%d)\n", __LINE__); +diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c +index c63e933..4b5741b 100644 +--- a/net/netfilter/xt_iprange.c ++++ b/net/netfilter/xt_iprange.c +@@ -67,7 +67,7 @@ iprange_mt4(const struct sk_buff *skb, const struct net_device *in, + if (info->flags & IPRANGE_SRC) { + m = ntohl(iph->saddr) < ntohl(info->src_min.ip); + m |= ntohl(iph->saddr) > ntohl(info->src_max.ip); +- m ^= info->flags & IPRANGE_SRC_INV; ++ m ^= !!(info->flags & IPRANGE_SRC_INV); + if (m) { + pr_debug("src IP " NIPQUAD_FMT " NOT in range %s" + NIPQUAD_FMT "-" NIPQUAD_FMT "\n", +@@ -81,7 +81,7 @@ iprange_mt4(const struct sk_buff *skb, const struct net_device *in, + if (info->flags & IPRANGE_DST) { + m = ntohl(iph->daddr) < ntohl(info->dst_min.ip); + m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip); +- m ^= info->flags & IPRANGE_DST_INV; ++ m ^= !!(info->flags & IPRANGE_DST_INV); + if (m) { + pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s" + NIPQUAD_FMT "-" NIPQUAD_FMT "\n", +@@ -123,14 +123,14 @@ iprange_mt6(const struct sk_buff *skb, const struct net_device *in, + if (info->flags & IPRANGE_SRC) { + m = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0; + m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0; +- m ^= info->flags & IPRANGE_SRC_INV; ++ m ^= !!(info->flags & IPRANGE_SRC_INV); + if (m) + return false; + } + if (info->flags & IPRANGE_DST) { + m = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0; + m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0; +- m ^= info->flags & IPRANGE_DST_INV; ++ m ^= !!(info->flags & IPRANGE_DST_INV); + if (m) + return false; + } diff --git a/debian/patches/bugfix/all/stable/patch-2.6.27.5 b/debian/patches/bugfix/all/stable/patch-2.6.27.5 new file mode 100644 index 000000000..db086ff2d --- /dev/null +++ b/debian/patches/bugfix/all/stable/patch-2.6.27.5 @@ -0,0 +1,2543 @@ +diff --git a/Documentation/i2c/busses/i2c-sis96x b/Documentation/i2c/busses/i2c-sis96x +index 266481f..70e6a0c 100644 +--- a/Documentation/i2c/busses/i2c-sis96x ++++ b/Documentation/i2c/busses/i2c-sis96x +@@ -42,7 +42,7 @@ I suspect that this driver could be made to work for the following SiS + chipsets as well: 635, and 635T. If anyone owns a board with those chips + AND is willing to risk crashing & burning an otherwise well-behaved kernel + in the name of progress... please contact me at or +-via the project's mailing list: . Please send bug ++via the linux-i2c mailing list: . Please send bug + reports and/or success stories as well. + + +diff --git a/MAINTAINERS b/MAINTAINERS +index 8dae455..ff24d01 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -360,7 +360,7 @@ S: Maintained + ALI1563 I2C DRIVER + P: Rudolf Marek + M: r.marek@assembler.cz +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + ALPHA PORT +@@ -1681,7 +1681,7 @@ FREESCALE I2C CPM DRIVER + P: Jochen Friedrich + M: jochen@scram.de + L: linuxppc-dev@ozlabs.org +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + FREESCALE SOC FS_ENET DRIVER +@@ -1982,7 +1982,7 @@ S: Maintained + I2C/SMBUS STUB DRIVER + P: Mark M. Hoffman + M: mhoffman@lightlink.com +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + I2C SUBSYSTEM +@@ -1990,14 +1990,14 @@ P: Jean Delvare (PC drivers, core) + M: khali@linux-fr.org + P: Ben Dooks (embedded platforms) + M: ben-linux@fluff.org +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/ + S: Maintained + + I2C-TINY-USB DRIVER + P: Till Harbaum + M: till@harbaum.org +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + T: http://www.harbaum.org/till/i2c_tiny_usb + S: Maintained + +@@ -3070,7 +3070,7 @@ S: Maintained + OPENCORES I2C BUS DRIVER + P: Peter Korsgaard + M: jacmet@sunsite.dk +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + ORACLE CLUSTER FILESYSTEM 2 (OCFS2) +@@ -3144,7 +3144,7 @@ S: Maintained + PA SEMI SMBUS DRIVER + P: Olof Johansson + M: olof@lixom.net +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + PARALLEL PORT SUPPORT +@@ -3280,7 +3280,7 @@ S: Maintained + PNXxxxx I2C DRIVER + P: Vitaly Wool + M: vitalywool@gmail.com +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + PPP PROTOCOL DRIVERS AND COMPRESSORS +@@ -3725,7 +3725,7 @@ S: Maintained + SIS 96X I2C/SMBUS DRIVER + P: Mark M. Hoffman + M: mhoffman@lightlink.com +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + SIS FRAMEBUFFER DRIVER +@@ -4445,7 +4445,7 @@ S: Maintained + VIAPRO SMBUS DRIVER + P: Jean Delvare + M: khali@linux-fr.org +-L: i2c@lm-sensors.org ++L: linux-i2c@vger.kernel.org + S: Maintained + + VIA VELOCITY NETWORK DRIVER +diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig +index 6fc4c21..d0846ec 100644 +--- a/arch/powerpc/configs/linkstation_defconfig ++++ b/arch/powerpc/configs/linkstation_defconfig +@@ -1,7 +1,7 @@ + # + # Automatically generated make config: don't edit +-# Linux kernel version: 2.6.27-rc4 +-# Thu Aug 21 00:52:05 2008 ++# Linux kernel version: 2.6.27 ++# Fri Oct 24 00:42:39 2008 + # + # CONFIG_PPC64 is not set + +@@ -934,7 +934,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 + CONFIG_SERIAL_CORE=y + CONFIG_SERIAL_CORE_CONSOLE=y + # CONFIG_SERIAL_JSM is not set +-CONFIG_SERIAL_OF_PLATFORM=y ++# CONFIG_SERIAL_OF_PLATFORM is not set + CONFIG_UNIX98_PTYS=y + CONFIG_LEGACY_PTYS=y + CONFIG_LEGACY_PTY_COUNT=256 +@@ -1211,7 +1211,6 @@ CONFIG_USB_STORAGE=m + # CONFIG_USB_STORAGE_ALAUDA is not set + # CONFIG_USB_STORAGE_ONETOUCH is not set + # CONFIG_USB_STORAGE_KARMA is not set +-# CONFIG_USB_STORAGE_SIERRA is not set + # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set + # CONFIG_USB_LIBUSUAL is not set + +diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c +index 8920eea..16319a5 100644 +--- a/arch/powerpc/mm/hash_utils_64.c ++++ b/arch/powerpc/mm/hash_utils_64.c +@@ -381,8 +381,10 @@ static int __init htab_dt_scan_hugepage_blocks(unsigned long node, + printk(KERN_INFO "Huge page(16GB) memory: " + "addr = 0x%lX size = 0x%lX pages = %d\n", + phys_addr, block_size, expected_pages); +- lmb_reserve(phys_addr, block_size * expected_pages); +- add_gpage(phys_addr, block_size, expected_pages); ++ if (phys_addr + (16 * GB) <= lmb_end_of_DRAM()) { ++ lmb_reserve(phys_addr, block_size * expected_pages); ++ add_gpage(phys_addr, block_size, expected_pages); ++ } + return 0; + } + +diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c +index d9a1813..b5ae97e 100644 +--- a/arch/powerpc/mm/numa.c ++++ b/arch/powerpc/mm/numa.c +@@ -89,6 +89,48 @@ static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn, + return 0; + } + ++/* ++ * get_active_region_work_fn - A helper function for get_node_active_region ++ * Returns datax set to the start_pfn and end_pfn if they contain ++ * the initial value of datax->start_pfn between them ++ * @start_pfn: start page(inclusive) of region to check ++ * @end_pfn: end page(exclusive) of region to check ++ * @datax: comes in with ->start_pfn set to value to search for and ++ * goes out with active range if it contains it ++ * Returns 1 if search value is in range else 0 ++ */ ++static int __init get_active_region_work_fn(unsigned long start_pfn, ++ unsigned long end_pfn, void *datax) ++{ ++ struct node_active_region *data; ++ data = (struct node_active_region *)datax; ++ ++ if (start_pfn <= data->start_pfn && end_pfn > data->start_pfn) { ++ data->start_pfn = start_pfn; ++ data->end_pfn = end_pfn; ++ return 1; ++ } ++ return 0; ++ ++} ++ ++/* ++ * get_node_active_region - Return active region containing start_pfn ++ * Active range returned is empty if none found. ++ * @start_pfn: The page to return the region for. ++ * @node_ar: Returned set to the active region containing start_pfn ++ */ ++static void __init get_node_active_region(unsigned long start_pfn, ++ struct node_active_region *node_ar) ++{ ++ int nid = early_pfn_to_nid(start_pfn); ++ ++ node_ar->nid = nid; ++ node_ar->start_pfn = start_pfn; ++ node_ar->end_pfn = start_pfn; ++ work_with_active_regions(nid, get_active_region_work_fn, node_ar); ++} ++ + static void __cpuinit map_cpu_to_node(int cpu, int node) + { + numa_cpu_lookup_table[cpu] = node; +@@ -837,38 +879,53 @@ void __init do_init_bootmem(void) + start_pfn, end_pfn); + + free_bootmem_with_active_regions(nid, end_pfn); ++ } + +- /* Mark reserved regions on this node */ +- for (i = 0; i < lmb.reserved.cnt; i++) { +- unsigned long physbase = lmb.reserved.region[i].base; +- unsigned long size = lmb.reserved.region[i].size; +- unsigned long start_paddr = start_pfn << PAGE_SHIFT; +- unsigned long end_paddr = end_pfn << PAGE_SHIFT; +- +- if (early_pfn_to_nid(physbase >> PAGE_SHIFT) != nid && +- early_pfn_to_nid((physbase+size-1) >> PAGE_SHIFT) != nid) +- continue; +- +- if (physbase < end_paddr && +- (physbase+size) > start_paddr) { +- /* overlaps */ +- if (physbase < start_paddr) { +- size -= start_paddr - physbase; +- physbase = start_paddr; +- } +- +- if (size > end_paddr - physbase) +- size = end_paddr - physbase; +- +- dbg("reserve_bootmem %lx %lx\n", physbase, +- size); +- reserve_bootmem_node(NODE_DATA(nid), physbase, +- size, BOOTMEM_DEFAULT); +- } ++ /* Mark reserved regions */ ++ for (i = 0; i < lmb.reserved.cnt; i++) { ++ unsigned long physbase = lmb.reserved.region[i].base; ++ unsigned long size = lmb.reserved.region[i].size; ++ unsigned long start_pfn = physbase >> PAGE_SHIFT; ++ unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT); ++ struct node_active_region node_ar; ++ ++ get_node_active_region(start_pfn, &node_ar); ++ while (start_pfn < end_pfn && ++ node_ar.start_pfn < node_ar.end_pfn) { ++ unsigned long reserve_size = size; ++ /* ++ * if reserved region extends past active region ++ * then trim size to active region ++ */ ++ if (end_pfn > node_ar.end_pfn) ++ reserve_size = (node_ar.end_pfn << PAGE_SHIFT) ++ - (start_pfn << PAGE_SHIFT); ++ dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, ++ reserve_size, node_ar.nid); ++ reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, ++ reserve_size, BOOTMEM_DEFAULT); ++ /* ++ * if reserved region is contained in the active region ++ * then done. ++ */ ++ if (end_pfn <= node_ar.end_pfn) ++ break; ++ ++ /* ++ * reserved region extends past the active region ++ * get next active region that contains this ++ * reserved region ++ */ ++ start_pfn = node_ar.end_pfn; ++ physbase = start_pfn << PAGE_SHIFT; ++ size = size - reserve_size; ++ get_node_active_region(start_pfn, &node_ar); + } + +- sparse_memory_present_with_active_regions(nid); + } ++ ++ for_each_online_node(nid) ++ sparse_memory_present_with_active_regions(nid); + } + + void __init paging_init(void) +diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c +index eb5d74e..2ca7be6 100644 +--- a/arch/powerpc/platforms/embedded6xx/linkstation.c ++++ b/arch/powerpc/platforms/embedded6xx/linkstation.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -54,6 +55,19 @@ static struct mtd_partition linkstation_physmap_partitions[] = { + }, + }; + ++static __initdata struct of_device_id of_bus_ids[] = { ++ { .type = "soc", }, ++ { .compatible = "simple-bus", }, ++ {}, ++}; ++ ++static int __init declare_of_platform_devices(void) ++{ ++ of_platform_bus_probe(NULL, of_bus_ids, NULL); ++ return 0; ++} ++machine_device_initcall(linkstation, declare_of_platform_devices); ++ + static int __init linkstation_add_bridge(struct device_node *dev) + { + #ifdef CONFIG_PCI +diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c +index 00b9b4d..fdfca4f 100644 +--- a/arch/s390/kernel/smp.c ++++ b/arch/s390/kernel/smp.c +@@ -1117,9 +1117,7 @@ out: + return rc; + } + +-static ssize_t __ref rescan_store(struct sys_device *dev, +- struct sysdev_attribute *attr, +- const char *buf, ++static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf, + size_t count) + { + int rc; +@@ -1127,12 +1125,10 @@ static ssize_t __ref rescan_store(struct sys_device *dev, + rc = smp_rescan_cpus(); + return rc ? rc : count; + } +-static SYSDEV_ATTR(rescan, 0200, NULL, rescan_store); ++static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store); + #endif /* CONFIG_HOTPLUG_CPU */ + +-static ssize_t dispatching_show(struct sys_device *dev, +- struct sysdev_attribute *attr, +- char *buf) ++static ssize_t dispatching_show(struct sysdev_class *class, char *buf) + { + ssize_t count; + +@@ -1142,9 +1138,8 @@ static ssize_t dispatching_show(struct sys_device *dev, + return count; + } + +-static ssize_t dispatching_store(struct sys_device *dev, +- struct sysdev_attribute *attr, +- const char *buf, size_t count) ++static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf, ++ size_t count) + { + int val, rc; + char delim; +@@ -1166,7 +1161,8 @@ out: + put_online_cpus(); + return rc ? rc : count; + } +-static SYSDEV_ATTR(dispatching, 0644, dispatching_show, dispatching_store); ++static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, ++ dispatching_store); + + static int __init topology_init(void) + { +@@ -1176,13 +1172,11 @@ static int __init topology_init(void) + register_cpu_notifier(&smp_cpu_nb); + + #ifdef CONFIG_HOTPLUG_CPU +- rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, +- &attr_rescan.attr); ++ rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_rescan); + if (rc) + return rc; + #endif +- rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj, +- &attr_dispatching.attr); ++ rc = sysdev_class_create_file(&cpu_sysdev_class, &attr_dispatching); + if (rc) + return rc; + for_each_present_cpu(cpu) { +diff --git a/arch/sparc64/kernel/trampoline.S b/arch/sparc64/kernel/trampoline.S +index 704a3af..83abd5a 100644 +--- a/arch/sparc64/kernel/trampoline.S ++++ b/arch/sparc64/kernel/trampoline.S +@@ -328,6 +328,12 @@ after_lock_tlb: + + wrpr %g0, 0, %wstate + ++ sethi %hi(prom_entry_lock), %g2 ++1: ldstub [%g2 + %lo(prom_entry_lock)], %g1 ++ membar #StoreLoad | #StoreStore ++ brnz,pn %g1, 1b ++ nop ++ + /* As a hack, put &init_thread_union into %g6. + * prom_world() loads from here to restore the %asi + * register. +@@ -337,7 +343,7 @@ after_lock_tlb: + + sethi %hi(is_sun4v), %o0 + lduw [%o0 + %lo(is_sun4v)], %o0 +- brz,pt %o0, 1f ++ brz,pt %o0, 2f + nop + + TRAP_LOAD_TRAP_BLOCK(%g2, %g3) +@@ -369,10 +375,10 @@ after_lock_tlb: + call %o1 + add %sp, (2047 + 128), %o0 + +- ba,pt %xcc, 2f ++ ba,pt %xcc, 3f + nop + +-1: sethi %hi(sparc64_ttable_tl0), %o0 ++2: sethi %hi(sparc64_ttable_tl0), %o0 + set prom_set_trap_table_name, %g2 + stx %g2, [%sp + 2047 + 128 + 0x00] + mov 1, %g2 +@@ -386,7 +392,11 @@ after_lock_tlb: + call %o1 + add %sp, (2047 + 128), %o0 + +-2: ldx [%l0], %g6 ++3: sethi %hi(prom_entry_lock), %g2 ++ stb %g0, [%g2 + %lo(prom_entry_lock)] ++ membar #StoreStore | #StoreLoad ++ ++ ldx [%l0], %g6 + ldx [%g6 + TI_TASK], %g4 + + mov 1, %g5 +diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c +index e12e0e4..5a7c539 100644 +--- a/arch/x86/kernel/process_64.c ++++ b/arch/x86/kernel/process_64.c +@@ -729,12 +729,12 @@ unsigned long get_wchan(struct task_struct *p) + if (!p || p == current || p->state==TASK_RUNNING) + return 0; + stack = (unsigned long)task_stack_page(p); +- if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE) ++ if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) + return 0; + fp = *(u64 *)(p->thread.sp); + do { + if (fp < (unsigned long)stack || +- fp > (unsigned long)stack+THREAD_SIZE) ++ fp >= (unsigned long)stack+THREAD_SIZE) + return 0; + ip = *(u64 *)(fp+8); + if (!in_sched_functions(ip)) +diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c +index 05191bb..0a23b57 100644 +--- a/arch/x86/kernel/rtc.c ++++ b/arch/x86/kernel/rtc.c +@@ -223,11 +223,25 @@ static struct platform_device rtc_device = { + static __init int add_rtc_cmos(void) + { + #ifdef CONFIG_PNP +- if (!pnp_platform_devices) +- platform_device_register(&rtc_device); +-#else ++ static const char *ids[] __initconst = ++ { "PNP0b00", "PNP0b01", "PNP0b02", }; ++ struct pnp_dev *dev; ++ struct pnp_id *id; ++ int i; ++ ++ pnp_for_each_dev(dev) { ++ for (id = dev->id; id; id = id->next) { ++ for (i = 0; i < ARRAY_SIZE(ids); i++) { ++ if (compare_pnp_id(id, ids[i]) != 0) ++ return 0; ++ } ++ } ++ } ++#endif ++ + platform_device_register(&rtc_device); +-#endif /* CONFIG_PNP */ ++ dev_info(&rtc_device.dev, ++ "registered platform RTC device (no PNP device found)\n"); + return 0; + } + device_initcall(add_rtc_cmos); +diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c +index 2a50e0f..ac144c2 100644 +--- a/arch/x86/mm/pat.c ++++ b/arch/x86/mm/pat.c +@@ -403,12 +403,16 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) + return 1; + } + #else ++/* This check is needed to avoid cache aliasing when PAT is enabled */ + static inline int range_is_allowed(unsigned long pfn, unsigned long size) + { + u64 from = ((u64)pfn) << PAGE_SHIFT; + u64 to = from + size; + u64 cursor = from; + ++ if (!pat_enabled) ++ return 1; ++ + while (cursor < to) { + if (!devmem_is_allowed(pfn)) { + printk(KERN_INFO +diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c +index 1dfec41..59352d9 100644 +--- a/drivers/acpi/button.c ++++ b/drivers/acpi/button.c +@@ -262,6 +262,7 @@ static int acpi_lid_send_state(struct acpi_button *button) + return -ENODEV; + /* input layer checks if event is redundant */ + input_report_switch(button->input, SW_LID, !state); ++ input_sync(button->input); + return 0; + } + +@@ -285,8 +286,8 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data) + input_report_key(input, keycode, 1); + input_sync(input); + input_report_key(input, keycode, 0); ++ input_sync(input); + } +- input_sync(input); + + acpi_bus_generate_proc_event(button->device, event, + ++button->pushed); +diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c +index 13593f9..444cd9e 100644 +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1,7 +1,7 @@ + /* +- * ec.c - ACPI Embedded Controller Driver (v2.0) ++ * ec.c - ACPI Embedded Controller Driver (v2.1) + * +- * Copyright (C) 2006, 2007 Alexey Starikovskiy ++ * Copyright (C) 2006-2008 Alexey Starikovskiy + * Copyright (C) 2006 Denis Sadykov + * Copyright (C) 2004 Luming Yu + * Copyright (C) 2001, 2002 Andy Grover +@@ -26,7 +26,7 @@ + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ + +-/* Uncomment next line to get verbose print outs*/ ++/* Uncomment next line to get verbose printout */ + /* #define DEBUG */ + + #include +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -65,22 +66,21 @@ enum ec_command { + ACPI_EC_COMMAND_QUERY = 0x84, + }; + +-/* EC events */ +-enum ec_event { +- ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ +- ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ +-}; +- + #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ + #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ + #define ACPI_EC_UDELAY 100 /* Wait 100us before polling EC again */ + ++#define ACPI_EC_STORM_THRESHOLD 20 /* number of false interrupts ++ per one transaction */ ++ + enum { +- EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ + EC_FLAGS_QUERY_PENDING, /* Query is pending */ +- EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ ++ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent ++ * for status change */ + EC_FLAGS_NO_GPE, /* Don't use GPE mode */ +- EC_FLAGS_RESCHEDULE_POLL /* Re-schedule poll */ ++ EC_FLAGS_GPE_STORM, /* GPE storm detected */ ++ EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and ++ * OpReg are installed */ + }; + + /* If we find an EC via the ECDT, we need to keep a ptr to its context */ +@@ -95,6 +95,15 @@ struct acpi_ec_query_handler { + u8 query_bit; + }; + ++struct transaction { ++ const u8 *wdata; ++ u8 *rdata; ++ unsigned short irq_count; ++ u8 command; ++ u8 wlen; ++ u8 rlen; ++}; ++ + static struct acpi_ec { + acpi_handle handle; + unsigned long gpe; +@@ -105,9 +114,8 @@ static struct acpi_ec { + struct mutex lock; + wait_queue_head_t wait; + struct list_head list; +- struct delayed_work work; +- atomic_t irq_count; +- u8 handlers_installed; ++ struct transaction *curr; ++ spinlock_t curr_lock; + } *boot_ec, *first_ec; + + /* +@@ -150,7 +158,7 @@ static inline u8 acpi_ec_read_data(struct acpi_ec *ec) + { + u8 x = inb(ec->data_addr); + pr_debug(PREFIX "---> data = 0x%2.2x\n", x); +- return inb(ec->data_addr); ++ return x; + } + + static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) +@@ -165,158 +173,172 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) + outb(data, ec->data_addr); + } + +-static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) ++static int ec_transaction_done(struct acpi_ec *ec) + { +- if (test_bit(EC_FLAGS_WAIT_GPE, &ec->flags)) +- return 0; +- if (event == ACPI_EC_EVENT_OBF_1) { +- if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) +- return 1; +- } else if (event == ACPI_EC_EVENT_IBF_0) { +- if (!(acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) +- return 1; +- } +- +- return 0; ++ unsigned long flags; ++ int ret = 0; ++ spin_lock_irqsave(&ec->curr_lock, flags); ++ if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) ++ ret = 1; ++ spin_unlock_irqrestore(&ec->curr_lock, flags); ++ return ret; + } + +-static void ec_schedule_ec_poll(struct acpi_ec *ec) ++static void gpe_transaction(struct acpi_ec *ec, u8 status) + { +- if (test_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags)) +- schedule_delayed_work(&ec->work, +- msecs_to_jiffies(ACPI_EC_DELAY)); ++ unsigned long flags; ++ spin_lock_irqsave(&ec->curr_lock, flags); ++ if (!ec->curr) ++ goto unlock; ++ if (ec->curr->wlen > 0) { ++ if ((status & ACPI_EC_FLAG_IBF) == 0) { ++ acpi_ec_write_data(ec, *(ec->curr->wdata++)); ++ --ec->curr->wlen; ++ } else ++ /* false interrupt, state didn't change */ ++ ++ec->curr->irq_count; ++ ++ } else if (ec->curr->rlen > 0) { ++ if ((status & ACPI_EC_FLAG_OBF) == 1) { ++ *(ec->curr->rdata++) = acpi_ec_read_data(ec); ++ --ec->curr->rlen; ++ } else ++ /* false interrupt, state didn't change */ ++ ++ec->curr->irq_count; ++ } ++unlock: ++ spin_unlock_irqrestore(&ec->curr_lock, flags); + } + +-static void ec_switch_to_poll_mode(struct acpi_ec *ec) ++static int acpi_ec_wait(struct acpi_ec *ec) + { ++ if (wait_event_timeout(ec->wait, ec_transaction_done(ec), ++ msecs_to_jiffies(ACPI_EC_DELAY))) ++ return 0; ++ /* missing GPEs, switch back to poll mode */ ++ if (printk_ratelimit()) ++ pr_info(PREFIX "missing confirmations, " ++ "switch off interrupt mode.\n"); + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); +- acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); +- set_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); ++ return 1; + } + +-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) ++static void acpi_ec_gpe_query(void *ec_cxt); ++ ++static int ec_check_sci(struct acpi_ec *ec, u8 state) + { +- atomic_set(&ec->irq_count, 0); +- if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && +- likely(!force_poll)) { +- if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), +- msecs_to_jiffies(ACPI_EC_DELAY))) +- return 0; +- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); +- if (acpi_ec_check_status(ec, event)) { +- /* missing GPEs, switch back to poll mode */ +- if (printk_ratelimit()) +- pr_info(PREFIX "missing confirmations, " +- "switch off interrupt mode.\n"); +- ec_switch_to_poll_mode(ec); +- ec_schedule_ec_poll(ec); +- return 0; +- } +- } else { +- unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); +- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); +- while (time_before(jiffies, delay)) { +- if (acpi_ec_check_status(ec, event)) +- return 0; +- msleep(1); +- } +- if (acpi_ec_check_status(ec,event)) ++ if (state & ACPI_EC_FLAG_SCI) { ++ if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) ++ return acpi_os_execute(OSL_EC_BURST_HANDLER, ++ acpi_ec_gpe_query, ec); ++ } ++ return 0; ++} ++ ++static int ec_poll(struct acpi_ec *ec) ++{ ++ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); ++ msleep(1); ++ while (time_before(jiffies, delay)) { ++ gpe_transaction(ec, acpi_ec_read_status(ec)); ++ msleep(1); ++ if (ec_transaction_done(ec)) + return 0; + } +- pr_err(PREFIX "acpi_ec_wait timeout, status = 0x%2.2x, event = %s\n", +- acpi_ec_read_status(ec), +- (event == ACPI_EC_EVENT_OBF_1) ? "\"b0=1\"" : "\"b1=0\""); + return -ETIME; + } + +-static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, +- const u8 * wdata, unsigned wdata_len, +- u8 * rdata, unsigned rdata_len, ++static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, ++ struct transaction *t, + int force_poll) + { +- int result = 0; +- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); ++ unsigned long tmp; ++ int ret = 0; + pr_debug(PREFIX "transaction start\n"); +- acpi_ec_write_cmd(ec, command); +- for (; wdata_len > 0; --wdata_len) { +- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); +- if (result) { +- pr_err(PREFIX +- "write_cmd timeout, command = %d\n", command); +- goto end; +- } +- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); +- acpi_ec_write_data(ec, *(wdata++)); ++ /* disable GPE during transaction if storm is detected */ ++ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { ++ clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); ++ acpi_disable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); + } +- +- if (!rdata_len) { +- result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); +- if (result) { +- pr_err(PREFIX +- "finish-write timeout, command = %d\n", command); +- goto end; +- } +- } else if (command == ACPI_EC_COMMAND_QUERY) ++ /* start transaction */ ++ spin_lock_irqsave(&ec->curr_lock, tmp); ++ /* following two actions should be kept atomic */ ++ t->irq_count = 0; ++ ec->curr = t; ++ acpi_ec_write_cmd(ec, ec->curr->command); ++ if (ec->curr->command == ACPI_EC_COMMAND_QUERY) + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); +- +- for (; rdata_len > 0; --rdata_len) { +- result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); +- if (result) { +- pr_err(PREFIX "read timeout, command = %d\n", command); +- goto end; +- } +- /* Don't expect GPE after last read */ +- if (rdata_len > 1) +- set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); +- *(rdata++) = acpi_ec_read_data(ec); +- } +- end: ++ spin_unlock_irqrestore(&ec->curr_lock, tmp); ++ /* if we selected poll mode or failed in GPE-mode do a poll loop */ ++ if (force_poll || ++ !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) || ++ acpi_ec_wait(ec)) ++ ret = ec_poll(ec); + pr_debug(PREFIX "transaction end\n"); +- return result; ++ spin_lock_irqsave(&ec->curr_lock, tmp); ++ ec->curr = NULL; ++ spin_unlock_irqrestore(&ec->curr_lock, tmp); ++ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { ++ /* check if we received SCI during transaction */ ++ ec_check_sci(ec, acpi_ec_read_status(ec)); ++ /* it is safe to enable GPE outside of transaction */ ++ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); ++ } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && ++ t->irq_count > ACPI_EC_STORM_THRESHOLD) { ++ pr_debug(PREFIX "GPE storm detected\n"); ++ set_bit(EC_FLAGS_GPE_STORM, &ec->flags); ++ } ++ return ret; ++} ++ ++static int ec_check_ibf0(struct acpi_ec *ec) ++{ ++ u8 status = acpi_ec_read_status(ec); ++ return (status & ACPI_EC_FLAG_IBF) == 0; + } + +-static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, +- const u8 * wdata, unsigned wdata_len, +- u8 * rdata, unsigned rdata_len, ++static int ec_wait_ibf0(struct acpi_ec *ec) ++{ ++ unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); ++ /* interrupt wait manually if GPE mode is not active */ ++ unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ? ++ msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1); ++ while (time_before(jiffies, delay)) ++ if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout)) ++ return 0; ++ return -ETIME; ++} ++ ++static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, + int force_poll) + { + int status; + u32 glk; +- +- if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) ++ if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) + return -EINVAL; +- +- if (rdata) +- memset(rdata, 0, rdata_len); +- ++ if (t->rdata) ++ memset(t->rdata, 0, t->rlen); + mutex_lock(&ec->lock); + if (ec->global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) { +- mutex_unlock(&ec->lock); +- return -ENODEV; ++ status = -ENODEV; ++ goto unlock; + } + } +- +- status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); +- if (status) { ++ if (ec_wait_ibf0(ec)) { + pr_err(PREFIX "input buffer is not empty, " + "aborting transaction\n"); ++ status = -ETIME; + goto end; + } +- +- status = acpi_ec_transaction_unlocked(ec, command, +- wdata, wdata_len, +- rdata, rdata_len, +- force_poll); +- +- end: +- ++ status = acpi_ec_transaction_unlocked(ec, t, force_poll); ++end: + if (ec->global_lock) + acpi_release_global_lock(glk); ++unlock: + mutex_unlock(&ec->lock); +- + return status; + } + +@@ -327,21 +349,32 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, + int acpi_ec_burst_enable(struct acpi_ec *ec) + { + u8 d; +- return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0); ++ struct transaction t = {.command = ACPI_EC_BURST_ENABLE, ++ .wdata = NULL, .rdata = &d, ++ .wlen = 0, .rlen = 1}; ++ ++ return acpi_ec_transaction(ec, &t, 0); + } + + int acpi_ec_burst_disable(struct acpi_ec *ec) + { +- return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0); ++ struct transaction t = {.command = ACPI_EC_BURST_DISABLE, ++ .wdata = NULL, .rdata = NULL, ++ .wlen = 0, .rlen = 0}; ++ ++ return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? ++ acpi_ec_transaction(ec, &t, 0) : 0; + } + + static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) + { + int result; + u8 d; ++ struct transaction t = {.command = ACPI_EC_COMMAND_READ, ++ .wdata = &address, .rdata = &d, ++ .wlen = 1, .rlen = 1}; + +- result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, +- &address, 1, &d, 1, 0); ++ result = acpi_ec_transaction(ec, &t, 0); + *data = d; + return result; + } +@@ -349,8 +382,11 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) + static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) + { + u8 wdata[2] = { address, data }; +- return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, +- wdata, 2, NULL, 0, 0); ++ struct transaction t = {.command = ACPI_EC_COMMAND_WRITE, ++ .wdata = wdata, .rdata = NULL, ++ .wlen = 2, .rlen = 0}; ++ ++ return acpi_ec_transaction(ec, &t, 0); + } + + /* +@@ -412,12 +448,13 @@ int ec_transaction(u8 command, + u8 * rdata, unsigned rdata_len, + int force_poll) + { ++ struct transaction t = {.command = command, ++ .wdata = wdata, .rdata = rdata, ++ .wlen = wdata_len, .rlen = rdata_len}; + if (!first_ec) + return -ENODEV; + +- return acpi_ec_transaction(first_ec, command, wdata, +- wdata_len, rdata, rdata_len, +- force_poll); ++ return acpi_ec_transaction(first_ec, &t, force_poll); + } + + EXPORT_SYMBOL(ec_transaction); +@@ -426,7 +463,9 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) + { + int result; + u8 d; +- ++ struct transaction t = {.command = ACPI_EC_COMMAND_QUERY, ++ .wdata = NULL, .rdata = &d, ++ .wlen = 0, .rlen = 1}; + if (!ec || !data) + return -EINVAL; + +@@ -436,7 +475,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) + * bit to be cleared (and thus clearing the interrupt source). + */ + +- result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0); ++ result = acpi_ec_transaction(ec, &t, 0); + if (result) + return result; + +@@ -513,46 +552,26 @@ static void acpi_ec_gpe_query(void *ec_cxt) + + static u32 acpi_ec_gpe_handler(void *data) + { +- acpi_status status = AE_OK; + struct acpi_ec *ec = data; +- u8 state = acpi_ec_read_status(ec); ++ u8 status; + + pr_debug(PREFIX "~~~> interrupt\n"); +- atomic_inc(&ec->irq_count); +- if (atomic_read(&ec->irq_count) > 5) { +- pr_err(PREFIX "GPE storm detected, disabling EC GPE\n"); +- ec_switch_to_poll_mode(ec); +- goto end; +- } +- clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); +- if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) ++ status = acpi_ec_read_status(ec); ++ ++ gpe_transaction(ec, status); ++ if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) + wake_up(&ec->wait); + +- if (state & ACPI_EC_FLAG_SCI) { +- if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) +- status = acpi_os_execute(OSL_EC_BURST_HANDLER, +- acpi_ec_gpe_query, ec); +- } else if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && +- !test_bit(EC_FLAGS_NO_GPE, &ec->flags) && +- in_interrupt()) { ++ ec_check_sci(ec, status); ++ if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && ++ !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { + /* this is non-query, must be confirmation */ + if (printk_ratelimit()) + pr_info(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); + set_bit(EC_FLAGS_GPE_MODE, &ec->flags); +- clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); + } +-end: +- ec_schedule_ec_poll(ec); +- return ACPI_SUCCESS(status) ? +- ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; +-} +- +-static void do_ec_poll(struct work_struct *work) +-{ +- struct acpi_ec *ec = container_of(work, struct acpi_ec, work.work); +- atomic_set(&ec->irq_count, 0); +- (void)acpi_ec_gpe_handler(ec); ++ return ACPI_INTERRUPT_HANDLED; + } + + /* -------------------------------------------------------------------------- +@@ -696,8 +715,7 @@ static struct acpi_ec *make_acpi_ec(void) + mutex_init(&ec->lock); + init_waitqueue_head(&ec->wait); + INIT_LIST_HEAD(&ec->list); +- INIT_DELAYED_WORK_DEFERRABLE(&ec->work, do_ec_poll); +- atomic_set(&ec->irq_count, 0); ++ spin_lock_init(&ec->curr_lock); + return ec; + } + +@@ -736,22 +754,15 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) + return AE_CTRL_TERMINATE; + } + +-static void ec_poll_stop(struct acpi_ec *ec) +-{ +- clear_bit(EC_FLAGS_RESCHEDULE_POLL, &ec->flags); +- cancel_delayed_work(&ec->work); +-} +- + static void ec_remove_handlers(struct acpi_ec *ec) + { +- ec_poll_stop(ec); + if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) + pr_err(PREFIX "failed to remove space handler\n"); + if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, + &acpi_ec_gpe_handler))) + pr_err(PREFIX "failed to remove gpe handler\n"); +- ec->handlers_installed = 0; ++ clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); + } + + static int acpi_ec_add(struct acpi_device *device) +@@ -846,17 +857,15 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context) + static int ec_install_handlers(struct acpi_ec *ec) + { + acpi_status status; +- if (ec->handlers_installed) ++ if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) + return 0; + status = acpi_install_gpe_handler(NULL, ec->gpe, +- ACPI_GPE_EDGE_TRIGGERED, +- &acpi_ec_gpe_handler, ec); ++ ACPI_GPE_EDGE_TRIGGERED, ++ &acpi_ec_gpe_handler, ec); + if (ACPI_FAILURE(status)) + return -ENODEV; +- + acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); +- + status = acpi_install_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, + &acpi_ec_space_handler, +@@ -866,7 +875,7 @@ static int ec_install_handlers(struct acpi_ec *ec) + return -ENODEV; + } + +- ec->handlers_installed = 1; ++ set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); + return 0; + } + +@@ -887,7 +896,6 @@ static int acpi_ec_start(struct acpi_device *device) + + /* EC is fully operational, allow queries */ + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); +- ec_schedule_ec_poll(ec); + return ret; + } + +@@ -906,7 +914,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type) + + int __init acpi_boot_ec_enable(void) + { +- if (!boot_ec || boot_ec->handlers_installed) ++ if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) + return 0; + if (!ec_install_handlers(boot_ec)) { + first_ec = boot_ec; +diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c +index ecb6ace..25dccdf 100644 +--- a/drivers/acpi/hardware/hwsleep.c ++++ b/drivers/acpi/hardware/hwsleep.c +@@ -612,6 +612,13 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state) + } + /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */ + ++ /* ++ * Some BIOSes assume that WAK_STS will be cleared on resume and use ++ * it to determine whether the system is rebooting or resuming. Clear ++ * it for compatibility. ++ */ ++ acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1); ++ + acpi_gbl_system_awake_and_running = TRUE; + + /* Enable power button */ +diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c +index a6b662c..755baf2 100644 +--- a/drivers/acpi/reboot.c ++++ b/drivers/acpi/reboot.c +@@ -15,9 +15,28 @@ void acpi_reboot(void) + + rr = &acpi_gbl_FADT.reset_register; + +- /* Is the reset register supported? */ +- if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || +- rr->bit_width != 8 || rr->bit_offset != 0) ++ /* ++ * Is the ACPI reset register supported? ++ * ++ * According to ACPI 3.0, FADT.flags.RESET_REG_SUP indicates ++ * whether the ACPI reset mechanism is supported. ++ * ++ * However, some boxes have this bit clear, yet a valid ++ * ACPI_RESET_REG & RESET_VALUE, and ACPI reboot is the only ++ * mechanism that works for them after S3. ++ * ++ * This suggests that other operating systems may not be checking ++ * the RESET_REG_SUP bit, and are using other means to decide ++ * whether to use the ACPI reboot mechanism or not. ++ * ++ * So when acpi reboot is requested, ++ * only the reset_register is checked. If the following ++ * conditions are met, it indicates that the reset register is supported. ++ * a. reset_register is not zero ++ * b. the access width is eight ++ * c. the bit_offset is zero ++ */ ++ if (!(rr->address) || rr->bit_width != 8 || rr->bit_offset != 0) + return; + + reset_value = acpi_gbl_FADT.reset_value; +diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c +index 79e3a8e..8228ae3 100644 +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -5259,6 +5259,8 @@ struct ata_port *ata_port_alloc(struct ata_host *host) + + #ifdef CONFIG_ATA_SFF + INIT_DELAYED_WORK(&ap->port_task, ata_pio_task); ++#else ++ INIT_DELAYED_WORK(&ap->port_task, NULL); + #endif + INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug); + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan); +diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c +index 0221c9a..35fd67d 100644 +--- a/drivers/ata/pata_it821x.c ++++ b/drivers/ata/pata_it821x.c +@@ -557,9 +557,8 @@ static unsigned int it821x_read_id(struct ata_device *adev, + if (strstr(model_num, "Integrated Technology Express")) { + /* Set feature bits the firmware neglects */ + id[49] |= 0x0300; /* LBA, DMA */ +- id[82] |= 0x0400; /* LBA48 */ + id[83] &= 0x7FFF; +- id[83] |= 0x4000; /* Word 83 is valid */ ++ id[83] |= 0x4400; /* Word 83 is valid and LBA48 */ + id[86] |= 0x0400; /* LBA48 on */ + id[ATA_ID_MAJOR_VER] |= 0x1F; + } +diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c +index 14601dc..8714c36 100644 +--- a/drivers/ata/sata_nv.c ++++ b/drivers/ata/sata_nv.c +@@ -307,10 +307,10 @@ static int nv_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val); + + static void nv_nf2_freeze(struct ata_port *ap); + static void nv_nf2_thaw(struct ata_port *ap); ++static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline); + static void nv_ck804_freeze(struct ata_port *ap); + static void nv_ck804_thaw(struct ata_port *ap); +-static int nv_hardreset(struct ata_link *link, unsigned int *class, +- unsigned long deadline); + static int nv_adma_slave_config(struct scsi_device *sdev); + static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc); + static void nv_adma_qc_prep(struct ata_queued_cmd *qc); +@@ -405,17 +405,8 @@ static struct scsi_host_template nv_swncq_sht = { + .slave_configure = nv_swncq_slave_config, + }; + +-/* OSDL bz3352 reports that some nv controllers can't determine device +- * signature reliably and nv_hardreset is implemented to work around +- * the problem. This was reported on nf3 and it's unclear whether any +- * other controllers are affected. However, the workaround has been +- * applied to all variants and there isn't much to gain by trying to +- * find out exactly which ones are affected at this point especially +- * because NV has moved over to ahci for newer controllers. +- */ + static struct ata_port_operations nv_common_ops = { + .inherits = &ata_bmdma_port_ops, +- .hardreset = nv_hardreset, + .scr_read = nv_scr_read, + .scr_write = nv_scr_write, + }; +@@ -429,12 +420,22 @@ static struct ata_port_operations nv_generic_ops = { + .hardreset = ATA_OP_NULL, + }; + ++/* OSDL bz3352 reports that nf2/3 controllers can't determine device ++ * signature reliably. Also, the following thread reports detection ++ * failure on cold boot with the standard debouncing timing. ++ * ++ * http://thread.gmane.org/gmane.linux.ide/34098 ++ * ++ * Debounce with hotplug timing and request follow-up SRST. ++ */ + static struct ata_port_operations nv_nf2_ops = { + .inherits = &nv_common_ops, + .freeze = nv_nf2_freeze, + .thaw = nv_nf2_thaw, ++ .hardreset = nv_nf2_hardreset, + }; + ++/* CK804 finally gets hardreset right */ + static struct ata_port_operations nv_ck804_ops = { + .inherits = &nv_common_ops, + .freeze = nv_ck804_freeze, +@@ -443,7 +444,7 @@ static struct ata_port_operations nv_ck804_ops = { + }; + + static struct ata_port_operations nv_adma_ops = { +- .inherits = &nv_common_ops, ++ .inherits = &nv_ck804_ops, + + .check_atapi_dma = nv_adma_check_atapi_dma, + .sff_tf_read = nv_adma_tf_read, +@@ -467,7 +468,7 @@ static struct ata_port_operations nv_adma_ops = { + }; + + static struct ata_port_operations nv_swncq_ops = { +- .inherits = &nv_common_ops, ++ .inherits = &nv_generic_ops, + + .qc_defer = ata_std_qc_defer, + .qc_prep = nv_swncq_qc_prep, +@@ -1553,6 +1554,17 @@ static void nv_nf2_thaw(struct ata_port *ap) + iowrite8(mask, scr_addr + NV_INT_ENABLE); + } + ++static int nv_nf2_hardreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline) ++{ ++ bool online; ++ int rc; ++ ++ rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, ++ &online, NULL); ++ return online ? -EAGAIN : rc; ++} ++ + static void nv_ck804_freeze(struct ata_port *ap) + { + void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR]; +@@ -1605,21 +1617,6 @@ static void nv_mcp55_thaw(struct ata_port *ap) + ata_sff_thaw(ap); + } + +-static int nv_hardreset(struct ata_link *link, unsigned int *class, +- unsigned long deadline) +-{ +- int rc; +- +- /* SATA hardreset fails to retrieve proper device signature on +- * some controllers. Request follow up SRST. For more info, +- * see http://bugzilla.kernel.org/show_bug.cgi?id=3352 +- */ +- rc = sata_sff_hardreset(link, class, deadline); +- if (rc) +- return rc; +- return -EAGAIN; +-} +- + static void nv_adma_error_handler(struct ata_port *ap) + { + struct nv_adma_port_priv *pp = ap->private_data; +diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c +index 030665b..b26885f 100644 +--- a/drivers/ata/sata_promise.c ++++ b/drivers/ata/sata_promise.c +@@ -153,6 +153,10 @@ static void pdc_freeze(struct ata_port *ap); + static void pdc_sata_freeze(struct ata_port *ap); + static void pdc_thaw(struct ata_port *ap); + static void pdc_sata_thaw(struct ata_port *ap); ++static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline); ++static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline); + static void pdc_error_handler(struct ata_port *ap); + static void pdc_post_internal_cmd(struct ata_queued_cmd *qc); + static int pdc_pata_cable_detect(struct ata_port *ap); +@@ -186,6 +190,7 @@ static struct ata_port_operations pdc_sata_ops = { + .scr_read = pdc_sata_scr_read, + .scr_write = pdc_sata_scr_write, + .port_start = pdc_sata_port_start, ++ .hardreset = pdc_sata_hardreset, + }; + + /* First-generation chips need a more restrictive ->check_atapi_dma op */ +@@ -200,6 +205,7 @@ static struct ata_port_operations pdc_pata_ops = { + .freeze = pdc_freeze, + .thaw = pdc_thaw, + .port_start = pdc_common_port_start, ++ .softreset = pdc_pata_softreset, + }; + + static const struct ata_port_info pdc_port_info[] = { +@@ -691,6 +697,20 @@ static void pdc_sata_thaw(struct ata_port *ap) + readl(host_mmio + hotplug_offset); /* flush */ + } + ++static int pdc_pata_softreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline) ++{ ++ pdc_reset_port(link->ap); ++ return ata_sff_softreset(link, class, deadline); ++} ++ ++static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, ++ unsigned long deadline) ++{ ++ pdc_reset_port(link->ap); ++ return sata_sff_hardreset(link, class, deadline); ++} ++ + static void pdc_error_handler(struct ata_port *ap) + { + if (!(ap->pflags & ATA_PFLAG_FROZEN)) +diff --git a/drivers/base/sys.c b/drivers/base/sys.c +index 75dd6e2..70499cb 100644 +--- a/drivers/base/sys.c ++++ b/drivers/base/sys.c +@@ -488,7 +488,8 @@ ssize_t sysdev_store_ulong(struct sys_device *sysdev, + if (end == buf) + return -EINVAL; + *(unsigned long *)(ea->var) = new; +- return end - buf; ++ /* Always return full write size even if we didn't consume all */ ++ return size; + } + EXPORT_SYMBOL_GPL(sysdev_store_ulong); + +@@ -511,7 +512,8 @@ ssize_t sysdev_store_int(struct sys_device *sysdev, + if (end == buf || new > INT_MAX || new < INT_MIN) + return -EINVAL; + *(int *)(ea->var) = new; +- return end - buf; ++ /* Always return full write size even if we didn't consume all */ ++ return size; + } + EXPORT_SYMBOL_GPL(sysdev_store_int); + +diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c +index 016fdf0..f1fe749 100644 +--- a/drivers/char/agp/intel-agp.c ++++ b/drivers/char/agp/intel-agp.c +@@ -54,8 +54,7 @@ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ +- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB || \ +- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB) ++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB) + + #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ +@@ -63,7 +62,8 @@ + + #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ +- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB) ++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G45_HB || \ ++ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB) + + extern int agp_memory_reserved; + +@@ -525,8 +525,10 @@ static void intel_i830_init_gtt_entries(void) + size += 4; + } else if (IS_G4X) { + /* On 4 series hardware, GTT stolen is separate from graphics +- * stolen, ignore it in stolen gtt entries counting */ +- size = 0; ++ * stolen, ignore it in stolen gtt entries counting. However, ++ * 4KB of the stolen memory doesn't get mapped to the GTT. ++ */ ++ size = 4; + } else { + /* On previous hardware, the GTT size was just what was + * required to map the aperture. +diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c +index 64e1c16..ecaf369 100644 +--- a/drivers/char/ipmi/ipmi_devintf.c ++++ b/drivers/char/ipmi/ipmi_devintf.c +@@ -957,3 +957,4 @@ module_exit(cleanup_ipmi); + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Corey Minyard "); + MODULE_DESCRIPTION("Linux device interface for the IPMI message handler."); ++MODULE_ALIAS("platform:ipmi_si"); +diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c +index 2e6d584..ed03234 100644 +--- a/drivers/firewire/fw-cdev.c ++++ b/drivers/firewire/fw-cdev.c +@@ -720,8 +720,8 @@ static int ioctl_create_iso_context(struct client *client, void *buffer) + #define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff) + #define GET_INTERRUPT(v) (((v) >> 16) & 0x01) + #define GET_SKIP(v) (((v) >> 17) & 0x01) +-#define GET_TAG(v) (((v) >> 18) & 0x02) +-#define GET_SY(v) (((v) >> 20) & 0x04) ++#define GET_TAG(v) (((v) >> 18) & 0x03) ++#define GET_SY(v) (((v) >> 20) & 0x0f) + #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff) + + static int ioctl_queue_iso(struct client *client, void *buffer) +@@ -913,7 +913,7 @@ dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) + return -EFAULT; + } + +- return 0; ++ return retval; + } + + static long +diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c +index aaff50e..4f73537 100644 +--- a/drivers/firewire/fw-sbp2.c ++++ b/drivers/firewire/fw-sbp2.c +@@ -172,6 +172,9 @@ struct sbp2_target { + int blocked; /* ditto */ + }; + ++/* Impossible login_id, to detect logout attempt before successful login */ ++#define INVALID_LOGIN_ID 0x10000 ++ + /* + * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be + * provided in the config rom. Most devices do provide a value, which +@@ -791,9 +794,20 @@ static void sbp2_release_target(struct kref *kref) + scsi_remove_device(sdev); + scsi_device_put(sdev); + } +- sbp2_send_management_orb(lu, tgt->node_id, lu->generation, +- SBP2_LOGOUT_REQUEST, lu->login_id, NULL); +- ++ if (lu->login_id != INVALID_LOGIN_ID) { ++ int generation, node_id; ++ /* ++ * tgt->node_id may be obsolete here if we failed ++ * during initial login or after a bus reset where ++ * the topology changed. ++ */ ++ generation = device->generation; ++ smp_rmb(); /* node_id vs. generation */ ++ node_id = device->node_id; ++ sbp2_send_management_orb(lu, node_id, generation, ++ SBP2_LOGOUT_REQUEST, ++ lu->login_id, NULL); ++ } + fw_core_remove_address_handler(&lu->address_handler); + list_del(&lu->link); + kfree(lu); +@@ -808,19 +822,20 @@ static void sbp2_release_target(struct kref *kref) + + static struct workqueue_struct *sbp2_wq; + ++static void sbp2_target_put(struct sbp2_target *tgt) ++{ ++ kref_put(&tgt->kref, sbp2_release_target); ++} ++ + /* + * Always get the target's kref when scheduling work on one its units. + * Each workqueue job is responsible to call sbp2_target_put() upon return. + */ + static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) + { +- if (queue_delayed_work(sbp2_wq, &lu->work, delay)) +- kref_get(&lu->tgt->kref); +-} +- +-static void sbp2_target_put(struct sbp2_target *tgt) +-{ +- kref_put(&tgt->kref, sbp2_release_target); ++ kref_get(&lu->tgt->kref); ++ if (!queue_delayed_work(sbp2_wq, &lu->work, delay)) ++ sbp2_target_put(lu->tgt); + } + + static void +@@ -993,6 +1008,7 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) + + lu->tgt = tgt; + lu->lun = lun_entry & 0xffff; ++ lu->login_id = INVALID_LOGIN_ID; + lu->retries = 0; + lu->has_sdev = false; + lu->blocked = false; +@@ -1158,7 +1174,7 @@ static int sbp2_probe(struct device *dev) + + /* Do the login in a workqueue so we can easily reschedule retries. */ + list_for_each_entry(lu, &tgt->lu_list, link) +- sbp2_queue_work(lu, 0); ++ sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); + return 0; + + fail_tgt_put: +diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c +index c1b8107..5e20471 100644 +--- a/drivers/firewire/fw-topology.c ++++ b/drivers/firewire/fw-topology.c +@@ -413,7 +413,7 @@ static void + update_tree(struct fw_card *card, struct fw_node *root) + { + struct list_head list0, list1; +- struct fw_node *node0, *node1; ++ struct fw_node *node0, *node1, *next1; + int i, event; + + INIT_LIST_HEAD(&list0); +@@ -485,7 +485,9 @@ update_tree(struct fw_card *card, struct fw_node *root) + } + + node0 = fw_node(node0->link.next); +- node1 = fw_node(node1->link.next); ++ next1 = fw_node(node1->link.next); ++ fw_node_put(node1); ++ node1 = next1; + } + } + +diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h +index 2ae1b0d..81b15ba 100644 +--- a/drivers/firewire/fw-transaction.h ++++ b/drivers/firewire/fw-transaction.h +@@ -248,7 +248,7 @@ struct fw_card { + struct fw_node *local_node; + struct fw_node *root_node; + struct fw_node *irm_node; +- int color; ++ u8 color; /* must be u8 to match the definition in struct fw_node */ + int gap_count; + bool beta_repeaters_present; + +diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c +index b15f882..49144cb 100644 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -247,8 +247,6 @@ + #define USB_DEVICE_ID_LD_MACHINETEST 0x2040 + + #define USB_VENDOR_ID_LOGITECH 0x046d +-#define USB_DEVICE_ID_LOGITECH_LX3 0xc044 +-#define USB_DEVICE_ID_LOGITECH_V150 0xc047 + #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 + #define USB_DEVICE_ID_LOGITECH_HARMONY 0xc110 + #define USB_DEVICE_ID_LOGITECH_HARMONY_2 0xc111 +@@ -603,8 +601,6 @@ static const struct hid_blacklist { + + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, + { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP }, +- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_LX3, HID_QUIRK_INVERT_HWHEEL }, +- { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_V150, HID_QUIRK_INVERT_HWHEEL }, + + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS }, +diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c +index c3022a0..e4c9853 100644 +--- a/drivers/i2c/busses/scx200_i2c.c ++++ b/drivers/i2c/busses/scx200_i2c.c +@@ -81,6 +81,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = { + + static struct i2c_adapter scx200_i2c_ops = { + .owner = THIS_MODULE, ++ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .id = I2C_HW_B_SCX200, + .algo_data = &scx200_i2c_data, + .name = "NatSemi SCx200 I2C", +diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c +index b1ce10f..e32c24d 100644 +--- a/drivers/input/keyboard/atkbd.c ++++ b/drivers/input/keyboard/atkbd.c +@@ -834,10 +834,10 @@ static void atkbd_disconnect(struct serio *serio) + } + + /* +- * Most special keys (Fn+F?) on Dell Latitudes do not generate release ++ * Most special keys (Fn+F?) on Dell laptops do not generate release + * events so we have to do it ourselves. + */ +-static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd) ++static void atkbd_dell_laptop_keymap_fixup(struct atkbd *atkbd) + { + const unsigned int forced_release_keys[] = { + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93, +@@ -1461,13 +1461,13 @@ static int __init atkbd_setup_fixup(const struct dmi_system_id *id) + + static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { + { +- .ident = "Dell Latitude series", ++ .ident = "Dell Laptop", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +- DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), ++ DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ + }, + .callback = atkbd_setup_fixup, +- .driver_data = atkbd_latitude_keymap_fixup, ++ .driver_data = atkbd_dell_laptop_keymap_fixup, + }, + { + .ident = "HP 2133", +diff --git a/drivers/media/dvb/frontends/s5h1411.c b/drivers/media/dvb/frontends/s5h1411.c +index 2da1a37..a92ee16 100644 +--- a/drivers/media/dvb/frontends/s5h1411.c ++++ b/drivers/media/dvb/frontends/s5h1411.c +@@ -471,6 +471,20 @@ static int s5h1411_set_spectralinversion(struct dvb_frontend *fe, int inversion) + return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x24, val); + } + ++static int s5h1411_set_serialmode(struct dvb_frontend *fe, int serial) ++{ ++ struct s5h1411_state *state = fe->demodulator_priv; ++ u16 val; ++ ++ dprintk("%s(%d)\n", __func__, serial); ++ val = s5h1411_readreg(state, S5H1411_I2C_TOP_ADDR, 0xbd) & ~0x100; ++ ++ if (serial == 1) ++ val |= 0x100; ++ ++ return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, val); ++} ++ + static int s5h1411_enable_modulation(struct dvb_frontend *fe, + fe_modulation_t m) + { +@@ -535,7 +549,7 @@ static int s5h1411_set_gpio(struct dvb_frontend *fe, int enable) + return s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xe0, val); + } + +-static int s5h1411_sleep(struct dvb_frontend *fe, int enable) ++static int s5h1411_set_powerstate(struct dvb_frontend *fe, int enable) + { + struct s5h1411_state *state = fe->demodulator_priv; + +@@ -551,6 +565,11 @@ static int s5h1411_sleep(struct dvb_frontend *fe, int enable) + return 0; + } + ++static int s5h1411_sleep(struct dvb_frontend *fe) ++{ ++ return s5h1411_set_powerstate(fe, 1); ++} ++ + static int s5h1411_register_reset(struct dvb_frontend *fe) + { + struct s5h1411_state *state = fe->demodulator_priv; +@@ -574,9 +593,6 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe, + + s5h1411_enable_modulation(fe, p->u.vsb.modulation); + +- /* Allow the demod to settle */ +- msleep(100); +- + if (fe->ops.tuner_ops.set_params) { + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); +@@ -587,6 +603,10 @@ static int s5h1411_set_frontend(struct dvb_frontend *fe, + fe->ops.i2c_gate_ctrl(fe, 0); + } + ++ /* Issue a reset to the demod so it knows to resync against the ++ newly tuned frequency */ ++ s5h1411_softreset(fe); ++ + return 0; + } + +@@ -599,7 +619,7 @@ static int s5h1411_init(struct dvb_frontend *fe) + + dprintk("%s()\n", __func__); + +- s5h1411_sleep(fe, 0); ++ s5h1411_set_powerstate(fe, 0); + s5h1411_register_reset(fe); + + for (i = 0; i < ARRAY_SIZE(init_tab); i++) +@@ -612,10 +632,10 @@ static int s5h1411_init(struct dvb_frontend *fe) + + if (state->config->output_mode == S5H1411_SERIAL_OUTPUT) + /* Serial */ +- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1101); ++ s5h1411_set_serialmode(fe, 1); + else + /* Parallel */ +- s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0xbd, 0x1001); ++ s5h1411_set_serialmode(fe, 0); + + s5h1411_set_spectralinversion(fe, state->config->inversion); + s5h1411_set_if_freq(fe, state->config->vsb_if); +@@ -863,6 +883,7 @@ static struct dvb_frontend_ops s5h1411_ops = { + }, + + .init = s5h1411_init, ++ .sleep = s5h1411_sleep, + .i2c_gate_ctrl = s5h1411_i2c_gate_ctrl, + .set_frontend = s5h1411_set_frontend, + .get_frontend = s5h1411_get_frontend, +diff --git a/drivers/media/video/pvrusb2/pvrusb2-encoder.c b/drivers/media/video/pvrusb2/pvrusb2-encoder.c +index a1252d6..273d2a1 100644 +--- a/drivers/media/video/pvrusb2/pvrusb2-encoder.c ++++ b/drivers/media/video/pvrusb2/pvrusb2-encoder.c +@@ -402,6 +402,10 @@ static int pvr2_encoder_prep_config(struct pvr2_hdw *hdw) + ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4, 0,3,0,0); + ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC,4,15,0,0,0); + ++ /* prevent the PTSs from slowly drifting away in the generated ++ MPEG stream */ ++ ret |= pvr2_encoder_vcmd(hdw, CX2341X_ENC_MISC, 2, 4, 1); ++ + return ret; + } + +diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c +index e23ce77..b46e599 100644 +--- a/drivers/net/atlx/atl1.c ++++ b/drivers/net/atlx/atl1.c +@@ -2317,7 +2317,8 @@ static void atl1_tx_queue(struct atl1_adapter *adapter, u16 count, + if (tpd != ptpd) + memcpy(tpd, ptpd, sizeof(struct tx_packet_desc)); + tpd->buffer_addr = cpu_to_le64(buffer_info->dma); +- tpd->word2 = (cpu_to_le16(buffer_info->length) & ++ tpd->word2 &= ~(TPD_BUFLEN_MASK << TPD_BUFLEN_SHIFT); ++ tpd->word2 |= (cpu_to_le16(buffer_info->length) & + TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT; + + /* +@@ -2426,8 +2427,8 @@ static int atl1_xmit_frame(struct sk_buff *skb, struct net_device *netdev) + vlan_tag = (vlan_tag << 4) | (vlan_tag >> 13) | + ((vlan_tag >> 9) & 0x8); + ptpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT; +- ptpd->word3 |= (vlan_tag & TPD_VL_TAGGED_MASK) << +- TPD_VL_TAGGED_SHIFT; ++ ptpd->word2 |= (vlan_tag & TPD_VLANTAG_MASK) << ++ TPD_VLANTAG_SHIFT; + } + + tso = atl1_tso(adapter, skb, ptpd); +diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h +index a5015b1..ffa73fc 100644 +--- a/drivers/net/atlx/atl1.h ++++ b/drivers/net/atlx/atl1.h +@@ -504,7 +504,7 @@ struct rx_free_desc { + #define TPD_PKTNT_MASK 0x0001 + #define TPD_PKTINT_SHIFT 15 + #define TPD_VLANTAG_MASK 0xFFFF +-#define TPD_VLAN_SHIFT 16 ++#define TPD_VLANTAG_SHIFT 16 + + /* tpd word 3 bits 0:13 */ + #define TPD_EOP_MASK 0x0001 +diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c +index b211486..4489e58 100644 +--- a/drivers/net/bonding/bond_alb.c ++++ b/drivers/net/bonding/bond_alb.c +@@ -167,11 +167,14 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_ + /* clear slave from tx_hashtbl */ + tx_hash_table = BOND_ALB_INFO(bond).tx_hashtbl; + +- index = SLAVE_TLB_INFO(slave).head; +- while (index != TLB_NULL_INDEX) { +- u32 next_index = tx_hash_table[index].next; +- tlb_init_table_entry(&tx_hash_table[index], save_load); +- index = next_index; ++ /* skip this if we've already freed the tx hash table */ ++ if (tx_hash_table) { ++ index = SLAVE_TLB_INFO(slave).head; ++ while (index != TLB_NULL_INDEX) { ++ u32 next_index = tx_hash_table[index].next; ++ tlb_init_table_entry(&tx_hash_table[index], save_load); ++ index = next_index; ++ } + } + + tlb_init_slave(slave); +diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c +index 4b27456..50927ea 100644 +--- a/drivers/net/wireless/libertas/scan.c ++++ b/drivers/net/wireless/libertas/scan.c +@@ -598,8 +598,8 @@ static int lbs_process_bss(struct bss_descriptor *bss, + + switch (elem->id) { + case MFIE_TYPE_SSID: +- bss->ssid_len = elem->len; +- memcpy(bss->ssid, elem->data, elem->len); ++ bss->ssid_len = min_t(int, 32, elem->len); ++ memcpy(bss->ssid, elem->data, bss->ssid_len); + lbs_deb_scan("got SSID IE: '%s', len %u\n", + escape_essid(bss->ssid, bss->ssid_len), + bss->ssid_len); +diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c +index 36698e5..bcafbd6 100644 +--- a/drivers/pci/probe.c ++++ b/drivers/pci/probe.c +@@ -219,7 +219,7 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar) + + res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK; + +- if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64) ++ if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) + return pci_bar_mem64; + return pci_bar_mem32; + } +diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c +index b184367..6ad46d7 100644 +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -1030,29 +1030,32 @@ static struct platform_driver cmos_platform_driver = { + + static int __init cmos_init(void) + { ++ int retval = 0; ++ + #ifdef CONFIG_PNP +- if (pnp_platform_devices) +- return pnp_register_driver(&cmos_pnp_driver); +- else +- return platform_driver_probe(&cmos_platform_driver, +- cmos_platform_probe); +-#else +- return platform_driver_probe(&cmos_platform_driver, +- cmos_platform_probe); +-#endif /* CONFIG_PNP */ ++ pnp_register_driver(&cmos_pnp_driver); ++#endif ++ ++ if (!cmos_rtc.dev) ++ retval = platform_driver_probe(&cmos_platform_driver, ++ cmos_platform_probe); ++ ++ if (retval == 0) ++ return 0; ++ ++#ifdef CONFIG_PNP ++ pnp_unregister_driver(&cmos_pnp_driver); ++#endif ++ return retval; + } + module_init(cmos_init); + + static void __exit cmos_exit(void) + { + #ifdef CONFIG_PNP +- if (pnp_platform_devices) +- pnp_unregister_driver(&cmos_pnp_driver); +- else +- platform_driver_unregister(&cmos_platform_driver); +-#else ++ pnp_unregister_driver(&cmos_pnp_driver); ++#endif + platform_driver_unregister(&cmos_platform_driver); +-#endif /* CONFIG_PNP */ + } + module_exit(cmos_exit); + +diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c +index e5e7d78..b7ea69c 100644 +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1047,7 +1047,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) + good_bytes = sd_completed_bytes(SCpnt); + break; + case RECOVERED_ERROR: +- case NO_SENSE: + /* Inform the user, but make sure that it's not treated + * as a hard error. + */ +@@ -1056,6 +1055,15 @@ static int sd_done(struct scsi_cmnd *SCpnt) + memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); + good_bytes = scsi_bufflen(SCpnt); + break; ++ case NO_SENSE: ++ /* This indicates a false check condition, so ignore it. An ++ * unknown amount of data was transferred so treat it as an ++ * error. ++ */ ++ scsi_print_sense("sd", SCpnt); ++ SCpnt->result = 0; ++ memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); ++ break; + case ABORTED_COMMAND: + if (sshdr.asc == 0x10) { /* DIF: Disk detected corruption */ + scsi_print_result(SCpnt); +diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c +index 706f3e6..7a4ccf5 100644 +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -106,6 +106,9 @@ static DEFINE_SPINLOCK(hcd_root_hub_lock); + /* used when updating an endpoint's URB list */ + static DEFINE_SPINLOCK(hcd_urb_list_lock); + ++/* used to protect against unlinking URBs after the device is gone */ ++static DEFINE_SPINLOCK(hcd_urb_unlink_lock); ++ + /* wait queue for synchronous unlinks */ + DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue); + +@@ -1377,10 +1380,25 @@ static int unlink1(struct usb_hcd *hcd, struct urb *urb, int status) + int usb_hcd_unlink_urb (struct urb *urb, int status) + { + struct usb_hcd *hcd; +- int retval; ++ int retval = -EIDRM; ++ unsigned long flags; + +- hcd = bus_to_hcd(urb->dev->bus); +- retval = unlink1(hcd, urb, status); ++ /* Prevent the device and bus from going away while ++ * the unlink is carried out. If they are already gone ++ * then urb->use_count must be 0, since disconnected ++ * devices can't have any active URBs. ++ */ ++ spin_lock_irqsave(&hcd_urb_unlink_lock, flags); ++ if (atomic_read(&urb->use_count) > 0) { ++ retval = 0; ++ usb_get_dev(urb->dev); ++ } ++ spin_unlock_irqrestore(&hcd_urb_unlink_lock, flags); ++ if (retval == 0) { ++ hcd = bus_to_hcd(urb->dev->bus); ++ retval = unlink1(hcd, urb, status); ++ usb_put_dev(urb->dev); ++ } + + if (retval == 0) + retval = -EINPROGRESS; +@@ -1529,6 +1547,17 @@ void usb_hcd_disable_endpoint(struct usb_device *udev, + hcd->driver->endpoint_disable(hcd, ep); + } + ++/* Protect against drivers that try to unlink URBs after the device ++ * is gone, by waiting until all unlinks for @udev are finished. ++ * Since we don't currently track URBs by device, simply wait until ++ * nothing is running in the locked region of usb_hcd_unlink_urb(). ++ */ ++void usb_hcd_synchronize_unlinks(struct usb_device *udev) ++{ ++ spin_lock_irq(&hcd_urb_unlink_lock); ++ spin_unlock_irq(&hcd_urb_unlink_lock); ++} ++ + /*-------------------------------------------------------------------------*/ + + /* called in any context */ +diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h +index 2dcde61..9465e70 100644 +--- a/drivers/usb/core/hcd.h ++++ b/drivers/usb/core/hcd.h +@@ -232,6 +232,7 @@ extern void usb_hcd_flush_endpoint(struct usb_device *udev, + struct usb_host_endpoint *ep); + extern void usb_hcd_disable_endpoint(struct usb_device *udev, + struct usb_host_endpoint *ep); ++extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); + extern int usb_hcd_get_frame_number(struct usb_device *udev); + + extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 875de9a..769f80f 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -1349,6 +1349,7 @@ void usb_disconnect(struct usb_device **pdev) + */ + dev_dbg (&udev->dev, "unregistering device\n"); + usb_disable_device(udev, 0); ++ usb_hcd_synchronize_unlinks(udev); + + usb_unlock_device(udev); + +diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c +index 47111e8..db72269 100644 +--- a/drivers/usb/core/urb.c ++++ b/drivers/usb/core/urb.c +@@ -465,6 +465,12 @@ EXPORT_SYMBOL_GPL(usb_submit_urb); + * indicating that the request has been canceled (rather than any other + * code). + * ++ * Drivers should not call this routine or related routines, such as ++ * usb_kill_urb() or usb_unlink_anchored_urbs(), after their disconnect ++ * method has returned. The disconnect function should synchronize with ++ * a driver's I/O routines to insure that all URB-related activity has ++ * completed before it returns. ++ * + * This request is always asynchronous. Success is indicated by + * returning -EINPROGRESS, at which time the URB will probably not yet + * have been given back to the device driver. When it is eventually +@@ -541,6 +547,9 @@ EXPORT_SYMBOL_GPL(usb_unlink_urb); + * This routine may not be used in an interrupt context (such as a bottom + * half or a completion handler), or when holding a spinlock, or in other + * situations where the caller can't schedule(). ++ * ++ * This routine should not be called by a driver after its disconnect ++ * method has returned. + */ + void usb_kill_urb(struct urb *urb) + { +@@ -568,6 +577,9 @@ EXPORT_SYMBOL_GPL(usb_kill_urb); + * + * this allows all outstanding URBs to be killed starting + * from the back of the queue ++ * ++ * This routine should not be called by a driver after its disconnect ++ * method has returned. + */ + void usb_kill_anchored_urbs(struct usb_anchor *anchor) + { +@@ -597,6 +609,9 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); + * from the back of the queue. This function is asynchronous. + * The unlinking is just tiggered. It may happen after this + * function has returned. ++ * ++ * This routine should not be called by a driver after its disconnect ++ * method has returned. + */ + void usb_unlink_anchored_urbs(struct usb_anchor *anchor) + { +diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h +index cd15547..061df9b 100644 +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -1745,6 +1745,15 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + ++/* Reported by Alexandre Oliva ++ * JMicron responds to USN and several other SCSI ioctls with a ++ * residue that causes subsequent I/O requests to fail. */ ++UNUSUAL_DEV( 0x152d, 0x2329, 0x0100, 0x0100, ++ "JMicron", ++ "USB to ATA/ATAPI Bridge", ++ US_SC_DEVICE, US_PR_DEVICE, NULL, ++ US_FL_IGNORE_RESIDUE ), ++ + /* Reported by Robert Schedel + * Note: this is a 'super top' device like the above 14cd/6600 device */ + UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, +diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c +index d128a25..ea30afc 100644 +--- a/fs/hfsplus/bitmap.c ++++ b/fs/hfsplus/bitmap.c +@@ -32,6 +32,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma + mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); + mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; + page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); ++ if (IS_ERR(page)) { ++ start = size; ++ goto out; ++ } + pptr = kmap(page); + curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; + i = offset % 32; +@@ -73,6 +77,10 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma + break; + page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, + NULL); ++ if (IS_ERR(page)) { ++ start = size; ++ goto out; ++ } + curr = pptr = kmap(page); + if ((size ^ offset) / PAGE_CACHE_BITS) + end = pptr + PAGE_CACHE_BITS / 32; +@@ -120,6 +128,10 @@ found: + offset += PAGE_CACHE_BITS; + page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, + NULL); ++ if (IS_ERR(page)) { ++ start = size; ++ goto out; ++ } + pptr = kmap(page); + curr = pptr; + end = pptr + PAGE_CACHE_BITS / 32; +diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c +index ba117c4..f6874ac 100644 +--- a/fs/hfsplus/catalog.c ++++ b/fs/hfsplus/catalog.c +@@ -168,6 +168,11 @@ int hfsplus_find_cat(struct super_block *sb, u32 cnid, + return -EIO; + } + ++ if (be16_to_cpu(tmp.thread.nodeName.length) > 255) { ++ printk(KERN_ERR "hfs: catalog name length corrupted\n"); ++ return -EIO; ++ } ++ + hfsplus_cat_build_key_uni(fd->search_key, be32_to_cpu(tmp.thread.parentID), + &tmp.thread.nodeName); + return hfs_brec_find(fd); +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 3d9120c..6bfb849 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -1286,7 +1286,9 @@ struct task_struct { + atomic_t fs_excl; /* holding fs exclusive resources */ + struct rcu_head rcu; + +- /* ++ struct list_head *scm_work_list; ++ ++/* + * cache last used pipe for splice + */ + struct pipe_inode_info *splice_pipe; +diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h +index bb46e76..408f743 100644 +--- a/include/math-emu/op-common.h ++++ b/include/math-emu/op-common.h +@@ -139,18 +139,27 @@ do { \ + if (X##_e <= _FP_WFRACBITS_##fs) \ + { \ + _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ +- _FP_ROUND(wc, X); \ + if (_FP_FRAC_HIGH_##fs(X) \ + & (_FP_OVERFLOW_##fs >> 1)) \ + { \ + X##_e = 1; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ +- FP_SET_EXCEPTION(FP_EX_INEXACT); \ + } \ + else \ + { \ +- X##_e = 0; \ +- _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ ++ _FP_ROUND(wc, X); \ ++ if (_FP_FRAC_HIGH_##fs(X) \ ++ & (_FP_OVERFLOW_##fs >> 1)) \ ++ { \ ++ X##_e = 1; \ ++ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ ++ FP_SET_EXCEPTION(FP_EX_INEXACT); \ ++ } \ ++ else \ ++ { \ ++ X##_e = 0; \ ++ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ ++ } \ + } \ + if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) || \ + (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ +diff --git a/include/net/scm.h b/include/net/scm.h +index 06df126..33e9986 100644 +--- a/include/net/scm.h ++++ b/include/net/scm.h +@@ -14,8 +14,9 @@ + + struct scm_fp_list + { +- int count; +- struct file *fp[SCM_MAX_FD]; ++ struct list_head list; ++ int count; ++ struct file *fp[SCM_MAX_FD]; + }; + + struct scm_cookie +diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c +index e8ab096..8178724 100644 +--- a/kernel/sched_clock.c ++++ b/kernel/sched_clock.c +@@ -118,13 +118,13 @@ static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now) + + /* + * scd->clock = clamp(scd->tick_gtod + delta, +- * max(scd->tick_gtod, scd->clock), +- * scd->tick_gtod + TICK_NSEC); ++ * max(scd->tick_gtod, scd->clock), ++ * max(scd->clock, scd->tick_gtod + TICK_NSEC)); + */ + + clock = scd->tick_gtod + delta; + min_clock = wrap_max(scd->tick_gtod, scd->clock); +- max_clock = scd->tick_gtod + TICK_NSEC; ++ max_clock = wrap_max(scd->clock, scd->tick_gtod + TICK_NSEC); + + clock = wrap_max(clock, min_clock); + clock = wrap_min(clock, max_clock); +diff --git a/kernel/sched_features.h b/kernel/sched_features.h +index 9353ca7..c4c88ae 100644 +--- a/kernel/sched_features.h ++++ b/kernel/sched_features.h +@@ -5,7 +5,7 @@ SCHED_FEAT(START_DEBIT, 1) + SCHED_FEAT(AFFINE_WAKEUPS, 1) + SCHED_FEAT(CACHE_HOT_BUDDY, 1) + SCHED_FEAT(SYNC_WAKEUPS, 1) +-SCHED_FEAT(HRTICK, 1) ++SCHED_FEAT(HRTICK, 0) + SCHED_FEAT(DOUBLE_TICK, 0) + SCHED_FEAT(ASYM_GRAN, 1) + SCHED_FEAT(LB_BIAS, 1) +diff --git a/net/core/scm.c b/net/core/scm.c +index 10f5c65..ab242cc 100644 +--- a/net/core/scm.c ++++ b/net/core/scm.c +@@ -75,6 +75,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) + if (!fpl) + return -ENOMEM; + *fplp = fpl; ++ INIT_LIST_HEAD(&fpl->list); + fpl->count = 0; + } + fpp = &fpl->fp[fpl->count]; +@@ -106,9 +107,25 @@ void __scm_destroy(struct scm_cookie *scm) + + if (fpl) { + scm->fp = NULL; +- for (i=fpl->count-1; i>=0; i--) +- fput(fpl->fp[i]); +- kfree(fpl); ++ if (current->scm_work_list) { ++ list_add_tail(&fpl->list, current->scm_work_list); ++ } else { ++ LIST_HEAD(work_list); ++ ++ current->scm_work_list = &work_list; ++ ++ list_add(&fpl->list, &work_list); ++ while (!list_empty(&work_list)) { ++ fpl = list_first_entry(&work_list, struct scm_fp_list, list); ++ ++ list_del(&fpl->list); ++ for (i=fpl->count-1; i>=0; i--) ++ fput(fpl->fp[i]); ++ kfree(fpl); ++ } ++ ++ current->scm_work_list = NULL; ++ } + } + } + +@@ -284,6 +301,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) + + new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); + if (new_fpl) { ++ INIT_LIST_HEAD(&new_fpl->list); + for (i=fpl->count-1; i>=0; i--) + get_file(fpl->fp[i]); + memcpy(new_fpl, fpl, sizeof(*fpl)); +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index 8165f5a..d083f9a 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -357,6 +357,17 @@ struct tcp_out_options { + __u32 tsval, tsecr; /* need to include OPTION_TS */ + }; + ++/* Beware: Something in the Internet is very sensitive to the ordering of ++ * TCP options, we learned this through the hard way, so be careful here. ++ * Luckily we can at least blame others for their non-compliance but from ++ * inter-operatibility perspective it seems that we're somewhat stuck with ++ * the ordering which we have been using if we want to keep working with ++ * those broken things (not that it currently hurts anybody as there isn't ++ * particular reason why the ordering would need to be changed). ++ * ++ * At least SACK_PERM as the first option is known to lead to a disaster ++ * (but it may well be that other scenarios fail similarly). ++ */ + static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, + const struct tcp_out_options *opts, + __u8 **md5_hash) { +@@ -371,6 +382,12 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, + *md5_hash = NULL; + } + ++ if (unlikely(opts->mss)) { ++ *ptr++ = htonl((TCPOPT_MSS << 24) | ++ (TCPOLEN_MSS << 16) | ++ opts->mss); ++ } ++ + if (likely(OPTION_TS & opts->options)) { + if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) { + *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | +@@ -387,12 +404,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, + *ptr++ = htonl(opts->tsecr); + } + +- if (unlikely(opts->mss)) { +- *ptr++ = htonl((TCPOPT_MSS << 24) | +- (TCPOLEN_MSS << 16) | +- opts->mss); +- } +- + if (unlikely(OPTION_SACK_ADVERTISE & opts->options && + !(OPTION_TS & opts->options))) { + *ptr++ = htonl((TCPOPT_NOP << 24) | +@@ -2266,6 +2277,11 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, + } + + memset(&opts, 0, sizeof(opts)); ++#ifdef CONFIG_SYN_COOKIES ++ if (unlikely(req->cookie_ts)) ++ TCP_SKB_CB(skb)->when = cookie_init_timestamp(req); ++ else ++#endif + TCP_SKB_CB(skb)->when = tcp_time_stamp; + tcp_header_size = tcp_synack_options(sk, req, + dst_metric(dst, RTAX_ADVMSS), +@@ -2292,11 +2308,6 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, + + /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ + th->window = htons(min(req->rcv_wnd, 65535U)); +-#ifdef CONFIG_SYN_COOKIES +- if (unlikely(req->cookie_ts)) +- TCP_SKB_CB(skb)->when = cookie_init_timestamp(req); +- else +-#endif + tcp_options_write((__be32 *)(th + 1), tp, &opts, &md5_hash_location); + th->doff = (tcp_header_size >> 2); + TCP_INC_STATS(sock_net(sk), TCP_MIB_OUTSEGS); +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 10e22fd..245cbc5 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1087,7 +1087,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); + *topt++ = htonl(tcp_time_stamp); +- *topt = htonl(ts); ++ *topt++ = htonl(ts); + } + + #ifdef CONFIG_TCP_MD5SIG +diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c +index ec0a083..700ae9e 100644 +--- a/net/sched/sch_generic.c ++++ b/net/sched/sch_generic.c +@@ -319,6 +319,7 @@ struct Qdisc_ops noop_qdisc_ops __read_mostly = { + + static struct netdev_queue noop_netdev_queue = { + .qdisc = &noop_qdisc, ++ .qdisc_sleeping = &noop_qdisc, + }; + + struct Qdisc noop_qdisc = { +@@ -344,6 +345,7 @@ static struct Qdisc_ops noqueue_qdisc_ops __read_mostly = { + static struct Qdisc noqueue_qdisc; + static struct netdev_queue noqueue_netdev_queue = { + .qdisc = &noqueue_qdisc, ++ .qdisc_sleeping = &noqueue_qdisc, + }; + + static struct Qdisc noqueue_qdisc = { +diff --git a/scripts/package/mkspec b/scripts/package/mkspec +index ffd61fe..62c5ffd 100755 +--- a/scripts/package/mkspec ++++ b/scripts/package/mkspec +@@ -64,8 +64,10 @@ fi + echo "%install" + echo "%ifarch ia64" + echo 'mkdir -p $RPM_BUILD_ROOT/boot/efi $RPM_BUILD_ROOT/lib/modules' ++echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware' + echo "%else" + echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib/modules' ++echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware' + echo "%endif" + + echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} modules_install' +@@ -92,5 +94,6 @@ echo "%files" + echo '%defattr (-, root, root)' + echo "%dir /lib/modules" + echo "/lib/modules/$KERNELRELEASE" ++echo "/lib/firmware" + echo "/boot/*" + echo "" +diff --git a/security/commoncap.c b/security/commoncap.c +index e4c4b3f..378172b 100644 +--- a/security/commoncap.c ++++ b/security/commoncap.c +@@ -279,10 +279,10 @@ static int get_file_caps(struct linux_binprm *bprm) + struct vfs_cap_data vcaps; + struct inode *inode; + +- if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) { +- bprm_clear_caps(bprm); ++ bprm_clear_caps(bprm); ++ ++ if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) + return 0; +- } + + dentry = dget(bprm->file->f_dentry); + inode = dentry->d_inode; +diff --git a/sound/core/control.c b/sound/core/control.c +index 281b2e2..236bbb1 100644 +--- a/sound/core/control.c ++++ b/sound/core/control.c +@@ -1427,12 +1427,12 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) + cardnum = card->number; + snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); + +- down_read(&card->controls_rwsem); ++ read_lock(&card->ctl_files_rwlock); + list_for_each_entry(ctl, &card->ctl_files, list) { + wake_up(&ctl->change_sleep); + kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); + } +- up_read(&card->controls_rwsem); ++ read_unlock(&card->ctl_files_rwlock); + + if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, + card, -1)) < 0) +diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c +index 1c53e33..0f014b1 100644 +--- a/sound/pci/hda/hda_intel.c ++++ b/sound/pci/hda/hda_intel.c +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include + #include + #include "hda_codec.h" +@@ -385,6 +386,9 @@ struct azx { + + /* for pending irqs */ + struct work_struct irq_pending_work; ++ ++ /* reboot notifier (for mysterious hangup problem at power-down) */ ++ struct notifier_block reboot_notifier; + }; + + /* driver types */ +@@ -1890,12 +1894,36 @@ static int azx_resume(struct pci_dev *pci) + + + /* ++ * reboot notifier for hang-up problem at power-down ++ */ ++static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf) ++{ ++ struct azx *chip = container_of(nb, struct azx, reboot_notifier); ++ azx_stop_chip(chip); ++ return NOTIFY_OK; ++} ++ ++static void azx_notifier_register(struct azx *chip) ++{ ++ chip->reboot_notifier.notifier_call = azx_halt; ++ register_reboot_notifier(&chip->reboot_notifier); ++} ++ ++static void azx_notifier_unregister(struct azx *chip) ++{ ++ if (chip->reboot_notifier.notifier_call) ++ unregister_reboot_notifier(&chip->reboot_notifier); ++} ++ ++/* + * destructor + */ + static int azx_free(struct azx *chip) + { + int i; + ++ azx_notifier_unregister(chip); ++ + if (chip->initialized) { + azx_clear_irq_pending(chip); + for (i = 0; i < chip->num_streams; i++) +@@ -2250,6 +2278,7 @@ static int __devinit azx_probe(struct pci_dev *pci, + pci_set_drvdata(pci, card); + chip->running = 1; + power_down_all_codecs(chip); ++ azx_notifier_register(chip); + + dev++; + return err; diff --git a/debian/patches/bugfix/all/stable/patch-2.6.27.6 b/debian/patches/bugfix/all/stable/patch-2.6.27.6 new file mode 100644 index 000000000..93d4dcfbe --- /dev/null +++ b/debian/patches/bugfix/all/stable/patch-2.6.27.6 @@ -0,0 +1,2220 @@ +diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt +index 8244c64..48d80d9 100644 +--- a/Documentation/cciss.txt ++++ b/Documentation/cciss.txt +@@ -26,6 +26,8 @@ This driver is known to work with the following cards: + * SA P410i + * SA P411 + * SA P812 ++ * SA P712m ++ * SA P711m + + Detecting drive failures: + ------------------------- +diff --git a/arch/arm/mach-pxa/include/mach/reset.h b/arch/arm/mach-pxa/include/mach/reset.h +index 9489a48..7b8842c 100644 +--- a/arch/arm/mach-pxa/include/mach/reset.h ++++ b/arch/arm/mach-pxa/include/mach/reset.h +@@ -10,9 +10,12 @@ + extern unsigned int reset_status; + extern void clear_reset_status(unsigned int mask); + +-/* +- * register GPIO as reset generator ++/** ++ * init_gpio_reset() - register GPIO as reset generator ++ * ++ * @gpio - gpio nr ++ * @output - set gpio as out/low instead of input during normal work + */ +-extern int init_gpio_reset(int gpio); ++extern int init_gpio_reset(int gpio, int output); + + #endif /* __ASM_ARCH_RESET_H */ +diff --git a/arch/arm/mach-pxa/reset.c b/arch/arm/mach-pxa/reset.c +index 9996c61..1b236a6 100644 +--- a/arch/arm/mach-pxa/reset.c ++++ b/arch/arm/mach-pxa/reset.c +@@ -20,7 +20,7 @@ static void do_hw_reset(void); + + static int reset_gpio = -1; + +-int init_gpio_reset(int gpio) ++int init_gpio_reset(int gpio, int output) + { + int rc; + +@@ -30,9 +30,12 @@ int init_gpio_reset(int gpio) + goto out; + } + +- rc = gpio_direction_input(gpio); ++ if (output) ++ rc = gpio_direction_output(gpio, 0); ++ else ++ rc = gpio_direction_input(gpio); + if (rc) { +- printk(KERN_ERR "Can't configure reset_gpio for input\n"); ++ printk(KERN_ERR "Can't configure reset_gpio\n"); + gpio_free(gpio); + goto out; + } +diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c +index b569f3b..32cee4c 100644 +--- a/arch/arm/mach-pxa/spitz.c ++++ b/arch/arm/mach-pxa/spitz.c +@@ -548,7 +548,7 @@ static void spitz_restart(char mode) + + static void __init common_init(void) + { +- init_gpio_reset(SPITZ_GPIO_ON_RESET); ++ init_gpio_reset(SPITZ_GPIO_ON_RESET, 1); + pm_power_off = spitz_poweroff; + arm_pm_restart = spitz_restart; + +diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c +index 9f3ef9e..130e37e 100644 +--- a/arch/arm/mach-pxa/tosa.c ++++ b/arch/arm/mach-pxa/tosa.c +@@ -781,7 +781,7 @@ static void __init tosa_init(void) + gpio_set_wake(MFP_PIN_GPIO1, 1); + /* We can't pass to gpio-keys since it will drop the Reset altfunc */ + +- init_gpio_reset(TOSA_GPIO_ON_RESET); ++ init_gpio_reset(TOSA_GPIO_ON_RESET, 0); + + pm_power_off = tosa_poweroff; + arm_pm_restart = tosa_restart; +diff --git a/arch/arm/mm/cache-xsc3l2.c b/arch/arm/mm/cache-xsc3l2.c +index 158bd96..99ec030 100644 +--- a/arch/arm/mm/cache-xsc3l2.c ++++ b/arch/arm/mm/cache-xsc3l2.c +@@ -97,7 +97,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) + /* + * Clean and invalidate partial last cache line. + */ +- if (end & (CACHE_LINE_SIZE - 1)) { ++ if (start < end && (end & (CACHE_LINE_SIZE - 1))) { + xsc3_l2_clean_pa(end & ~(CACHE_LINE_SIZE - 1)); + xsc3_l2_inv_pa(end & ~(CACHE_LINE_SIZE - 1)); + end &= ~(CACHE_LINE_SIZE - 1); +@@ -106,7 +106,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end) + /* + * Invalidate all full cache lines between 'start' and 'end'. + */ +- while (start != end) { ++ while (start < end) { + xsc3_l2_inv_pa(start); + start += CACHE_LINE_SIZE; + } +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index ed92864..552d2b7 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -1059,6 +1059,26 @@ config HIGHPTE + low memory. Setting this option will put user-space page table + entries in high memory. + ++config X86_RESERVE_LOW_64K ++ bool "Reserve low 64K of RAM on AMI/Phoenix BIOSen" ++ default y ++ help ++ Reserve the first 64K of physical RAM on BIOSes that are known ++ to potentially corrupt that memory range. A numbers of BIOSes are ++ known to utilize this area during suspend/resume, so it must not ++ be used by the kernel. ++ ++ Set this to N if you are absolutely sure that you trust the BIOS ++ to get all its memory reservations and usages right. ++ ++ If you have doubts about the BIOS (e.g. suspend/resume does not ++ work or there's kernel crashes after certain hardware hotplug ++ events) and it's not AMI or Phoenix, then you might want to enable ++ X86_CHECK_BIOS_CORRUPTION=y to allow the kernel to check typical ++ corruption patterns. ++ ++ Say Y if unsure. ++ + config MATH_EMULATION + bool + prompt "Math emulation" if X86_32 +diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c +index 9838f25..64b5c42 100644 +--- a/arch/x86/kernel/setup.c ++++ b/arch/x86/kernel/setup.c +@@ -578,6 +578,39 @@ static struct x86_quirks default_x86_quirks __initdata; + + struct x86_quirks *x86_quirks __initdata = &default_x86_quirks; + ++static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) ++{ ++ printk(KERN_NOTICE ++ "%s detected: BIOS may corrupt low RAM, working it around.\n", ++ d->ident); ++ ++ e820_update_range(0, 0x10000, E820_RAM, E820_RESERVED); ++ sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); ++ ++ return 0; ++} ++ ++/* List of systems that have known low memory corruption BIOS problems */ ++static struct dmi_system_id __initdata bad_bios_dmi_table[] = { ++#ifdef CONFIG_X86_RESERVE_LOW_64K ++ { ++ .callback = dmi_low_memory_corruption, ++ .ident = "AMI BIOS", ++ .matches = { ++ DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), ++ }, ++ }, ++ { ++ .callback = dmi_low_memory_corruption, ++ .ident = "Phoenix BIOS", ++ .matches = { ++ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"), ++ }, ++ }, ++#endif ++ {} ++}; ++ + /* + * Determine if we were loaded by an EFI loader. If so, then we have also been + * passed the efi memmap, systab, etc., so we should use these data structures +@@ -699,6 +732,10 @@ void __init setup_arch(char **cmdline_p) + + finish_e820_parsing(); + ++ dmi_scan_machine(); ++ ++ dmi_check_system(bad_bios_dmi_table); ++ + #ifdef CONFIG_X86_32 + probe_roms(); + #endif +@@ -781,8 +818,6 @@ void __init setup_arch(char **cmdline_p) + vsmp_init(); + #endif + +- dmi_scan_machine(); +- + io_delay_init(); + + /* +@@ -885,3 +920,5 @@ void __init setup_arch(char **cmdline_p) + #endif + #endif + } ++ ++ +diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c +index 8f98e9d..de850e9 100644 +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -639,10 +639,6 @@ void __init tsc_init(void) + cpu_khz = calibrate_cpu(); + #endif + +- lpj = ((u64)tsc_khz * 1000); +- do_div(lpj, HZ); +- lpj_fine = lpj; +- + printk("Detected %lu.%03lu MHz processor.\n", + (unsigned long)cpu_khz / 1000, + (unsigned long)cpu_khz % 1000); +@@ -662,6 +658,10 @@ void __init tsc_init(void) + /* now allow native_sched_clock() to use rdtsc */ + tsc_disabled = 0; + ++ lpj = ((u64)tsc_khz * 1000); ++ do_div(lpj, HZ); ++ lpj_fine = lpj; ++ + use_tsc_delay(); + /* Check and install the TSC clocksource */ + dmi_check_system(bad_tsc_dmi_table); +diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c +index 7d2edf1..25d2161 100644 +--- a/drivers/acpi/dock.c ++++ b/drivers/acpi/dock.c +@@ -604,14 +604,17 @@ static int handle_eject_request(struct dock_station *ds, u32 event) + static void dock_notify(acpi_handle handle, u32 event, void *data) + { + struct dock_station *ds = data; ++ struct acpi_device *tmp; + + switch (event) { + case ACPI_NOTIFY_BUS_CHECK: +- if (!dock_in_progress(ds) && dock_present(ds)) { ++ if (!dock_in_progress(ds) && acpi_bus_get_device(ds->handle, ++ &tmp)) { + begin_dock(ds); + dock(ds); + if (!dock_present(ds)) { + printk(KERN_ERR PREFIX "Unable to dock!\n"); ++ complete_dock(ds); + break; + } + atomic_notifier_call_chain(&dock_notifier_list, +diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c +index c1db2f2..2c4ccec 100644 +--- a/drivers/ata/libata-eh.c ++++ b/drivers/ata/libata-eh.c +@@ -604,9 +604,6 @@ void ata_scsi_error(struct Scsi_Host *host) + if (ata_ncq_enabled(dev)) + ehc->saved_ncq_enabled |= 1 << devno; + } +- +- /* set last reset timestamp to some time in the past */ +- ehc->last_reset = jiffies - 60 * HZ; + } + + ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS; +@@ -2209,17 +2206,21 @@ int ata_eh_reset(struct ata_link *link, int classify, + if (link->flags & ATA_LFLAG_NO_SRST) + softreset = NULL; + +- now = jiffies; +- deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); +- if (time_before(now, deadline)) +- schedule_timeout_uninterruptible(deadline - now); ++ /* make sure each reset attemp is at least COOL_DOWN apart */ ++ if (ehc->i.flags & ATA_EHI_DID_RESET) { ++ now = jiffies; ++ WARN_ON(time_after(ehc->last_reset, now)); ++ deadline = ata_deadline(ehc->last_reset, ++ ATA_EH_RESET_COOL_DOWN); ++ if (time_before(now, deadline)) ++ schedule_timeout_uninterruptible(deadline - now); ++ } + + spin_lock_irqsave(ap->lock, flags); + ap->pflags |= ATA_PFLAG_RESETTING; + spin_unlock_irqrestore(ap->lock, flags); + + ata_eh_about_to_do(link, NULL, ATA_EH_RESET); +- ehc->last_reset = jiffies; + + ata_link_for_each_dev(dev, link) { + /* If we issue an SRST then an ATA drive (not ATAPI) +@@ -2285,7 +2286,6 @@ int ata_eh_reset(struct ata_link *link, int classify, + /* + * Perform reset + */ +- ehc->last_reset = jiffies; + if (ata_is_host_link(link)) + ata_eh_freeze_port(ap); + +@@ -2297,6 +2297,7 @@ int ata_eh_reset(struct ata_link *link, int classify, + reset == softreset ? "soft" : "hard"); + + /* mark that this EH session started with reset */ ++ ehc->last_reset = jiffies; + if (reset == hardreset) + ehc->i.flags |= ATA_EHI_DID_HARDRESET; + else +@@ -2404,7 +2405,7 @@ int ata_eh_reset(struct ata_link *link, int classify, + + /* reset successful, schedule revalidation */ + ata_eh_done(link, NULL, ATA_EH_RESET); +- ehc->last_reset = jiffies; ++ ehc->last_reset = jiffies; /* update to completion time */ + ehc->i.action |= ATA_EH_REVALIDATE; + + rc = 0; +diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c +index b73116e..2ac91b8 100644 +--- a/drivers/block/cciss.c ++++ b/drivers/block/cciss.c +@@ -96,6 +96,8 @@ static const struct pci_device_id cciss_pci_device_id[] = { + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, ++ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, + {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, + {0,} +@@ -133,6 +135,8 @@ static struct board_type products[] = { + {0x3245103C, "Smart Array P410i", &SA5_access}, + {0x3247103C, "Smart Array P411", &SA5_access}, + {0x3249103C, "Smart Array P812", &SA5_access}, ++ {0x324A103C, "Smart Array P712m", &SA5_access}, ++ {0x324B103C, "Smart Array P711m", &SA5_access}, + {0xFFFF103C, "Unknown Smart Array", &SA5_access}, + }; + +@@ -1365,6 +1369,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, + disk->first_minor = drv_index << NWD_SHIFT; + disk->fops = &cciss_fops; + disk->private_data = &h->drv[drv_index]; ++ disk->driverfs_dev = &h->pdev->dev; + + /* Set up queue information */ + blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); +@@ -3403,7 +3408,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, + int i; + int j = 0; + int rc; +- int dac; ++ int dac, return_code; ++ InquiryData_struct *inq_buff = NULL; + + i = alloc_cciss_hba(); + if (i < 0) +@@ -3509,6 +3515,25 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, + /* Turn the interrupts on so we can service requests */ + hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); + ++ /* Get the firmware version */ ++ inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL); ++ if (inq_buff == NULL) { ++ printk(KERN_ERR "cciss: out of memory\n"); ++ goto clean4; ++ } ++ ++ return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff, ++ sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD); ++ if (return_code == IO_OK) { ++ hba[i]->firm_ver[0] = inq_buff->data_byte[32]; ++ hba[i]->firm_ver[1] = inq_buff->data_byte[33]; ++ hba[i]->firm_ver[2] = inq_buff->data_byte[34]; ++ hba[i]->firm_ver[3] = inq_buff->data_byte[35]; ++ } else { /* send command failed */ ++ printk(KERN_WARNING "cciss: unable to determine firmware" ++ " version of controller\n"); ++ } ++ + cciss_procinit(i); + + hba[i]->cciss_max_sectors = 2048; +@@ -3519,6 +3544,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, + return 1; + + clean4: ++ kfree(inq_buff); + #ifdef CONFIG_CISS_SCSI_TAPE + kfree(hba[i]->scsi_rejects.complete); + #endif +diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c +index 09c1434..f5d2e54 100644 +--- a/drivers/block/cpqarray.c ++++ b/drivers/block/cpqarray.c +@@ -567,7 +567,12 @@ static int __init cpqarray_init(void) + num_cntlrs_reg++; + } + +- return(num_cntlrs_reg); ++ if (num_cntlrs_reg) ++ return 0; ++ else { ++ pci_unregister_driver(&cpqarray_pci_driver); ++ return -ENODEV; ++ } + } + + /* Function to find the first free pointer into our hba[] array */ +diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c +index ec249d2..d883e1b 100644 +--- a/drivers/dca/dca-core.c ++++ b/drivers/dca/dca-core.c +@@ -270,6 +270,6 @@ static void __exit dca_exit(void) + dca_sysfs_exit(); + } + +-module_init(dca_init); ++subsys_initcall(dca_init); + module_exit(dca_exit); + +diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c +index bc8c6e3..3f4db54 100644 +--- a/drivers/dma/ioat_dma.c ++++ b/drivers/dma/ioat_dma.c +@@ -519,7 +519,7 @@ static dma_cookie_t ioat1_tx_submit(struct dma_async_tx_descriptor *tx) + } + + hw->ctl = IOAT_DMA_DESCRIPTOR_CTL_CP_STS; +- if (new->async_tx.callback) { ++ if (first->async_tx.callback) { + hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; + if (first != new) { + /* move callback into to last desc */ +@@ -611,7 +611,7 @@ static dma_cookie_t ioat2_tx_submit(struct dma_async_tx_descriptor *tx) + } + + hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_CP_STS; +- if (new->async_tx.callback) { ++ if (first->async_tx.callback) { + hw->ctl |= IOAT_DMA_DESCRIPTOR_CTL_INT_GN; + if (first != new) { + /* move callback into to last desc */ +@@ -801,6 +801,12 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) + struct ioat_desc_sw *desc, *_desc; + int in_use_descs = 0; + ++ /* Before freeing channel resources first check ++ * if they have been previously allocated for this channel. ++ */ ++ if (ioat_chan->desccount == 0) ++ return; ++ + tasklet_disable(&ioat_chan->cleanup_task); + ioat_dma_memcpy_cleanup(ioat_chan); + +@@ -863,6 +869,7 @@ static void ioat_dma_free_chan_resources(struct dma_chan *chan) + ioat_chan->last_completion = ioat_chan->completion_addr = 0; + ioat_chan->pending = 0; + ioat_chan->dmacount = 0; ++ ioat_chan->desccount = 0; + ioat_chan->watchdog_completion = 0; + ioat_chan->last_compl_desc_addr_hw = 0; + ioat_chan->watchdog_tcp_cookie = +diff --git a/drivers/dma/iovlock.c b/drivers/dma/iovlock.c +index e763d72..9f6fe46 100644 +--- a/drivers/dma/iovlock.c ++++ b/drivers/dma/iovlock.c +@@ -55,7 +55,6 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) + int nr_iovecs = 0; + int iovec_len_used = 0; + int iovec_pages_used = 0; +- long err; + + /* don't pin down non-user-based iovecs */ + if (segment_eq(get_fs(), KERNEL_DS)) +@@ -72,23 +71,21 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) + local_list = kmalloc(sizeof(*local_list) + + (nr_iovecs * sizeof (struct dma_page_list)) + + (iovec_pages_used * sizeof (struct page*)), GFP_KERNEL); +- if (!local_list) { +- err = -ENOMEM; ++ if (!local_list) + goto out; +- } + + /* list of pages starts right after the page list array */ + pages = (struct page **) &local_list->page_list[nr_iovecs]; + ++ local_list->nr_iovecs = 0; ++ + for (i = 0; i < nr_iovecs; i++) { + struct dma_page_list *page_list = &local_list->page_list[i]; + + len -= iov[i].iov_len; + +- if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) { +- err = -EFAULT; ++ if (!access_ok(VERIFY_WRITE, iov[i].iov_base, iov[i].iov_len)) + goto unpin; +- } + + page_list->nr_pages = num_pages_spanned(&iov[i]); + page_list->base_address = iov[i].iov_base; +@@ -109,10 +106,8 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) + NULL); + up_read(¤t->mm->mmap_sem); + +- if (ret != page_list->nr_pages) { +- err = -ENOMEM; ++ if (ret != page_list->nr_pages) + goto unpin; +- } + + local_list->nr_iovecs = i + 1; + } +@@ -122,7 +117,7 @@ struct dma_pinned_list *dma_pin_iovec_pages(struct iovec *iov, size_t len) + unpin: + dma_unpin_iovec_pages(local_list); + out: +- return ERR_PTR(err); ++ return NULL; + } + + void dma_unpin_iovec_pages(struct dma_pinned_list *pinned_list) +diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c +index c40f040..8c030d9 100644 +--- a/drivers/hid/hidraw.c ++++ b/drivers/hid/hidraw.c +@@ -113,7 +113,7 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t + if (!dev->hid_output_raw_report) + return -ENODEV; + +- if (count > HID_MIN_BUFFER_SIZE) { ++ if (count > HID_MAX_BUFFER_SIZE) { + printk(KERN_WARNING "hidraw: pid %d passed too large report\n", + task_pid_nr(current)); + return -EINVAL; +diff --git a/drivers/md/linear.c b/drivers/md/linear.c +index b1eebf8..a58a19e 100644 +--- a/drivers/md/linear.c ++++ b/drivers/md/linear.c +@@ -157,6 +157,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) + + min_spacing = conf->array_sectors / 2; + sector_div(min_spacing, PAGE_SIZE/sizeof(struct dev_info *)); ++ if (min_spacing == 0) ++ min_spacing = 1; + + /* min_spacing is the minimum spacing that will fit the hash + * table in one PAGE. This may be much smaller than needed. +diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c +index e34cd0e..941576d 100644 +--- a/drivers/md/raid10.c ++++ b/drivers/md/raid10.c +@@ -1132,7 +1132,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) + if (!enough(conf)) + return -EINVAL; + +- if (rdev->raid_disk) ++ if (rdev->raid_disk >= 0) + first = last = rdev->raid_disk; + + if (rdev->saved_raid_disk >= 0 && +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 044d84e..f7284b9 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -280,7 +280,11 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) + (card->host->ios.clock / 1000); + + if (data->flags & MMC_DATA_WRITE) +- limit_us = 250000; ++ /* ++ * The limit is really 250 ms, but that is ++ * insufficient for some crappy cards. ++ */ ++ limit_us = 300000; + else + limit_us = 100000; + +diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c +index a972cc6..9e7a236 100644 +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -362,19 +362,6 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) + /* Set the default CFI lock/unlock addresses */ + cfi->addr_unlock1 = 0x555; + cfi->addr_unlock2 = 0x2aa; +- /* Modify the unlock address if we are in compatibility mode */ +- if ( /* x16 in x8 mode */ +- ((cfi->device_type == CFI_DEVICETYPE_X8) && +- (cfi->cfiq->InterfaceDesc == +- CFI_INTERFACE_X8_BY_X16_ASYNC)) || +- /* x32 in x16 mode */ +- ((cfi->device_type == CFI_DEVICETYPE_X16) && +- (cfi->cfiq->InterfaceDesc == +- CFI_INTERFACE_X16_BY_X32_ASYNC))) +- { +- cfi->addr_unlock1 = 0xaaa; +- cfi->addr_unlock2 = 0x555; +- } + + } /* CFI mode */ + else if (cfi->cfi_mode == CFI_MODE_JEDEC) { +diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c +index f84ab61..2f3f2f7 100644 +--- a/drivers/mtd/chips/jedec_probe.c ++++ b/drivers/mtd/chips/jedec_probe.c +@@ -1808,9 +1808,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, uint32_t base, + * several first banks can contain 0x7f instead of actual ID + */ + do { +- uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), +- cfi_interleave(cfi), +- cfi->device_type); ++ uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi); + mask = (1 << (cfi->device_type * 8)) - 1; + result = map_read(map, base + ofs); + bank++; +@@ -1824,7 +1822,7 @@ static inline u32 jedec_read_id(struct map_info *map, uint32_t base, + { + map_word result; + unsigned long mask; +- u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type); ++ u32 ofs = cfi_build_cmd_addr(1, map, cfi); + mask = (1 << (cfi->device_type * 8)) -1; + result = map_read(map, base + ofs); + return result.x[0] & mask; +@@ -2067,8 +2065,8 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, + + } + /* Ensure the unlock addresses we try stay inside the map */ +- probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, cfi_interleave(cfi), cfi->device_type); +- probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, cfi_interleave(cfi), cfi->device_type); ++ probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, map, cfi); ++ probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, map, cfi); + if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || + ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) + goto retry; +diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c +index 0f6f974..39c17bb 100644 +--- a/drivers/net/r8169.c ++++ b/drivers/net/r8169.c +@@ -370,8 +370,9 @@ struct ring_info { + }; + + enum features { +- RTL_FEATURE_WOL = (1 << 0), +- RTL_FEATURE_MSI = (1 << 1), ++ RTL_FEATURE_WOL = (1 << 0), ++ RTL_FEATURE_MSI = (1 << 1), ++ RTL_FEATURE_GMII = (1 << 2), + }; + + struct rtl8169_private { +@@ -406,13 +407,15 @@ struct rtl8169_private { + struct vlan_group *vlgrp; + #endif + int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex); +- void (*get_settings)(struct net_device *, struct ethtool_cmd *); ++ int (*get_settings)(struct net_device *, struct ethtool_cmd *); + void (*phy_reset_enable)(void __iomem *); + void (*hw_start)(struct net_device *); + unsigned int (*phy_reset_pending)(void __iomem *); + unsigned int (*link_ok)(void __iomem *); + struct delayed_work task; + unsigned features; ++ ++ struct mii_if_info mii; + }; + + MODULE_AUTHOR("Realtek and the Linux r8169 crew "); +@@ -482,6 +485,23 @@ static int mdio_read(void __iomem *ioaddr, int reg_addr) + return value; + } + ++static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, ++ int val) ++{ ++ struct rtl8169_private *tp = netdev_priv(dev); ++ void __iomem *ioaddr = tp->mmio_addr; ++ ++ mdio_write(ioaddr, location, val); ++} ++ ++static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) ++{ ++ struct rtl8169_private *tp = netdev_priv(dev); ++ void __iomem *ioaddr = tp->mmio_addr; ++ ++ return mdio_read(ioaddr, location); ++} ++ + static void rtl8169_irq_mask_and_ack(void __iomem *ioaddr) + { + RTL_W16(IntrMask, 0x0000); +@@ -720,9 +740,13 @@ static int rtl8169_set_speed_xmii(struct net_device *dev, + + auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; + +- if ((tp->mac_version == RTL_GIGA_MAC_VER_12) || +- (tp->mac_version == RTL_GIGA_MAC_VER_17)) { +- /* Vendor specific (0x1f) and reserved (0x0e) MII registers. */ ++ if ((tp->mac_version == RTL_GIGA_MAC_VER_11) || ++ (tp->mac_version == RTL_GIGA_MAC_VER_12) || ++ (tp->mac_version >= RTL_GIGA_MAC_VER_17)) { ++ /* ++ * Wake up the PHY. ++ * Vendor specific (0x1f) and reserved (0x0e) MII registers. ++ */ + mdio_write(ioaddr, 0x1f, 0x0000); + mdio_write(ioaddr, 0x0e, 0x0000); + } +@@ -850,7 +874,7 @@ static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, + + #endif + +-static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) ++static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct rtl8169_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->mmio_addr; +@@ -867,65 +891,29 @@ static void rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) + + cmd->speed = SPEED_1000; + cmd->duplex = DUPLEX_FULL; /* Always set */ ++ ++ return 0; + } + +-static void rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) ++static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct rtl8169_private *tp = netdev_priv(dev); +- void __iomem *ioaddr = tp->mmio_addr; +- u8 status; +- +- cmd->supported = SUPPORTED_10baseT_Half | +- SUPPORTED_10baseT_Full | +- SUPPORTED_100baseT_Half | +- SUPPORTED_100baseT_Full | +- SUPPORTED_1000baseT_Full | +- SUPPORTED_Autoneg | +- SUPPORTED_TP; +- +- cmd->autoneg = 1; +- cmd->advertising = ADVERTISED_TP | ADVERTISED_Autoneg; +- +- if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) +- cmd->advertising |= ADVERTISED_10baseT_Half; +- if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) +- cmd->advertising |= ADVERTISED_10baseT_Full; +- if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) +- cmd->advertising |= ADVERTISED_100baseT_Half; +- if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) +- cmd->advertising |= ADVERTISED_100baseT_Full; +- if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) +- cmd->advertising |= ADVERTISED_1000baseT_Full; +- +- status = RTL_R8(PHYstatus); +- +- if (status & _1000bpsF) +- cmd->speed = SPEED_1000; +- else if (status & _100bps) +- cmd->speed = SPEED_100; +- else if (status & _10bps) +- cmd->speed = SPEED_10; +- +- if (status & TxFlowCtrl) +- cmd->advertising |= ADVERTISED_Asym_Pause; +- if (status & RxFlowCtrl) +- cmd->advertising |= ADVERTISED_Pause; +- +- cmd->duplex = ((status & _1000bpsF) || (status & FullDup)) ? +- DUPLEX_FULL : DUPLEX_HALF; ++ ++ return mii_ethtool_gset(&tp->mii, cmd); + } + + static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) + { + struct rtl8169_private *tp = netdev_priv(dev); + unsigned long flags; ++ int rc; + + spin_lock_irqsave(&tp->lock, flags); + +- tp->get_settings(dev, cmd); ++ rc = tp->get_settings(dev, cmd); + + spin_unlock_irqrestore(&tp->lock, flags); +- return 0; ++ return rc; + } + + static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, +@@ -1513,7 +1501,7 @@ static const struct rtl_cfg_info { + unsigned int align; + u16 intr_event; + u16 napi_event; +- unsigned msi; ++ unsigned features; + } rtl_cfg_infos [] = { + [RTL_CFG_0] = { + .hw_start = rtl_hw_start_8169, +@@ -1522,7 +1510,7 @@ static const struct rtl_cfg_info { + .intr_event = SYSErr | LinkChg | RxOverflow | + RxFIFOOver | TxErr | TxOK | RxOK | RxErr, + .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, +- .msi = 0 ++ .features = RTL_FEATURE_GMII + }, + [RTL_CFG_1] = { + .hw_start = rtl_hw_start_8168, +@@ -1531,7 +1519,7 @@ static const struct rtl_cfg_info { + .intr_event = SYSErr | LinkChg | RxOverflow | + TxErr | TxOK | RxOK | RxErr, + .napi_event = TxErr | TxOK | RxOK | RxOverflow, +- .msi = RTL_FEATURE_MSI ++ .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI + }, + [RTL_CFG_2] = { + .hw_start = rtl_hw_start_8101, +@@ -1540,7 +1528,7 @@ static const struct rtl_cfg_info { + .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout | + RxFIFOOver | TxErr | TxOK | RxOK | RxErr, + .napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow, +- .msi = RTL_FEATURE_MSI ++ .features = RTL_FEATURE_MSI + } + }; + +@@ -1552,7 +1540,7 @@ static unsigned rtl_try_msi(struct pci_dev *pdev, void __iomem *ioaddr, + u8 cfg2; + + cfg2 = RTL_R8(Config2) & ~MSIEnable; +- if (cfg->msi) { ++ if (cfg->features & RTL_FEATURE_MSI) { + if (pci_enable_msi(pdev)) { + dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); + } else { +@@ -1578,6 +1566,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; + const unsigned int region = cfg->region; + struct rtl8169_private *tp; ++ struct mii_if_info *mii; + struct net_device *dev; + void __iomem *ioaddr; + unsigned int i; +@@ -1602,6 +1591,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + tp->pci_dev = pdev; + tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); + ++ mii = &tp->mii; ++ mii->dev = dev; ++ mii->mdio_read = rtl_mdio_read; ++ mii->mdio_write = rtl_mdio_write; ++ mii->phy_id_mask = 0x1f; ++ mii->reg_num_mask = 0x1f; ++ mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); ++ + /* enable device (incl. PCI PM wakeup and hotplug setup) */ + rc = pci_enable_device(pdev); + if (rc < 0) { +@@ -2099,8 +2096,6 @@ static void rtl_hw_start_8168(struct net_device *dev) + + RTL_R8(IntrMask); + +- RTL_W32(RxMissed, 0); +- + rtl_set_rx_mode(dev); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); +@@ -2143,8 +2138,6 @@ static void rtl_hw_start_8101(struct net_device *dev) + + RTL_R8(IntrMask); + +- RTL_W32(RxMissed, 0); +- + rtl_set_rx_mode(dev); + + RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); +@@ -2922,6 +2915,17 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) + return work_done; + } + ++static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) ++{ ++ struct rtl8169_private *tp = netdev_priv(dev); ++ ++ if (tp->mac_version > RTL_GIGA_MAC_VER_06) ++ return; ++ ++ dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); ++ RTL_W32(RxMissed, 0); ++} ++ + static void rtl8169_down(struct net_device *dev) + { + struct rtl8169_private *tp = netdev_priv(dev); +@@ -2939,9 +2943,7 @@ core_down: + + rtl8169_asic_down(ioaddr); + +- /* Update the error counts. */ +- dev->stats.rx_missed_errors += RTL_R32(RxMissed); +- RTL_W32(RxMissed, 0); ++ rtl8169_rx_missed(dev, ioaddr); + + spin_unlock_irq(&tp->lock); + +@@ -3063,8 +3065,7 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev) + + if (netif_running(dev)) { + spin_lock_irqsave(&tp->lock, flags); +- dev->stats.rx_missed_errors += RTL_R32(RxMissed); +- RTL_W32(RxMissed, 0); ++ rtl8169_rx_missed(dev, ioaddr); + spin_unlock_irqrestore(&tp->lock, flags); + } + +@@ -3089,8 +3090,7 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state) + + rtl8169_asic_down(ioaddr); + +- dev->stats.rx_missed_errors += RTL_R32(RxMissed); +- RTL_W32(RxMissed, 0); ++ rtl8169_rx_missed(dev, ioaddr); + + spin_unlock_irq(&tp->lock); + +diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +index 17d4f31..c479ee2 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h ++++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +@@ -129,6 +129,13 @@ struct iwl5000_shared { + __le32 padding2; + } __attribute__ ((packed)); + ++/* calibrations defined for 5000 */ ++/* defines the order in which results should be sent to the runtime uCode */ ++enum iwl5000_calib { ++ IWL5000_CALIB_LO, ++ IWL5000_CALIB_TX_IQ, ++ IWL5000_CALIB_TX_IQ_PERD, ++}; + + #endif /* __iwl_5000_hw_h__ */ + +diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c +index b08036a..79ff288 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-5000.c ++++ b/drivers/net/wireless/iwlwifi/iwl-5000.c +@@ -445,48 +445,6 @@ static int iwl5000_send_Xtal_calib(struct iwl_priv *priv) + sizeof(cal_cmd), &cal_cmd); + } + +-static int iwl5000_send_calib_results(struct iwl_priv *priv) +-{ +- int ret = 0; +- +- struct iwl_host_cmd hcmd = { +- .id = REPLY_PHY_CALIBRATION_CMD, +- .meta.flags = CMD_SIZE_HUGE, +- }; +- +- if (priv->calib_results.lo_res) { +- hcmd.len = priv->calib_results.lo_res_len; +- hcmd.data = priv->calib_results.lo_res; +- ret = iwl_send_cmd_sync(priv, &hcmd); +- +- if (ret) +- goto err; +- } +- +- if (priv->calib_results.tx_iq_res) { +- hcmd.len = priv->calib_results.tx_iq_res_len; +- hcmd.data = priv->calib_results.tx_iq_res; +- ret = iwl_send_cmd_sync(priv, &hcmd); +- +- if (ret) +- goto err; +- } +- +- if (priv->calib_results.tx_iq_perd_res) { +- hcmd.len = priv->calib_results.tx_iq_perd_res_len; +- hcmd.data = priv->calib_results.tx_iq_perd_res; +- ret = iwl_send_cmd_sync(priv, &hcmd); +- +- if (ret) +- goto err; +- } +- +- return 0; +-err: +- IWL_ERROR("Error %d\n", ret); +- return ret; +-} +- + static int iwl5000_send_calib_cfg(struct iwl_priv *priv) + { + struct iwl5000_calib_cfg_cmd calib_cfg_cmd; +@@ -511,33 +469,30 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, + struct iwl_rx_packet *pkt = (void *)rxb->skb->data; + struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw; + int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK; +- +- iwl_free_calib_results(priv); ++ int index; + + /* reduce the size of the length field itself */ + len -= 4; + ++ /* Define the order in which the results will be sent to the runtime ++ * uCode. iwl_send_calib_results sends them in a row according to their ++ * index. We sort them here */ + switch (hdr->op_code) { + case IWL5000_PHY_CALIBRATE_LO_CMD: +- priv->calib_results.lo_res = kzalloc(len, GFP_ATOMIC); +- priv->calib_results.lo_res_len = len; +- memcpy(priv->calib_results.lo_res, pkt->u.raw, len); ++ index = IWL5000_CALIB_LO; + break; + case IWL5000_PHY_CALIBRATE_TX_IQ_CMD: +- priv->calib_results.tx_iq_res = kzalloc(len, GFP_ATOMIC); +- priv->calib_results.tx_iq_res_len = len; +- memcpy(priv->calib_results.tx_iq_res, pkt->u.raw, len); ++ index = IWL5000_CALIB_TX_IQ; + break; + case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD: +- priv->calib_results.tx_iq_perd_res = kzalloc(len, GFP_ATOMIC); +- priv->calib_results.tx_iq_perd_res_len = len; +- memcpy(priv->calib_results.tx_iq_perd_res, pkt->u.raw, len); ++ index = IWL5000_CALIB_TX_IQ_PERD; + break; + default: + IWL_ERROR("Unknown calibration notification %d\n", + hdr->op_code); + return; + } ++ iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); + } + + static void iwl5000_rx_calib_complete(struct iwl_priv *priv, +@@ -832,7 +787,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv) + iwl5000_send_Xtal_calib(priv); + + if (priv->ucode_type == UCODE_RT) +- iwl5000_send_calib_results(priv); ++ iwl_send_calib_results(priv); + + return 0; + } +diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c +index e01f048..72a6743 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-agn.c ++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c +@@ -2090,7 +2090,6 @@ static void iwl_alive_start(struct iwl_priv *priv) + iwl4965_error_recovery(priv); + + iwl_power_update_mode(priv, 1); +- ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); + + if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) + iwl4965_set_mode(priv, priv->iw_mode); +@@ -2342,6 +2341,7 @@ static void iwl_bg_alive_start(struct work_struct *data) + mutex_lock(&priv->mutex); + iwl_alive_start(priv); + mutex_unlock(&priv->mutex); ++ ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); + } + + static void iwl4965_bg_rf_kill(struct work_struct *work) +@@ -2486,6 +2486,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) + if (!priv->vif || !priv->is_open) + return; + ++ iwl_power_cancel_timeout(priv); + iwl_scan_cancel_timeout(priv, 200); + + conf = ieee80211_get_hw_conf(priv->hw); +@@ -2503,8 +2504,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) + + priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; + +- if (priv->current_ht_config.is_ht) +- iwl_set_rxon_ht(priv, &priv->current_ht_config); ++ iwl_set_rxon_ht(priv, &priv->current_ht_config); + + iwl_set_rxon_chain(priv); + priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); +@@ -2550,10 +2550,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) + break; + } + +- /* Enable Rx differential gain and sensitivity calibrations */ +- iwl_chain_noise_reset(priv); +- priv->start_calib = 1; +- + if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) + priv->assoc_station_added = 1; + +@@ -2561,7 +2557,12 @@ static void iwl4965_post_associate(struct iwl_priv *priv) + iwl_activate_qos(priv, 0); + spin_unlock_irqrestore(&priv->lock, flags); + +- iwl_power_update_mode(priv, 0); ++ iwl_power_enable_management(priv); ++ ++ /* Enable Rx differential gain and sensitivity calibrations */ ++ iwl_chain_noise_reset(priv); ++ priv->start_calib = 1; ++ + /* we have just associated, don't start scan too early */ + priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; + } +@@ -3212,18 +3213,26 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) + goto out_unlock; + } + +- /* we don't schedule scan within next_scan_jiffies period */ ++ /* We don't schedule scan within next_scan_jiffies period. ++ * Avoid scanning during possible EAPOL exchange, return ++ * success immediately. ++ */ + if (priv->next_scan_jiffies && +- time_after(priv->next_scan_jiffies, jiffies)) { +- rc = -EAGAIN; ++ time_after(priv->next_scan_jiffies, jiffies)) { ++ IWL_DEBUG_SCAN("scan rejected: within next scan period\n"); ++ queue_work(priv->workqueue, &priv->scan_completed); ++ rc = 0; + goto out_unlock; + } + /* if we just finished scan ask for delay */ +- if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies + +- IWL_DELAY_NEXT_SCAN, jiffies)) { +- rc = -EAGAIN; ++ if (iwl_is_associated(priv) && priv->last_scan_jiffies && ++ time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { ++ IWL_DEBUG_SCAN("scan rejected: within previous scan period\n"); ++ queue_work(priv->workqueue, &priv->scan_completed); ++ rc = 0; + goto out_unlock; + } ++ + if (len) { + IWL_DEBUG_SCAN("direct scan for %s [%d]\n ", + iwl_escape_essid(ssid, len), (int)len); +@@ -3546,6 +3555,16 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) + /* Per mac80211.h: This is only used in IBSS mode... */ + if (priv->iw_mode != IEEE80211_IF_TYPE_IBSS) { + ++ /* switch to CAM during association period. ++ * the ucode will block any association/authentication ++ * frome during assiciation period if it can not hear ++ * the AP because of PM. the timer enable PM back is ++ * association do not complete ++ */ ++ if (priv->hw->conf.channel->flags & (IEEE80211_CHAN_PASSIVE_SCAN | ++ IEEE80211_CHAN_RADAR)) ++ iwl_power_disable_management(priv, 3000); ++ + IWL_DEBUG_MAC80211("leave - not in IBSS\n"); + mutex_unlock(&priv->mutex); + return; +@@ -4083,6 +4102,7 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) + /* FIXME : remove when resolved PENDING */ + INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); + iwl_setup_scan_deferred_work(priv); ++ iwl_setup_power_deferred_work(priv); + + if (priv->cfg->ops->lib->setup_deferred_work) + priv->cfg->ops->lib->setup_deferred_work(priv); +@@ -4102,6 +4122,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) + + cancel_delayed_work_sync(&priv->init_alive_start); + cancel_delayed_work(&priv->scan_check); ++ cancel_delayed_work_sync(&priv->set_power_save); + cancel_delayed_work(&priv->alive_start); + cancel_work_sync(&priv->beacon_update); + del_timer_sync(&priv->statistics_periodic); +@@ -4204,13 +4225,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e + + pci_set_master(pdev); + +- err = pci_set_dma_mask(pdev, DMA_64BIT_MASK); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); + if (!err) +- err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); + if (err) { +- err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (!err) +- err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); + /* both attempts failed: */ + if (err) { + printk(KERN_WARNING "%s: No suitable DMA available.\n", +diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c +index ef49440..35fb4a4 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-calib.c ++++ b/drivers/net/wireless/iwlwifi/iwl-calib.c +@@ -66,6 +66,66 @@ + #include "iwl-core.h" + #include "iwl-calib.h" + ++/***************************************************************************** ++ * INIT calibrations framework ++ *****************************************************************************/ ++ ++ int iwl_send_calib_results(struct iwl_priv *priv) ++{ ++ int ret = 0; ++ int i = 0; ++ ++ struct iwl_host_cmd hcmd = { ++ .id = REPLY_PHY_CALIBRATION_CMD, ++ .meta.flags = CMD_SIZE_HUGE, ++ }; ++ ++ for (i = 0; i < IWL_CALIB_MAX; i++) ++ if (priv->calib_results[i].buf) { ++ hcmd.len = priv->calib_results[i].buf_len; ++ hcmd.data = priv->calib_results[i].buf; ++ ret = iwl_send_cmd_sync(priv, &hcmd); ++ if (ret) ++ goto err; ++ } ++ ++ return 0; ++err: ++ IWL_ERROR("Error %d iteration %d\n", ret, i); ++ return ret; ++} ++EXPORT_SYMBOL(iwl_send_calib_results); ++ ++int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) ++{ ++ if (res->buf_len != len) { ++ kfree(res->buf); ++ res->buf = kzalloc(len, GFP_ATOMIC); ++ } ++ if (unlikely(res->buf == NULL)) ++ return -ENOMEM; ++ ++ res->buf_len = len; ++ memcpy(res->buf, buf, len); ++ return 0; ++} ++EXPORT_SYMBOL(iwl_calib_set); ++ ++void iwl_calib_free_results(struct iwl_priv *priv) ++{ ++ int i; ++ ++ for (i = 0; i < IWL_CALIB_MAX; i++) { ++ kfree(priv->calib_results[i].buf); ++ priv->calib_results[i].buf = NULL; ++ priv->calib_results[i].buf_len = 0; ++ } ++} ++ ++/***************************************************************************** ++ * RUNTIME calibrations framework ++ *****************************************************************************/ ++ + /* "false alarms" are signals that our DSP tries to lock onto, + * but then determines that they are either noise, or transmissions + * from a distant wireless network (also "noise", really) that get +diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c +index 80f2f84..1383fd1 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-core.c ++++ b/drivers/net/wireless/iwlwifi/iwl-core.c +@@ -646,8 +646,14 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) + struct iwl_rxon_cmd *rxon = &priv->staging_rxon; + u32 val; + +- if (!ht_info->is_ht) ++ if (!ht_info->is_ht) { ++ rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | ++ RXON_FLG_CHANNEL_MODE_PURE_40_MSK | ++ RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | ++ RXON_FLG_FAT_PROT_MSK | ++ RXON_FLG_HT_PROT_MSK); + return; ++ } + + /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ + if (iwl_is_fat_tx_allowed(priv, NULL)) +@@ -950,22 +956,6 @@ err: + } + EXPORT_SYMBOL(iwl_init_drv); + +-void iwl_free_calib_results(struct iwl_priv *priv) +-{ +- kfree(priv->calib_results.lo_res); +- priv->calib_results.lo_res = NULL; +- priv->calib_results.lo_res_len = 0; +- +- kfree(priv->calib_results.tx_iq_res); +- priv->calib_results.tx_iq_res = NULL; +- priv->calib_results.tx_iq_res_len = 0; +- +- kfree(priv->calib_results.tx_iq_perd_res); +- priv->calib_results.tx_iq_perd_res = NULL; +- priv->calib_results.tx_iq_perd_res_len = 0; +-} +-EXPORT_SYMBOL(iwl_free_calib_results); +- + int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) + { + int ret = 0; +@@ -993,10 +983,9 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) + } + EXPORT_SYMBOL(iwl_set_tx_power); + +- + void iwl_uninit_drv(struct iwl_priv *priv) + { +- iwl_free_calib_results(priv); ++ iwl_calib_free_results(priv); + iwlcore_free_geos(priv); + iwl_free_channel_map(priv); + kfree(priv->scan); +diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h +index 64f139e..51b36b1 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-core.h ++++ b/drivers/net/wireless/iwlwifi/iwl-core.h +@@ -186,7 +186,6 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, + void iwl_hw_detect(struct iwl_priv *priv); + + void iwl_clear_stations_table(struct iwl_priv *priv); +-void iwl_free_calib_results(struct iwl_priv *priv); + void iwl_reset_qos(struct iwl_priv *priv); + void iwl_set_rxon_chain(struct iwl_priv *priv); + int iwl_set_rxon_channel(struct iwl_priv *priv, +@@ -291,6 +290,13 @@ int iwl_scan_initiate(struct iwl_priv *priv); + void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); + void iwl_setup_scan_deferred_work(struct iwl_priv *priv); + ++/******************************************************************************* ++ * Calibrations - implemented in iwl-calib.c ++ ******************************************************************************/ ++int iwl_send_calib_results(struct iwl_priv *priv); ++int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); ++void iwl_calib_free_results(struct iwl_priv *priv); ++ + /***************************************************** + * S e n d i n g H o s t C o m m a n d s * + *****************************************************/ +diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h +index cdfb343..09bdf8e 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-dev.h ++++ b/drivers/net/wireless/iwlwifi/iwl-dev.h +@@ -745,13 +745,10 @@ struct statistics_general_data { + u32 beacon_energy_c; + }; + +-struct iwl_calib_results { +- void *tx_iq_res; +- void *tx_iq_perd_res; +- void *lo_res; +- u32 tx_iq_res_len; +- u32 tx_iq_perd_res_len; +- u32 lo_res_len; ++/* Opaque calibration results */ ++struct iwl_calib_result { ++ void *buf; ++ size_t buf_len; + }; + + enum ucode_type { +@@ -813,6 +810,7 @@ enum { + + + #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ ++#define IWL_CALIB_MAX 3 + + struct iwl_priv { + +@@ -857,7 +855,7 @@ struct iwl_priv { + s32 last_temperature; + + /* init calibration results */ +- struct iwl_calib_results calib_results; ++ struct iwl_calib_result calib_results[IWL_CALIB_MAX]; + + /* Scan related variables */ + unsigned long last_scan_jiffies; +@@ -1047,6 +1045,7 @@ struct iwl_priv { + + struct tasklet_struct irq_tasklet; + ++ struct delayed_work set_power_save; + struct delayed_work init_alive_start; + struct delayed_work alive_start; + struct delayed_work scan_check; +diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c +index a099c9e..ae60bfd 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-power.c ++++ b/drivers/net/wireless/iwlwifi/iwl-power.c +@@ -324,7 +324,7 @@ EXPORT_SYMBOL(iwl_power_update_mode); + * this will be usefull for rate scale to disable PM during heavy + * Tx/Rx activities + */ +-int iwl_power_disable_management(struct iwl_priv *priv) ++int iwl_power_disable_management(struct iwl_priv *priv, u32 ms) + { + u16 prev_mode; + int ret = 0; +@@ -337,6 +337,11 @@ int iwl_power_disable_management(struct iwl_priv *priv) + ret = iwl_power_update_mode(priv, 0); + priv->power_data.power_disabled = 1; + priv->power_data.user_power_setting = prev_mode; ++ cancel_delayed_work(&priv->set_power_save); ++ if (ms) ++ queue_delayed_work(priv->workqueue, &priv->set_power_save, ++ msecs_to_jiffies(ms)); ++ + + return ret; + } +@@ -431,3 +436,35 @@ int iwl_power_temperature_change(struct iwl_priv *priv) + return ret; + } + EXPORT_SYMBOL(iwl_power_temperature_change); ++ ++static void iwl_bg_set_power_save(struct work_struct *work) ++{ ++ struct iwl_priv *priv = container_of(work, ++ struct iwl_priv, set_power_save.work); ++ IWL_DEBUG(IWL_DL_STATE, "update power\n"); ++ ++ if (test_bit(STATUS_EXIT_PENDING, &priv->status)) ++ return; ++ ++ mutex_lock(&priv->mutex); ++ ++ /* on starting association we disable power managment ++ * until association, if association failed then this ++ * timer will expire and enable PM again. ++ */ ++ if (!iwl_is_associated(priv)) ++ iwl_power_enable_management(priv); ++ ++ mutex_unlock(&priv->mutex); ++} ++void iwl_setup_power_deferred_work(struct iwl_priv *priv) ++{ ++ INIT_DELAYED_WORK(&priv->set_power_save, iwl_bg_set_power_save); ++} ++EXPORT_SYMBOL(iwl_setup_power_deferred_work); ++ ++void iwl_power_cancel_timeout(struct iwl_priv *priv) ++{ ++ cancel_delayed_work(&priv->set_power_save); ++} ++EXPORT_SYMBOL(iwl_power_cancel_timeout); +diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h +index abcbbf9..aa99f36 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-power.h ++++ b/drivers/net/wireless/iwlwifi/iwl-power.h +@@ -78,8 +78,10 @@ struct iwl_power_mgr { + u8 power_disabled; /* flag to disable using power saving level */ + }; + ++void iwl_setup_power_deferred_work(struct iwl_priv *priv); ++void iwl_power_cancel_timeout(struct iwl_priv *priv); + int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh); +-int iwl_power_disable_management(struct iwl_priv *priv); ++int iwl_power_disable_management(struct iwl_priv *priv, u32 ms); + int iwl_power_enable_management(struct iwl_priv *priv); + int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode); + int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode); +diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c +index 6c8ac3a..3a90a67 100644 +--- a/drivers/net/wireless/iwlwifi/iwl-scan.c ++++ b/drivers/net/wireless/iwlwifi/iwl-scan.c +@@ -464,11 +464,6 @@ void iwl_init_scan_params(struct iwl_priv *priv) + + int iwl_scan_initiate(struct iwl_priv *priv) + { +- if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { +- IWL_ERROR("APs don't scan.\n"); +- return 0; +- } +- + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); + return -EIO; +@@ -480,8 +475,7 @@ int iwl_scan_initiate(struct iwl_priv *priv) + } + + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { +- IWL_DEBUG_SCAN("Scan request while abort pending. " +- "Queuing.\n"); ++ IWL_DEBUG_SCAN("Scan request while abort pending\n"); + return -EAGAIN; + } + +diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c +index b775d5b..752e7f8 100644 +--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c ++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c +@@ -5761,7 +5761,6 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) + if (priv->error_recovering) + iwl3945_error_recovery(priv); + +- ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); + return; + + restart: +@@ -6006,6 +6005,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data) + mutex_lock(&priv->mutex); + iwl3945_alive_start(priv); + mutex_unlock(&priv->mutex); ++ ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); + } + + static void iwl3945_bg_rf_kill(struct work_struct *work) +@@ -6259,6 +6259,11 @@ static void iwl3945_bg_request_scan(struct work_struct *data) + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + ++ if (scan->channel_count == 0) { ++ IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count); ++ goto done; ++ } ++ + cmd.len += le16_to_cpu(scan->tx_cmd.len) + + scan->channel_count * sizeof(struct iwl3945_scan_channel); + cmd.data = scan; +diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c +index a60ae86..a3ccd8c 100644 +--- a/drivers/net/wireless/zd1211rw/zd_usb.c ++++ b/drivers/net/wireless/zd1211rw/zd_usb.c +@@ -61,6 +61,7 @@ static struct usb_device_id usb_ids[] = { + { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, + /* ZD1211B */ + { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, ++ { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, +@@ -82,6 +83,7 @@ static struct usb_device_id usb_ids[] = { + { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, ++ { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, + /* "Driverless" devices that need ejecting */ + { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, + { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, +diff --git a/fs/ext3/super.c b/fs/ext3/super.c +index f38a5af..810bf7c 100644 +--- a/fs/ext3/super.c ++++ b/fs/ext3/super.c +@@ -2365,13 +2365,12 @@ static void ext3_write_super (struct super_block * sb) + + static int ext3_sync_fs(struct super_block *sb, int wait) + { +- tid_t target; +- + sb->s_dirt = 0; +- if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) { +- if (wait) +- log_wait_commit(EXT3_SB(sb)->s_journal, target); +- } ++ if (wait) ++ ext3_force_commit(sb); ++ else ++ journal_start_commit(EXT3_SB(sb)->s_journal, NULL); ++ + return 0; + } + +diff --git a/fs/hfs/catalog.c b/fs/hfs/catalog.c +index ba85157..6d98f11 100644 +--- a/fs/hfs/catalog.c ++++ b/fs/hfs/catalog.c +@@ -190,6 +190,10 @@ int hfs_cat_find_brec(struct super_block *sb, u32 cnid, + + fd->search_key->cat.ParID = rec.thread.ParID; + len = fd->search_key->cat.CName.len = rec.thread.CName.len; ++ if (len > HFS_NAMELEN) { ++ printk(KERN_ERR "hfs: bad catalog namelength\n"); ++ return -EIO; ++ } + memcpy(fd->search_key->cat.CName.name, rec.thread.CName.name, len); + return hfs_brec_find(fd); + } +diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c +index 8adebd3..0fd792b 100644 +--- a/fs/jffs2/background.c ++++ b/fs/jffs2/background.c +@@ -85,15 +85,15 @@ static int jffs2_garbage_collect_thread(void *_c) + for (;;) { + allow_signal(SIGHUP); + again: ++ spin_lock(&c->erase_completion_lock); + if (!jffs2_thread_should_wake(c)) { + set_current_state (TASK_INTERRUPTIBLE); ++ spin_unlock(&c->erase_completion_lock); + D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); +- /* Yes, there's a race here; we checked jffs2_thread_should_wake() +- before setting current->state to TASK_INTERRUPTIBLE. But it doesn't +- matter - We don't care if we miss a wakeup, because the GC thread +- is only an optimisation anyway. */ + schedule(); +- } ++ } else ++ spin_unlock(&c->erase_completion_lock); ++ + + /* This thread is purely an optimisation. But if it runs when + other things could be running, it actually makes things a +diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c +index 47b0457..90cb60d 100644 +--- a/fs/jffs2/compr_lzo.c ++++ b/fs/jffs2/compr_lzo.c +@@ -19,7 +19,7 @@ + + static void *lzo_mem; + static void *lzo_compress_buf; +-static DEFINE_MUTEX(deflate_mutex); ++static DEFINE_MUTEX(deflate_mutex); /* for lzo_mem and lzo_compress_buf */ + + static void free_workspace(void) + { +@@ -49,18 +49,21 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, + + mutex_lock(&deflate_mutex); + ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); +- mutex_unlock(&deflate_mutex); +- + if (ret != LZO_E_OK) +- return -1; ++ goto fail; + + if (compress_size > *dstlen) +- return -1; ++ goto fail; + + memcpy(cpage_out, lzo_compress_buf, compress_size); +- *dstlen = compress_size; ++ mutex_unlock(&deflate_mutex); + ++ *dstlen = compress_size; + return 0; ++ ++ fail: ++ mutex_unlock(&deflate_mutex); ++ return -1; + } + + static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, +diff --git a/include/asm-generic/memory_model.h b/include/asm-generic/memory_model.h +index ae060c6..18546d8 100644 +--- a/include/asm-generic/memory_model.h ++++ b/include/asm-generic/memory_model.h +@@ -34,7 +34,7 @@ + + #define __pfn_to_page(pfn) \ + ({ unsigned long __pfn = (pfn); \ +- unsigned long __nid = arch_pfn_to_nid(pfn); \ ++ unsigned long __nid = arch_pfn_to_nid(__pfn); \ + NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\ + }) + +diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h +index d6fb115..3a16bea 100644 +--- a/include/linux/mtd/cfi.h ++++ b/include/linux/mtd/cfi.h +@@ -281,9 +281,25 @@ struct cfi_private { + /* + * Returns the command address according to the given geometry. + */ +-static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type) ++static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, ++ struct map_info *map, struct cfi_private *cfi) + { +- return (cmd_ofs * type) * interleave; ++ unsigned bankwidth = map_bankwidth(map); ++ unsigned interleave = cfi_interleave(cfi); ++ unsigned type = cfi->device_type; ++ uint32_t addr; ++ ++ addr = (cmd_ofs * type) * interleave; ++ ++ /* Modify the unlock address if we are in compatiblity mode. ++ * For 16bit devices on 8 bit busses ++ * and 32bit devices on 16 bit busses ++ * set the low bit of the alternating bit sequence of the address. ++ */ ++ if (((type * interleave) > bankwidth) && ((uint8_t)cmd_ofs == 0xaa)) ++ addr |= (type >> 1)*interleave; ++ ++ return addr; + } + + /* +@@ -429,7 +445,7 @@ static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t + int type, map_word *prev_val) + { + map_word val; +- uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type); ++ uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi); + + val = cfi_build_cmd(cmd, map, cfi); + +diff --git a/include/net/af_unix.h b/include/net/af_unix.h +index 7dd29b7..c29ff1d 100644 +--- a/include/net/af_unix.h ++++ b/include/net/af_unix.h +@@ -54,6 +54,7 @@ struct unix_sock { + atomic_long_t inflight; + spinlock_t lock; + unsigned int gc_candidate : 1; ++ unsigned int gc_maybe_cycle : 1; + wait_queue_head_t peer_wait; + }; + #define unix_sk(__sk) ((struct unix_sock *)__sk) +diff --git a/kernel/cgroup.c b/kernel/cgroup.c +index a0123d7..d68bf2b 100644 +--- a/kernel/cgroup.c ++++ b/kernel/cgroup.c +@@ -2443,7 +2443,6 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) + list_del(&cgrp->sibling); + spin_lock(&cgrp->dentry->d_lock); + d = dget(cgrp->dentry); +- cgrp->dentry = NULL; + spin_unlock(&d->d_lock); + + cgroup_d_remove_dir(d); +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 67a7119..77427c8 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -353,11 +353,26 @@ static int vma_has_reserves(struct vm_area_struct *vma) + return 0; + } + ++static void clear_gigantic_page(struct page *page, ++ unsigned long addr, unsigned long sz) ++{ ++ int i; ++ struct page *p = page; ++ ++ might_sleep(); ++ for (i = 0; i < sz/PAGE_SIZE; i++, p = mem_map_next(p, page, i)) { ++ cond_resched(); ++ clear_user_highpage(p, addr + i * PAGE_SIZE); ++ } ++} + static void clear_huge_page(struct page *page, + unsigned long addr, unsigned long sz) + { + int i; + ++ if (unlikely(sz > MAX_ORDER_NR_PAGES)) ++ return clear_gigantic_page(page, addr, sz); ++ + might_sleep(); + for (i = 0; i < sz/PAGE_SIZE; i++) { + cond_resched(); +@@ -365,12 +380,32 @@ static void clear_huge_page(struct page *page, + } + } + ++static void copy_gigantic_page(struct page *dst, struct page *src, ++ unsigned long addr, struct vm_area_struct *vma) ++{ ++ int i; ++ struct hstate *h = hstate_vma(vma); ++ struct page *dst_base = dst; ++ struct page *src_base = src; ++ might_sleep(); ++ for (i = 0; i < pages_per_huge_page(h); ) { ++ cond_resched(); ++ copy_user_highpage(dst, src, addr + i*PAGE_SIZE, vma); ++ ++ i++; ++ dst = mem_map_next(dst, dst_base, i); ++ src = mem_map_next(src, src_base, i); ++ } ++} + static void copy_huge_page(struct page *dst, struct page *src, + unsigned long addr, struct vm_area_struct *vma) + { + int i; + struct hstate *h = hstate_vma(vma); + ++ if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) ++ return copy_gigantic_page(dst, src, addr, vma); ++ + might_sleep(); + for (i = 0; i < pages_per_huge_page(h); i++) { + cond_resched(); +@@ -455,6 +490,8 @@ static void update_and_free_page(struct hstate *h, struct page *page) + { + int i; + ++ VM_BUG_ON(h->order >= MAX_ORDER); ++ + h->nr_huge_pages--; + h->nr_huge_pages_node[page_to_nid(page)]--; + for (i = 0; i < pages_per_huge_page(h); i++) { +@@ -969,6 +1006,14 @@ found: + return 1; + } + ++static void prep_compound_huge_page(struct page *page, int order) ++{ ++ if (unlikely(order > (MAX_ORDER - 1))) ++ prep_compound_gigantic_page(page, order); ++ else ++ prep_compound_page(page, order); ++} ++ + /* Put bootmem huge pages into the standard lists after mem_map is up */ + static void __init gather_bootmem_prealloc(void) + { +@@ -979,7 +1024,7 @@ static void __init gather_bootmem_prealloc(void) + struct hstate *h = m->hstate; + __ClearPageReserved(page); + WARN_ON(page_count(page) != 1); +- prep_compound_page(page, h->order); ++ prep_compound_huge_page(page, h->order); + prep_new_huge_page(h, page, page_to_nid(page)); + } + } +@@ -2103,7 +2148,7 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, + same_page: + if (pages) { + get_page(page); +- pages[i] = page + pfn_offset; ++ pages[i] = mem_map_offset(page, pfn_offset); + } + + if (vmas) +diff --git a/mm/internal.h b/mm/internal.h +index 1f43f74..92729ea 100644 +--- a/mm/internal.h ++++ b/mm/internal.h +@@ -17,6 +17,7 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, + unsigned long floor, unsigned long ceiling); + + extern void prep_compound_page(struct page *page, unsigned long order); ++extern void prep_compound_gigantic_page(struct page *page, unsigned long order); + + static inline void set_page_count(struct page *page, int v) + { +@@ -53,6 +54,34 @@ static inline unsigned long page_order(struct page *page) + } + + /* ++ * Return the mem_map entry representing the 'offset' subpage within ++ * the maximally aligned gigantic page 'base'. Handle any discontiguity ++ * in the mem_map at MAX_ORDER_NR_PAGES boundaries. ++ */ ++static inline struct page *mem_map_offset(struct page *base, int offset) ++{ ++ if (unlikely(offset >= MAX_ORDER_NR_PAGES)) ++ return pfn_to_page(page_to_pfn(base) + offset); ++ return base + offset; ++} ++ ++/* ++ * Iterator over all subpages withing the maximally aligned gigantic ++ * page 'base'. Handle any discontiguity in the mem_map. ++ */ ++static inline struct page *mem_map_next(struct page *iter, ++ struct page *base, int offset) ++{ ++ if (unlikely((offset & (MAX_ORDER_NR_PAGES - 1)) == 0)) { ++ unsigned long pfn = page_to_pfn(base) + offset; ++ if (!pfn_valid(pfn)) ++ return NULL; ++ return pfn_to_page(pfn); ++ } ++ return iter + 1; ++} ++ ++/* + * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node, + * so all functions starting at paging_init should be marked __init + * in those cases. SPARSEMEM, however, allows for memory hotplug, +diff --git a/mm/page_alloc.c b/mm/page_alloc.c +index 27b8681..ed5cdae 100644 +--- a/mm/page_alloc.c ++++ b/mm/page_alloc.c +@@ -268,24 +268,39 @@ void prep_compound_page(struct page *page, unsigned long order) + { + int i; + int nr_pages = 1 << order; ++ ++ set_compound_page_dtor(page, free_compound_page); ++ set_compound_order(page, order); ++ __SetPageHead(page); ++ for (i = 1; i < nr_pages; i++) { ++ struct page *p = page + i; ++ ++ __SetPageTail(p); ++ p->first_page = page; ++ } ++} ++ ++#ifdef CONFIG_HUGETLBFS ++void prep_compound_gigantic_page(struct page *page, unsigned long order) ++{ ++ int i; ++ int nr_pages = 1 << order; + struct page *p = page + 1; + + set_compound_page_dtor(page, free_compound_page); + set_compound_order(page, order); + __SetPageHead(page); +- for (i = 1; i < nr_pages; i++, p++) { +- if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) +- p = pfn_to_page(page_to_pfn(page) + i); ++ for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) { + __SetPageTail(p); + p->first_page = page; + } + } ++#endif + + static void destroy_compound_page(struct page *page, unsigned long order) + { + int i; + int nr_pages = 1 << order; +- struct page *p = page + 1; + + if (unlikely(compound_order(page) != order)) + bad_page(page); +@@ -293,9 +308,8 @@ static void destroy_compound_page(struct page *page, unsigned long order) + if (unlikely(!PageHead(page))) + bad_page(page); + __ClearPageHead(page); +- for (i = 1; i < nr_pages; i++, p++) { +- if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) +- p = pfn_to_page(page_to_pfn(page) + i); ++ for (i = 1; i < nr_pages; i++) { ++ struct page *p = page + i; + + if (unlikely(!PageTail(p) | + (p->first_page != page))) +diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c +index 015606b..8bde9bf 100644 +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1300,14 +1300,23 @@ static void unix_destruct_fds(struct sk_buff *skb) + sock_wfree(skb); + } + +-static void unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) ++static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) + { + int i; ++ ++ /* ++ * Need to duplicate file references for the sake of garbage ++ * collection. Otherwise a socket in the fps might become a ++ * candidate for GC while the skb is not yet queued. ++ */ ++ UNIXCB(skb).fp = scm_fp_dup(scm->fp); ++ if (!UNIXCB(skb).fp) ++ return -ENOMEM; ++ + for (i=scm->fp->count-1; i>=0; i--) + unix_inflight(scm->fp->fp[i]); +- UNIXCB(skb).fp = scm->fp; + skb->destructor = unix_destruct_fds; +- scm->fp = NULL; ++ return 0; + } + + /* +@@ -1366,8 +1375,11 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, + goto out; + + memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); +- if (siocb->scm->fp) +- unix_attach_fds(siocb->scm, skb); ++ if (siocb->scm->fp) { ++ err = unix_attach_fds(siocb->scm, skb); ++ if (err) ++ goto out_free; ++ } + unix_get_secdata(siocb->scm, skb); + + skb_reset_transport_header(skb); +@@ -1536,8 +1548,13 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, + size = min_t(int, size, skb_tailroom(skb)); + + memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); +- if (siocb->scm->fp) +- unix_attach_fds(siocb->scm, skb); ++ if (siocb->scm->fp) { ++ err = unix_attach_fds(siocb->scm, skb); ++ if (err) { ++ kfree_skb(skb); ++ goto out_err; ++ } ++ } + + if ((err = memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size)) != 0) { + kfree_skb(skb); +diff --git a/net/unix/garbage.c b/net/unix/garbage.c +index 2a27b84..6d4a9a8 100644 +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -186,8 +186,17 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), + */ + struct sock *sk = unix_get_socket(*fp++); + if (sk) { +- hit = true; +- func(unix_sk(sk)); ++ struct unix_sock *u = unix_sk(sk); ++ ++ /* ++ * Ignore non-candidates, they could ++ * have been added to the queues after ++ * starting the garbage collection ++ */ ++ if (u->gc_candidate) { ++ hit = true; ++ func(u); ++ } + } + } + if (hit && hitlist != NULL) { +@@ -249,11 +258,11 @@ static void inc_inflight_move_tail(struct unix_sock *u) + { + atomic_long_inc(&u->inflight); + /* +- * If this is still a candidate, move it to the end of the +- * list, so that it's checked even if it was already passed +- * over ++ * If this still might be part of a cycle, move it to the end ++ * of the list, so that it's checked even if it was already ++ * passed over + */ +- if (u->gc_candidate) ++ if (u->gc_maybe_cycle) + list_move_tail(&u->link, &gc_candidates); + } + +@@ -267,6 +276,7 @@ void unix_gc(void) + struct unix_sock *next; + struct sk_buff_head hitlist; + struct list_head cursor; ++ LIST_HEAD(not_cycle_list); + + spin_lock(&unix_gc_lock); + +@@ -282,10 +292,14 @@ void unix_gc(void) + * + * Holding unix_gc_lock will protect these candidates from + * being detached, and hence from gaining an external +- * reference. This also means, that since there are no +- * possible receivers, the receive queues of these sockets are +- * static during the GC, even though the dequeue is done +- * before the detach without atomicity guarantees. ++ * reference. Since there are no possible receivers, all ++ * buffers currently on the candidates' queues stay there ++ * during the garbage collection. ++ * ++ * We also know that no new candidate can be added onto the ++ * receive queues. Other, non candidate sockets _can_ be ++ * added to queue, so we must make sure only to touch ++ * candidates. + */ + list_for_each_entry_safe(u, next, &gc_inflight_list, link) { + long total_refs; +@@ -299,6 +313,7 @@ void unix_gc(void) + if (total_refs == inflight_refs) { + list_move_tail(&u->link, &gc_candidates); + u->gc_candidate = 1; ++ u->gc_maybe_cycle = 1; + } + } + +@@ -325,14 +340,24 @@ void unix_gc(void) + list_move(&cursor, &u->link); + + if (atomic_long_read(&u->inflight) > 0) { +- list_move_tail(&u->link, &gc_inflight_list); +- u->gc_candidate = 0; ++ list_move_tail(&u->link, ¬_cycle_list); ++ u->gc_maybe_cycle = 0; + scan_children(&u->sk, inc_inflight_move_tail, NULL); + } + } + list_del(&cursor); + + /* ++ * not_cycle_list contains those sockets which do not make up a ++ * cycle. Restore these to the inflight list. ++ */ ++ while (!list_empty(¬_cycle_list)) { ++ u = list_entry(not_cycle_list.next, struct unix_sock, link); ++ u->gc_candidate = 0; ++ list_move_tail(&u->link, &gc_inflight_list); ++ } ++ ++ /* + * Now gc_candidates contains only garbage. Restore original + * inflight counters for these as well, and remove the skbuffs + * which are creating the cycle(s). +diff --git a/security/keys/internal.h b/security/keys/internal.h +index b39f5c2..239098f 100644 +--- a/security/keys/internal.h ++++ b/security/keys/internal.h +@@ -107,6 +107,7 @@ extern key_ref_t search_process_keyrings(struct key_type *type, + + extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); + ++extern int install_user_keyrings(struct task_struct *tsk); + extern int install_thread_keyring(struct task_struct *tsk); + extern int install_process_keyring(struct task_struct *tsk); + +diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c +index 5be6d01..45b240a 100644 +--- a/security/keys/process_keys.c ++++ b/security/keys/process_keys.c +@@ -40,7 +40,7 @@ struct key_user root_key_user = { + /* + * install user and user session keyrings for a particular UID + */ +-static int install_user_keyrings(struct task_struct *tsk) ++int install_user_keyrings(struct task_struct *tsk) + { + struct user_struct *user = tsk->user; + struct key *uid_keyring, *session_keyring; +diff --git a/security/keys/request_key.c b/security/keys/request_key.c +index ba32ca6..abea08f 100644 +--- a/security/keys/request_key.c ++++ b/security/keys/request_key.c +@@ -74,6 +74,10 @@ static int call_sbin_request_key(struct key_construction *cons, + + kenter("{%d},{%d},%s", key->serial, authkey->serial, op); + ++ ret = install_user_keyrings(tsk); ++ if (ret < 0) ++ goto error_alloc; ++ + /* allocate a new session keyring */ + sprintf(desc, "_req.%u", key->serial); + +diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c +index f3da621..732ce13 100644 +--- a/sound/pci/hda/patch_sigmatel.c ++++ b/sound/pci/hda/patch_sigmatel.c +@@ -67,6 +67,7 @@ enum { + enum { + STAC_92HD73XX_REF, + STAC_DELL_M6, ++ STAC_DELL_EQ, + STAC_92HD73XX_MODELS + }; + +@@ -560,9 +561,7 @@ static struct hda_verb dell_eq_core_init[] = { + }; + + static struct hda_verb dell_m6_core_init[] = { +- /* set master volume to max value without distortion +- * and direct control */ +- { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xec}, ++ { 0x1f, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, + /* setup audio connections */ + { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00}, + { 0x0a, AC_VERB_SET_CONNECT_SEL, 0x01}, +@@ -1297,11 +1296,13 @@ static unsigned int dell_m6_pin_configs[13] = { + static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { + [STAC_92HD73XX_REF] = ref92hd73xx_pin_configs, + [STAC_DELL_M6] = dell_m6_pin_configs, ++ [STAC_DELL_EQ] = dell_m6_pin_configs, + }; + + static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { + [STAC_92HD73XX_REF] = "ref", + [STAC_DELL_M6] = "dell-m6", ++ [STAC_DELL_EQ] = "dell-eq", + }; + + static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { +@@ -3560,8 +3561,12 @@ again: + spec->gpio_data = 0x01; + + switch (spec->board_config) { +- case STAC_DELL_M6: ++ case STAC_DELL_EQ: + spec->init = dell_eq_core_init; ++ /* fallthru */ ++ case STAC_DELL_M6: ++ if (!spec->init) ++ spec->init = dell_m6_core_init; + switch (codec->subsystem_id) { + case 0x1028025e: /* Analog Mics */ + case 0x1028025f: +@@ -3570,8 +3575,6 @@ again: + break; + case 0x10280271: /* Digital Mics */ + case 0x10280272: +- spec->init = dell_m6_core_init; +- /* fall-through */ + case 0x10280254: + case 0x10280255: + stac92xx_set_config_reg(codec, 0x13, 0x90A60160); diff --git a/debian/patches/series/1~experimental.1 b/debian/patches/series/1~experimental.1 index 6246a9022..3d4fa7345 100644 --- a/debian/patches/series/1~experimental.1 +++ b/debian/patches/series/1~experimental.1 @@ -25,3 +25,9 @@ + bugfix/fix-hifn_795X-divdi3.patch + bugfix/powerpc/mm-mol.patch #+ bugfix/powerpc/lpar-console.patch ++ bugfix/all/stable/patch-2.6.27.1 ++ bugfix/all/stable/patch-2.6.27.2 ++ bugfix/all/stable/patch-2.6.27.3 ++ bugfix/all/stable/patch-2.6.27.4 ++ bugfix/all/stable/patch-2.6.27.5 ++ bugfix/all/stable/patch-2.6.27.6