Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9 685 lines 23 kB view raw
1/* 2 * *************************************************************************** 3 * FILE: putest.c 4 * 5 * PURPOSE: putest related functions. 6 * 7 * Copyright (C) 2008-2009 by Cambridge Silicon Radio Ltd. 8 * 9 * Refer to LICENSE.txt included with this source code for details on 10 * the license terms. 11 * 12 * *************************************************************************** 13 */ 14 15#include <linux/vmalloc.h> 16#include <linux/firmware.h> 17 18#include "unifi_priv.h" 19#include "csr_wifi_hip_chiphelper.h" 20 21#define UNIFI_PROC_BOTH 3 22 23 24int unifi_putest_cmd52_read(unifi_priv_t *priv, unsigned char *arg) 25{ 26 struct unifi_putest_cmd52 cmd52_params; 27 u8 *arg_pos; 28 unsigned int cmd_param_size; 29 int r; 30 CsrResult csrResult; 31 unsigned char ret_buffer[32]; 32 u8 *ret_buffer_pos; 33 u8 retries; 34 35 arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); 36 if (get_user(cmd_param_size, (int*)arg_pos)) { 37 unifi_error(priv, 38 "unifi_putest_cmd52_read: Failed to get the argument\n"); 39 return -EFAULT; 40 } 41 42 if (cmd_param_size != sizeof(struct unifi_putest_cmd52)) { 43 unifi_error(priv, 44 "unifi_putest_cmd52_read: cmd52 struct mismatch\n"); 45 return -EINVAL; 46 } 47 48 arg_pos += sizeof(unsigned int); 49 if (copy_from_user(&cmd52_params, 50 (void*)arg_pos, 51 sizeof(struct unifi_putest_cmd52))) { 52 unifi_error(priv, 53 "unifi_putest_cmd52_read: Failed to get the cmd52 params\n"); 54 return -EFAULT; 55 } 56 57 unifi_trace(priv, UDBG2, "cmd52r: func=%d addr=0x%x ", 58 cmd52_params.funcnum, cmd52_params.addr); 59 60 retries = 3; 61 CsrSdioClaim(priv->sdio); 62 do { 63 if (cmd52_params.funcnum == 0) { 64 csrResult = CsrSdioF0Read8(priv->sdio, cmd52_params.addr, &cmd52_params.data); 65 } else { 66 csrResult = CsrSdioRead8(priv->sdio, cmd52_params.addr, &cmd52_params.data); 67 } 68 } while (--retries && ((csrResult == CSR_SDIO_RESULT_CRC_ERROR) || (csrResult == CSR_SDIO_RESULT_TIMEOUT))); 69 CsrSdioRelease(priv->sdio); 70 71 if (csrResult != CSR_RESULT_SUCCESS) { 72 unifi_error(priv, 73 "\nunifi_putest_cmd52_read: Read8() failed (csrResult=0x%x)\n", csrResult); 74 return -EFAULT; 75 } 76 unifi_trace(priv, UDBG2, "data=%d\n", cmd52_params.data); 77 78 /* Copy the info to the out buffer */ 79 *(unifi_putest_command_t*)ret_buffer = UNIFI_PUTEST_CMD52_READ; 80 ret_buffer_pos = (u8*)(((unifi_putest_command_t*)ret_buffer) + 1); 81 *(unsigned int*)ret_buffer_pos = sizeof(struct unifi_putest_cmd52); 82 ret_buffer_pos += sizeof(unsigned int); 83 memcpy(ret_buffer_pos, &cmd52_params, sizeof(struct unifi_putest_cmd52)); 84 ret_buffer_pos += sizeof(struct unifi_putest_cmd52); 85 86 r = copy_to_user((void*)arg, 87 ret_buffer, 88 ret_buffer_pos - ret_buffer); 89 if (r) { 90 unifi_error(priv, 91 "unifi_putest_cmd52_read: Failed to return the data\n"); 92 return -EFAULT; 93 } 94 95 return 0; 96} 97 98 99int unifi_putest_cmd52_write(unifi_priv_t *priv, unsigned char *arg) 100{ 101 struct unifi_putest_cmd52 cmd52_params; 102 u8 *arg_pos; 103 unsigned int cmd_param_size; 104 CsrResult csrResult; 105 u8 retries; 106 107 arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); 108 if (get_user(cmd_param_size, (int*)arg_pos)) { 109 unifi_error(priv, 110 "unifi_putest_cmd52_write: Failed to get the argument\n"); 111 return -EFAULT; 112 } 113 114 if (cmd_param_size != sizeof(struct unifi_putest_cmd52)) { 115 unifi_error(priv, 116 "unifi_putest_cmd52_write: cmd52 struct mismatch\n"); 117 return -EINVAL; 118 } 119 120 arg_pos += sizeof(unsigned int); 121 if (copy_from_user(&cmd52_params, 122 (void*)(arg_pos), 123 sizeof(struct unifi_putest_cmd52))) { 124 unifi_error(priv, 125 "unifi_putest_cmd52_write: Failed to get the cmd52 params\n"); 126 return -EFAULT; 127 } 128 129 unifi_trace(priv, UDBG2, "cmd52w: func=%d addr=0x%x data=%d\n", 130 cmd52_params.funcnum, cmd52_params.addr, cmd52_params.data); 131 132 retries = 3; 133 CsrSdioClaim(priv->sdio); 134 do { 135 if (cmd52_params.funcnum == 0) { 136 csrResult = CsrSdioF0Write8(priv->sdio, cmd52_params.addr, cmd52_params.data); 137 } else { 138 csrResult = CsrSdioWrite8(priv->sdio, cmd52_params.addr, cmd52_params.data); 139 } 140 } while (--retries && ((csrResult == CSR_SDIO_RESULT_CRC_ERROR) || (csrResult == CSR_SDIO_RESULT_TIMEOUT))); 141 CsrSdioRelease(priv->sdio); 142 143 if (csrResult != CSR_RESULT_SUCCESS) { 144 unifi_error(priv, 145 "unifi_putest_cmd52_write: Write8() failed (csrResult=0x%x)\n", csrResult); 146 return -EFAULT; 147 } 148 149 return 0; 150} 151 152int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg) 153{ 154 struct unifi_putest_gp_rw16 gp_r16_params; 155 u8 *arg_pos; 156 unsigned int cmd_param_size; 157 int r; 158 CsrResult csrResult; 159 unsigned char ret_buffer[32]; 160 u8 *ret_buffer_pos; 161 162 arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); 163 if (get_user(cmd_param_size, (int*)arg_pos)) { 164 unifi_error(priv, 165 "unifi_putest_gp_read16: Failed to get the argument\n"); 166 return -EFAULT; 167 } 168 169 if (cmd_param_size != sizeof(struct unifi_putest_gp_rw16)) { 170 unifi_error(priv, 171 "unifi_putest_gp_read16: struct mismatch\n"); 172 return -EINVAL; 173 } 174 175 arg_pos += sizeof(unsigned int); 176 if (copy_from_user(&gp_r16_params, 177 (void*)arg_pos, 178 sizeof(struct unifi_putest_gp_rw16))) { 179 unifi_error(priv, 180 "unifi_putest_gp_read16: Failed to get the params\n"); 181 return -EFAULT; 182 } 183 CsrSdioClaim(priv->sdio); 184 csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data); 185 CsrSdioRelease(priv->sdio); 186 if (csrResult != CSR_RESULT_SUCCESS) { 187 unifi_error(priv, 188 "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params.addr, csrResult); 189 return -EFAULT; 190 } 191 192 unifi_trace(priv, UDBG2, "gp_r16: GP=0x%08x, data=0x%04x\n", gp_r16_params.addr, gp_r16_params.data); 193 194 /* Copy the info to the out buffer */ 195 *(unifi_putest_command_t*)ret_buffer = UNIFI_PUTEST_GP_READ16; 196 ret_buffer_pos = (u8*)(((unifi_putest_command_t*)ret_buffer) + 1); 197 *(unsigned int*)ret_buffer_pos = sizeof(struct unifi_putest_gp_rw16); 198 ret_buffer_pos += sizeof(unsigned int); 199 memcpy(ret_buffer_pos, &gp_r16_params, sizeof(struct unifi_putest_gp_rw16)); 200 ret_buffer_pos += sizeof(struct unifi_putest_gp_rw16); 201 202 r = copy_to_user((void*)arg, 203 ret_buffer, 204 ret_buffer_pos - ret_buffer); 205 if (r) { 206 unifi_error(priv, 207 "unifi_putest_gp_read16: Failed to return the data\n"); 208 return -EFAULT; 209 } 210 211 return 0; 212} 213 214int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg) 215{ 216 struct unifi_putest_gp_rw16 gp_w16_params; 217 u8 *arg_pos; 218 unsigned int cmd_param_size; 219 CsrResult csrResult; 220 221 arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); 222 if (get_user(cmd_param_size, (int*)arg_pos)) { 223 unifi_error(priv, 224 "unifi_putest_gp_write16: Failed to get the argument\n"); 225 return -EFAULT; 226 } 227 228 if (cmd_param_size != sizeof(struct unifi_putest_gp_rw16)) { 229 unifi_error(priv, 230 "unifi_putest_gp_write16: struct mismatch\n"); 231 return -EINVAL; 232 } 233 234 arg_pos += sizeof(unsigned int); 235 if (copy_from_user(&gp_w16_params, 236 (void*)(arg_pos), 237 sizeof(struct unifi_putest_gp_rw16))) { 238 unifi_error(priv, 239 "unifi_putest_gp_write16: Failed to get the params\n"); 240 return -EFAULT; 241 } 242 243 unifi_trace(priv, UDBG2, "gp_w16: GP=0x%08x, data=0x%04x\n", gp_w16_params.addr, gp_w16_params.data); 244 CsrSdioClaim(priv->sdio); 245 csrResult = unifi_card_write16(priv->card, gp_w16_params.addr, gp_w16_params.data); 246 CsrSdioRelease(priv->sdio); 247 if (csrResult != CSR_RESULT_SUCCESS) { 248 unifi_error(priv, 249 "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params.addr, csrResult); 250 return -EFAULT; 251 } 252 253 return 0; 254} 255 256int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg) 257{ 258 int sdio_clock_speed; 259 CsrResult csrResult; 260 261 if (get_user(sdio_clock_speed, (int*)(((unifi_putest_command_t*)arg) + 1))) { 262 unifi_error(priv, 263 "unifi_putest_set_sdio_clock: Failed to get the argument\n"); 264 return -EFAULT; 265 } 266 267 unifi_trace(priv, UDBG2, "set sdio clock: %d KHz\n", sdio_clock_speed); 268 269 CsrSdioClaim(priv->sdio); 270 csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed * 1000); 271 CsrSdioRelease(priv->sdio); 272 if (csrResult != CSR_RESULT_SUCCESS) { 273 unifi_error(priv, 274 "unifi_putest_set_sdio_clock: Set clock failed (csrResult=0x%x)\n", csrResult); 275 return -EFAULT; 276 } 277 278 return 0; 279} 280 281 282int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg) 283{ 284 int r; 285 CsrResult csrResult; 286 int already_in_test = priv->ptest_mode; 287 288 /* Ensure that sme_sys_suspend() doesn't power down the chip because: 289 * 1) Power is needed anyway for ptest. 290 * 2) The app code uses the START ioctl as a reset, so it gets called 291 * multiple times. If the app stops the XAPs, but the power_down/up 292 * sequence doesn't actually power down the chip, there can be problems 293 * resetting, because part of the power_up sequence disables function 1 294 */ 295 priv->ptest_mode = 1; 296 297 /* Suspend the SME and UniFi */ 298 if (priv->sme_cli) { 299 r = sme_sys_suspend(priv); 300 if (r) { 301 unifi_error(priv, 302 "unifi_putest_start: failed to suspend UniFi\n"); 303 return r; 304 } 305 } 306 307 /* Application may have stopped the XAPs, but they are needed for reset */ 308 if (already_in_test) { 309 CsrSdioClaim(priv->sdio); 310 csrResult = unifi_start_processors(priv->card); 311 CsrSdioRelease(priv->sdio); 312 if (csrResult != CSR_RESULT_SUCCESS) { 313 unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); 314 } 315 } else { 316 /* Ensure chip is powered for the case where there's no unifi_helper */ 317 CsrSdioClaim(priv->sdio); 318 csrResult = CsrSdioPowerOn(priv->sdio); 319 CsrSdioRelease(priv->sdio); 320 if (csrResult != CSR_RESULT_SUCCESS) { 321 unifi_error(priv, "CsrSdioPowerOn csrResult = %d\n", csrResult); 322 } 323 } 324 CsrSdioClaim(priv->sdio); 325 csrResult = unifi_init(priv->card); 326 CsrSdioRelease(priv->sdio); 327 if (csrResult != CSR_RESULT_SUCCESS) { 328 unifi_error(priv, 329 "unifi_putest_start: failed to init UniFi\n"); 330 return CsrHipResultToStatus(csrResult); 331 } 332 333 return 0; 334} 335 336 337int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg) 338{ 339 int r = 0; 340 CsrResult csrResult; 341 342 /* Application may have stopped the XAPs, but they are needed for reset */ 343 CsrSdioClaim(priv->sdio); 344 csrResult = unifi_start_processors(priv->card); 345 CsrSdioRelease(priv->sdio); 346 if (csrResult != CSR_RESULT_SUCCESS) { 347 unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); 348 } 349 350 /* PUTEST_STOP is also used to resume the XAPs after SME coredump. 351 * Don't power off the chip, leave that to the normal wifi-off which is 352 * about to carry on. No need to resume the SME either, as it wasn't suspended. 353 */ 354 if (priv->coredump_mode) { 355 priv->coredump_mode = 0; 356 return 0; 357 } 358 359 /* At this point function 1 is enabled and the XAPs are running, so it is 360 * safe to let the card power down. Power is restored later, asynchronously, 361 * during the wifi_on requested by the SME. 362 */ 363 CsrSdioClaim(priv->sdio); 364 CsrSdioPowerOff(priv->sdio); 365 CsrSdioRelease(priv->sdio); 366 367 /* Resume the SME and UniFi */ 368 if (priv->sme_cli) { 369 r = sme_sys_resume(priv); 370 if (r) { 371 unifi_error(priv, 372 "unifi_putest_stop: failed to resume SME\n"); 373 } 374 } 375 priv->ptest_mode = 0; 376 377 return r; 378} 379 380 381int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg) 382{ 383#define UF_PUTEST_MAX_FW_FILE_NAME 16 384#define UNIFI_MAX_FW_PATH_LEN 32 385 unsigned int fw_name_length; 386 unsigned char fw_name[UF_PUTEST_MAX_FW_FILE_NAME+1]; 387 unsigned char *name_buffer; 388 int postfix; 389 char fw_path[UNIFI_MAX_FW_PATH_LEN]; 390 const struct firmware *fw_entry; 391 struct dlpriv temp_fw_sta; 392 int r; 393 CsrResult csrResult; 394 395 /* Get the f/w file name length */ 396 if (get_user(fw_name_length, (unsigned int*)(((unifi_putest_command_t*)arg) + 1))) { 397 unifi_error(priv, 398 "unifi_putest_dl_fw: Failed to get the length argument\n"); 399 return -EFAULT; 400 } 401 402 unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file name size = %d\n", fw_name_length); 403 404 /* Sanity check for the f/w file name length */ 405 if (fw_name_length > UF_PUTEST_MAX_FW_FILE_NAME) { 406 unifi_error(priv, 407 "unifi_putest_dl_fw: F/W file name is too long\n"); 408 return -EINVAL; 409 } 410 411 /* Get the f/w file name */ 412 name_buffer = ((unsigned char*)arg) + sizeof(unifi_putest_command_t) + sizeof(unsigned int); 413 if (copy_from_user(fw_name, (void*)name_buffer, fw_name_length)) { 414 unifi_error(priv, "unifi_putest_dl_fw: Failed to get the file name\n"); 415 return -EFAULT; 416 } 417 fw_name[fw_name_length] = '\0'; 418 unifi_trace(priv, UDBG2, "unifi_putest_dl_fw: file = %s\n", fw_name); 419 420 /* Keep the existing f/w to a temp, we need to restore it later */ 421 temp_fw_sta = priv->fw_sta; 422 423 /* Get the putest f/w */ 424 postfix = priv->instance; 425 scnprintf(fw_path, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s", 426 postfix, fw_name); 427 r = request_firmware(&fw_entry, fw_path, priv->unifi_device); 428 if (r == 0) { 429 priv->fw_sta.fw_desc = (void *)fw_entry; 430 priv->fw_sta.dl_data = fw_entry->data; 431 priv->fw_sta.dl_len = fw_entry->size; 432 } else { 433 unifi_error(priv, "Firmware file not available\n"); 434 return -EINVAL; 435 } 436 437 /* Application may have stopped the XAPs, but they are needed for reset */ 438 CsrSdioClaim(priv->sdio); 439 csrResult = unifi_start_processors(priv->card); 440 CsrSdioRelease(priv->sdio); 441 if (csrResult != CSR_RESULT_SUCCESS) { 442 unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); 443 } 444 445 /* Download the f/w. On UF6xxx this will cause the f/w file to convert 446 * into patch format and download via the ROM boot loader 447 */ 448 CsrSdioClaim(priv->sdio); 449 csrResult = unifi_download(priv->card, 0x0c00); 450 CsrSdioRelease(priv->sdio); 451 if (csrResult != CSR_RESULT_SUCCESS) { 452 unifi_error(priv, 453 "unifi_putest_dl_fw: failed to download the f/w\n"); 454 goto free_fw; 455 } 456 457 /* Free the putest f/w... */ 458free_fw: 459 uf_release_firmware(priv, &priv->fw_sta); 460 /* ... and restore the original f/w */ 461 priv->fw_sta = temp_fw_sta; 462 463 return CsrHipResultToStatus(csrResult); 464} 465 466 467int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg) 468{ 469 unsigned int fw_length; 470 unsigned char *fw_buf = NULL; 471 unsigned char *fw_user_ptr; 472 struct dlpriv temp_fw_sta; 473 CsrResult csrResult; 474 475 /* Get the f/w buffer length */ 476 if (get_user(fw_length, (unsigned int*)(((unifi_putest_command_t*)arg) + 1))) { 477 unifi_error(priv, 478 "unifi_putest_dl_fw_buff: Failed to get the length arg\n"); 479 return -EFAULT; 480 } 481 482 unifi_trace(priv, UDBG2, "unifi_putest_dl_fw_buff: size = %d\n", fw_length); 483 484 /* Sanity check for the buffer length */ 485 if (fw_length == 0 || fw_length > 0xfffffff) { 486 unifi_error(priv, 487 "unifi_putest_dl_fw_buff: buffer length bad %u\n", fw_length); 488 return -EINVAL; 489 } 490 491 /* Buffer for kernel copy of the f/w image */ 492 fw_buf = kmalloc(fw_length, GFP_KERNEL); 493 if (!fw_buf) { 494 unifi_error(priv, "unifi_putest_dl_fw_buff: malloc fail\n"); 495 return -ENOMEM; 496 } 497 498 /* Get the f/w image */ 499 fw_user_ptr = ((unsigned char*)arg) + sizeof(unifi_putest_command_t) + sizeof(unsigned int); 500 if (copy_from_user(fw_buf, (void*)fw_user_ptr, fw_length)) { 501 unifi_error(priv, "unifi_putest_dl_fw_buff: Failed to get the buffer\n"); 502 kfree(fw_buf); 503 return -EFAULT; 504 } 505 506 /* Save the existing f/w to a temp, we need to restore it later */ 507 temp_fw_sta = priv->fw_sta; 508 509 /* Setting fw_desc NULL indicates to the core that no f/w file was loaded 510 * via the kernel request_firmware() mechanism. This indicates to the core 511 * that it shouldn't call release_firmware() after the download is done. 512 */ 513 priv->fw_sta.fw_desc = NULL; /* No OS f/w resource */ 514 priv->fw_sta.dl_data = fw_buf; 515 priv->fw_sta.dl_len = fw_length; 516 517 /* Application may have stopped the XAPs, but they are needed for reset */ 518 CsrSdioClaim(priv->sdio); 519 csrResult = unifi_start_processors(priv->card); 520 CsrSdioRelease(priv->sdio); 521 if (csrResult != CSR_RESULT_SUCCESS) { 522 unifi_error(priv, "Failed to start XAPs. Hard reset required.\n"); 523 } 524 525 /* Download the f/w. On UF6xxx this will cause the f/w file to convert 526 * into patch format and download via the ROM boot loader 527 */ 528 CsrSdioClaim(priv->sdio); 529 csrResult = unifi_download(priv->card, 0x0c00); 530 CsrSdioRelease(priv->sdio); 531 if (csrResult != CSR_RESULT_SUCCESS) { 532 unifi_error(priv, 533 "unifi_putest_dl_fw_buff: failed to download the f/w\n"); 534 goto free_fw; 535 } 536 537free_fw: 538 /* Finished with the putest f/w, so restore the station f/w */ 539 priv->fw_sta = temp_fw_sta; 540 kfree(fw_buf); 541 542 return CsrHipResultToStatus(csrResult); 543} 544 545 546int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg) 547{ 548 u16 data_u16; 549 s32 i; 550 CsrResult r; 551 552 unifi_info(priv, "Preparing for SDIO coredump\n"); 553#if defined (CSR_WIFI_HIP_DEBUG_OFFLINE) 554 unifi_debug_buf_dump(); 555#endif 556 557 /* Sanity check that userspace hasn't called a PUTEST_START, because that 558 * would have reset UniFi, potentially power cycling it and losing context 559 */ 560 if (priv->ptest_mode) { 561 unifi_error(priv, "PUTEST_START shouldn't be used before a coredump\n"); 562 } 563 564 /* Flag that the userspace has requested coredump. Even if this preparation 565 * fails, the SME will call PUTEST_STOP to tidy up. 566 */ 567 priv->coredump_mode = 1; 568 569 for (i = 0; i < 3; i++) { 570 CsrSdioClaim(priv->sdio); 571 r = CsrSdioRead16(priv->sdio, CHIP_HELPER_UNIFI_GBL_CHIP_VERSION*2, &data_u16); 572 CsrSdioRelease(priv->sdio); 573 if (r != CSR_RESULT_SUCCESS) { 574 unifi_info(priv, "Failed to read chip version! Try %d\n", i); 575 576 /* First try, re-enable function which may have been disabled by f/w panic */ 577 if (i == 0) { 578 unifi_info(priv, "Try function enable\n"); 579 CsrSdioClaim(priv->sdio); 580 r = CsrSdioFunctionEnable(priv->sdio); 581 CsrSdioRelease(priv->sdio); 582 if (r != CSR_RESULT_SUCCESS) { 583 unifi_error(priv, "CsrSdioFunctionEnable failed %d\n", r); 584 } 585 continue; 586 } 587 588 /* Subsequent tries, reset */ 589 590 /* Set clock speed low */ 591 CsrSdioClaim(priv->sdio); 592 r = CsrSdioMaxBusClockFrequencySet(priv->sdio, UNIFI_SDIO_CLOCK_SAFE_HZ); 593 CsrSdioRelease(priv->sdio); 594 if (r != CSR_RESULT_SUCCESS) { 595 unifi_error(priv, "CsrSdioMaxBusClockFrequencySet() failed %d\n", r); 596 } 597 598 /* Card software reset */ 599 CsrSdioClaim(priv->sdio); 600 r = unifi_card_hard_reset(priv->card); 601 CsrSdioRelease(priv->sdio); 602 if (r != CSR_RESULT_SUCCESS) { 603 unifi_error(priv, "unifi_card_hard_reset() failed %d\n", r); 604 } 605 } else { 606 unifi_info(priv, "Read chip version of 0x%04x\n", data_u16); 607 break; 608 } 609 } 610 611 if (r != CSR_RESULT_SUCCESS) { 612 unifi_error(priv, "Failed to prepare chip\n"); 613 return -EIO; 614 } 615 616 /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at 617 * Raw SDIO deinit, to resume them. 618 */ 619 CsrSdioClaim(priv->sdio); 620 r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH); 621 CsrSdioRelease(priv->sdio); 622 if (r != CSR_RESULT_SUCCESS) { 623 unifi_error(priv, "Failed to stop processors\n"); 624 } 625 626 return 0; 627} 628 629int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg) 630{ 631 struct unifi_putest_block_cmd52_r block_cmd52; 632 u8 *arg_pos; 633 unsigned int cmd_param_size; 634 CsrResult r; 635 u8 *block_local_buffer; 636 637 arg_pos = (u8*)(((unifi_putest_command_t*)arg) + 1); 638 if (get_user(cmd_param_size, (int*)arg_pos)) { 639 unifi_error(priv, 640 "cmd52r_block: Failed to get the argument\n"); 641 return -EFAULT; 642 } 643 644 if (cmd_param_size != sizeof(struct unifi_putest_block_cmd52_r)) { 645 unifi_error(priv, 646 "cmd52r_block: cmd52 struct mismatch\n"); 647 return -EINVAL; 648 } 649 650 arg_pos += sizeof(unsigned int); 651 if (copy_from_user(&block_cmd52, 652 (void*)arg_pos, 653 sizeof(struct unifi_putest_block_cmd52_r))) { 654 unifi_error(priv, 655 "cmd52r_block: Failed to get the cmd52 params\n"); 656 return -EFAULT; 657 } 658 659 unifi_trace(priv, UDBG2, "cmd52r_block: func=%d addr=0x%x len=0x%x ", 660 block_cmd52.funcnum, block_cmd52.addr, block_cmd52.length); 661 662 block_local_buffer = vmalloc(block_cmd52.length); 663 if (block_local_buffer == NULL) { 664 unifi_error(priv, "cmd52r_block: Failed to allocate buffer\n"); 665 return -ENOMEM; 666 } 667 668 CsrSdioClaim(priv->sdio); 669 r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length); 670 CsrSdioRelease(priv->sdio); 671 if (r != CSR_RESULT_SUCCESS) { 672 unifi_error(priv, "cmd52r_block: unifi_readn failed\n"); 673 return -EIO; 674 } 675 676 if (copy_to_user((void*)block_cmd52.data, 677 block_local_buffer, 678 block_cmd52.length)) { 679 unifi_error(priv, 680 "cmd52r_block: Failed to return the data\n"); 681 return -EFAULT; 682 } 683 684 return 0; 685}