1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
/*
* QLogic qlcnic NIC Driver
* Copyright (c) 2009-2013 QLogic Corporation
*
* See LICENSE.qlcnic for copyright and licensing details.
*/
#ifndef _QLCNIC_83XX_SRIOV_H_
#define _QLCNIC_83XX_SRIOV_H_
#include <linux/types.h>
#include <linux/pci.h>
#include "qlcnic.h"
extern const u32 qlcnic_83xx_reg_tbl[];
extern const u32 qlcnic_83xx_ext_reg_tbl[];
struct qlcnic_bc_payload {
u64 payload[126];
};
struct qlcnic_bc_hdr {
#if defined(__LITTLE_ENDIAN)
u8 version;
u8 msg_type:4;
u8 rsvd1:3;
u8 op_type:1;
u8 num_cmds;
u8 num_frags;
u8 frag_num;
u8 cmd_op;
u16 seq_id;
u64 rsvd3;
#elif defined(__BIG_ENDIAN)
u8 num_frags;
u8 num_cmds;
u8 op_type:1;
u8 rsvd1:3;
u8 msg_type:4;
u8 version;
u16 seq_id;
u8 cmd_op;
u8 frag_num;
u64 rsvd3;
#endif
};
enum qlcnic_bc_commands {
QLCNIC_BC_CMD_CHANNEL_INIT = 0x0,
QLCNIC_BC_CMD_CHANNEL_TERM = 0x1,
QLCNIC_BC_CMD_GET_ACL = 0x2,
QLCNIC_BC_CMD_CFG_GUEST_VLAN = 0x3,
};
#define QLCNIC_83XX_SRIOV_VF_MAX_MAC 2
#define QLC_BC_CMD 1
struct qlcnic_trans_list {
/* Lock for manipulating list */
spinlock_t lock;
struct list_head wait_list;
int count;
};
enum qlcnic_trans_state {
QLC_INIT = 0,
QLC_WAIT_FOR_CHANNEL_FREE,
QLC_WAIT_FOR_RESP,
QLC_ABORT,
QLC_END,
};
struct qlcnic_bc_trans {
u8 func_id;
u8 active;
u8 curr_rsp_frag;
u8 curr_req_frag;
u16 cmd_id;
u16 req_pay_size;
u16 rsp_pay_size;
u32 trans_id;
enum qlcnic_trans_state trans_state;
struct list_head list;
struct qlcnic_bc_hdr *req_hdr;
struct qlcnic_bc_hdr *rsp_hdr;
struct qlcnic_bc_payload *req_pay;
struct qlcnic_bc_payload *rsp_pay;
struct completion resp_cmpl;
struct qlcnic_vf_info *vf;
};
enum qlcnic_vf_state {
QLC_BC_VF_SEND = 0,
QLC_BC_VF_RECV,
QLC_BC_VF_CHANNEL,
QLC_BC_VF_STATE,
QLC_BC_VF_FLR,
QLC_BC_VF_SOFT_FLR,
};
enum qlcnic_vlan_mode {
QLC_NO_VLAN_MODE = 0,
QLC_PVID_MODE,
QLC_GUEST_VLAN_MODE,
};
struct qlcnic_resources {
u16 num_tx_mac_filters;
u16 num_rx_ucast_mac_filters;
u16 num_rx_mcast_mac_filters;
u16 num_txvlan_keys;
u16 num_rx_queues;
u16 num_tx_queues;
u16 num_rx_buf_rings;
u16 num_rx_status_rings;
u16 num_destip;
u32 num_lro_flows_supported;
u16 max_local_ipv6_addrs;
u16 max_remote_ipv6_addrs;
};
struct qlcnic_vport {
u16 handle;
u16 max_tx_bw;
u16 min_tx_bw;
u16 pvid;
u8 vlan_mode;
u8 qos;
bool spoofchk;
u8 mac[6];
};
struct qlcnic_vf_info {
u8 pci_func;
u16 rx_ctx_id;
u16 tx_ctx_id;
u16 *sriov_vlans;
int num_vlan;
unsigned long state;
struct completion ch_free_cmpl;
struct work_struct trans_work;
struct work_struct flr_work;
/* It synchronizes commands sent from VF */
struct mutex send_cmd_lock;
struct qlcnic_bc_trans *send_cmd;
struct qlcnic_bc_trans *flr_trans;
struct qlcnic_trans_list rcv_act;
struct qlcnic_trans_list rcv_pend;
struct qlcnic_adapter *adapter;
struct qlcnic_vport *vp;
spinlock_t vlan_list_lock; /* Lock for VLAN list */
};
struct qlcnic_async_cmd {
struct list_head list;
struct qlcnic_cmd_args *cmd;
};
struct qlcnic_back_channel {
u16 trans_counter;
struct workqueue_struct *bc_trans_wq;
struct workqueue_struct *bc_async_wq;
struct workqueue_struct *bc_flr_wq;
struct qlcnic_adapter *adapter;
struct list_head async_cmd_list;
struct work_struct vf_async_work;
spinlock_t queue_lock; /* async_cmd_list queue lock */
};
struct qlcnic_sriov {
u16 vp_handle;
u8 num_vfs;
u8 any_vlan;
u8 vlan_mode;
u16 num_allowed_vlans;
u16 *allowed_vlans;
u16 vlan;
struct qlcnic_resources ff_max;
struct qlcnic_back_channel bc;
struct qlcnic_vf_info *vf_info;
};
int qlcnic_sriov_init(struct qlcnic_adapter *, int);
void qlcnic_sriov_cleanup(struct qlcnic_adapter *);
void __qlcnic_sriov_cleanup(struct qlcnic_adapter *);
void qlcnic_sriov_vf_register_map(struct qlcnic_hardware_context *);
int qlcnic_sriov_vf_init(struct qlcnic_adapter *, int);
void qlcnic_sriov_vf_set_ops(struct qlcnic_adapter *);
int qlcnic_sriov_func_to_index(struct qlcnic_adapter *, u8);
void qlcnic_sriov_handle_bc_event(struct qlcnic_adapter *, u32);
int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *, u8);
void qlcnic_sriov_cleanup_async_list(struct qlcnic_back_channel *);
void qlcnic_sriov_cleanup_list(struct qlcnic_trans_list *);
int __qlcnic_sriov_add_act_list(struct qlcnic_sriov *, struct qlcnic_vf_info *,
struct qlcnic_bc_trans *);
int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *,
struct qlcnic_info *, u16);
int qlcnic_sriov_cfg_vf_guest_vlan(struct qlcnic_adapter *, u16, u8);
void qlcnic_sriov_free_vlans(struct qlcnic_adapter *);
void qlcnic_sriov_alloc_vlans(struct qlcnic_adapter *);
bool qlcnic_sriov_check_any_vlan(struct qlcnic_vf_info *);
void qlcnic_sriov_del_vlan_id(struct qlcnic_sriov *,
struct qlcnic_vf_info *, u16);
void qlcnic_sriov_add_vlan_id(struct qlcnic_sriov *,
struct qlcnic_vf_info *, u16);
static inline bool qlcnic_sriov_enable_check(struct qlcnic_adapter *adapter)
{
return test_bit(__QLCNIC_SRIOV_ENABLE, &adapter->state) ? true : false;
}
#ifdef CONFIG_QLCNIC_SRIOV
void qlcnic_sriov_pf_process_bc_cmd(struct qlcnic_adapter *,
struct qlcnic_bc_trans *,
struct qlcnic_cmd_args *);
void qlcnic_sriov_pf_disable(struct qlcnic_adapter *);
void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *);
int qlcnic_pci_sriov_configure(struct pci_dev *, int);
void qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *, u32 *);
void qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *, u32 *);
void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *, struct qlcnic_vf_info *);
bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *,
struct qlcnic_bc_trans *,
struct qlcnic_vf_info *);
void qlcnic_sriov_pf_reset(struct qlcnic_adapter *);
int qlcnic_sriov_pf_reinit(struct qlcnic_adapter *);
int qlcnic_sriov_set_vf_mac(struct net_device *, int, u8 *);
int qlcnic_sriov_set_vf_tx_rate(struct net_device *, int, int, int);
int qlcnic_sriov_get_vf_config(struct net_device *, int ,
struct ifla_vf_info *);
int qlcnic_sriov_set_vf_vlan(struct net_device *, int, u16, u8);
int qlcnic_sriov_set_vf_spoofchk(struct net_device *, int, bool);
#else
static inline void qlcnic_sriov_pf_disable(struct qlcnic_adapter *adapter) {}
static inline void qlcnic_sriov_pf_cleanup(struct qlcnic_adapter *adapter) {}
static inline void
qlcnic_pf_set_interface_id_create_rx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_create_tx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_del_rx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_del_tx_ctx(struct qlcnic_adapter *adapter,
u32 *int_id) {}
static inline void
qlcnic_pf_set_interface_id_ipaddr(struct qlcnic_adapter *adapter, u32 *int_id)
{}
static inline void
qlcnic_pf_set_interface_id_macaddr(struct qlcnic_adapter *adapter, u32 *int_id)
{}
static inline void
qlcnic_pf_set_interface_id_promisc(struct qlcnic_adapter *adapter, u32 *int_id)
{}
static inline void qlcnic_sriov_pf_handle_flr(struct qlcnic_sriov *sriov,
struct qlcnic_vf_info *vf) {}
static inline bool qlcnic_sriov_soft_flr_check(struct qlcnic_adapter *adapter,
struct qlcnic_bc_trans *trans,
struct qlcnic_vf_info *vf)
{ return false; }
static inline void qlcnic_sriov_pf_reset(struct qlcnic_adapter *adapter) {}
static inline int qlcnic_sriov_pf_reinit(struct qlcnic_adapter *adapter)
{ return 0; }
#endif
#endif
|