Commit 99ef563901a18d44a6c2eadd2b958e2e83aeca51
Committed by
David S. Miller
1 parent
f8cac14acf
Exists in
master
and in
20 other branches
enic: Use a lighter reset operation for enic devices
The port profile information for a dynamic enic device is set by the upper layers, that are oblivious to the device reset operation. We do not want a reset operation erase the network state of a dynamic enic device as there is no way to set up the port profile information again. Hence a lighter reset operation called hang reset is used. Hang reset, unlike soft reset does not reset the network state and resets the host side state only. 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>
Showing 4 changed files with 55 additions and 8 deletions Side-by-side Diff
drivers/net/enic/enic_main.c
... | ... | @@ -812,9 +812,10 @@ |
812 | 812 | return net_stats; |
813 | 813 | } |
814 | 814 | |
815 | -static void enic_reset_mcaddrs(struct enic *enic) | |
815 | +static void enic_reset_multicast_list(struct enic *enic) | |
816 | 816 | { |
817 | 817 | enic->mc_count = 0; |
818 | + enic->flags = 0; | |
818 | 819 | } |
819 | 820 | |
820 | 821 | static int enic_set_mac_addr(struct net_device *netdev, char *addr) |
821 | 822 | |
822 | 823 | |
... | ... | @@ -1847,15 +1848,15 @@ |
1847 | 1848 | return err; |
1848 | 1849 | } |
1849 | 1850 | |
1850 | -static int enic_dev_soft_reset(struct enic *enic) | |
1851 | +static int enic_dev_hang_reset(struct enic *enic) | |
1851 | 1852 | { |
1852 | 1853 | int err; |
1853 | 1854 | |
1854 | - err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset, | |
1855 | - vnic_dev_soft_reset_done, 0); | |
1855 | + err = enic_dev_wait(enic->vdev, vnic_dev_hang_reset, | |
1856 | + vnic_dev_hang_reset_done, 0); | |
1856 | 1857 | if (err) |
1857 | 1858 | printk(KERN_ERR PFX |
1858 | - "vNIC soft reset failed, err %d.\n", err); | |
1859 | + "vNIC hang reset failed, err %d.\n", err); | |
1859 | 1860 | |
1860 | 1861 | return err; |
1861 | 1862 | } |
... | ... | @@ -1906,9 +1907,8 @@ |
1906 | 1907 | spin_unlock(&enic->devcmd_lock); |
1907 | 1908 | |
1908 | 1909 | enic_stop(enic->netdev); |
1909 | - enic_dev_soft_reset(enic); | |
1910 | - vnic_dev_init(enic->vdev, 0); | |
1911 | - enic_reset_mcaddrs(enic); | |
1910 | + enic_dev_hang_reset(enic); | |
1911 | + enic_reset_multicast_list(enic); | |
1912 | 1912 | enic_init_vnic_resources(enic); |
1913 | 1913 | enic_set_niccfg(enic); |
1914 | 1914 | enic_dev_set_ig_vlan_rewrite_mode(enic); |
drivers/net/enic/vnic_dev.c
... | ... | @@ -486,6 +486,44 @@ |
486 | 486 | return 0; |
487 | 487 | } |
488 | 488 | |
489 | +int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg) | |
490 | +{ | |
491 | + u64 a0 = (u32)arg, a1 = 0; | |
492 | + int wait = 1000; | |
493 | + int err; | |
494 | + | |
495 | + err = vnic_dev_cmd(vdev, CMD_HANG_RESET, &a0, &a1, wait); | |
496 | + if (err == ERR_ECMDUNKNOWN) { | |
497 | + err = vnic_dev_soft_reset(vdev, arg); | |
498 | + if (err) | |
499 | + return err; | |
500 | + | |
501 | + return vnic_dev_init(vdev, 0); | |
502 | + } | |
503 | + | |
504 | + return err; | |
505 | +} | |
506 | + | |
507 | +int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done) | |
508 | +{ | |
509 | + u64 a0 = 0, a1 = 0; | |
510 | + int wait = 1000; | |
511 | + int err; | |
512 | + | |
513 | + *done = 0; | |
514 | + | |
515 | + err = vnic_dev_cmd(vdev, CMD_HANG_RESET_STATUS, &a0, &a1, wait); | |
516 | + if (err) { | |
517 | + if (err == ERR_ECMDUNKNOWN) | |
518 | + return vnic_dev_soft_reset_done(vdev, done); | |
519 | + return err; | |
520 | + } | |
521 | + | |
522 | + *done = (a0 == 0); | |
523 | + | |
524 | + return 0; | |
525 | +} | |
526 | + | |
489 | 527 | int vnic_dev_hang_notify(struct vnic_dev *vdev) |
490 | 528 | { |
491 | 529 | u64 a0, a1; |
drivers/net/enic/vnic_dev.h
... | ... | @@ -129,6 +129,8 @@ |
129 | 129 | int vnic_dev_deinit(struct vnic_dev *vdev); |
130 | 130 | int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); |
131 | 131 | int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); |
132 | +int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg); | |
133 | +int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done); | |
132 | 134 | void vnic_dev_set_intr_mode(struct vnic_dev *vdev, |
133 | 135 | enum vnic_dev_intr_mode intr_mode); |
134 | 136 | enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev); |
drivers/net/enic/vnic_devcmd.h
... | ... | @@ -212,6 +212,13 @@ |
212 | 212 | */ |
213 | 213 | CMD_IAR = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38), |
214 | 214 | |
215 | + /* initiate hangreset, like softreset after hang detected */ | |
216 | + CMD_HANG_RESET = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 39), | |
217 | + | |
218 | + /* hangreset status: | |
219 | + * out: a0=0 reset complete, a0=1 reset in progress */ | |
220 | + CMD_HANG_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 40), | |
221 | + | |
215 | 222 | /* |
216 | 223 | * Set hw ingress packet vlan rewrite mode: |
217 | 224 | * in: (u32)a0=new vlan rewrite mode |