Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[deliverable/linux.git] / drivers / net / qlge / qlge_mpi.c
1 #include "qlge.h"
2
3 int ql_read_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
4 {
5 int status;
6 /* wait for reg to come ready */
7 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
8 if (status)
9 goto exit;
10 /* set up for reg read */
11 ql_write32(qdev, PROC_ADDR, reg | PROC_ADDR_R);
12 /* wait for reg to come ready */
13 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
14 if (status)
15 goto exit;
16 /* get the data */
17 *data = ql_read32(qdev, PROC_DATA);
18 exit:
19 return status;
20 }
21
22 int ql_write_mpi_reg(struct ql_adapter *qdev, u32 reg, u32 data)
23 {
24 int status = 0;
25 /* wait for reg to come ready */
26 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
27 if (status)
28 goto exit;
29 /* write the data to the data reg */
30 ql_write32(qdev, PROC_DATA, data);
31 /* trigger the write */
32 ql_write32(qdev, PROC_ADDR, reg);
33 /* wait for reg to come ready */
34 status = ql_wait_reg_rdy(qdev, PROC_ADDR, PROC_ADDR_RDY, PROC_ADDR_ERR);
35 if (status)
36 goto exit;
37 exit:
38 return status;
39 }
40
41 int ql_soft_reset_mpi_risc(struct ql_adapter *qdev)
42 {
43 int status;
44 status = ql_write_mpi_reg(qdev, 0x00001010, 1);
45 return status;
46 }
47
48 static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp)
49 {
50 int i, status;
51
52 status = ql_sem_spinlock(qdev, SEM_PROC_REG_MASK);
53 if (status)
54 return -EBUSY;
55 for (i = 0; i < mbcp->out_count; i++) {
56 status =
57 ql_read_mpi_reg(qdev, qdev->mailbox_out + i,
58 &mbcp->mbox_out[i]);
59 if (status) {
60 QPRINTK(qdev, DRV, ERR, "Failed mailbox read.\n");
61 break;
62 }
63 }
64 ql_sem_unlock(qdev, SEM_PROC_REG_MASK); /* does flush too */
65 return status;
66 }
67
68 static void ql_link_up(struct ql_adapter *qdev, struct mbox_params *mbcp)
69 {
70 mbcp->out_count = 2;
71
72 if (ql_get_mb_sts(qdev, mbcp))
73 goto exit;
74
75 qdev->link_status = mbcp->mbox_out[1];
76 QPRINTK(qdev, DRV, ERR, "Link Up.\n");
77 QPRINTK(qdev, DRV, INFO, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]);
78 if (!netif_carrier_ok(qdev->ndev)) {
79 QPRINTK(qdev, LINK, INFO, "Link is Up.\n");
80 netif_carrier_on(qdev->ndev);
81 netif_wake_queue(qdev->ndev);
82 }
83 exit:
84 /* Clear the MPI firmware status. */
85 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
86 }
87
88 static void ql_link_down(struct ql_adapter *qdev, struct mbox_params *mbcp)
89 {
90 mbcp->out_count = 3;
91
92 if (ql_get_mb_sts(qdev, mbcp)) {
93 QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n");
94 goto exit;
95 }
96
97 if (netif_carrier_ok(qdev->ndev)) {
98 QPRINTK(qdev, LINK, INFO, "Link is Down.\n");
99 netif_carrier_off(qdev->ndev);
100 netif_stop_queue(qdev->ndev);
101 }
102 QPRINTK(qdev, DRV, ERR, "Link Down.\n");
103 QPRINTK(qdev, DRV, ERR, "Link Status = 0x%.08x.\n", mbcp->mbox_out[1]);
104 exit:
105 /* Clear the MPI firmware status. */
106 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
107 }
108
109 static void ql_init_fw_done(struct ql_adapter *qdev, struct mbox_params *mbcp)
110 {
111 mbcp->out_count = 2;
112
113 if (ql_get_mb_sts(qdev, mbcp)) {
114 QPRINTK(qdev, DRV, ERR, "Firmware did not initialize!\n");
115 goto exit;
116 }
117 QPRINTK(qdev, DRV, ERR, "Firmware initialized!\n");
118 QPRINTK(qdev, DRV, ERR, "Firmware status = 0x%.08x.\n",
119 mbcp->mbox_out[0]);
120 QPRINTK(qdev, DRV, ERR, "Firmware Revision = 0x%.08x.\n",
121 mbcp->mbox_out[1]);
122 exit:
123 /* Clear the MPI firmware status. */
124 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
125 }
126
127 /* Process an async event and clear it unless it's an
128 * error condition.
129 * This can get called iteratively from the mpi_work thread
130 * when events arrive via an interrupt.
131 * It also gets called when a mailbox command is polling for
132 * it's completion. */
133 static int ql_mpi_handler(struct ql_adapter *qdev, struct mbox_params *mbcp)
134 {
135 int status;
136
137 /* Just get mailbox zero for now. */
138 mbcp->out_count = 1;
139 status = ql_get_mb_sts(qdev, mbcp);
140 if (status) {
141 QPRINTK(qdev, DRV, ERR,
142 "Could not read MPI, resetting ASIC!\n");
143 ql_queue_asic_error(qdev);
144 goto end;
145 }
146
147 switch (mbcp->mbox_out[0]) {
148
149 case AEN_LINK_UP:
150 ql_link_up(qdev, mbcp);
151 break;
152
153 case AEN_LINK_DOWN:
154 ql_link_down(qdev, mbcp);
155 break;
156
157 case AEN_FW_INIT_DONE:
158 ql_init_fw_done(qdev, mbcp);
159 break;
160
161 case MB_CMD_STS_GOOD:
162 break;
163
164 case AEN_FW_INIT_FAIL:
165 case AEN_SYS_ERR:
166 case MB_CMD_STS_ERR:
167 ql_queue_fw_error(qdev);
168 break;
169
170 default:
171 QPRINTK(qdev, DRV, ERR,
172 "Unsupported AE %.08x.\n", mbcp->mbox_out[0]);
173 /* Clear the MPI firmware status. */
174 }
175 end:
176 ql_write32(qdev, CSR, CSR_CMD_CLR_R2PCI_INT);
177 return status;
178 }
179
180 void ql_mpi_work(struct work_struct *work)
181 {
182 struct ql_adapter *qdev =
183 container_of(work, struct ql_adapter, mpi_work.work);
184 struct mbox_params mbc;
185 struct mbox_params *mbcp = &mbc;
186
187 mutex_lock(&qdev->mpi_mutex);
188
189 while (ql_read32(qdev, STS) & STS_PI) {
190 memset(mbcp, 0, sizeof(struct mbox_params));
191 mbcp->out_count = 1;
192 ql_mpi_handler(qdev, mbcp);
193 }
194
195 mutex_unlock(&qdev->mpi_mutex);
196 ql_enable_completion_interrupt(qdev, 0);
197 }
198
199 void ql_mpi_reset_work(struct work_struct *work)
200 {
201 struct ql_adapter *qdev =
202 container_of(work, struct ql_adapter, mpi_reset_work.work);
203 ql_soft_reset_mpi_risc(qdev);
204 }
This page took 0.044392 seconds and 6 git commands to generate.