#define IS_ILK(id) (id == 0x00408086 || id == 0x00448086 || id== 0x00628086 || id == 0x006A8086)
#define IS_CPT(id) (id == 0x01008086 || id == 0x01048086)
+/* SandyBridge IGD timeouts in milliseconds */
+#define SNB_IGD_TIMEOUT_LEGACY 1000
+#define SNB_IGD_TIMEOUT 670
+static unsigned int snb_igd_timeout;
+
static u32 __read_mostly ioh_id;
static u32 __initdata igd_id;
bool_t __read_mostly rwbf_quirk;
* Workaround is to prevent graphics get into RC6
* state when doing VT-d IOTLB operations, do the VT-d
* IOTLB operation, and then re-enable RC6 state.
+ *
+ * This quirk is enabled with the snb_igd_quirk command
+ * line parameter. Specifying snb_igd_quirk with no value
+ * (or any of the standard boolean values) enables this
+ * quirk and sets the timeout to the legacy timeout of
+ * 1000 msec. Setting this parameter to the string
+ * "cap" enables this quirk and sets the timeout to
+ * the theoretical maximum of 670 msec. Setting this
+ * parameter to a numerical value enables the quirk and
+ * sets the timeout to that numerical number of msecs.
*/
static void snb_vtd_ops_preamble(struct iommu* iommu)
{
start_time = NOW();
while ( (*(volatile u32 *)(igd_reg_va + 0x22AC) & 0xF) != 0 )
{
- if ( NOW() > start_time + DMAR_OPERATION_TIMEOUT )
+ if ( NOW() > start_time + snb_igd_timeout )
{
dprintk(XENLOG_INFO VTDPREFIX,
"snb_vtd_ops_preamble: failed to disable idle handshake\n");
* call before VT-d translation enable and IOTLB flush operations.
*/
-static int snb_igd_quirk;
-boolean_param("snb_igd_quirk", snb_igd_quirk);
-
void vtd_ops_preamble_quirk(struct iommu* iommu)
{
cantiga_vtd_ops_preamble(iommu);
- if ( snb_igd_quirk )
+ if ( snb_igd_timeout != 0 )
{
spin_lock(&igd_lock);
*/
void vtd_ops_postamble_quirk(struct iommu* iommu)
{
- if ( snb_igd_quirk )
+ if ( snb_igd_timeout != 0 )
{
snb_vtd_ops_postamble(iommu);
}
}
+static void __init parse_snb_timeout(const char *s)
+{
+ int t;
+
+ t = parse_bool(s);
+ if ( t < 0 )
+ {
+ if ( *s == '\0' )
+ t = SNB_IGD_TIMEOUT_LEGACY;
+ else if ( strcmp(s, "cap") == 0 )
+ t = SNB_IGD_TIMEOUT;
+ else
+ t = strtoul(s, NULL, 0);
+ }
+ else
+ t = t ? SNB_IGD_TIMEOUT_LEGACY : 0;
+ snb_igd_timeout = MILLISECS(t);
+
+ return;
+}
+custom_param("snb_igd_quirk", parse_snb_timeout);
+
/* 5500/5520/X58 Chipset Interrupt remapping errata, for stepping B-3.
* Fixed in stepping C-2. */
static void __init tylersburg_intremap_quirk(void)