Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Linux-御风守护者
linux
提交
f7ba35da
L
linux
项目概览
Linux-御风守护者
/
linux
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
linux
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f7ba35da
编写于
10月 17, 2011
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next
上级
01b7806c
15e5209f
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
246 addition
and
50 deletion
+246
-50
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb.h
+3
-0
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igb/igb_main.c
+147
-30
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/igbvf/netdev.c
+2
-2
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe.h
+2
-1
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
+2
-0
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+8
-8
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+78
-6
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+4
-3
未找到文件。
drivers/net/ethernet/intel/igb/igb.h
浏览文件 @
f7ba35da
...
...
@@ -72,6 +72,8 @@ struct igb_adapter;
#define IGB_MAX_VF_MC_ENTRIES 30
#define IGB_MAX_VF_FUNCTIONS 8
#define IGB_MAX_VFTA_ENTRIES 128
#define IGB_82576_VF_DEV_ID 0x10CA
#define IGB_I350_VF_DEV_ID 0x1520
struct
vf_data_storage
{
unsigned
char
vf_mac_addresses
[
ETH_ALEN
];
...
...
@@ -83,6 +85,7 @@ struct vf_data_storage {
u16
pf_vlan
;
/* When set, guest VLAN config not allowed. */
u16
pf_qos
;
u16
tx_rate
;
struct
pci_dev
*
vfdev
;
};
#define IGB_VF_FLAG_CTS 0x00000001
/* VF is clear to send data */
...
...
drivers/net/ethernet/intel/igb/igb_main.c
浏览文件 @
f7ba35da
...
...
@@ -162,6 +162,9 @@ static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
static
int
igb_ndo_get_vf_config
(
struct
net_device
*
netdev
,
int
vf
,
struct
ifla_vf_info
*
ivi
);
static
void
igb_check_vf_rate_limit
(
struct
igb_adapter
*
);
static
int
igb_vf_configure
(
struct
igb_adapter
*
adapter
,
int
vf
);
static
int
igb_find_enabled_vfs
(
struct
igb_adapter
*
adapter
);
static
int
igb_check_vf_assignment
(
struct
igb_adapter
*
adapter
);
#ifdef CONFIG_PM
static
int
igb_suspend
(
struct
pci_dev
*
,
pm_message_t
);
...
...
@@ -2232,8 +2235,12 @@ static void __devexit igb_remove(struct pci_dev *pdev)
/* reclaim resources allocated to VFs */
if
(
adapter
->
vf_data
)
{
/* disable iov and allow time for transactions to clear */
pci_disable_sriov
(
pdev
);
msleep
(
500
);
if
(
!
igb_check_vf_assignment
(
adapter
))
{
pci_disable_sriov
(
pdev
);
msleep
(
500
);
}
else
{
dev_info
(
&
pdev
->
dev
,
"VF(s) assigned to guests!
\n
"
);
}
kfree
(
adapter
->
vf_data
);
adapter
->
vf_data
=
NULL
;
...
...
@@ -2270,42 +2277,49 @@ static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
struct
pci_dev
*
pdev
=
adapter
->
pdev
;
int
old_vfs
=
igb_find_enabled_vfs
(
adapter
);
int
i
;
if
(
adapter
->
vfs_allocated_count
)
{
adapter
->
vf_data
=
kcalloc
(
adapter
->
vfs_allocated_count
,
sizeof
(
struct
vf_data_storage
),
GFP_KERNEL
);
/* if allocation failed then we do not support SR-IOV */
if
(
!
adapter
->
vf_data
)
{
adapter
->
vfs_allocated_count
=
0
;
dev_err
(
&
pdev
->
dev
,
"Unable to allocate memory for VF "
"Data Storage
\n
"
);
}
if
(
old_vfs
)
{
dev_info
(
&
pdev
->
dev
,
"%d pre-allocated VFs found - override "
"max_vfs setting of %d
\n
"
,
old_vfs
,
max_vfs
);
adapter
->
vfs_allocated_count
=
old_vfs
;
}
if
(
pci_enable_sriov
(
pdev
,
adapter
->
vfs_allocated_count
))
{
kfree
(
adapter
->
vf_data
);
adapter
->
vf_data
=
NULL
;
#endif
/* CONFIG_PCI_IOV */
if
(
!
adapter
->
vfs_allocated_count
)
return
;
adapter
->
vf_data
=
kcalloc
(
adapter
->
vfs_allocated_count
,
sizeof
(
struct
vf_data_storage
),
GFP_KERNEL
);
/* if allocation failed then we do not support SR-IOV */
if
(
!
adapter
->
vf_data
)
{
adapter
->
vfs_allocated_count
=
0
;
#ifdef CONFIG_PCI_IOV
}
else
{
unsigned
char
mac_addr
[
ETH_ALEN
];
int
i
;
dev_info
(
&
pdev
->
dev
,
"%d vfs allocated
\n
"
,
adapter
->
vfs_allocated_count
);
for
(
i
=
0
;
i
<
adapter
->
vfs_allocated_count
;
i
++
)
{
random_ether_addr
(
mac_addr
);
igb_set_vf_mac
(
adapter
,
i
,
mac_addr
);
}
/* DMA Coalescing is not supported in IOV mode. */
if
(
adapter
->
flags
&
IGB_FLAG_DMAC
)
adapter
->
flags
&=
~
IGB_FLAG_DMAC
;
dev_err
(
&
pdev
->
dev
,
"Unable to allocate memory for VF "
"Data Storage
\n
"
);
goto
out
;
}
if
(
!
old_vfs
)
{
if
(
pci_enable_sriov
(
pdev
,
adapter
->
vfs_allocated_count
))
goto
err_out
;
}
dev_info
(
&
pdev
->
dev
,
"%d VFs allocated
\n
"
,
adapter
->
vfs_allocated_count
);
for
(
i
=
0
;
i
<
adapter
->
vfs_allocated_count
;
i
++
)
igb_vf_configure
(
adapter
,
i
);
/* DMA Coalescing is not supported in IOV mode. */
adapter
->
flags
&=
~
IGB_FLAG_DMAC
;
goto
out
;
err_out:
kfree
(
adapter
->
vf_data
);
adapter
->
vf_data
=
NULL
;
adapter
->
vfs_allocated_count
=
0
;
out:
return
;
#endif
/* CONFIG_PCI_IOV */
}
/**
* igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp
* @adapter: board private structure to initialize
...
...
@@ -4917,6 +4931,109 @@ static int igb_notify_dca(struct notifier_block *nb, unsigned long event,
}
#endif
/* CONFIG_IGB_DCA */
#ifdef CONFIG_PCI_IOV
static
int
igb_vf_configure
(
struct
igb_adapter
*
adapter
,
int
vf
)
{
unsigned
char
mac_addr
[
ETH_ALEN
];
struct
pci_dev
*
pdev
=
adapter
->
pdev
;
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
struct
pci_dev
*
pvfdev
;
unsigned
int
device_id
;
u16
thisvf_devfn
;
random_ether_addr
(
mac_addr
);
igb_set_vf_mac
(
adapter
,
vf
,
mac_addr
);
switch
(
adapter
->
hw
.
mac
.
type
)
{
case
e1000_82576
:
device_id
=
IGB_82576_VF_DEV_ID
;
/* VF Stride for 82576 is 2 */
thisvf_devfn
=
(
pdev
->
devfn
+
0x80
+
(
vf
<<
1
))
|
(
pdev
->
devfn
&
1
);
break
;
case
e1000_i350
:
device_id
=
IGB_I350_VF_DEV_ID
;
/* VF Stride for I350 is 4 */
thisvf_devfn
=
(
pdev
->
devfn
+
0x80
+
(
vf
<<
2
))
|
(
pdev
->
devfn
&
3
);
break
;
default:
device_id
=
0
;
thisvf_devfn
=
0
;
break
;
}
pvfdev
=
pci_get_device
(
hw
->
vendor_id
,
device_id
,
NULL
);
while
(
pvfdev
)
{
if
(
pvfdev
->
devfn
==
thisvf_devfn
)
break
;
pvfdev
=
pci_get_device
(
hw
->
vendor_id
,
device_id
,
pvfdev
);
}
if
(
pvfdev
)
adapter
->
vf_data
[
vf
].
vfdev
=
pvfdev
;
else
dev_err
(
&
pdev
->
dev
,
"Couldn't find pci dev ptr for VF %4.4x
\n
"
,
thisvf_devfn
);
return
pvfdev
!=
NULL
;
}
static
int
igb_find_enabled_vfs
(
struct
igb_adapter
*
adapter
)
{
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
struct
pci_dev
*
pdev
=
adapter
->
pdev
;
struct
pci_dev
*
pvfdev
;
u16
vf_devfn
=
0
;
u16
vf_stride
;
unsigned
int
device_id
;
int
vfs_found
=
0
;
switch
(
adapter
->
hw
.
mac
.
type
)
{
case
e1000_82576
:
device_id
=
IGB_82576_VF_DEV_ID
;
/* VF Stride for 82576 is 2 */
vf_stride
=
2
;
break
;
case
e1000_i350
:
device_id
=
IGB_I350_VF_DEV_ID
;
/* VF Stride for I350 is 4 */
vf_stride
=
4
;
break
;
default:
device_id
=
0
;
vf_stride
=
0
;
break
;
}
vf_devfn
=
pdev
->
devfn
+
0x80
;
pvfdev
=
pci_get_device
(
hw
->
vendor_id
,
device_id
,
NULL
);
while
(
pvfdev
)
{
if
(
pvfdev
->
devfn
==
vf_devfn
)
vfs_found
++
;
vf_devfn
+=
vf_stride
;
pvfdev
=
pci_get_device
(
hw
->
vendor_id
,
device_id
,
pvfdev
);
}
return
vfs_found
;
}
static
int
igb_check_vf_assignment
(
struct
igb_adapter
*
adapter
)
{
int
i
;
for
(
i
=
0
;
i
<
adapter
->
vfs_allocated_count
;
i
++
)
{
if
(
adapter
->
vf_data
[
i
].
vfdev
)
{
if
(
adapter
->
vf_data
[
i
].
vfdev
->
dev_flags
&
PCI_DEV_FLAGS_ASSIGNED
)
return
true
;
}
}
return
false
;
}
#endif
static
void
igb_ping_all_vfs
(
struct
igb_adapter
*
adapter
)
{
struct
e1000_hw
*
hw
=
&
adapter
->
hw
;
...
...
drivers/net/ethernet/intel/igbvf/netdev.c
浏览文件 @
f7ba35da
...
...
@@ -102,8 +102,8 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
{
if
(
status
&
E1000_RXD_STAT_VP
)
{
u16
vid
=
le16_to_cpu
(
vlan
)
&
E1000_RXD_SPC_VLAN_MASK
;
__vlan_hwaccel_put_tag
(
skb
,
vid
);
if
(
test_bit
(
vid
,
adapter
->
active_vlans
))
__vlan_hwaccel_put_tag
(
skb
,
vid
);
}
netif_receive_skb
(
skb
);
}
...
...
drivers/net/ethernet/intel/ixgbe/ixgbe.h
浏览文件 @
f7ba35da
...
...
@@ -497,7 +497,8 @@ struct ixgbe_adapter {
u64
rsc_total_count
;
u64
rsc_total_flush
;
u32
wol
;
u16
eeprom_version
;
u16
eeprom_verh
;
u16
eeprom_verl
;
u16
eeprom_cap
;
int
node
;
...
...
drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c
浏览文件 @
f7ba35da
...
...
@@ -1305,6 +1305,8 @@ static struct ixgbe_mac_operations mac_ops_82598 = {
static
struct
ixgbe_eeprom_operations
eeprom_ops_82598
=
{
.
init_params
=
&
ixgbe_init_eeprom_params_generic
,
.
read
=
&
ixgbe_read_eerd_generic
,
.
write
=
&
ixgbe_write_eeprom_generic
,
.
write_buffer
=
&
ixgbe_write_eeprom_buffer_bit_bang_generic
,
.
read_buffer
=
&
ixgbe_read_eerd_buffer_generic
,
.
calc_checksum
=
&
ixgbe_calc_eeprom_checksum_generic
,
.
validate_checksum
=
&
ixgbe_validate_eeprom_checksum_generic
,
...
...
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
浏览文件 @
f7ba35da
...
...
@@ -3341,7 +3341,7 @@ static u8 ixgbe_calculate_checksum(u8 *buffer, u32 length)
* Communicates with the manageability block. On success return 0
* else return IXGBE_ERR_HOST_INTERFACE_COMMAND.
**/
static
s32
ixgbe_host_interface_command
(
struct
ixgbe_hw
*
hw
,
u
8
*
buffer
,
static
s32
ixgbe_host_interface_command
(
struct
ixgbe_hw
*
hw
,
u
32
*
buffer
,
u32
length
)
{
u32
hicr
,
i
;
...
...
@@ -3374,7 +3374,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
*/
for
(
i
=
0
;
i
<
dword_len
;
i
++
)
IXGBE_WRITE_REG_ARRAY
(
hw
,
IXGBE_FLEX_MNG
,
i
,
*
((
u32
*
)
buffer
+
i
));
i
,
cpu_to_le32
(
buffer
[
i
]
));
/* Setting this bit tells the ARC that a new command is pending. */
IXGBE_WRITE_REG
(
hw
,
IXGBE_HICR
,
hicr
|
IXGBE_HICR_C
);
...
...
@@ -3398,9 +3398,10 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
dword_len
=
hdr_size
>>
2
;
/* first pull in the header so we know the buffer length */
for
(
i
=
0
;
i
<
dword_len
;
i
++
)
*
((
u32
*
)
buffer
+
i
)
=
IXGBE_READ_REG_ARRAY
(
hw
,
IXGBE_FLEX_MNG
,
i
);
for
(
i
=
0
;
i
<
dword_len
;
i
++
)
{
buffer
[
i
]
=
IXGBE_READ_REG_ARRAY
(
hw
,
IXGBE_FLEX_MNG
,
i
);
le32_to_cpus
(
&
buffer
[
i
]);
}
/* If there is any thing in data position pull it in */
buf_len
=
((
struct
ixgbe_hic_hdr
*
)
buffer
)
->
buf_len
;
...
...
@@ -3418,8 +3419,7 @@ static s32 ixgbe_host_interface_command(struct ixgbe_hw *hw, u8 *buffer,
/* Pull in the rest of the buffer (i is where we left off)*/
for
(;
i
<
buf_len
;
i
++
)
*
((
u32
*
)
buffer
+
i
)
=
IXGBE_READ_REG_ARRAY
(
hw
,
IXGBE_FLEX_MNG
,
i
);
buffer
[
i
]
=
IXGBE_READ_REG_ARRAY
(
hw
,
IXGBE_FLEX_MNG
,
i
);
out:
return
ret_val
;
...
...
@@ -3465,7 +3465,7 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
fw_cmd
.
pad2
=
0
;
for
(
i
=
0
;
i
<=
FW_CEM_MAX_RETRIES
;
i
++
)
{
ret_val
=
ixgbe_host_interface_command
(
hw
,
(
u
8
*
)
&
fw_cmd
,
ret_val
=
ixgbe_host_interface_command
(
hw
,
(
u
32
*
)
&
fw_cmd
,
sizeof
(
fw_cmd
));
if
(
ret_val
!=
0
)
continue
;
...
...
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
浏览文件 @
f7ba35da
...
...
@@ -814,26 +814,97 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
return
ret_val
;
}
static
int
ixgbe_set_eeprom
(
struct
net_device
*
netdev
,
struct
ethtool_eeprom
*
eeprom
,
u8
*
bytes
)
{
struct
ixgbe_adapter
*
adapter
=
netdev_priv
(
netdev
);
struct
ixgbe_hw
*
hw
=
&
adapter
->
hw
;
u16
*
eeprom_buff
;
void
*
ptr
;
int
max_len
,
first_word
,
last_word
,
ret_val
=
0
;
u16
i
;
if
(
eeprom
->
len
==
0
)
return
-
EINVAL
;
if
(
eeprom
->
magic
!=
(
hw
->
vendor_id
|
(
hw
->
device_id
<<
16
)))
return
-
EINVAL
;
max_len
=
hw
->
eeprom
.
word_size
*
2
;
first_word
=
eeprom
->
offset
>>
1
;
last_word
=
(
eeprom
->
offset
+
eeprom
->
len
-
1
)
>>
1
;
eeprom_buff
=
kmalloc
(
max_len
,
GFP_KERNEL
);
if
(
!
eeprom_buff
)
return
-
ENOMEM
;
ptr
=
eeprom_buff
;
if
(
eeprom
->
offset
&
1
)
{
/*
* need read/modify/write of first changed EEPROM word
* only the second byte of the word is being modified
*/
ret_val
=
hw
->
eeprom
.
ops
.
read
(
hw
,
first_word
,
&
eeprom_buff
[
0
]);
if
(
ret_val
)
goto
err
;
ptr
++
;
}
if
((
eeprom
->
offset
+
eeprom
->
len
)
&
1
)
{
/*
* need read/modify/write of last changed EEPROM word
* only the first byte of the word is being modified
*/
ret_val
=
hw
->
eeprom
.
ops
.
read
(
hw
,
last_word
,
&
eeprom_buff
[
last_word
-
first_word
]);
if
(
ret_val
)
goto
err
;
}
/* Device's eeprom is always little-endian, word addressable */
for
(
i
=
0
;
i
<
last_word
-
first_word
+
1
;
i
++
)
le16_to_cpus
(
&
eeprom_buff
[
i
]);
memcpy
(
ptr
,
bytes
,
eeprom
->
len
);
for
(
i
=
0
;
i
<
last_word
-
first_word
+
1
;
i
++
)
cpu_to_le16s
(
&
eeprom_buff
[
i
]);
ret_val
=
hw
->
eeprom
.
ops
.
write_buffer
(
hw
,
first_word
,
last_word
-
first_word
+
1
,
eeprom_buff
);
/* Update the checksum */
if
(
ret_val
==
0
)
hw
->
eeprom
.
ops
.
update_checksum
(
hw
);
err:
kfree
(
eeprom_buff
);
return
ret_val
;
}
static
void
ixgbe_get_drvinfo
(
struct
net_device
*
netdev
,
struct
ethtool_drvinfo
*
drvinfo
)
{
struct
ixgbe_adapter
*
adapter
=
netdev_priv
(
netdev
);
char
firmware_version
[
32
];
u32
nvm_track_id
;
strncpy
(
drvinfo
->
driver
,
ixgbe_driver_name
,
sizeof
(
drvinfo
->
driver
)
-
1
);
strncpy
(
drvinfo
->
version
,
ixgbe_driver_version
,
sizeof
(
drvinfo
->
version
)
-
1
);
snprintf
(
firmware_version
,
sizeof
(
firmware_version
),
"%d.%d-%d"
,
(
adapter
->
eeprom_version
&
0xF000
)
>>
12
,
(
adapter
->
eeprom_version
&
0x0FF0
)
>>
4
,
adapter
->
eeprom_version
&
0x000F
);
nvm_track_id
=
(
adapter
->
eeprom_verh
<<
16
)
|
adapter
->
eeprom_verl
;
snprintf
(
firmware_version
,
sizeof
(
firmware_version
),
"0x%08x"
,
nvm_track_id
);
strncpy
(
drvinfo
->
fw_version
,
firmware_version
,
sizeof
(
drvinfo
->
fw_version
)
);
sizeof
(
drvinfo
->
fw_version
)
-
1
);
strncpy
(
drvinfo
->
bus_info
,
pci_name
(
adapter
->
pdev
),
sizeof
(
drvinfo
->
bus_info
)
);
sizeof
(
drvinfo
->
bus_info
)
-
1
);
drvinfo
->
n_stats
=
IXGBE_STATS_LEN
;
drvinfo
->
testinfo_len
=
IXGBE_TEST_LEN
;
drvinfo
->
regdump_len
=
ixgbe_get_regs_len
(
netdev
);
...
...
@@ -2524,6 +2595,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
.
get_link
=
ethtool_op_get_link
,
.
get_eeprom_len
=
ixgbe_get_eeprom_len
,
.
get_eeprom
=
ixgbe_get_eeprom
,
.
set_eeprom
=
ixgbe_set_eeprom
,
.
get_ringparam
=
ixgbe_get_ringparam
,
.
set_ringparam
=
ixgbe_set_ringparam
,
.
get_pauseparam
=
ixgbe_get_pauseparam
,
...
...
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
浏览文件 @
f7ba35da
...
...
@@ -7640,6 +7640,10 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
}
device_set_wakeup_enable
(
&
adapter
->
pdev
->
dev
,
adapter
->
wol
);
/* save off EEPROM version number */
hw
->
eeprom
.
ops
.
read
(
hw
,
0x2e
,
&
adapter
->
eeprom_verh
);
hw
->
eeprom
.
ops
.
read
(
hw
,
0x2d
,
&
adapter
->
eeprom_verl
);
/* pick up the PCI bus settings for reporting later */
hw
->
mac
.
ops
.
get_bus_info
(
hw
);
...
...
@@ -7672,9 +7676,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
"is required.
\n
"
);
}
/* save off EEPROM version number */
hw
->
eeprom
.
ops
.
read
(
hw
,
0x29
,
&
adapter
->
eeprom_version
);
/* reset the hardware with the new settings */
err
=
hw
->
mac
.
ops
.
start_hw
(
hw
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录