* [PATCH dtv-scan-tables] Rename pl-Krosno_Sucha_Gora with only ASCII characters
From: Thomas Petazzoni @ 2016-11-14 21:05 UTC (permalink / raw)
To: Olliver Schinagl, linux-media, Mauro Carvalho Chehab; +Cc: Thomas Petazzoni
The pl-Krosno_Sucha_Gora file, added in commit
4cb113fd15e562f0629000fcad9f41405595198d, is the only file that
contains non-ASCII characters in the tree. This causes a number of
build issues with other packages that don't necessarily handle very
well non-ASCII file name encodings.
Since no other file in the tree contain non-ASCII characters in their
name, this commit renames pl-Krosno_Sucha_Gora similarly.
Examples of files that are named with only ASCII characters even if
the city name really contains non-ASCII characters:
- pl-Wroclaw should be written pl-Wrocław
- se-Laxsjo should be written se-Laxsjö
- de-Dusseldorf should be written de-Düsseldorf
- vn-Thaibinh should be written vn-Thái_Bình
Since there is no real standardization on the encoding of file names,
we'd better be safe and use only ASCII characters.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
"dvb-t/pl-Krosno_Sucha_G\303\263ra" => dvb-t/pl-Krosno_Sucha_Gora | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename "dvb-t/pl-Krosno_Sucha_G\303\263ra" => dvb-t/pl-Krosno_Sucha_Gora (100%)
diff --git "a/dvb-t/pl-Krosno_Sucha_G\303\263ra" b/dvb-t/pl-Krosno_Sucha_Gora
similarity index 100%
rename from "dvb-t/pl-Krosno_Sucha_G\303\263ra"
rename to dvb-t/pl-Krosno_Sucha_Gora
--
2.7.4
^ permalink raw reply
* [Intel-wired-lan] [next PATCH S53-V2 1/5] i40e: use unsigned printf format specifier for active_filters count
From: Bimmy Pujari @ 2016-11-14 21:06 UTC (permalink / raw)
To: intel-wired-lan
From: Jacob Keller <jacob.e.keller@intel.com>
Replace the %d specifier used for printing vsi->active_filters and
vsi->promisc_threshold with an unsigned %u format specifier. While it is
unlikely in practice that these values will ever reach such a large
number they are unsigned values and thus should not be interpreted as
negative numbers.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Change-ID: Iff050fad5a1c8537c4c57fcd527441cd95cfc0d4
---
Testing-hints:
This should go upstream, even though it is in debugfs code. We're not
adding features but simply correcting output of existing features.
drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index b8a03a0..f1f41f1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -172,7 +172,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
f->macaddr, f->vlan,
i40e_filter_state_string[f->state]);
}
- dev_info(&pf->pdev->dev, " active_filters %d, promisc_threshold %d, overflow promisc %s\n",
+ dev_info(&pf->pdev->dev, " active_filters %u, promisc_threshold %u, overflow promisc %s\n",
vsi->active_filters, vsi->promisc_threshold,
(test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) ?
"ON" : "OFF"));
--
2.4.11
^ permalink raw reply related
* [Intel-wired-lan] [next PATCH S53-V2 2/5] i40e: Add support for 25G devices
From: Bimmy Pujari @ 2016-11-14 21:06 UTC (permalink / raw)
To: intel-wired-lan
In-Reply-To: <1479157609-30812-1-git-send-email-bimmy.pujari@intel.com>
From: Carolyn Wyborny <carolyn.wyborny@intel.com>
Add support for 25G devices - defines and data structures.
One tricky part here is that the firmware support for these
Devices introduces a mismatch between the PHY type enum and
the bitfields for the phy types.
This change creates a macro and uses it to increment the 25G
PHY values when creating 25G bitfields.
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Signed-off-by: Michal Kosiarz <michal.kosiarz@intel.com>
Signed-off-by: Eric Joyner <eric.joyner@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Henry Tieman <henry.w.tieman@intel.com>
Signed-off-by: Avinash Dayanand <avinash.dayanand@intel.com>
Change-ID: I69b24d837d44cf9220bf5cb8dd46c5be89ce490b
---
Testing Hints : Check that 25G devices link and report
correct device speed.
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 30 +++++++-
drivers/net/ethernet/intel/i40e/i40e_common.c | 11 ++-
drivers/net/ethernet/intel/i40e/i40e_devids.h | 2 +
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 20 +++++-
drivers/net/ethernet/intel/i40e/i40e_main.c | 6 +-
drivers/net/ethernet/intel/i40e/i40e_type.h | 82 +++++++++++++---------
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 3 +
.../net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 30 +++++++-
drivers/net/ethernet/intel/i40evf/i40e_common.c | 2 +
drivers/net/ethernet/intel/i40evf/i40e_devids.h | 2 +
drivers/net/ethernet/intel/i40evf/i40e_type.h | 82 +++++++++++++---------
drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c | 8 +++
.../net/ethernet/intel/i40evf/i40evf_virtchnl.c | 3 +
13 files changed, 202 insertions(+), 79 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
index 67e396b..c9d1f91 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -1642,6 +1642,10 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_1000BASE_LX = 0x1C,
I40E_PHY_TYPE_1000BASE_T_OPTICAL = 0x1D,
I40E_PHY_TYPE_20GBASE_KR2 = 0x1E,
+ I40E_PHY_TYPE_25GBASE_KR = 0x1F,
+ I40E_PHY_TYPE_25GBASE_CR = 0x20,
+ I40E_PHY_TYPE_25GBASE_SR = 0x21,
+ I40E_PHY_TYPE_25GBASE_LR = 0x22,
I40E_PHY_TYPE_MAX
};
@@ -1650,6 +1654,7 @@ enum i40e_aq_phy_type {
#define I40E_LINK_SPEED_10GB_SHIFT 0x3
#define I40E_LINK_SPEED_40GB_SHIFT 0x4
#define I40E_LINK_SPEED_20GB_SHIFT 0x5
+#define I40E_LINK_SPEED_25GB_SHIFT 0x6
enum i40e_aq_link_speed {
I40E_LINK_SPEED_UNKNOWN = 0,
@@ -1657,7 +1662,8 @@ enum i40e_aq_link_speed {
I40E_LINK_SPEED_1GB = BIT(I40E_LINK_SPEED_1000MB_SHIFT),
I40E_LINK_SPEED_10GB = BIT(I40E_LINK_SPEED_10GB_SHIFT),
I40E_LINK_SPEED_40GB = BIT(I40E_LINK_SPEED_40GB_SHIFT),
- I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT)
+ I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT),
+ I40E_LINK_SPEED_25GB = BIT(I40E_LINK_SPEED_25GB_SHIFT),
};
struct i40e_aqc_module_desc {
@@ -1690,7 +1696,13 @@ struct i40e_aq_get_phy_abilities_resp {
__le32 eeer_val;
u8 d3_lpan;
#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 mod_type_ext;
+ u8 ext_comp_code;
u8 phy_id[4];
u8 module_type[3];
u8 qualified_module_count;
@@ -1712,7 +1724,12 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
__le16 eee_capability;
__le32 eeer;
u8 low_power_ctrl;
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 reserved[2];
};
I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1792,6 +1809,13 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_LINK_TX_DRAINED 0x01
#define I40E_AQ_LINK_TX_FLUSHED 0x03
#define I40E_AQ_LINK_FORCED_40G 0x10
+/* 25G Error Codes */
+#define I40E_AQ_25G_NO_ERR 0X00
+#define I40E_AQ_25G_NOT_PRESENT 0X01
+#define I40E_AQ_25G_NVM_CRC_ERR 0X02
+#define I40E_AQ_25G_SBUS_UCODE_ERR 0X03
+#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
+#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
__le16 max_frame_size;
u8 config;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index d1dcd4f..3961fc2 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -53,6 +53,8 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_10G_BASE_T4:
case I40E_DEV_ID_20G_KR2:
case I40E_DEV_ID_20G_KR2_A:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
hw->mac.type = I40E_MAC_XL710;
break;
case I40E_DEV_ID_KX_X722:
@@ -1183,6 +1185,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
case I40E_PHY_TYPE_1000BASE_LX:
case I40E_PHY_TYPE_40GBASE_SR4:
case I40E_PHY_TYPE_40GBASE_LR4:
+ case I40E_PHY_TYPE_25GBASE_LR:
+ case I40E_PHY_TYPE_25GBASE_SR:
media = I40E_MEDIA_TYPE_FIBER;
break;
case I40E_PHY_TYPE_100BASE_TX:
@@ -1197,6 +1201,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
case I40E_PHY_TYPE_10GBASE_SFPP_CU:
case I40E_PHY_TYPE_40GBASE_AOC:
case I40E_PHY_TYPE_10GBASE_AOC:
+ case I40E_PHY_TYPE_25GBASE_CR:
media = I40E_MEDIA_TYPE_DA;
break;
case I40E_PHY_TYPE_1000BASE_KX:
@@ -1204,6 +1209,7 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw)
case I40E_PHY_TYPE_10GBASE_KR:
case I40E_PHY_TYPE_40GBASE_KR4:
case I40E_PHY_TYPE_20GBASE_KR2:
+ case I40E_PHY_TYPE_25GBASE_KR:
media = I40E_MEDIA_TYPE_BACKPLANE;
break;
case I40E_PHY_TYPE_SGMII:
@@ -1608,8 +1614,10 @@ i40e_status i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
if (hw->aq.asq_last_status == I40E_AQ_RC_EIO)
status = I40E_ERR_UNKNOWN_PHY;
- if (report_init)
+ if (report_init) {
hw->phy.phy_types = le32_to_cpu(abilities->phy_type);
+ hw->phy.phy_types |= ((u64)abilities->phy_type_ext << 32);
+ }
return status;
}
@@ -1701,6 +1709,7 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
/* Copy over all the old settings */
config.phy_type = abilities.phy_type;
+ config.phy_type_ext = abilities.phy_type_ext;
config.link_speed = abilities.link_speed;
config.eee_capability = abilities.eee_capability;
config.eeer = abilities.eeer_val;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_devids.h b/drivers/net/ethernet/intel/i40e/i40e_devids.h
index dd4457d..8e46098 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_devids.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_devids.h
@@ -39,6 +39,8 @@
#define I40E_DEV_ID_20G_KR2 0x1587
#define I40E_DEV_ID_20G_KR2_A 0x1588
#define I40E_DEV_ID_10G_BASE_T4 0x1589
+#define I40E_DEV_ID_25G_B 0x158A
+#define I40E_DEV_ID_25G_SFP28 0x158B
#define I40E_DEV_ID_KX_X722 0x37CE
#define I40E_DEV_ID_QSFP_X722 0x37CF
#define I40E_DEV_ID_SFP_X722 0x37D0
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index 6ba0035..4b3a71a 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -265,8 +265,9 @@ static void i40e_partition_setting_complaint(struct i40e_pf *pf)
static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
u32 *advertising)
{
- enum i40e_aq_capabilities_phy_type phy_types = pf->hw.phy.phy_types;
struct i40e_link_status *hw_link_info = &pf->hw.phy.link_info;
+ u64 phy_types = pf->hw.phy.phy_types;
+
*supported = 0x0;
*advertising = 0x0;
@@ -369,6 +370,15 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported,
if (!(pf->flags & I40E_FLAG_HAVE_CRT_RETIMER))
*advertising |= ADVERTISED_1000baseKX_Full;
}
+ if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR ||
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR) {
+ *supported |= SUPPORTED_Autoneg |
+ SUPPORTED_2500baseX_Full;
+ *advertising |= ADVERTISED_Autoneg |
+ ADVERTISED_2500baseX_Full;
+ }
}
/**
@@ -491,6 +501,14 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
ADVERTISED_1000baseKX_Full |
ADVERTISED_Autoneg;
break;
+ case I40E_PHY_TYPE_25GBASE_KR:
+ case I40E_PHY_TYPE_25GBASE_CR:
+ case I40E_PHY_TYPE_25GBASE_SR:
+ case I40E_PHY_TYPE_25GBASE_LR:
+ ecmd->supported |= SUPPORTED_2500baseX_Full |
+ SUPPORTED_Autoneg;
+ ecmd->advertising |= ADVERTISED_2500baseX_Full |
+ ADVERTISED_Autoneg;
default:
/* if we got here and link is up something bad is afoot */
netdev_info(netdev, "WARNING: Link is up but PHY type 0x%x is not recognized.\n",
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index a032dfd..849feaa 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -86,6 +86,8 @@ static const struct pci_device_id i40e_pci_tbl[] = {
{PCI_VDEVICE(INTEL, I40E_DEV_ID_SFP_I_X722), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2), 0},
{PCI_VDEVICE(INTEL, I40E_DEV_ID_20G_KR2_A), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_B), 0},
+ {PCI_VDEVICE(INTEL, I40E_DEV_ID_25G_SFP28), 0},
/* required last entry */
{0, }
};
@@ -5248,6 +5250,9 @@ void i40e_print_link_message(struct i40e_vsi *vsi, bool isup)
case I40E_LINK_SPEED_20GB:
speed = "20 G";
break;
+ case I40E_LINK_SPEED_25GB:
+ speed = "25 G";
+ break;
case I40E_LINK_SPEED_10GB:
speed = "10 G";
break;
@@ -11356,7 +11361,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_dbg(&pf->pdev->dev, "get supported phy types ret = %s last_status = %s\n",
i40e_stat_str(&pf->hw, err),
i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
- pf->hw.phy.phy_types = le32_to_cpu(abilities.phy_type);
/* Add a filter to drop all Flow control frames from any VSI from being
* transmitted. By doing so we stop a malicious VF from sending out
diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h
index e02cb73..7272be3 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_type.h
@@ -213,47 +213,59 @@ struct i40e_link_status {
#define I40E_MODULE_TYPE_1000BASE_T 0x08
};
-enum i40e_aq_capabilities_phy_type {
- I40E_CAP_PHY_TYPE_SGMII = BIT(I40E_PHY_TYPE_SGMII),
- I40E_CAP_PHY_TYPE_1000BASE_KX = BIT(I40E_PHY_TYPE_1000BASE_KX),
- I40E_CAP_PHY_TYPE_10GBASE_KX4 = BIT(I40E_PHY_TYPE_10GBASE_KX4),
- I40E_CAP_PHY_TYPE_10GBASE_KR = BIT(I40E_PHY_TYPE_10GBASE_KR),
- I40E_CAP_PHY_TYPE_40GBASE_KR4 = BIT(I40E_PHY_TYPE_40GBASE_KR4),
- I40E_CAP_PHY_TYPE_XAUI = BIT(I40E_PHY_TYPE_XAUI),
- I40E_CAP_PHY_TYPE_XFI = BIT(I40E_PHY_TYPE_XFI),
- I40E_CAP_PHY_TYPE_SFI = BIT(I40E_PHY_TYPE_SFI),
- I40E_CAP_PHY_TYPE_XLAUI = BIT(I40E_PHY_TYPE_XLAUI),
- I40E_CAP_PHY_TYPE_XLPPI = BIT(I40E_PHY_TYPE_XLPPI),
- I40E_CAP_PHY_TYPE_40GBASE_CR4_CU = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU),
- I40E_CAP_PHY_TYPE_10GBASE_CR1_CU = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU),
- I40E_CAP_PHY_TYPE_10GBASE_AOC = BIT(I40E_PHY_TYPE_10GBASE_AOC),
- I40E_CAP_PHY_TYPE_40GBASE_AOC = BIT(I40E_PHY_TYPE_40GBASE_AOC),
- I40E_CAP_PHY_TYPE_100BASE_TX = BIT(I40E_PHY_TYPE_100BASE_TX),
- I40E_CAP_PHY_TYPE_1000BASE_T = BIT(I40E_PHY_TYPE_1000BASE_T),
- I40E_CAP_PHY_TYPE_10GBASE_T = BIT(I40E_PHY_TYPE_10GBASE_T),
- I40E_CAP_PHY_TYPE_10GBASE_SR = BIT(I40E_PHY_TYPE_10GBASE_SR),
- I40E_CAP_PHY_TYPE_10GBASE_LR = BIT(I40E_PHY_TYPE_10GBASE_LR),
- I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU),
- I40E_CAP_PHY_TYPE_10GBASE_CR1 = BIT(I40E_PHY_TYPE_10GBASE_CR1),
- I40E_CAP_PHY_TYPE_40GBASE_CR4 = BIT(I40E_PHY_TYPE_40GBASE_CR4),
- I40E_CAP_PHY_TYPE_40GBASE_SR4 = BIT(I40E_PHY_TYPE_40GBASE_SR4),
- I40E_CAP_PHY_TYPE_40GBASE_LR4 = BIT(I40E_PHY_TYPE_40GBASE_LR4),
- I40E_CAP_PHY_TYPE_1000BASE_SX = BIT(I40E_PHY_TYPE_1000BASE_SX),
- I40E_CAP_PHY_TYPE_1000BASE_LX = BIT(I40E_PHY_TYPE_1000BASE_LX),
- I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL =
- BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL),
- I40E_CAP_PHY_TYPE_20GBASE_KR2 = BIT(I40E_PHY_TYPE_20GBASE_KR2)
-};
-
struct i40e_phy_info {
struct i40e_link_status link_info;
struct i40e_link_status link_info_old;
bool get_link_info;
enum i40e_media_type media_type;
/* all the phy types the NVM is capable of */
- enum i40e_aq_capabilities_phy_type phy_types;
-};
-
+ u64 phy_types;
+};
+
+#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII)
+#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX)
+#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4)
+#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR)
+#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4)
+#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI)
+#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI)
+#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI)
+#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI)
+#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR)
+#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR)
+#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4)
+#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX)
+#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \
+ BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL)
+#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2)
+/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some
+ * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit
+ * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So,
+ * a shift is needed to adjust for this with values larger than 31. The
+ * only affected values are I40E_PHY_TYPE_25GBASE_*.
+ */
+#define I40E_PHY_TYPE_OFFSET 1
+#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
+ I40E_PHY_TYPE_OFFSET)
#define I40E_HW_CAP_MAX_GPIO 30
/* Capabilities of a PF or a VF or the whole device */
struct i40e_hw_capabilities {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 05ed49b..d28b684 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -2921,6 +2921,9 @@ int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
case I40E_LINK_SPEED_40GB:
speed = 40000;
break;
+ case I40E_LINK_SPEED_25GB:
+ speed = 25000;
+ break;
case I40E_LINK_SPEED_20GB:
speed = 20000;
break;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index 40b0eaf..f8d7d95 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -1639,6 +1639,10 @@ enum i40e_aq_phy_type {
I40E_PHY_TYPE_1000BASE_LX = 0x1C,
I40E_PHY_TYPE_1000BASE_T_OPTICAL = 0x1D,
I40E_PHY_TYPE_20GBASE_KR2 = 0x1E,
+ I40E_PHY_TYPE_25GBASE_KR = 0x1F,
+ I40E_PHY_TYPE_25GBASE_CR = 0x20,
+ I40E_PHY_TYPE_25GBASE_SR = 0x21,
+ I40E_PHY_TYPE_25GBASE_LR = 0x22,
I40E_PHY_TYPE_MAX
};
@@ -1647,6 +1651,7 @@ enum i40e_aq_phy_type {
#define I40E_LINK_SPEED_10GB_SHIFT 0x3
#define I40E_LINK_SPEED_40GB_SHIFT 0x4
#define I40E_LINK_SPEED_20GB_SHIFT 0x5
+#define I40E_LINK_SPEED_25GB_SHIFT 0x6
enum i40e_aq_link_speed {
I40E_LINK_SPEED_UNKNOWN = 0,
@@ -1654,7 +1659,8 @@ enum i40e_aq_link_speed {
I40E_LINK_SPEED_1GB = BIT(I40E_LINK_SPEED_1000MB_SHIFT),
I40E_LINK_SPEED_10GB = BIT(I40E_LINK_SPEED_10GB_SHIFT),
I40E_LINK_SPEED_40GB = BIT(I40E_LINK_SPEED_40GB_SHIFT),
- I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT)
+ I40E_LINK_SPEED_20GB = BIT(I40E_LINK_SPEED_20GB_SHIFT),
+ I40E_LINK_SPEED_25GB = BIT(I40E_LINK_SPEED_25GB_SHIFT),
};
struct i40e_aqc_module_desc {
@@ -1687,7 +1693,13 @@ struct i40e_aq_get_phy_abilities_resp {
__le32 eeer_val;
u8 d3_lpan;
#define I40E_AQ_SET_PHY_D3_LPAN_ENA 0x01
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 mod_type_ext;
+ u8 ext_comp_code;
u8 phy_id[4];
u8 module_type[3];
u8 qualified_module_count;
@@ -1709,7 +1721,12 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
__le16 eee_capability;
__le32 eeer;
u8 low_power_ctrl;
- u8 reserved[3];
+ u8 phy_type_ext;
+#define I40E_AQ_PHY_TYPE_EXT_25G_KR 0X01
+#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
+#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
+#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
+ u8 reserved[2];
};
I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1789,6 +1806,13 @@ struct i40e_aqc_get_link_status {
#define I40E_AQ_LINK_TX_DRAINED 0x01
#define I40E_AQ_LINK_TX_FLUSHED 0x03
#define I40E_AQ_LINK_FORCED_40G 0x10
+/* 25G Error Codes */
+#define I40E_AQ_25G_NO_ERR 0X00
+#define I40E_AQ_25G_NOT_PRESENT 0X01
+#define I40E_AQ_25G_NVM_CRC_ERR 0X02
+#define I40E_AQ_25G_SBUS_UCODE_ERR 0X03
+#define I40E_AQ_25G_SERDES_UCODE_ERR 0X04
+#define I40E_AQ_25G_NIMB_UCODE_ERR 0X05
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
__le16 max_frame_size;
u8 config;
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_common.c b/drivers/net/ethernet/intel/i40evf/i40e_common.c
index 7953c13..aa63b7f 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_common.c
@@ -53,6 +53,8 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_10G_BASE_T4:
case I40E_DEV_ID_20G_KR2:
case I40E_DEV_ID_20G_KR2_A:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
hw->mac.type = I40E_MAC_XL710;
break;
case I40E_DEV_ID_SFP_X722:
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_devids.h b/drivers/net/ethernet/intel/i40evf/i40e_devids.h
index 7023570..21dcaee 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_devids.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_devids.h
@@ -39,6 +39,8 @@
#define I40E_DEV_ID_20G_KR2 0x1587
#define I40E_DEV_ID_20G_KR2_A 0x1588
#define I40E_DEV_ID_10G_BASE_T4 0x1589
+#define I40E_DEV_ID_25G_B 0x158A
+#define I40E_DEV_ID_25G_SFP28 0x158B
#define I40E_DEV_ID_VF 0x154C
#define I40E_DEV_ID_VF_HV 0x1571
#define I40E_DEV_ID_SFP_X722 0x37D0
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_type.h b/drivers/net/ethernet/intel/i40evf/i40e_type.h
index 515484c..c85e8a3 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_type.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_type.h
@@ -187,47 +187,59 @@ struct i40e_link_status {
#define I40E_MODULE_TYPE_1000BASE_T 0x08
};
-enum i40e_aq_capabilities_phy_type {
- I40E_CAP_PHY_TYPE_SGMII = BIT(I40E_PHY_TYPE_SGMII),
- I40E_CAP_PHY_TYPE_1000BASE_KX = BIT(I40E_PHY_TYPE_1000BASE_KX),
- I40E_CAP_PHY_TYPE_10GBASE_KX4 = BIT(I40E_PHY_TYPE_10GBASE_KX4),
- I40E_CAP_PHY_TYPE_10GBASE_KR = BIT(I40E_PHY_TYPE_10GBASE_KR),
- I40E_CAP_PHY_TYPE_40GBASE_KR4 = BIT(I40E_PHY_TYPE_40GBASE_KR4),
- I40E_CAP_PHY_TYPE_XAUI = BIT(I40E_PHY_TYPE_XAUI),
- I40E_CAP_PHY_TYPE_XFI = BIT(I40E_PHY_TYPE_XFI),
- I40E_CAP_PHY_TYPE_SFI = BIT(I40E_PHY_TYPE_SFI),
- I40E_CAP_PHY_TYPE_XLAUI = BIT(I40E_PHY_TYPE_XLAUI),
- I40E_CAP_PHY_TYPE_XLPPI = BIT(I40E_PHY_TYPE_XLPPI),
- I40E_CAP_PHY_TYPE_40GBASE_CR4_CU = BIT(I40E_PHY_TYPE_40GBASE_CR4_CU),
- I40E_CAP_PHY_TYPE_10GBASE_CR1_CU = BIT(I40E_PHY_TYPE_10GBASE_CR1_CU),
- I40E_CAP_PHY_TYPE_10GBASE_AOC = BIT(I40E_PHY_TYPE_10GBASE_AOC),
- I40E_CAP_PHY_TYPE_40GBASE_AOC = BIT(I40E_PHY_TYPE_40GBASE_AOC),
- I40E_CAP_PHY_TYPE_100BASE_TX = BIT(I40E_PHY_TYPE_100BASE_TX),
- I40E_CAP_PHY_TYPE_1000BASE_T = BIT(I40E_PHY_TYPE_1000BASE_T),
- I40E_CAP_PHY_TYPE_10GBASE_T = BIT(I40E_PHY_TYPE_10GBASE_T),
- I40E_CAP_PHY_TYPE_10GBASE_SR = BIT(I40E_PHY_TYPE_10GBASE_SR),
- I40E_CAP_PHY_TYPE_10GBASE_LR = BIT(I40E_PHY_TYPE_10GBASE_LR),
- I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU = BIT(I40E_PHY_TYPE_10GBASE_SFPP_CU),
- I40E_CAP_PHY_TYPE_10GBASE_CR1 = BIT(I40E_PHY_TYPE_10GBASE_CR1),
- I40E_CAP_PHY_TYPE_40GBASE_CR4 = BIT(I40E_PHY_TYPE_40GBASE_CR4),
- I40E_CAP_PHY_TYPE_40GBASE_SR4 = BIT(I40E_PHY_TYPE_40GBASE_SR4),
- I40E_CAP_PHY_TYPE_40GBASE_LR4 = BIT(I40E_PHY_TYPE_40GBASE_LR4),
- I40E_CAP_PHY_TYPE_1000BASE_SX = BIT(I40E_PHY_TYPE_1000BASE_SX),
- I40E_CAP_PHY_TYPE_1000BASE_LX = BIT(I40E_PHY_TYPE_1000BASE_LX),
- I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL =
- BIT(I40E_PHY_TYPE_1000BASE_T_OPTICAL),
- I40E_CAP_PHY_TYPE_20GBASE_KR2 = BIT(I40E_PHY_TYPE_20GBASE_KR2)
-};
-
struct i40e_phy_info {
struct i40e_link_status link_info;
struct i40e_link_status link_info_old;
bool get_link_info;
enum i40e_media_type media_type;
/* all the phy types the NVM is capable of */
- enum i40e_aq_capabilities_phy_type phy_types;
-};
-
+ u64 phy_types;
+};
+
+#define I40E_CAP_PHY_TYPE_SGMII BIT_ULL(I40E_PHY_TYPE_SGMII)
+#define I40E_CAP_PHY_TYPE_1000BASE_KX BIT_ULL(I40E_PHY_TYPE_1000BASE_KX)
+#define I40E_CAP_PHY_TYPE_10GBASE_KX4 BIT_ULL(I40E_PHY_TYPE_10GBASE_KX4)
+#define I40E_CAP_PHY_TYPE_10GBASE_KR BIT_ULL(I40E_PHY_TYPE_10GBASE_KR)
+#define I40E_CAP_PHY_TYPE_40GBASE_KR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_KR4)
+#define I40E_CAP_PHY_TYPE_XAUI BIT_ULL(I40E_PHY_TYPE_XAUI)
+#define I40E_CAP_PHY_TYPE_XFI BIT_ULL(I40E_PHY_TYPE_XFI)
+#define I40E_CAP_PHY_TYPE_SFI BIT_ULL(I40E_PHY_TYPE_SFI)
+#define I40E_CAP_PHY_TYPE_XLAUI BIT_ULL(I40E_PHY_TYPE_XLAUI)
+#define I40E_CAP_PHY_TYPE_XLPPI BIT_ULL(I40E_PHY_TYPE_XLPPI)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4_CU BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_AOC BIT_ULL(I40E_PHY_TYPE_10GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_40GBASE_AOC BIT_ULL(I40E_PHY_TYPE_40GBASE_AOC)
+#define I40E_CAP_PHY_TYPE_100BASE_TX BIT_ULL(I40E_PHY_TYPE_100BASE_TX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T BIT_ULL(I40E_PHY_TYPE_1000BASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_T BIT_ULL(I40E_PHY_TYPE_10GBASE_T)
+#define I40E_CAP_PHY_TYPE_10GBASE_SR BIT_ULL(I40E_PHY_TYPE_10GBASE_SR)
+#define I40E_CAP_PHY_TYPE_10GBASE_LR BIT_ULL(I40E_PHY_TYPE_10GBASE_LR)
+#define I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU BIT_ULL(I40E_PHY_TYPE_10GBASE_SFPP_CU)
+#define I40E_CAP_PHY_TYPE_10GBASE_CR1 BIT_ULL(I40E_PHY_TYPE_10GBASE_CR1)
+#define I40E_CAP_PHY_TYPE_40GBASE_CR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_CR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_SR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_SR4)
+#define I40E_CAP_PHY_TYPE_40GBASE_LR4 BIT_ULL(I40E_PHY_TYPE_40GBASE_LR4)
+#define I40E_CAP_PHY_TYPE_1000BASE_SX BIT_ULL(I40E_PHY_TYPE_1000BASE_SX)
+#define I40E_CAP_PHY_TYPE_1000BASE_LX BIT_ULL(I40E_PHY_TYPE_1000BASE_LX)
+#define I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL \
+ BIT_ULL(I40E_PHY_TYPE_1000BASE_T_OPTICAL)
+#define I40E_CAP_PHY_TYPE_20GBASE_KR2 BIT_ULL(I40E_PHY_TYPE_20GBASE_KR2)
+/* Defining the macro I40E_TYPE_OFFSET to implement a bit shift for some
+ * PHY types. There is an unused bit (31) in the I40E_CAP_PHY_TYPE_* bit
+ * fields but no corresponding gap in the i40e_aq_phy_type enumeration. So,
+ * a shift is needed to adjust for this with values larger than 31. The
+ * only affected values are I40E_PHY_TYPE_25GBASE_*.
+ */
+#define I40E_PHY_TYPE_OFFSET 1
+#define I40E_CAP_PHY_TYPE_25GBASE_KR BIT_ULL(I40E_PHY_TYPE_25GBASE_KR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_CR BIT_ULL(I40E_PHY_TYPE_25GBASE_CR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_SR BIT_ULL(I40E_PHY_TYPE_25GBASE_SR + \
+ I40E_PHY_TYPE_OFFSET)
+#define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \
+ I40E_PHY_TYPE_OFFSET)
#define I40E_HW_CAP_MAX_GPIO 30
/* Capabilities of a PF or a VF or the whole device */
struct i40e_hw_capabilities {
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
index a994015..272d600 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c
@@ -85,6 +85,14 @@ static int i40evf_get_settings(struct net_device *netdev,
case I40E_LINK_SPEED_40GB:
ethtool_cmd_speed_set(ecmd, SPEED_40000);
break;
+ case I40E_LINK_SPEED_25GB:
+#ifdef SPEED_25000
+ ethtool_cmd_speed_set(ecmd, SPEED_25000);
+#else
+ netdev_info(netdev,
+ "Speed is 25G, display not supported by this version of ethtool.\n");
+#endif
+ break;
case I40E_LINK_SPEED_20GB:
ethtool_cmd_speed_set(ecmd, SPEED_20000);
break;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
index ddf478d..2059a8e 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
@@ -836,6 +836,9 @@ static void i40evf_print_link_message(struct i40evf_adapter *adapter)
case I40E_LINK_SPEED_40GB:
speed = "40 G";
break;
+ case I40E_LINK_SPEED_25GB:
+ speed = "25 G";
+ break;
case I40E_LINK_SPEED_20GB:
speed = "20 G";
break;
--
2.4.11
^ permalink raw reply related
* Re: BUG: KASAN: use-after-free in snd_usb_audio_free
From: Takashi Iwai @ 2016-11-14 21:06 UTC (permalink / raw)
To: Shuah Khan; +Cc: Shuah Khan, alsa-devel, LKML
In-Reply-To: <c0ebdec6-717a-c5d8-56e4-9b9a5a9e111d@osg.samsung.com>
On Mon, 14 Nov 2016 17:55:54 +0100,
Shuah Khan wrote:
>
> On 11/14/2016 03:25 AM, Takashi Iwai wrote:
> > On Sat, 12 Nov 2016 00:34:38 +0100,
> > Shuah Khan wrote:
> >>
> >> Hi Takashi,
> >>
> >> I am seeing the following use-after-free error when I disconnect an
> >> USB speaker. I saw this on 4.9-rc4 and 4.8.7. There might be race
> >> condition between the disconnect and pcm close perhaps.
> >
> > Thanks, this looks like a new discovery.
> > Could you check whether the patch below works?
> >
> >
> > Takashi
> >
> > ---
> > diff --git a/sound/usb/card.c b/sound/usb/card.c
> > index 9e5276d6dda0..2ddc034673a8 100644
> > --- a/sound/usb/card.c
> > +++ b/sound/usb/card.c
> > @@ -315,7 +315,8 @@ static int snd_usb_audio_free(struct snd_usb_audio *chip)
> > snd_usb_endpoint_free(ep);
> >
> > mutex_destroy(&chip->mutex);
> > - dev_set_drvdata(&chip->dev->dev, NULL);
> > + if (!atomic_read(&chip->shutdown))
> > + dev_set_drvdata(&chip->dev->dev, NULL);
> > kfree(chip);
> > return 0;
> > }
> >
>
> Hi Takashi,
>
> The patch fixed the problem on 4.9-rc4. Didn't get a chance
> to test it on 4.8.7.
Thanks, this should fix for 4.8.x, too, as there hasn't been any
significant changes in usb-audio recently.
FWIW, below is the proper patch I'm going to queue.
Takashi
-- 8< --
From: Takashi Iwai <tiwai@suse.de>
Subject: [PATCH] ALSA: usb-audio: Fix use-after-free of usb_device at
disconnect
The usb-audio driver implements the deferred device disconnection for
the device in use. In this mode, the disconnection callback returns
immediately while the actual ALSA card object removal happens later
when all files get closed. As Shuah reported, this code flow,
however, leads to a use-after-free, detected by KASAN:
BUG: KASAN: use-after-free in snd_usb_audio_free+0x134/0x160 [snd_usb_audio] at addr ffff8801c863ce10
Write of size 8 by task pulseaudio/2244
Call Trace:
[<ffffffff81b31473>] dump_stack+0x67/0x94
[<ffffffff81564ef1>] kasan_object_err+0x21/0x70
[<ffffffff8156518a>] kasan_report_error+0x1fa/0x4e0
[<ffffffff81564ad7>] ? kasan_slab_free+0x87/0xb0
[<ffffffff81565733>] __asan_report_store8_noabort+0x43/0x50
[<ffffffffa0fc0f54>] ? snd_usb_audio_free+0x134/0x160 [snd_usb_audio]
[<ffffffffa0fc0f54>] snd_usb_audio_free+0x134/0x160 [snd_usb_audio]
[<ffffffffa0fc0fb1>] snd_usb_audio_dev_free+0x31/0x40 [snd_usb_audio]
[<ffffffff8243c78a>] __snd_device_free+0x12a/0x210
[<ffffffff8243d1f5>] snd_device_free_all+0x85/0xd0
[<ffffffff8242cae4>] release_card_device+0x34/0x130
[<ffffffff81ef1846>] device_release+0x76/0x1e0
[<ffffffff81b37ad7>] kobject_release+0x107/0x370
.....
Object at ffff8801c863cc80, in cache kmalloc-2048 size: 2048
Allocated:
[<ffffffff810804eb>] save_stack_trace+0x2b/0x50
[<ffffffff81564296>] save_stack+0x46/0xd0
[<ffffffff8156450d>] kasan_kmalloc+0xad/0xe0
[<ffffffff81560d1a>] kmem_cache_alloc_trace+0xfa/0x240
[<ffffffff8214ea47>] usb_alloc_dev+0x57/0xc90
[<ffffffff8216349d>] hub_event+0xf1d/0x35f0
....
Freed:
[<ffffffff810804eb>] save_stack_trace+0x2b/0x50
[<ffffffff81564296>] save_stack+0x46/0xd0
[<ffffffff81564ac1>] kasan_slab_free+0x71/0xb0
[<ffffffff81560929>] kfree+0xd9/0x280
[<ffffffff8214de6e>] usb_release_dev+0xde/0x110
[<ffffffff81ef1846>] device_release+0x76/0x1e0
....
It's the code trying to clear drvdata of the assigned usb_device where
the usb_device itself was already released in usb_release_dev() after
the disconnect callback.
This patch fixes it by checking whether the code path is via the
disconnect callback, i.e. chip->shutdown flag is set.
Fixes: 79289e24194a ('ALSA: usb-audio: Refer to chip->usb_id for quirks...')
Reported-and-tested-by: Shuah Khan <shuahkh@osg.samsung.com>
Cc: <stable@vger.kernel.org> # v4.6+
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/usb/card.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 9e5276d6dda0..2ddc034673a8 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -315,7 +315,8 @@ static int snd_usb_audio_free(struct snd_usb_audio *chip)
snd_usb_endpoint_free(ep);
mutex_destroy(&chip->mutex);
- dev_set_drvdata(&chip->dev->dev, NULL);
+ if (!atomic_read(&chip->shutdown))
+ dev_set_drvdata(&chip->dev->dev, NULL);
kfree(chip);
return 0;
}
--
2.10.2
^ permalink raw reply related
* [Intel-wired-lan] [next PATCH S53-V2 3/5] i40e: Add FEC for 25g
From: Bimmy Pujari @ 2016-11-14 21:06 UTC (permalink / raw)
To: intel-wired-lan
In-Reply-To: <1479157609-30812-1-git-send-email-bimmy.pujari@intel.com>
From: Carolyn Wyborny <carolyn.wyborny@intel.com>
This patch adds adminq support for Forward Error
Correction ("FEC")for 25g products.
Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jacek Naczyk <jacek.naczyk@intel.com>
Change-ID: Iaff4910737c239d2c730e5c22a313ce9c37d3964
---
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h | 25 ++++++++++++++++++++--
drivers/net/ethernet/intel/i40e/i40e_common.c | 2 ++
.../net/ethernet/intel/i40evf/i40e_adminq_cmd.h | 25 ++++++++++++++++++++--
3 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
index c9d1f91..b2101a5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
@@ -1686,6 +1686,8 @@ struct i40e_aq_get_phy_abilities_resp {
#define I40E_AQ_PHY_LINK_ENABLED 0x08
#define I40E_AQ_PHY_AN_ENABLED 0x10
#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20
+#define I40E_AQ_PHY_FEC_ABILITY_KR 0x40
+#define I40E_AQ_PHY_FEC_ABILITY_RS 0x80
__le16 eee_capability;
#define I40E_AQ_EEE_100BASE_TX 0x0002
#define I40E_AQ_EEE_1000BASE_T 0x0004
@@ -1701,7 +1703,16 @@ struct i40e_aq_get_phy_abilities_resp {
#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
- u8 mod_type_ext;
+ u8 fec_cfg_curr_mod_ext_info;
+#define I40E_AQ_ENABLE_FEC_KR 0x01
+#define I40E_AQ_ENABLE_FEC_RS 0x02
+#define I40E_AQ_REQUEST_FEC_KR 0x04
+#define I40E_AQ_REQUEST_FEC_RS 0x08
+#define I40E_AQ_ENABLE_FEC_AUTO 0x10
+#define I40E_AQ_FEC
+#define I40E_AQ_MODULE_TYPE_EXT_MASK 0xE0
+#define I40E_AQ_MODULE_TYPE_EXT_SHIFT 5
+
u8 ext_comp_code;
u8 phy_id[4];
u8 module_type[3];
@@ -1729,7 +1740,15 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
- u8 reserved[2];
+ u8 fec_config;
+#define I40E_AQ_SET_FEC_ABILITY_KR BIT(0)
+#define I40E_AQ_SET_FEC_ABILITY_RS BIT(1)
+#define I40E_AQ_SET_FEC_REQUEST_KR BIT(2)
+#define I40E_AQ_SET_FEC_REQUEST_RS BIT(3)
+#define I40E_AQ_SET_FEC_AUTO BIT(4)
+#define I40E_AQ_PHY_FEC_CONFIG_SHIFT 0x0
+#define I40E_AQ_PHY_FEC_CONFIG_MASK (0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
+ u8 reserved;
};
I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1819,6 +1838,8 @@ struct i40e_aqc_get_link_status {
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
__le16 max_frame_size;
u8 config;
+#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
+#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78
u8 external_power_ability;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index 3961fc2..d9da786 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -1714,6 +1714,8 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
config.eee_capability = abilities.eee_capability;
config.eeer = abilities.eeer_val;
config.low_power_ctrl = abilities.d3_lpan;
+ config.fec_config = abilities.fec_cfg_curr_mod_ext_info &
+ I40E_AQ_PHY_FEC_CONFIG_MASK;
status = i40e_aq_set_phy_config(hw, &config, NULL);
if (status)
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
index f8d7d95..eeb9864 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
@@ -1683,6 +1683,8 @@ struct i40e_aq_get_phy_abilities_resp {
#define I40E_AQ_PHY_LINK_ENABLED 0x08
#define I40E_AQ_PHY_AN_ENABLED 0x10
#define I40E_AQ_PHY_FLAG_MODULE_QUAL 0x20
+#define I40E_AQ_PHY_FEC_ABILITY_KR 0x40
+#define I40E_AQ_PHY_FEC_ABILITY_RS 0x80
__le16 eee_capability;
#define I40E_AQ_EEE_100BASE_TX 0x0002
#define I40E_AQ_EEE_1000BASE_T 0x0004
@@ -1698,7 +1700,16 @@ struct i40e_aq_get_phy_abilities_resp {
#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
- u8 mod_type_ext;
+ u8 fec_cfg_curr_mod_ext_info;
+#define I40E_AQ_ENABLE_FEC_KR 0x01
+#define I40E_AQ_ENABLE_FEC_RS 0x02
+#define I40E_AQ_REQUEST_FEC_KR 0x04
+#define I40E_AQ_REQUEST_FEC_RS 0x08
+#define I40E_AQ_ENABLE_FEC_AUTO 0x10
+#define I40E_AQ_FEC
+#define I40E_AQ_MODULE_TYPE_EXT_MASK 0xE0
+#define I40E_AQ_MODULE_TYPE_EXT_SHIFT 5
+
u8 ext_comp_code;
u8 phy_id[4];
u8 module_type[3];
@@ -1726,7 +1737,15 @@ struct i40e_aq_set_phy_config { /* same bits as above in all */
#define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02
#define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04
#define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08
- u8 reserved[2];
+ u8 fec_config;
+#define I40E_AQ_SET_FEC_ABILITY_KR BIT(0)
+#define I40E_AQ_SET_FEC_ABILITY_RS BIT(1)
+#define I40E_AQ_SET_FEC_REQUEST_KR BIT(2)
+#define I40E_AQ_SET_FEC_REQUEST_RS BIT(3)
+#define I40E_AQ_SET_FEC_AUTO BIT(4)
+#define I40E_AQ_PHY_FEC_CONFIG_SHIFT 0x0
+#define I40E_AQ_PHY_FEC_CONFIG_MASK (0x1F << I40E_AQ_PHY_FEC_CONFIG_SHIFT)
+ u8 reserved;
};
I40E_CHECK_CMD_LENGTH(i40e_aq_set_phy_config);
@@ -1816,6 +1835,8 @@ struct i40e_aqc_get_link_status {
u8 loopback; /* use defines from i40e_aqc_set_lb_mode */
__le16 max_frame_size;
u8 config;
+#define I40E_AQ_CONFIG_FEC_KR_ENA 0x01
+#define I40E_AQ_CONFIG_FEC_RS_ENA 0x02
#define I40E_AQ_CONFIG_CRC_ENA 0x04
#define I40E_AQ_CONFIG_PACING_MASK 0x78
u8 external_power_ability;
--
2.4.11
^ permalink raw reply related
* [Intel-wired-lan] [next PATCH S53-V2 4/5] i40e: Add functions which apply correct PHY access method for read and write operation
From: Bimmy Pujari @ 2016-11-14 21:06 UTC (permalink / raw)
To: intel-wired-lan
In-Reply-To: <1479157609-30812-1-git-send-email-bimmy.pujari@intel.com>
From: Michal Kosiarz <michal.kosiarz@intel.com>
Depending on external PHY type, register access method should be
different. Clause22 or Clause45 can be chosen for different PHYs.
Implemented functions apply correct access method for used device.
Signed-off-by: Michal Kosiarz <michal.kosiarz@intel.com>
Change-ID: If39d5f0da9c0b905a8cbdc1ab89885535e7d0426
---
drivers/net/ethernet/intel/i40e/i40e_common.c | 72 ++++++++++++++++++++++
drivers/net/ethernet/intel/i40e/i40e_prototype.h | 4 ++
drivers/net/ethernet/intel/i40evf/i40e_prototype.h | 4 ++
3 files changed, 80 insertions(+)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index d9da786..59e766c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -4676,6 +4676,78 @@ i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw, u8 page,
}
/**
+ * i40e_write_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Writes value to specified PHY register
+ **/
+i40e_status i40e_write_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 value)
+{
+ i40e_status status;
+
+ switch (hw->device_id) {
+ case I40E_DEV_ID_1G_BASE_T_X722:
+ status = i40e_write_phy_register_clause22(hw,
+ reg, phy_addr, value);
+ break;
+ case I40E_DEV_ID_10G_BASE_T:
+ case I40E_DEV_ID_10G_BASE_T4:
+ case I40E_DEV_ID_10G_BASE_T_X722:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
+ status = i40e_write_phy_register_clause45(hw,
+ page, reg, phy_addr, value);
+ break;
+ default:
+ status = I40E_ERR_UNKNOWN_PHY;
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * i40e_read_phy_register
+ * @hw: pointer to the HW structure
+ * @page: registers page number
+ * @reg: register address in the page
+ * @phy_adr: PHY address on MDIO interface
+ * @value: PHY register value
+ *
+ * Reads specified PHY register value
+ **/
+i40e_status i40e_read_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 *value)
+{
+ i40e_status status;
+
+ switch (hw->device_id) {
+ case I40E_DEV_ID_1G_BASE_T_X722:
+ status = i40e_read_phy_register_clause22(hw, reg, phy_addr,
+ value);
+ break;
+ case I40E_DEV_ID_10G_BASE_T:
+ case I40E_DEV_ID_10G_BASE_T4:
+ case I40E_DEV_ID_10G_BASE_T_X722:
+ case I40E_DEV_ID_25G_B:
+ case I40E_DEV_ID_25G_SFP28:
+ status = i40e_read_phy_register_clause45(hw, page, reg,
+ phy_addr, value);
+ break;
+ default:
+ status = I40E_ERR_UNKNOWN_PHY;
+ break;
+ }
+
+ return status;
+}
+
+/**
* i40e_get_phy_address
* @hw: pointer to the HW structure
* @dev_num: PHY port num that address we want
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
index 4e641a6..bb5c982 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -373,6 +373,10 @@ i40e_status i40e_read_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval);
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
index d89d521..ee5d7fe 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40evf/i40e_prototype.h
@@ -115,6 +115,10 @@ i40e_status i40e_read_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 *value);
i40e_status i40e_write_phy_register(struct i40e_hw *hw, u8 page,
u16 reg, u8 phy_addr, u16 value);
+i40e_status i40e_read_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 *value);
+i40e_status i40e_write_phy_register(struct i40e_hw *hw,
+ u8 page, u16 reg, u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
i40e_status i40e_blink_phy_link_led(struct i40e_hw *hw,
u32 time, u32 interval);
--
2.4.11
^ permalink raw reply related
* [Intel-wired-lan] [next PATCH S53-V2 5/5] i40e: lock service task correctly
From: Bimmy Pujari @ 2016-11-14 21:06 UTC (permalink / raw)
To: intel-wired-lan
In-Reply-To: <1479157609-30812-1-git-send-email-bimmy.pujari@intel.com>
From: Mitch Williams <mitch.a.williams@intel.com>
The service task lock was being set in the scheduling function, not the
actual service task. This would potentially leave the bit set for a long
time before the task actually ran. Furthermore, if the service task
takes too long, it calls the schedule function to reschedule itself -
which would fail to take the lock and do nothing.
Instead, set and clear the lock bit in the service task itself. In the
process, get rid of the i40e_service_event_complete() function, which is
really just two lines of code that can be put right in the service task
itself.
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Change-ID: I83155e682b686121e2897f4429eb7d3f7c669168
---
Testing Hints : Should be no functional change, particularly around
link up/down events. This is prep work for using this lock bit in
the client.
drivers/net/ethernet/intel/i40e/i40e_main.c | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 849feaa..57850fd 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -288,8 +288,7 @@ struct i40e_vsi *i40e_find_vsi_from_id(struct i40e_pf *pf, u16 id)
void i40e_service_event_schedule(struct i40e_pf *pf)
{
if (!test_bit(__I40E_DOWN, &pf->state) &&
- !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state) &&
- !test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
+ !test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state))
queue_work(i40e_wq, &pf->service_task);
}
@@ -5943,19 +5942,6 @@ static void i40e_handle_lan_overflow_event(struct i40e_pf *pf,
}
/**
- * i40e_service_event_complete - Finish up the service event
- * @pf: board private structure
- **/
-static void i40e_service_event_complete(struct i40e_pf *pf)
-{
- WARN_ON(!test_bit(__I40E_SERVICE_SCHED, &pf->state));
-
- /* flush memory to make sure state is correct before next watchog */
- smp_mb__before_atomic();
- clear_bit(__I40E_SERVICE_SCHED, &pf->state);
-}
-
-/**
* i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
* @pf: board private structure
**/
@@ -7264,10 +7250,12 @@ static void i40e_service_task(struct work_struct *work)
/* don't bother with service tasks if a reset is in progress */
if (test_bit(__I40E_RESET_RECOVERY_PENDING, &pf->state)) {
- i40e_service_event_complete(pf);
return;
}
+ if (test_and_set_bit(__I40E_SERVICE_SCHED, &pf->state))
+ return;
+
i40e_detect_recover_hung(pf);
i40e_sync_filters_subtask(pf);
i40e_reset_subtask(pf);
@@ -7280,7 +7268,9 @@ static void i40e_service_task(struct work_struct *work)
i40e_sync_udp_filters_subtask(pf);
i40e_clean_adminq_subtask(pf);
- i40e_service_event_complete(pf);
+ /* flush memory to make sure state is correct before next watchdog */
+ smp_mb__before_atomic();
+ clear_bit(__I40E_SERVICE_SCHED, &pf->state);
/* If the tasks have taken longer than one timer cycle or there
* is more work to be done, reschedule the service task now
--
2.4.11
^ permalink raw reply related
* [Intel-wired-lan] [jkirsher-net-queue:dev-queue] BUILD SUCCESS 3b5d0516c41e3411e7028d90bf9ea60d3062a362
From: kbuild test robot @ 2016-11-14 21:06 UTC (permalink / raw)
To: intel-wired-lan
https://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-queue.git dev-queue
3b5d0516c41e3411e7028d90bf9ea60d3062a362 igb: re-assign hw address pointer on reset after PCI error
elapsed time: 76m
configs tested: 178
The following configs have been built successfully.
More configs may be tested in the coming days.
i386 randconfig-a0-201646
x86_64 randconfig-a0-11150150
x86_64 acpi-redef
x86_64 allyesdebian
x86_64 nfsroot
blackfin BF526-EZBRD_defconfig
blackfin BF533-EZKIT_defconfig
blackfin BF561-EZKIT-SMP_defconfig
blackfin TCM-BF537_defconfig
cris etrax-100lx_v2_defconfig
i386 tinyconfig
sh allnoconfig
sh rsk7269_defconfig
sh sh7785lcr_32bit_defconfig
sh titan_defconfig
i386 randconfig-c0-11150231
x86_64 kexec
x86_64 rhel
x86_64 rhel-7.2
x86_64 randconfig-g0-11150243
avr32 atngw100_defconfig
avr32 atstk1006_defconfig
frv defconfig
mn10300 asb2364_defconfig
openrisc or1ksim_defconfig
tile tilegx_defconfig
um i386_defconfig
um x86_64_defconfig
alpha defconfig
parisc allnoconfig
parisc b180_defconfig
parisc c3000_defconfig
parisc defconfig
i386 allmodconfig
powerpc mpc83xx_defconfig
sh ecovec24-romimage_defconfig
um allmodconfig
arm ebsa110_defconfig
mips ar7_defconfig
sh urquell_defconfig
tile allnoconfig
x86_64 randconfig-x011-201646
x86_64 randconfig-x014-201646
x86_64 randconfig-x017-201646
x86_64 randconfig-x015-201646
x86_64 randconfig-x012-201646
x86_64 randconfig-x018-201646
x86_64 randconfig-x019-201646
x86_64 randconfig-x013-201646
x86_64 randconfig-x010-201646
x86_64 randconfig-x016-201646
i386 alldefconfig
i386 allnoconfig
i386 defconfig
arm allmodconfig
arm arm5
arm arm67
arm imx_v6_v7_defconfig
arm ixp4xx_defconfig
arm mvebu_v7_defconfig
arm omap2plus_defconfig
arm sa1100
arm samsung
arm sh
arm tegra_defconfig
arm64 alldefconfig
arm64 allmodconfig
m68k m5475evb_defconfig
m68k multi_defconfig
m68k sun3_defconfig
i386 randconfig-s0-201646
i386 randconfig-s1-201646
x86_64 randconfig-s0-11150359
x86_64 randconfig-s1-11150359
x86_64 randconfig-s2-11150359
x86_64 randconfig-s3-11150352
x86_64 randconfig-s4-11150352
x86_64 randconfig-s5-11150352
powerpc allnoconfig
powerpc defconfig
powerpc ppc64_defconfig
s390 default_defconfig
x86_64 randconfig-i0-201646
microblaze mmu_defconfig
microblaze nommu_defconfig
i386 randconfig-i0-11140126
i386 randconfig-i1-11140126
x86_64 randconfig-b0-11150030
sparc defconfig
sparc64 allnoconfig
sparc64 defconfig
x86_64 allmodconfig
x86_64 randconfig-u0-11150246
x86_64 randconfig-u0-11150439
c6x evmc6678_defconfig
h8300 h8300h-sim_defconfig
m32r m32104ut_defconfig
m32r mappi3.smp_defconfig
m32r opsput_defconfig
m32r usrv_defconfig
nios2 10m50_defconfig
score spct6600_defconfig
xtensa common_defconfig
xtensa iss_defconfig
arm pleb_defconfig
arm cm_x2xx_defconfig
arm pxa_defconfig
x86_64 randconfig-ne0-11150251
c6x dsk6455_defconfig
mips sb1250_swarm_defconfig
powerpc wii_defconfig
i386 randconfig-x014-201646
i386 randconfig-x019-201646
i386 randconfig-x018-201646
i386 randconfig-x017-201646
i386 randconfig-x015-201646
i386 randconfig-x016-201646
i386 randconfig-x012-201646
i386 randconfig-x011-201646
i386 randconfig-x013-201646
i386 randconfig-x010-201646
x86_64 lkp
i386 randconfig-n0-201646
ia64 alldefconfig
ia64 allnoconfig
ia64 defconfig
i386 randconfig-x070-201646
i386 randconfig-x071-201646
i386 randconfig-x072-201646
i386 randconfig-x073-201646
i386 randconfig-x074-201646
i386 randconfig-x075-201646
i386 randconfig-x076-201646
i386 randconfig-x077-201646
i386 randconfig-x078-201646
i386 randconfig-x079-201646
i386 randconfig-sb0-11150109
arm allnoconfig
arm at91_dt_defconfig
arm efm32_defconfig
arm exynos_defconfig
arm multi_v5_defconfig
arm multi_v7_defconfig
arm shmobile_defconfig
arm sunxi_defconfig
arm64 allnoconfig
arm64 defconfig
x86_64 randconfig-ws0-11150035
x86_64 randconfig-x008-201646
x86_64 randconfig-x001-201646
x86_64 randconfig-x009-201646
x86_64 randconfig-x000-201646
x86_64 randconfig-x003-201646
x86_64 randconfig-x005-201646
x86_64 randconfig-x002-201646
x86_64 randconfig-x007-201646
x86_64 randconfig-x004-201646
x86_64 randconfig-x006-201646
i386 randconfig-r0-201646
x86_64 randconfig-r0-11150207
i386 randconfig-x006-201646
i386 randconfig-x004-201646
i386 randconfig-x007-201646
i386 randconfig-x003-201646
i386 randconfig-x008-201646
i386 randconfig-x000-201646
i386 randconfig-x009-201646
i386 randconfig-x002-201646
i386 randconfig-x001-201646
i386 randconfig-x005-201646
mips 32r2_defconfig
mips 64r6el_defconfig
mips allnoconfig
mips fuloong2e_defconfig
mips jz4740
mips malta_kvm_defconfig
mips txx9
Thanks,
Fengguang
^ permalink raw reply
* [Intel-wired-lan] [next PATCH S53 3/5] i40e: Add FEC for 25g
From: Pujari, Bimmy @ 2016-11-14 21:06 UTC (permalink / raw)
To: intel-wired-lan
In-Reply-To: <178d1f9e-7645-525f-21d4-2721abc7f8a9@onemain.com>
Fixed it.
-----Original Message-----
From: Shannon Nelson [mailto:sln at onemain.com]
Sent: Saturday, November 12, 2016 12:13 PM
To: Pujari, Bimmy <bimmy.pujari@intel.com>; intel-wired-lan at lists.osuosl.org
Cc: Naczyk, Jacek <jacek.naczyk@intel.com>
Subject: Re: [Intel-wired-lan] [next PATCH S53 3/5] i40e: Add FEC for 25g
On 11/11/2016 12:16 PM, Bimmy Pujari wrote:
> From: Carolyn Wyborny <carolyn.wyborny@intel.com>
>
> This patch adds adminq support for Forward Error Correction ("FEC")for
> 25g products.
[...]
> diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> index f8d7d95..267c698 100644
> --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h
> @@ -28,7 +28,7 @@
> #define _I40E_ADMINQ_CMD_H_
>
> /* This header file defines the i40e Admin Queue commands and is
> shared between
> - * i40e Firmware and Software.
> + * i40e Fitruct i40e_aq_set_phy_configmware and Software.
Huh?
sln
^ permalink raw reply
* Re: [PATCH kvm-unit-tests v2 17/17] x86/unittests: add intel-iommu test
From: Peter Xu @ 2016-11-14 21:07 UTC (permalink / raw)
To: Andrew Jones; +Cc: kvm, rkrcmar, agordeev, jan.kiszka, pbonzini
In-Reply-To: <20161110202141.t76gr5ibj4omrizg@hawk.localdomain>
On Thu, Nov 10, 2016 at 09:21:41PM +0100, Andrew Jones wrote:
> On Wed, Nov 09, 2016 at 10:10:24AM -0500, Peter Xu wrote:
> > Signed-off-by: Peter Xu <peterx@redhat.com>
> > ---
> > x86/unittests.cfg | 7 +++++++
> > 1 file changed, 7 insertions(+)
> >
> > diff --git a/x86/unittests.cfg b/x86/unittests.cfg
> > index 23395c6..5413838 100644
> > --- a/x86/unittests.cfg
> > +++ b/x86/unittests.cfg
> > @@ -217,3 +217,10 @@ extra_params = -cpu kvm64,hv_time,hv_synic,hv_stimer -device hyperv-testdev
> > file = hyperv_clock.flat
> > smp = 2
> > extra_params = -cpu kvm64,hv_time
> > +
> > +[intel_iommu]
> > +file = intel-iommu.flat
> > +arch = x86_64
> > +timeout = 30
> > +smp = 4
> > +extra_params = -M q35,kernel-irqchip=split -device intel-iommu,intremap=on,eim=off -device edu
> > --
> > 2.7.4
> >
>
> I haven't looked up eim=off means, whether or not we want it, but
> otherwise it looks good to me.
When set eim=off, x2apic will be disabled. So basically "eim" bit is
to configure whether we want to support x2apic in the guest, in case
we want to use more than 255 vcpus.
Here:
- if with eim=off, vt-d test will need latest QEMU to run (so if with
older QEMUs, it'll fail)
- if without eim=off, vt-d test will need latest KVM to run (so if
with older KVM, it'll fail)
I just chose the 1st one since I guess a latest QEMU is easier to get
and compile than kernel.
Thanks,
-- peterx
^ permalink raw reply
* Re: [PATCH 2/2] tls: Don't fail if root CA present in received chain
From: Denis Kenzior @ 2016-11-14 21:08 UTC (permalink / raw)
To: ell
In-Reply-To: <1479154592-8116-2-git-send-email-andrew.zaborowski@intel.com>
[-- Attachment #1: Type: text/plain, Size: 812 bytes --]
Hi Andrew,
On 11/14/2016 02:16 PM, Andrew Zaborowski wrote:
> The certificate chain from the Server Certificate message may be a
> complete chain from server's certificate to root CA. l_keyring_link
> would fail if we tried to add the self-signed root CA to the ring,
> this seems to be unrelated to that certificate being the same as the
> one in the trusted ring.
>
> In the early userspace tls_cert_verify_certchain implementation the
> verification would succeed if any of the certificates in the chain
> was trusted by the supplied CA + the trust chain was correct, but the
> RFC implies this must be the root CA (see the comment in the code).
> ---
> ell/tls.c | 21 +++++++++++++++++----
> 1 file changed, 17 insertions(+), 4 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply
* [kvm-unit-tests PATCH v6 01/11] lib: xstr: allow multiple args
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm; +Cc: marc.zyngier, andre.przywara, pbonzini
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Make implementation equivalent to Linux's include/linux/stringify.h
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/libcflat.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 72b1bf9668ef..82005f5d014f 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -27,8 +27,8 @@
#define __unused __attribute__((__unused__))
-#define xstr(s) xxstr(s)
-#define xxstr(s) #s
+#define xstr(s...) xxstr(s)
+#define xxstr(s...) #s
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 03/11] arm/arm64: smp: support more than 8 cpus
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm; +Cc: marc.zyngier, andre.przywara, pbonzini
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
By adding support for launching with gicv3 we can break the 8 vcpu
limit. This patch adds support to smp code and also selects the
vgic model corresponding to the host. The vgic model may also be
manually selected by adding e.g. -machine gic-version=3 to
extra_params.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v5: left cpus a u32 for now. Changing to u64 requires a change to
devicetree. Will do it later. [Andre]
v4: improved commit message
---
arm/run | 19 ++++++++++++-------
arm/selftest.c | 5 ++++-
lib/arm/asm/processor.h | 9 +++++++--
lib/arm/asm/setup.h | 4 ++--
lib/arm/setup.c | 10 ++++++++++
lib/arm64/asm/processor.h | 9 +++++++--
6 files changed, 42 insertions(+), 14 deletions(-)
diff --git a/arm/run b/arm/run
index 1ee6231599d6..a35952b28b46 100755
--- a/arm/run
+++ b/arm/run
@@ -31,13 +31,6 @@ if [ -z "$ACCEL" ]; then
fi
fi
-if [ "$HOST" = "aarch64" ] && [ "$ACCEL" = "kvm" ]; then
- processor="host"
- if [ "$ARCH" = "arm" ]; then
- processor+=",aarch64=off"
- fi
-fi
-
qemu="${QEMU:-qemu-system-$ARCH_NAME}"
qpath=$(which $qemu 2>/dev/null)
@@ -53,6 +46,18 @@ fi
M='-machine virt'
+if [ "$ACCEL" = "kvm" ]; then
+ if $qemu $M,\? 2>&1 | grep gic-version > /dev/null; then
+ M+=',gic-version=host'
+ fi
+ if [ "$HOST" = "aarch64" ]; then
+ processor="host"
+ if [ "$ARCH" = "arm" ]; then
+ processor+=",aarch64=off"
+ fi
+ fi
+fi
+
if ! $qemu $M -device '?' 2>&1 | grep virtconsole > /dev/null; then
echo "$qpath doesn't support virtio-console for chr-testdev. Exiting."
exit 2
diff --git a/arm/selftest.c b/arm/selftest.c
index 196164f5313d..2f117f795d2d 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -312,9 +312,10 @@ static bool psci_check(void)
static cpumask_t smp_reported;
static void cpu_report(void)
{
+ unsigned long mpidr = get_mpidr();
int cpu = smp_processor_id();
- report("CPU%d online", true, cpu);
+ report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == cpu, cpu, mpidr);
cpumask_set_cpu(cpu, &smp_reported);
halt();
}
@@ -343,6 +344,7 @@ int main(int argc, char **argv)
} else if (strcmp(argv[1], "smp") == 0) {
+ unsigned long mpidr = get_mpidr();
int cpu;
report("PSCI version", psci_check());
@@ -353,6 +355,7 @@ int main(int argc, char **argv)
smp_boot_secondary(cpu, cpu_report);
}
+ report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == 0, 0, mpidr);
cpumask_set_cpu(0, &smp_reported);
while (!cpumask_full(&smp_reported))
cpu_relax();
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index 02f912f99974..ecf5bbe1824a 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -40,8 +40,13 @@ static inline unsigned long get_mpidr(void)
return mpidr;
}
-/* Only support Aff0 for now, up to 4 cpus */
-#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
+#define MPIDR_HWID_BITMASK 0xffffff
+extern int mpidr_to_cpu(unsigned long mpidr);
+
+#define MPIDR_LEVEL_SHIFT(level) \
+ (((1 << level) >> 1) << 3)
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+ ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
index cb8fdbd38dd5..1de99dd184d1 100644
--- a/lib/arm/asm/setup.h
+++ b/lib/arm/asm/setup.h
@@ -10,8 +10,8 @@
#include <asm/page.h>
#include <asm/pgtable-hwdef.h>
-#define NR_CPUS 8
-extern u32 cpus[NR_CPUS];
+#define NR_CPUS 255
+extern u32 cpus[NR_CPUS]; /* per-cpu IDs (MPIDRs) */
extern int nr_cpus;
#define NR_MEM_REGIONS 8
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 7e7b39f11dde..241bf9410447 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -30,6 +30,16 @@ int nr_cpus;
struct mem_region mem_regions[NR_MEM_REGIONS];
phys_addr_t __phys_offset, __phys_end;
+int mpidr_to_cpu(unsigned long mpidr)
+{
+ int i;
+
+ for (i = 0; i < nr_cpus; ++i)
+ if (cpus[i] == (mpidr & MPIDR_HWID_BITMASK))
+ return i;
+ return -1;
+}
+
static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused)
{
int cpu = nr_cpus++;
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 9a208ff729b7..7e448dc81a6a 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -78,8 +78,13 @@ static inline type get_##reg(void) \
DEFINE_GET_SYSREG64(mpidr)
-/* Only support Aff0 for now, gicv2 only */
-#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
+#define MPIDR_HWID_BITMASK 0xff00ffffff
+extern int mpidr_to_cpu(unsigned long mpidr);
+
+#define MPIDR_LEVEL_SHIFT(level) \
+ (((1 << level) >> 1) << 3)
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+ ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
--
2.7.4
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 04/11] arm/arm64: add some delay routines
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm; +Cc: marc.zyngier, andre.przywara, pbonzini
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Allow a thread to wait some specified amount of time. Can
specify in cycles, usecs, and msecs.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/arm/asm/processor.h | 19 +++++++++++++++++++
lib/arm/processor.c | 15 +++++++++++++++
lib/arm64/asm/processor.h | 19 +++++++++++++++++++
lib/arm64/processor.c | 15 +++++++++++++++
4 files changed, 68 insertions(+)
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index ecf5bbe1824a..bc46d1f980ee 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -5,7 +5,9 @@
*
* This work is licensed under the terms of the GNU LGPL, version 2.
*/
+#include <libcflat.h>
#include <asm/ptrace.h>
+#include <asm/barrier.h>
enum vector {
EXCPTN_RST,
@@ -51,4 +53,21 @@ extern int mpidr_to_cpu(unsigned long mpidr);
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
+static inline u64 get_cntvct(void)
+{
+ u64 vct;
+ isb();
+ asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (vct));
+ return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+ while (msecs--)
+ udelay(1000);
+}
+
#endif /* _ASMARM_PROCESSOR_H_ */
diff --git a/lib/arm/processor.c b/lib/arm/processor.c
index 54fdb87ef019..c2ee360df688 100644
--- a/lib/arm/processor.c
+++ b/lib/arm/processor.c
@@ -9,6 +9,7 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
+#include <asm/barrier.h>
static const char *processor_modes[] = {
"USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" ,
@@ -141,3 +142,17 @@ bool is_user(void)
{
return current_thread_info()->flags & TIF_USER_MODE;
}
+
+void delay(u64 cycles)
+{
+ u64 start = get_cntvct();
+ while ((get_cntvct() - start) < cycles)
+ cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+ unsigned int frq;
+ asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq));
+ delay((u64)usec * frq / 1000000);
+}
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 7e448dc81a6a..94f7ce35b65c 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -17,8 +17,10 @@
#define SCTLR_EL1_M (1 << 0)
#ifndef __ASSEMBLY__
+#include <libcflat.h>
#include <asm/ptrace.h>
#include <asm/esr.h>
+#include <asm/barrier.h>
enum vector {
EL1T_SYNC,
@@ -89,5 +91,22 @@ extern int mpidr_to_cpu(unsigned long mpidr);
extern void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr);
extern bool is_user(void);
+static inline u64 get_cntvct(void)
+{
+ u64 vct;
+ isb();
+ asm volatile("mrs %0, cntvct_el0" : "=r" (vct));
+ return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+ while (msecs--)
+ udelay(1000);
+}
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMARM64_PROCESSOR_H_ */
diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
index deeab4ec9c8a..50fa835c6f1e 100644
--- a/lib/arm64/processor.c
+++ b/lib/arm64/processor.c
@@ -9,6 +9,7 @@
#include <asm/ptrace.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
+#include <asm/barrier.h>
static const char *vector_names[] = {
"el1t_sync",
@@ -253,3 +254,17 @@ bool is_user(void)
{
return current_thread_info()->flags & TIF_USER_MODE;
}
+
+void delay(u64 cycles)
+{
+ u64 start = get_cntvct();
+ while ((get_cntvct() - start) < cycles)
+ cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+ unsigned int frq;
+ asm volatile("mrs %0, cntfrq_el0" : "=r" (frq));
+ delay((u64)usec * frq / 1000000);
+}
--
2.7.4
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 00/11] arm/arm64: add gic framework
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm
Cc: pbonzini, andre.przywara, peter.maydell, alex.bennee,
marc.zyngier, eric.auger, christoffer.dall
v6:
- rebased to latest master
- several other changes thanks to Andre and Alex, changes in
individual patch change logs
- some code cleanups
v5:
- fix arm32/gicv3 compile [drew]
- use modern register names [Andre]
- one Andre r-b
v4:
- Eric's r-b's
- Andre's suggestion to only take defines we need
- several other changes listed in individual patches
v3:
- Rebased on latest master
- Added Alex's r-b's
v2:
Rebased on latest master + my "populate argv[0]" series (will
send a REPOST for that shortly. Additionally a few patches got
fixes/features;
07/10 got same fix as kernel 7c9b973061 "irqchip/gic-v3: Configure
all interrupts as non-secure Group-1" in order to continue
working over TCG, as the gicv3 code for TCG removed a hack
it had there to make Linux happy.
08/10 added more output for when things fail (if they fail)
09/10 switched gicv3 broadcast implementation to using IRM. This
found a bug in a recent (but not tip) kernel, which I was
about to fix, but then I saw MarcZ beat me to it.
10/10 actually check that the input irq is the received irq
Import defines, and steal enough helper functions, from Linux to
enable programming of the gic (v2 and v3). Then use the framework
to add an initial test (an ipi test; self, target-list, broadcast).
It's my hope that this framework will be a suitable base on which
more tests may be easily added, particularly because we have
vgic-new and tcg gicv3 emulation getting close to merge. (v3 UPDATE:
vgic-new and tcg gicv3 are merged now)
To run it, along with other tests, just do
./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
make
export QEMU=$PATH_TO_QEMU
./run_tests.sh
To run it separately do, e.g.
$QEMU -machine virt,accel=tcg -cpu cortex-a57 \
-device virtio-serial-device \
-device virtconsole,chardev=ctd -chardev testdev,id=ctd \
-display none -serial stdio \
-kernel arm/gic.flat \
-smp 123 -machine gic-version=3 -append ipi
^^ note, we can go nuts with nr-cpus on TCG :-)
Or, a KVM example using a different "sender" cpu and irq (other than zero)
$QEMU -machine virt,accel=kvm -cpu host \
-device virtio-serial-device \
-device virtconsole,chardev=ctd -chardev testdev,id=ctd \
-display none -serial stdio \
-kernel arm/gic.flat \
-smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'
Patches:
01-05: fixes and functionality needed by the later gic patches
06-07: enable gicv2 and gicv2 IPI test
08-10: enable gicv3 and gicv3 IPI test
11: extend the IPI tests to take variable sender and irq
Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v6
Andrew Jones (10):
lib: xstr: allow multiple args
arm64: fix get_"sysreg32" and make MPIDR 64bit
arm/arm64: smp: support more than 8 cpus
arm/arm64: add some delay routines
arm/arm64: irq enable/disable
arm/arm64: add initial gicv2 support
arm/arm64: gicv2: add an IPI test
arm/arm64: add initial gicv3 support
arm/arm64: gicv3: add an IPI test
arm/arm64: gic: don't just use zero
Peter Xu (1):
libcflat: add IS_ALIGNED() macro, and page sizes
arm/Makefile.common | 9 +-
arm/gic.c | 340 +++++++++++++++++++++++++++++++++++++++++++++
arm/run | 19 ++-
arm/selftest.c | 5 +-
arm/unittests.cfg | 14 ++
lib/arm/asm/arch_gicv3.h | 70 ++++++++++
lib/arm/asm/gic-v2.h | 36 +++++
lib/arm/asm/gic-v3.h | 112 +++++++++++++++
lib/arm/asm/gic.h | 106 ++++++++++++++
lib/arm/asm/processor.h | 42 +++++-
lib/arm/asm/setup.h | 4 +-
lib/arm/gic.c | 267 +++++++++++++++++++++++++++++++++++
lib/arm/processor.c | 15 ++
lib/arm/setup.c | 10 ++
lib/arm64/asm/arch_gicv3.h | 66 +++++++++
lib/arm64/asm/gic-v2.h | 1 +
lib/arm64/asm/gic-v3.h | 1 +
lib/arm64/asm/gic.h | 1 +
lib/arm64/asm/processor.h | 53 +++++--
lib/arm64/asm/sysreg.h | 44 ++++++
lib/arm64/processor.c | 15 ++
lib/libcflat.h | 10 +-
22 files changed, 1212 insertions(+), 28 deletions(-)
create mode 100644 arm/gic.c
create mode 100644 lib/arm/asm/arch_gicv3.h
create mode 100644 lib/arm/asm/gic-v2.h
create mode 100644 lib/arm/asm/gic-v3.h
create mode 100644 lib/arm/asm/gic.h
create mode 100644 lib/arm/gic.c
create mode 100644 lib/arm64/asm/arch_gicv3.h
create mode 100644 lib/arm64/asm/gic-v2.h
create mode 100644 lib/arm64/asm/gic-v3.h
create mode 100644 lib/arm64/asm/gic.h
create mode 100644 lib/arm64/asm/sysreg.h
--
2.7.4
^ permalink raw reply
* [kvm-unit-tests PATCH v6 02/11] arm64: fix get_"sysreg32" and make MPIDR 64bit
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm
Cc: pbonzini, andre.przywara, peter.maydell, alex.bennee,
marc.zyngier, eric.auger, christoffer.dall
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
mrs is always 64bit, so we should always use a 64bit register.
Sometimes we'll only want to return the lower 32, but not for
MPIDR, as that does define fields in the upper 32.
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v5: switch arm32's get_mpidr to 'unsigned long' too, to be
consistent with arm64 [Andre]
---
lib/arm/asm/processor.h | 4 ++--
lib/arm64/asm/processor.h | 15 +++++++++------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index f25e7eee3666..02f912f99974 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -33,9 +33,9 @@ static inline unsigned long current_cpsr(void)
#define current_mode() (current_cpsr() & MODE_MASK)
-static inline unsigned int get_mpidr(void)
+static inline unsigned long get_mpidr(void)
{
- unsigned int mpidr;
+ unsigned long mpidr;
asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (mpidr));
return mpidr;
}
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 84d5c7ce752b..9a208ff729b7 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -66,14 +66,17 @@ static inline unsigned long current_level(void)
return el & 0xc;
}
-#define DEFINE_GET_SYSREG32(reg) \
-static inline unsigned int get_##reg(void) \
+#define DEFINE_GET_SYSREG(reg, type) \
+static inline type get_##reg(void) \
{ \
- unsigned int reg; \
- asm volatile("mrs %0, " #reg "_el1" : "=r" (reg)); \
- return reg; \
+ unsigned long r; \
+ asm volatile("mrs %0, " #reg "_el1" : "=r" (r)); \
+ return (type)r; \
}
-DEFINE_GET_SYSREG32(mpidr)
+#define DEFINE_GET_SYSREG32(reg) DEFINE_GET_SYSREG(reg, unsigned int)
+#define DEFINE_GET_SYSREG64(reg) DEFINE_GET_SYSREG(reg, unsigned long)
+
+DEFINE_GET_SYSREG64(mpidr)
/* Only support Aff0 for now, gicv2 only */
#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 05/11] arm/arm64: irq enable/disable
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm
Cc: pbonzini, andre.przywara, peter.maydell, alex.bennee,
marc.zyngier, eric.auger, christoffer.dall
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/arm/asm/processor.h | 10 ++++++++++
lib/arm64/asm/processor.h | 10 ++++++++++
2 files changed, 20 insertions(+)
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index bc46d1f980ee..959ecda5dced 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -35,6 +35,16 @@ static inline unsigned long current_cpsr(void)
#define current_mode() (current_cpsr() & MODE_MASK)
+static inline void local_irq_enable(void)
+{
+ asm volatile("cpsie i" : : : "memory", "cc");
+}
+
+static inline void local_irq_disable(void)
+{
+ asm volatile("cpsid i" : : : "memory", "cc");
+}
+
static inline unsigned long get_mpidr(void)
{
unsigned long mpidr;
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 94f7ce35b65c..d54a4ed1c187 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -68,6 +68,16 @@ static inline unsigned long current_level(void)
return el & 0xc;
}
+static inline void local_irq_enable(void)
+{
+ asm volatile("msr daifclr, #2" : : : "memory");
+}
+
+static inline void local_irq_disable(void)
+{
+ asm volatile("msr daifset, #2" : : : "memory");
+}
+
#define DEFINE_GET_SYSREG(reg, type) \
static inline type get_##reg(void) \
{ \
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 06/11] arm/arm64: add initial gicv2 support
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm
Cc: pbonzini, andre.przywara, peter.maydell, alex.bennee,
marc.zyngier, eric.auger, christoffer.dall
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Add some gicv2 support. This just adds init and enable
functions, allowing unit tests to start messing with it.
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v6: added comments (register offset headers) [Alex]
v5: share/use only the modern register names [Andre]
v4:
- only take defines from kernel we need now [Andre]
- moved defines to asm/gic.h so they'll be shared with v3 [drew]
- simplify enable by not caring if we reinit the distributor [drew]
- init all GICD_INT_DEF_PRI_X4 registers [Eric]
---
arm/Makefile.common | 1 +
lib/arm/asm/gic-v2.h | 34 ++++++++++++++++++++++
lib/arm/asm/gic.h | 39 ++++++++++++++++++++++++++
lib/arm/gic.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
lib/arm64/asm/gic-v2.h | 1 +
lib/arm64/asm/gic.h | 1 +
6 files changed, 152 insertions(+)
create mode 100644 lib/arm/asm/gic-v2.h
create mode 100644 lib/arm/asm/gic.h
create mode 100644 lib/arm/gic.c
create mode 100644 lib/arm64/asm/gic-v2.h
create mode 100644 lib/arm64/asm/gic.h
diff --git a/arm/Makefile.common b/arm/Makefile.common
index f37b5c2a3de4..6f56015c43c4 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -46,6 +46,7 @@ cflatobjs += lib/arm/mmu.o
cflatobjs += lib/arm/bitops.o
cflatobjs += lib/arm/psci.o
cflatobjs += lib/arm/smp.o
+cflatobjs += lib/arm/gic.o
libeabi = lib/arm/libeabi.a
eabiobjs = lib/arm/eabi_compat.o
diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h
new file mode 100644
index 000000000000..c2d5fecd4886
--- /dev/null
+++ b/lib/arm/asm/gic-v2.h
@@ -0,0 +1,34 @@
+/*
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_V2_H_
+#define _ASMARM_GIC_V2_H_
+
+#ifndef _ASMARM_GIC_H_
+#error Do not directly include <asm/gic-v2.h>. Include <asm/gic.h>
+#endif
+
+#define GICD_ENABLE 0x1
+#define GICC_ENABLE 0x1
+
+#ifndef __ASSEMBLY__
+
+struct gicv2_data {
+ void *dist_base;
+ void *cpu_base;
+ unsigned int irq_nr;
+};
+extern struct gicv2_data gicv2_data;
+
+#define gicv2_dist_base() (gicv2_data.dist_base)
+#define gicv2_cpu_base() (gicv2_data.cpu_base)
+
+extern int gicv2_init(void);
+extern void gicv2_enable_defaults(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_V2_H_ */
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
new file mode 100644
index 000000000000..e3580bd1d42d
--- /dev/null
+++ b/lib/arm/asm/gic.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_H_
+#define _ASMARM_GIC_H_
+
+#include <asm/gic-v2.h>
+
+/* Distributor registers */
+#define GICD_CTLR 0x0000
+#define GICD_TYPER 0x0004
+#define GICD_ISENABLER 0x0100
+#define GICD_IPRIORITYR 0x0400
+
+#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32)
+#define GICD_INT_EN_SET_SGI 0x0000ffff
+#define GICD_INT_DEF_PRI_X4 0xa0a0a0a0
+
+/* CPU interface registers */
+#define GICC_CTLR 0x0000
+#define GICC_PMR 0x0004
+
+#define GICC_INT_PRI_THRESHOLD 0xf0
+
+#ifndef __ASSEMBLY__
+
+/*
+ * gic_init will try to find all known gics, and then
+ * initialize the gic data for the one found.
+ * returns
+ * 0 : no gic was found
+ * > 0 : the gic version of the gic found
+ */
+extern int gic_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_H_ */
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
new file mode 100644
index 000000000000..d655105e058b
--- /dev/null
+++ b/lib/arm/gic.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include <devicetree.h>
+#include <asm/gic.h>
+#include <asm/io.h>
+
+struct gicv2_data gicv2_data;
+
+/*
+ * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+ */
+static bool
+gic_get_dt_bases(const char *compatible, void **base1, void **base2)
+{
+ struct dt_pbus_reg reg;
+ struct dt_device gic;
+ struct dt_bus bus;
+ int node, ret;
+
+ dt_bus_init_defaults(&bus);
+ dt_device_init(&gic, &bus, NULL);
+
+ node = dt_device_find_compatible(&gic, compatible);
+ assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
+
+ if (node == -FDT_ERR_NOTFOUND)
+ return false;
+
+ dt_device_bind_node(&gic, node);
+
+ ret = dt_pbus_translate(&gic, 0, ®);
+ assert(ret == 0);
+ *base1 = ioremap(reg.addr, reg.size);
+
+ ret = dt_pbus_translate(&gic, 1, ®);
+ assert(ret == 0);
+ *base2 = ioremap(reg.addr, reg.size);
+
+ return true;
+}
+
+int gicv2_init(void)
+{
+ return gic_get_dt_bases("arm,cortex-a15-gic",
+ &gicv2_data.dist_base, &gicv2_data.cpu_base);
+}
+
+int gic_init(void)
+{
+ if (gicv2_init())
+ return 2;
+ return 0;
+}
+
+void gicv2_enable_defaults(void)
+{
+ void *dist = gicv2_dist_base();
+ void *cpu_base = gicv2_cpu_base();
+ unsigned int i;
+
+ gicv2_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
+ if (gicv2_data.irq_nr > 1020)
+ gicv2_data.irq_nr = 1020;
+
+ for (i = 0; i < gicv2_data.irq_nr; i += 4)
+ writel(GICD_INT_DEF_PRI_X4, dist + GICD_IPRIORITYR + i);
+
+ writel(GICD_INT_EN_SET_SGI, dist + GICD_ISENABLER + 0);
+ writel(GICD_ENABLE, dist + GICD_CTLR);
+
+ writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR);
+ writel(GICC_ENABLE, cpu_base + GICC_CTLR);
+}
diff --git a/lib/arm64/asm/gic-v2.h b/lib/arm64/asm/gic-v2.h
new file mode 100644
index 000000000000..52226624a209
--- /dev/null
+++ b/lib/arm64/asm/gic-v2.h
@@ -0,0 +1 @@
+#include "../../arm/asm/gic-v2.h"
diff --git a/lib/arm64/asm/gic.h b/lib/arm64/asm/gic.h
new file mode 100644
index 000000000000..e5eb302a31b4
--- /dev/null
+++ b/lib/arm64/asm/gic.h
@@ -0,0 +1 @@
+#include "../../arm/asm/gic.h"
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 07/11] arm/arm64: gicv2: add an IPI test
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm; +Cc: marc.zyngier, andre.przywara, pbonzini
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v6: move the spurious check to its own check_ function [drew]
v5: use modern registers [Andre]
v4: properly mask irqnr in ipi_handler
v2: add more details in the output if a test fails,
report spurious interrupts if we get them
---
arm/Makefile.common | 8 +--
arm/gic.c | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++
arm/unittests.cfg | 8 +++
lib/arm/asm/gic-v2.h | 2 +
lib/arm/asm/gic.h | 4 ++
5 files changed, 217 insertions(+), 4 deletions(-)
create mode 100644 arm/gic.c
diff --git a/arm/Makefile.common b/arm/Makefile.common
index 6f56015c43c4..2fe7aeeca6d4 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -9,10 +9,10 @@ ifeq ($(LOADADDR),)
LOADADDR = 0x40000000
endif
-tests-common = \
- $(TEST_DIR)/selftest.flat \
- $(TEST_DIR)/spinlock-test.flat \
- $(TEST_DIR)/pci-test.flat
+tests-common = $(TEST_DIR)/selftest.flat
+tests-common += $(TEST_DIR)/spinlock-test.flat
+tests-common += $(TEST_DIR)/pci-test.flat
+tests-common += $(TEST_DIR)/gic.flat
all: test_cases
diff --git a/arm/gic.c b/arm/gic.c
new file mode 100644
index 000000000000..b42c2b1ca1e1
--- /dev/null
+++ b/arm/gic.c
@@ -0,0 +1,199 @@
+/*
+ * GIC tests
+ *
+ * GICv2
+ * + test sending/receiving IPIs
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include <libcflat.h>
+#include <asm/setup.h>
+#include <asm/processor.h>
+#include <asm/gic.h>
+#include <asm/smp.h>
+#include <asm/barrier.h>
+#include <asm/io.h>
+
+static int gic_version;
+static int acked[NR_CPUS], spurious[NR_CPUS];
+static cpumask_t ready;
+
+static void nr_cpu_check(int nr)
+{
+ if (nr_cpus < nr)
+ report_abort("At least %d cpus required", nr);
+}
+
+static void wait_on_ready(void)
+{
+ cpumask_set_cpu(smp_processor_id(), &ready);
+ while (!cpumask_full(&ready))
+ cpu_relax();
+}
+
+static void check_acked(cpumask_t *mask)
+{
+ int missing = 0, extra = 0, unexpected = 0;
+ int nr_pass, cpu, i;
+
+ /* Wait up to 5s for all interrupts to be delivered */
+ for (i = 0; i < 50; ++i) {
+ mdelay(100);
+ nr_pass = 0;
+ for_each_present_cpu(cpu) {
+ smp_rmb();
+ nr_pass += cpumask_test_cpu(cpu, mask) ?
+ acked[cpu] == 1 : acked[cpu] == 0;
+ }
+ if (nr_pass == nr_cpus) {
+ report("Completed in %d ms", true, ++i * 100);
+ return;
+ }
+ }
+
+ for_each_present_cpu(cpu) {
+ if (cpumask_test_cpu(cpu, mask)) {
+ if (!acked[cpu])
+ ++missing;
+ else if (acked[cpu] > 1)
+ ++extra;
+ } else {
+ if (acked[cpu])
+ ++unexpected;
+ }
+ }
+
+ report("Timed-out (5s). ACKS: missing=%d extra=%d unexpected=%d",
+ false, missing, extra, unexpected);
+}
+
+static void check_spurious(void)
+{
+ int cpu;
+
+ smp_rmb();
+ for_each_present_cpu(cpu) {
+ if (spurious[cpu])
+ printf("ipi: WARN: cpu%d got %d spurious interrupts\n",
+ spurious[cpu], smp_processor_id());
+ }
+}
+
+static void ipi_handler(struct pt_regs *regs __unused)
+{
+ u32 irqstat = readl(gicv2_cpu_base() + GICC_IAR);
+ u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+
+ if (irqnr != GICC_INT_SPURIOUS) {
+ writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
+ smp_rmb(); /* pairs with wmb in ipi_test functions */
+ ++acked[smp_processor_id()];
+ smp_wmb(); /* pairs with rmb in check_acked */
+ } else {
+ ++spurious[smp_processor_id()];
+ smp_wmb();
+ }
+}
+
+static void ipi_test_self(void)
+{
+ cpumask_t mask;
+
+ report_prefix_push("self");
+ memset(acked, 0, sizeof(acked));
+ smp_wmb();
+ cpumask_clear(&mask);
+ cpumask_set_cpu(0, &mask);
+ writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
+ check_acked(&mask);
+ report_prefix_pop();
+}
+
+static void ipi_test_smp(void)
+{
+ cpumask_t mask;
+ unsigned long tlist;
+
+ report_prefix_push("target-list");
+ memset(acked, 0, sizeof(acked));
+ smp_wmb();
+ tlist = cpumask_bits(&cpu_present_mask)[0] & 0xaa;
+ cpumask_bits(&mask)[0] = tlist;
+ writel((u8)tlist << 16, gicv2_dist_base() + GICD_SGIR);
+ check_acked(&mask);
+ report_prefix_pop();
+
+ report_prefix_push("broadcast");
+ memset(acked, 0, sizeof(acked));
+ smp_wmb();
+ cpumask_copy(&mask, &cpu_present_mask);
+ cpumask_clear_cpu(0, &mask);
+ writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
+ check_acked(&mask);
+ report_prefix_pop();
+}
+
+static void ipi_enable(void)
+{
+ gicv2_enable_defaults();
+#ifdef __arm__
+ install_exception_handler(EXCPTN_IRQ, ipi_handler);
+#else
+ install_irq_handler(EL1H_IRQ, ipi_handler);
+#endif
+ local_irq_enable();
+}
+
+static void ipi_recv(void)
+{
+ ipi_enable();
+ cpumask_set_cpu(smp_processor_id(), &ready);
+ while (1)
+ wfi();
+}
+
+int main(int argc, char **argv)
+{
+ char pfx[8];
+ int cpu;
+
+ gic_version = gic_init();
+ if (!gic_version)
+ report_abort("No gic present!");
+
+ snprintf(pfx, sizeof(pfx), "gicv%d", gic_version);
+ report_prefix_push(pfx);
+
+ if (argc < 2) {
+
+ report_prefix_push("ipi");
+ ipi_enable();
+ ipi_test_self();
+ check_spurious();
+ report_prefix_pop();
+
+ } else if (strcmp(argv[1], "ipi") == 0) {
+
+ report_prefix_push(argv[1]);
+ nr_cpu_check(2);
+
+ for_each_present_cpu(cpu) {
+ if (cpu == 0)
+ continue;
+ smp_boot_secondary(cpu, ipi_recv);
+ }
+ ipi_enable();
+ wait_on_ready();
+ ipi_test_self();
+ ipi_test_smp();
+ check_spurious();
+ report_prefix_pop();
+
+ } else {
+ report_abort("Unknown subtest '%s'", argv[1]);
+ }
+
+ return report_summary();
+}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index ae32a42a91c3..e631c35e2bbb 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -55,6 +55,14 @@ smp = $MAX_SMP
extra_params = -append 'smp'
groups = selftest
+# pci-testdev
[pci-test]
file = pci-test.flat
groups = pci
+
+# Test GIC emulation
+[gicv2-ipi]
+file = gic.flat
+smp = $((($MAX_SMP < 8)?$MAX_SMP:8))
+extra_params = -machine gic-version=2 -append 'ipi'
+groups = gic
diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h
index c2d5fecd4886..8b3f7ed6790c 100644
--- a/lib/arm/asm/gic-v2.h
+++ b/lib/arm/asm/gic-v2.h
@@ -13,7 +13,9 @@
#endif
#define GICD_ENABLE 0x1
+
#define GICC_ENABLE 0x1
+#define GICC_IAR_INT_ID_MASK 0x3ff
#ifndef __ASSEMBLY__
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
index e3580bd1d42d..d816b96e46b4 100644
--- a/lib/arm/asm/gic.h
+++ b/lib/arm/asm/gic.h
@@ -13,6 +13,7 @@
#define GICD_TYPER 0x0004
#define GICD_ISENABLER 0x0100
#define GICD_IPRIORITYR 0x0400
+#define GICD_SGIR 0x0f00
#define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32)
#define GICD_INT_EN_SET_SGI 0x0000ffff
@@ -21,8 +22,11 @@
/* CPU interface registers */
#define GICC_CTLR 0x0000
#define GICC_PMR 0x0004
+#define GICC_IAR 0x000c
+#define GICC_EOIR 0x0010
#define GICC_INT_PRI_THRESHOLD 0xf0
+#define GICC_INT_SPURIOUS 0x3ff
#ifndef __ASSEMBLY__
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 08/11] libcflat: add IS_ALIGNED() macro, and page sizes
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm; +Cc: marc.zyngier, andre.przywara, pbonzini
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
From: Peter Xu <peterx@redhat.com>
These macros will be useful to do page alignment checks.
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
[drew: also added SZ_64K and changed to shifts]
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v6: change to shifts [Alex]
---
lib/libcflat.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 82005f5d014f..244e40a724be 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -33,6 +33,12 @@
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
#define ALIGN(x, a) __ALIGN((x), (a))
+#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
+
+#define SZ_4K (1 << 12)
+#define SZ_64K (1 << 16)
+#define SZ_2M (1 << 21)
+#define SZ_1G (1 << 30)
typedef uint8_t u8;
typedef int8_t s8;
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 10/11] arm/arm64: gicv3: add an IPI test
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm
Cc: pbonzini, andre.przywara, peter.maydell, alex.bennee,
marc.zyngier, eric.auger, christoffer.dall
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v6: move most gicv2/gicv3 wrappers to common code [Alex]
v5:
- fix copy+paste error in gicv3_write_eoir [drew]
- use modern register names [Andre]
v4:
- heavily comment gicv3_ipi_send_tlist() [Eric]
- changes needed for gicv2 iar/irqstat fix to other patch
v2:
- use IRM for gicv3 broadcast
---
arm/gic.c | 97 +++++++++++++++++++++++++-----
arm/unittests.cfg | 6 ++
lib/arm/asm/arch_gicv3.h | 23 +++++++
lib/arm/asm/gic-v3.h | 10 +++-
lib/arm/asm/gic.h | 60 +++++++++++++++++++
lib/arm/gic.c | 145 ++++++++++++++++++++++++++++++++++++++++++---
lib/arm64/asm/arch_gicv3.h | 22 +++++++
7 files changed, 338 insertions(+), 25 deletions(-)
diff --git a/arm/gic.c b/arm/gic.c
index b42c2b1ca1e1..d954a3775c26 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -3,6 +3,8 @@
*
* GICv2
* + test sending/receiving IPIs
+ * GICv3
+ * + test sending/receiving IPIs
*
* Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
*
@@ -16,7 +18,15 @@
#include <asm/barrier.h>
#include <asm/io.h>
-static int gic_version;
+struct gic {
+ struct {
+ void (*send_self)(void);
+ void (*send_tlist)(cpumask_t *mask, int irq);
+ void (*send_broadcast)(void);
+ } ipi;
+};
+
+static struct gic *gic;
static int acked[NR_CPUS], spurious[NR_CPUS];
static cpumask_t ready;
@@ -83,11 +93,11 @@ static void check_spurious(void)
static void ipi_handler(struct pt_regs *regs __unused)
{
- u32 irqstat = readl(gicv2_cpu_base() + GICC_IAR);
- u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+ u32 irqstat = gic_read_iar();
+ u32 irqnr = gic_iar_irqnr(irqstat);
if (irqnr != GICC_INT_SPURIOUS) {
- writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
+ gic_write_eoir(irqstat);
smp_rmb(); /* pairs with wmb in ipi_test functions */
++acked[smp_processor_id()];
smp_wmb(); /* pairs with rmb in check_acked */
@@ -97,6 +107,38 @@ static void ipi_handler(struct pt_regs *regs __unused)
}
}
+static void gicv2_ipi_send_self(void)
+{
+ writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
+}
+
+static void gicv2_ipi_send_tlist(cpumask_t *mask, int irq __unused)
+{
+ u8 tlist = (u8)cpumask_bits(mask)[0];
+
+ writel(tlist << 16, gicv2_dist_base() + GICD_SGIR);
+}
+
+static void gicv2_ipi_send_broadcast(void)
+{
+ writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
+}
+
+static void gicv3_ipi_send_self(void)
+{
+ cpumask_t mask;
+
+ cpumask_clear(&mask);
+ cpumask_set_cpu(smp_processor_id(), &mask);
+ gicv3_ipi_send_tlist(&mask, 0);
+}
+
+static void gicv3_ipi_send_broadcast(void)
+{
+ gicv3_write_sgi1r(1ULL << 40);
+ isb();
+}
+
static void ipi_test_self(void)
{
cpumask_t mask;
@@ -106,7 +148,7 @@ static void ipi_test_self(void)
smp_wmb();
cpumask_clear(&mask);
cpumask_set_cpu(0, &mask);
- writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
+ gic->ipi.send_self();
check_acked(&mask);
report_prefix_pop();
}
@@ -114,14 +156,15 @@ static void ipi_test_self(void)
static void ipi_test_smp(void)
{
cpumask_t mask;
- unsigned long tlist;
+ int i;
report_prefix_push("target-list");
memset(acked, 0, sizeof(acked));
smp_wmb();
- tlist = cpumask_bits(&cpu_present_mask)[0] & 0xaa;
- cpumask_bits(&mask)[0] = tlist;
- writel((u8)tlist << 16, gicv2_dist_base() + GICD_SGIR);
+ cpumask_copy(&mask, &cpu_present_mask);
+ for (i = 0; i < nr_cpus; i += 2)
+ cpumask_clear_cpu(i, &mask);
+ gic->ipi.send_tlist(&mask, 0);
check_acked(&mask);
report_prefix_pop();
@@ -130,14 +173,14 @@ static void ipi_test_smp(void)
smp_wmb();
cpumask_copy(&mask, &cpu_present_mask);
cpumask_clear_cpu(0, &mask);
- writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
+ gic->ipi.send_broadcast();
check_acked(&mask);
report_prefix_pop();
}
static void ipi_enable(void)
{
- gicv2_enable_defaults();
+ gic_enable_defaults();
#ifdef __arm__
install_exception_handler(EXCPTN_IRQ, ipi_handler);
#else
@@ -154,18 +197,42 @@ static void ipi_recv(void)
wfi();
}
+static struct gic gicv2 = {
+ .ipi = {
+ .send_self = gicv2_ipi_send_self,
+ .send_tlist = gicv2_ipi_send_tlist,
+ .send_broadcast = gicv2_ipi_send_broadcast,
+ },
+};
+
+static struct gic gicv3 = {
+ .ipi = {
+ .send_self = gicv3_ipi_send_self,
+ .send_tlist = gicv3_ipi_send_tlist,
+ .send_broadcast = gicv3_ipi_send_broadcast,
+ },
+};
+
int main(int argc, char **argv)
{
char pfx[8];
int cpu;
- gic_version = gic_init();
- if (!gic_version)
- report_abort("No gic present!");
+ if (!gic_init())
+ report_abort("No supported gic present!");
- snprintf(pfx, sizeof(pfx), "gicv%d", gic_version);
+ snprintf(pfx, sizeof(pfx), "gicv%d", gic_version());
report_prefix_push(pfx);
+ switch (gic_version()) {
+ case 2:
+ gic = &gicv2;
+ break;
+ case 3:
+ gic = &gicv3;
+ break;
+ }
+
if (argc < 2) {
report_prefix_push("ipi");
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index e631c35e2bbb..c7392c747f98 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -66,3 +66,9 @@ file = gic.flat
smp = $((($MAX_SMP < 8)?$MAX_SMP:8))
extra_params = -machine gic-version=2 -append 'ipi'
groups = gic
+
+[gicv3-ipi]
+file = gic.flat
+smp = $MAX_SMP
+extra_params = -machine gic-version=3 -append 'ipi'
+groups = gic
diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h
index 276577452a14..b47cd2e0090b 100644
--- a/lib/arm/asm/arch_gicv3.h
+++ b/lib/arm/asm/arch_gicv3.h
@@ -16,10 +16,28 @@
#define __stringify xstr
#define __ACCESS_CP15(CRn, Op1, CRm, Op2) p15, Op1, %0, CRn, CRm, Op2
+#define __ACCESS_CP15_64(Op1, CRm) p15, Op1, %Q0, %R0, CRm
+#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1)
+#define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0)
+#define ICC_SGI1R __ACCESS_CP15_64(0, c12)
#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0)
#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7)
+static inline void gicv3_write_eoir(u32 irq)
+{
+ asm volatile("mcr " __stringify(ICC_EOIR1) : : "r" (irq));
+ isb();
+}
+
+static inline u32 gicv3_read_iar(void)
+{
+ u32 irqstat;
+ asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat));
+ dsb(sy);
+ return irqstat;
+}
+
static inline void gicv3_write_pmr(u32 val)
{
asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
@@ -31,6 +49,11 @@ static inline void gicv3_write_grpen1(u32 val)
isb();
}
+static inline void gicv3_write_sgi1r(u64 val)
+{
+ asm volatile("mcrr " __stringify(ICC_SGI1R) : : "r" (val));
+}
+
/*
* We may access GICR_TYPER and GITS_TYPER by reading both the TYPER
* offset and the following offset (+ 4) and then combining them to
diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h
index 73ade4681d21..43f9ffce56de 100644
--- a/lib/arm/asm/gic-v3.h
+++ b/lib/arm/asm/gic-v3.h
@@ -33,12 +33,19 @@
#define GICR_ISENABLER0 GICD_ISENABLER
#define GICR_IPRIORITYR0 GICD_IPRIORITYR
+#define ICC_SGI1R_AFFINITY_1_SHIFT 16
+#define ICC_SGI1R_AFFINITY_2_SHIFT 32
+#define ICC_SGI1R_AFFINITY_3_SHIFT 48
+#define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
+ (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level ## _SHIFT)
+
#include <asm/arch_gicv3.h>
#ifndef __ASSEMBLY__
#include <asm/setup.h>
-#include <asm/smp.h>
#include <asm/processor.h>
+#include <asm/cpumask.h>
+#include <asm/smp.h>
#include <asm/io.h>
struct gicv3_data {
@@ -55,6 +62,7 @@ extern struct gicv3_data gicv3_data;
extern int gicv3_init(void);
extern void gicv3_enable_defaults(void);
extern void gicv3_set_redist_base(size_t stride);
+extern void gicv3_ipi_send_tlist(cpumask_t *mask, int irq);
static inline void gicv3_do_wait_for_rwp(void *base)
{
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
index 21511997f2a9..c2267b6b3937 100644
--- a/lib/arm/asm/gic.h
+++ b/lib/arm/asm/gic.h
@@ -42,5 +42,65 @@
*/
extern int gic_init(void);
+/*
+ * gic_common_ops collects some functions that we provide unit
+ * tests that don't care which gic version they're using.
+ */
+struct gic_common_ops {
+ int gic_version;
+ u32 (*read_iar)(void);
+ u32 (*iar_irqnr)(u32 iar);
+ void (*write_eoir)(u32 irqstat);
+ void (*ipi_send)(int cpu, int irq);
+};
+
+extern struct gic_common_ops *gic_common_ops;
+
+static inline int gic_version(void)
+{
+ assert(gic_common_ops);
+ return gic_common_ops->gic_version;
+}
+
+static inline u32 gic_read_iar(void)
+{
+ assert(gic_common_ops && gic_common_ops->read_iar);
+ return gic_common_ops->read_iar();
+}
+
+static inline u32 gic_iar_irqnr(u32 iar)
+{
+ assert(gic_common_ops && gic_common_ops->iar_irqnr);
+ return gic_common_ops->iar_irqnr(iar);
+}
+
+static inline void gic_write_eoir(u32 irqstat)
+{
+ assert(gic_common_ops && gic_common_ops->write_eoir);
+ gic_common_ops->write_eoir(irqstat);
+}
+
+static inline void gic_ipi_send(int cpu, int irq)
+{
+ assert(gic_common_ops && gic_common_ops->ipi_send);
+ gic_common_ops->ipi_send(cpu, irq);
+}
+
+static inline void gic_enable_defaults(void)
+{
+ switch (gic_version()) {
+ case 2:
+ gicv2_enable_defaults();
+ break;
+ case 3:
+ gicv3_enable_defaults();
+ break;
+ default:
+ printf("%s: Unknown gic version %d\n", __func__,
+ gic_version());
+ abort();
+ }
+}
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMARM_GIC_H_ */
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
index d703ad96a37e..4f67363e073b 100644
--- a/lib/arm/gic.c
+++ b/lib/arm/gic.c
@@ -56,15 +56,6 @@ int gicv3_init(void)
&gicv3_data.redist_base[0]);
}
-int gic_init(void)
-{
- if (gicv2_init())
- return 2;
- else if (gicv3_init())
- return 3;
- return 0;
-}
-
void gicv2_enable_defaults(void)
{
void *dist = gicv2_dist_base();
@@ -85,6 +76,28 @@ void gicv2_enable_defaults(void)
writel(GICC_ENABLE, cpu_base + GICC_CTLR);
}
+static u32 gicv2_read_iar(void)
+{
+ return readl(gicv2_cpu_base() + GICC_IAR);
+}
+
+static u32 gicv2_iar_irqnr(u32 iar)
+{
+ return iar & GICC_IAR_INT_ID_MASK;
+}
+
+static void gicv2_write_eoir(u32 irqstat)
+{
+ writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
+}
+
+static void gicv2_ipi_send(int cpu, int irq)
+{
+ assert(cpu < 8);
+ assert(irq < 16);
+ writel(1 << (cpu + 16) | irq, gicv2_dist_base() + GICD_SGIR);
+}
+
void gicv3_set_redist_base(size_t stride)
{
u32 aff = mpidr_compress(get_mpidr());
@@ -138,3 +151,117 @@ void gicv3_enable_defaults(void)
gicv3_write_pmr(GICC_INT_PRI_THRESHOLD);
gicv3_write_grpen1(1);
}
+
+static u32 gicv3_iar_irqnr(u32 iar)
+{
+ return iar;
+}
+
+void gicv3_ipi_send_tlist(cpumask_t *mask, int irq)
+{
+ u16 tlist;
+ int cpu;
+
+ assert(irq < 16);
+
+ /*
+ * For each cpu in the mask collect its peers, which are also in
+ * the mask, in order to form target lists.
+ */
+ for_each_cpu(cpu, mask) {
+ u64 mpidr = cpus[cpu], sgi1r;
+ u64 cluster_id;
+
+ /*
+ * GICv3 can send IPIs to up 16 peer cpus with a single
+ * write to ICC_SGI1R_EL1 (using the target list). Peers
+ * are cpus that have nearly identical MPIDRs, the only
+ * difference being Aff0. The matching upper affinity
+ * levels form the cluster ID.
+ */
+ cluster_id = mpidr & ~0xffUL;
+ tlist = 0;
+
+ /*
+ * Sort of open code for_each_cpu in order to have a
+ * nested for_each_cpu loop.
+ */
+ while (cpu < nr_cpus) {
+ if ((mpidr & 0xff) >= 16) {
+ printf("cpu%d MPIDR:aff0 is %d (>= 16)!\n",
+ cpu, (int)(mpidr & 0xff));
+ break;
+ }
+
+ tlist |= 1 << (mpidr & 0xf);
+
+ cpu = cpumask_next(cpu, mask);
+ if (cpu >= nr_cpus)
+ break;
+
+ mpidr = cpus[cpu];
+
+ if (cluster_id != (mpidr & ~0xffUL)) {
+ /*
+ * The next cpu isn't in our cluster. Roll
+ * back the cpu index allowing the outer
+ * for_each_cpu to find it again with
+ * cpumask_next
+ */
+ --cpu;
+ break;
+ }
+ }
+
+ /* Send the IPIs for the target list of this cluster */
+ sgi1r = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3) |
+ MPIDR_TO_SGI_AFFINITY(cluster_id, 2) |
+ irq << 24 |
+ MPIDR_TO_SGI_AFFINITY(cluster_id, 1) |
+ tlist);
+
+ gicv3_write_sgi1r(sgi1r);
+ }
+
+ /* Force the above writes to ICC_SGI1R_EL1 to be executed */
+ isb();
+}
+
+static void gicv3_ipi_send(int cpu, int irq)
+{
+ cpumask_t mask;
+
+ cpumask_clear(&mask);
+ cpumask_set_cpu(cpu, &mask);
+ gicv3_ipi_send_tlist(&mask, irq);
+}
+
+static struct gic_common_ops gicv2_common_ops = {
+ .gic_version = 2,
+ .read_iar = gicv2_read_iar,
+ .iar_irqnr = gicv2_iar_irqnr,
+ .write_eoir = gicv2_write_eoir,
+ .ipi_send = gicv2_ipi_send,
+};
+
+static struct gic_common_ops gicv3_common_ops = {
+ .gic_version = 3,
+ .read_iar = gicv3_read_iar,
+ .iar_irqnr = gicv3_iar_irqnr,
+ .write_eoir = gicv3_write_eoir,
+ .ipi_send = gicv3_ipi_send,
+};
+
+struct gic_common_ops *gic_common_ops;
+
+int gic_init(void)
+{
+ if (gicv2_init()) {
+ gic_common_ops = &gicv2_common_ops;
+ return 2;
+ } else if (gicv3_init()) {
+ gic_common_ops = &gicv3_common_ops;
+ return 3;
+ }
+ return 0;
+}
diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h
index 6d353567f56a..874775828016 100644
--- a/lib/arm64/asm/arch_gicv3.h
+++ b/lib/arm64/asm/arch_gicv3.h
@@ -10,6 +10,9 @@
#include <asm/sysreg.h>
+#define ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1)
+#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
+#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
#define ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7)
@@ -27,6 +30,20 @@
* sets the GP register's most significant bits to 0 with an explicit cast.
*/
+static inline void gicv3_write_eoir(u32 irq)
+{
+ asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq));
+ isb();
+}
+
+static inline u32 gicv3_read_iar(void)
+{
+ u64 irqstat;
+ asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
+ dsb(sy);
+ return (u64)irqstat;
+}
+
static inline void gicv3_write_pmr(u32 val)
{
asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));
@@ -38,6 +55,11 @@ static inline void gicv3_write_grpen1(u32 val)
isb();
}
+static inline void gicv3_write_sgi1r(u64 val)
+{
+ asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
+}
+
#define gicv3_read_typer(c) readq(c)
#endif /* __ASSEMBLY__ */
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 09/11] arm/arm64: add initial gicv3 support
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm; +Cc: marc.zyngier, andre.przywara, pbonzini
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v6:
- added comments [Alex]
- added stride parameter to gicv3_set_redist_base [Andre]
- redist-wait s/rwp/uwp/ and comment [Andre]
- removed unnecessary wait-for-rwps [Andre]
v5: use modern register names [Andre]
v4:
- only take defines from kernel we need now [Andre]
- simplify enable by not caring if we reinit the distributor [drew]
v2:
- configure irqs as NS GRP1
---
lib/arm/asm/arch_gicv3.h | 47 ++++++++++++++++++++
lib/arm/asm/gic-v3.h | 104 +++++++++++++++++++++++++++++++++++++++++++++
lib/arm/asm/gic.h | 5 ++-
lib/arm/gic.c | 64 ++++++++++++++++++++++++++++
lib/arm64/asm/arch_gicv3.h | 44 +++++++++++++++++++
lib/arm64/asm/gic-v3.h | 1 +
lib/arm64/asm/sysreg.h | 44 +++++++++++++++++++
7 files changed, 308 insertions(+), 1 deletion(-)
create mode 100644 lib/arm/asm/arch_gicv3.h
create mode 100644 lib/arm/asm/gic-v3.h
create mode 100644 lib/arm64/asm/arch_gicv3.h
create mode 100644 lib/arm64/asm/gic-v3.h
create mode 100644 lib/arm64/asm/sysreg.h
diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h
new file mode 100644
index 000000000000..276577452a14
--- /dev/null
+++ b/lib/arm/asm/arch_gicv3.h
@@ -0,0 +1,47 @@
+/*
+ * All ripped off from arch/arm/include/asm/arch_gicv3.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_ARCH_GICV3_H_
+#define _ASMARM_ARCH_GICV3_H_
+
+#ifndef __ASSEMBLY__
+#include <libcflat.h>
+#include <asm/barrier.h>
+#include <asm/io.h>
+
+#define __stringify xstr
+
+#define __ACCESS_CP15(CRn, Op1, CRm, Op2) p15, Op1, %0, CRn, CRm, Op2
+
+#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0)
+#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7)
+
+static inline void gicv3_write_pmr(u32 val)
+{
+ asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
+}
+
+static inline void gicv3_write_grpen1(u32 val)
+{
+ asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val));
+ isb();
+}
+
+/*
+ * We may access GICR_TYPER and GITS_TYPER by reading both the TYPER
+ * offset and the following offset (+ 4) and then combining them to
+ * form a 64-bit address.
+ */
+static inline u64 gicv3_read_typer(const volatile void __iomem *addr)
+{
+ u64 val = readl(addr);
+ val |= (u64)readl(addr + 4) << 32;
+ return val;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_ARCH_GICV3_H_ */
diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h
new file mode 100644
index 000000000000..73ade4681d21
--- /dev/null
+++ b/lib/arm/asm/gic-v3.h
@@ -0,0 +1,104 @@
+/*
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_V3_H_
+#define _ASMARM_GIC_V3_H_
+
+#ifndef _ASMARM_GIC_H_
+#error Do not directly include <asm/gic-v3.h>. Include <asm/gic.h>
+#endif
+
+/*
+ * Distributor registers
+ *
+ * We expect to be run in Non-secure mode, thus we define the
+ * group1 enable bits with respect to that view.
+ */
+#define GICD_CTLR_RWP (1U << 31)
+#define GICD_CTLR_ARE_NS (1U << 4)
+#define GICD_CTLR_ENABLE_G1A (1U << 1)
+#define GICD_CTLR_ENABLE_G1 (1U << 0)
+
+/* Re-Distributor registers, offsets from RD_base */
+#define GICR_TYPER 0x0008
+
+#define GICR_TYPER_LAST (1U << 4)
+
+/* Re-Distributor registers, offsets from SGI_base */
+#define GICR_IGROUPR0 GICD_IGROUPR
+#define GICR_ISENABLER0 GICD_ISENABLER
+#define GICR_IPRIORITYR0 GICD_IPRIORITYR
+
+#include <asm/arch_gicv3.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/setup.h>
+#include <asm/smp.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+
+struct gicv3_data {
+ void *dist_base;
+ void *redist_base[NR_CPUS];
+ unsigned int irq_nr;
+};
+extern struct gicv3_data gicv3_data;
+
+#define gicv3_dist_base() (gicv3_data.dist_base)
+#define gicv3_redist_base() (gicv3_data.redist_base[smp_processor_id()])
+#define gicv3_sgi_base() (gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
+
+extern int gicv3_init(void);
+extern void gicv3_enable_defaults(void);
+extern void gicv3_set_redist_base(size_t stride);
+
+static inline void gicv3_do_wait_for_rwp(void *base)
+{
+ int count = 100000; /* 1s */
+
+ while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
+ if (!--count) {
+ printf("GICv3: RWP timeout!\n");
+ abort();
+ }
+ cpu_relax();
+ udelay(10);
+ };
+}
+
+static inline void gicv3_dist_wait_for_rwp(void)
+{
+ gicv3_do_wait_for_rwp(gicv3_dist_base());
+}
+
+static inline void gicv3_redist_wait_for_uwp(void)
+{
+ /*
+ * We can build on gic_do_wait_for_rwp, which uses GICD_ registers
+ * because GICD_CTLR == GICR_CTLR and GICD_CTLR_RWP == GICR_CTLR_UWP
+ */
+ gicv3_do_wait_for_rwp(gicv3_redist_base());
+}
+
+static inline u32 mpidr_compress(u64 mpidr)
+{
+ u64 compressed = mpidr & MPIDR_HWID_BITMASK;
+
+ compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
+ return compressed;
+}
+
+static inline u64 mpidr_uncompress(u32 compressed)
+{
+ u64 mpidr = ((u64)compressed >> 24) << 32;
+
+ mpidr |= compressed & MPIDR_HWID_BITMASK;
+ return mpidr;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_V3_H_ */
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
index d816b96e46b4..21511997f2a9 100644
--- a/lib/arm/asm/gic.h
+++ b/lib/arm/asm/gic.h
@@ -6,11 +6,11 @@
#ifndef _ASMARM_GIC_H_
#define _ASMARM_GIC_H_
-#include <asm/gic-v2.h>
/* Distributor registers */
#define GICD_CTLR 0x0000
#define GICD_TYPER 0x0004
+#define GICD_IGROUPR 0x0080
#define GICD_ISENABLER 0x0100
#define GICD_IPRIORITYR 0x0400
#define GICD_SGIR 0x0f00
@@ -28,6 +28,9 @@
#define GICC_INT_PRI_THRESHOLD 0xf0
#define GICC_INT_SPURIOUS 0x3ff
+#include <asm/gic-v2.h>
+#include <asm/gic-v3.h>
+
#ifndef __ASSEMBLY__
/*
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
index d655105e058b..d703ad96a37e 100644
--- a/lib/arm/gic.c
+++ b/lib/arm/gic.c
@@ -8,9 +8,11 @@
#include <asm/io.h>
struct gicv2_data gicv2_data;
+struct gicv3_data gicv3_data;
/*
* Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+ * Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
*/
static bool
gic_get_dt_bases(const char *compatible, void **base1, void **base2)
@@ -48,10 +50,18 @@ int gicv2_init(void)
&gicv2_data.dist_base, &gicv2_data.cpu_base);
}
+int gicv3_init(void)
+{
+ return gic_get_dt_bases("arm,gic-v3", &gicv3_data.dist_base,
+ &gicv3_data.redist_base[0]);
+}
+
int gic_init(void)
{
if (gicv2_init())
return 2;
+ else if (gicv3_init())
+ return 3;
return 0;
}
@@ -74,3 +84,57 @@ void gicv2_enable_defaults(void)
writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR);
writel(GICC_ENABLE, cpu_base + GICC_CTLR);
}
+
+void gicv3_set_redist_base(size_t stride)
+{
+ u32 aff = mpidr_compress(get_mpidr());
+ void *ptr = gicv3_data.redist_base[0];
+ u64 typer;
+
+ do {
+ typer = gicv3_read_typer(ptr + GICR_TYPER);
+ if ((typer >> 32) == aff) {
+ gicv3_redist_base() = ptr;
+ return;
+ }
+ ptr += stride; /* skip RD_base, SGI_base, etc. */
+ } while (!(typer & GICR_TYPER_LAST));
+
+ /* should never reach here */
+ assert(0);
+}
+
+void gicv3_enable_defaults(void)
+{
+ void *dist = gicv3_dist_base();
+ void *sgi_base;
+ unsigned int i;
+
+ gicv3_data.irq_nr = GICD_TYPER_IRQS(readl(dist + GICD_TYPER));
+ if (gicv3_data.irq_nr > 1020)
+ gicv3_data.irq_nr = 1020;
+
+ writel(0, dist + GICD_CTLR);
+ gicv3_dist_wait_for_rwp();
+
+ writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1,
+ dist + GICD_CTLR);
+ gicv3_dist_wait_for_rwp();
+
+ for (i = 0; i < gicv3_data.irq_nr; i += 4)
+ writel(~0, dist + GICD_IGROUPR + i);
+
+ if (!gicv3_redist_base())
+ gicv3_set_redist_base(SZ_64K * 2);
+ sgi_base = gicv3_sgi_base();
+
+ writel(~0, sgi_base + GICR_IGROUPR0);
+
+ for (i = 0; i < 16; i += 4)
+ writel(GICD_INT_DEF_PRI_X4, sgi_base + GICR_IPRIORITYR0 + i);
+
+ writel(GICD_INT_EN_SET_SGI, sgi_base + GICR_ISENABLER0);
+
+ gicv3_write_pmr(GICC_INT_PRI_THRESHOLD);
+ gicv3_write_grpen1(1);
+}
diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h
new file mode 100644
index 000000000000..6d353567f56a
--- /dev/null
+++ b/lib/arm64/asm/arch_gicv3.h
@@ -0,0 +1,44 @@
+/*
+ * All ripped off from arch/arm64/include/asm/arch_gicv3.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM64_ARCH_GICV3_H_
+#define _ASMARM64_ARCH_GICV3_H_
+
+#include <asm/sysreg.h>
+
+#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
+#define ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7)
+
+#ifndef __ASSEMBLY__
+
+#include <libcflat.h>
+#include <asm/barrier.h>
+
+#define __stringify xstr
+
+/*
+ * Low-level accessors
+ *
+ * These system registers are 32 bits, but we make sure that the compiler
+ * sets the GP register's most significant bits to 0 with an explicit cast.
+ */
+
+static inline void gicv3_write_pmr(u32 val)
+{
+ asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));
+}
+
+static inline void gicv3_write_grpen1(u32 val)
+{
+ asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));
+ isb();
+}
+
+#define gicv3_read_typer(c) readq(c)
+
+#endif /* __ASSEMBLY__ */
+#endif /* _ASMARM64_ARCH_GICV3_H_ */
diff --git a/lib/arm64/asm/gic-v3.h b/lib/arm64/asm/gic-v3.h
new file mode 100644
index 000000000000..8ee5d4d9c181
--- /dev/null
+++ b/lib/arm64/asm/gic-v3.h
@@ -0,0 +1 @@
+#include "../../arm/asm/gic-v3.h"
diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h
new file mode 100644
index 000000000000..544a46cb8cc5
--- /dev/null
+++ b/lib/arm64/asm/sysreg.h
@@ -0,0 +1,44 @@
+/*
+ * Ripped off from arch/arm64/include/asm/sysreg.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM64_SYSREG_H_
+#define _ASMARM64_SYSREG_H_
+
+#define sys_reg(op0, op1, crn, crm, op2) \
+ ((((op0)&3)<<19)|((op1)<<16)|((crn)<<12)|((crm)<<8)|((op2)<<5))
+
+#ifdef __ASSEMBLY__
+ .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
+ .equ .L__reg_num_x\num, \num
+ .endr
+ .equ .L__reg_num_xzr, 31
+
+ .macro mrs_s, rt, sreg
+ .inst 0xd5200000|(\sreg)|(.L__reg_num_\rt)
+ .endm
+
+ .macro msr_s, sreg, rt
+ .inst 0xd5000000|(\sreg)|(.L__reg_num_\rt)
+ .endm
+#else
+asm(
+" .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n"
+" .equ .L__reg_num_x\\num, \\num\n"
+" .endr\n"
+" .equ .L__reg_num_xzr, 31\n"
+"\n"
+" .macro mrs_s, rt, sreg\n"
+" .inst 0xd5200000|(\\sreg)|(.L__reg_num_\\rt)\n"
+" .endm\n"
+"\n"
+" .macro msr_s, sreg, rt\n"
+" .inst 0xd5000000|(\\sreg)|(.L__reg_num_\\rt)\n"
+" .endm\n"
+);
+#endif
+
+#endif /* _ASMARM64_SYSREG_H_ */
--
2.7.4
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 11/11] arm/arm64: gic: don't just use zero
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm; +Cc: marc.zyngier, andre.przywara, pbonzini
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Allow user to select who sends ipis and with which irq,
rather than just always sending irq=0 from cpu0.
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
v6:
- make sender/irq names more future-proof [drew]
- sanity check inputs [drew]
- introduce check_sender/irq and bad_sender/irq to more
cleanly do checks [drew]
- default sender and irq to 1, instead of still zero [drew]
v4: improve structure and make sure spurious checking is
done even when the sender isn't cpu0
v2: actually check that the irq received was the irq sent,
and (for gicv2) that the sender is the expected one.
---
arm/gic.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 99 insertions(+), 25 deletions(-)
diff --git a/arm/gic.c b/arm/gic.c
index d954a3775c26..638b8b140c96 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -11,6 +11,7 @@
* This work is licensed under the terms of the GNU LGPL, version 2.
*/
#include <libcflat.h>
+#include <util.h>
#include <asm/setup.h>
#include <asm/processor.h>
#include <asm/gic.h>
@@ -28,6 +29,8 @@ struct gic {
static struct gic *gic;
static int acked[NR_CPUS], spurious[NR_CPUS];
+static int bad_sender[NR_CPUS], bad_irq[NR_CPUS];
+static int cmdl_sender = 1, cmdl_irq = 1;
static cpumask_t ready;
static void nr_cpu_check(int nr)
@@ -43,10 +46,23 @@ static void wait_on_ready(void)
cpu_relax();
}
+static void stats_reset(void)
+{
+ int i;
+
+ for (i = 0; i < nr_cpus; ++i) {
+ acked[i] = 0;
+ bad_sender[i] = -1;
+ bad_irq[i] = -1;
+ }
+ smp_wmb();
+}
+
static void check_acked(cpumask_t *mask)
{
int missing = 0, extra = 0, unexpected = 0;
int nr_pass, cpu, i;
+ bool bad = false;
/* Wait up to 5s for all interrupts to be delivered */
for (i = 0; i < 50; ++i) {
@@ -56,9 +72,21 @@ static void check_acked(cpumask_t *mask)
smp_rmb();
nr_pass += cpumask_test_cpu(cpu, mask) ?
acked[cpu] == 1 : acked[cpu] == 0;
+
+ if (bad_sender[cpu] != -1) {
+ printf("cpu%d received IPI from wrong sender %d\n",
+ cpu, bad_sender[cpu]);
+ bad = true;
+ }
+
+ if (bad_irq[cpu] != -1) {
+ printf("cpu%d received wrong irq %d\n",
+ cpu, bad_irq[cpu]);
+ bad = true;
+ }
}
if (nr_pass == nr_cpus) {
- report("Completed in %d ms", true, ++i * 100);
+ report("Completed in %d ms", !bad, ++i * 100);
return;
}
}
@@ -91,6 +119,22 @@ static void check_spurious(void)
}
}
+static void check_ipi_sender(u32 irqstat)
+{
+ if (gic_version() == 2) {
+ int src = (irqstat >> 10) & 7;
+
+ if (src != cmdl_sender)
+ bad_sender[smp_processor_id()] = src;
+ }
+}
+
+static void check_irqnr(u32 irqnr)
+{
+ if (irqnr != (u32)cmdl_irq)
+ bad_irq[smp_processor_id()] = irqnr;
+}
+
static void ipi_handler(struct pt_regs *regs __unused)
{
u32 irqstat = gic_read_iar();
@@ -98,8 +142,10 @@ static void ipi_handler(struct pt_regs *regs __unused)
if (irqnr != GICC_INT_SPURIOUS) {
gic_write_eoir(irqstat);
- smp_rmb(); /* pairs with wmb in ipi_test functions */
+ smp_rmb(); /* pairs with wmb in stats_reset */
++acked[smp_processor_id()];
+ check_ipi_sender(irqstat);
+ check_irqnr(irqnr);
smp_wmb(); /* pairs with rmb in check_acked */
} else {
++spurious[smp_processor_id()];
@@ -109,19 +155,19 @@ static void ipi_handler(struct pt_regs *regs __unused)
static void gicv2_ipi_send_self(void)
{
- writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
+ writel(2 << 24 | cmdl_irq, gicv2_dist_base() + GICD_SGIR);
}
-static void gicv2_ipi_send_tlist(cpumask_t *mask, int irq __unused)
+static void gicv2_ipi_send_tlist(cpumask_t *mask, int irq)
{
u8 tlist = (u8)cpumask_bits(mask)[0];
- writel(tlist << 16, gicv2_dist_base() + GICD_SGIR);
+ writel(tlist << 16 | irq, gicv2_dist_base() + GICD_SGIR);
}
static void gicv2_ipi_send_broadcast(void)
{
- writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
+ writel(1 << 24 | cmdl_irq, gicv2_dist_base() + GICD_SGIR);
}
static void gicv3_ipi_send_self(void)
@@ -130,12 +176,12 @@ static void gicv3_ipi_send_self(void)
cpumask_clear(&mask);
cpumask_set_cpu(smp_processor_id(), &mask);
- gicv3_ipi_send_tlist(&mask, 0);
+ gicv3_ipi_send_tlist(&mask, cmdl_irq);
}
static void gicv3_ipi_send_broadcast(void)
{
- gicv3_write_sgi1r(1ULL << 40);
+ gicv3_write_sgi1r(1ULL << 40 | cmdl_irq << 24);
isb();
}
@@ -144,10 +190,9 @@ static void ipi_test_self(void)
cpumask_t mask;
report_prefix_push("self");
- memset(acked, 0, sizeof(acked));
- smp_wmb();
+ stats_reset();
cpumask_clear(&mask);
- cpumask_set_cpu(0, &mask);
+ cpumask_set_cpu(smp_processor_id(), &mask);
gic->ipi.send_self();
check_acked(&mask);
report_prefix_pop();
@@ -159,20 +204,18 @@ static void ipi_test_smp(void)
int i;
report_prefix_push("target-list");
- memset(acked, 0, sizeof(acked));
- smp_wmb();
+ stats_reset();
cpumask_copy(&mask, &cpu_present_mask);
- for (i = 0; i < nr_cpus; i += 2)
+ for (i = smp_processor_id() & 1; i < nr_cpus; i += 2)
cpumask_clear_cpu(i, &mask);
- gic->ipi.send_tlist(&mask, 0);
+ gic->ipi.send_tlist(&mask, cmdl_irq);
check_acked(&mask);
report_prefix_pop();
report_prefix_push("broadcast");
- memset(acked, 0, sizeof(acked));
- smp_wmb();
+ stats_reset();
cpumask_copy(&mask, &cpu_present_mask);
- cpumask_clear_cpu(0, &mask);
+ cpumask_clear_cpu(smp_processor_id(), &mask);
gic->ipi.send_broadcast();
check_acked(&mask);
report_prefix_pop();
@@ -189,6 +232,16 @@ static void ipi_enable(void)
local_irq_enable();
}
+static void ipi_send(void)
+{
+ ipi_enable();
+ wait_on_ready();
+ ipi_test_self();
+ ipi_test_smp();
+ check_spurious();
+ exit(report_summary());
+}
+
static void ipi_recv(void)
{
ipi_enable();
@@ -197,6 +250,14 @@ static void ipi_recv(void)
wfi();
}
+static void ipi_test(void)
+{
+ if (smp_processor_id() == cmdl_sender)
+ ipi_send();
+ else
+ ipi_recv();
+}
+
static struct gic gicv2 = {
.ipi = {
.send_self = gicv2_ipi_send_self,
@@ -242,21 +303,34 @@ int main(int argc, char **argv)
report_prefix_pop();
} else if (strcmp(argv[1], "ipi") == 0) {
+ int off, i = 1;
+ long val;
report_prefix_push(argv[1]);
nr_cpu_check(2);
+ while (--argc != 1) {
+ off = parse_keyval(argv[++i], &val);
+ if (off == -1)
+ continue;
+ argv[i][off] = '\0';
+ if (strcmp(argv[i], "sender") == 0) {
+ if (val >= nr_cpus)
+ report_abort("invalid sender %d, nr_cpus=%d", val, nr_cpus);
+ cmdl_sender = val;
+ } else if (strcmp(argv[i], "irq") == 0) {
+ if (val > 15)
+ report_abort("irq (SGI) must be < 16");
+ cmdl_irq = val;
+ }
+ }
+
for_each_present_cpu(cpu) {
if (cpu == 0)
continue;
- smp_boot_secondary(cpu, ipi_recv);
+ smp_boot_secondary(cpu, ipi_test);
}
- ipi_enable();
- wait_on_ready();
- ipi_test_self();
- ipi_test_smp();
- check_spurious();
- report_prefix_pop();
+ ipi_test();
} else {
report_abort("Unknown subtest '%s'", argv[1]);
--
2.7.4
^ permalink raw reply related
* [kvm-unit-tests PATCH v6 01/11] lib: xstr: allow multiple args
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm
Cc: pbonzini, andre.przywara, peter.maydell, alex.bennee,
marc.zyngier, eric.auger, christoffer.dall
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Make implementation equivalent to Linux's include/linux/stringify.h
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/libcflat.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 72b1bf9668ef..82005f5d014f 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -27,8 +27,8 @@
#define __unused __attribute__((__unused__))
-#define xstr(s) xxstr(s)
-#define xxstr(s) #s
+#define xstr(s...) xxstr(s)
+#define xxstr(s...) #s
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
--
2.7.4
^ permalink raw reply related
* [Qemu-devel] [kvm-unit-tests PATCH v6 01/11] lib: xstr: allow multiple args
From: Andrew Jones @ 2016-11-14 21:08 UTC (permalink / raw)
To: kvm, kvmarm, qemu-devel, qemu-arm
Cc: pbonzini, andre.przywara, peter.maydell, alex.bennee,
marc.zyngier, eric.auger, christoffer.dall
In-Reply-To: <1479157719-31021-1-git-send-email-drjones@redhat.com>
Make implementation equivalent to Linux's include/linux/stringify.h
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Andrew Jones <drjones@redhat.com>
---
lib/libcflat.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/libcflat.h b/lib/libcflat.h
index 72b1bf9668ef..82005f5d014f 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -27,8 +27,8 @@
#define __unused __attribute__((__unused__))
-#define xstr(s) xxstr(s)
-#define xxstr(s) #s
+#define xstr(s...) xxstr(s)
+#define xxstr(s...) #s
#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.