--- /dev/null
+From stable-bounces@linux.kernel.org Wed Dec 12 20:57:54 2007
+From: Pavel Emelyanov <xemul@openvz.org>
+Date: Thu, 13 Dec 2007 12:57:24 +0800
+Subject: BRIDGE: Properly dereference the br_should_route_hook
+To: Greg KH <greg@kroah.com>
+Cc: bunk@kernel.org, stable@kernel.org, <davem@davemloft.net>
+Message-ID: <20071213045723.GA1770@gondor.apana.org.au>
+Content-Disposition: inline
+
+
+From: Pavel Emelyanov <xemul@openvz.org>
+
+[BRIDGE]: Properly dereference the br_should_route_hook
+
+[ Upstream commit: 82de382ce8e1c7645984616728dc7aaa057821e4 ]
+
+This hook is protected with the RCU, so simple
+
+if (br_should_route_hook)
+ br_should_route_hook(...)
+
+is not enough on some architectures.
+
+Use the rcu_dereference/rcu_assign_pointer in this case.
+
+Fixed Stephen's comment concerning using the typeof().
+
+Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ net/bridge/br_input.c | 7 ++++---
+ net/bridge/netfilter/ebtable_broute.c | 4 ++--
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+--- a/net/bridge/br_input.c
++++ b/net/bridge/br_input.c
+@@ -127,6 +127,7 @@ static inline int is_link_local(const un
+ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
+ {
+ const unsigned char *dest = eth_hdr(skb)->h_dest;
++ int (*rhook)(struct sk_buff **pskb);
+
+ if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
+ goto drop;
+@@ -148,9 +149,9 @@ struct sk_buff *br_handle_frame(struct n
+
+ switch (p->state) {
+ case BR_STATE_FORWARDING:
+-
+- if (br_should_route_hook) {
+- if (br_should_route_hook(&skb))
++ rhook = rcu_dereference(br_should_route_hook);
++ if (rhook != NULL) {
++ if (rhook(&skb))
+ return skb;
+ dest = eth_hdr(skb)->h_dest;
+ }
+--- a/net/bridge/netfilter/ebtable_broute.c
++++ b/net/bridge/netfilter/ebtable_broute.c
+@@ -70,13 +70,13 @@ static int __init ebtable_broute_init(vo
+ if (ret < 0)
+ return ret;
+ /* see br_input.c */
+- br_should_route_hook = ebt_broute;
++ rcu_assign_pointer(br_should_route_hook, ebt_broute);
+ return ret;
+ }
+
+ static void __exit ebtable_broute_fini(void)
+ {
+- br_should_route_hook = NULL;
++ rcu_assign_pointer(br_should_route_hook, NULL);
+ synchronize_net();
+ ebt_unregister_table(&broute_table);
+ }
--- /dev/null
+From stable-bounces@linux.kernel.org Fri Dec 7 16:26:06 2007
+From: Tejun Heo <htejun@gmail.com>
+Date: Sat, 08 Dec 2007 09:25:31 +0900
+Subject: [stable] [PATCH -stable] libata: kill spurious NCQ completion detection
+To: stable@kernel.org, IDE/ATA development list <linux-ide@vger.kernel.org>
+Cc: Michael Tokarev <mjt@tls.msk.ru>, Jeff Garzik <jeff@garzik.org>, Diego Torres <dtorres@coral.dnsalias.org>
+Message-ID: <4759E47B.8000108@gmail.com>
+
+From: Tejun Heo <htejun@gmail.com>
+
+patch 459ad68893a84fb0881e57919340b97edbbc3dc7 in mainline.
+
+Spurious NCQ completion detection implemented in ahci was incorrect.
+On AHCI receving and processing FISes and raising interrupts are not
+interlocked and spurious interrupts are expected.
+
+For example, if an interrupt occurs while interrupt handler is running
+and the running interrupt handler handles the event the new IRQ
+indicated, after IRQ handler finishes, it will be executed again
+because IRQ pending bit is set by the new interrupt but there won't be
+anything to process.
+
+Please read the following message for more information.
+
+ http://article.gmane.org/gmane.linux.ide/26012
+
+This patch...
+
+* Removes all spurious IRQ whining from ahci. Spurious NCQ completion
+ detection was completely wrong. Spurious D2H Register FIS taught us
+ that some early drives send spurious D2H Register FIS with I bit set
+ while NCQ commands are in progress but none of recent drives does
+ that and even the ones which show such behavior can do NCQ fine.
+
+* Kills all NCQ blacklist entries which were added because of spurious
+ NCQ completions. I tracked down each commit and verified all
+ removed ones are actually added because of spurious completions.
+
+ WD740ADFD-00NLR1 wasn't deleted but moved upward because the drive
+ not only had spurious NCQ completions but also is slow on sequential
+ data transfers if NCQ is enabled.
+
+ Maxtor 7V300F0 was added by 0e3dbc01d53940fe10e5a5cfec15ede3e929c918
+ from Alan Cox. I can only find evidences that the drive only had
+ troubles with spuruious completions by searching the mailing list.
+ This entry needs to be verified and removed if it doesn't have other
+ NCQ related problems.
+
+Signed-off-by: Tejun Heo <htejun@gmail.com>
+Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
+Signed-off-by: Jeff Garzik <jeff@garzik.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/ahci.c | 65 ----------------------------------------------
+ drivers/ata/libata-core.c | 10 -------
+ 2 files changed, 2 insertions(+), 73 deletions(-)
+
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -1241,7 +1241,7 @@ static void ahci_host_intr(struct ata_po
+ struct ata_eh_info *ehi = &ap->eh_info;
+ struct ahci_port_priv *pp = ap->private_data;
+ u32 status, qc_active;
+- int rc, known_irq = 0;
++ int rc;
+
+ status = readl(port_mmio + PORT_IRQ_STAT);
+ writel(status, port_mmio + PORT_IRQ_STAT);
+@@ -1257,74 +1257,11 @@ static void ahci_host_intr(struct ata_po
+ qc_active = readl(port_mmio + PORT_CMD_ISSUE);
+
+ rc = ata_qc_complete_multiple(ap, qc_active, NULL);
+- if (rc > 0)
+- return;
+ if (rc < 0) {
+ ehi->err_mask |= AC_ERR_HSM;
+ ehi->action |= ATA_EH_SOFTRESET;
+ ata_port_freeze(ap);
+- return;
+- }
+-
+- /* hmmm... a spurious interupt */
+-
+- /* if !NCQ, ignore. No modern ATA device has broken HSM
+- * implementation for non-NCQ commands.
+- */
+- if (!ap->sactive)
+- return;
+-
+- if (status & PORT_IRQ_D2H_REG_FIS) {
+- if (!pp->ncq_saw_d2h)
+- ata_port_printk(ap, KERN_INFO,
+- "D2H reg with I during NCQ, "
+- "this message won't be printed again\n");
+- pp->ncq_saw_d2h = 1;
+- known_irq = 1;
+- }
+-
+- if (status & PORT_IRQ_DMAS_FIS) {
+- if (!pp->ncq_saw_dmas)
+- ata_port_printk(ap, KERN_INFO,
+- "DMAS FIS during NCQ, "
+- "this message won't be printed again\n");
+- pp->ncq_saw_dmas = 1;
+- known_irq = 1;
+- }
+-
+- if (status & PORT_IRQ_SDB_FIS) {
+- const __le32 *f = pp->rx_fis + RX_FIS_SDB;
+-
+- if (le32_to_cpu(f[1])) {
+- /* SDB FIS containing spurious completions
+- * might be dangerous, whine and fail commands
+- * with HSM violation. EH will turn off NCQ
+- * after several such failures.
+- */
+- ata_ehi_push_desc(ehi,
+- "spurious completions during NCQ "
+- "issue=0x%x SAct=0x%x FIS=%08x:%08x",
+- readl(port_mmio + PORT_CMD_ISSUE),
+- readl(port_mmio + PORT_SCR_ACT),
+- le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+- ehi->err_mask |= AC_ERR_HSM;
+- ehi->action |= ATA_EH_SOFTRESET;
+- ata_port_freeze(ap);
+- } else {
+- if (!pp->ncq_saw_sdb)
+- ata_port_printk(ap, KERN_INFO,
+- "spurious SDB FIS %08x:%08x during NCQ, "
+- "this message won't be printed again\n",
+- le32_to_cpu(f[0]), le32_to_cpu(f[1]));
+- pp->ncq_saw_sdb = 1;
+- }
+- known_irq = 1;
+ }
+-
+- if (!known_irq)
+- ata_port_printk(ap, KERN_INFO, "spurious interrupt "
+- "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n",
+- status, ap->active_tag, ap->sactive);
+ }
+
+ static void ahci_irq_clear(struct ata_port *ap)
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -3785,6 +3785,7 @@ static const struct ata_blacklist_entry
+ /* Devices where NCQ should be avoided */
+ /* NCQ is slow */
+ { "WDC WD740ADFD-00", NULL, ATA_HORKAGE_NONCQ },
++ { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, },
+ /* http://thread.gmane.org/gmane.linux.ide/14907 */
+ { "FUJITSU MHT2060BH", NULL, ATA_HORKAGE_NONCQ },
+ /* NCQ is broken */
+@@ -3803,15 +3804,6 @@ static const struct ata_blacklist_entry
+ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
+ { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, },
+ { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, },
+- /* Drives which do spurious command completion */
+- { "HTS541680J9SA00", "SB2IC7EP", ATA_HORKAGE_NONCQ, },
+- { "HTS541612J9SA00", "SBDIC7JP", ATA_HORKAGE_NONCQ, },
+- { "Hitachi HTS541616J9SA00", "SB4OC70P", ATA_HORKAGE_NONCQ, },
+- { "WDC WD740ADFD-00NLR1", NULL, ATA_HORKAGE_NONCQ, },
+- { "FUJITSU MHV2080BH", "00840028", ATA_HORKAGE_NONCQ, },
+- { "ST9160821AS", "3.CLF", ATA_HORKAGE_NONCQ, },
+- { "ST3160812AS", "3.AD", ATA_HORKAGE_NONCQ, },
+- { "SAMSUNG HD401LJ", "ZZ100-15", ATA_HORKAGE_NONCQ, },
+
+ /* End Marker */
+ { }