Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
4615fd15
Commit
4615fd15
authored
Nov 26, 2015
by
Emmanuel Grumbach
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'iwlwifi-fixes/master' into next
parents
6d808eba
9513c5e1
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
79 additions
and
55 deletions
+79
-55
drivers/net/wireless/intel/iwlwifi/iwl-7000.c
drivers/net/wireless/intel/iwlwifi/iwl-7000.c
+1
-1
drivers/net/wireless/intel/iwlwifi/iwl-8000.c
drivers/net/wireless/intel/iwlwifi/iwl-8000.c
+1
-1
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+2
-6
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+8
-3
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+47
-41
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+2
-2
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+18
-1
No files found.
drivers/net/wireless/intel/iwlwifi/iwl-7000.c
View file @
4615fd15
...
...
@@ -69,7 +69,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL7260_UCODE_API_MAX 1
7
#define IWL7260_UCODE_API_MAX 1
9
/* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK 13
...
...
drivers/net/wireless/intel/iwlwifi/iwl-8000.c
View file @
4615fd15
...
...
@@ -69,7 +69,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL8000_UCODE_API_MAX 1
7
#define IWL8000_UCODE_API_MAX 1
9
/* Oldest version we won't warn about */
#define IWL8000_UCODE_API_OK 13
...
...
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
View file @
4615fd15
...
...
@@ -309,9 +309,9 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
* to transmit packets to the AP, i.e. the PTK.
*/
if
(
key
->
flags
&
IEEE80211_KEY_FLAG_PAIRWISE
)
{
key
->
hw_key_idx
=
0
;
mvm
->
ptk_ivlen
=
key
->
iv_len
;
mvm
->
ptk_icvlen
=
key
->
icv_len
;
ret
=
iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
key
,
0
);
}
else
{
/*
* firmware only supports TSC/RSC for a single key,
...
...
@@ -319,12 +319,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
* with new ones -- this relies on mac80211 doing
* list_add_tail().
*/
key
->
hw_key_idx
=
1
;
mvm
->
gtk_ivlen
=
key
->
iv_len
;
mvm
->
gtk_icvlen
=
key
->
icv_len
;
ret
=
iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
key
,
1
);
}
ret
=
iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
key
,
true
);
data
->
error
=
ret
!=
0
;
out_unlock:
mutex_unlock
(
&
mvm
->
mutex
);
...
...
@@ -772,9 +771,6 @@ static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
*/
set_bit
(
IWL_MVM_STATUS_IN_HW_RESTART
,
&
mvm
->
status
);
/* We reprogram keys and shouldn't allocate new key indices */
memset
(
mvm
->
fw_key_table
,
0
,
sizeof
(
mvm
->
fw_key_table
));
mvm
->
ptk_ivlen
=
0
;
mvm
->
ptk_icvlen
=
0
;
mvm
->
ptk_ivlen
=
0
;
...
...
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
View file @
4615fd15
...
...
@@ -2941,6 +2941,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
{
struct
iwl_mvm
*
mvm
=
IWL_MAC80211_GET_MVM
(
hw
);
int
ret
;
u8
key_offset
;
if
(
iwlwifi_mod_params
.
sw_crypto
)
{
IWL_DEBUG_MAC80211
(
mvm
,
"leave - hwcrypto disabled
\n
"
);
...
...
@@ -3006,10 +3007,14 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
break
;
}
/* in HW restart reuse the index, otherwise request a new one */
if
(
test_bit
(
IWL_MVM_STATUS_IN_HW_RESTART
,
&
mvm
->
status
))
key_offset
=
key
->
hw_key_idx
;
else
key_offset
=
STA_KEY_IDX_INVALID
;
IWL_DEBUG_MAC80211
(
mvm
,
"set hwcrypto key
\n
"
);
ret
=
iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
key
,
test_bit
(
IWL_MVM_STATUS_IN_HW_RESTART
,
&
mvm
->
status
));
ret
=
iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
key
,
key_offset
);
if
(
ret
)
{
IWL_WARN
(
mvm
,
"set key failed
\n
"
);
/*
...
...
drivers/net/wireless/intel/iwlwifi/mvm/sta.c
View file @
4615fd15
...
...
@@ -1201,7 +1201,8 @@ static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
return
max_offs
;
}
static
u8
iwl_mvm_get_key_sta_id
(
struct
ieee80211_vif
*
vif
,
static
u8
iwl_mvm_get_key_sta_id
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
)
{
struct
iwl_mvm_vif
*
mvmvif
=
iwl_mvm_vif_from_mac80211
(
vif
);
...
...
@@ -1218,8 +1219,21 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
* station ID, then use AP's station ID.
*/
if
(
vif
->
type
==
NL80211_IFTYPE_STATION
&&
mvmvif
->
ap_sta_id
!=
IWL_MVM_STATION_COUNT
)
return
mvmvif
->
ap_sta_id
;
mvmvif
->
ap_sta_id
!=
IWL_MVM_STATION_COUNT
)
{
u8
sta_id
=
mvmvif
->
ap_sta_id
;
sta
=
rcu_dereference_protected
(
mvm
->
fw_id_to_mac_id
[
sta_id
],
lockdep_is_held
(
&
mvm
->
mutex
));
/*
* It is possible that the 'sta' parameter is NULL,
* for example when a GTK is removed - the sta_id will then
* be the AP ID, and no station was passed by mac80211.
*/
if
(
IS_ERR_OR_NULL
(
sta
))
return
IWL_MVM_STATION_COUNT
;
return
sta_id
;
}
return
IWL_MVM_STATION_COUNT
;
}
...
...
@@ -1227,7 +1241,8 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
static
int
iwl_mvm_send_sta_key
(
struct
iwl_mvm
*
mvm
,
struct
iwl_mvm_sta
*
mvm_sta
,
struct
ieee80211_key_conf
*
keyconf
,
bool
mcast
,
u32
tkip_iv32
,
u16
*
tkip_p1k
,
u32
cmd_flags
)
u32
tkip_iv32
,
u16
*
tkip_p1k
,
u32
cmd_flags
,
u8
key_offset
)
{
struct
iwl_mvm_add_sta_key_cmd
cmd
=
{};
__le16
key_flags
;
...
...
@@ -1269,7 +1284,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
if
(
mcast
)
key_flags
|=
cpu_to_le16
(
STA_KEY_MULTICAST
);
cmd
.
key_offset
=
key
conf
->
hw_key_idx
;
cmd
.
key_offset
=
key
_offset
;
cmd
.
key_flags
=
key_flags
;
cmd
.
sta_id
=
sta_id
;
...
...
@@ -1360,6 +1375,7 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
keyconf
,
u8
key_offset
,
bool
mcast
)
{
struct
iwl_mvm_sta
*
mvm_sta
=
iwl_mvm_sta_from_mac80211
(
sta
);
...
...
@@ -1375,17 +1391,17 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
ieee80211_get_key_rx_seq
(
keyconf
,
0
,
&
seq
);
ieee80211_get_tkip_rx_p1k
(
keyconf
,
addr
,
seq
.
tkip
.
iv32
,
p1k
);
ret
=
iwl_mvm_send_sta_key
(
mvm
,
mvm_sta
,
keyconf
,
mcast
,
seq
.
tkip
.
iv32
,
p1k
,
0
);
seq
.
tkip
.
iv32
,
p1k
,
0
,
key_offset
);
break
;
case
WLAN_CIPHER_SUITE_CCMP
:
case
WLAN_CIPHER_SUITE_WEP40
:
case
WLAN_CIPHER_SUITE_WEP104
:
ret
=
iwl_mvm_send_sta_key
(
mvm
,
mvm_sta
,
keyconf
,
mcast
,
0
,
NULL
,
0
);
0
,
NULL
,
0
,
key_offset
);
break
;
default:
ret
=
iwl_mvm_send_sta_key
(
mvm
,
mvm_sta
,
keyconf
,
mcast
,
0
,
NULL
,
0
);
0
,
NULL
,
0
,
key_offset
);
}
return
ret
;
...
...
@@ -1433,7 +1449,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
keyconf
,
bool
have_
key_offset
)
u8
key_offset
)
{
bool
mcast
=
!
(
keyconf
->
flags
&
IEEE80211_KEY_FLAG_PAIRWISE
);
u8
sta_id
;
...
...
@@ -1443,7 +1459,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
lockdep_assert_held
(
&
mvm
->
mutex
);
/* Get the station id from the mvm local station table */
sta_id
=
iwl_mvm_get_key_sta_id
(
vif
,
sta
);
sta_id
=
iwl_mvm_get_key_sta_id
(
mvm
,
vif
,
sta
);
if
(
sta_id
==
IWL_MVM_STATION_COUNT
)
{
IWL_ERR
(
mvm
,
"Failed to find station id
\n
"
);
return
-
EINVAL
;
...
...
@@ -1470,18 +1486,25 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
if
(
WARN_ON_ONCE
(
iwl_mvm_sta_from_mac80211
(
sta
)
->
vif
!=
vif
))
return
-
EINVAL
;
if
(
!
have_key_offset
)
{
/*
* The D3 firmware hardcodes the PTK offset to 0, so we have to
* configure it there. As a result, this workaround exists to
* let the caller set the key offset (hw_key_idx), see d3.c.
*/
keyconf
->
hw_key_idx
=
iwl_mvm_set_fw_key_idx
(
mvm
);
if
(
keyconf
->
hw_key_idx
==
STA_KEY_IDX_INVALID
)
/* If the key_offset is not pre-assigned, we need to find a
* new offset to use. In normal cases, the offset is not
* pre-assigned, but during HW_RESTART we want to reuse the
* same indices, so we pass them when this function is called.
*
* In D3 entry, we need to hardcoded the indices (because the
* firmware hardcodes the PTK offset to 0). In this case, we
* need to make sure we don't overwrite the hw_key_idx in the
* keyconf structure, because otherwise we cannot configure
* the original ones back when resuming.
*/
if
(
key_offset
==
STA_KEY_IDX_INVALID
)
{
key_offset
=
iwl_mvm_set_fw_key_idx
(
mvm
);
if
(
key_offset
==
STA_KEY_IDX_INVALID
)
return
-
ENOSPC
;
keyconf
->
hw_key_idx
=
key_offset
;
}
ret
=
__iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
keyconf
,
mcast
);
ret
=
__iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
keyconf
,
key_offset
,
mcast
);
if
(
ret
)
{
__clear_bit
(
keyconf
->
hw_key_idx
,
mvm
->
fw_key_table
);
goto
end
;
...
...
@@ -1495,7 +1518,8 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
*/
if
(
keyconf
->
cipher
==
WLAN_CIPHER_SUITE_WEP40
||
keyconf
->
cipher
==
WLAN_CIPHER_SUITE_WEP104
)
{
ret
=
__iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
keyconf
,
!
mcast
);
ret
=
__iwl_mvm_set_sta_key
(
mvm
,
vif
,
sta
,
keyconf
,
key_offset
,
!
mcast
);
if
(
ret
)
{
__clear_bit
(
keyconf
->
hw_key_idx
,
mvm
->
fw_key_table
);
__iwl_mvm_remove_sta_key
(
mvm
,
sta_id
,
keyconf
,
mcast
);
...
...
@@ -1521,7 +1545,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
lockdep_assert_held
(
&
mvm
->
mutex
);
/* Get the station id from the mvm local station table */
sta_id
=
iwl_mvm_get_key_sta_id
(
vif
,
sta
);
sta_id
=
iwl_mvm_get_key_sta_id
(
mvm
,
vif
,
sta
);
IWL_DEBUG_WEP
(
mvm
,
"mvm remove dynamic key: idx=%d sta=%d
\n
"
,
keyconf
->
keyidx
,
sta_id
);
...
...
@@ -1547,24 +1571,6 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
return
0
;
}
/*
* It is possible that the 'sta' parameter is NULL, and thus
* there is a need to retrieve the sta from the local station table,
* for example when a GTK is removed (where the sta_id will then be
* the AP ID, and no station was passed by mac80211.)
*/
if
(
!
sta
)
{
sta
=
rcu_dereference_protected
(
mvm
->
fw_id_to_mac_id
[
sta_id
],
lockdep_is_held
(
&
mvm
->
mutex
));
if
(
!
sta
)
{
IWL_ERR
(
mvm
,
"Invalid station id
\n
"
);
return
-
EINVAL
;
}
}
if
(
WARN_ON_ONCE
(
iwl_mvm_sta_from_mac80211
(
sta
)
->
vif
!=
vif
))
return
-
EINVAL
;
ret
=
__iwl_mvm_remove_sta_key
(
mvm
,
sta_id
,
keyconf
,
mcast
);
if
(
ret
)
return
ret
;
...
...
@@ -1584,7 +1590,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
u16
*
phase1key
)
{
struct
iwl_mvm_sta
*
mvm_sta
;
u8
sta_id
=
iwl_mvm_get_key_sta_id
(
vif
,
sta
);
u8
sta_id
=
iwl_mvm_get_key_sta_id
(
mvm
,
vif
,
sta
);
bool
mcast
=
!
(
keyconf
->
flags
&
IEEE80211_KEY_FLAG_PAIRWISE
);
if
(
WARN_ON_ONCE
(
sta_id
==
IWL_MVM_STATION_COUNT
))
...
...
@@ -1602,7 +1608,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
mvm_sta
=
iwl_mvm_sta_from_mac80211
(
sta
);
iwl_mvm_send_sta_key
(
mvm
,
mvm_sta
,
keyconf
,
mcast
,
iv32
,
phase1key
,
CMD_ASYNC
);
iv32
,
phase1key
,
CMD_ASYNC
,
keyconf
->
hw_key_idx
);
rcu_read_unlock
();
}
...
...
drivers/net/wireless/intel/iwlwifi/mvm/sta.h
View file @
4615fd15
...
...
@@ -365,8 +365,8 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
int
iwl_mvm_set_sta_key
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
struct
ieee80211_key_conf
*
key
,
bool
have_
key_offset
);
struct
ieee80211_key_conf
*
key
conf
,
u8
key_offset
);
int
iwl_mvm_remove_sta_key
(
struct
iwl_mvm
*
mvm
,
struct
ieee80211_vif
*
vif
,
struct
ieee80211_sta
*
sta
,
...
...
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
View file @
4615fd15
...
...
@@ -423,14 +423,21 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
/* 8000 Series */
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0010
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x1010
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0130
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x1130
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0132
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x1132
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0110
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x01F0
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0012
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x1012
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x1110
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0050
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0250
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x1050
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0150
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x1150
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F4
,
0x0030
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F4
,
0x1130
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F4
,
0x1030
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0xC010
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0xC110
,
iwl8260_2ac_cfg
)},
...
...
@@ -438,18 +445,28 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
{
IWL_PCI_DEVICE
(
0x24F3
,
0xC050
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0xD050
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x8010
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x8110
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x9010
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x9110
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F4
,
0x8030
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F4
,
0x9030
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x8130
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x9130
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x8132
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x9132
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x8050
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x8150
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x9050
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x9150
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0004
,
iwl8260_2n_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0044
,
iwl8260_2n_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F5
,
0x0010
,
iwl4165_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F6
,
0x0030
,
iwl4165_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0810
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0910
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0850
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0950
,
iwl8260_2ac_cfg
)},
{
IWL_PCI_DEVICE
(
0x24F3
,
0x0930
,
iwl8260_2ac_cfg
)},
#endif
/* CONFIG_IWLMVM */
{
0
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment