Resolves: bz 1307431

This commit is contained in:
Neil Horman 2016-02-16 11:52:18 -05:00
parent cbae95aa4c
commit 587202f673
14 changed files with 379 additions and 1 deletions

View File

@ -0,0 +1,12 @@
diff -up ./drivers/net/bnx2x/bnx2x.h.bnx2x ./drivers/net/bnx2x/bnx2x.h
--- ./drivers/net/bnx2x/bnx2x.h.bnx2x 2016-02-15 15:05:01.900577388 -0500
+++ ./drivers/net/bnx2x/bnx2x.h 2016-02-15 15:06:26.037956379 -0500
@@ -1608,7 +1608,7 @@ void bnx2x_reg_write32(struct bnx2x_soft
#define INIT_DMAE_C(sc) ((SC_PORT(sc) * MAX_DMAE_C_PER_PORT) + SC_VN(sc))
#define PMF_DMAE_C(sc) ((SC_PORT(sc) * MAX_DMAE_C_PER_PORT) + E1HVN_MAX)
-static const uint32_t dmae_reg_go_c[] = {
+static const uint32_t dmae_reg_go_c[] __attribute__((unused)) = {
DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,

33
dpdk-2.2-indent.patch Normal file
View File

@ -0,0 +1,33 @@
diff -up ./drivers/net/e1000/base/e1000_phy.c.indent ./drivers/net/e1000/base/e1000_phy.c
--- ./drivers/net/e1000/base/e1000_phy.c.indent 2016-02-15 13:42:25.576470272 -0500
+++ ./drivers/net/e1000/base/e1000_phy.c 2016-02-15 13:48:18.070422353 -0500
@@ -4153,12 +4153,13 @@ s32 e1000_read_phy_reg_mphy(struct e1000
*data = E1000_READ_REG(hw, E1000_MPHY_DATA);
/* Disable access to mPHY if it was originally disabled */
- if (locked)
+ if (locked) {
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
E1000_MPHY_DIS_ACCESS);
+ }
return E1000_SUCCESS;
}
@@ -4218,12 +4219,13 @@ s32 e1000_write_phy_reg_mphy(struct e100
E1000_WRITE_REG(hw, E1000_MPHY_DATA, data);
/* Disable access to mPHY if it was originally disabled */
- if (locked)
+ if (locked) {
ready = e1000_is_mphy_ready(hw);
if (!ready)
return -E1000_ERR_PHY;
E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
E1000_MPHY_DIS_ACCESS);
+ }
return E1000_SUCCESS;
}

View File

@ -0,0 +1,16 @@
diff -up ./drivers/net/ixgbe/ixgbe_ethdev.c.ixgbe_ethdev ./drivers/net/ixgbe/ixgbe_ethdev.c
--- ./drivers/net/ixgbe/ixgbe_ethdev.c.ixgbe_ethdev 2016-02-15 15:27:26.677573547 -0500
+++ ./drivers/net/ixgbe/ixgbe_ethdev.c 2016-02-15 15:28:41.771693991 -0500
@@ -4258,10 +4258,11 @@ ixgbe_set_pool_vlan_filter(struct rte_et
if (ixgbe_vmdq_mode_check(hw) < 0)
return (-ENOTSUP);
for (pool_idx = 0; pool_idx < ETH_64_POOLS; pool_idx++) {
- if (pool_mask & ((uint64_t)(1ULL << pool_idx)))
+ if (pool_mask & ((uint64_t)(1ULL << pool_idx))) {
ret = hw->mac.ops.set_vfta(hw,vlan,pool_idx,vlan_on);
if (ret < 0)
return ret;
+ }
}
return ret;

View File

@ -0,0 +1,12 @@
diff -up ./drivers/net/ixgbe/ixgbe_rxtx.c.ixgbe ./drivers/net/ixgbe/ixgbe_rxtx.c
--- ./drivers/net/ixgbe/ixgbe_rxtx.c.ixgbe 2016-02-15 15:07:07.874139300 -0500
+++ ./drivers/net/ixgbe/ixgbe_rxtx.c 2016-02-15 15:09:18.420830519 -0500
@@ -1574,6 +1574,8 @@ ixgbe_recv_pkts_lro(void *rx_queue, stru
uint32_t staterr;
next_desc:
+ next_rxe = NULL;
+
/*
* The code in this whole file uses the volatile pointer to
* ensure the read ordering of the status and the rest of the

View File

@ -0,0 +1,15 @@
diff -up ./drivers/net/ixgbe/ixgbe_pf.c.ixgbe_pf ./drivers/net/ixgbe/ixgbe_pf.c
--- ./drivers/net/ixgbe/ixgbe_pf.c.ixgbe_pf 2016-02-15 15:39:44.723411150 -0500
+++ ./drivers/net/ixgbe/ixgbe_pf.c 2016-02-15 15:40:16.297302507 -0500
@@ -236,9 +236,9 @@ int ixgbe_pf_host_configure(struct rte_e
vfre_slot = (vf_num >> VFRE_SHIFT) > 0 ? 1 : 0;
/* Enable pools reserved to PF only */
- IXGBE_WRITE_REG(hw, IXGBE_VFRE(vfre_slot), (~0) << vfre_offset);
+ IXGBE_WRITE_REG(hw, IXGBE_VFRE(vfre_slot), UINT_MAX << vfre_offset);
IXGBE_WRITE_REG(hw, IXGBE_VFRE(vfre_slot ^ 1), vfre_slot - 1);
- IXGBE_WRITE_REG(hw, IXGBE_VFTE(vfre_slot), (~0) << vfre_offset);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTE(vfre_slot), UINT_MAX << vfre_offset);
IXGBE_WRITE_REG(hw, IXGBE_VFTE(vfre_slot ^ 1), vfre_slot - 1);
/* PFDMA Tx General Switch Control Enables VMDQ loopback */

21
dpdk-2.2-l3fwd-main.patch Normal file
View File

@ -0,0 +1,21 @@
diff -up ./examples/l3fwd/main.c.mainfix ./examples/l3fwd/main.c
--- ./examples/l3fwd/main.c.mainfix 2016-02-16 11:35:19.639478702 -0500
+++ ./examples/l3fwd/main.c 2016-02-16 11:37:30.337193083 -0500
@@ -1098,7 +1098,7 @@ l3fwd_simple_forward(struct rte_mbuf *m,
++(ipv4_hdr->hdr_checksum);
#endif
/* dst addr */
- *(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[dst_port];
+ memcpy(&eth_hdr->d_addr, &dest_eth_addr[dst_port], sizeof(uint64_t));
/* src addr */
ether_addr_copy(&ports_eth_addr[dst_port], &eth_hdr->s_addr);
@@ -1117,7 +1117,7 @@ l3fwd_simple_forward(struct rte_mbuf *m,
dst_port = portid;
/* dst addr */
- *(uint64_t *)&eth_hdr->d_addr = dest_eth_addr[dst_port];
+ memcpy(&eth_hdr->d_addr, &dest_eth_addr[dst_port], sizeof(uint64_t));
/* src addr */
ether_addr_copy(&ports_eth_addr[dst_port], &eth_hdr->s_addr);

View File

@ -0,0 +1,16 @@
diff -up ./examples/ip_pipeline/pipeline/pipeline_firewall.c.pfire ./examples/ip_pipeline/pipeline/pipeline_firewall.c
--- ./examples/ip_pipeline/pipeline/pipeline_firewall.c.pfire 2016-02-16 10:16:03.856528168 -0500
+++ ./examples/ip_pipeline/pipeline/pipeline_firewall.c 2016-02-16 10:17:31.128996838 -0500
@@ -256,10 +256,10 @@ app_pipeline_firewall_key_check_and_norm
return -1;
if (src_ip_depth)
- src_ip_netmask = (~0) << (32 - src_ip_depth);
+ src_ip_netmask = UINT_MAX << (32 - src_ip_depth);
if (dst_ip_depth)
- dst_ip_netmask = ((~0) << (32 - dst_ip_depth));
+ dst_ip_netmask = (UINT_MAX << (32 - dst_ip_depth));
key->key.ipv4_5tuple.src_ip &= src_ip_netmask;
key->key.ipv4_5tuple.dst_ip &= dst_ip_netmask;

View File

@ -0,0 +1,21 @@
diff -up ./examples/ip_pipeline/pipeline/pipeline_common_fe.c.pipe_common ./examples/ip_pipeline/pipeline/pipeline_common_fe.c
--- ./examples/ip_pipeline/pipeline/pipeline_common_fe.c.pipe_common 2016-02-15 16:51:32.161025145 -0500
+++ ./examples/ip_pipeline/pipeline/pipeline_common_fe.c 2016-02-15 16:55:05.654052482 -0500
@@ -337,7 +337,7 @@ app_link_config(struct app_params *app,
return -1;
}
- netmask = (~0) << (32 - depth);
+ netmask = UINT_MAX << (32 - depth);
host = ip & netmask;
bcast = host | (~netmask);
@@ -889,7 +889,7 @@ print_link_info(struct app_link_params *
{
struct rte_eth_stats stats;
struct ether_addr *mac_addr;
- uint32_t netmask = (~0) << (32 - p->depth);
+ uint32_t netmask = UINT_MAX << (32 - p->depth);
uint32_t host = p->ip & netmask;
uint32_t bcast = host | (~netmask);

View File

@ -0,0 +1,39 @@
diff -up ./examples/ip_pipeline/pipeline/pipeline_routing_be.c.proutebe ./examples/ip_pipeline/pipeline/pipeline_routing_be.c
--- ./examples/ip_pipeline/pipeline/pipeline_routing_be.c.proutebe 2015-12-15 12:06:58.000000000 -0500
+++ ./examples/ip_pipeline/pipeline/pipeline_routing_be.c 2016-02-16 11:22:04.187871609 -0500
@@ -1461,7 +1461,7 @@ pipeline_routing_msg_req_route_add_handl
uint64_t macaddr_dst;
uint64_t ethertype = ETHER_TYPE_IPv4;
- macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
+ memcpy(&macaddr_dst, &(req->data.ethernet.macaddr), sizeof(uint64_t));
macaddr_dst = rte_bswap64(macaddr_dst << 16);
entry_arp0.slab[0] =
@@ -1502,7 +1502,7 @@ pipeline_routing_msg_req_route_add_handl
uint64_t svlan = req->data.l2.qinq.svlan;
uint64_t cvlan = req->data.l2.qinq.cvlan;
- macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
+ memcpy(&macaddr_dst, &(req->data.ethernet.macaddr), sizeof(uint64_t));
macaddr_dst = rte_bswap64(macaddr_dst << 16);
entry_arp0.slab[0] = rte_bswap64((svlan << 48) |
@@ -1561,7 +1561,7 @@ pipeline_routing_msg_req_route_add_handl
uint64_t label3 = req->data.l2.mpls.labels[3];
uint32_t n_labels = req->data.l2.mpls.n_labels;
- macaddr_dst = *((uint64_t *)&(req->data.ethernet.macaddr));
+ memcpy(&macaddr_dst, &(req->data.ethernet.macaddr), sizeof(uint64_t));
macaddr_dst = rte_bswap64(macaddr_dst << 16);
switch (n_labels) {
@@ -1811,7 +1811,7 @@ pipeline_routing_msg_req_arp_add_handler
return rsp;
}
- entry.macaddr = *((uint64_t *)&(req->macaddr));
+ memcpy(&entry.macaddr, &(req->macaddr), sizeof(uint64_t));
entry.macaddr = entry.macaddr << 16;
rsp->status = rte_pipeline_table_entry_add(p->p,

View File

@ -0,0 +1,21 @@
diff -up ./examples/ip_pipeline/pipeline/pipeline_routing.c.pipe_route ./examples/ip_pipeline/pipeline/pipeline_routing.c
--- ./examples/ip_pipeline/pipeline/pipeline_routing.c.pipe_route 2016-02-15 16:37:25.909132363 -0500
+++ ./examples/ip_pipeline/pipeline/pipeline_routing.c 2016-02-15 16:38:28.644903861 -0500
@@ -319,7 +319,7 @@ app_pipeline_routing_add_route(struct ap
if ((depth == 0) || (depth > 32))
return -1;
- netmask = (~0) << (32 - depth);
+ netmask = UINT_MAX << (32 - depth);
key->key.ipv4.ip &= netmask;
/* data */
@@ -421,7 +421,7 @@ app_pipeline_routing_delete_route(struct
if ((depth == 0) || (depth > 32))
return -1;
- netmask = (~0) << (32 - depth);
+ netmask = UINT_MAX << (32 - depth);
key->key.ipv4.ip &= netmask;
}
break;

95
dpdk-2.2-punning.patch Normal file
View File

@ -0,0 +1,95 @@
diff -up ./lib/librte_lpm/rte_lpm.h.pun ./lib/librte_lpm/rte_lpm.h
--- ./lib/librte_lpm/rte_lpm.h.pun 2015-12-15 12:06:58.000000000 -0500
+++ ./lib/librte_lpm/rte_lpm.h 2016-02-15 12:45:26.306750412 -0500
@@ -43,6 +43,7 @@
#include <sys/queue.h>
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <rte_branch_prediction.h>
#include <rte_byteorder.h>
#include <rte_memory.h>
@@ -286,7 +287,7 @@ rte_lpm_lookup(struct rte_lpm *lpm, uint
RTE_LPM_RETURN_IF_TRUE(((lpm == NULL) || (next_hop == NULL)), -EINVAL);
/* Copy tbl24 entry */
- tbl_entry = *(const uint16_t *)&lpm->tbl24[tbl24_index];
+ memcpy(&tbl_entry, &lpm->tbl24[tbl24_index], sizeof(uint16_t));
/* Copy tbl8 entry (only if needed) */
if (unlikely((tbl_entry & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
@@ -295,7 +296,7 @@ rte_lpm_lookup(struct rte_lpm *lpm, uint
unsigned tbl8_index = (uint8_t)ip +
((uint8_t)tbl_entry * RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
- tbl_entry = *(const uint16_t *)&lpm->tbl8[tbl8_index];
+ memcpy(&tbl_entry, &lpm->tbl8[tbl8_index], sizeof(uint16_t));
}
*next_hop = (uint8_t)tbl_entry;
@@ -342,7 +343,7 @@ rte_lpm_lookup_bulk_func(const struct rt
for (i = 0; i < n; i++) {
/* Simply copy tbl24 entry to output */
- next_hops[i] = *(const uint16_t *)&lpm->tbl24[tbl24_indexes[i]];
+ memcpy(&next_hops[i], &lpm->tbl24[tbl24_indexes[i]], sizeof(uint16_t));
/* Overwrite output with tbl8 entry if needed */
if (unlikely((next_hops[i] & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
@@ -352,7 +353,7 @@ rte_lpm_lookup_bulk_func(const struct rt
((uint8_t)next_hops[i] *
RTE_LPM_TBL8_GROUP_NUM_ENTRIES);
- next_hops[i] = *(const uint16_t *)&lpm->tbl8[tbl8_index];
+ memcpy(&next_hops[i], &lpm->tbl8[tbl8_index], sizeof(uint16_t));
}
}
return 0;
@@ -419,13 +420,13 @@ rte_lpm_lookupx4(const struct rte_lpm *l
idx = _mm_cvtsi128_si64(i24);
i24 = _mm_srli_si128(i24, sizeof(uint64_t));
- tbl[0] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx];
- tbl[1] = *(const uint16_t *)&lpm->tbl24[idx >> 32];
+ memcpy(&tbl[0], &lpm->tbl24[(uint32_t)idx], sizeof(uint16_t));
+ memcpy(&tbl[1], &lpm->tbl24[idx >> 32], sizeof(uint16_t));
idx = _mm_cvtsi128_si64(i24);
- tbl[2] = *(const uint16_t *)&lpm->tbl24[(uint32_t)idx];
- tbl[3] = *(const uint16_t *)&lpm->tbl24[idx >> 32];
+ memcpy(&tbl[2], &lpm->tbl24[(uint32_t)idx], sizeof(uint16_t));
+ memcpy(&tbl[3], &lpm->tbl24[idx >> 32], sizeof(uint16_t));
/* get 4 indexes for tbl8[]. */
i8.x = _mm_and_si128(ip, mask8);
@@ -446,25 +447,25 @@ rte_lpm_lookupx4(const struct rte_lpm *l
RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
i8.u32[0] = i8.u32[0] +
(uint8_t)tbl[0] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
- tbl[0] = *(const uint16_t *)&lpm->tbl8[i8.u32[0]];
+ memcpy(&tbl[0], &lpm->tbl8[i8.u32[0]], sizeof(uint16_t));
}
if (unlikely((pt >> 16 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
i8.u32[1] = i8.u32[1] +
(uint8_t)tbl[1] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
- tbl[1] = *(const uint16_t *)&lpm->tbl8[i8.u32[1]];
+ memcpy(&tbl[1], &lpm->tbl8[i8.u32[1]], sizeof(uint16_t));
}
if (unlikely((pt >> 32 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
i8.u32[2] = i8.u32[2] +
(uint8_t)tbl[2] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
- tbl[2] = *(const uint16_t *)&lpm->tbl8[i8.u32[2]];
+ memcpy(&tbl[2], &lpm->tbl8[i8.u32[2]], sizeof(uint16_t));
}
if (unlikely((pt >> 48 & RTE_LPM_VALID_EXT_ENTRY_BITMASK) ==
RTE_LPM_VALID_EXT_ENTRY_BITMASK)) {
i8.u32[3] = i8.u32[3] +
(uint8_t)tbl[3] * RTE_LPM_TBL8_GROUP_NUM_ENTRIES;
- tbl[3] = *(const uint16_t *)&lpm->tbl8[i8.u32[3]];
+ memcpy(&tbl[3], &lpm->tbl8[i8.u32[3]], sizeof(uint16_t));
}
hop[0] = (tbl[0] & RTE_LPM_LOOKUP_SUCCESS) ? (uint8_t)tbl[0] : defv;

33
dpdk-2.2-shift.patch Normal file
View File

@ -0,0 +1,33 @@
diff -up ./drivers/net/e1000/em_ethdev.c.shift ./drivers/net/e1000/em_ethdev.c
--- ./drivers/net/e1000/em_ethdev.c.shift 2016-02-15 14:26:14.678723144 -0500
+++ ./drivers/net/e1000/em_ethdev.c 2016-02-15 14:29:50.859841821 -0500
@@ -637,13 +637,14 @@ eth_em_start(struct rte_eth_dev *dev)
if (rte_intr_allow_others(intr_handle)) {
/* check if lsc interrupt is enabled */
- if (dev->data->dev_conf.intr_conf.lsc != 0)
+ if (dev->data->dev_conf.intr_conf.lsc != 0) {
ret = eth_em_interrupt_setup(dev);
if (ret) {
PMD_INIT_LOG(ERR, "Unable to setup interrupts");
em_dev_clear_queues(dev);
return ret;
}
+ }
} else {
rte_intr_callback_unregister(intr_handle,
eth_em_interrupt_handler,
diff -up ./drivers/net/e1000/igb_pf.c.shift ./drivers/net/e1000/igb_pf.c
--- ./drivers/net/e1000/igb_pf.c.shift 2016-02-15 14:09:55.541062415 -0500
+++ ./drivers/net/e1000/igb_pf.c 2016-02-15 14:09:18.566018267 -0500
@@ -172,8 +172,8 @@ int igb_pf_host_configure(struct rte_eth
E1000_WRITE_REG(hw, E1000_VT_CTL, vtctl);
/* Enable pools reserved to PF only */
- E1000_WRITE_REG(hw, E1000_VFRE, (~0) << vf_num);
- E1000_WRITE_REG(hw, E1000_VFTE, (~0) << vf_num);
+ E1000_WRITE_REG(hw, E1000_VFRE, UINT_MAX << vf_num);
+ E1000_WRITE_REG(hw, E1000_VFTE, UINT_MAX << vf_num);
/* PFDMA Tx General Switch Control Enables VMDQ loopback */
if (hw->mac.type == e1000_i350)

15
dpdk-2.2-test-fixes.patch Normal file
View File

@ -0,0 +1,15 @@
diff -up ./app/test/test.c.test ./app/test/test.c
--- ./app/test/test.c.test 2016-02-15 16:07:28.736385392 -0500
+++ ./app/test/test.c 2016-02-15 16:08:06.596454441 -0500
@@ -162,9 +162,10 @@ unit_test_suite_runner(struct unit_test_
int test_success;
unsigned total = 0, executed = 0, skipped = 0, succeeded = 0, failed = 0;
- if (suite->suite_name)
+ if (suite->suite_name) {
printf(" + ------------------------------------------------------- +\n");
printf(" + Test Suite : %s\n", suite->suite_name);
+ }
if (suite->setup)
if (suite->setup() != 0)

View File

@ -10,13 +10,26 @@
Name: dpdk
Version: 2.2.0
Release: 4%{?dist}
Release: 5%{?dist}
URL: http://dpdk.org
Source: http://dpdk.org/browse/dpdk/snapshot/dpdk-%{version}.tar.gz
Patch1: enic-pun-fix.patch
Patch2: dpdk-2.2-dtneeded.patch
Patch4: dpdk-2.2-examples.patch
Patch5: dpdk-2.2-punning.patch
Patch6: dpdk-2.2-indent.patch
Patch7: dpdk-2.2-shift.patch
Patch8: dpdk-2.2-bnx2x-fixes.patch
Patch9: dpdk-2.2-ixgbe-fixes.patch
Patch10: dpdk-2.2-ixgbe-ethdev-fixes.patch
Patch11: dpdk-2.2-ixgbe-pf-fixes.patch
Patch12: dpdk-2.2-test-fixes.patch
Patch13: dpdk-2.2-pipeline-routing-fixes.patch
Patch14: dpdk-2.2-pipeline-common-fixes.patch
Patch15: dpdk-2.2-pfire-fixes.patch
Patch16: dpdk-2.2-pipeline-routebe-fixes.patch
Patch17: dpdk-2.2-l3fwd-main.patch
Summary: Set of libraries and drivers for fast packet processing
@ -104,6 +117,19 @@ as L2 and L3 forwarding.
%patch1 -p2 -z .enic
%patch2 -p1 -z .dtneeded
%patch4 -p1 -z .examples
%patch5 -p1 -z .pun
%patch6 -p1 -z .indent
%patch7 -p1 -z .shift
%patch8 -p1 -z .bnx2x
%patch9 -p1 -z .ixgbe
%patch10 -p1 -z .ixgbe_ethdev
%patch11 -p1 -z .ixgbe_pf
%patch12 -p1 -z .test
%patch13 -p1 -z .pipeline
%patch14 -p1 -z .pipe_common
%patch15 -p1 -z .pfire
%patch16 -p1 -z .proutebe
%patch17 -p1 -z .l3fwmain
%build
# set up a method for modifying the resulting .config file
@ -268,6 +294,9 @@ install -m 644 ${comblib} %{buildroot}/%{_libdir}/${comblib}
%endif
%changelog
* Mon Feb 15 2016 Neil Horman <nhorman@redhat.com> 2.2.0-5
- Fix ftbfs isssue (1307431)
* Wed Feb 03 2016 Fedora Release Engineering <releng@fedoraproject.org> - 2.2.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild