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