* [net-next 07/13] i40e: separate PF and VSI state flags
From: Jeff Kirsher @ 2017-04-30 13:24 UTC (permalink / raw)
To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170430132451.68494-1-jeffrey.t.kirsher@intel.com>
From: Jacob Keller <jacob.e.keller@intel.com>
Avoid using the same named flags for both vsi->state and pf->state. This
makes code review easier, as it is more likely that future authors will
use the correct state field when checking bits. Previous commits already
found issues with at least one check, and possibly others may be
incorrect.
This reduces confusion as it is more clear what each flag represents,
and which flags are valid for which state field.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e.h | 12 ++++-
drivers/net/ethernet/intel/i40e/i40e_client.c | 4 +-
drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +-
drivers/net/ethernet/intel/i40e/i40e_main.c | 66 ++++++++++++-------------
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 8 +--
drivers/net/ethernet/intel/i40evf/i40e_txrx.c | 8 +--
drivers/net/ethernet/intel/i40evf/i40evf.h | 7 ++-
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 10 ++--
8 files changed, 64 insertions(+), 55 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 0f22c03ec726..ac2a4850a30b 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -125,7 +125,6 @@ enum i40e_state_t {
__I40E_CONFIG_BUSY,
__I40E_CONFIG_DONE,
__I40E_DOWN,
- __I40E_NEEDS_RESTART,
__I40E_SERVICE_SCHED,
__I40E_ADMINQ_EVENT_PENDING,
__I40E_MDD_EVENT_PENDING,
@@ -138,7 +137,6 @@ enum i40e_state_t {
__I40E_GLOBAL_RESET_REQUESTED,
__I40E_EMP_RESET_REQUESTED,
__I40E_EMP_RESET_INTR_RECEIVED,
- __I40E_FILTER_OVERFLOW_PROMISC,
__I40E_SUSPENDED,
__I40E_PTP_TX_IN_PROGRESS,
__I40E_BAD_EEPROM,
@@ -149,6 +147,16 @@ enum i40e_state_t {
__I40E_VF_DISABLE,
};
+/* VSI state flags */
+enum i40e_vsi_state_t {
+ __I40E_VSI_DOWN,
+ __I40E_VSI_NEEDS_RESTART,
+ __I40E_VSI_SYNCING_FILTERS,
+ __I40E_VSI_OVERFLOW_PROMISC,
+ __I40E_VSI_REINIT_REQUESTED,
+ __I40E_VSI_DOWN_REQUESTED,
+};
+
enum i40e_interrupt_policy {
I40E_INTERRUPT_BEST_CASE,
I40E_INTERRUPT_MEDIUM,
diff --git a/drivers/net/ethernet/intel/i40e/i40e_client.c b/drivers/net/ethernet/intel/i40e/i40e_client.c
index eb2896fd52a6..75e528a6943f 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_client.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_client.c
@@ -382,7 +382,7 @@ void i40e_client_subtask(struct i40e_pf *pf)
* the netdev is up, then open the client.
*/
if (!test_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state)) {
- if (!test_bit(__I40E_DOWN, &vsi->state) &&
+ if (!test_bit(__I40E_VSI_DOWN, &vsi->state) &&
client->ops && client->ops->open) {
set_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
ret = client->ops->open(&cdev->lan_info, client);
@@ -397,7 +397,7 @@ void i40e_client_subtask(struct i40e_pf *pf)
/* Likewise for client close. If the client is up, but the netdev
* is down, then close the client.
*/
- if (test_bit(__I40E_DOWN, &vsi->state) &&
+ if (test_bit(__I40E_VSI_DOWN, &vsi->state) &&
client->ops && client->ops->close) {
clear_bit(__I40E_CLIENT_INSTANCE_OPENED, &cdev->state);
client->ops->close(&cdev->lan_info, client, false);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index a3d7ec62b76c..5408dbf04a00 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -174,7 +174,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
}
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) ?
+ (test_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state) ?
"ON" : "OFF"));
nstat = i40e_get_vsi_stats_struct(vsi);
dev_info(&pf->pdev->dev,
@@ -1706,7 +1706,7 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
} else if (!vsi->netdev) {
dev_info(&pf->pdev->dev, "tx_timeout: no netdev for VSI %d\n",
vsi_seid);
- } else if (test_bit(__I40E_DOWN, &vsi->state)) {
+ } else if (test_bit(__I40E_VSI_DOWN, &vsi->state)) {
dev_info(&pf->pdev->dev, "tx_timeout: VSI %d not UP\n",
vsi_seid);
} else if (rtnl_trylock()) {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 20850a646e6c..c30f2bc65451 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -422,7 +422,7 @@ static void i40e_get_netdev_stats_struct(struct net_device *netdev,
struct rtnl_link_stats64 *vsi_stats = i40e_get_vsi_stats_struct(vsi);
int i;
- if (test_bit(__I40E_DOWN, &vsi->state))
+ if (test_bit(__I40E_VSI_DOWN, &vsi->state))
return;
if (!vsi->tx_rings)
@@ -753,7 +753,7 @@ static void i40e_update_vsi_stats(struct i40e_vsi *vsi)
u64 tx_p, tx_b;
u16 q;
- if (test_bit(__I40E_DOWN, &vsi->state) ||
+ if (test_bit(__I40E_VSI_DOWN, &vsi->state) ||
test_bit(__I40E_CONFIG_BUSY, &pf->state))
return;
@@ -1346,7 +1346,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
* to failed, so we don't bother to try sending the filter
* to the hardware.
*/
- if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state))
+ if (test_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state))
f->state = I40E_FILTER_FAILED;
else
f->state = I40E_FILTER_NEW;
@@ -1525,7 +1525,7 @@ static int i40e_set_mac(struct net_device *netdev, void *p)
return 0;
}
- if (test_bit(__I40E_DOWN, &vsi->back->state) ||
+ if (test_bit(__I40E_VSI_DOWN, &vsi->back->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
return -EADDRNOTAVAIL;
@@ -1920,7 +1920,7 @@ void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
if (fcnt != num_add) {
*promisc_changed = true;
- set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+ set_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state);
dev_warn(&vsi->back->pdev->dev,
"Error %s adding RX filters on %s, promiscuous mode forced on\n",
i40e_aq_str(hw, aq_err),
@@ -2003,7 +2003,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
struct i40e_aqc_add_macvlan_element_data *add_list;
struct i40e_aqc_remove_macvlan_element_data *del_list;
- while (test_and_set_bit(__I40E_CONFIG_BUSY, &vsi->state))
+ while (test_and_set_bit(__I40E_VSI_SYNCING_FILTERS, &vsi->state))
usleep_range(1000, 2000);
pf = vsi->back;
@@ -2139,7 +2139,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
num_add = 0;
hlist_for_each_entry_safe(new, h, &tmp_add_list, hlist) {
- if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
+ if (test_bit(__I40E_VSI_OVERFLOW_PROMISC,
&vsi->state)) {
new->state = I40E_FILTER_FAILED;
continue;
@@ -2227,20 +2227,20 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
* safely exit if we didn't just enter, we no longer have any failed
* filters, and we have reduced filters below the threshold value.
*/
- if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state) &&
+ if (test_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state) &&
!promisc_changed && !failed_filters &&
(vsi->active_filters < vsi->promisc_threshold)) {
dev_info(&pf->pdev->dev,
"filter logjam cleared on %s, leaving overflow promiscuous mode\n",
vsi_name);
- clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+ clear_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state);
promisc_changed = true;
vsi->promisc_threshold = 0;
}
/* if the VF is not trusted do not do promisc */
if ((vsi->type == I40E_VSI_SRIOV) && !pf->vf[vsi->vf_id].trusted) {
- clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+ clear_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state);
goto out;
}
@@ -2265,11 +2265,11 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
}
if ((changed_flags & IFF_PROMISC) ||
(promisc_changed &&
- test_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state))) {
+ test_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state))) {
bool cur_promisc;
cur_promisc = (!!(vsi->current_netdev_flags & IFF_PROMISC) ||
- test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
+ test_bit(__I40E_VSI_OVERFLOW_PROMISC,
&vsi->state));
if ((vsi->type == I40E_VSI_MAIN) &&
(pf->lan_veb != I40E_NO_VEB) &&
@@ -2353,7 +2353,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
if (retval)
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
- clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+ clear_bit(__I40E_VSI_SYNCING_FILTERS, &vsi->state);
return retval;
err_no_memory:
@@ -2365,7 +2365,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)
spin_unlock_bh(&vsi->mac_filter_hash_lock);
vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
- clear_bit(__I40E_CONFIG_BUSY, &vsi->state);
+ clear_bit(__I40E_VSI_SYNCING_FILTERS, &vsi->state);
return -ENOMEM;
}
@@ -3907,7 +3907,7 @@ static void i40e_netpoll(struct net_device *netdev)
int i;
/* if interface is down do nothing */
- if (test_bit(__I40E_DOWN, &vsi->state))
+ if (test_bit(__I40E_VSI_DOWN, &vsi->state))
return;
if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
@@ -4436,7 +4436,7 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi)
static void i40e_vsi_close(struct i40e_vsi *vsi)
{
struct i40e_pf *pf = vsi->back;
- if (!test_and_set_bit(__I40E_DOWN, &vsi->state))
+ if (!test_and_set_bit(__I40E_VSI_DOWN, &vsi->state))
i40e_down(vsi);
i40e_vsi_free_irq(vsi);
i40e_vsi_free_tx_resources(vsi);
@@ -4453,10 +4453,10 @@ static void i40e_vsi_close(struct i40e_vsi *vsi)
**/
static void i40e_quiesce_vsi(struct i40e_vsi *vsi)
{
- if (test_bit(__I40E_DOWN, &vsi->state))
+ if (test_bit(__I40E_VSI_DOWN, &vsi->state))
return;
- set_bit(__I40E_NEEDS_RESTART, &vsi->state);
+ set_bit(__I40E_VSI_NEEDS_RESTART, &vsi->state);
if (vsi->netdev && netif_running(vsi->netdev))
vsi->netdev->netdev_ops->ndo_stop(vsi->netdev);
else
@@ -4469,10 +4469,9 @@ static void i40e_quiesce_vsi(struct i40e_vsi *vsi)
**/
static void i40e_unquiesce_vsi(struct i40e_vsi *vsi)
{
- if (!test_bit(__I40E_NEEDS_RESTART, &vsi->state))
+ if (!test_and_clear_bit(__I40E_VSI_NEEDS_RESTART, &vsi->state))
return;
- clear_bit(__I40E_NEEDS_RESTART, &vsi->state);
if (vsi->netdev && netif_running(vsi->netdev))
vsi->netdev->netdev_ops->ndo_open(vsi->netdev);
else
@@ -4638,7 +4637,7 @@ static void i40e_detect_recover_hung(struct i40e_pf *pf)
return;
/* Make sure, VSI state is not DOWN/RECOVERY_PENDING */
- if (test_bit(__I40E_DOWN, &vsi->back->state) ||
+ if (test_bit(__I40E_VSI_DOWN, &vsi->back->state) ||
test_bit(__I40E_RESET_RECOVERY_PENDING, &vsi->back->state))
return;
@@ -5354,7 +5353,7 @@ static int i40e_up_complete(struct i40e_vsi *vsi)
if (err)
return err;
- clear_bit(__I40E_DOWN, &vsi->state);
+ clear_bit(__I40E_VSI_DOWN, &vsi->state);
i40e_napi_enable_all(vsi);
i40e_vsi_enable_irq(vsi);
@@ -5435,7 +5434,7 @@ void i40e_down(struct i40e_vsi *vsi)
int i;
/* It is assumed that the caller of this function
- * sets the vsi->state __I40E_DOWN bit.
+ * sets the vsi->state __I40E_VSI_DOWN bit.
*/
if (vsi->netdev) {
netif_carrier_off(vsi->netdev);
@@ -5787,10 +5786,9 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired)
struct i40e_vsi *vsi = pf->vsi[v];
if (vsi != NULL &&
- test_bit(__I40E_REINIT_REQUESTED, &vsi->state)) {
+ test_and_clear_bit(__I40E_VSI_REINIT_REQUESTED,
+ &vsi->state))
i40e_vsi_reinit_locked(pf->vsi[v]);
- clear_bit(__I40E_REINIT_REQUESTED, &vsi->state);
- }
}
} else if (reset_flags & BIT_ULL(__I40E_DOWN_REQUESTED)) {
int v;
@@ -5801,10 +5799,10 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired)
struct i40e_vsi *vsi = pf->vsi[v];
if (vsi != NULL &&
- test_bit(__I40E_DOWN_REQUESTED, &vsi->state)) {
- set_bit(__I40E_DOWN, &vsi->state);
+ test_and_clear_bit(__I40E_VSI_DOWN_REQUESTED,
+ &vsi->state)) {
+ set_bit(__I40E_VSI_DOWN, &vsi->state);
i40e_down(vsi);
- clear_bit(__I40E_DOWN_REQUESTED, &vsi->state);
}
}
} else {
@@ -6223,7 +6221,7 @@ static void i40e_fdir_reinit_subtask(struct i40e_pf *pf)
**/
static void i40e_vsi_link_event(struct i40e_vsi *vsi, bool link_up)
{
- if (!vsi || test_bit(__I40E_DOWN, &vsi->state))
+ if (!vsi || test_bit(__I40E_VSI_DOWN, &vsi->state))
return;
switch (vsi->type) {
@@ -6316,11 +6314,11 @@ static void i40e_link_event(struct i40e_pf *pf)
if (new_link == old_link &&
new_link_speed == old_link_speed &&
- (test_bit(__I40E_DOWN, &vsi->state) ||
+ (test_bit(__I40E_VSI_DOWN, &vsi->state) ||
new_link == netif_carrier_ok(vsi->netdev)))
return;
- if (!test_bit(__I40E_DOWN, &vsi->state))
+ if (!test_bit(__I40E_VSI_DOWN, &vsi->state))
i40e_print_link_message(vsi, new_link);
/* Notify the base of the switch tree connected to
@@ -7591,7 +7589,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
}
vsi->type = type;
vsi->back = pf;
- set_bit(__I40E_DOWN, &vsi->state);
+ set_bit(__I40E_VSI_DOWN, &vsi->state);
vsi->flags = 0;
vsi->idx = vsi_idx;
vsi->int_rate_limit = 0;
@@ -9718,7 +9716,7 @@ static int i40e_add_vsi(struct i40e_vsi *vsi)
}
vsi->active_filters = 0;
- clear_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+ clear_bit(__I40E_VSI_OVERFLOW_PROMISC, &vsi->state);
spin_lock_bh(&vsi->mac_filter_hash_lock);
/* If macvlan filters already exist, force them to get loaded */
hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 1531a0f9fcc6..bbd21cbf3e4d 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -850,7 +850,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
if (budget &&
((j / WB_STRIDE) == 0) && (j > 0) &&
- !test_bit(__I40E_DOWN, &vsi->state) &&
+ !test_bit(__I40E_VSI_DOWN, &vsi->state) &&
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
tx_ring->arm_wb = true;
}
@@ -868,7 +868,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
smp_mb();
if (__netif_subqueue_stopped(tx_ring->netdev,
tx_ring->queue_index) &&
- !test_bit(__I40E_DOWN, &vsi->state)) {
+ !test_bit(__I40E_VSI_DOWN, &vsi->state)) {
netif_wake_subqueue(tx_ring->netdev,
tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue;
@@ -2179,7 +2179,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
}
enable_int:
- if (!test_bit(__I40E_DOWN, &vsi->state))
+ if (!test_bit(__I40E_VSI_DOWN, &vsi->state))
wr32(hw, INTREG(vector - 1), txval);
if (q_vector->itr_countdown)
@@ -2208,7 +2208,7 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
int budget_per_ring;
int work_done = 0;
- if (test_bit(__I40E_DOWN, &vsi->state)) {
+ if (test_bit(__I40E_VSI_DOWN, &vsi->state)) {
napi_complete(napi);
return 0;
}
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
index 34e96d98251a..c95ee0a8950f 100644
--- a/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.c
@@ -266,7 +266,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
if (budget &&
((j / WB_STRIDE) == 0) && (j > 0) &&
- !test_bit(__I40E_DOWN, &vsi->state) &&
+ !test_bit(__I40E_VSI_DOWN, &vsi->state) &&
(I40E_DESC_UNUSED(tx_ring) != tx_ring->count))
tx_ring->arm_wb = true;
}
@@ -284,7 +284,7 @@ static bool i40e_clean_tx_irq(struct i40e_vsi *vsi,
smp_mb();
if (__netif_subqueue_stopped(tx_ring->netdev,
tx_ring->queue_index) &&
- !test_bit(__I40E_DOWN, &vsi->state)) {
+ !test_bit(__I40E_VSI_DOWN, &vsi->state)) {
netif_wake_subqueue(tx_ring->netdev,
tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue;
@@ -1508,7 +1508,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
}
enable_int:
- if (!test_bit(__I40E_DOWN, &vsi->state))
+ if (!test_bit(__I40E_VSI_DOWN, &vsi->state))
wr32(hw, INTREG(vector - 1), txval);
if (q_vector->itr_countdown)
@@ -1537,7 +1537,7 @@ int i40evf_napi_poll(struct napi_struct *napi, int budget)
int budget_per_ring;
int work_done = 0;
- if (test_bit(__I40E_DOWN, &vsi->state)) {
+ if (test_bit(__I40E_VSI_DOWN, &vsi->state)) {
napi_complete(napi);
return 0;
}
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
index 40f56e2335df..a56a6e54d907 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
@@ -49,6 +49,11 @@
#define DEFAULT_DEBUG_LEVEL_SHIFT 3
#define PFX "i40evf: "
+/* VSI state flags shared with common code */
+enum i40evf_vsi_state_t {
+ __I40E_VSI_DOWN,
+};
+
/* dummy struct to make common code less painful */
struct i40e_vsi {
struct i40evf_adapter *back;
@@ -168,8 +173,6 @@ enum i40evf_critical_section_t {
__I40EVF_IN_CRITICAL_TASK, /* cannot be interrupted */
__I40EVF_IN_CLIENT_TASK,
};
-/* make common code happy */
-#define __I40E_DOWN __I40EVF_DOWN
/* board specific private data structure */
struct i40evf_adapter {
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 3ea81bd0db32..b453d05c2a30 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -497,7 +497,7 @@ static void i40evf_netpoll(struct net_device *netdev)
int i;
/* if interface is down do nothing */
- if (test_bit(__I40E_DOWN, &adapter->vsi.state))
+ if (test_bit(__I40E_VSI_DOWN, &adapter->vsi.state))
return;
for (i = 0; i < q_vectors; i++)
@@ -1087,7 +1087,7 @@ static void i40evf_configure(struct i40evf_adapter *adapter)
static void i40evf_up_complete(struct i40evf_adapter *adapter)
{
adapter->state = __I40EVF_RUNNING;
- clear_bit(__I40E_DOWN, &adapter->vsi.state);
+ clear_bit(__I40E_VSI_DOWN, &adapter->vsi.state);
i40evf_napi_enable_all(adapter);
@@ -1753,7 +1753,7 @@ static void i40evf_disable_vf(struct i40evf_adapter *adapter)
adapter->flags |= I40EVF_FLAG_PF_COMMS_FAILED;
if (netif_running(adapter->netdev)) {
- set_bit(__I40E_DOWN, &adapter->vsi.state);
+ set_bit(__I40E_VSI_DOWN, &adapter->vsi.state);
netif_carrier_off(adapter->netdev);
netif_tx_disable(adapter->netdev);
adapter->link_up = false;
@@ -2233,7 +2233,7 @@ static int i40evf_close(struct net_device *netdev)
return 0;
- set_bit(__I40E_DOWN, &adapter->vsi.state);
+ set_bit(__I40E_VSI_DOWN, &adapter->vsi.state);
if (CLIENT_ENABLED(adapter))
adapter->flags |= I40EVF_FLAG_CLIENT_NEEDS_CLOSE;
@@ -2674,7 +2674,7 @@ static void i40evf_init_task(struct work_struct *work)
dev_info(&pdev->dev, "GRO is enabled\n");
adapter->state = __I40EVF_DOWN;
- set_bit(__I40E_DOWN, &adapter->vsi.state);
+ set_bit(__I40E_VSI_DOWN, &adapter->vsi.state);
i40evf_misc_irq_enable(adapter);
adapter->rss_key = kzalloc(adapter->rss_key_size, GFP_KERNEL);
--
2.12.2
^ permalink raw reply related
* [net-next 11/13] i40evf: remove I40E_FLAG_FDIR_ATR_ENABLED
From: Jeff Kirsher @ 2017-04-30 13:24 UTC (permalink / raw)
To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170430132451.68494-1-jeffrey.t.kirsher@intel.com>
From: Jacob Keller <jacob.e.keller@intel.com>
The flag used by the common code and PF code is I40E_FLAG_FD_ATR_ENABLED,
not *FDIR*. It turns out none of the txrx code actually shared with the
VF driver actually checks the ATR flag. This is made even more obvious
by the typo in the VF header file.
Let's just remove the flag from the VF driver since it's not needed.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40evf.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h
index 4681c63ee7e3..b8ada6d8d890 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf.h
+++ b/drivers/net/ethernet/intel/i40evf/i40evf.h
@@ -223,7 +223,6 @@ struct i40evf_adapter {
#define I40EVF_FLAG_ALLMULTI_ON BIT(19)
#define I40EVF_FLAG_LEGACY_RX BIT(20)
/* duplicates for common code */
-#define I40E_FLAG_FDIR_ATR_ENABLED 0
#define I40E_FLAG_DCB_ENABLED 0
#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
#define I40E_FLAG_WB_ON_ITR_CAPABLE I40EVF_FLAG_WB_ON_ITR_CAPABLE
--
2.12.2
^ permalink raw reply related
* [net-next 10/13] i40e: remove hw_disabled_flags in favor of using separate flag bits
From: Jeff Kirsher @ 2017-04-30 13:24 UTC (permalink / raw)
To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170430132451.68494-1-jeffrey.t.kirsher@intel.com>
From: Jacob Keller <jacob.e.keller@intel.com>
The hw_disabled_flags field was added as a way of signifying that
a feature was automatically or temporarily disabled. However, we
actually only use this for FDir features. Replace its use with new
_AUTO_DISABLED flags instead. This is more readable, because you aren't
setting an *_ENABLED flag to *disable* the feature.
Additionally, clean up a few areas where we used these bits. First, we
don't really need to set the auto-disable flag for ATR if we're fully
disabling the feature via ethtool.
Second, we should always clear the auto-disable bits in case they somehow
got set when the feature was disabled. However, avoid displaying
a message that we've re-enabled the feature.
Third, we shouldn't be re-enabling ATR in the SB ntuple add flow,
because it might have been disabled due to space constraints. Instead,
we should just wait for the fdir_check_and_reenable to be called by the
watchdog.
Overall, this change allows us to simplify some code by removing an
extra field we didn't need, and the result should make it more clear as
to what we're actually doing with these flags.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e.h | 9 +----
drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 6 +--
drivers/net/ethernet/intel/i40e/i40e_main.c | 53 +++++++++++++-------------
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 22 ++++-------
4 files changed, 38 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index 6eb21abdc60e..cdde3cc28fb5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -408,6 +408,8 @@ struct i40e_pf {
#define I40E_FLAG_DCB_ENABLED BIT_ULL(20)
#define I40E_FLAG_FD_SB_ENABLED BIT_ULL(21)
#define I40E_FLAG_FD_ATR_ENABLED BIT_ULL(22)
+#define I40E_FLAG_FD_SB_AUTO_DISABLED BIT_ULL(23)
+#define I40E_FLAG_FD_ATR_AUTO_DISABLED BIT_ULL(24)
#define I40E_FLAG_PTP BIT_ULL(25)
#define I40E_FLAG_MFP_ENABLED BIT_ULL(26)
#define I40E_FLAG_UDP_FILTER_SYNC BIT_ULL(27)
@@ -440,13 +442,6 @@ struct i40e_pf {
#define I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE BIT_ULL(57)
#define I40E_FLAG_LEGACY_RX BIT_ULL(58)
- /* Tracks features that are disabled due to hw limitations.
- * If a bit is set here, it means that the corresponding
- * bit in the 'flags' field is cleared i.e that feature
- * is disabled
- */
- u64 hw_disabled_flags;
-
struct i40e_client_instance *cinst;
bool stat_offsets_loaded;
struct i40e_hw_port_stats stats;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index b1064c6468c2..7a8eb486b9ea 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -3643,7 +3643,7 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
return -EOPNOTSUPP;
- if (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)
+ if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED)
return -ENOSPC;
if (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state) ||
@@ -4086,12 +4086,12 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
/* Flush current ATR settings if ATR was disabled */
if ((changed_flags & I40E_FLAG_FD_ATR_ENABLED) &&
!(pf->flags & I40E_FLAG_FD_ATR_ENABLED)) {
- pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
+ pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
set_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
}
/* Only allow ATR evict on hardware that is capable of handling it */
- if (pf->hw_disabled_flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
+ if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE)
pf->flags &= ~I40E_FLAG_HW_ATR_EVICT_CAPABLE;
if (changed_flags & I40E_FLAG_TRUE_PROMISC_SUPPORT) {
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index 38772e49bb84..d5c9c9e06ff5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -1050,13 +1050,13 @@ static void i40e_update_pf_stats(struct i40e_pf *pf)
&osd->rx_lpi_count, &nsd->rx_lpi_count);
if (pf->flags & I40E_FLAG_FD_SB_ENABLED &&
- !(pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED))
+ !(pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED))
nsd->fd_sb_status = true;
else
nsd->fd_sb_status = false;
if (pf->flags & I40E_FLAG_FD_ATR_ENABLED &&
- !(pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED))
+ !(pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))
nsd->fd_atr_status = true;
else
nsd->fd_atr_status = false;
@@ -6078,31 +6078,30 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
if (test_bit(__I40E_FD_FLUSH_REQUESTED, pf->state))
return;
- /* Check if, FD SB or ATR was auto disabled and if there is enough room
- * to re-enable
- */
+ /* Check if we have enough room to re-enable FDir SB capability. */
fcnt_prog = i40e_get_global_fd_count(pf);
fcnt_avail = pf->fdir_pf_filter_count;
if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) ||
(pf->fd_add_err == 0) ||
(i40e_get_current_atr_cnt(pf) < pf->fd_atr_cnt)) {
- if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
- (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)) {
- pf->hw_disabled_flags &= ~I40E_FLAG_FD_SB_ENABLED;
- if (I40E_DEBUG_FD & pf->hw.debug_mask)
+ if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
+ pf->flags &= ~I40E_FLAG_FD_SB_AUTO_DISABLED;
+ if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
+ (I40E_DEBUG_FD & pf->hw.debug_mask))
dev_info(&pf->pdev->dev, "FD Sideband/ntuple is being enabled since we have space in the table now\n");
}
}
- /* Wait for some more space to be available to turn on ATR. We also
- * must check that no existing ntuple rules for TCP are in effect
+ /* We should wait for even more space before re-enabling ATR.
+ * Additionally, we cannot enable ATR as long as we still have TCP SB
+ * rules active.
*/
- if (fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM * 2)) {
- if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
- (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED) &&
- (pf->fd_tcp4_filter_cnt == 0)) {
- pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
- if (I40E_DEBUG_FD & pf->hw.debug_mask)
+ if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) &&
+ (pf->fd_tcp4_filter_cnt == 0)) {
+ if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
+ pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
+ if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+ (I40E_DEBUG_FD & pf->hw.debug_mask))
dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table and there are no conflicting ntuple rules\n");
}
}
@@ -6153,7 +6152,7 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
}
pf->fd_flush_timestamp = jiffies;
- pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
+ pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
/* flush all filters */
wr32(&pf->hw, I40E_PFQF_CTL_1,
I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
@@ -6173,7 +6172,7 @@ static void i40e_fdir_flush_and_replay(struct i40e_pf *pf)
/* replay sideband filters */
i40e_fdir_filter_restore(pf->vsi[pf->lan_vsi]);
if (!disable_atr && !pf->fd_tcp4_filter_cnt)
- pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
+ pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
clear_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
if (I40E_DEBUG_FD & pf->hw.debug_mask)
dev_info(&pf->pdev->dev, "FD Filter table flushed and FD-SB replayed.\n");
@@ -8822,9 +8821,9 @@ static int i40e_sw_init(struct i40e_pf *pf)
(pf->hw.aq.api_min_ver > 4))) {
/* Supported in FW API version higher than 1.4 */
pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
- pf->hw_disabled_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
+ pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
} else {
- pf->hw_disabled_flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
+ pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
}
pf->eeprom_version = 0xDEAD;
@@ -8884,16 +8883,16 @@ bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features)
need_reset = true;
i40e_fdir_filter_exit(pf);
}
- pf->flags &= ~I40E_FLAG_FD_SB_ENABLED;
- pf->hw_disabled_flags &= ~I40E_FLAG_FD_SB_ENABLED;
+ pf->flags &= ~(I40E_FLAG_FD_SB_ENABLED |
+ I40E_FLAG_FD_SB_AUTO_DISABLED);
/* reset fd counters */
pf->fd_add_err = 0;
pf->fd_atr_cnt = 0;
/* if ATR was auto disabled it can be re-enabled. */
- if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
- (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED)) {
- pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
- if (I40E_DEBUG_FD & pf->hw.debug_mask)
+ if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
+ pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
+ if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
+ (I40E_DEBUG_FD & pf->hw.debug_mask))
dev_info(&pf->pdev->dev, "ATR re-enabled.\n");
}
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 6e677a235fe4..29321a6167a6 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -333,15 +333,9 @@ static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
I40E_DEBUG_FD & pf->hw.debug_mask)
dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n");
- pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
+ pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
} else {
pf->fd_tcp4_filter_cnt--;
- if (pf->fd_tcp4_filter_cnt == 0) {
- if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
- I40E_DEBUG_FD & pf->hw.debug_mask)
- dev_info(&pf->pdev->dev, "ATR re-enabled due to no sideband TCP/IPv4 rules\n");
- pf->hw_disabled_flags &= ~I40E_FLAG_FD_ATR_ENABLED;
- }
}
return 0;
@@ -597,8 +591,8 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
pf->fd_atr_cnt = i40e_get_current_atr_cnt(pf);
if ((rx_desc->wb.qword0.hi_dword.fd_id == 0) &&
- (pf->hw_disabled_flags & I40E_FLAG_FD_SB_ENABLED)) {
- pf->hw_disabled_flags |= I40E_FLAG_FD_ATR_ENABLED;
+ pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
+ pf->flags |= I40E_FLAG_FD_ATR_AUTO_DISABLED;
set_bit(__I40E_FD_FLUSH_REQUESTED, pf->state);
}
@@ -611,12 +605,10 @@ static void i40e_fd_handle_status(struct i40e_ring *rx_ring,
*/
if (fcnt_prog >= (fcnt_avail - I40E_FDIR_BUFFER_FULL_MARGIN)) {
if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
- !(pf->hw_disabled_flags &
- I40E_FLAG_FD_SB_ENABLED)) {
+ !(pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED)) {
+ pf->flags |= I40E_FLAG_FD_SB_AUTO_DISABLED;
if (I40E_DEBUG_FD & pf->hw.debug_mask)
dev_warn(&pdev->dev, "FD filter space full, new ntuple rules will not be added\n");
- pf->hw_disabled_flags |=
- I40E_FLAG_FD_SB_ENABLED;
}
}
} else if (error == BIT(I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) {
@@ -2312,7 +2304,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
if (!(pf->flags & I40E_FLAG_FD_ATR_ENABLED))
return;
- if ((pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED))
+ if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED)
return;
/* if sampling is disabled do nothing */
@@ -2346,7 +2338,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
th = (struct tcphdr *)(hdr.network + hlen);
/* Due to lack of space, no more new filters can be programmed */
- if (th->syn && (pf->hw_disabled_flags & I40E_FLAG_FD_ATR_ENABLED))
+ if (th->syn && (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED))
return;
if (pf->flags & I40E_FLAG_HW_ATR_EVICT_CAPABLE) {
/* HW ATR eviction will take care of removing filters on FIN
--
2.12.2
^ permalink raw reply related
* [net-next 12/13] i40evf: allocate queues before we setup the interrupts and q_vectors
From: Jeff Kirsher @ 2017-04-30 13:24 UTC (permalink / raw)
To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170430132451.68494-1-jeffrey.t.kirsher@intel.com>
From: Jacob Keller <jacob.e.keller@intel.com>
This matches the ordering of how we free stuff during reset and remove.
It also makes logical sense because we set the interrupts based on the
number of queues. Currently this doesn't really matter in practice.
However a future patch moves the assignment of num_active_queues into
i40evf_alloc_queues, which is required by
i40evf_set_interrupt_capability.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 89035ee01679..445a97a57853 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -1508,6 +1508,13 @@ int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter)
{
int err;
+ err = i40evf_alloc_queues(adapter);
+ if (err) {
+ dev_err(&adapter->pdev->dev,
+ "Unable to allocate memory for queues\n");
+ goto err_alloc_queues;
+ }
+
rtnl_lock();
err = i40evf_set_interrupt_capability(adapter);
rtnl_unlock();
@@ -1524,23 +1531,16 @@ int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter)
goto err_alloc_q_vectors;
}
- err = i40evf_alloc_queues(adapter);
- if (err) {
- dev_err(&adapter->pdev->dev,
- "Unable to allocate memory for queues\n");
- goto err_alloc_queues;
- }
-
dev_info(&adapter->pdev->dev, "Multiqueue %s: Queue pair count = %u",
(adapter->num_active_queues > 1) ? "Enabled" : "Disabled",
adapter->num_active_queues);
return 0;
-err_alloc_queues:
- i40evf_free_q_vectors(adapter);
err_alloc_q_vectors:
i40evf_reset_interrupt_capability(adapter);
err_set_interrupt:
+ i40evf_free_queues(adapter);
+err_alloc_queues:
return err;
}
--
2.12.2
^ permalink raw reply related
* [net-next 06/13] i40e: remove unnecessary msleep() delay in i40e_free_vfs
From: Jeff Kirsher @ 2017-04-30 13:24 UTC (permalink / raw)
To: davem; +Cc: Jacob Keller, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170430132451.68494-1-jeffrey.t.kirsher@intel.com>
From: Jacob Keller <jacob.e.keller@intel.com>
The delay was added because of a desire to ensure that the VF driver can
finish up removing. However, pci_disable_sriov already has its own
ssleep() call that will sleep for an entire second, so there is no
reason to add extra delay on top of this by using msleep here. In
practice, an msleep() won't have a huge impact on timing but there is no
real value in keeping it, so lets just simplify the code and remove it.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +-
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 2 --
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 2 +-
3 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index f44affc7e08c..20850a646e6c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -47,7 +47,7 @@ static const char i40e_driver_string[] =
#define DRV_VERSION_MAJOR 2
#define DRV_VERSION_MINOR 1
-#define DRV_VERSION_BUILD 7
+#define DRV_VERSION_BUILD 14
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index 2a47a6474366..29f53f032c3c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -1219,8 +1219,6 @@ void i40e_free_vfs(struct i40e_pf *pf)
else
dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n");
- msleep(20); /* let any messages in transit get finished up */
-
/* free up VF resources */
tmp = pf->num_alloc_vfs;
pf->num_alloc_vfs = 0;
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 5915273c372f..3ea81bd0db32 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -46,7 +46,7 @@ static const char i40evf_driver_string[] =
#define DRV_VERSION_MAJOR 2
#define DRV_VERSION_MINOR 1
-#define DRV_VERSION_BUILD 7
+#define DRV_VERSION_BUILD 14
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) \
--
2.12.2
^ permalink raw reply related
* [net-next 13/13] i40evf: hide unused variable
From: Jeff Kirsher @ 2017-04-30 13:24 UTC (permalink / raw)
To: davem; +Cc: Arnd Bergmann, netdev, nhorman, sassmann, jogreene, Jeff Kirsher
In-Reply-To: <20170430132451.68494-1-jeffrey.t.kirsher@intel.com>
From: Arnd Bergmann <arnd@arndb.de>
On architectures with larger pages, we get a warning about an unused variable:
drivers/net/ethernet/intel/i40evf/i40evf_main.c: In function 'i40evf_configure_rx':
drivers/net/ethernet/intel/i40evf/i40evf_main.c:690:21: error: unused variable 'netdev' [-Werror=unused-variable]
This moves the declaration into the #ifdef to avoid the warning.
Fixes: dab86afdbbd1 ("i40e/i40evf: Change the way we limit the maximum frame size for Rx")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 445a97a57853..ea110a730e16 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -694,13 +694,14 @@ static void i40evf_configure_tx(struct i40evf_adapter *adapter)
static void i40evf_configure_rx(struct i40evf_adapter *adapter)
{
unsigned int rx_buf_len = I40E_RXBUFFER_2048;
- struct net_device *netdev = adapter->netdev;
struct i40e_hw *hw = &adapter->hw;
int i;
/* Legacy Rx will always default to a 2048 buffer size. */
#if (PAGE_SIZE < 8192)
if (!(adapter->flags & I40EVF_FLAG_LEGACY_RX)) {
+ struct net_device *netdev = adapter->netdev;
+
/* For jumbo frames on systems with 4K pages we have to use
* an order 1 page, so we might as well increase the size
* of our Rx buffer to make better use of the available space
--
2.12.2
^ permalink raw reply related
* [PATCH net-next] net/esp4: Fix invalid esph pointer crash
From: ilant @ 2017-04-30 13:34 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, Ilan Tayari
From: Ilan Tayari <ilant@mellanox.com>
Both esp_output and esp_xmit take a pointer to the ESP header
and place it in esp_info struct prior to calling esp_output_head.
Inside esp_output_head, the call to esp_output_udp_encap
makes sure to update the pointer if it gets invalid.
However, if esp_output_head itself calls skb_cow_data, the
pointer is not updated and stays invalid, causing a crash
after esp_output_head returns.
Update the pointer if it becomes invalid in esp_output_head
Fixes: fca11ebde3f0 ("esp4: Reorganize esp_output")
Signed-off-by: Ilan Tayari <ilant@mellanox.com>
---
net/ipv4/esp4.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 7f2caf71212b..65cc02bd82bc 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -317,6 +317,7 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
if (nfrags < 0)
goto out;
tail = skb_tail_pointer(trailer);
+ esp->esph = ip_esp_hdr(skb);
skip_cow:
esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto);
--
2.11.0
^ permalink raw reply related
* [PATCH net-next] xfrm: Indicate xfrm_state offload errors
From: ilant @ 2017-04-30 13:51 UTC (permalink / raw)
To: Steffen Klassert; +Cc: netdev, Ilan Tayari
From: Ilan Tayari <ilant@mellanox.com>
Current code silently ignores driver errors when configuring
IPSec offload xfrm_state, and falls back to host-based crypto.
Fail the xfrm_state creation if the driver has an error, because
the NIC offloading was explicitly requested by the user program.
This will communicate back to the user that there was an error.
Fixes: d77e38e612a0 ("xfrm: Add an IPsec hardware offloading API")
Signed-off-by: Ilan Tayari <ilant@mellanox.com>
---
net/xfrm/xfrm_user.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index ba74e5eeeeef..c4cceddac9db 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -595,9 +595,12 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
goto error;
}
- if (attrs[XFRMA_OFFLOAD_DEV] &&
- xfrm_dev_state_add(net, x, nla_data(attrs[XFRMA_OFFLOAD_DEV])))
- goto error;
+ if (attrs[XFRMA_OFFLOAD_DEV]) {
+ err = xfrm_dev_state_add(net, x,
+ nla_data(attrs[XFRMA_OFFLOAD_DEV]));
+ if (err)
+ goto error;
+ }
if ((err = xfrm_alloc_replay_state_esn(&x->replay_esn, &x->preplay_esn,
attrs[XFRMA_REPLAY_ESN_VAL])))
--
2.11.0
^ permalink raw reply related
* Re: [PATCH/RFC net-next 0/4] net/sched: cls_flower: avoid false matching of truncated packets
From: Jamal Hadi Salim @ 2017-04-30 13:51 UTC (permalink / raw)
To: Simon Horman
Cc: Jiri Pirko, Cong Wang, Dinan Gunawardena, netdev, oss-drivers
In-Reply-To: <20170428141414.GA11256@vergenet.net>
On 17-04-28 10:14 AM, Simon Horman wrote:
> On Fri, Apr 28, 2017 at 09:41:00AM -0400, Jamal Hadi Salim wrote:
>> On 17-04-28 09:11 AM, Simon Horman wrote:
[..]
>> A default lower prio match all on udp or icmp?
>
> I'm certainly not opposed to exploring ideas here.
>
> The way that flower currently works is that a match on ip_proto ==
> UDP/TCP/SCTP/ICMP but not fields in the L4 header itself would not result in
> the dissector only dissecting the packet's L4 header and thus would not
> discover (or as in currently the case, silently ignore) the absence of the
> ports/ICMP type and code in the L4 header.
>
> What my patch attempts to do is to describe a policy of what to do if
> a given classifier invokes the dissector (to pull out the headers needed for
> the match in question) and that dissection fails. Its basically describing
> the error-path.
>
Understood - I was struggling with whether error-path is the same as
"didnt match".
>
> There are two issues:
>
> 1. As things stand, without this patch-set, flower does not differentiate
> between a packet truncated at the end of the IP header and a packet with
> zero ports. Likewise for icmp type and code of zero.
>
> The first three patches of this series address that so that a match for
> port == zero only matches if ports are present in the packet. Again,
> likewise for ICMP.
>
> This is a bug-fix to my way of thinking.
>
Agreed to bug fix. I would have said there is never a legit packet with
TCP/UDP but I think some fingerprinting apps use it. And one would need
to distinguish between the two at classification time.
ICMP type 0 is certainly used.
minimal some flag should qualify it as "truncated".
> 2. The behaviour described above, prior to this patchset, might have been
> utilised to f.e. drop packets that are either truncated or have port == 0
> (because flower didn't differentiate between these cases).
>
> So the question becomes if/how to provide such a feature.
> The last patch is my attempt to answer that question.
It almost feels like you need metadata matching as well - one being
"truncated".
cheers,
jamal
^ permalink raw reply
* Re: [patch net-next] net: sched: add helpers to handle extended actions
From: Jamal Hadi Salim @ 2017-04-30 14:08 UTC (permalink / raw)
To: Jiri Pirko, netdev; +Cc: davem, xiyou.wangcong, mlxsw
In-Reply-To: <1493396006-11084-1-git-send-email-jiri@resnulli.us>
Jiri,
With "goto chain X" this will have to be more generalized. Maybe
we have 0xAXXXXXXX Where "A" recognizes the extension with
current values ACT_JUMP(0x1) and GOTO_CHAIN(maybe 0x2)
and the rest "XXXXXXX" is a free floating parameter values
which carry the goto count for ACT_JUMP and GOTO_CHAIN chain-id.
cheers,
jamal
On 17-04-28 12:13 PM, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@mellanox.com>
>
> Jump is now the only one using value action opcode. This is going to
> change soon. So introduce helpers to work with this. Convert TC_ACT_JUMP.
>
> Signed-off-by: Jiri Pirko <jiri@mellanox.com>
> ---
> include/uapi/linux/pkt_cls.h | 15 ++++++++++++++-
> net/sched/act_api.c | 2 +-
> 2 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
> index f1129e3..d613be3 100644
> --- a/include/uapi/linux/pkt_cls.h
> +++ b/include/uapi/linux/pkt_cls.h
> @@ -37,7 +37,20 @@ enum {
> #define TC_ACT_QUEUED 5
> #define TC_ACT_REPEAT 6
> #define TC_ACT_REDIRECT 7
> -#define TC_ACT_JUMP 0x10000000
> +
> +/* There is a special kind of actions called "extended actions",
> + * which need a value parameter. These have a local opcode located in
> + * the highest nibble, starting from 1. The rest of the bits
> + * are used to carry the value. These two parts together make
> + * a combined opcode.
> + */
> +#define __TC_ACT_EXT_SHIFT 28
> +#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
> +#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
> +#define TC_ACT_EXT_CMP(combined, opcode) \
> + (((combined) & (~TC_ACT_EXT_VAL_MASK)) == opcode)
> +
> +#define TC_ACT_JUMP __TC_ACT_EXT(1)
>
> /* Action type identifiers*/
> enum {
> diff --git a/net/sched/act_api.c b/net/sched/act_api.c
> index 7f2cd70..a90e8f3 100644
> --- a/net/sched/act_api.c
> +++ b/net/sched/act_api.c
> @@ -453,7 +453,7 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
> if (ret == TC_ACT_REPEAT)
> goto repeat; /* we need a ttl - JHS */
>
> - if (ret & TC_ACT_JUMP) {
> + if (TC_ACT_EXT_CMP(ret, TC_ACT_JUMP)) {
> jmp_prgcnt = ret & TCA_ACT_MAX_PRIO_MASK;
> if (!jmp_prgcnt || (jmp_prgcnt > nr_actions)) {
> /* faulty opcode, stop pipeline */
>
^ permalink raw reply
* pull request: bluetooth-next 2017-04-30
From: Johan Hedberg @ 2017-04-30 14:09 UTC (permalink / raw)
To: davem; +Cc: linux-bluetooth, netdev
[-- Attachment #1: Type: text/plain, Size: 2347 bytes --]
Hi Dave,
Here's one last batch of Bluetooth patches in the bluetooth-next tree
targeting the 4.12 kernel.
- Remove custom ECDH implementation and use new KPP API instead
- Add protocol checks to hci_ldisc
- Add module license to HCI UART Nokia H4+ driver
- Minor fix for 32bit user space - 64 bit kernel combination
Please let me know if there are any issues pulling. Thanks.
Johan
---
The following changes since commit e3a724edeec3836ed44675a6587a6db7b6b68dbe:
sparc64: Support cbcond instructions in eBPF JIT. (2017-04-24 15:56:21 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git for-upstream
for you to fetch changes up to 71653eb64bcca6110c42aadfd50b8d54d3a88079:
Bluetooth: Add selftest for ECDH key generation (2017-04-30 16:52:43 +0300)
----------------------------------------------------------------
Dean Jenkins (3):
Bluetooth: hci_ldisc: Add protocol check to hci_uart_send_frame()
Bluetooth: hci_ldisc: Add protocol check to hci_uart_dequeue()
Bluetooth: hci_ldisc: Add protocol check to hci_uart_tx_wakeup()
Frédéric Danis (1):
Bluetooth: Add module license for HCI UART Nokia H4+
Marcel Holtmann (2):
Bluetooth: zero kpp input for key generation
Bluetooth: Add selftest for ECDH key generation
Salvatore Benedetto (2):
Bluetooth: convert smp and selftest to crypto kpp API
Bluetooth: allocate data for kpp on heap
Szymon Janc (1):
Bluetooth: Fix user channel for 32bit userspace on 64bit kernel
drivers/bluetooth/hci_ldisc.c | 14 +-
drivers/bluetooth/hci_nokia.c | 7 +
net/bluetooth/Kconfig | 1 +
net/bluetooth/Makefile | 2 +-
net/bluetooth/ecc.c | 816 ------------------------------------------
net/bluetooth/ecc.h | 54 ---
net/bluetooth/ecdh_helper.c | 231 ++++++++++++
net/bluetooth/ecdh_helper.h | 27 ++
net/bluetooth/hci_sock.c | 3 +-
net/bluetooth/selftest.c | 28 +-
net/bluetooth/smp.c | 46 ++-
11 files changed, 342 insertions(+), 887 deletions(-)
delete mode 100644 net/bluetooth/ecc.c
delete mode 100644 net/bluetooth/ecc.h
create mode 100644 net/bluetooth/ecdh_helper.c
create mode 100644 net/bluetooth/ecdh_helper.h
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH iproute2 net-next] ip xfrm: Add xfrm state crypto offload
From: ilant @ 2017-04-30 14:16 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Steffen Klassert, netdev, Boris Pismenny, Ilan Tayari
From: Boris Pismenny <borisp@mellanox.com>
syntax:
ip xfrm state .... offload dev <if-name> dir <in or out>
Example to add inbound offload:
ip xfrm state .... offload dev mlx0 dir in
Example to add outbound offload:
ip xfrm state .... offload dev mlx0 dir out
Signed-off-by: Boris Pismenny <borisp@mellanox.com>
Signed-off-by: Ilan Tayari <ilant@mellanox.com>
---
ip/ipxfrm.c | 19 +++++++++++++++++++
ip/xfrm_state.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+)
diff --git a/ip/ipxfrm.c b/ip/ipxfrm.c
index b0cfac17..d5eb22e2 100644
--- a/ip/ipxfrm.c
+++ b/ip/ipxfrm.c
@@ -862,6 +862,25 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
}
fprintf(fp, "%s", _SL_);
}
+ if (tb[XFRMA_OFFLOAD_DEV]) {
+ struct xfrm_user_offload *xuo;
+
+ if (prefix)
+ fputs(prefix, fp);
+ fprintf(fp, "crypto offload parameters: ");
+
+ if (RTA_PAYLOAD(tb[XFRMA_OFFLOAD_DEV]) < sizeof(*xuo)) {
+ fprintf(fp, "(ERROR truncated)");
+ fprintf(fp, "%s", _SL_);
+ return;
+ }
+
+ xuo = (struct xfrm_user_offload *)
+ RTA_DATA(tb[XFRMA_OFFLOAD_DEV]);
+ fprintf(fp, "dev %s dir %s", ll_index_to_name(xuo->ifindex),
+ (xuo->flags & XFRM_OFFLOAD_INBOUND) ? "in" : "out");
+ fprintf(fp, "%s", _SL_);
+ }
}
static int xfrm_selector_iszero(struct xfrm_selector *s)
diff --git a/ip/xfrm_state.c b/ip/xfrm_state.c
index ea7d4f34..e11c93bf 100644
--- a/ip/xfrm_state.c
+++ b/ip/xfrm_state.c
@@ -60,6 +60,7 @@ static void usage(void)
fprintf(stderr, " [ replay-seq-hi SEQ ] [ replay-oseq-hi SEQ ]\n");
fprintf(stderr, " [ flag FLAG-LIST ] [ sel SELECTOR ] [ LIMIT-LIST ] [ encap ENCAP ]\n");
fprintf(stderr, " [ coa ADDR[/PLEN] ] [ ctx CTX ] [ extra-flag EXTRA-FLAG-LIST ]\n");
+ fprintf(stderr, " [ offload [dev DEV] dir DIR ]\n");
fprintf(stderr, "Usage: ip xfrm state allocspi ID [ mode MODE ] [ mark MARK [ mask MASK ] ]\n");
fprintf(stderr, " [ reqid REQID ] [ seq SEQ ] [ min SPI max SPI ]\n");
fprintf(stderr, "Usage: ip xfrm state { delete | get } ID [ mark MARK [ mask MASK ] ]\n");
@@ -108,6 +109,7 @@ static void usage(void)
fprintf(stderr, "LIMIT := { time-soft | time-hard | time-use-soft | time-use-hard } SECONDS |\n");
fprintf(stderr, " { byte-soft | byte-hard } SIZE | { packet-soft | packet-hard } COUNT\n");
fprintf(stderr, "ENCAP := { espinudp | espinudp-nonike } SPORT DPORT OADDR\n");
+ fprintf(stderr, "DIR := in | out\n");
exit(-1);
}
@@ -264,6 +266,24 @@ static int xfrm_state_extra_flag_parse(__u32 *extra_flags, int *argcp, char ***a
return 0;
}
+static int xfrm_offload_dir_parse(__u8 *dir, int *argcp, char ***argvp)
+{
+ int argc = *argcp;
+ char **argv = *argvp;
+
+ if (strcmp(*argv, "in") == 0)
+ *dir = XFRM_OFFLOAD_INBOUND;
+ else if (strcmp(*argv, "out") == 0)
+ *dir = 0;
+ else
+ invarg("DIR value is invalid", *argv);
+
+ *argcp = argc;
+ *argvp = argv;
+
+ return 0;
+}
+
static int xfrm_state_modify(int cmd, unsigned int flags, int argc, char **argv)
{
struct rtnl_handle rth;
@@ -283,6 +303,10 @@ static int xfrm_state_modify(int cmd, unsigned int flags, int argc, char **argv)
};
struct xfrm_replay_state replay = {};
struct xfrm_replay_state_esn replay_esn = {};
+ struct xfrm_user_offload xuo = {};
+ unsigned int ifindex = 0;
+ __u8 dir = 0;
+ bool is_offload = false;
__u32 replay_window = 0;
__u32 seq = 0, oseq = 0, seq_hi = 0, oseq_hi = 0;
char *idp = NULL;
@@ -394,6 +418,25 @@ static int xfrm_state_modify(int cmd, unsigned int flags, int argc, char **argv)
xfrm_sctx_parse((char *)&ctx.str, context, &ctx.sctx);
addattr_l(&req.n, sizeof(req.buf), XFRMA_SEC_CTX,
(void *)&ctx, ctx.sctx.len);
+ } else if (strcmp(*argv, "offload") == 0) {
+ is_offload = true;
+ NEXT_ARG();
+ if (strcmp(*argv, "dev") == 0) {
+ NEXT_ARG();
+ ifindex = ll_name_to_index(*argv);
+ if (!ifindex) {
+ invarg("value after \"offload dev\" is invalid", *argv);
+ is_offload = false;
+ }
+ NEXT_ARG();
+ }
+ if (strcmp(*argv, "dir") == 0) {
+ NEXT_ARG();
+ xfrm_offload_dir_parse(&dir, &argc, &argv);
+ } else {
+ invarg("value after \"offload dir\" is invalid", *argv);
+ is_offload = false;
+ }
} else {
/* try to assume ALGO */
int type = xfrm_algotype_getbyname(*argv);
@@ -531,6 +574,12 @@ static int xfrm_state_modify(int cmd, unsigned int flags, int argc, char **argv)
exit(-1);
}
+ if (is_offload) {
+ xuo.ifindex = ifindex;
+ xuo.flags = dir;
+ addattr_l(&req.n, sizeof(req.buf), XFRMA_OFFLOAD_DEV, &xuo,
+ sizeof(xuo));
+ }
if (req.xsinfo.flags & XFRM_STATE_ESN ||
replay_window > (sizeof(replay.bitmap) * 8)) {
replay_esn.seq = seq;
--
2.11.0
^ permalink raw reply related
* [PATCH net-next RFC 1/1] net netlink: Add new type NLA_FLAG_BITS
From: Jamal Hadi Salim @ 2017-04-30 14:28 UTC (permalink / raw)
To: davem; +Cc: netdev, jiri, xiyou.wangcong, Jamal Hadi Salim
From: Jamal Hadi Salim <jhs@mojatatu.com>
Generic bitflags attribute content sent to the kernel by user.
With this type the user can either set or unset a flag in the
kernel.
The nla_flag_values is a bitmap that defines the values being set
The nla_flag_selector is a bitmask that defines which value is legit
A check is made to ensure the rules that a kernel subsystem always
conforms to bitflags the kernel already knows about. Example
if the user tries to set a bit flag that is not understood then
the _it will be rejected_.
The user specifies the attribute policy as:
[ATTR_GOO] = { .type = NLA_FLAG_BITS, .validation_data = &myvalidflags },
where myvalidflags is the bit mask of the flags the kernel understands.
If the user _does not_ provide myvalidflags then the attribute will
also be rejected.
Examples:
nla_flag_values = 0x0, and nla_flag_selector = 0x1
implies we are selecting bit 1 and we want to set its value to 0.
nla_flag_values = 0x2, and nla_flag_selector = 0x2
implies we are selecting bit 2 and we want to set its value to 1.
This patch also provides an extra feature (which should be a separate
pach): a validation callback that could be speaciliazed for other types.
So a kernel subsystem could specify validation rules of the following
nature:
[ATTR_GOO] = { .type = MYTYPE,
.validation_data = &myvalidation_data,
.validate_content = mycontent_validator },
With validator callback looking like:
int mycontent_validator(const struct nlattr *nla, void *valid_data)
{
const struct myattribute *user_data = nla_data(nla);
struct myvalidation_struct *valid_data_constraint = valid_data;
... validate user_data against valid_data_constraint ...
... return appropriate error code etc ...
}
Only compile tested to float the idea.
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
include/net/netlink.h | 11 +++++++++++
include/uapi/linux/rtnetlink.h | 17 +++++++++++++++++
lib/nlattr.c | 25 +++++++++++++++++++++++++
3 files changed, 53 insertions(+)
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 0170917..8ab9784 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -6,6 +6,11 @@
#include <linux/jiffies.h>
#include <linux/in6.h>
+struct nla_bit_flags {
+ u32 nla_flag_values;
+ u32 nla_flag_selector;
+};
+
/* ========================================================================
* Netlink Messages and Attributes Interface (As Seen On TV)
* ------------------------------------------------------------------------
@@ -178,6 +183,7 @@ enum {
NLA_S16,
NLA_S32,
NLA_S64,
+ NLA_FLAG_BITS,
__NLA_TYPE_MAX,
};
@@ -206,6 +212,7 @@ enum {
* NLA_MSECS Leaving the length field zero will verify the
* given type fits, using it verifies minimum length
* just like "All other"
+ * NLA_FLAG_BITS A bitmap/bitselector attribute
* All other Minimum length of attribute payload
*
* Example:
@@ -213,11 +220,15 @@ enum {
* [ATTR_FOO] = { .type = NLA_U16 },
* [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ },
* [ATTR_BAZ] = { .len = sizeof(struct mystruct) },
+ * [ATTR_GOO] = { .type = NLA_FLAG_BITS, .validation_data = &myvalidflags },
* };
*/
struct nla_policy {
u16 type;
u16 len;
+ void *validation_data;
+ int (*validate_content)(const struct nlattr *nla,
+ const void *validation_data);
};
/**
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index cce0613..3691d8d 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -179,6 +179,23 @@ struct rtattr {
#define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
+/* Generic bitflags attribute content sent to the kernel.
+ *
+ * The nla_flag_values is a bitmap that defines the values being set
+ * The nla_flag_selector is a bitmask that defines which value is legit
+ *
+ * Examples:
+ * nla_flag_values = 0x0, and nla_flag_selector = 0x1
+ * implies we are selecting bit 1 and we want to set its value to 0.
+ *
+ * nla_flag_values = 0x2, and nla_flag_selector = 0x2
+ * implies we are selecting bit 2 and we want to set its value to 1.
+ *
+ */
+struct __nla_bit_flags {
+ __u32 nla_flag_values;
+ __u32 nla_flag_selector;
+};
diff --git a/lib/nlattr.c b/lib/nlattr.c
index a7e0b16..78fed43 100644
--- a/lib/nlattr.c
+++ b/lib/nlattr.c
@@ -27,6 +27,21 @@
[NLA_S64] = sizeof(s64),
};
+static int validate_nla_bit_flags(const struct nlattr *nla, void *valid_data)
+{
+ const struct nla_bit_flags *nbf = nla_data(nla);
+ u32 *valid_flags_mask = valid_data;
+
+ if (!valid_data)
+ return -EINVAL;
+
+
+ if (nbf->nla_flag_values & ~*valid_flags_mask)
+ return -EINVAL;
+
+ return 0;
+}
+
static int validate_nla(const struct nlattr *nla, int maxtype,
const struct nla_policy *policy)
{
@@ -46,6 +61,13 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
return -ERANGE;
break;
+ case NLA_FLAG_BITS:
+ if (attrlen != 8) /* 2 x 32 bits */
+ return -ERANGE;
+
+ return validate_nla_bit_flags(nla, pt->validation_data);
+ break;
+
case NLA_NUL_STRING:
if (pt->len)
minlen = min_t(int, attrlen, pt->len + 1);
@@ -103,6 +125,9 @@ static int validate_nla(const struct nlattr *nla, int maxtype,
return -ERANGE;
}
+ if (pt->validate_content)
+ return pt->validate_content(nla, pt->validation_data);
+
return 0;
}
--
1.9.1
^ permalink raw reply related
* Re: [PATCH/RFC net-next 0/4] net/sched: cls_flower: avoid false matching of truncated packets
From: Jamal Hadi Salim @ 2017-04-30 14:45 UTC (permalink / raw)
To: Simon Horman
Cc: Jiri Pirko, Cong Wang, Dinan Gunawardena, netdev, oss-drivers
In-Reply-To: <0e993860-4dfd-3562-5ccb-c5ad24e5f970@mojatatu.com>
On 17-04-30 09:51 AM, Jamal Hadi Salim wrote:
[..]
>> 1. As things stand, without this patch-set, flower does not differentiate
>> between a packet truncated at the end of the IP header and a packet
>> with
>> zero ports. Likewise for icmp type and code of zero.
>>
>> The first three patches of this series address that so that a match
>> for
>> port == zero only matches if ports are present in the packet. Again,
>> likewise for ICMP.
>>
>> This is a bug-fix to my way of thinking.
>>
>
> Agreed to bug fix. I would have said there is never a legit packet with
> TCP/UDP
Meant:
"never a legit packet with TCP/UDP port 0 on the wire".
cheers,
jamal
^ permalink raw reply
* Re: [PATCH 0/4] TI Bluetooth serdev support
From: Adam Ford @ 2017-04-30 15:14 UTC (permalink / raw)
To: Rob Herring
Cc: Marcel Holtmann, linux-bluetooth-u79uwXL29TY76Z2rM5mHXA,
Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA, Johan Hedberg,
Gustavo Padovan, Satish Patel, Wei Xu, Eyal Reizer,
netdev-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170405183005.20570-1-robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
On Wed, Apr 5, 2017 at 1:30 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> This series adds serdev support to the HCI LL protocol used on TI BT
> modules and enables support on HiKey board with with the WL1835 module.
> With this the custom TI UIM daemon and btattach are no longer needed.
Without UIM daemon, what instruction do you use to load the BT firmware?
I was thinking 'hciattach' but I was having trouble. I was hoping you
might have some insight.
hciattach -t 30 -s 115200 /dev/ttymxc1 texas 3000000 flow Just
returns a timeout.
I modified my i.MX6 device tree per the binding documentation and
setup the regulators and enable GPIO pins.
adam
>
> The series is available on this git branch[1]. Patch 2 is just clean-up
> and can be applied independently. Patch 3 is dependent on the series
> "Nokia H4+ support". I'd suggest both series are merged thru the BT tree.
>
> Rob
>
> [1] git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git ti-bluetooth
>
> Rob Herring (4):
> dt-bindings: net: Add TI WiLink shared transport binding
> bluetooth: hci_uart: remove unused hci_uart_init_tty
> bluetooth: hci_uart: add LL protocol serdev driver support
> arm64: dts: hikey: add WL1835 Bluetooth device node
>
> .../devicetree/bindings/net/ti,wilink-st.txt | 35 +++
> arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts | 5 +
> drivers/bluetooth/hci_ldisc.c | 19 --
> drivers/bluetooth/hci_ll.c | 261 ++++++++++++++++++++-
> drivers/bluetooth/hci_uart.h | 1 -
> 5 files changed, 300 insertions(+), 21 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/net/ti,wilink-st.txt
>
> --
> 2.10.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: assembler mnenomics for call/tailcall plus maps...
From: David Miller @ 2017-04-30 15:27 UTC (permalink / raw)
To: ast; +Cc: daniel, netdev, xdp-newbies
In-Reply-To: <c9ff0d0c-b91b-c3dc-654e-8b1c1a4c92f0@fb.com>
From: Alexei Starovoitov <ast@fb.com>
Date: Sat, 29 Apr 2017 23:35:30 -0700
> On 4/29/17 11:38 AM, David Miller wrote:
>> or, taking it one step further, do the following since we know this
>> maps to a 32-bit FD:
>>
>> mov32 r1, %map(hash_map)
>
> hence this approach won't work without serious elf loader hacks.
> The kernel needs to see ldimm64 because after it validated map_fd,
> it will store real 'struct bpf_map *' pointer into this ldimm64
> instruction and it will clear 'src_reg' markings.
I didn't see this part, now it all makes sense why ldimm64 is used
and I therefore think we should keep it this way.
> So from interpreter and from JITs point of view there are no
> special ldimm64 instructions. All ldimm64 are moving 64-bit
> constant into a register. It's only verifier that knows that
> some of these constants are real pointers.
>
>> In GCC it will be simple to get the backend to emit this, various
>> options exist. We can make it a special "__attribute__((map))", or
>> use address spaces to annotate the map object. And then when the
>> ldimm64 or whatever instruction is emitted, and it sees the symbol
>> referenced has this special type, it will emit "%%map(%s)" instead of
>> just "%s" for the symbol name in the asembler output.
>
> I like the %map(symbol) idea.
> I think it fits the whole thing quite well.
> Not sure though how gcc will know that it needs to emit %map(..)
I just explained it in that paragraph above :-)
struct bpf_map_def SEC("maps") jmp_table __attribute__((map)) = {
And when referenced by an instruction the bpf gcc backend can see that
the "map" attribute is set and emit the appropriate %map() string into
the assembler.
We can even make the special map attribute do the SEC("") part too.
> I take all the blame for not documenting this thing properly.
> The elf loader in samples/bpf/bpf_load.c should have been temporary.
> Its only purpose was to have minimal demo to parse elf and load it.
> I didn't expect the .o approach to come that far.
> My bet was on iovisor/bcc approach where elf file is never generated.
> C->bpf is compiled in memory and loaded into the kernel completely
> without elf and without relocations.
I think it is better to have real objects for introspection (even
after session is complete) and for testing under simulators (one of
which I plan to write).
And if we linked a real final static object, elf header would be all
that would be needed to find execution entry point.
^ permalink raw reply
* Re: [PATCH v3 binutils] Add BPF support to binutils...
From: David Miller @ 2017-04-30 15:28 UTC (permalink / raw)
To: ast; +Cc: daniel, aconole, netdev, xdp-newbies
In-Reply-To: <76ed19a7-add3-0642-4298-9402c7ff0be8@fb.com>
From: Alexei Starovoitov <ast@fb.com>
Date: Sat, 29 Apr 2017 23:44:59 -0700
> On 4/29/17 7:37 PM, David Miller wrote:
>> From: David Miller <davem@davemloft.net>
>> Date: Sat, 29 Apr 2017 22:24:50 -0400 (EDT)
>>
>>> Some of your bugs should be fixed by this patch below, I'll add
>>> test cases soon:
>>
>> Ok, here are all the local changes in my tree. I made the relocs
>> match LLVM and I fixed some dwarf debugging stuff.
>>
>> With this we are also down to one test case failure under binutils/
>> and it's something weird with merging 64-bit notes which I should be
>> able to fix soon.
>>
>> I can fix these bugs fast, keep reporting.
>>
>> BTW, should I just remove tailcall from the opcode table altogether?
>
> yeah. tailcall is not a special opcode from user space point of view.
> Only after normal call with func_id=bpf_tail_call passes verifier
> then verifier will change insn->code into CALL|X
> It's done only to have two 'case' statement in the interpreter,
> so that normal calls and tailcalls don't interfere.
> From user space pov CALL|X opcode is reserved and we can use it
> for something in the future. Just need to change interpeter and JITs.
>
>> case 'O':
>> - (*info->fprintf_func) (stream, "%d", off);
>> + (*info->fprintf_func) (stream, "%d", (int) off);
>
> tried this diff. It looks better
> 10: 7b 1a f8 ff 00 00 00 00 stdw [r1+-8], r10
> 18: 79 a1 f8 ff 00 00 00 00 lddw r10, [r1+-8]
> I wonder if '+' can be removed as well.
All disassemblers in binutils print it this way, sparc, x86, etc.
> '-g' still doesn't seem to work:
> /w/binutils-gdb/bld/binutils/objdump: invalid relocation type 10
> /w/binutils-gdb/bld/binutils/objdump: BFD (GNU Binutils)
> 2.28.51.20170429 assertion fail ../../bfd/elf64-bpf.c:139
> 0: 18 01 00 00 39 47 98 83 ldimm64 r0, 590618314553
Hmm, I defined a relocation type 10 in the patch, make sure BFD got
rebuilt properly...
I'll double check here too.
^ permalink raw reply
* Re: [PATCH v1 1/3] bnx2x: Replace custom scnprintf()
From: David Miller @ 2017-04-30 15:32 UTC (permalink / raw)
To: andy.shevchenko; +Cc: Yuval.Mintz, andriy.shevchenko, netdev, Ariel.Elior
In-Reply-To: <CAHp75VcitfXWzUsUDthAXp97yjQQnEGND7eqSH-AFRVjH6pYDg@mail.gmail.com>
From: Andy Shevchenko <andy.shevchenko@gmail.com>
Date: Sun, 30 Apr 2017 15:58:18 +0300
> On Sun, Apr 30, 2017 at 11:16 AM, Mintz, Yuval <Yuval.Mintz@cavium.com> wrote:
>>> From: Andy Shevchenko <andy.shevchenko@gmail.com>
>>>
>>> Use scnprintf() when printing version instead of custom open coded variants.
>>>
>>> Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
>>
>> Hi Andy this seems correct.
>> Was there a cover-letter for your series? I've failed to find it.
>
> There was none since patches are quite straight forward.
All patch series, regardless of how simple, should provide
a proper cover letter.
It is an essential part of all patch series.
^ permalink raw reply
* Re: [net-next 0/4][pull request] 1GbE Intel Wired LAN Driver Updates 2017-04-30
From: David Miller @ 2017-04-30 15:35 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, nhorman, sassmann, jogreene
In-Reply-To: <20170430123614.67897-1-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Sun, 30 Apr 2017 05:36:10 -0700
> This series contains updates to e1000e only.
>
> Jarod Wilson fixes an issue where the workaround for 82574 & 82583
> is needed for i218 as well, so set the appropriate flags.
>
> Sasha adds support for the upcoming new i219 devices for the client
> platform (CannonLake), which includes the support for 38.4MHz frequency
> to support PTP on CannonLake.
>
> The following are changes since commit c08bac03d2894113bdb114e66e6ada009defb120:
> Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue 1GbE
Pulled.
^ permalink raw reply
* Re: [net-next 00/13][pull request] 40GbE Intel Wired LAN Driver Updates 2017-04-30
From: David Miller @ 2017-04-30 15:36 UTC (permalink / raw)
To: jeffrey.t.kirsher; +Cc: netdev, nhorman, sassmann, jogreene
In-Reply-To: <20170430132451.68494-1-jeffrey.t.kirsher@intel.com>
From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Sun, 30 Apr 2017 06:24:38 -0700
> This series contains updates to i40e and i40evf only.
...
> The following are changes since commit c08bac03d2894113bdb114e66e6ada009defb120:
> Merge branch '10GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue
> and are available in the git repository at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue 40GbE
Also pulled, thanks Jeff.
^ permalink raw reply
* Re: [PATCH v3 binutils] Add BPF support to binutils...
From: David Miller @ 2017-04-30 15:40 UTC (permalink / raw)
To: ast; +Cc: daniel, aconole, netdev, xdp-newbies
In-Reply-To: <76ed19a7-add3-0642-4298-9402c7ff0be8@fb.com>
From: Alexei Starovoitov <ast@fb.com>
Date: Sat, 29 Apr 2017 23:44:59 -0700
> On 4/29/17 7:37 PM, David Miller wrote:
>> BTW, should I just remove tailcall from the opcode table altogether?
>
> yeah. tailcall is not a special opcode from user space point of view.
> Only after normal call with func_id=bpf_tail_call passes verifier
> then verifier will change insn->code into CALL|X
> It's done only to have two 'case' statement in the interpreter,
> so that normal calls and tailcalls don't interfere.
> From user space pov CALL|X opcode is reserved and we can use it
> for something in the future. Just need to change interpeter and JITs.
Ok, I've removed it from my tree.
Thanks.
^ permalink raw reply
* Re: [PATCH 0/4] TI Bluetooth serdev support
From: Sebastian Reichel @ 2017-04-30 16:04 UTC (permalink / raw)
To: Adam Ford
Cc: Mark Rutland, Rob Herring, Johan Hedberg, devicetree,
Gustavo Padovan, Marcel Holtmann, Wei Xu, linux-bluetooth,
Eyal Reizer, netdev, Satish Patel, linux-arm-kernel
In-Reply-To: <CAHCN7xJUxZm1qKAxT0kaK6qoDg+HWOJK7sTH-q9za4HJuUwe8Q@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 1160 bytes --]
Hi,
On Sun, Apr 30, 2017 at 10:14:20AM -0500, Adam Ford wrote:
> On Wed, Apr 5, 2017 at 1:30 PM, Rob Herring <robh@kernel.org> wrote:
> > This series adds serdev support to the HCI LL protocol used on TI BT
> > modules and enables support on HiKey board with with the WL1835 module.
> > With this the custom TI UIM daemon and btattach are no longer needed.
>
> Without UIM daemon, what instruction do you use to load the BT firmware?
>
> I was thinking 'hciattach' but I was having trouble. I was hoping you
> might have some insight.
>
> hciattach -t 30 -s 115200 /dev/ttymxc1 texas 3000000 flow Just
> returns a timeout.
>
> I modified my i.MX6 device tree per the binding documentation and
> setup the regulators and enable GPIO pins.
If you configured everything correctly no userspace interaction is
required. The driver should request the firmware automatically once
you power up the bluetooth device.
Apart from DT changes make sure, that the following options are
enabled and check dmesg for any hints.
CONFIG_SERIAL_DEV_BUS
CONFIG_SERIAL_DEV_CTRL_TTYPORT
CONFIG_BT_HCIUART
CONFIG_BT_HCIUART_LL
-- Sebastian
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 176 bytes --]
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v4 binutils] Add BPF support to binutils...
From: David Miller @ 2017-04-30 16:07 UTC (permalink / raw)
To: ast; +Cc: daniel, netdev, xdp-newbies
This is mainly a synchronization point, I still need to look
more deeply into Alexei's -g issue.
New in this version from v3:
- Remove tailcall from opcode table
- Rearrange relocations so that numbers match with LLVM ones
- Emit relocs properly so that dwarf2 debug info tests pass
- Handle negative load/store offsets properly, add tests
Signed-off-by: David S. Miller <davem@davemloft.net>
---
bfd/Makefile.am | 2 +
bfd/Makefile.in | 3 +
bfd/archures.c | 3 +
bfd/bfd-in2.h | 8 +
bfd/config.bfd | 6 +
bfd/configure | 2 +
bfd/configure.ac | 2 +
bfd/cpu-bpf.c | 41 +++
bfd/elf64-bpf.c | 159 ++++++++++
bfd/elf64-bpf.h | 24 ++
bfd/libbfd.h | 4 +
bfd/reloc.c | 11 +
bfd/targets.c | 5 +
binutils/readelf.c | 11 +
config.sub | 5 +-
gas/Makefile.am | 2 +
gas/Makefile.in | 17 ++
gas/config/tc-bpf.c | 639 ++++++++++++++++++++++++++++++++++++++++
gas/config/tc-bpf.h | 45 +++
gas/configure.tgt | 3 +
gas/testsuite/gas/bpf/arith.d | 61 ++++
gas/testsuite/gas/bpf/arith.s | 53 ++++
gas/testsuite/gas/bpf/atomics.d | 12 +
gas/testsuite/gas/bpf/atomics.s | 4 +
gas/testsuite/gas/bpf/bpf.exp | 28 ++
gas/testsuite/gas/bpf/call.d | 14 +
gas/testsuite/gas/bpf/call.s | 6 +
gas/testsuite/gas/bpf/imm64.d | 30 ++
gas/testsuite/gas/bpf/imm64.s | 12 +
gas/testsuite/gas/bpf/jump.d | 43 +++
gas/testsuite/gas/bpf/jump.s | 35 +++
gas/testsuite/gas/bpf/loads.d | 27 ++
gas/testsuite/gas/bpf/loads.s | 19 ++
gas/testsuite/gas/bpf/move.d | 19 ++
gas/testsuite/gas/bpf/move.s | 11 +
gas/testsuite/gas/bpf/stores.d | 21 ++
gas/testsuite/gas/bpf/stores.s | 13 +
gdb/bpf-tdep.c | 229 ++++++++++++++
gdb/bpf-tdep.h | 40 +++
gdb/configure.tgt | 4 +
include/dis-asm.h | 1 +
include/elf/bpf.h | 39 +++
include/opcode/bpf.h | 16 +
ld/Makefile.am | 4 +
ld/Makefile.in | 5 +
ld/configure.tgt | 2 +
ld/emulparams/elf64_bpf.sh | 8 +
opcodes/Makefile.am | 2 +
opcodes/bpf-dis.c | 161 ++++++++++
opcodes/bpf-opc.c | 147 +++++++++
opcodes/configure | 1 +
opcodes/configure.ac | 1 +
opcodes/disassemble.c | 6 +
sim/configure.tgt | 3 +
54 files changed, 2067 insertions(+), 2 deletions(-)
create mode 100644 bfd/cpu-bpf.c
create mode 100644 bfd/elf64-bpf.c
create mode 100644 bfd/elf64-bpf.h
create mode 100644 gas/config/tc-bpf.c
create mode 100644 gas/config/tc-bpf.h
create mode 100644 gas/testsuite/gas/bpf/arith.d
create mode 100644 gas/testsuite/gas/bpf/arith.s
create mode 100644 gas/testsuite/gas/bpf/atomics.d
create mode 100644 gas/testsuite/gas/bpf/atomics.s
create mode 100644 gas/testsuite/gas/bpf/bpf.exp
create mode 100644 gas/testsuite/gas/bpf/call.d
create mode 100644 gas/testsuite/gas/bpf/call.s
create mode 100644 gas/testsuite/gas/bpf/imm64.d
create mode 100644 gas/testsuite/gas/bpf/imm64.s
create mode 100644 gas/testsuite/gas/bpf/jump.d
create mode 100644 gas/testsuite/gas/bpf/jump.s
create mode 100644 gas/testsuite/gas/bpf/loads.d
create mode 100644 gas/testsuite/gas/bpf/loads.s
create mode 100644 gas/testsuite/gas/bpf/move.d
create mode 100644 gas/testsuite/gas/bpf/move.s
create mode 100644 gas/testsuite/gas/bpf/stores.d
create mode 100644 gas/testsuite/gas/bpf/stores.s
create mode 100644 gdb/bpf-tdep.c
create mode 100644 gdb/bpf-tdep.h
create mode 100644 include/elf/bpf.h
create mode 100644 include/opcode/bpf.h
create mode 100644 ld/emulparams/elf64_bpf.sh
create mode 100644 opcodes/bpf-dis.c
create mode 100644 opcodes/bpf-opc.c
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 97b608c..911655a 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -95,6 +95,7 @@ ALL_MACHINES = \
cpu-arm.lo \
cpu-avr.lo \
cpu-bfin.lo \
+ cpu-bpf.lo \
cpu-cr16.lo \
cpu-cr16c.lo \
cpu-cris.lo \
@@ -185,6 +186,7 @@ ALL_MACHINES_CFILES = \
cpu-arm.c \
cpu-avr.c \
cpu-bfin.c \
+ cpu-bpf.c \
cpu-cr16.c \
cpu-cr16c.c \
cpu-cris.c \
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index e48abaf..930aa09 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -428,6 +428,7 @@ ALL_MACHINES = \
cpu-arm.lo \
cpu-avr.lo \
cpu-bfin.lo \
+ cpu-bpf.lo \
cpu-cr16.lo \
cpu-cr16c.lo \
cpu-cris.lo \
@@ -518,6 +519,7 @@ ALL_MACHINES_CFILES = \
cpu-arm.c \
cpu-avr.c \
cpu-bfin.c \
+ cpu-bpf.c \
cpu-cr16.c \
cpu-cr16c.c \
cpu-cris.c \
@@ -1380,6 +1382,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-avr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-bfin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-bpf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-cr16.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-cr16c.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-cris.Plo@am__quote@
diff --git a/bfd/archures.c b/bfd/archures.c
index c6e7152..f096d73 100644
--- a/bfd/archures.c
+++ b/bfd/archures.c
@@ -447,6 +447,8 @@ DESCRIPTION
.#define bfd_mach_avrxmega7 107
. bfd_arch_bfin, {* ADI Blackfin *}
.#define bfd_mach_bfin 1
+. bfd_arch_bpf, {* eBPF *}
+.#define bfd_mach_bpf 1
. bfd_arch_cr16, {* National Semiconductor CompactRISC (ie CR16). *}
.#define bfd_mach_cr16 1
. bfd_arch_cr16c, {* National Semiconductor CompactRISC. *}
@@ -582,6 +584,7 @@ extern const bfd_arch_info_type bfd_arc_arch;
extern const bfd_arch_info_type bfd_arm_arch;
extern const bfd_arch_info_type bfd_avr_arch;
extern const bfd_arch_info_type bfd_bfin_arch;
+extern const bfd_arch_info_type bfd_bpf_arch;
extern const bfd_arch_info_type bfd_cr16_arch;
extern const bfd_arch_info_type bfd_cr16c_arch;
extern const bfd_arch_info_type bfd_cris_arch;
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 17a35c0..6d44534 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2304,6 +2304,8 @@ enum bfd_architecture
#define bfd_mach_avrxmega7 107
bfd_arch_bfin, /* ADI Blackfin */
#define bfd_mach_bfin 1
+ bfd_arch_bpf, /* eBPF */
+#define bfd_mach_bpf 1
bfd_arch_cr16, /* National Semiconductor CompactRISC (ie CR16). */
#define bfd_mach_cr16 1
bfd_arch_cr16c, /* National Semiconductor CompactRISC. */
@@ -3910,6 +3912,12 @@ pc-relative or some form of GOT-indirect relocation. */
/* ADI Blackfin arithmetic relocation. */
BFD_ARELOC_BFIN_ADDR,
+/* BPF relocations */
+ BFD_RELOC_BPF_16,
+ BFD_RELOC_BPF_32,
+ BFD_RELOC_BPF_64,
+ BFD_RELOC_BPF_WDISP16,
+
/* Mitsubishi D10V relocs.
This is a 10-bit reloc with the right 2 bits
assumed to be 0. */
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 151de95..f6d90cd 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -161,6 +161,7 @@ am33_2.0*) targ_archs=bfd_mn10300_arch ;;
arc*) targ_archs=bfd_arc_arch ;;
arm*) targ_archs=bfd_arm_arch ;;
bfin*) targ_archs=bfd_bfin_arch ;;
+bpf*) targ_archs=bfd_bpf_arch ;;
c30*) targ_archs=bfd_tic30_arch ;;
c4x*) targ_archs=bfd_tic4x_arch ;;
c54x*) targ_archs=bfd_tic54x_arch ;;
@@ -471,6 +472,11 @@ case "${targ}" in
targ_underscore=yes
;;
+ bpf-*-*)
+ targ_defvec=bpf_elf64_be_vec
+ targ_selvecs=bpf_elf64_le_vec
+ ;;
+
c30-*-*aout* | tic30-*-*aout*)
targ_defvec=tic30_aout_vec
;;
diff --git a/bfd/configure b/bfd/configure
index 24e3e2f..2a5ba40 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -14298,6 +14298,8 @@ do
avr_elf32_vec) tb="$tb elf32-avr.lo elf32.lo $elf" ;;
bfin_elf32_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
bfin_elf32_fdpic_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
+ bpf_elf64_le_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;;
+ bpf_elf64_be_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;;
bout_be_vec) tb="$tb bout.lo aout32.lo" ;;
bout_le_vec) tb="$tb bout.lo aout32.lo" ;;
cr16_elf32_vec) tb="$tb elf32-cr16.lo elf32.lo $elf" ;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index e568847..0dd7139 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -429,6 +429,8 @@ do
avr_elf32_vec) tb="$tb elf32-avr.lo elf32.lo $elf" ;;
bfin_elf32_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
bfin_elf32_fdpic_vec) tb="$tb elf32-bfin.lo elf32.lo $elf" ;;
+ bpf_elf64_le_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;;
+ bpf_elf64_be_vec) tb="$tb elf64-bpf.lo elf64.lo $elf" ;;
bout_be_vec) tb="$tb bout.lo aout32.lo" ;;
bout_le_vec) tb="$tb bout.lo aout32.lo" ;;
cr16_elf32_vec) tb="$tb elf32-cr16.lo elf32.lo $elf" ;;
diff --git a/bfd/cpu-bpf.c b/bfd/cpu-bpf.c
new file mode 100644
index 0000000..551e42e
--- /dev/null
+++ b/bfd/cpu-bpf.c
@@ -0,0 +1,41 @@
+/* BFD Support for the eBPF.
+
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_bpf_arch =
+ {
+ 64, /* Bits in a word. */
+ 64, /* Bits in an address. */
+ 8, /* Bits in a byte. */
+ bfd_arch_bpf,
+ 0, /* Only one machine. */
+ "bpf", /* Arch name. */
+ "bpf", /* Arch printable name. */
+ 3, /* Section align power. */
+ TRUE, /* The one and only. */
+ bfd_default_compatible,
+ bfd_default_scan,
+ bfd_arch_default_fill,
+ 0,
+ };
diff --git a/bfd/elf64-bpf.c b/bfd/elf64-bpf.c
new file mode 100644
index 0000000..a42f768
--- /dev/null
+++ b/bfd/elf64-bpf.c
@@ -0,0 +1,159 @@
+#include "sysdep.h"
+#include "bfd.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "libiberty.h"
+#include "elf-bfd.h"
+#include "elf/bpf.h"
+#include "opcode/bpf.h"
+#include "objalloc.h"
+#include "elf64-bpf.h"
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */
+#define MINUS_ONE (~ (bfd_vma) 0)
+
+static reloc_howto_type _bfd_bpf_elf_howto_table[] =
+{
+ HOWTO(R_BPF_NONE, 0,3, 0,FALSE,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_BPF_NONE", FALSE,0,0x00000000,TRUE),
+
+ /* XXX these are wrong XXX */
+ HOWTO(R_BPF_INSN_64, 0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_BPF_INSN_64", FALSE,0,MINUS_ONE,TRUE),
+ HOWTO(R_BPF_INSN_32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_BPF_INSN_32", FALSE,0,0xffffffff,TRUE),
+ HOWTO(R_BPF_INSN_16, 0,1,16,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_BPF_INSN_16", FALSE,0,0x0000ffff,TRUE),
+ HOWTO(R_BPF_WDISP16, 0,1,16,TRUE, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_BPF_WDISP16", FALSE,0,0x0000ffff,TRUE),
+
+ EMPTY_HOWTO(5),
+ EMPTY_HOWTO(6),
+ EMPTY_HOWTO(7),
+ HOWTO(R_BPF_DATA_8, 0,0, 8,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_BPF_DATA_8", FALSE,0,0x000000ff,TRUE),
+ HOWTO(R_BPF_DATA_16, 0,1,16,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_BPF_DATA_16", FALSE,0,0x0000ffff,TRUE),
+ HOWTO(R_BPF_DATA_32, 0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_BPF_DATA_32", FALSE,0,0xffffffff,TRUE),
+ HOWTO(R_BPF_DATA_64, 0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_BPF_DATA_64", FALSE,0,MINUS_ONE,TRUE),
+};
+
+reloc_howto_type *
+_bfd_bpf_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type code)
+{
+ switch (code)
+ {
+ case BFD_RELOC_NONE:
+ return &_bfd_bpf_elf_howto_table[R_BPF_NONE];
+
+ case BFD_RELOC_BPF_WDISP16:
+ return &_bfd_bpf_elf_howto_table[R_BPF_WDISP16];
+
+ case BFD_RELOC_BPF_16:
+ return &_bfd_bpf_elf_howto_table[R_BPF_INSN_16];
+
+ case BFD_RELOC_BPF_32:
+ return &_bfd_bpf_elf_howto_table[R_BPF_INSN_32];
+
+ case BFD_RELOC_BPF_64:
+ return &_bfd_bpf_elf_howto_table[R_BPF_INSN_64];
+
+ case BFD_RELOC_8:
+ return &_bfd_bpf_elf_howto_table[R_BPF_DATA_8];
+
+ case BFD_RELOC_16:
+ return &_bfd_bpf_elf_howto_table[R_BPF_DATA_16];
+
+ case BFD_RELOC_32:
+ return &_bfd_bpf_elf_howto_table[R_BPF_DATA_32];
+
+ case BFD_RELOC_64:
+ return &_bfd_bpf_elf_howto_table[R_BPF_DATA_64];
+
+ default:
+ break;
+ }
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+}
+
+reloc_howto_type *
+_bfd_bpf_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < (sizeof (_bfd_bpf_elf_howto_table)
+ / sizeof (_bfd_bpf_elf_howto_table[0]));
+ i++)
+ if (_bfd_bpf_elf_howto_table[i].name != NULL
+ && strcasecmp (_bfd_bpf_elf_howto_table[i].name, r_name) == 0)
+ return &_bfd_bpf_elf_howto_table[i];
+
+ return NULL;
+}
+
+static void
+check_for_relocs (bfd * abfd, asection * o, void * failed)
+{
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ Elf_Internal_Ehdr *ehdrp;
+
+ ehdrp = elf_elfheader (abfd);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%B: Relocations in generic ELF (EM: %d)"),
+ abfd, ehdrp->e_machine);
+
+ bfd_set_error (bfd_error_wrong_format);
+ * (bfd_boolean *) failed = TRUE;
+ }
+}
+
+static bfd_boolean
+elf64_generic_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
+{
+ bfd_boolean failed = FALSE;
+
+ /* Check if there are any relocations. */
+ bfd_map_over_sections (abfd, check_for_relocs, & failed);
+
+ if (failed)
+ return FALSE;
+ return bfd_elf_link_add_symbols (abfd, info);
+}
+
+static reloc_howto_type *
+elf_bpf_rtype_to_howto (unsigned int r_type)
+{
+ if (r_type >= (unsigned int) R_BPF_max)
+ {
+ _bfd_error_handler (_("invalid relocation type %d"), (int) r_type);
+ r_type = R_BPF_NONE;
+ }
+ return &_bfd_bpf_elf_howto_table[r_type];
+}
+
+/* Given a bpf ELF reloc type, fill in an arelent structure. */
+
+static void
+elf_bpf_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
+ Elf_Internal_Rela *dst)
+{
+ unsigned r_type;
+
+ r_type = ELF64_R_TYPE (dst->r_info);
+ cache_ptr->howto = elf_bpf_rtype_to_howto (r_type);
+ BFD_ASSERT (r_type == cache_ptr->howto->type);
+}
+
+#define TARGET_LITTLE_SYM bpf_elf64_le_vec
+#define TARGET_LITTLE_NAME "elf64-bpfle"
+#define TARGET_BIG_SYM bpf_elf64_be_vec
+#define TARGET_BIG_NAME "elf64-bpfbe"
+#define ELF_ARCH bfd_arch_bpf
+#define ELF_MAXPAGESIZE 0x100000
+#define ELF_MACHINE_CODE EM_BPF
+
+#define elf_info_to_howto elf_bpf_info_to_howto
+
+#define bfd_elf64_bfd_reloc_type_lookup _bfd_bpf_elf_reloc_type_lookup
+#define bfd_elf64_bfd_reloc_name_lookup _bfd_bpf_elf_reloc_name_lookup
+#define bfd_elf64_bfd_link_add_symbols elf64_generic_link_add_symbols
+
+#include "elf64-target.h"
diff --git a/bfd/elf64-bpf.h b/bfd/elf64-bpf.h
new file mode 100644
index 0000000..f435e2e
--- /dev/null
+++ b/bfd/elf64-bpf.h
@@ -0,0 +1,24 @@
+/* BPF ELF specific backend routines.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+extern reloc_howto_type *_bfd_bpf_elf_reloc_type_lookup
+ (bfd *, bfd_reloc_code_real_type);
+extern reloc_howto_type *_bfd_bpf_elf_reloc_name_lookup
+ (bfd *, const char *);
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 8bac650..1a3001d 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1794,6 +1794,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_ARELOC_BFIN_PAGE",
"BFD_ARELOC_BFIN_HWPAGE",
"BFD_ARELOC_BFIN_ADDR",
+ "BFD_RELOC_BPF_16",
+ "BFD_RELOC_BPF_32",
+ "BFD_RELOC_BPF_64",
+ "BFD_RELOC_BPF_WDISP16",
"BFD_RELOC_D10V_10_PCREL_R",
"BFD_RELOC_D10V_10_PCREL_L",
"BFD_RELOC_D10V_18",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 9a04022..4100caf 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -3854,6 +3854,17 @@ ENUMDOC
ADI Blackfin arithmetic relocation.
ENUM
+ BFD_RELOC_BPF_16
+ENUMX
+ BFD_RELOC_BPF_32
+ENUMX
+ BFD_RELOC_BPF_64
+ENUMX
+ BFD_RELOC_BPF_WDISP16
+ENUMDOC
+ BPF relocations
+
+ENUM
BFD_RELOC_D10V_10_PCREL_R
ENUMDOC
Mitsubishi D10V relocs.
diff --git a/bfd/targets.c b/bfd/targets.c
index 5841e8d..c38c4fb 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -619,6 +619,8 @@ extern const bfd_target arm_pei_wince_le_vec;
extern const bfd_target avr_elf32_vec;
extern const bfd_target bfin_elf32_vec;
extern const bfd_target bfin_elf32_fdpic_vec;
+extern const bfd_target bpf_elf64_le_vec;
+extern const bfd_target bpf_elf64_be_vec;
extern const bfd_target bout_be_vec;
extern const bfd_target bout_le_vec;
extern const bfd_target cr16_elf32_vec;
@@ -1029,6 +1031,9 @@ static const bfd_target * const _bfd_target_vector[] =
&bfin_elf32_vec,
&bfin_elf32_fdpic_vec,
+ &bpf_elf64_le_vec,
+ &bpf_elf64_be_vec,
+
&bout_be_vec,
&bout_le_vec,
diff --git a/binutils/readelf.c b/binutils/readelf.c
index b57e1e0..b4013fb 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -95,6 +95,7 @@
#include "elf/arm.h"
#include "elf/avr.h"
#include "elf/bfin.h"
+#include "elf/bpf.h"
#include "elf/cr16.h"
#include "elf/cris.h"
#include "elf/crx.h"
@@ -746,6 +747,7 @@ guess_is_rela (unsigned int e_machine)
case EM_AVR:
case EM_AVR_OLD:
case EM_BLACKFIN:
+ case EM_BPF:
case EM_CR16:
case EM_CRIS:
case EM_CRX:
@@ -1458,6 +1460,10 @@ dump_relocations (FILE * file,
rtype = elf_bfin_reloc_type (type);
break;
+ case EM_BPF:
+ rtype = elf_bpf_reloc_type (type);
+ break;
+
case EM_CYGNUS_MEP:
rtype = elf_mep_reloc_type (type);
break;
@@ -12006,6 +12012,8 @@ is_32bit_abs_reloc (unsigned int reloc_type)
return reloc_type == 1;
case EM_BLACKFIN:
return reloc_type == 0x12; /* R_byte4_data. */
+ case EM_BPF:
+ return reloc_type == 10; /* R_BPF_DATA_32 */
case EM_CRIS:
return reloc_type == 3; /* R_CRIS_32. */
case EM_CR16:
@@ -12245,6 +12253,8 @@ is_64bit_abs_reloc (unsigned int reloc_type)
return reloc_type == 257; /* R_AARCH64_ABS64. */
case EM_ALPHA:
return reloc_type == 2; /* R_ALPHA_REFQUAD. */
+ case EM_BPF:
+ return reloc_type == 11; /* R_BPF_DATA_64 */
case EM_IA_64:
return reloc_type == 0x27; /* R_IA64_DIR64LSB. */
case EM_PARISC:
@@ -12411,6 +12421,7 @@ is_none_reloc (unsigned int reloc_type)
case EM_ARC_COMPACT2: /* R_ARC_NONE. */
case EM_ARC_COMPACT: /* R_ARC_NONE. */
case EM_ARM: /* R_ARM_NONE. */
+ case EM_BPF: /* R_BPF_NONE. */
case EM_C166: /* R_XC16X_NONE. */
case EM_CRIS: /* R_CRIS_NONE. */
case EM_FT32: /* R_FT32_NONE. */
diff --git a/config.sub b/config.sub
index 40ea5df..942989e 100755
--- a/config.sub
+++ b/config.sub
@@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2017 Free Software Foundation, Inc.
-timestamp='2017-04-02'
+timestamp='2017-04-25'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -257,6 +257,7 @@ case $basic_machine in
| ba \
| be32 | be64 \
| bfin \
+ | bpf \
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
| e2k | epiphany \
@@ -380,7 +381,7 @@ case $basic_machine in
| avr-* | avr32-* \
| ba-* \
| be32-* | be64-* \
- | bfin-* | bs2000-* \
+ | bfin-* | bpf-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
diff --git a/gas/Makefile.am b/gas/Makefile.am
index c9f9de0..bfd6ed9 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -135,6 +135,7 @@ TARGET_CPU_CFILES = \
config/tc-arm.c \
config/tc-avr.c \
config/tc-bfin.c \
+ config/tc-bpf.c \
config/tc-cr16.c \
config/tc-cris.c \
config/tc-crx.c \
@@ -212,6 +213,7 @@ TARGET_CPU_HFILES = \
config/tc-arm.h \
config/tc-avr.h \
config/tc-bfin.h \
+ config/tc-bpf.h \
config/tc-cr16.h \
config/tc-cris.h \
config/tc-crx.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index 1927de5..ee62f1a 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -431,6 +431,7 @@ TARGET_CPU_CFILES = \
config/tc-arm.c \
config/tc-avr.c \
config/tc-bfin.c \
+ config/tc-bpf.c \
config/tc-cr16.c \
config/tc-cris.c \
config/tc-crx.c \
@@ -508,6 +509,7 @@ TARGET_CPU_HFILES = \
config/tc-arm.h \
config/tc-avr.h \
config/tc-bfin.h \
+ config/tc-bpf.h \
config/tc-cr16.h \
config/tc-cris.h \
config/tc-crx.h \
@@ -868,6 +870,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-arm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-avr.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-bfin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-bpf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-cr16.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-cris.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-crx.Po@am__quote@
@@ -1045,6 +1048,20 @@ tc-bfin.obj: config/tc-bfin.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-bfin.obj `if test -f 'config/tc-bfin.c'; then $(CYGPATH_W) 'config/tc-bfin.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-bfin.c'; fi`
+tc-bpf.o: config/tc-bpf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-bpf.o -MD -MP -MF $(DEPDIR)/tc-bpf.Tpo -c -o tc-bpf.o `test -f 'config/tc-bpf.c' || echo '$(srcdir)/'`config/tc-bpf.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-bpf.Tpo $(DEPDIR)/tc-bpf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-bpf.c' object='tc-bpf.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-bpf.o `test -f 'config/tc-bpf.c' || echo '$(srcdir)/'`config/tc-bpf.c
+
+tc-bpf.obj: config/tc-bpf.c
+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-bpf.obj -MD -MP -MF $(DEPDIR)/tc-bpf.Tpo -c -o tc-bpf.obj `if test -f 'config/tc-bpf.c'; then $(CYGPATH_W) 'config/tc-bpf.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-bpf.c'; fi`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-bpf.Tpo $(DEPDIR)/tc-bpf.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-bpf.c' object='tc-bpf.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-bpf.obj `if test -f 'config/tc-bpf.c'; then $(CYGPATH_W) 'config/tc-bpf.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-bpf.c'; fi`
+
tc-cr16.o: config/tc-cr16.c
@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-cr16.o -MD -MP -MF $(DEPDIR)/tc-cr16.Tpo -c -o tc-cr16.o `test -f 'config/tc-cr16.c' || echo '$(srcdir)/'`config/tc-cr16.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-cr16.Tpo $(DEPDIR)/tc-cr16.Po
diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c
new file mode 100644
index 0000000..36393b7
--- /dev/null
+++ b/gas/config/tc-bpf.c
@@ -0,0 +1,639 @@
+/* tc-bpf.c -- Assemble for the SPARC
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GAS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#include "as.h"
+#include "safe-ctype.h"
+#include "subsegs.h"
+#include "opcode/bpf.h"
+#ifdef OBJ_ELF
+#include "elf/bpf.h"
+#include "dwarf2dbg.h"
+#endif
+
+const pseudo_typeS md_pseudo_table[] =
+{
+ {"align", s_align_bytes, 0}, /* Defaulting is invalid (0). */
+ {"global", s_globl, 0},
+ {"half", cons, 2},
+ {"skip", s_space, 0},
+ {"word", cons, 4},
+ {"xword", cons, 8},
+ {NULL, 0, 0},
+};
+
+const char comment_chars[] = "!";
+const char line_comment_chars[] = "#";
+const char line_separator_chars[] = ";";
+const char EXP_CHARS[] = "eE";
+const char FLT_CHARS[] = "rRsSfFdDxXpP";
+
+const char *md_shortopts = "V";
+struct option md_longopts[] =
+{
+#define OPTION_LITTLE_ENDIAN (OPTION_MD_BASE + 8)
+ {"EL", no_argument, NULL, OPTION_LITTLE_ENDIAN},
+#define OPTION_BIG_ENDIAN (OPTION_MD_BASE + 9)
+ {"EB", no_argument, NULL, OPTION_BIG_ENDIAN},
+ { NULL, no_argument, NULL, 0 },
+};
+size_t md_longopts_size = sizeof (md_longopts);
+
+/* Whether or not, we've set target_big_endian. */
+static int set_target_endian = 0;
+
+int
+md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
+{
+ switch (c)
+ {
+ case OPTION_LITTLE_ENDIAN:
+ target_big_endian = 0;
+ set_target_endian = 1;
+ break;
+ case OPTION_BIG_ENDIAN:
+ target_big_endian = 1;
+ set_target_endian = 1;
+ break;
+ case 'V':
+ print_version_id ();
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+void
+md_show_usage (FILE *stream)
+{
+ fprintf (stream, _("BPF options:\n"));
+}
+
+/* Handle of the OPCODE hash table. */
+static struct hash_control *op_hash;
+
+void
+md_begin (void)
+{
+ const char *retval = NULL;
+ unsigned int i = 0;
+ int lose = 0;
+
+ op_hash = hash_new ();
+ while (i < (unsigned int) bpf_num_opcodes)
+ {
+ const char *name = bpf_opcodes[i].name;
+ retval = hash_insert (op_hash, name, (void *) &bpf_opcodes[i]);
+ if (retval != NULL)
+ {
+ as_bad (_("Internal error: can't hash `%s': %s\n"),
+ bpf_opcodes[i].name, retval);
+ lose = 1;
+ }
+ do
+ {
+ ++i;
+ }
+ while (i < (unsigned int) bpf_num_opcodes
+ && !strcmp (bpf_opcodes[i].name, name));
+ }
+ if (lose)
+ as_fatal (_("Broken assembler. No assembly attempted."));
+
+ if (!set_target_endian)
+ {
+ /* Default to host endianness. */
+#ifdef WORDS_BIGENDIAN
+ target_big_endian = 1;
+#else
+ target_big_endian = 0;
+#endif
+ set_target_endian = 1;
+ }
+}
+
+const char *
+bpf_target_format (void)
+{
+ return target_big_endian ? "elf64-bpfbe" : "elf64-bpfle";
+}
+
+struct bpf_it
+ {
+ const char *error;
+ valueT opcode;
+ valueT high64;
+ expressionS exp;
+ int pcrel;
+ int imm64;
+ bfd_reloc_code_real_type reloc;
+ };
+
+/* Subroutine of md_assemble to output one insn. */
+
+static void
+output_insn (struct bpf_it *theinsn)
+{
+ valueT opc = theinsn->opcode;
+ char *toP = frag_more (theinsn->imm64 ? 16 : 8);
+ char code, regs;
+
+ code = opc >> (64 - 8);
+ regs = opc >> (64 - (8 + 8));
+
+ toP[0] = code;
+ toP[1] = regs;
+
+ /* Put out the opcode. */
+ if (target_big_endian)
+ {
+ number_to_chars_bigendian (toP + 2, opc >> 32, 2);
+ number_to_chars_bigendian (toP + 4, opc, 4);
+ }
+ else
+ {
+ number_to_chars_littleendian (toP + 2, opc >> 32, 2);
+ number_to_chars_littleendian (toP + 4, opc, 4);
+ }
+
+ if (theinsn->imm64)
+ {
+ toP[8] = 0;
+ toP[9] = 0;
+ toP[10] = 0;
+ toP[11] = 0;
+ if (target_big_endian)
+ {
+ number_to_chars_bigendian (toP + 12, theinsn->high64, 4);
+ }
+ else
+ {
+ number_to_chars_littleendian (toP + 12, theinsn->high64, 4);
+ }
+ }
+
+ /* Put out the symbol-dependent stuff. */
+ if (theinsn->reloc != BFD_RELOC_NONE)
+ {
+ fixS *fixP = fix_new_exp (frag_now, /* Which frag. */
+ (toP - frag_now->fr_literal), /* Where. */
+ 4, /* Size. */
+ &theinsn->exp,
+ theinsn->pcrel,
+ theinsn->reloc);
+ /* Turn off overflow checking in fixup_segment. We'll do our
+ own overflow checking in md_apply_fix. This is necessary because
+ the insn size is 4 and fixup_segment will signal an overflow for
+ large 8 byte quantities. */
+ fixP->fx_no_overflow = 1;
+ }
+
+#ifdef OBJ_ELF
+ dwarf2_emit_insn (8);
+#endif
+}
+
+static struct bpf_it the_insn;
+static char *expr_end;
+
+static int
+get_expression (char *str, expressionS *exp)
+{
+ char *save_in;
+ segT seg;
+
+ save_in = input_line_pointer;
+ input_line_pointer = str;
+ seg = expression (exp);
+ if (seg != absolute_section
+ && seg != text_section
+ && seg != data_section
+ && seg != bss_section
+ && seg != undefined_section)
+ {
+ the_insn.error = _("bad segment");
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 1;
+ }
+ expr_end = input_line_pointer;
+ input_line_pointer = save_in;
+ return 0;
+}
+
+void
+md_assemble (char *str ATTRIBUTE_UNUSED)
+{
+ const struct bpf_opcode *insn;
+ const char *args;
+ char *argsStart;
+ int match = 0;
+ valueT mask;
+ char *s, c;
+
+ s = str;
+ if (ISLOWER (*s))
+ {
+ do
+ ++s;
+ while (ISLOWER (*s) || ISDIGIT (*s) || *s == '_');
+ }
+
+ switch (*s)
+ {
+ case '\0':
+ break;
+
+ case ' ':
+ *s++ = '\0';
+ break;
+
+ default:
+ as_bad (_("Unknown opcode: `%s'"), str);
+ return;
+ }
+ insn = (struct bpf_opcode *) hash_find (op_hash, str);
+
+ if (insn == NULL)
+ {
+ as_bad (_("Unknown opcode: `%s'"), str);
+ return;
+ }
+
+ argsStart = s;
+ for (;;)
+ {
+ memset (&the_insn, '\0', sizeof (the_insn));
+ the_insn.reloc = BFD_RELOC_NONE;
+ the_insn.opcode = ((valueT)insn->code << 56);
+
+ for (args = insn->args;; args++)
+ {
+ switch (*args)
+ {
+ case '+':
+ if (*s == '+')
+ {
+ ++s;
+ continue;
+ }
+ if (*s == '-')
+ continue;
+ break;
+ case ',':
+ case '[':
+ case ']':
+ if (*s++ == *args)
+ continue;
+ break;
+ case '1':
+ if (*s++ == 'r')
+ {
+ if (!ISDIGIT ((c = *s++)))
+ {
+ goto error;
+ }
+ c -= '0';
+ mask = c;
+ if (ISDIGIT (*s))
+ {
+ c = *s++;
+ if (c != '0' || mask != 1)
+ goto error;
+ mask = 10;
+ }
+ the_insn.opcode |= (mask << 52);
+ continue;
+ }
+ break;
+ case '2':
+ if (*s++ == 'r')
+ {
+ if (!ISDIGIT ((c = *s++)))
+ {
+ goto error;
+ }
+ c -= '0';
+ mask = c;
+ if (ISDIGIT (*s))
+ {
+ c = *s++;
+ if (c != '0' || mask != 1)
+ goto error;
+ mask = 10;
+ }
+ the_insn.opcode |= (mask << 48);
+ continue;
+ }
+ break;
+ case 'i':
+ case 'C':
+ the_insn.reloc = BFD_RELOC_BPF_32;
+ if (*s == ' ')
+ s++;
+ get_expression (s, &the_insn.exp);
+ s = expr_end;
+ if (the_insn.exp.X_op == O_constant
+ && the_insn.exp.X_add_symbol == 0
+ && the_insn.exp.X_op_symbol == 0)
+ {
+ valueT val = the_insn.exp.X_add_number;
+
+ the_insn.reloc = BFD_RELOC_NONE;
+ val &= 0xffffffff;
+ the_insn.opcode |= val;
+ }
+ continue;
+ case 'O':
+ the_insn.reloc = BFD_RELOC_BPF_16;
+ if (*s == ' ')
+ s++;
+ get_expression (s, &the_insn.exp);
+ s = expr_end;
+ if (the_insn.exp.X_op == O_constant
+ && the_insn.exp.X_add_symbol == 0
+ && the_insn.exp.X_op_symbol == 0)
+ {
+ valueT val = the_insn.exp.X_add_number;
+
+ the_insn.reloc = BFD_RELOC_NONE;
+ val &= 0xffff;
+ the_insn.opcode |= val << 32;
+ }
+ continue;
+ case 'L':
+ the_insn.reloc = BFD_RELOC_BPF_WDISP16;
+ the_insn.pcrel = 1;
+ if (*s == ' ')
+ s++;
+ get_expression (s, &the_insn.exp);
+ s = expr_end;
+ if (the_insn.exp.X_op == O_constant
+ && the_insn.exp.X_add_symbol == 0
+ && the_insn.exp.X_op_symbol == 0)
+ {
+ valueT val = the_insn.exp.X_add_number;
+
+ the_insn.reloc = BFD_RELOC_NONE;
+ val &= 0xffff;
+ the_insn.opcode |= val << 32;
+ }
+ continue;
+ case 'D':
+ the_insn.reloc = BFD_RELOC_BPF_64;
+ the_insn.imm64 = 1;
+ if (*s == ' ')
+ s++;
+ get_expression (s, &the_insn.exp);
+ s = expr_end;
+ if (the_insn.exp.X_op == O_constant
+ && the_insn.exp.X_add_symbol == 0
+ && the_insn.exp.X_op_symbol == 0)
+ {
+ valueT val = the_insn.exp.X_add_number;
+
+ the_insn.reloc = BFD_RELOC_NONE;
+ the_insn.opcode |= (val & 0xffffffff);
+ the_insn.high64 = ((val >> 32) & 0xffffffff);
+ }
+ continue;
+ case '\0': /* End of args. */
+ match = 1;
+ break;
+ default:
+ as_fatal (_("failed sanity check."));
+ }
+
+ /* Break out of for() loop. */
+ break;
+ }
+ error:
+ if (match == 0)
+ {
+ /* Args don't match. */
+ if (&insn[1] - bpf_opcodes < bpf_num_opcodes
+ && (insn->name == insn[1].name
+ || !strcmp (insn->name, insn[1].name)))
+ {
+ ++insn;
+ s = argsStart;
+ continue;
+ }
+ else
+ {
+ as_bad (_("Illegal operands%s"), "");
+ return;
+ }
+ }
+ break;
+ }
+
+ output_insn (&the_insn);
+}
+
+void
+md_number_to_chars (char *buf, valueT val, int n)
+{
+ if (target_big_endian)
+ number_to_chars_bigendian (buf, val, n);
+ else
+ number_to_chars_littleendian (buf, val, n);
+}
+
+static void
+md_apply_u16 (offsetT val, char *buf)
+{
+ long off;
+
+ if (target_big_endian)
+ off = bfd_getb16 ((unsigned char *) buf + 2);
+ else
+ off = bfd_getl16 ((unsigned char *) buf + 2);
+ off |= val;
+ if (target_big_endian)
+ bfd_putb16 (off, (unsigned char *) buf + 2);
+ else
+ bfd_putl16 (off, (unsigned char *) buf + 2);
+}
+
+static void
+md_apply_u32 (offsetT val, char *buf)
+{
+ long imm;
+
+ if (target_big_endian)
+ imm = bfd_getb32 ((unsigned char *) buf + 4);
+ else
+ imm = bfd_getl32 ((unsigned char *) buf + 4);
+ imm |= val;
+ if (target_big_endian)
+ bfd_putb32 (imm, (unsigned char *) buf + 4);
+ else
+ bfd_putl32 (imm, (unsigned char *) buf + 4);
+}
+
+static void
+md_apply_u64 (offsetT val, char *buf)
+{
+ md_apply_u32(val & 0xffffffff, buf);
+ md_apply_u32((val >> 32) & 0xffffffff, buf + 12);
+}
+
+void
+md_apply_fix (fixS *fixP, valueT *valP ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED)
+{
+ char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
+ offsetT val = * (offsetT *) valP;
+
+ gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
+
+ fixP->fx_addnumber = val; /* Remember value for emit_reloc. */
+
+ /* If this is a data relocation, just output VAL. */
+
+ if (fixP->fx_r_type == BFD_RELOC_8)
+ {
+ md_number_to_chars (buf, val, 1);
+ }
+ else if (fixP->fx_r_type == BFD_RELOC_16)
+ {
+ md_number_to_chars (buf, val, 2);
+ }
+ else if (fixP->fx_r_type == BFD_RELOC_32)
+ {
+ md_number_to_chars (buf, val, 4);
+ }
+ else if (fixP->fx_r_type == BFD_RELOC_64)
+ {
+ md_number_to_chars (buf, val, 8);
+ }
+ else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+ || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+ {
+ fixP->fx_done = 0;
+ return;
+ }
+ else
+ {
+ /* It's a relocation against an instruction. */
+
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_BPF_WDISP16:
+ val = val >> 3;
+ md_apply_u16((val + 1) & 0xffff, buf);
+ break;
+ case BFD_RELOC_BPF_16:
+ md_apply_u16(val & 0xffff, buf);
+ break;
+ case BFD_RELOC_BPF_32:
+ md_apply_u32(val & 0xffffffff, buf);
+ break;
+ case BFD_RELOC_BPF_64:
+ md_apply_u64(val, buf);
+ break;
+ case BFD_RELOC_NONE:
+ default:
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("bad or unhandled relocation type: 0x%02x"),
+ fixP->fx_r_type);
+ break;
+ }
+
+ }
+ if (fixP->fx_addsy == NULL)
+ fixP->fx_done = 1;
+}
+
+arelent *
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp ATTRIBUTE_UNUSED)
+{
+ bfd_reloc_code_real_type code;
+ arelent *reloc;
+
+ reloc = XNEW (arelent);
+ reloc->sym_ptr_ptr = XNEW (asymbol *);
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+
+ switch (fixp->fx_r_type)
+ {
+ case BFD_RELOC_BPF_WDISP16:
+ case BFD_RELOC_BPF_16:
+ case BFD_RELOC_BPF_32:
+ case BFD_RELOC_BPF_64:
+ case BFD_RELOC_8:
+ case BFD_RELOC_16:
+ case BFD_RELOC_32:
+ case BFD_RELOC_64:
+ code = fixp->fx_r_type;
+ break;
+ default:
+ abort ();
+ return NULL;
+ }
+
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
+ if (reloc->howto == 0)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("internal error: can't export reloc type %d (`%s')"),
+ fixp->fx_r_type, bfd_get_reloc_code_name (code));
+ xfree (reloc);
+ return NULL;
+ }
+ if (code != BFD_RELOC_BPF_WDISP16)
+ reloc->addend = fixp->fx_addnumber;
+ else if (symbol_section_p (fixp->fx_addsy))
+ reloc->addend = (section->vma
+ + fixp->fx_addnumber
+ + md_pcrel_from (fixp));
+ else
+ reloc->addend = fixp->fx_offset;
+
+ return reloc;
+}
+
+symbolS *
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+valueT
+md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
+{
+ return size;
+}
+
+long
+md_pcrel_from (fixS *fixP)
+{
+ long ret;
+
+ ret = fixP->fx_where + fixP->fx_frag->fr_address;
+ /* XXX */
+ return ret;
+}
+
+const char *
+md_atof (int type, char *litP, int *sizeP)
+{
+ return ieee_md_atof (type, litP, sizeP, target_big_endian);
+}
diff --git a/gas/config/tc-bpf.h b/gas/config/tc-bpf.h
new file mode 100644
index 0000000..45ab5d2
--- /dev/null
+++ b/gas/config/tc-bpf.h
@@ -0,0 +1,45 @@
+/* tc-bpf.h - Macros and type defines for the bpf.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of GAS, the GNU Assembler.
+
+ GAS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3,
+ or (at your option) any later version.
+
+ GAS is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with GAS; see the file COPYING. If not, write
+ to the Free Software Foundation, 51 Franklin Street - Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifndef TC_BPF
+#define TC_BPF 1
+
+#define TARGET_ARCH bfd_arch_bpf
+
+#ifdef WORDS_BIGENDIAN
+#define TARGET_BYTES_BIG_ENDIAN 1
+#else
+#define TARGET_BYTES_BIG_ENDIAN 0
+#endif
+
+#define TARGET_FORMAT (bpf_target_format ())
+extern const char *bpf_target_format (void);
+
+#define md_convert_frag(b,s,f) \
+ as_fatal (_("bpf convert_frag\n"))
+#define md_estimate_size_before_relax(f,s) \
+ (as_fatal (_("estimate_size_before_relax called")), 1)
+#define md_operand(x)
+
+#define LISTING_HEADER "BPF GAS "
+
+#define WORKING_DOT_WORD
+
+#endif
diff --git a/gas/configure.tgt b/gas/configure.tgt
index ca58b69..fa959c3 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -54,6 +54,7 @@ case ${cpu} in
arm*be|arm*b) cpu_type=arm endian=big ;;
arm*) cpu_type=arm endian=little ;;
bfin*) cpu_type=bfin endian=little ;;
+ bpf*) cpu_type=bpf ;;
c4x*) cpu_type=tic4x ;;
cr16*) cpu_type=cr16 endian=little ;;
crisv32) cpu_type=cris arch=crisv32 ;;
@@ -171,6 +172,8 @@ case ${generic_target} in
bfin-*-uclinux*) fmt=elf em=linux ;;
bfin-*elf) fmt=elf ;;
+ bpf-*elf) fmt=elf ;;
+
cr16-*-elf*) fmt=elf ;;
cris-*-linux-* | crisv32-*-linux-*)
diff --git a/gas/testsuite/gas/bpf/arith.d b/gas/testsuite/gas/bpf/arith.d
new file mode 100644
index 0000000..d63de38
--- /dev/null
+++ b/gas/testsuite/gas/bpf/arith.d
@@ -0,0 +1,61 @@
+#as: -EL
+#objdump: -dr
+#name: arith
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: 0f 12 00 00 00 00 00 00 add r1, r2
+ 8: 07 10 00 00 05 00 00 00 add r1, 5
+ 10: 0c 12 00 00 00 00 00 00 add32 r1, r2
+ 18: 04 10 00 00 05 00 00 00 add32 r1, 5
+ 20: 1f 12 00 00 00 00 00 00 sub r1, r2
+ 28: 17 10 00 00 05 00 00 00 sub r1, 5
+ 30: 1c 12 00 00 00 00 00 00 sub32 r1, r2
+ 38: 14 10 00 00 05 00 00 00 sub32 r1, 5
+ 40: 5f 12 00 00 00 00 00 00 and r1, r2
+ 48: 57 10 00 00 ff 00 00 00 and r1, 255
+ 50: 5c 12 00 00 00 00 00 00 and32 r1, r2
+ 58: 54 10 00 00 ff 00 00 00 and32 r1, 255
+ 60: 4f 12 00 00 00 00 00 00 or r1, r2
+ 68: a7 10 00 00 80 00 00 00 or r1, 128
+ 70: 4c 12 00 00 00 00 00 00 or32 r1, r2
+ 78: a4 10 00 00 80 00 00 00 or32 r1, 128
+ 80: af 12 00 00 00 00 00 00 xor r1, r2
+ 88: 47 10 00 00 1f 00 00 00 xor r1, 31
+ 90: ac 12 00 00 00 00 00 00 xor32 r1, r2
+ 98: 44 10 00 00 1f 00 00 00 xor32 r1, 31
+ a0: 2f 12 00 00 00 00 00 00 mul r1, r2
+ a8: 27 10 00 00 05 00 00 00 mul r1, 5
+ b0: 2c 12 00 00 00 00 00 00 mul32 r1, r2
+ b8: 24 10 00 00 05 00 00 00 mul32 r1, 5
+ c0: 3f 12 00 00 00 00 00 00 div r1, r2
+ c8: 37 10 00 00 02 00 00 00 div r1, 2
+ d0: 3c 12 00 00 00 00 00 00 div32 r1, r2
+ d8: 34 10 00 00 02 00 00 00 div32 r1, 2
+ e0: 9f 12 00 00 00 00 00 00 mod r1, r2
+ e8: 97 10 00 00 03 00 00 00 mod r1, 3
+ f0: 9c 12 00 00 00 00 00 00 mod32 r1, r2
+ f8: 94 10 00 00 03 00 00 00 mod32 r1, 3
+ 100: 6f 12 00 00 00 00 00 00 lsh r1, r2
+ 108: 67 10 00 00 01 00 00 00 lsh r1, 1
+ 110: 6c 12 00 00 00 00 00 00 lsh32 r1, r2
+ 118: 64 10 00 00 01 00 00 00 lsh32 r1, 1
+ 120: 7f 12 00 00 00 00 00 00 rsh r1, r2
+ 128: 77 10 00 00 01 00 00 00 rsh r1, 1
+ 130: 7c 12 00 00 00 00 00 00 rsh32 r1, r2
+ 138: 74 10 00 00 01 00 00 00 rsh32 r1, 1
+ 140: cf 12 00 00 00 00 00 00 arsh r1, r2
+ 148: c7 10 00 00 04 00 00 00 arsh r1, 4
+ 150: cc 12 00 00 00 00 00 00 arsh32 r1, r2
+ 158: c4 10 00 00 04 00 00 00 arsh32 r1, 4
+ 160: 8f 10 00 00 00 00 00 00 neg r1
+ 168: 8c 10 00 00 00 00 00 00 neg32 r1
+ 170: dc 10 00 00 10 00 00 00 endbe r1, 16
+ 178: dc 10 00 00 20 00 00 00 endbe r1, 32
+ 180: dc 10 00 00 40 00 00 00 endbe r1, 64
+ 188: d4 10 00 00 10 00 00 00 endle r1, 16
+ 190: d4 10 00 00 20 00 00 00 endle r1, 32
+ 198: d4 10 00 00 40 00 00 00 endle r1, 64
diff --git a/gas/testsuite/gas/bpf/arith.s b/gas/testsuite/gas/bpf/arith.s
new file mode 100644
index 0000000..58bf2a5
--- /dev/null
+++ b/gas/testsuite/gas/bpf/arith.s
@@ -0,0 +1,53 @@
+ .text
+ add r1, r2
+ add r1, 5
+ add32 r1, r2
+ add32 r1, 5
+ sub r1, r2
+ sub r1, 5
+ sub32 r1, r2
+ sub32 r1, 5
+ and r1, r2
+ and r1, 0xff
+ and32 r1, r2
+ and32 r1, 0xff
+ or r1, r2
+ or r1, 0x80
+ or32 r1, r2
+ or32 r1, 0x80
+ xor r1, r2
+ xor r1, 0x1f
+ xor32 r1, r2
+ xor32 r1, 0x1f
+ mul r1, r2
+ mul r1, 5
+ mul32 r1, r2
+ mul32 r1, 5
+ div r1, r2
+ div r1, 2
+ div32 r1, r2
+ div32 r1, 2
+ mod r1, r2
+ mod r1, 3
+ mod32 r1, r2
+ mod32 r1, 3
+ lsh r1, r2
+ lsh r1, 1
+ lsh32 r1, r2
+ lsh32 r1, 1
+ rsh r1, r2
+ rsh r1, 1
+ rsh32 r1, r2
+ rsh32 r1, 1
+ arsh r1, r2
+ arsh r1, 4
+ arsh32 r1, r2
+ arsh32 r1, 4
+ neg r1
+ neg32 r1
+ endbe r1, 16
+ endbe r1, 32
+ endbe r1, 64
+ endle r1, 16
+ endle r1, 32
+ endle r1, 64
diff --git a/gas/testsuite/gas/bpf/atomics.d b/gas/testsuite/gas/bpf/atomics.d
new file mode 100644
index 0000000..fc710d6
--- /dev/null
+++ b/gas/testsuite/gas/bpf/atomics.d
@@ -0,0 +1,12 @@
+#as: -EL
+#objdump: -dr
+#name: atomics
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: b7 20 00 00 06 00 00 00 mov r2, 6
+ 8: db 12 00 00 00 00 00 00 xadddw \[r1\+0\], r2
+ 10: c3 12 08 00 00 00 00 00 xaddw \[r1\+8\], r2
diff --git a/gas/testsuite/gas/bpf/atomics.s b/gas/testsuite/gas/bpf/atomics.s
new file mode 100644
index 0000000..6552ef3
--- /dev/null
+++ b/gas/testsuite/gas/bpf/atomics.s
@@ -0,0 +1,4 @@
+ .text
+ mov r2, 6
+ xadddw [r1+0], r2
+ xaddw [r1+8], r2
diff --git a/gas/testsuite/gas/bpf/bpf.exp b/gas/testsuite/gas/bpf/bpf.exp
new file mode 100644
index 0000000..363fd2c
--- /dev/null
+++ b/gas/testsuite/gas/bpf/bpf.exp
@@ -0,0 +1,28 @@
+# Copyright (C) 2017 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+# BPF assembler testsuite
+
+if [istarget bpf*-*-*] {
+ run_dump_test "arith"
+ run_dump_test "jump"
+ run_dump_test "move"
+ run_dump_test "loads"
+ run_dump_test "stores"
+ run_dump_test "atomics"
+ run_dump_test "call"
+ run_dump_test "imm64"
+}
diff --git a/gas/testsuite/gas/bpf/call.d b/gas/testsuite/gas/bpf/call.d
new file mode 100644
index 0000000..8521f25
--- /dev/null
+++ b/gas/testsuite/gas/bpf/call.d
@@ -0,0 +1,14 @@
+#as: -EL
+#objdump: -dr
+#name: call
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: 85 00 00 00 01 00 00 00 call 0x1
+ 8: 85 00 00 00 02 00 00 00 call 0x2
+ 10: 85 00 00 00 03 00 00 00 call 0x3
+ 18: 85 00 00 00 04 00 00 00 call 0x4
+ 20: 95 00 00 00 00 00 00 00 exit
diff --git a/gas/testsuite/gas/bpf/call.s b/gas/testsuite/gas/bpf/call.s
new file mode 100644
index 0000000..e31980d
--- /dev/null
+++ b/gas/testsuite/gas/bpf/call.s
@@ -0,0 +1,6 @@
+ .text
+ call 1
+ call 2
+ call 3
+ call 4
+ exit
diff --git a/gas/testsuite/gas/bpf/imm64.d b/gas/testsuite/gas/bpf/imm64.d
new file mode 100644
index 0000000..4dcaf7b
--- /dev/null
+++ b/gas/testsuite/gas/bpf/imm64.d
@@ -0,0 +1,30 @@
+#as: -EL
+#objdump: -dr
+#name: imm64a
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: 18 10 00 00 01 00 00 00 ldimm64 r1, 1
+ 8: 00 00 00 00 00 00 00 00
+ 10: 18 10 00 00 02 00 00 00 ldimm64 r1, 2
+ 18: 00 00 00 00 00 00 00 00
+ 20: 18 10 00 00 00 00 01 00 ldimm64 r1, 65536
+ 28: 00 00 00 00 00 00 00 00
+ 30: 18 10 00 00 ff ff ff ff ldimm64 r1, 4294967295
+ 38: 00 00 00 00 00 00 00 00
+ 40: 18 10 00 00 01 00 00 00 ldimm64 r1, -4294967295
+ 48: 00 00 00 00 ff ff ff ff
+ 50: 18 10 00 00 ff ff ff ff ldimm64 r1, -1
+ 58: 00 00 00 00 ff ff ff ff
+ 60: 18 20 00 00 00 ff ff ff ldimm64 r2, -256
+ 68: 00 00 00 00 ff ff ff ff
+ 70: 18 30 00 00 00 00 ff ff ldimm64 r3, -65536
+ 78: 00 00 00 00 ff ff ff ff
+ 80: 18 40 00 00 00 00 00 00 ldimm64 r4, 4294967296
+ 88: 00 00 00 00 01 00 00 00
+ 90: 18 50 00 00 00 00 00 00 ldimm64 r5, -9223372036854775808
+ 98: 00 00 00 00 00 00 00 80
+ a0: 95 00 00 00 00 00 00 00 exit
diff --git a/gas/testsuite/gas/bpf/imm64.s b/gas/testsuite/gas/bpf/imm64.s
new file mode 100644
index 0000000..929e357
--- /dev/null
+++ b/gas/testsuite/gas/bpf/imm64.s
@@ -0,0 +1,12 @@
+ .text
+ ldimm64 r1, 1
+ ldimm64 r1, 2
+ ldimm64 r1, 65536
+ ldimm64 r1, 4294967295
+ ldimm64 r1, -4294967295
+ ldimm64 r1, -1
+ ldimm64 r2, -256
+ ldimm64 r3, -65536
+ ldimm64 r4, 4294967296
+ ldimm64 r5, -9223372036854775808
+ exit
diff --git a/gas/testsuite/gas/bpf/jump.d b/gas/testsuite/gas/bpf/jump.d
new file mode 100644
index 0000000..fc1e6bd
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jump.d
@@ -0,0 +1,43 @@
+#as: -EL
+#objdump: -dr
+#name: jump
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: 05 00 03 00 00 00 00 00 ja 0x10
+ 8: bf 11 00 00 00 00 00 00 mov r1, r1
+ 10: b7 20 00 00 03 00 00 00 mov r2, 3
+ 18: 25 20 06 00 02 00 00 00 jgt r2, 2, 0x40
+ 20: bf 11 00 00 00 00 00 00 mov r1, r1
+ 28: b7 30 00 00 03 00 00 00 mov r3, 3
+ 30: 15 30 03 00 03 00 00 00 jeq r3, 3, 0x40
+ 38: bf 11 00 00 00 00 00 00 mov r1, r1
+ 40: 1d 32 03 00 00 00 00 00 jeq r3, r2, 0x50
+ 48: bf 11 00 00 00 00 00 00 mov r1, r1
+ 50: b7 40 00 00 04 00 00 00 mov r4, 4
+ 58: 2d 43 03 00 00 00 00 00 jgt r4, r3, 0x68
+ 60: bf 11 00 00 00 00 00 00 mov r1, r1
+ 68: 3d 43 03 00 00 00 00 00 jge r4, r3, 0x78
+ 70: bf 11 00 00 00 00 00 00 mov r1, r1
+ 78: 35 30 03 00 03 00 00 00 jge r3, 3, 0x88
+ 80: bf 11 00 00 00 00 00 00 mov r1, r1
+ 88: 5d 43 03 00 00 00 00 00 jne r4, r3, 0x98
+ 90: bf 11 00 00 00 00 00 00 mov r1, r1
+ 98: 55 30 03 00 03 00 00 00 jne r3, 3, 0xa8
+ a0: bf 11 00 00 00 00 00 00 mov r1, r1
+ a8: 6d 43 03 00 00 00 00 00 jsgt r4, r3, 0xb8
+ b0: bf 11 00 00 00 00 00 00 mov r1, r1
+ b8: 65 30 03 00 03 00 00 00 jsgt r3, 3, 0xc8
+ c0: bf 11 00 00 00 00 00 00 mov r1, r1
+ c8: 7d 43 03 00 00 00 00 00 jsge r4, r3, 0xd8
+ d0: bf 11 00 00 00 00 00 00 mov r1, r1
+ d8: 75 30 03 00 03 00 00 00 jsge r3, 3, 0xe8
+ e0: bf 11 00 00 00 00 00 00 mov r1, r1
+ e8: 4d 43 03 00 00 00 00 00 jset r4, r3, 0xf8
+ f0: bf 11 00 00 00 00 00 00 mov r1, r1
+ f8: 45 30 03 00 03 00 00 00 jset r3, 3, 0x108
+ 100: bf 11 00 00 00 00 00 00 mov r1, r1
+ 108: 95 00 00 00 00 00 00 00 exit
diff --git a/gas/testsuite/gas/bpf/jump.s b/gas/testsuite/gas/bpf/jump.s
new file mode 100644
index 0000000..4e084b4
--- /dev/null
+++ b/gas/testsuite/gas/bpf/jump.s
@@ -0,0 +1,35 @@
+ .text
+ ja 1f
+ mov r1, r1
+1: mov r2, 3
+ jgt r2, 2, 1f
+ mov r1, r1
+ mov r3, 3
+ jeq r3, 3, 1f
+ mov r1, r1
+1: jeq r3, r2, 1f
+ mov r1, r1
+1: mov r4, 4
+ jgt r4, r3, 1f
+ mov r1, r1
+1: jge r4, r3, 1f
+ mov r1, r1
+1: jge r3, 3, 1f
+ mov r1, r1
+1: jne r4, r3, 1f
+ mov r1, r1
+1: jne r3, 3, 1f
+ mov r1, r1
+1: jsgt r4, r3, 1f
+ mov r1, r1
+1: jsgt r3, 3, 1f
+ mov r1, r1
+1: jsge r4, r3, 1f
+ mov r1, r1
+1: jsge r3, 3, 1f
+ mov r1, r1
+1: jset r4, r3, 1f
+ mov r1, r1
+1: jset r3, 3, 1f
+ mov r1, r1
+1: exit
diff --git a/gas/testsuite/gas/bpf/loads.d b/gas/testsuite/gas/bpf/loads.d
new file mode 100644
index 0000000..542e895
--- /dev/null
+++ b/gas/testsuite/gas/bpf/loads.d
@@ -0,0 +1,27 @@
+#as: -EL
+#objdump: -dr
+#name: loads
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: 71 12 03 00 00 00 00 00 ldb r1, \[r2\+3\]
+ 8: 69 12 02 00 00 00 00 00 ldh r1, \[r2\+2\]
+ 10: 61 12 04 00 00 00 00 00 ldw r1, \[r2\+4\]
+ 18: 79 12 08 00 00 00 00 00 lddw r1, \[r2\+8\]
+ 20: 61 34 04 00 00 00 00 00 ldw r3, \[r4\+4\]
+ 28: 61 44 08 00 00 00 00 00 ldw r4, \[r4\+8\]
+ 30: 61 54 00 00 00 00 00 00 ldw r5, \[r4\+0\]
+ 38: 69 33 02 00 00 00 00 00 ldh r3, \[r3\+2\]
+ 40: 69 43 04 00 00 00 00 00 ldh r4, \[r3\+4\]
+ 48: 69 53 00 00 00 00 00 00 ldh r5, \[r3\+0\]
+ 50: 71 33 01 00 00 00 00 00 ldb r3, \[r3\+1\]
+ 58: 71 43 02 00 00 00 00 00 ldb r4, \[r3\+2\]
+ 60: 71 53 03 00 00 00 00 00 ldb r5, \[r3\+3\]
+ 68: 71 63 00 00 00 00 00 00 ldb r6, \[r3\+0\]
+ 70: 71 1a f8 ff 00 00 00 00 ldb r1, \[r10\+-8\]
+ 78: 69 2a f6 ff 00 00 00 00 ldh r2, \[r10\+-10\]
+ 80: 61 3a f4 ff 00 00 00 00 ldw r3, \[r10\+-12\]
+ 88: 79 4a f0 ff 00 00 00 00 lddw r4, \[r10\+-16\]
diff --git a/gas/testsuite/gas/bpf/loads.s b/gas/testsuite/gas/bpf/loads.s
new file mode 100644
index 0000000..1aa8f88
--- /dev/null
+++ b/gas/testsuite/gas/bpf/loads.s
@@ -0,0 +1,19 @@
+ .text
+ ldb r1, [r2+3]
+ ldh r1, [r2+2]
+ ldw r1, [r2+4]
+ lddw r1, [r2+8]
+ ldw r3, [r4+4]
+ ldw r4, [r4+8]
+ ldw r5, [r4+0]
+ ldh r3, [r3+2]
+ ldh r4, [r3+4]
+ ldh r5, [r3+0]
+ ldb r3, [r3+1]
+ ldb r4, [r3+2]
+ ldb r5, [r3+3]
+ ldb r6, [r3+0]
+ ldb r1, [r10-8]
+ ldh r2, [r10-10]
+ ldw r3, [r10-12]
+ lddw r4, [r10-16]
diff --git a/gas/testsuite/gas/bpf/move.d b/gas/testsuite/gas/bpf/move.d
new file mode 100644
index 0000000..f15ad23
--- /dev/null
+++ b/gas/testsuite/gas/bpf/move.d
@@ -0,0 +1,19 @@
+#as: -EL
+#objdump: -dr
+#name: move
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: bf 12 00 00 00 00 00 00 mov r1, r2
+ 8: b7 10 00 00 ef 00 00 00 mov r1, 239
+ 10: bc 12 00 00 00 00 00 00 mov32 r1, r2
+ 18: b4 10 00 00 ef 00 00 00 mov32 r1, 239
+ 20: bf 36 00 00 00 00 00 00 mov r3, r6
+ 28: bf 63 00 00 00 00 00 00 mov r6, r3
+ 30: bf 89 00 00 00 00 00 00 mov r8, r9
+ 38: bf a1 00 00 00 00 00 00 mov r10, r1
+ 40: bf 73 00 00 00 00 00 00 mov r7, r3
+ 48: b7 50 00 00 02 00 00 00 mov r5, 2
diff --git a/gas/testsuite/gas/bpf/move.s b/gas/testsuite/gas/bpf/move.s
new file mode 100644
index 0000000..36797b3
--- /dev/null
+++ b/gas/testsuite/gas/bpf/move.s
@@ -0,0 +1,11 @@
+ .text
+ mov r1, r2
+ mov r1, 0xef
+ mov32 r1, r2
+ mov32 r1, 0xef
+ mov r3, r6
+ mov r6, r3
+ mov r8, r9
+ mov r10, r1
+ mov r7, r3
+ mov r5, 2
diff --git a/gas/testsuite/gas/bpf/stores.d b/gas/testsuite/gas/bpf/stores.d
new file mode 100644
index 0000000..6033d43
--- /dev/null
+++ b/gas/testsuite/gas/bpf/stores.d
@@ -0,0 +1,21 @@
+#as: -EL
+#objdump: -dr
+#name: stores
+
+.*: +file format elf64-bpfle
+
+Disassembly of section .text:
+
+0000000000000000 <.text>:
+ 0: 63 12 00 00 00 00 00 00 stw \[r1\+0\], r2
+ 8: 62 10 04 00 00 00 00 00 stw \[r1\+4\], 0
+ 10: 6b 13 00 00 00 00 00 00 sth \[r1\+0\], r3
+ 18: 6a 10 02 00 01 00 00 00 sth \[r1\+2\], 1
+ 20: 73 14 00 00 00 00 00 00 stb \[r1\+0\], r4
+ 28: 72 10 02 00 02 00 00 00 stb \[r1\+2\], 2
+ 30: 7b 15 08 00 00 00 00 00 stdw \[r1\+8\], r5
+ 38: 7a 10 10 00 10 00 00 00 stdw \[r1\+16\], 16
+ 40: 73 a1 f8 ff 00 00 00 00 stb \[r10\+-8\], r1
+ 48: 6b a2 f6 ff 00 00 00 00 sth \[r10\+-10\], r2
+ 50: 63 a3 f4 ff 00 00 00 00 stw \[r10\+-12\], r3
+ 58: 7b a4 f0 ff 00 00 00 00 stdw \[r10\+-16\], r4
diff --git a/gas/testsuite/gas/bpf/stores.s b/gas/testsuite/gas/bpf/stores.s
new file mode 100644
index 0000000..eb7c6e6
--- /dev/null
+++ b/gas/testsuite/gas/bpf/stores.s
@@ -0,0 +1,13 @@
+ .text
+ stw [r1+0], r2
+ stw [r1+4], 0
+ sth [r1+0], r3
+ sth [r1+2], 1
+ stb [r1+0], r4
+ stb [r1+2], 2
+ stdw [r1+8], r5
+ stdw [r1+16], 16
+ stb [r10-8], r1
+ sth [r10-10], r2
+ stw [r10-12], r3
+ stdw [r10-16], r4
diff --git a/gdb/bpf-tdep.c b/gdb/bpf-tdep.c
new file mode 100644
index 0000000..6629f73
--- /dev/null
+++ b/gdb/bpf-tdep.c
@@ -0,0 +1,229 @@
+/* Target-dependent code for eBPF, for GDB.
+
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "arch-utils.h"
+#include "regcache.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
+#include "dis-asm.h"
+#include "dwarf2-frame.h"
+#include "symtab.h"
+#include "elf-bfd.h"
+#include "osabi.h"
+#include "infcall.h"
+#include "bpf-tdep.h"
+
+static const char * const bpf_register_name_strings[] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "pc",
+};
+
+#define NUM_BPF_REGNAMES ARRAY_SIZE (bpf_register_name_strings)
+
+/* Return the BPF register name corresponding to register I. */
+
+static const char *
+bpf_register_name (struct gdbarch *gdbarch, int i)
+{
+ return bpf_register_name_strings[i];
+}
+
+/* Return the GDB type object for the "standard" data type of data in
+ register N. */
+
+static struct type *
+bpf_register_type (struct gdbarch *gdbarch, int regnum)
+{
+ if (regnum == BPF_R10_REGNUM)
+ return builtin_type (gdbarch)->builtin_data_ptr;
+
+ if (regnum == BPF_PC_REGNUM)
+ return builtin_type (gdbarch)->builtin_func_ptr;
+
+ return builtin_type (gdbarch)->builtin_int32;
+}
+
+/* Convert DWARF2 register number REG to the appropriate register number
+ used by GDB. */
+
+static int
+bpf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
+{
+ if (reg < 0 || reg >= BPF_NUM_REGS)
+ return -1;
+
+ return reg;
+}
+
+static struct frame_id
+bpf_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
+{
+ CORE_ADDR sp;
+
+ sp = get_frame_register_unsigned (this_frame, BPF_R10_REGNUM);
+
+ return frame_id_build (sp, get_frame_pc (this_frame));
+}
+
+static CORE_ADDR
+bpf_push_dummy_call (struct gdbarch *gdbarch,
+ struct value *function,
+ struct regcache *regcache,
+ CORE_ADDR bp_addr,
+ int nargs,
+ struct value **args,
+ CORE_ADDR sp,
+ int struct_return,
+ CORE_ADDR struct_addr)
+{
+ return sp; /* XXX */
+}
+
+/* Extract a function return value of TYPE from REGCACHE, and copy
+ that into VALBUF. */
+
+static void
+bpf_extract_return_value (struct type *type, struct regcache *regcache,
+ gdb_byte *valbuf)
+{
+ int len = TYPE_LENGTH (type);
+ gdb_byte buf[8];
+
+ regcache_cooked_read (regcache, BPF_R0_REGNUM, buf);
+ memcpy (valbuf, buf + 8 - len, len);
+}
+
+/* Store the function return value of type TYPE from VALBUF into
+ REGCACHE. */
+
+static void
+bpf_store_return_value (struct type *type, struct regcache *regcache,
+ const gdb_byte *valbuf)
+{
+ int len = TYPE_LENGTH (type);
+ gdb_byte buf[8];
+
+ memcpy (buf + 8 - len, valbuf, len);
+ regcache_cooked_write (regcache, BPF_R0_REGNUM, buf);
+}
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+ should be returned. If it is supposed to be returned in registers,
+ and READBUF is nonzero, read the appropriate value from REGCACHE,
+ and copy it into READBUF. If WRITEBUF is nonzero, write the value
+ from WRITEBUF into REGCACHE. */
+
+static enum return_value_convention
+bpf_return_value (struct gdbarch *gdbarch,
+ struct value *function,
+ struct type *type,
+ struct regcache *regcache,
+ gdb_byte *readbuf,
+ const gdb_byte *writebuf)
+{
+ if (TYPE_LENGTH (type) > 8)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+
+ if (readbuf)
+ bpf_extract_return_value (type, regcache, readbuf);
+
+ if (writebuf)
+ bpf_store_return_value (type, regcache, writebuf);
+
+ return RETURN_VALUE_REGISTER_CONVENTION;
+}
+
+static CORE_ADDR
+bpf_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+ return frame_unwind_register_unsigned (next_frame, BPF_PC_REGNUM);
+}
+
+/* Skip all the insns that appear in generated function prologues. */
+
+static CORE_ADDR
+bpf_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ return pc;
+}
+
+/* Implement the breakpoint_kind_from_pc gdbarch method. */
+
+static int
+bpf_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+ return 8;
+}
+
+/* Initialize the current architecture based on INFO. If possible,
+ re-use an architecture from ARCHES, which is a list of
+ architectures already created during this debugging session.
+
+ Called e.g. at program startup, when reading a core file, and when
+ reading a binary file. */
+
+static struct gdbarch *
+bpf_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch_tdep *tdep;
+ struct gdbarch *gdbarch;
+
+ tdep = XNEW (struct gdbarch_tdep);
+ gdbarch = gdbarch_alloc (&info, tdep);
+
+ tdep->xxx = 0;
+
+ set_gdbarch_num_regs (gdbarch, BPF_NUM_REGS);
+ set_gdbarch_sp_regnum (gdbarch, BPF_R10_REGNUM);
+ set_gdbarch_pc_regnum (gdbarch, BPF_PC_REGNUM);
+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, bpf_reg_to_regnum);
+ set_gdbarch_register_name (gdbarch, bpf_register_name);
+ set_gdbarch_register_type (gdbarch, bpf_register_type);
+ set_gdbarch_dummy_id (gdbarch, bpf_dummy_id);
+ set_gdbarch_push_dummy_call (gdbarch, bpf_push_dummy_call);
+ set_gdbarch_return_value (gdbarch, bpf_return_value);
+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
+ set_gdbarch_frame_args_skip (gdbarch, 8);
+ set_gdbarch_unwind_pc (gdbarch, bpf_unwind_pc);
+ set_gdbarch_print_insn (gdbarch, print_insn_bpf);
+
+ set_gdbarch_skip_prologue (gdbarch, bpf_skip_prologue);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch, bpf_breakpoint_kind_from_pc);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
+
+ dwarf2_append_unwinders (gdbarch);
+ return gdbarch;
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_bpf_tdep;
+
+void
+_initialize_bpf_tdep (void)
+{
+ register_gdbarch_init (bfd_arch_bpf, bpf_gdbarch_init);
+}
diff --git a/gdb/bpf-tdep.h b/gdb/bpf-tdep.h
new file mode 100644
index 0000000..52cae6d
--- /dev/null
+++ b/gdb/bpf-tdep.h
@@ -0,0 +1,40 @@
+/* Target-dependent code for eBPF, for GDB.
+
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+enum gdb_regnum {
+ BPF_R0_REGNUM = 0,
+ BPF_R1_REGNUM,
+ BPF_R2_REGNUM,
+ BPF_R3_REGNUM,
+ BPF_R4_REGNUM,
+ BPF_R5_REGNUM,
+ BPF_R6_REGNUM,
+ BPF_R7_REGNUM,
+ BPF_R8_REGNUM,
+ BPF_R9_REGNUM,
+ BPF_R10_REGNUM,
+ BPF_PC_REGNUM,
+};
+
+#define BPF_NUM_REGS (BPF_PC_REGNUM + 1)
+
+struct gdbarch_tdep
+{
+ int xxx;
+};
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index fdcb7b1..e8d5fb4 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -142,6 +142,10 @@ bfin-*-*)
gdb_sim=../sim/bfin/libsim.a
;;
+bpf*)
+ # Target: eBPF
+ gdb_target_obs="bpf-tdep.o"
+ ;;
cris*)
# Target: CRIS
gdb_target_obs="cris-tdep.o cris-linux-tdep.o linux-tdep.o solib-svr4.o"
diff --git a/include/dis-asm.h b/include/dis-asm.h
index 6f1801d..cbfebc8 100644
--- a/include/dis-asm.h
+++ b/include/dis-asm.h
@@ -241,6 +241,7 @@ extern int print_insn_aarch64 (bfd_vma, disassemble_info *);
extern int print_insn_alpha (bfd_vma, disassemble_info *);
extern int print_insn_avr (bfd_vma, disassemble_info *);
extern int print_insn_bfin (bfd_vma, disassemble_info *);
+extern int print_insn_bpf (bfd_vma, disassemble_info *);
extern int print_insn_big_arm (bfd_vma, disassemble_info *);
extern int print_insn_big_mips (bfd_vma, disassemble_info *);
extern int print_insn_big_nios2 (bfd_vma, disassemble_info *);
diff --git a/include/elf/bpf.h b/include/elf/bpf.h
new file mode 100644
index 0000000..4aa38cc
--- /dev/null
+++ b/include/elf/bpf.h
@@ -0,0 +1,39 @@
+/* BPF ELF support for BFD.
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#ifndef _ELF_BPF_H
+#define _ELF_BPF_H
+
+#include "elf/reloc-macros.h"
+
+/* Relocation types. */
+START_RELOC_NUMBERS (elf_bpf_reloc_type)
+ RELOC_NUMBER (R_BPF_NONE, 0)
+ RELOC_NUMBER (R_BPF_INSN_64, 1)
+ RELOC_NUMBER (R_BPF_INSN_32, 2)
+ RELOC_NUMBER (R_BPF_INSN_16, 3)
+ RELOC_NUMBER (R_BPF_WDISP16, 4)
+ RELOC_NUMBER (R_BPF_DATA_8, 8)
+ RELOC_NUMBER (R_BPF_DATA_16, 9)
+ RELOC_NUMBER (R_BPF_DATA_32, 10)
+ RELOC_NUMBER (R_BPF_DATA_64, 11)
+END_RELOC_NUMBERS (R_BPF_max)
+
+#endif /* _ELF_BPF_H */
diff --git a/include/opcode/bpf.h b/include/opcode/bpf.h
new file mode 100644
index 0000000..298ed1b
--- /dev/null
+++ b/include/opcode/bpf.h
@@ -0,0 +1,16 @@
+#ifndef OPCODE_BPF_H
+#define OPCODE_BPF_H
+
+/* Structure of an opcode table entry. */
+
+typedef struct bpf_opcode
+{
+ const char *name;
+ unsigned char code;
+ const char *args;
+} bpf_opcode;
+
+extern const struct bpf_opcode bpf_opcodes[];
+extern const int bpf_num_opcodes;
+
+#endif /* OPCODE_BPF_H */
diff --git a/ld/Makefile.am b/ld/Makefile.am
index 3aa7e80..d840bed 100644
--- a/ld/Makefile.am
+++ b/ld/Makefile.am
@@ -477,6 +477,7 @@ ALL_64_EMULATION_SOURCES = \
eelf32ltsmipn32_fbsd.c \
eelf32mipswindiss.c \
eelf64_aix.c \
+ eelf64_bpf.c \
eelf64_ia64.c \
eelf64_ia64_fbsd.c \
eelf64_ia64_vms.c \
@@ -1920,6 +1921,9 @@ eelf32_x86_64_nacl.c: $(srcdir)/emulparams/elf32_x86_64_nacl.sh \
eelf64_aix.c: $(srcdir)/emulparams/elf64_aix.sh \
$(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+eelf64_bpf.c: $(srcdir)/emulparams/elf64_bpf.sh \
+ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+
eelf64_ia64.c: $(srcdir)/emulparams/elf64_ia64.sh \
$(ELF_DEPS) $(srcdir)/emultempl/ia64elf.em \
$(srcdir)/emultempl/needrelax.em \
diff --git a/ld/Makefile.in b/ld/Makefile.in
index f485f4f..706a889 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -845,6 +845,7 @@ ALL_64_EMULATION_SOURCES = \
eelf32ltsmipn32_fbsd.c \
eelf32mipswindiss.c \
eelf64_aix.c \
+ eelf64_bpf.c \
eelf64_ia64.c \
eelf64_ia64_fbsd.c \
eelf64_ia64_vms.c \
@@ -1292,6 +1293,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xstormy16.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_bpf.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_vms.Po@am__quote@
@@ -3484,6 +3486,9 @@ eelf32_x86_64_nacl.c: $(srcdir)/emulparams/elf32_x86_64_nacl.sh \
eelf64_aix.c: $(srcdir)/emulparams/elf64_aix.sh \
$(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+eelf64_bpf.c: $(srcdir)/emulparams/elf64_bpf.sh \
+ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+
eelf64_ia64.c: $(srcdir)/emulparams/elf64_ia64.sh \
$(ELF_DEPS) $(srcdir)/emultempl/ia64elf.em \
$(srcdir)/emultempl/needrelax.em \
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 895f0fb..13645f5 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -177,6 +177,8 @@ bfin-*-linux-uclibc*) targ_emul=elf32bfinfd;
targ_extra_emuls="elf32bfin"
targ_extra_libpath=$targ_extra_emuls
;;
+bpf-*-elf) targ_emul=elf64_bpf
+ ;;
cr16-*-elf*) targ_emul=elf32cr16 ;;
cr16c-*-elf*) targ_emul=elf32cr16c
;;
diff --git a/ld/emulparams/elf64_bpf.sh b/ld/emulparams/elf64_bpf.sh
new file mode 100644
index 0000000..0e1e549
--- /dev/null
+++ b/ld/emulparams/elf64_bpf.sh
@@ -0,0 +1,8 @@
+# See genscripts.sh and ../scripttempl/elf.sc for the meaning of these.
+SCRIPT_NAME=elf
+ELFSIZE=64
+TEMPLATE_NAME=elf32
+OUTPUT_FORMAT="elf64-bpf"
+TARGET_PAGE_SIZE=0x1000
+ARCH=bpf
+MACHINE=
diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am
index 1ac6bb1..ccc9453 100644
--- a/opcodes/Makefile.am
+++ b/opcodes/Makefile.am
@@ -105,6 +105,8 @@ TARGET_LIBOPCODES_CFILES = \
arm-dis.c \
avr-dis.c \
bfin-dis.c \
+ bpf-dis.c \
+ bpf-opc.c \
cgen-asm.c \
cgen-bitset.c \
cgen-dis.c \
diff --git a/opcodes/bpf-dis.c b/opcodes/bpf-dis.c
new file mode 100644
index 0000000..39656bf
--- /dev/null
+++ b/opcodes/bpf-dis.c
@@ -0,0 +1,161 @@
+#include "sysdep.h"
+#include <stdio.h>
+#include "opcode/bpf.h"
+#include "dis-asm.h"
+#include "libiberty.h"
+
+#define HASH_SIZE 256
+#define HASH_INSN(CODE) (CODE)
+
+typedef struct bpf_opcode_hash
+{
+ struct bpf_opcode_hash *next;
+ const bpf_opcode *opcode;
+} bpf_opcode_hash;
+
+static bpf_opcode_hash *opcode_hash_table[HASH_SIZE];
+
+static void
+build_hash_table (const bpf_opcode *opcode_table,
+ bpf_opcode_hash **hash_table,
+ int num_opcodes)
+{
+ static bpf_opcode_hash *hash_buf = NULL;
+ int i;
+
+ memset (hash_table, 0, HASH_SIZE * sizeof (hash_table[0]));
+ if (hash_buf != NULL)
+ free (hash_buf);
+ hash_buf = xmalloc (sizeof (* hash_buf) * num_opcodes);
+ for (i = num_opcodes - 1; i >= 0; --i)
+ {
+ int hash = HASH_INSN (opcode_table[i].code);
+ bpf_opcode_hash *h = &hash_buf[i];
+
+ h->next = hash_table[hash];
+ h->opcode = &opcode_table[i];
+ hash_table[hash] = h;
+ }
+}
+
+int
+print_insn_bpf (bfd_vma memaddr, disassemble_info *info)
+{
+ static unsigned long current_mach = 0;
+ static int opcodes_initialized = 0;
+ bfd_vma (*getword) (const void *);
+ bfd_vma (*gethalf) (const void *);
+ FILE *stream = info->stream;
+ bpf_opcode_hash *op;
+ int code, dest, src;
+ bfd_byte buffer[8];
+ signed short off;
+ int status, ret;
+ signed int imm;
+
+ if (!opcodes_initialized
+ || info->mach != current_mach)
+ {
+ build_hash_table (bpf_opcodes, opcode_hash_table, bpf_num_opcodes);
+ current_mach = info->mach;
+ opcodes_initialized = 1;
+ }
+
+ info->bytes_per_line = 8;
+
+ status = (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+
+ if (info->endian == BFD_ENDIAN_BIG)
+ {
+ getword = bfd_getb32;
+ gethalf = bfd_getb16;
+ }
+ else
+ {
+ getword = bfd_getl32;
+ gethalf = bfd_getl16;
+ }
+
+ code = buffer[0];
+ dest = (buffer[1] & 0xf0) >> 4;
+ src = buffer[1] & 0x0f;
+ off = gethalf(&buffer[2]);
+ imm = getword(&buffer[4]);
+
+ ret = sizeof (buffer);
+ for (op = opcode_hash_table[HASH_INSN (code)]; op; op = op->next)
+ {
+ const bpf_opcode *opcode = op->opcode;
+ BFD_HOST_U_64_BIT value;
+ signed int imm2;
+ const char *s;
+
+ if (opcode->code != code)
+ continue;
+
+ if (!strcmp (opcode->name, "mov")
+ && !strcmp (opcode->args, "1,2")
+ && src == 0 && dest == 0)
+ {
+ (*info->fprintf_func) (stream, "%s\t", opcode->name);
+ break;
+ }
+
+ (*info->fprintf_func) (stream, "%s\t", opcode->name);
+ for (s = opcode->args; *s != '\0'; s++)
+ {
+ switch (*s)
+ {
+ case '+':
+ default:
+ (*info->fprintf_func) (stream, "%c", *s);
+ break;
+ case ',':
+ (*info->fprintf_func) (stream, ", ");
+ break;
+ case '1':
+ (*info->fprintf_func) (stream, "r%d", dest);
+ break;
+ case '2':
+ (*info->fprintf_func) (stream, "r%d", src);
+ break;
+ case 'i':
+ (*info->fprintf_func) (stream, "%d", imm);
+ break;
+ case 'O':
+ (*info->fprintf_func) (stream, "%d", (int) off);
+ break;
+ case 'L':
+ info->target = memaddr + ((off - 1) * 8);
+ (*info->print_address_func) (info->target, info);
+ break;
+ case 'C':
+ info->target = imm;
+ (*info->print_address_func) (info->target, info);
+ break;
+ case 'D':
+ status = (*info->read_memory_func) (memaddr + 8, buffer,
+ sizeof (buffer), info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
+ }
+ ret += sizeof (buffer);
+ imm2 = getword(&buffer[4]);
+ value = ((BFD_HOST_U_64_BIT) (unsigned) imm2) << 32;
+ value |= (BFD_HOST_U_64_BIT) (unsigned) imm;
+ (*info->fprintf_func) (stream, "%lld", (long long) value);
+ break;
+ }
+ }
+ break;
+ }
+
+ return ret;
+}
diff --git a/opcodes/bpf-opc.c b/opcodes/bpf-opc.c
new file mode 100644
index 0000000..8afb637
--- /dev/null
+++ b/opcodes/bpf-opc.c
@@ -0,0 +1,147 @@
+#include "sysdep.h"
+#include <stdio.h>
+#include "opcode/bpf.h"
+
+#define BPF_OPC_ALU64 0x07
+#define BPF_OPC_DW 0x18
+#define BPF_OPC_XADD 0xc0
+#define BPF_OPC_MOV 0xb0
+#define BPF_OPC_ARSH 0xc0
+#define BPF_OPC_END 0xd0
+#define BPF_OPC_TO_LE 0x00
+#define BPF_OPC_TO_BE 0x08
+#define BPF_OPC_JNE 0x50
+#define BPF_OPC_JSGT 0x60
+#define BPF_OPC_JSGE 0x70
+#define BPF_OPC_CALL 0x80
+#define BPF_OPC_EXIT 0x90
+
+#define BPF_OPC_LD 0x00
+#define BPF_OPC_LDX 0x01
+#define BPF_OPC_ST 0x02
+#define BPF_OPC_STX 0x03
+#define BPF_OPC_ALU 0x04
+#define BPF_OPC_JMP 0x05
+#define BPF_OPC_RET 0x06
+#define BPF_OPC_MISC 0x07
+
+#define BPF_OPC_W 0x00
+#define BPF_OPC_H 0x08
+#define BPF_OPC_B 0x10
+
+#define BPF_OPC_IMM 0x00
+#define BPF_OPC_ABS 0x20
+#define BPF_OPC_IND 0x40
+#define BPF_OPC_MEM 0x60
+#define BPF_OPC_LEL 0x80
+#define BPF_OPC_MSH 0xa0
+
+#define BPF_OPC_ADD 0x00
+#define BPF_OPC_SUB 0x10
+#define BPF_OPC_MUL 0x20
+#define BPF_OPC_DIV 0x30
+#define BPF_OPC_OR 0x40
+#define BPF_OPC_AND 0x50
+#define BPF_OPC_LSH 0x60
+#define BPF_OPC_RSH 0x70
+#define BPF_OPC_NEG 0x80
+#define BPF_OPC_MOD 0x90
+#define BPF_OPC_XOR 0xa0
+
+#define BPF_OPC_JA 0x00
+#define BPF_OPC_JEQ 0x10
+#define BPF_OPC_JGT 0x20
+#define BPF_OPC_JGE 0x30
+#define BPF_OPC_JSET 0x40
+
+#define BPF_OPC_K 0x00
+#define BPF_OPC_X 0x08
+
+const struct bpf_opcode bpf_opcodes[] = {
+ { "mov32", BPF_OPC_ALU | BPF_OPC_MOV | BPF_OPC_X, "1,2" },
+ { "mov32", BPF_OPC_ALU | BPF_OPC_MOV | BPF_OPC_K, "1,i" },
+ { "mov", BPF_OPC_ALU64 | BPF_OPC_MOV | BPF_OPC_X, "1,2" },
+ { "mov", BPF_OPC_ALU64 | BPF_OPC_MOV | BPF_OPC_K, "1,i" },
+ { "nop", BPF_OPC_ALU64 | BPF_OPC_MOV | BPF_OPC_X, "" },
+ { "add32", BPF_OPC_ALU | BPF_OPC_ADD | BPF_OPC_X, "1,2" },
+ { "add32", BPF_OPC_ALU | BPF_OPC_ADD | BPF_OPC_K, "1,i" },
+ { "add", BPF_OPC_ALU64 | BPF_OPC_ADD | BPF_OPC_X, "1,2" },
+ { "add", BPF_OPC_ALU64 | BPF_OPC_ADD | BPF_OPC_K, "1,i" },
+ { "sub32", BPF_OPC_ALU | BPF_OPC_SUB | BPF_OPC_X, "1,2" },
+ { "sub32", BPF_OPC_ALU | BPF_OPC_SUB | BPF_OPC_K, "1,i" },
+ { "sub", BPF_OPC_ALU64 | BPF_OPC_SUB | BPF_OPC_X, "1,2" },
+ { "sub", BPF_OPC_ALU64 | BPF_OPC_SUB | BPF_OPC_K, "1,i" },
+ { "and32", BPF_OPC_ALU | BPF_OPC_AND | BPF_OPC_X, "1,2" },
+ { "and32", BPF_OPC_ALU | BPF_OPC_AND | BPF_OPC_K, "1,i" },
+ { "and", BPF_OPC_ALU64 | BPF_OPC_AND | BPF_OPC_X, "1,2" },
+ { "and", BPF_OPC_ALU64 | BPF_OPC_AND | BPF_OPC_K, "1,i" },
+ { "or32", BPF_OPC_ALU | BPF_OPC_OR | BPF_OPC_X, "1,2" },
+ { "or32", BPF_OPC_ALU | BPF_OPC_XOR | BPF_OPC_K, "1,i" },
+ { "or", BPF_OPC_ALU64 | BPF_OPC_OR | BPF_OPC_X, "1,2" },
+ { "or", BPF_OPC_ALU64 | BPF_OPC_XOR | BPF_OPC_K, "1,i" },
+ { "xor32", BPF_OPC_ALU | BPF_OPC_XOR | BPF_OPC_X, "1,2" },
+ { "xor32", BPF_OPC_ALU | BPF_OPC_OR | BPF_OPC_K, "1,i" },
+ { "xor", BPF_OPC_ALU64 | BPF_OPC_XOR | BPF_OPC_X, "1,2" },
+ { "xor", BPF_OPC_ALU64 | BPF_OPC_OR | BPF_OPC_K, "1,i" },
+ { "mul32", BPF_OPC_ALU | BPF_OPC_MUL | BPF_OPC_X, "1,2" },
+ { "mul32", BPF_OPC_ALU | BPF_OPC_MUL | BPF_OPC_K, "1,i" },
+ { "mul", BPF_OPC_ALU64 | BPF_OPC_MUL | BPF_OPC_X, "1,2" },
+ { "mul", BPF_OPC_ALU64 | BPF_OPC_MUL | BPF_OPC_K, "1,i" },
+ { "div32", BPF_OPC_ALU | BPF_OPC_DIV | BPF_OPC_X, "1,2" },
+ { "div32", BPF_OPC_ALU | BPF_OPC_DIV | BPF_OPC_K, "1,i" },
+ { "div", BPF_OPC_ALU64 | BPF_OPC_DIV | BPF_OPC_X, "1,2" },
+ { "div", BPF_OPC_ALU64 | BPF_OPC_DIV | BPF_OPC_K, "1,i" },
+ { "mod32", BPF_OPC_ALU | BPF_OPC_MOD | BPF_OPC_X, "1,2" },
+ { "mod32", BPF_OPC_ALU | BPF_OPC_MOD | BPF_OPC_K, "1,i" },
+ { "mod", BPF_OPC_ALU64 | BPF_OPC_MOD | BPF_OPC_X, "1,2" },
+ { "mod", BPF_OPC_ALU64 | BPF_OPC_MOD | BPF_OPC_K, "1,i" },
+ { "lsh32", BPF_OPC_ALU | BPF_OPC_LSH | BPF_OPC_X, "1,2" },
+ { "lsh32", BPF_OPC_ALU | BPF_OPC_LSH | BPF_OPC_K, "1,i" },
+ { "lsh", BPF_OPC_ALU64 | BPF_OPC_LSH | BPF_OPC_X, "1,2" },
+ { "lsh", BPF_OPC_ALU64 | BPF_OPC_LSH | BPF_OPC_K, "1,i" },
+ { "rsh32", BPF_OPC_ALU | BPF_OPC_RSH | BPF_OPC_X, "1,2" },
+ { "rsh32", BPF_OPC_ALU | BPF_OPC_RSH | BPF_OPC_K, "1,i" },
+ { "rsh", BPF_OPC_ALU64 | BPF_OPC_RSH | BPF_OPC_X, "1,2" },
+ { "rsh", BPF_OPC_ALU64 | BPF_OPC_RSH | BPF_OPC_K, "1,i" },
+ { "arsh32", BPF_OPC_ALU | BPF_OPC_ARSH | BPF_OPC_X, "1,2" },
+ { "arsh32", BPF_OPC_ALU | BPF_OPC_ARSH | BPF_OPC_K, "1,i" },
+ { "arsh", BPF_OPC_ALU64 | BPF_OPC_ARSH | BPF_OPC_X, "1,2" },
+ { "arsh", BPF_OPC_ALU64 | BPF_OPC_ARSH | BPF_OPC_K, "1,i" },
+ { "neg32", BPF_OPC_ALU | BPF_OPC_NEG | BPF_OPC_X, "1" },
+ { "neg", BPF_OPC_ALU64 | BPF_OPC_NEG | BPF_OPC_X, "1" },
+ { "endbe", BPF_OPC_ALU | BPF_OPC_END | BPF_OPC_TO_BE, "1,i" },
+ { "endle", BPF_OPC_ALU | BPF_OPC_END | BPF_OPC_TO_LE, "1,i" },
+ { "ja", BPF_OPC_JMP | BPF_OPC_JA, "L" },
+ { "jeq", BPF_OPC_JMP | BPF_OPC_JEQ | BPF_OPC_X, "1,2,L" },
+ { "jeq", BPF_OPC_JMP | BPF_OPC_JEQ | BPF_OPC_K, "1,i,L" },
+ { "jgt", BPF_OPC_JMP | BPF_OPC_JGT | BPF_OPC_X, "1,2,L" },
+ { "jgt", BPF_OPC_JMP | BPF_OPC_JGT | BPF_OPC_K, "1,i,L" },
+ { "jge", BPF_OPC_JMP | BPF_OPC_JGE | BPF_OPC_X, "1,2,L" },
+ { "jge", BPF_OPC_JMP | BPF_OPC_JGE | BPF_OPC_K, "1,i,L" },
+ { "jne", BPF_OPC_JMP | BPF_OPC_JNE | BPF_OPC_X, "1,2,L" },
+ { "jne", BPF_OPC_JMP | BPF_OPC_JNE | BPF_OPC_K, "1,i,L" },
+ { "jsgt", BPF_OPC_JMP | BPF_OPC_JSGT | BPF_OPC_X, "1,2,L" },
+ { "jsgt", BPF_OPC_JMP | BPF_OPC_JSGT | BPF_OPC_K, "1,i,L" },
+ { "jsge", BPF_OPC_JMP | BPF_OPC_JSGE | BPF_OPC_X, "1,2,L" },
+ { "jsge", BPF_OPC_JMP | BPF_OPC_JSGE | BPF_OPC_K, "1,i,L" },
+ { "jset", BPF_OPC_JMP | BPF_OPC_JSET | BPF_OPC_X, "1,2,L" },
+ { "jset", BPF_OPC_JMP | BPF_OPC_JSET | BPF_OPC_K, "1,i,L" },
+ { "call", BPF_OPC_JMP | BPF_OPC_CALL, "C" },
+ { "exit", BPF_OPC_JMP | BPF_OPC_EXIT, "" },
+ { "ldimm64", BPF_OPC_LD | BPF_OPC_IMM | BPF_OPC_DW, "1,D" },
+ { "ldw", BPF_OPC_LDX | BPF_OPC_MEM | BPF_OPC_W, "1,[2+O]" },
+ { "ldh", BPF_OPC_LDX | BPF_OPC_MEM | BPF_OPC_H, "1,[2+O]" },
+ { "ldb", BPF_OPC_LDX | BPF_OPC_MEM | BPF_OPC_B, "1,[2+O]" },
+ { "lddw", BPF_OPC_LDX | BPF_OPC_MEM | BPF_OPC_DW, "1,[2+O]" },
+ { "stw", BPF_OPC_STX | BPF_OPC_MEM | BPF_OPC_W, "[1+O],2" },
+ { "stw", BPF_OPC_ST | BPF_OPC_MEM | BPF_OPC_W, "[1+O],i" },
+ { "sth", BPF_OPC_STX | BPF_OPC_MEM | BPF_OPC_H, "[1+O],2" },
+ { "sth", BPF_OPC_ST | BPF_OPC_MEM | BPF_OPC_H, "[1+O],i" },
+ { "stb", BPF_OPC_STX | BPF_OPC_MEM | BPF_OPC_B, "[1+O],2" },
+ { "stb", BPF_OPC_ST | BPF_OPC_MEM | BPF_OPC_B, "[1+O],i" },
+ { "stdw", BPF_OPC_STX | BPF_OPC_MEM | BPF_OPC_DW, "[1+O],2" },
+ { "stdw", BPF_OPC_ST | BPF_OPC_MEM | BPF_OPC_DW, "[1+O],i" },
+ { "xaddw", BPF_OPC_STX | BPF_OPC_XADD | BPF_OPC_W, "[1+O],2" },
+ { "xadddw", BPF_OPC_STX | BPF_OPC_XADD | BPF_OPC_DW, "[1+O],2" },
+};
+const int bpf_num_opcodes = ((sizeof bpf_opcodes)/(sizeof bpf_opcodes[0]));
diff --git a/opcodes/configure b/opcodes/configure
index 27d1472..7583220 100755
--- a/opcodes/configure
+++ b/opcodes/configure
@@ -12634,6 +12634,7 @@ if test x${all_targets} = xfalse ; then
bfd_arm_arch) ta="$ta arm-dis.lo" ;;
bfd_avr_arch) ta="$ta avr-dis.lo" ;;
bfd_bfin_arch) ta="$ta bfin-dis.lo" ;;
+ bfd_bpf_arch) ta="$ta bpf-dis.lo bpf-opc.lo" ;;
bfd_cr16_arch) ta="$ta cr16-dis.lo cr16-opc.lo" ;;
bfd_cris_arch) ta="$ta cris-dis.lo cris-opc.lo cgen-bitset.lo" ;;
bfd_crx_arch) ta="$ta crx-dis.lo crx-opc.lo" ;;
diff --git a/opcodes/configure.ac b/opcodes/configure.ac
index a9fbfd6..7dc6a92 100644
--- a/opcodes/configure.ac
+++ b/opcodes/configure.ac
@@ -258,6 +258,7 @@ if test x${all_targets} = xfalse ; then
bfd_arm_arch) ta="$ta arm-dis.lo" ;;
bfd_avr_arch) ta="$ta avr-dis.lo" ;;
bfd_bfin_arch) ta="$ta bfin-dis.lo" ;;
+ bfd_bpf_arch) ta="$ta bpf-dis.lo bpf-opc.lo" ;;
bfd_cr16_arch) ta="$ta cr16-dis.lo cr16-opc.lo" ;;
bfd_cris_arch) ta="$ta cris-dis.lo cris-opc.lo cgen-bitset.lo" ;;
bfd_crx_arch) ta="$ta crx-dis.lo crx-opc.lo" ;;
diff --git a/opcodes/disassemble.c b/opcodes/disassemble.c
index dd7d3a3..e594f86 100644
--- a/opcodes/disassemble.c
+++ b/opcodes/disassemble.c
@@ -29,6 +29,7 @@
#define ARCH_arm
#define ARCH_avr
#define ARCH_bfin
+#define ARCH_bpf
#define ARCH_cr16
#define ARCH_cris
#define ARCH_crx
@@ -151,6 +152,11 @@ disassembler (bfd *abfd)
disassemble = print_insn_bfin;
break;
#endif
+#ifdef ARCH_bpf
+ case bfd_arch_bpf:
+ disassemble = print_insn_bpf;
+ break;
+#endif
#ifdef ARCH_cr16
case bfd_arch_cr16:
disassemble = print_insn_cr16;
diff --git a/sim/configure.tgt b/sim/configure.tgt
index c958fb3..09eec72 100644
--- a/sim/configure.tgt
+++ b/sim/configure.tgt
@@ -26,6 +26,9 @@ case "${target}" in
bfin-*-*)
SIM_ARCH(bfin)
;;
+ bpf-*-*)
+ SIM_ARCH(bpf)
+ ;;
cr16*-*-*)
SIM_ARCH(cr16)
;;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH] netvsc: make sure napi enabled before vmbus_open
From: Stephen Hemminger @ 2017-04-30 16:22 UTC (permalink / raw)
To: David Miller; +Cc: netdev, sthemmin
In-Reply-To: <20170428.160913.1378797538282359486.davem@davemloft.net>
On Fri, 28 Apr 2017 16:09:13 -0400 (EDT)
David Miller <davem@davemloft.net> wrote:
> From: Stephen Hemminger <stephen@networkplumber.org>
> Date: Wed, 26 Apr 2017 16:58:30 -0700
>
> > This fixes a race where vmbus callback for new packet arriving
> > could occur before NAPI is initialized. Happens more on WS2008
> > which takes longer to setup channel.
> >
> > Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
>
> This doesn't apply cleanly to 'net'.
Patch was for net-next. Will resend in next group
^ permalink raw reply
* Re: [Patch net-next v2] ipv4: get rid of ip_ra_lock
From: Eric Dumazet @ 2017-04-30 16:42 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev
In-Reply-To: <1493399069-31743-1-git-send-email-xiyou.wangcong@gmail.com>
On Fri, 2017-04-28 at 10:04 -0700, Cong Wang wrote:
> After commit 1215e51edad1 ("ipv4: fix a deadlock in ip_ra_control")
> we always take RTNL lock for ip_ra_control() which is the only place
> we update the list ip_ra_chain, so the ip_ra_lock is no longer needed.
>
> As Eric points out, BH does not need to disable either, RCU readers
> don't care.
>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> ---
> net/ipv4/ip_sockglue.c | 9 +--------
> 1 file changed, 1 insertion(+), 8 deletions(-)
>
> diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
> index 1d46d05..4c25458 100644
> --- a/net/ipv4/ip_sockglue.c
> +++ b/net/ipv4/ip_sockglue.c
> @@ -330,7 +330,6 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
> sent to multicast group to reach destination designated router.
> */
> struct ip_ra_chain __rcu *ip_ra_chain;
> -static DEFINE_SPINLOCK(ip_ra_lock);
>
>
> static void ip_ra_destroy_rcu(struct rcu_head *head)
> @@ -352,21 +351,17 @@ int ip_ra_control(struct sock *sk, unsigned char on,
>
> new_ra = on ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL;
>
> - spin_lock_bh(&ip_ra_lock);
> for (rap = &ip_ra_chain;
> - (ra = rcu_dereference_protected(*rap,
> - lockdep_is_held(&ip_ra_lock))) != NULL;
> + (ra = rtnl_dereference(*rap)) != NULL;
> rap = &ra->next) {
> if (ra->sk == sk) {
> if (on) {
> - spin_unlock_bh(&ip_ra_lock);
> kfree(new_ra);
> return -EADDRINUSE;
> }
> /* dont let ip_call_ra_chain() use sk again */
> ra->sk = NULL;
> RCU_INIT_POINTER(*rap, ra->next);
> - spin_unlock_bh(&ip_ra_lock);
>
> if (ra->destructor)
> ra->destructor(sk);
> @@ -381,7 +376,6 @@ int ip_ra_control(struct sock *sk, unsigned char on,
> }
> }
> if (!new_ra) {
> - spin_unlock_bh(&ip_ra_lock);
> return -ENOBUFS;
> }
Minor point : You could have removed the {}
Acked-by: Eric Dumazet <edumazet@google.com>
Thanks !
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox