diff options
author | Len Brown <len.brown@intel.com> | 2009-01-09 03:39:43 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-01-09 03:39:43 -0500 |
commit | b2576e1d4408e134e2188c967b1f28af39cd79d4 (patch) | |
tree | 004f3c82faab760f304ce031d6d2f572e7746a50 /drivers/net/enic/vnic_dev.c | |
parent | 3cc8a5f4ba91f67bbdb81a43a99281a26aab8d77 (diff) | |
parent | 2150edc6c5cf00f7adb54538b9ea2a3e9cedca3f (diff) |
Merge branch 'linus' into release
Diffstat (limited to 'drivers/net/enic/vnic_dev.c')
-rw-r--r-- | drivers/net/enic/vnic_dev.c | 70 |
1 files changed, 44 insertions, 26 deletions
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 4d104f5c30f9..11708579b6ce 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c | |||
@@ -43,6 +43,7 @@ struct vnic_dev { | |||
43 | struct vnic_devcmd_notify *notify; | 43 | struct vnic_devcmd_notify *notify; |
44 | struct vnic_devcmd_notify notify_copy; | 44 | struct vnic_devcmd_notify notify_copy; |
45 | dma_addr_t notify_pa; | 45 | dma_addr_t notify_pa; |
46 | u32 notify_sz; | ||
46 | u32 *linkstatus; | 47 | u32 *linkstatus; |
47 | dma_addr_t linkstatus_pa; | 48 | dma_addr_t linkstatus_pa; |
48 | struct vnic_stats *stats; | 49 | struct vnic_stats *stats; |
@@ -235,14 +236,6 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | |||
235 | struct vnic_devcmd __iomem *devcmd = vdev->devcmd; | 236 | struct vnic_devcmd __iomem *devcmd = vdev->devcmd; |
236 | int delay; | 237 | int delay; |
237 | u32 status; | 238 | u32 status; |
238 | int dev_cmd_err[] = { | ||
239 | /* convert from fw's version of error.h to host's version */ | ||
240 | 0, /* ERR_SUCCESS */ | ||
241 | EINVAL, /* ERR_EINVAL */ | ||
242 | EFAULT, /* ERR_EFAULT */ | ||
243 | EPERM, /* ERR_EPERM */ | ||
244 | EBUSY, /* ERR_EBUSY */ | ||
245 | }; | ||
246 | int err; | 239 | int err; |
247 | 240 | ||
248 | status = ioread32(&devcmd->status); | 241 | status = ioread32(&devcmd->status); |
@@ -270,10 +263,12 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | |||
270 | if (!(status & STAT_BUSY)) { | 263 | if (!(status & STAT_BUSY)) { |
271 | 264 | ||
272 | if (status & STAT_ERROR) { | 265 | if (status & STAT_ERROR) { |
273 | err = dev_cmd_err[(int)readq(&devcmd->args[0])]; | 266 | err = (int)readq(&devcmd->args[0]); |
274 | printk(KERN_ERR "Error %d devcmd %d\n", | 267 | if (err != ERR_ECMDUNKNOWN || |
275 | err, _CMD_N(cmd)); | 268 | cmd != CMD_CAPABILITY) |
276 | return -err; | 269 | printk(KERN_ERR "Error %d devcmd %d\n", |
270 | err, _CMD_N(cmd)); | ||
271 | return err; | ||
277 | } | 272 | } |
278 | 273 | ||
279 | if (_CMD_DIR(cmd) & _CMD_DIR_READ) { | 274 | if (_CMD_DIR(cmd) & _CMD_DIR_READ) { |
@@ -290,6 +285,17 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd, | |||
290 | return -ETIMEDOUT; | 285 | return -ETIMEDOUT; |
291 | } | 286 | } |
292 | 287 | ||
288 | static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd) | ||
289 | { | ||
290 | u64 a0 = (u32)cmd, a1 = 0; | ||
291 | int wait = 1000; | ||
292 | int err; | ||
293 | |||
294 | err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait); | ||
295 | |||
296 | return !(err || a0); | ||
297 | } | ||
298 | |||
293 | int vnic_dev_fw_info(struct vnic_dev *vdev, | 299 | int vnic_dev_fw_info(struct vnic_dev *vdev, |
294 | struct vnic_devcmd_fw_info **fw_info) | 300 | struct vnic_devcmd_fw_info **fw_info) |
295 | { | 301 | { |
@@ -489,10 +495,7 @@ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr) | |||
489 | 495 | ||
490 | err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); | 496 | err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); |
491 | if (err) | 497 | if (err) |
492 | printk(KERN_ERR | 498 | printk(KERN_ERR "Can't add addr [%pM], %d\n", addr, err); |
493 | "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", | ||
494 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], | ||
495 | err); | ||
496 | } | 499 | } |
497 | 500 | ||
498 | void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) | 501 | void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) |
@@ -507,16 +510,14 @@ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr) | |||
507 | 510 | ||
508 | err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); | 511 | err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait); |
509 | if (err) | 512 | if (err) |
510 | printk(KERN_ERR | 513 | printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err); |
511 | "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n", | ||
512 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], | ||
513 | err); | ||
514 | } | 514 | } |
515 | 515 | ||
516 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) | 516 | int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) |
517 | { | 517 | { |
518 | u64 a0, a1; | 518 | u64 a0, a1; |
519 | int wait = 1000; | 519 | int wait = 1000; |
520 | int r; | ||
520 | 521 | ||
521 | if (!vdev->notify) { | 522 | if (!vdev->notify) { |
522 | vdev->notify = pci_alloc_consistent(vdev->pdev, | 523 | vdev->notify = pci_alloc_consistent(vdev->pdev, |
@@ -524,13 +525,16 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr) | |||
524 | &vdev->notify_pa); | 525 | &vdev->notify_pa); |
525 | if (!vdev->notify) | 526 | if (!vdev->notify) |
526 | return -ENOMEM; | 527 | return -ENOMEM; |
528 | memset(vdev->notify, 0, sizeof(struct vnic_devcmd_notify)); | ||
527 | } | 529 | } |
528 | 530 | ||
529 | a0 = vdev->notify_pa; | 531 | a0 = vdev->notify_pa; |
530 | a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; | 532 | a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL; |
531 | a1 += sizeof(struct vnic_devcmd_notify); | 533 | a1 += sizeof(struct vnic_devcmd_notify); |
532 | 534 | ||
533 | return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); | 535 | r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); |
536 | vdev->notify_sz = (r == 0) ? (u32)a1 : 0; | ||
537 | return r; | ||
534 | } | 538 | } |
535 | 539 | ||
536 | void vnic_dev_notify_unset(struct vnic_dev *vdev) | 540 | void vnic_dev_notify_unset(struct vnic_dev *vdev) |
@@ -543,22 +547,22 @@ void vnic_dev_notify_unset(struct vnic_dev *vdev) | |||
543 | a1 += sizeof(struct vnic_devcmd_notify); | 547 | a1 += sizeof(struct vnic_devcmd_notify); |
544 | 548 | ||
545 | vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); | 549 | vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait); |
550 | vdev->notify_sz = 0; | ||
546 | } | 551 | } |
547 | 552 | ||
548 | static int vnic_dev_notify_ready(struct vnic_dev *vdev) | 553 | static int vnic_dev_notify_ready(struct vnic_dev *vdev) |
549 | { | 554 | { |
550 | u32 *words; | 555 | u32 *words; |
551 | unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4; | 556 | unsigned int nwords = vdev->notify_sz / 4; |
552 | unsigned int i; | 557 | unsigned int i; |
553 | u32 csum; | 558 | u32 csum; |
554 | 559 | ||
555 | if (!vdev->notify) | 560 | if (!vdev->notify || !vdev->notify_sz) |
556 | return 0; | 561 | return 0; |
557 | 562 | ||
558 | do { | 563 | do { |
559 | csum = 0; | 564 | csum = 0; |
560 | memcpy(&vdev->notify_copy, vdev->notify, | 565 | memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz); |
561 | sizeof(struct vnic_devcmd_notify)); | ||
562 | words = (u32 *)&vdev->notify_copy; | 566 | words = (u32 *)&vdev->notify_copy; |
563 | for (i = 1; i < nwords; i++) | 567 | for (i = 1; i < nwords; i++) |
564 | csum += words[i]; | 568 | csum += words[i]; |
@@ -571,7 +575,20 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) | |||
571 | { | 575 | { |
572 | u64 a0 = (u32)arg, a1 = 0; | 576 | u64 a0 = (u32)arg, a1 = 0; |
573 | int wait = 1000; | 577 | int wait = 1000; |
574 | return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); | 578 | int r = 0; |
579 | |||
580 | if (vnic_dev_capable(vdev, CMD_INIT)) | ||
581 | r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); | ||
582 | else { | ||
583 | vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); | ||
584 | if (a0 & CMD_INITF_DEFAULT_MAC) { | ||
585 | // Emulate these for old CMD_INIT_v1 which | ||
586 | // didn't pass a0 so no CMD_INITF_*. | ||
587 | vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); | ||
588 | vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); | ||
589 | } | ||
590 | } | ||
591 | return r; | ||
575 | } | 592 | } |
576 | 593 | ||
577 | int vnic_dev_link_status(struct vnic_dev *vdev) | 594 | int vnic_dev_link_status(struct vnic_dev *vdev) |
@@ -672,3 +689,4 @@ err_out: | |||
672 | return NULL; | 689 | return NULL; |
673 | } | 690 | } |
674 | 691 | ||
692 | |||