aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/enic/vnic_dev.c136
-rw-r--r--drivers/net/enic/vnic_dev.h5
-rw-r--r--drivers/net/enic/vnic_devcmd.h14
3 files changed, 146 insertions, 9 deletions
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 042f4b84a870..180912f48007 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -30,6 +30,11 @@
30#include "vnic_dev.h" 30#include "vnic_dev.h"
31#include "vnic_stats.h" 31#include "vnic_stats.h"
32 32
33enum vnic_proxy_type {
34 PROXY_NONE,
35 PROXY_BY_BDF,
36};
37
33struct vnic_res { 38struct vnic_res {
34 void __iomem *vaddr; 39 void __iomem *vaddr;
35 dma_addr_t bus_addr; 40 dma_addr_t bus_addr;
@@ -55,6 +60,9 @@ struct vnic_dev {
55 struct vnic_devcmd_fw_info *fw_info; 60 struct vnic_devcmd_fw_info *fw_info;
56 dma_addr_t fw_info_pa; 61 dma_addr_t fw_info_pa;
57 u32 cap_flags; 62 u32 cap_flags;
63 enum vnic_proxy_type proxy;
64 u32 proxy_index;
65 u64 args[VNIC_DEVCMD_NARGS];
58}; 66};
59 67
60#define VNIC_MAX_RES_HDR_SIZE \ 68#define VNIC_MAX_RES_HDR_SIZE \
@@ -257,10 +265,11 @@ void vnic_dev_free_desc_ring(struct vnic_dev *vdev, struct vnic_dev_ring *ring)
257 } 265 }
258} 266}
259 267
260int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, 268static int _vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
261 u64 *a0, u64 *a1, int wait) 269 int wait)
262{ 270{
263 struct vnic_devcmd __iomem *devcmd = vdev->devcmd; 271 struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
272 unsigned int i;
264 int delay; 273 int delay;
265 u32 status; 274 u32 status;
266 int err; 275 int err;
@@ -272,8 +281,8 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
272 } 281 }
273 282
274 if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) { 283 if (_CMD_DIR(cmd) & _CMD_DIR_WRITE) {
275 writeq(*a0, &devcmd->args[0]); 284 for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
276 writeq(*a1, &devcmd->args[1]); 285 writeq(vdev->args[i], &devcmd->args[i]);
277 wmb(); 286 wmb();
278 } 287 }
279 288
@@ -287,6 +296,7 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
287 udelay(100); 296 udelay(100);
288 297
289 status = ioread32(&devcmd->status); 298 status = ioread32(&devcmd->status);
299
290 if (!(status & STAT_BUSY)) { 300 if (!(status & STAT_BUSY)) {
291 301
292 if (status & STAT_ERROR) { 302 if (status & STAT_ERROR) {
@@ -300,8 +310,8 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
300 310
301 if (_CMD_DIR(cmd) & _CMD_DIR_READ) { 311 if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
302 rmb(); 312 rmb();
303 *a0 = readq(&devcmd->args[0]); 313 for (i = 0; i < VNIC_DEVCMD_NARGS; i++)
304 *a1 = readq(&devcmd->args[1]); 314 vdev->args[i] = readq(&devcmd->args[i]);
305 } 315 }
306 316
307 return 0; 317 return 0;
@@ -312,6 +322,80 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
312 return -ETIMEDOUT; 322 return -ETIMEDOUT;
313} 323}
314 324
325static int vnic_dev_cmd_proxy_by_bdf(struct vnic_dev *vdev,
326 enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
327{
328 u32 status;
329 int err;
330
331 memset(vdev->args, 0, sizeof(vdev->args));
332
333 vdev->args[0] = vdev->proxy_index; /* bdf */
334 vdev->args[1] = cmd;
335 vdev->args[2] = *a0;
336 vdev->args[3] = *a1;
337
338 err = _vnic_dev_cmd(vdev, CMD_PROXY_BY_BDF, wait);
339 if (err)
340 return err;
341
342 status = (u32)vdev->args[0];
343 if (status & STAT_ERROR) {
344 err = (int)vdev->args[1];
345 if (err != ERR_ECMDUNKNOWN ||
346 cmd != CMD_CAPABILITY)
347 pr_err("Error %d proxy devcmd %d\n", err, _CMD_N(cmd));
348 return err;
349 }
350
351 *a0 = vdev->args[1];
352 *a1 = vdev->args[2];
353
354 return 0;
355}
356
357static int vnic_dev_cmd_no_proxy(struct vnic_dev *vdev,
358 enum vnic_devcmd_cmd cmd, u64 *a0, u64 *a1, int wait)
359{
360 int err;
361
362 vdev->args[0] = *a0;
363 vdev->args[1] = *a1;
364
365 err = _vnic_dev_cmd(vdev, cmd, wait);
366
367 *a0 = vdev->args[0];
368 *a1 = vdev->args[1];
369
370 return err;
371}
372
373void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf)
374{
375 vdev->proxy = PROXY_BY_BDF;
376 vdev->proxy_index = bdf;
377}
378
379void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev)
380{
381 vdev->proxy = PROXY_NONE;
382 vdev->proxy_index = 0;
383}
384
385int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
386 u64 *a0, u64 *a1, int wait)
387{
388 memset(vdev->args, 0, sizeof(vdev->args));
389
390 switch (vdev->proxy) {
391 case PROXY_BY_BDF:
392 return vnic_dev_cmd_proxy_by_bdf(vdev, cmd, a0, a1, wait);
393 case PROXY_NONE:
394 default:
395 return vnic_dev_cmd_no_proxy(vdev, cmd, a0, a1, wait);
396 }
397}
398
315static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd) 399static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
316{ 400{
317 u64 a0 = (u32)cmd, a1 = 0; 401 u64 a0 = (u32)cmd, a1 = 0;
@@ -430,6 +514,19 @@ int vnic_dev_enable(struct vnic_dev *vdev)
430 return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait); 514 return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
431} 515}
432 516
517int vnic_dev_enable_wait(struct vnic_dev *vdev)
518{
519 u64 a0 = 0, a1 = 0;
520 int wait = 1000;
521 int err;
522
523 err = vnic_dev_cmd(vdev, CMD_ENABLE_WAIT, &a0, &a1, wait);
524 if (err == ERR_ECMDUNKNOWN)
525 return vnic_dev_cmd(vdev, CMD_ENABLE, &a0, &a1, wait);
526
527 return err;
528}
529
433int vnic_dev_disable(struct vnic_dev *vdev) 530int vnic_dev_disable(struct vnic_dev *vdev)
434{ 531{
435 u64 a0 = 0, a1 = 0; 532 u64 a0 = 0, a1 = 0;
@@ -569,6 +666,26 @@ int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
569 return err; 666 return err;
570} 667}
571 668
669int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed,
670 int multicast, int broadcast, int promisc, int allmulti)
671{
672 u64 a0, a1 = 0;
673 int wait = 1000;
674 int err;
675
676 a0 = (directed ? CMD_PFILTER_DIRECTED : 0) |
677 (multicast ? CMD_PFILTER_MULTICAST : 0) |
678 (broadcast ? CMD_PFILTER_BROADCAST : 0) |
679 (promisc ? CMD_PFILTER_PROMISCUOUS : 0) |
680 (allmulti ? CMD_PFILTER_ALL_MULTICAST : 0);
681
682 err = vnic_dev_cmd(vdev, CMD_PACKET_FILTER_ALL, &a0, &a1, wait);
683 if (err)
684 pr_err("Can't set packet filter\n");
685
686 return err;
687}
688
572int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) 689int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
573{ 690{
574 u64 a0 = 0, a1 = 0; 691 u64 a0 = 0, a1 = 0;
@@ -731,8 +848,9 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
731 else { 848 else {
732 vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); 849 vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
733 if (a0 & CMD_INITF_DEFAULT_MAC) { 850 if (a0 & CMD_INITF_DEFAULT_MAC) {
734 // Emulate these for old CMD_INIT_v1 which 851 /* Emulate these for old CMD_INIT_v1 which
735 // didn't pass a0 so no CMD_INITF_*. 852 * didn't pass a0 so no CMD_INITF_*.
853 */
736 vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); 854 vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
737 vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); 855 vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
738 } 856 }
@@ -754,7 +872,7 @@ int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err)
754 872
755 *done = (a0 == 0); 873 *done = (a0 == 0);
756 874
757 *err = (a0 == 0) ? a1 : 0; 875 *err = (a0 == 0) ? (int)a1:0;
758 876
759 return 0; 877 return 0;
760} 878}
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index 11659c6678f5..cfdaa69bf5a5 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -95,6 +95,8 @@ void vnic_dev_free_desc_ring(struct vnic_dev *vdev,
95 struct vnic_dev_ring *ring); 95 struct vnic_dev_ring *ring);
96int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, 96int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
97 u64 *a0, u64 *a1, int wait); 97 u64 *a0, u64 *a1, int wait);
98void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf);
99void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev);
98int vnic_dev_fw_info(struct vnic_dev *vdev, 100int vnic_dev_fw_info(struct vnic_dev *vdev,
99 struct vnic_devcmd_fw_info **fw_info); 101 struct vnic_devcmd_fw_info **fw_info);
100int vnic_dev_hw_version(struct vnic_dev *vdev, 102int vnic_dev_hw_version(struct vnic_dev *vdev,
@@ -106,6 +108,8 @@ int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
106int vnic_dev_hang_notify(struct vnic_dev *vdev); 108int vnic_dev_hang_notify(struct vnic_dev *vdev);
107int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, 109int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
108 int broadcast, int promisc, int allmulti); 110 int broadcast, int promisc, int allmulti);
111int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed,
112 int multicast, int broadcast, int promisc, int allmulti);
109int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); 113int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
110int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); 114int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
111int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); 115int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
@@ -124,6 +128,7 @@ u32 vnic_dev_notify_status(struct vnic_dev *vdev);
124u32 vnic_dev_uif(struct vnic_dev *vdev); 128u32 vnic_dev_uif(struct vnic_dev *vdev);
125int vnic_dev_close(struct vnic_dev *vdev); 129int vnic_dev_close(struct vnic_dev *vdev);
126int vnic_dev_enable(struct vnic_dev *vdev); 130int vnic_dev_enable(struct vnic_dev *vdev);
131int vnic_dev_enable_wait(struct vnic_dev *vdev);
127int vnic_dev_disable(struct vnic_dev *vdev); 132int vnic_dev_disable(struct vnic_dev *vdev);
128int vnic_dev_open(struct vnic_dev *vdev, int arg); 133int vnic_dev_open(struct vnic_dev *vdev, int arg);
129int vnic_dev_open_done(struct vnic_dev *vdev, int *done); 134int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index 1c4fb35671fa..e6c80c77dbd8 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -98,6 +98,9 @@ enum vnic_devcmd_cmd {
98 /* set Rx packet filter: (u32)a0=filters (see CMD_PFILTER_*) */ 98 /* set Rx packet filter: (u32)a0=filters (see CMD_PFILTER_*) */
99 CMD_PACKET_FILTER = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 7), 99 CMD_PACKET_FILTER = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 7),
100 100
101 /* set Rx packet filter for all: (u32)a0=filters (see CMD_PFILTER_*) */
102 CMD_PACKET_FILTER_ALL = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 7),
103
101 /* hang detection notification */ 104 /* hang detection notification */
102 CMD_HANG_NOTIFY = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 8), 105 CMD_HANG_NOTIFY = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 8),
103 106
@@ -171,6 +174,9 @@ enum vnic_devcmd_cmd {
171 /* enable virtual link */ 174 /* enable virtual link */
172 CMD_ENABLE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28), 175 CMD_ENABLE = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28),
173 176
177 /* enable virtual link, waiting variant. */
178 CMD_ENABLE_WAIT = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 28),
179
174 /* disable virtual link */ 180 /* disable virtual link */
175 CMD_DISABLE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 29), 181 CMD_DISABLE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 29),
176 182
@@ -224,6 +230,14 @@ enum vnic_devcmd_cmd {
224 * in: (u32)a0=new vlan rewrite mode 230 * in: (u32)a0=new vlan rewrite mode
225 * out: (u32)a0=old vlan rewrite mode */ 231 * out: (u32)a0=old vlan rewrite mode */
226 CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41), 232 CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41),
233
234 /*
235 * in: (u16)a0=bdf of target vnic
236 * (u32)a1=cmd to proxy
237 * a2-a15=args to cmd in a1
238 * out: (u32)a0=status of proxied cmd
239 * a1-a15=out args of proxied cmd */
240 CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42),
227}; 241};
228 242
229/* flags for CMD_OPEN */ 243/* flags for CMD_OPEN */