aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ioat
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2012-09-15 00:08:39 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-11-15 08:20:01 -0500
commit07bd34db29e56be78297e973fd16e8f32ecd0a43 (patch)
tree486c1174e0612af0aff858b36ce048622b59410a /drivers/dma/ioat
parent702ed3c1a9dfe4dfe112f13542d0c9d689f5008b (diff)
ioat: Do not enable DCA if tag map is invalid
I have encountered several systems that have an invalid tag map. This invalid tag map results in only two tags being generated 0x1F which is usually applied to the first core in a Hyper-threaded pair and 0x00 which is applied to the second core in a Hyper-threaded pair. The net result of all this is that DCA causes significant cache thrash because the 0x1F tag will send traffic to the second socket, which the 0x00 tag will not DCA tag the frame resulting in no benefit. For now the best solution from the driver's perspective is to just disable DCA if the tag map is invalid. The correct solution for this would be to have the BIOS on affected systems updated so that the correct tags are generated for a given APIC ID. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Stephen Ko <stephen.s.ko@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/dma/ioat')
-rw-r--r--drivers/dma/ioat/dca.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/dma/ioat/dca.c b/drivers/dma/ioat/dca.c
index abd9038e06b1..d6668071bd0d 100644
--- a/drivers/dma/ioat/dca.c
+++ b/drivers/dma/ioat/dca.c
@@ -604,6 +604,23 @@ static int ioat3_dca_count_dca_slots(void *iobase, u16 dca_offset)
604 return slots; 604 return slots;
605} 605}
606 606
607static inline int dca3_tag_map_invalid(u8 *tag_map)
608{
609 /*
610 * If the tag map is not programmed by the BIOS the default is:
611 * 0x80 0x80 0x80 0x80 0x80 0x00 0x00 0x00
612 *
613 * This an invalid map and will result in only 2 possible tags
614 * 0x1F and 0x00. 0x00 is an invalid DCA tag so we know that
615 * this entire definition is invalid.
616 */
617 return ((tag_map[0] == DCA_TAG_MAP_VALID) &&
618 (tag_map[1] == DCA_TAG_MAP_VALID) &&
619 (tag_map[2] == DCA_TAG_MAP_VALID) &&
620 (tag_map[3] == DCA_TAG_MAP_VALID) &&
621 (tag_map[4] == DCA_TAG_MAP_VALID));
622}
623
607struct dca_provider * __devinit 624struct dca_provider * __devinit
608ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase) 625ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
609{ 626{
@@ -674,6 +691,12 @@ ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
674 ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK; 691 ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
675 } 692 }
676 693
694 if (dca3_tag_map_invalid(ioatdca->tag_map)) {
695 dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n");
696 free_dca_provider(dca);
697 return NULL;
698 }
699
677 err = register_dca_provider(dca, &pdev->dev); 700 err = register_dca_provider(dca, &pdev->dev);
678 if (err) { 701 if (err) {
679 free_dca_provider(dca); 702 free_dca_provider(dca);