1/*******************************************************************************
2
3
4  Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved.
5
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the Free
8  Software Foundation; either version 2 of the License, or (at your option)
9  any later version.
10
11  This program is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  more details.
15
16  You should have received a copy of the GNU General Public License along with
17  this program; if not, write to the Free Software Foundation, Inc., 59
18  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19
20  The full GNU General Public License is included in this distribution in the
21  file called LICENSE.
22
23  Contact Information:
24  Linux NICS <linux.nics@intel.com>
25  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26*******************************************************************************/
27
28#include "e100.h"
29#include "e100_config.h"
30
31extern u16 e100_eeprom_read(struct e100_private *, u16);
32extern int e100_wait_exec_cmplx(struct e100_private *, u32,u8);
33extern void e100_phy_reset(struct e100_private *bdp);
34extern void e100_phy_autoneg(struct e100_private *bdp);
35extern void e100_phy_set_loopback(struct e100_private *bdp);
36extern void e100_force_speed_duplex(struct e100_private *bdp);
37
38static u8 e100_diag_selftest(struct net_device *);
39static u8 e100_diag_eeprom(struct net_device *);
40static u8 e100_diag_loopback(struct net_device *);
41
42static u8 e100_diag_one_loopback (struct net_device *, u8);
43static u8 e100_diag_rcv_loopback_pkt(struct e100_private *);
44static void e100_diag_config_loopback(struct e100_private *, u8, u8, u8 *,u8 *);
45static u8 e100_diag_loopback_alloc(struct e100_private *);
46static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
47static u8 e100_diag_check_pkt(u8 *);
48static void e100_diag_loopback_free(struct e100_private *);
49
50#define LB_PACKET_SIZE 1500
51
52/**
53 * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines
54 * @dev: atapter's net device data struct
55 * @test_info: array with test request mask also used to store test results
56 *
57 * RETURNS: updated flags field of struct ethtool_test
58 */
59u32
60e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
61{
62	struct e100_private* bdp = dev->priv;
63	u8 test_result = true;
64
65	e100_isolate_driver(bdp);
66
67	if (flags & ETH_TEST_FL_OFFLINE) {
68		u8 fail_mask;
69
70		fail_mask = e100_diag_selftest(dev);
71		if (fail_mask) {
72			test_result = false;
73			if (fail_mask & REGISTER_TEST_FAIL)
74				test_info [E100_REG_TEST_FAIL] = true;
75			if (fail_mask & ROM_TEST_FAIL)
76				test_info [E100_ROM_TEST_FAIL] = true;
77			if (fail_mask & SELF_TEST_FAIL)
78				test_info [E100_MAC_TEST_FAIL] = true;
79			if (fail_mask & TEST_TIMEOUT)
80				test_info [E100_CHIP_TIMEOUT] = true;
81		}
82
83		fail_mask = e100_diag_loopback(dev);
84		if (fail_mask) {
85			test_result = false;
86			if (fail_mask & PHY_LOOPBACK)
87				test_info [E100_LPBK_PHY_FAIL] = true;
88			if (fail_mask & MAC_LOOPBACK)
89				test_info [E100_LPBK_MAC_FAIL] = true;
90		}
91	}
92
93	if (!e100_diag_eeprom(dev)) {
94		test_result = false;
95		test_info [E100_EEPROM_TEST_FAIL] = true;
96	}
97
98	/* fully recover only if the device is open*/
99	if (netif_running(dev))  {
100		e100_deisolate_driver(bdp, true, false);
101	} else {
102    		e100_deisolate_driver(bdp, false, false);
103	}
104	/*Let card recover from the test*/
105	set_current_state(TASK_UNINTERRUPTIBLE);
106	schedule_timeout(HZ * 2);
107
108	return flags | (test_result ? 0 : ETH_TEST_FL_FAILED);
109}
110
111/**
112 * e100_diag_selftest - run hardware selftest
113 * @dev: atapter's net device data struct
114 */
115static u8
116e100_diag_selftest(struct net_device *dev)
117{
118	struct e100_private *bdp = dev->priv;
119	u32 st_timeout, st_result;
120	u8 retval = 0;
121
122	if (!e100_selftest(bdp, &st_timeout, &st_result)) {
123		if (!st_timeout) {
124			if (st_result & CB_SELFTEST_REGISTER_BIT)
125				retval |= REGISTER_TEST_FAIL;
126			if (st_result & CB_SELFTEST_DIAG_BIT)
127				retval |= SELF_TEST_FAIL;
128			if (st_result & CB_SELFTEST_ROM_BIT)
129				retval |= ROM_TEST_FAIL;
130		} else {
131            		retval = TEST_TIMEOUT;
132		}
133	}
134
135	e100_hw_reset_recover(bdp,PORT_SOFTWARE_RESET);
136
137	return retval;
138}
139
140/**
141 * e100_diag_eeprom - validate eeprom checksum correctness
142 * @dev: atapter's net device data struct
143 *
144 */
145static u8
146e100_diag_eeprom (struct net_device *dev)
147{
148	struct e100_private *bdp = dev->priv;
149	u16 i, eeprom_sum, eeprom_actual_csm;
150
151	for (i = 0, eeprom_sum = 0; i < (bdp->eeprom_size - 1); i++) {
152		eeprom_sum += e100_eeprom_read(bdp, i);
153	}
154
155	eeprom_actual_csm = e100_eeprom_read(bdp, bdp->eeprom_size - 1);
156
157	if (eeprom_actual_csm == (u16)(EEPROM_SUM - eeprom_sum)) {
158		return true;
159	}
160
161	return false;
162}
163
164/**
165 * e100_diag_loopback - performs loopback test
166 * @dev: atapter's net device data struct
167 */
168static u8
169e100_diag_loopback (struct net_device *dev)
170{
171	u8 rc = 0;
172
173	if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
174		rc |= PHY_LOOPBACK;
175	}
176
177	if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
178		rc |= MAC_LOOPBACK;
179	}
180
181	return rc;
182}
183
184/**
185 * e100_diag_loopback - performs loopback test
186 * @dev: atapter's net device data struct
187 * @mode: lopback test type
188 */
189static u8
190e100_diag_one_loopback (struct net_device *dev, u8 mode)
191{
192        struct e100_private *bdp = dev->priv;
193        u8 res = false;
194   	u8 saved_dynamic_tbd = false;
195   	u8 saved_extended_tcb = false;
196
197	if (!e100_diag_loopback_alloc(bdp))
198		return false;
199
200	/* change the config block to standard tcb and the correct loopback */
201        e100_diag_config_loopback(bdp, true, mode,
202				  &saved_extended_tcb, &saved_dynamic_tbd);
203
204	e100_diag_loopback_cu_ru_exec(bdp);
205
206        if (e100_diag_rcv_loopback_pkt(bdp)) {
207		res = true;
208	}
209
210        e100_diag_loopback_free(bdp);
211
212        /* change the config block to previous tcb mode and the no loopback */
213        e100_diag_config_loopback(bdp, false, mode,
214				  &saved_extended_tcb, &saved_dynamic_tbd);
215	return res;
216}
217
218/**
219 * e100_diag_config_loopback - setup/clear loopback before/after lpbk test
220 * @bdp: atapter's private data struct
221 * @set_loopback: true if the function is called to set lb
222 * @loopback_mode: the loopback mode(MAC or PHY)
223 * @tcb_extended: true if need to set extended tcb mode after clean loopback
224 * @dynamic_tbd: true if needed to set dynamic tbd mode after clean loopback
225 *
226 */
227void
228e100_diag_config_loopback(struct e100_private* bdp,
229			  u8 set_loopback,
230			  u8 loopback_mode,
231			  u8* tcb_extended,
232			  u8* dynamic_tbd)
233{
234	/* if set_loopback == true - we want to clear tcb_extended/dynamic_tbd.
235	 * the previous values are saved in the params tcb_extended/dynamic_tbd
236	 * if set_loopback == false - we want to restore previous value.
237	 */
238	if (set_loopback || (*tcb_extended))
239		  *tcb_extended = e100_config_tcb_ext_enable(bdp,*tcb_extended);
240
241	if (set_loopback || (*dynamic_tbd))
242		 *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd);
243
244	if (set_loopback) {
245		/* Configure loopback on MAC */
246		e100_config_loopback_mode(bdp,loopback_mode);
247	} else {
248		e100_config_loopback_mode(bdp,NO_LOOPBACK);
249	}
250
251	e100_config(bdp);
252
253	if (loopback_mode == PHY_LOOPBACK) {
254		if (set_loopback)
255                        /* Set PHY loopback mode */
256                        e100_phy_set_loopback(bdp);
257                else {	/* Back to normal speed and duplex */
258                	if (bdp->params.e100_speed_duplex == E100_AUTONEG)
259				/* Reset PHY and do autoneg */
260                        	e100_phy_autoneg(bdp);
261			else
262				/* Reset PHY and force speed and duplex */
263				e100_force_speed_duplex(bdp);
264		}
265                /* Wait for PHY state change */
266		set_current_state(TASK_UNINTERRUPTIBLE);
267                schedule_timeout(HZ);
268	} else { /* For MAC loopback wait 500 msec to take effect */
269		set_current_state(TASK_UNINTERRUPTIBLE);
270		schedule_timeout(HZ / 2);
271	}
272}
273
274/**
275 * e100_diag_loopback_alloc - alloc & initate tcb and rfd for the loopback
276 * @bdp: atapter's private data struct
277 *
278 */
279static u8
280e100_diag_loopback_alloc(struct e100_private *bdp)
281{
282	dma_addr_t dma_handle;
283	tcb_t *tcb;
284	rfd_t *rfd;
285	tbd_t *tbd;
286
287	/* tcb, tbd and transmit buffer are allocated */
288	tcb = pci_alloc_consistent(bdp->pdev,
289				   (sizeof (tcb_t) + sizeof (tbd_t) +
290				    LB_PACKET_SIZE),
291				   &dma_handle);
292        if (tcb == NULL)
293		return false;
294
295	memset(tcb, 0x00, sizeof (tcb_t) + sizeof (tbd_t) + LB_PACKET_SIZE);
296	tcb->tcb_phys = dma_handle;
297	tcb->tcb_hdr.cb_status = 0;
298	tcb->tcb_hdr.cb_cmd =
299		cpu_to_le16(CB_EL_BIT | CB_TRANSMIT | CB_TX_SF_BIT);
300	/* Next command is null */
301	tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(0xffffffff);
302	tcb->tcb_cnt = 0;
303	tcb->tcb_thrshld = bdp->tx_thld;
304	tcb->tcb_tbd_num = 1;
305	/* Set up tcb tbd pointer */
306	tcb->tcb_tbd_ptr = cpu_to_le32(tcb->tcb_phys + sizeof (tcb_t));
307	tbd = (tbd_t *) ((u8 *) tcb + sizeof (tcb_t));
308	/* Set up tbd transmit buffer */
309	tbd->tbd_buf_addr =
310		cpu_to_le32(le32_to_cpu(tcb->tcb_tbd_ptr) + sizeof (tbd_t));
311	tbd->tbd_buf_cnt = __constant_cpu_to_le16(1024);
312	/* The value of first 512 bytes is FF */
313	memset((void *) ((u8 *) tbd + sizeof (tbd_t)), 0xFF, 512);
314	/* The value of second 512 bytes is BA */
315	memset((void *) ((u8 *) tbd + sizeof (tbd_t) + 512), 0xBA, 512);
316	wmb();
317	rfd = pci_alloc_consistent(bdp->pdev, sizeof (rfd_t), &dma_handle);
318
319	if (rfd == NULL) {
320		pci_free_consistent(bdp->pdev,
321				    sizeof (tcb_t) + sizeof (tbd_t) +
322				    LB_PACKET_SIZE, tcb, tcb->tcb_phys);
323		return false;
324	}
325
326	memset(rfd, 0x00, sizeof (rfd_t));
327
328	/* init all fields in rfd */
329	rfd->rfd_header.cb_cmd = cpu_to_le16(RFD_EL_BIT);
330	rfd->rfd_sz = cpu_to_le16(ETH_FRAME_LEN + CHKSUM_SIZE);
331	/* dma_handle is physical address of rfd */
332	bdp->loopback.dma_handle = dma_handle;
333	bdp->loopback.tcb = tcb;
334	bdp->loopback.rfd = rfd;
335	wmb();
336	return true;
337}
338
339/**
340 * e100_diag_loopback_cu_ru_exec - activates cu and ru to send & receive the pkt
341 * @bdp: atapter's private data struct
342 *
343 */
344static void
345e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
346{
347	/*load CU & RU base */
348	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE))
349		printk("e100: SCB_CUC_LOAD_BASE failed\n");
350	if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE))
351		printk("e100: SCB_RUC_LOAD_BASE failed!\n");
352	if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START))
353		printk("e100: SCB_RUC_START failed!\n");
354
355	bdp->next_cu_cmd = START_WAIT;
356	e100_start_cu(bdp, bdp->loopback.tcb);
357	bdp->last_tcb = NULL;
358	rmb();
359}
360/**
361 * e100_diag_check_pkt - checks if a given packet is a loopback packet
362 * @bdp: atapter's private data struct
363 *
364 * Returns true if OK false otherwise.
365 */
366static u8
367e100_diag_check_pkt(u8 *datap)
368{
369	int i;
370	for (i = 0; i<512; i++) {
371		if( !((*datap)==0xFF && (*(datap + 512) == 0xBA)) ) {
372			printk (KERN_ERR "e100: check loopback packet failed at: %x\n", i);
373			return false;
374			}
375	}
376	printk (KERN_DEBUG "e100: Check received loopback packet OK\n");
377	return true;
378}
379
380/**
381 * e100_diag_rcv_loopback_pkt - waits for receive and checks lpbk packet
382 * @bdp: atapter's private data struct
383 *
384 * Returns true if OK false otherwise.
385 */
386static u8
387e100_diag_rcv_loopback_pkt(struct e100_private* bdp)
388{
389	rfd_t *rfdp;
390	u16 rfd_status;
391	unsigned long expires = jiffies + HZ * 2;
392
393        rfdp =bdp->loopback.rfd;
394
395        rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
396
397        while (!(rfd_status & RFD_STATUS_COMPLETE)) {
398		if (time_before(jiffies, expires)) {
399			yield();
400			rmb();
401			rfd_status = le16_to_cpu(rfdp->rfd_header.cb_status);
402		} else {
403			break;
404		}
405        }
406
407        if (rfd_status & RFD_STATUS_COMPLETE) {
408		printk(KERN_DEBUG "e100: Loopback packet received\n");
409                return e100_diag_check_pkt(((u8 *)rfdp+bdp->rfd_size));
410	}
411	else {
412		printk(KERN_ERR "e100: Loopback packet not received\n");
413		return false;
414	}
415}
416
417/**
418 * e100_diag_loopback_free - free data allocated for loopback pkt send/receive
419 * @bdp: atapter's private data struct
420 *
421 */
422static void
423e100_diag_loopback_free (struct e100_private *bdp)
424{
425        pci_free_consistent(bdp->pdev,
426			    sizeof(tcb_t) + sizeof(tbd_t) + LB_PACKET_SIZE,
427			    bdp->loopback.tcb, bdp->loopback.tcb->tcb_phys);
428
429        pci_free_consistent(bdp->pdev, sizeof(rfd_t), bdp->loopback.rfd,
430			    bdp->loopback.dma_handle);
431}
432
433