diff options
author | Vasanthy Kolluri <vkolluri@cisco.com> | 2010-06-24 06:50:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-25 23:46:01 -0400 |
commit | 99ef563901a18d44a6c2eadd2b958e2e83aeca51 (patch) | |
tree | 29bbf0fe2457effbaa62281eca6aff2191cc9f75 | |
parent | f8cac14acff870203ea7f61f1a92c5486d1774fa (diff) |
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>
-rw-r--r-- | drivers/net/enic/enic_main.c | 16 | ||||
-rw-r--r-- | drivers/net/enic/vnic_dev.c | 38 | ||||
-rw-r--r-- | drivers/net/enic/vnic_dev.h | 2 | ||||
-rw-r--r-- | drivers/net/enic/vnic_devcmd.h | 7 |
4 files changed, 55 insertions, 8 deletions
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 7f98af1eb1ea..d7434b7b4c52 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -812,9 +812,10 @@ static struct net_device_stats *enic_get_stats(struct net_device *netdev) | |||
812 | return net_stats; | 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 | enic->mc_count = 0; | 817 | enic->mc_count = 0; |
818 | enic->flags = 0; | ||
818 | } | 819 | } |
819 | 820 | ||
820 | static int enic_set_mac_addr(struct net_device *netdev, char *addr) | 821 | static int enic_set_mac_addr(struct net_device *netdev, char *addr) |
@@ -1847,15 +1848,15 @@ static int enic_dev_open(struct enic *enic) | |||
1847 | return err; | 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 | int err; | 1853 | int err; |
1853 | 1854 | ||
1854 | err = enic_dev_wait(enic->vdev, vnic_dev_soft_reset, | 1855 | err = enic_dev_wait(enic->vdev, vnic_dev_hang_reset, |
1855 | vnic_dev_soft_reset_done, 0); | 1856 | vnic_dev_hang_reset_done, 0); |
1856 | if (err) | 1857 | if (err) |
1857 | printk(KERN_ERR PFX | 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 | return err; | 1861 | return err; |
1861 | } | 1862 | } |
@@ -1906,9 +1907,8 @@ static void enic_reset(struct work_struct *work) | |||
1906 | spin_unlock(&enic->devcmd_lock); | 1907 | spin_unlock(&enic->devcmd_lock); |
1907 | 1908 | ||
1908 | enic_stop(enic->netdev); | 1909 | enic_stop(enic->netdev); |
1909 | enic_dev_soft_reset(enic); | 1910 | enic_dev_hang_reset(enic); |
1910 | vnic_dev_init(enic->vdev, 0); | 1911 | enic_reset_multicast_list(enic); |
1911 | enic_reset_mcaddrs(enic); | ||
1912 | enic_init_vnic_resources(enic); | 1912 | enic_init_vnic_resources(enic); |
1913 | enic_set_niccfg(enic); | 1913 | enic_set_niccfg(enic); |
1914 | enic_dev_set_ig_vlan_rewrite_mode(enic); | 1914 | enic_dev_set_ig_vlan_rewrite_mode(enic); |
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index e3742faa06fe..c93012f2faa9 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c | |||
@@ -486,6 +486,44 @@ int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done) | |||
486 | return 0; | 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 | int vnic_dev_hang_notify(struct vnic_dev *vdev) | 527 | int vnic_dev_hang_notify(struct vnic_dev *vdev) |
490 | { | 528 | { |
491 | u64 a0, a1; | 529 | u64 a0, a1; |
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h index 780c3cd73292..4980615fcee2 100644 --- a/drivers/net/enic/vnic_dev.h +++ b/drivers/net/enic/vnic_dev.h | |||
@@ -129,6 +129,8 @@ int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len); | |||
129 | int vnic_dev_deinit(struct vnic_dev *vdev); | 129 | int vnic_dev_deinit(struct vnic_dev *vdev); |
130 | int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); | 130 | int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); |
131 | int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); | 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 | void vnic_dev_set_intr_mode(struct vnic_dev *vdev, | 134 | void vnic_dev_set_intr_mode(struct vnic_dev *vdev, |
133 | enum vnic_dev_intr_mode intr_mode); | 135 | enum vnic_dev_intr_mode intr_mode); |
134 | enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev); | 136 | enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev); |
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h index c5ff4ff2ed26..1c4fb35671fa 100644 --- a/drivers/net/enic/vnic_devcmd.h +++ b/drivers/net/enic/vnic_devcmd.h | |||
@@ -212,6 +212,13 @@ enum vnic_devcmd_cmd { | |||
212 | */ | 212 | */ |
213 | CMD_IAR = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38), | 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 | * Set hw ingress packet vlan rewrite mode: | 223 | * Set hw ingress packet vlan rewrite mode: |
217 | * in: (u32)a0=new vlan rewrite mode | 224 | * in: (u32)a0=new vlan rewrite mode |