diff options
author | Ron Mercer <ron.mercer@qlogic.com> | 2009-10-08 05:54:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-09 01:54:51 -0400 |
commit | 84087f4d482c5d554e1b26a557d424761213e5dc (patch) | |
tree | 8d7058d6008db2814e577caa779533482ee2b635 /drivers/net/qlge/qlge_mpi.c | |
parent | 76b26694cc9eb8c7ea1004b0601a5953cfa57b89 (diff) |
qlge: Fix chip reset process.
Add wait for NIC fifo and MGMNT fifo to empty before applying reset.
Otherwise broken frames can be processed by management processor and
cause it to hang.
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/qlge/qlge_mpi.c')
-rw-r--r-- | drivers/net/qlge/qlge_mpi.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index c2e43073047e..8810f5be7862 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c | |||
@@ -768,6 +768,95 @@ static int ql_idc_wait(struct ql_adapter *qdev) | |||
768 | return status; | 768 | return status; |
769 | } | 769 | } |
770 | 770 | ||
771 | int ql_mb_set_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 control) | ||
772 | { | ||
773 | struct mbox_params mbc; | ||
774 | struct mbox_params *mbcp = &mbc; | ||
775 | int status; | ||
776 | |||
777 | memset(mbcp, 0, sizeof(struct mbox_params)); | ||
778 | |||
779 | mbcp->in_count = 1; | ||
780 | mbcp->out_count = 2; | ||
781 | |||
782 | mbcp->mbox_in[0] = MB_CMD_SET_MGMNT_TFK_CTL; | ||
783 | mbcp->mbox_in[1] = control; | ||
784 | |||
785 | status = ql_mailbox_command(qdev, mbcp); | ||
786 | if (status) | ||
787 | return status; | ||
788 | |||
789 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) | ||
790 | return status; | ||
791 | |||
792 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | ||
793 | QPRINTK(qdev, DRV, ERR, | ||
794 | "Command not supported by firmware.\n"); | ||
795 | status = -EINVAL; | ||
796 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | ||
797 | /* This indicates that the firmware is | ||
798 | * already in the state we are trying to | ||
799 | * change it to. | ||
800 | */ | ||
801 | QPRINTK(qdev, DRV, ERR, | ||
802 | "Command parameters make no change.\n"); | ||
803 | } | ||
804 | return status; | ||
805 | } | ||
806 | |||
807 | /* Returns a negative error code or the mailbox command status. */ | ||
808 | static int ql_mb_get_mgmnt_traffic_ctl(struct ql_adapter *qdev, u32 *control) | ||
809 | { | ||
810 | struct mbox_params mbc; | ||
811 | struct mbox_params *mbcp = &mbc; | ||
812 | int status; | ||
813 | |||
814 | memset(mbcp, 0, sizeof(struct mbox_params)); | ||
815 | *control = 0; | ||
816 | |||
817 | mbcp->in_count = 1; | ||
818 | mbcp->out_count = 1; | ||
819 | |||
820 | mbcp->mbox_in[0] = MB_CMD_GET_MGMNT_TFK_CTL; | ||
821 | |||
822 | status = ql_mailbox_command(qdev, mbcp); | ||
823 | if (status) | ||
824 | return status; | ||
825 | |||
826 | if (mbcp->mbox_out[0] == MB_CMD_STS_GOOD) { | ||
827 | *control = mbcp->mbox_in[1]; | ||
828 | return status; | ||
829 | } | ||
830 | |||
831 | if (mbcp->mbox_out[0] == MB_CMD_STS_INVLD_CMD) { | ||
832 | QPRINTK(qdev, DRV, ERR, | ||
833 | "Command not supported by firmware.\n"); | ||
834 | status = -EINVAL; | ||
835 | } else if (mbcp->mbox_out[0] == MB_CMD_STS_ERR) { | ||
836 | QPRINTK(qdev, DRV, ERR, | ||
837 | "Failed to get MPI traffic control.\n"); | ||
838 | status = -EIO; | ||
839 | } | ||
840 | return status; | ||
841 | } | ||
842 | |||
843 | int ql_wait_fifo_empty(struct ql_adapter *qdev) | ||
844 | { | ||
845 | int count = 5; | ||
846 | u32 mgmnt_fifo_empty; | ||
847 | u32 nic_fifo_empty; | ||
848 | |||
849 | do { | ||
850 | nic_fifo_empty = ql_read32(qdev, STS) & STS_NFE; | ||
851 | ql_mb_get_mgmnt_traffic_ctl(qdev, &mgmnt_fifo_empty); | ||
852 | mgmnt_fifo_empty &= MB_GET_MPI_TFK_FIFO_EMPTY; | ||
853 | if (nic_fifo_empty && mgmnt_fifo_empty) | ||
854 | return 0; | ||
855 | msleep(100); | ||
856 | } while (count-- > 0); | ||
857 | return -ETIMEDOUT; | ||
858 | } | ||
859 | |||
771 | /* API called in work thread context to set new TX/RX | 860 | /* API called in work thread context to set new TX/RX |
772 | * maximum frame size values to match MTU. | 861 | * maximum frame size values to match MTU. |
773 | */ | 862 | */ |