diff options
author | Upinder Malhi <umalhi@cisco.com> | 2014-01-09 17:48:07 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2014-01-14 03:44:41 -0500 |
commit | 2183b990b67b761f81c68a18f60df028e080cf05 (patch) | |
tree | a4584a808fa389bd51394b4e8c1ef5fe2979fe48 /drivers/infiniband | |
parent | 301a0dd68e5ddd22d992a58f466b621987d9df3b (diff) |
IB/usnic: Push all forwarding state to usnic_fwd.[hc]
Push all of the usnic device forwarding state - such as mtu, mac - to
usnic_fwd_dev. Furthermore, usnic_fwd.h exposes a improved interface
for rest of the usnic code. The primary improvement is that
usnic_fwd.h's flow management interface takes in high-level *filter*
and *action* structures now, instead of low-level paramaters such as
vnic_idx, rq_idx.
Signed-off-by: Upinder Malhi <umalhi@cisco.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/usnic/usnic_fwd.c | 269 | ||||
-rw-r--r-- | drivers/infiniband/hw/usnic/usnic_fwd.h | 68 |
2 files changed, 212 insertions, 125 deletions
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.c b/drivers/infiniband/hw/usnic/usnic_fwd.c index 8e42216362e7..33fdd771e599 100644 --- a/drivers/infiniband/hw/usnic/usnic_fwd.c +++ b/drivers/infiniband/hw/usnic/usnic_fwd.c | |||
@@ -23,6 +23,49 @@ | |||
23 | #include "usnic_fwd.h" | 23 | #include "usnic_fwd.h" |
24 | #include "usnic_log.h" | 24 | #include "usnic_log.h" |
25 | 25 | ||
26 | static int usnic_fwd_devcmd_locked(struct usnic_fwd_dev *ufdev, int vnic_idx, | ||
27 | enum vnic_devcmd_cmd cmd, u64 *a0, | ||
28 | u64 *a1) | ||
29 | { | ||
30 | int status; | ||
31 | struct net_device *netdev = ufdev->netdev; | ||
32 | |||
33 | lockdep_assert_held(&ufdev->lock); | ||
34 | |||
35 | status = enic_api_devcmd_proxy_by_index(netdev, | ||
36 | vnic_idx, | ||
37 | cmd, | ||
38 | a0, a1, | ||
39 | 1000); | ||
40 | if (status) { | ||
41 | if (status == ERR_EINVAL && cmd == CMD_DEL_FILTER) { | ||
42 | usnic_dbg("Dev %s vnic idx %u cmd %u already deleted", | ||
43 | ufdev->name, vnic_idx, cmd); | ||
44 | } else { | ||
45 | usnic_err("Dev %s vnic idx %u cmd %u failed with status %d\n", | ||
46 | ufdev->name, vnic_idx, cmd, | ||
47 | status); | ||
48 | } | ||
49 | } else { | ||
50 | usnic_dbg("Dev %s vnic idx %u cmd %u success", | ||
51 | ufdev->name, vnic_idx, cmd); | ||
52 | } | ||
53 | |||
54 | return status; | ||
55 | } | ||
56 | |||
57 | static int usnic_fwd_devcmd(struct usnic_fwd_dev *ufdev, int vnic_idx, | ||
58 | enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1) | ||
59 | { | ||
60 | int status; | ||
61 | |||
62 | spin_lock(&ufdev->lock); | ||
63 | status = usnic_fwd_devcmd_locked(ufdev, vnic_idx, cmd, a0, a1); | ||
64 | spin_unlock(&ufdev->lock); | ||
65 | |||
66 | return status; | ||
67 | } | ||
68 | |||
26 | struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev) | 69 | struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev) |
27 | { | 70 | { |
28 | struct usnic_fwd_dev *ufdev; | 71 | struct usnic_fwd_dev *ufdev; |
@@ -34,6 +77,8 @@ struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev) | |||
34 | ufdev->pdev = pdev; | 77 | ufdev->pdev = pdev; |
35 | ufdev->netdev = pci_get_drvdata(pdev); | 78 | ufdev->netdev = pci_get_drvdata(pdev); |
36 | spin_lock_init(&ufdev->lock); | 79 | spin_lock_init(&ufdev->lock); |
80 | strncpy(ufdev->name, netdev_name(ufdev->netdev), | ||
81 | sizeof(ufdev->name) - 1); | ||
37 | 82 | ||
38 | return ufdev; | 83 | return ufdev; |
39 | } | 84 | } |
@@ -43,200 +88,208 @@ void usnic_fwd_dev_free(struct usnic_fwd_dev *ufdev) | |||
43 | kfree(ufdev); | 88 | kfree(ufdev); |
44 | } | 89 | } |
45 | 90 | ||
46 | static int usnic_fwd_devcmd(struct usnic_fwd_dev *ufdev, int vnic_idx, | 91 | void usnic_fwd_set_mac(struct usnic_fwd_dev *ufdev, char mac[ETH_ALEN]) |
47 | enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1) | ||
48 | { | 92 | { |
49 | int status; | 93 | spin_lock(&ufdev->lock); |
50 | struct net_device *netdev = ufdev->netdev; | 94 | memcpy(&ufdev->mac, mac, sizeof(ufdev->mac)); |
95 | spin_unlock(&ufdev->lock); | ||
96 | } | ||
51 | 97 | ||
98 | void usnic_fwd_carrier_up(struct usnic_fwd_dev *ufdev) | ||
99 | { | ||
52 | spin_lock(&ufdev->lock); | 100 | spin_lock(&ufdev->lock); |
53 | status = enic_api_devcmd_proxy_by_index(netdev, | 101 | ufdev->link_up = 1; |
54 | vnic_idx, | ||
55 | cmd, | ||
56 | a0, a1, | ||
57 | 1000); | ||
58 | spin_unlock(&ufdev->lock); | 102 | spin_unlock(&ufdev->lock); |
59 | if (status) { | 103 | } |
60 | if (status == ERR_EINVAL && cmd == CMD_DEL_FILTER) { | ||
61 | usnic_dbg("Dev %s vnic idx %u cmd %u already deleted", | ||
62 | netdev_name(netdev), vnic_idx, cmd); | ||
63 | } else { | ||
64 | usnic_err("Dev %s vnic idx %u cmd %u failed with status %d\n", | ||
65 | netdev_name(netdev), vnic_idx, cmd, | ||
66 | status); | ||
67 | } | ||
68 | } else { | ||
69 | usnic_dbg("Dev %s vnic idx %u cmd %u success", | ||
70 | netdev_name(netdev), vnic_idx, | ||
71 | cmd); | ||
72 | } | ||
73 | 104 | ||
74 | return status; | 105 | void usnic_fwd_carrier_down(struct usnic_fwd_dev *ufdev) |
106 | { | ||
107 | spin_lock(&ufdev->lock); | ||
108 | ufdev->link_up = 0; | ||
109 | spin_unlock(&ufdev->lock); | ||
110 | } | ||
111 | |||
112 | void usnic_fwd_set_mtu(struct usnic_fwd_dev *ufdev, unsigned int mtu) | ||
113 | { | ||
114 | spin_lock(&ufdev->lock); | ||
115 | ufdev->mtu = mtu; | ||
116 | spin_unlock(&ufdev->lock); | ||
117 | } | ||
118 | |||
119 | static int usnic_fwd_dev_ready_locked(struct usnic_fwd_dev *ufdev) | ||
120 | { | ||
121 | lockdep_assert_held(&ufdev->lock); | ||
122 | |||
123 | if (!ufdev->link_up) | ||
124 | return -EPERM; | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static void fill_tlv(struct filter_tlv *tlv, struct filter *filter, | ||
130 | struct filter_action *action) | ||
131 | { | ||
132 | tlv->type = CLSF_TLV_FILTER; | ||
133 | tlv->length = sizeof(struct filter); | ||
134 | *((struct filter *)&tlv->val) = *filter; | ||
135 | |||
136 | tlv = (struct filter_tlv *)((char *)tlv + sizeof(struct filter_tlv) + | ||
137 | sizeof(struct filter)); | ||
138 | tlv->type = CLSF_TLV_ACTION; | ||
139 | tlv->length = sizeof(struct filter_action); | ||
140 | *((struct filter_action *)&tlv->val) = *action; | ||
75 | } | 141 | } |
76 | 142 | ||
77 | int usnic_fwd_add_usnic_filter(struct usnic_fwd_dev *ufdev, int vnic_idx, | 143 | struct usnic_fwd_flow* |
78 | int rq_idx, struct usnic_fwd_filter *fwd_filter, | 144 | usnic_fwd_alloc_flow(struct usnic_fwd_dev *ufdev, struct filter *filter, |
79 | struct usnic_fwd_filter_hndl **filter_hndl) | 145 | struct usnic_filter_action *uaction) |
80 | { | 146 | { |
81 | struct filter_tlv *tlv, *tlv_va; | 147 | struct filter_tlv *tlv; |
82 | struct filter *filter; | ||
83 | struct filter_action *action; | ||
84 | struct pci_dev *pdev; | 148 | struct pci_dev *pdev; |
85 | struct usnic_fwd_filter_hndl *usnic_filter_hndl; | 149 | struct usnic_fwd_flow *flow; |
86 | int status; | 150 | uint64_t a0, a1; |
87 | u64 a0, a1; | 151 | uint64_t tlv_size; |
88 | u64 tlv_size; | ||
89 | dma_addr_t tlv_pa; | 152 | dma_addr_t tlv_pa; |
153 | int status; | ||
90 | 154 | ||
91 | pdev = ufdev->pdev; | 155 | pdev = ufdev->pdev; |
92 | tlv_size = (2*sizeof(struct filter_tlv) + | 156 | tlv_size = (2*sizeof(struct filter_tlv) + sizeof(struct filter) + |
93 | sizeof(struct filter) + | 157 | sizeof(struct filter_action)); |
94 | sizeof(struct filter_action)); | 158 | |
159 | flow = kzalloc(sizeof(*flow), GFP_ATOMIC); | ||
160 | if (!flow) | ||
161 | return ERR_PTR(-ENOMEM); | ||
162 | |||
95 | tlv = pci_alloc_consistent(pdev, tlv_size, &tlv_pa); | 163 | tlv = pci_alloc_consistent(pdev, tlv_size, &tlv_pa); |
96 | if (!tlv) { | 164 | if (!tlv) { |
97 | usnic_err("Failed to allocate memory\n"); | 165 | usnic_err("Failed to allocate memory\n"); |
98 | return -ENOMEM; | 166 | status = -ENOMEM; |
167 | goto out_free_flow; | ||
99 | } | 168 | } |
100 | 169 | ||
101 | usnic_filter_hndl = kzalloc(sizeof(*usnic_filter_hndl), GFP_ATOMIC); | 170 | fill_tlv(tlv, filter, &uaction->action); |
102 | if (!usnic_filter_hndl) { | 171 | |
103 | usnic_err("Failed to allocate memory for hndl\n"); | 172 | spin_lock(&ufdev->lock); |
104 | pci_free_consistent(pdev, tlv_size, tlv, tlv_pa); | 173 | status = usnic_fwd_dev_ready_locked(ufdev); |
105 | return -ENOMEM; | 174 | if (status) { |
175 | usnic_err("Forwarding dev %s not ready with status %d\n", | ||
176 | ufdev->name, status); | ||
177 | goto out_free_tlv; | ||
106 | } | 178 | } |
107 | 179 | ||
108 | tlv_va = tlv; | 180 | /* Issue Devcmd */ |
109 | a0 = tlv_pa; | 181 | a0 = tlv_pa; |
110 | a1 = tlv_size; | 182 | a1 = tlv_size; |
111 | memset(tlv, 0, tlv_size); | 183 | status = usnic_fwd_devcmd_locked(ufdev, uaction->vnic_idx, |
112 | tlv->type = CLSF_TLV_FILTER; | 184 | CMD_ADD_FILTER, &a0, &a1); |
113 | tlv->length = sizeof(struct filter); | ||
114 | filter = (struct filter *)&tlv->val; | ||
115 | filter->type = FILTER_USNIC_ID; | ||
116 | filter->u.usnic.ethtype = USNIC_ROCE_ETHERTYPE; | ||
117 | filter->u.usnic.flags = FILTER_FIELD_USNIC_ETHTYPE | | ||
118 | FILTER_FIELD_USNIC_ID | | ||
119 | FILTER_FIELD_USNIC_PROTO; | ||
120 | filter->u.usnic.proto_version = (USNIC_ROCE_GRH_VER << | ||
121 | USNIC_ROCE_GRH_VER_SHIFT) | ||
122 | | USNIC_PROTO_VER; | ||
123 | filter->u.usnic.usnic_id = fwd_filter->port_num; | ||
124 | tlv = (struct filter_tlv *)((char *)tlv + sizeof(struct filter_tlv) + | ||
125 | sizeof(struct filter)); | ||
126 | tlv->type = CLSF_TLV_ACTION; | ||
127 | tlv->length = sizeof(struct filter_action); | ||
128 | action = (struct filter_action *)&tlv->val; | ||
129 | action->type = FILTER_ACTION_RQ_STEERING; | ||
130 | action->u.rq_idx = rq_idx; | ||
131 | |||
132 | status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_ADD_FILTER, &a0, &a1); | ||
133 | pci_free_consistent(pdev, tlv_size, tlv_va, tlv_pa); | ||
134 | if (status) { | 185 | if (status) { |
135 | usnic_err("VF %s Filter add failed with status:%d", | 186 | usnic_err("VF %s Filter add failed with status:%d", |
136 | pci_name(pdev), | 187 | ufdev->name, status); |
137 | status); | 188 | status = -EFAULT; |
138 | kfree(usnic_filter_hndl); | 189 | goto out_free_tlv; |
139 | return status; | ||
140 | } else { | 190 | } else { |
141 | usnic_dbg("VF %s FILTER ID:%u", | 191 | usnic_dbg("VF %s FILTER ID:%llu", ufdev->name, a0); |
142 | pci_name(pdev), | ||
143 | (u32)a0); | ||
144 | } | 192 | } |
145 | 193 | ||
146 | usnic_filter_hndl->type = FILTER_USNIC_ID; | 194 | flow->flow_id = (uint32_t) a0; |
147 | usnic_filter_hndl->id = (u32)a0; | 195 | flow->vnic_idx = uaction->vnic_idx; |
148 | usnic_filter_hndl->vnic_idx = vnic_idx; | 196 | flow->ufdev = ufdev; |
149 | usnic_filter_hndl->ufdev = ufdev; | ||
150 | usnic_filter_hndl->filter = fwd_filter; | ||
151 | *filter_hndl = usnic_filter_hndl; | ||
152 | 197 | ||
153 | return status; | 198 | out_free_tlv: |
199 | spin_unlock(&ufdev->lock); | ||
200 | pci_free_consistent(pdev, tlv_size, tlv, tlv_pa); | ||
201 | if (!status) | ||
202 | return flow; | ||
203 | out_free_flow: | ||
204 | kfree(flow); | ||
205 | return ERR_PTR(status); | ||
154 | } | 206 | } |
155 | 207 | ||
156 | int usnic_fwd_del_filter(struct usnic_fwd_filter_hndl *filter_hndl) | 208 | int usnic_fwd_dealloc_flow(struct usnic_fwd_flow *flow) |
157 | { | 209 | { |
158 | int status; | 210 | int status; |
159 | u64 a0, a1; | 211 | u64 a0, a1; |
160 | struct net_device *netdev; | ||
161 | 212 | ||
162 | netdev = filter_hndl->ufdev->netdev; | 213 | a0 = flow->flow_id; |
163 | a0 = filter_hndl->id; | ||
164 | 214 | ||
165 | status = usnic_fwd_devcmd(filter_hndl->ufdev, filter_hndl->vnic_idx, | 215 | status = usnic_fwd_devcmd(flow->ufdev, flow->vnic_idx, |
166 | CMD_DEL_FILTER, &a0, &a1); | 216 | CMD_DEL_FILTER, &a0, &a1); |
167 | if (status) { | 217 | if (status) { |
168 | if (status == ERR_EINVAL) { | 218 | if (status == ERR_EINVAL) { |
169 | usnic_dbg("Filter %u already deleted for VF Idx %u pf: %s status: %d", | 219 | usnic_dbg("Filter %u already deleted for VF Idx %u pf: %s status: %d", |
170 | filter_hndl->id, filter_hndl->vnic_idx, | 220 | flow->flow_id, flow->vnic_idx, |
171 | netdev_name(netdev), status); | 221 | flow->ufdev->name, status); |
172 | status = 0; | ||
173 | kfree(filter_hndl); | ||
174 | } else { | 222 | } else { |
175 | usnic_err("PF %s VF Idx %u Filter: %u FILTER DELETE failed with status %d", | 223 | usnic_err("PF %s VF Idx %u Filter: %u FILTER DELETE failed with status %d", |
176 | netdev_name(netdev), | 224 | flow->ufdev->name, flow->vnic_idx, |
177 | filter_hndl->vnic_idx, filter_hndl->id, | 225 | flow->flow_id, status); |
178 | status); | ||
179 | } | 226 | } |
227 | status = 0; | ||
228 | /* | ||
229 | * Log the error and fake success to the caller because if | ||
230 | * a flow fails to be deleted in the firmware, it is an | ||
231 | * unrecoverable error. | ||
232 | */ | ||
180 | } else { | 233 | } else { |
181 | usnic_dbg("PF %s VF Idx %u Filter: %u FILTER DELETED", | 234 | usnic_dbg("PF %s VF Idx %u Filter: %u FILTER DELETED", |
182 | netdev_name(netdev), filter_hndl->vnic_idx, | 235 | flow->ufdev->name, flow->vnic_idx, |
183 | filter_hndl->id); | 236 | flow->flow_id); |
184 | kfree(filter_hndl); | ||
185 | } | 237 | } |
186 | 238 | ||
239 | kfree(flow); | ||
187 | return status; | 240 | return status; |
188 | } | 241 | } |
189 | 242 | ||
190 | int usnic_fwd_enable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx) | 243 | int usnic_fwd_enable_qp(struct usnic_fwd_dev *ufdev, int vnic_idx, int qp_idx) |
191 | { | 244 | { |
192 | int status; | 245 | int status; |
193 | struct net_device *pf_netdev; | 246 | struct net_device *pf_netdev; |
194 | u64 a0, a1; | 247 | u64 a0, a1; |
195 | 248 | ||
196 | pf_netdev = ufdev->netdev; | 249 | pf_netdev = ufdev->netdev; |
197 | a0 = rq_idx; | 250 | a0 = qp_idx; |
198 | a1 = CMD_QP_RQWQ; | 251 | a1 = CMD_QP_RQWQ; |
199 | 252 | ||
200 | status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_ENABLE, &a0, &a1); | 253 | status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_ENABLE, |
201 | 254 | &a0, &a1); | |
202 | if (status) { | 255 | if (status) { |
203 | usnic_err("PF %s VNIC Index %u RQ Index: %u ENABLE Failed with status %d", | 256 | usnic_err("PF %s VNIC Index %u RQ Index: %u ENABLE Failed with status %d", |
204 | netdev_name(pf_netdev), | 257 | netdev_name(pf_netdev), |
205 | vnic_idx, | 258 | vnic_idx, |
206 | rq_idx, | 259 | qp_idx, |
207 | status); | 260 | status); |
208 | } else { | 261 | } else { |
209 | usnic_dbg("PF %s VNIC Index %u RQ Index: %u ENABLED", | 262 | usnic_dbg("PF %s VNIC Index %u RQ Index: %u ENABLED", |
210 | netdev_name(pf_netdev), | 263 | netdev_name(pf_netdev), |
211 | vnic_idx, rq_idx); | 264 | vnic_idx, qp_idx); |
212 | } | 265 | } |
213 | 266 | ||
214 | return status; | 267 | return status; |
215 | } | 268 | } |
216 | 269 | ||
217 | int usnic_fwd_disable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx) | 270 | int usnic_fwd_disable_qp(struct usnic_fwd_dev *ufdev, int vnic_idx, int qp_idx) |
218 | { | 271 | { |
219 | int status; | 272 | int status; |
220 | u64 a0, a1; | 273 | u64 a0, a1; |
221 | struct net_device *pf_netdev; | 274 | struct net_device *pf_netdev; |
222 | 275 | ||
223 | pf_netdev = ufdev->netdev; | 276 | pf_netdev = ufdev->netdev; |
224 | a0 = rq_idx; | 277 | a0 = qp_idx; |
225 | a1 = CMD_QP_RQWQ; | 278 | a1 = CMD_QP_RQWQ; |
226 | 279 | ||
227 | status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_DISABLE, &a0, &a1); | 280 | status = usnic_fwd_devcmd(ufdev, vnic_idx, CMD_QP_DISABLE, |
228 | 281 | &a0, &a1); | |
229 | if (status) { | 282 | if (status) { |
230 | usnic_err("PF %s VNIC Index %u RQ Index: %u DISABLE Failed with status %d", | 283 | usnic_err("PF %s VNIC Index %u RQ Index: %u DISABLE Failed with status %d", |
231 | netdev_name(pf_netdev), | 284 | netdev_name(pf_netdev), |
232 | vnic_idx, | 285 | vnic_idx, |
233 | rq_idx, | 286 | qp_idx, |
234 | status); | 287 | status); |
235 | } else { | 288 | } else { |
236 | usnic_dbg("PF %s VNIC Index %u RQ Index: %u DISABLED", | 289 | usnic_dbg("PF %s VNIC Index %u RQ Index: %u DISABLED", |
237 | netdev_name(pf_netdev), | 290 | netdev_name(pf_netdev), |
238 | vnic_idx, | 291 | vnic_idx, |
239 | rq_idx); | 292 | qp_idx); |
240 | } | 293 | } |
241 | 294 | ||
242 | return status; | 295 | return status; |
diff --git a/drivers/infiniband/hw/usnic/usnic_fwd.h b/drivers/infiniband/hw/usnic/usnic_fwd.h index 6973901da8af..b146eb97d82c 100644 --- a/drivers/infiniband/hw/usnic/usnic_fwd.h +++ b/drivers/infiniband/hw/usnic/usnic_fwd.h | |||
@@ -20,39 +20,73 @@ | |||
20 | #define USNIC_FWD_H_ | 20 | #define USNIC_FWD_H_ |
21 | 21 | ||
22 | #include <linux/if.h> | 22 | #include <linux/if.h> |
23 | #include <linux/netdevice.h> | ||
23 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
24 | #include <linux/spinlock.h> | 25 | #include <linux/in.h> |
25 | 26 | ||
26 | #include "usnic_abi.h" | 27 | #include "usnic_abi.h" |
28 | #include "usnic_common_pkt_hdr.h" | ||
27 | #include "vnic_devcmd.h" | 29 | #include "vnic_devcmd.h" |
28 | 30 | ||
29 | struct usnic_fwd_dev { | 31 | struct usnic_fwd_dev { |
30 | struct pci_dev *pdev; | 32 | struct pci_dev *pdev; |
31 | struct net_device *netdev; | 33 | struct net_device *netdev; |
32 | spinlock_t lock; | 34 | spinlock_t lock; |
35 | /* | ||
36 | * The following fields can be read directly off the device. | ||
37 | * However, they should be set by a accessor function, except name, | ||
38 | * which cannot be changed. | ||
39 | */ | ||
40 | bool link_up; | ||
41 | char mac[ETH_ALEN]; | ||
42 | unsigned int mtu; | ||
43 | char name[IFNAMSIZ+1]; | ||
33 | }; | 44 | }; |
34 | 45 | ||
35 | struct usnic_fwd_filter { | 46 | struct usnic_fwd_flow { |
36 | enum usnic_transport_type transport; | 47 | uint32_t flow_id; |
37 | u16 port_num; | 48 | struct usnic_fwd_dev *ufdev; |
49 | unsigned int vnic_idx; | ||
38 | }; | 50 | }; |
39 | 51 | ||
40 | struct usnic_fwd_filter_hndl { | 52 | struct usnic_filter_action { |
41 | enum filter_type type; | 53 | int vnic_idx; |
42 | u32 id; | 54 | struct filter_action action; |
43 | u32 vnic_idx; | ||
44 | struct usnic_fwd_dev *ufdev; | ||
45 | struct list_head link; | ||
46 | struct usnic_fwd_filter *filter; | ||
47 | }; | 55 | }; |
48 | 56 | ||
49 | struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev); | 57 | struct usnic_fwd_dev *usnic_fwd_dev_alloc(struct pci_dev *pdev); |
50 | void usnic_fwd_dev_free(struct usnic_fwd_dev *ufdev); | 58 | void usnic_fwd_dev_free(struct usnic_fwd_dev *ufdev); |
51 | int usnic_fwd_add_usnic_filter(struct usnic_fwd_dev *ufdev, int vnic_idx, | 59 | |
52 | int rq_idx, struct usnic_fwd_filter *filter, | 60 | void usnic_fwd_set_mac(struct usnic_fwd_dev *ufdev, char mac[ETH_ALEN]); |
53 | struct usnic_fwd_filter_hndl **filter_hndl); | 61 | void usnic_fwd_carrier_up(struct usnic_fwd_dev *ufdev); |
54 | int usnic_fwd_del_filter(struct usnic_fwd_filter_hndl *filter_hndl); | 62 | void usnic_fwd_carrier_down(struct usnic_fwd_dev *ufdev); |
55 | int usnic_fwd_enable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx); | 63 | void usnic_fwd_set_mtu(struct usnic_fwd_dev *ufdev, unsigned int mtu); |
56 | int usnic_fwd_disable_rq(struct usnic_fwd_dev *ufdev, int vnic_idx, int rq_idx); | 64 | |
65 | /* | ||
66 | * Allocate a flow on this forwarding device. Whoever calls this function, | ||
67 | * must monitor netdev events on ufdev's netdevice. If NETDEV_REBOOT or | ||
68 | * NETDEV_DOWN is seen, flow will no longer function and must be | ||
69 | * immediately freed by calling usnic_dealloc_flow. | ||
70 | */ | ||
71 | struct usnic_fwd_flow* | ||
72 | usnic_fwd_alloc_flow(struct usnic_fwd_dev *ufdev, struct filter *filter, | ||
73 | struct usnic_filter_action *action); | ||
74 | int usnic_fwd_dealloc_flow(struct usnic_fwd_flow *flow); | ||
75 | int usnic_fwd_enable_qp(struct usnic_fwd_dev *ufdev, int vnic_idx, int qp_idx); | ||
76 | int usnic_fwd_disable_qp(struct usnic_fwd_dev *ufdev, int vnic_idx, int qp_idx); | ||
77 | |||
78 | static inline void usnic_fwd_init_usnic_filter(struct filter *filter, | ||
79 | uint32_t usnic_id) | ||
80 | { | ||
81 | filter->type = FILTER_USNIC_ID; | ||
82 | filter->u.usnic.ethtype = USNIC_ROCE_ETHERTYPE; | ||
83 | filter->u.usnic.flags = FILTER_FIELD_USNIC_ETHTYPE | | ||
84 | FILTER_FIELD_USNIC_ID | | ||
85 | FILTER_FIELD_USNIC_PROTO; | ||
86 | filter->u.usnic.proto_version = (USNIC_ROCE_GRH_VER << | ||
87 | USNIC_ROCE_GRH_VER_SHIFT) | | ||
88 | USNIC_PROTO_VER; | ||
89 | filter->u.usnic.usnic_id = usnic_id; | ||
90 | } | ||
57 | 91 | ||
58 | #endif /* !USNIC_FWD_H_ */ | 92 | #endif /* !USNIC_FWD_H_ */ |