diff options
| author | Vasanthy Kolluri <vkolluri@cisco.com> | 2010-06-24 06:51:43 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-06-25 23:50:23 -0400 |
| commit | 70feadf36df94dc0dc2f32fec4c131ecd75344f2 (patch) | |
| tree | 2b397cecaedf4c42134f4d1281ab74c5b8c1be79 | |
| parent | a7a79debcca02fbf908c0abed8d8fb25d0e51b48 (diff) | |
enic: Add new firmware devcmds
Add new firmware devcmds - CMD_PROXY_BY_BDF, CMD_PACKET_FILTER_ALL,
CMD_ENABLE_WAIT.
Signed-off-by: Scott Feldman <scofeldm@cisco.com>
Signed-off-by: Vasanthy Kolluri <vkolluri@cisco.com>
Signed-off-by: Roopa Prabhu <roprabhu@cisco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/enic/vnic_dev.c | 136 | ||||
| -rw-r--r-- | drivers/net/enic/vnic_dev.h | 5 | ||||
| -rw-r--r-- | drivers/net/enic/vnic_devcmd.h | 14 |
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 | ||
| 33 | enum vnic_proxy_type { | ||
| 34 | PROXY_NONE, | ||
| 35 | PROXY_BY_BDF, | ||
| 36 | }; | ||
| 37 | |||
| 33 | struct vnic_res { | 38 | struct 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 | ||
| 260 | int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | 268 | static 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 | ||
| 325 | static 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 | |||
| 357 | static 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 | |||
| 373 | void 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 | |||
| 379 | void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev) | ||
| 380 | { | ||
| 381 | vdev->proxy = PROXY_NONE; | ||
| 382 | vdev->proxy_index = 0; | ||
| 383 | } | ||
| 384 | |||
| 385 | int 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 | |||
| 315 | static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd) | 399 | static 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 | ||
| 517 | int 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 | |||
| 433 | int vnic_dev_disable(struct vnic_dev *vdev) | 530 | int 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 | ||
| 669 | int 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 | |||
| 572 | int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) | 689 | int 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); |
| 96 | int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | 96 | int 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); |
| 98 | void vnic_dev_cmd_proxy_by_bdf_start(struct vnic_dev *vdev, u16 bdf); | ||
| 99 | void vnic_dev_cmd_proxy_end(struct vnic_dev *vdev); | ||
| 98 | int vnic_dev_fw_info(struct vnic_dev *vdev, | 100 | int vnic_dev_fw_info(struct vnic_dev *vdev, |
| 99 | struct vnic_devcmd_fw_info **fw_info); | 101 | struct vnic_devcmd_fw_info **fw_info); |
| 100 | int vnic_dev_hw_version(struct vnic_dev *vdev, | 102 | int 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); | |||
| 106 | int vnic_dev_hang_notify(struct vnic_dev *vdev); | 108 | int vnic_dev_hang_notify(struct vnic_dev *vdev); |
| 107 | int vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast, | 109 | int 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); |
| 111 | int vnic_dev_packet_filter_all(struct vnic_dev *vdev, int directed, | ||
| 112 | int multicast, int broadcast, int promisc, int allmulti); | ||
| 109 | int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); | 113 | int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr); |
| 110 | int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); | 114 | int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr); |
| 111 | int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); | 115 | int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr); |
| @@ -124,6 +128,7 @@ u32 vnic_dev_notify_status(struct vnic_dev *vdev); | |||
| 124 | u32 vnic_dev_uif(struct vnic_dev *vdev); | 128 | u32 vnic_dev_uif(struct vnic_dev *vdev); |
| 125 | int vnic_dev_close(struct vnic_dev *vdev); | 129 | int vnic_dev_close(struct vnic_dev *vdev); |
| 126 | int vnic_dev_enable(struct vnic_dev *vdev); | 130 | int vnic_dev_enable(struct vnic_dev *vdev); |
| 131 | int vnic_dev_enable_wait(struct vnic_dev *vdev); | ||
| 127 | int vnic_dev_disable(struct vnic_dev *vdev); | 132 | int vnic_dev_disable(struct vnic_dev *vdev); |
| 128 | int vnic_dev_open(struct vnic_dev *vdev, int arg); | 133 | int vnic_dev_open(struct vnic_dev *vdev, int arg); |
| 129 | int vnic_dev_open_done(struct vnic_dev *vdev, int *done); | 134 | int 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 */ |
