11ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez/* 21ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Intel Wireless UWB Link 1480 31ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Main driver 41ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 51ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Copyright (C) 2005-2006 Intel Corporation 61ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 71ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 81ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 91ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 101ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 111ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 121ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 131ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 141ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 151ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * GNU General Public License for more details. 161ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 171ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 181ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * along with this program; if not, write to the Free Software 191ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 201ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 02110-1301, USA. 211ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 221ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 231ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Common code for firmware upload used by the USB and PCI version; 241ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * i1480_fw_upload() takes a device descriptor and uses the function 251ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * pointers it provides to upload firmware and prepare the PHY. 261ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 271ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * As well, provides common functions used by the rest of the code. 281ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez */ 291ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez#include "i1480-dfu.h" 301ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez#include <linux/errno.h> 311ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez#include <linux/delay.h> 321ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez#include <linux/pci.h> 331ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez#include <linux/device.h> 341ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez#include <linux/uwb.h> 351ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez#include <linux/random.h> 36475c0a6b2cff037ca522d3aff839024ab30ed7ebPaul Gortmaker#include <linux/export.h> 371ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 38bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel/* 39b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * i1480_rceb_check - Check RCEB for expected field values 40b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * @i1480: pointer to device for which RCEB is being checked 41b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * @rceb: RCEB being checked 42b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * @cmd: which command the RCEB is related to 43b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * @context: expected context 44b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * @expected_type: expected event type 45b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * @expected_event: expected event 46b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * 47b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * If @cmd is NULL, do not print error messages, but still return an error 48b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * code. 49b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * 50b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * Return 0 if @rceb matches the expected values, -EINVAL otherwise. 51b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo */ 521ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezint i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb, 53b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo const char *cmd, u8 context, u8 expected_type, 54b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo unsigned expected_event) 551ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez{ 561ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez int result = 0; 571ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez struct device *dev = i1480->dev; 581ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (rceb->bEventContext != context) { 59b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo if (cmd) 60b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo dev_err(dev, "%s: unexpected context id 0x%02x " 61b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo "(expected 0x%02x)\n", cmd, 62b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo rceb->bEventContext, context); 631ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = -EINVAL; 641ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 651ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (rceb->bEventType != expected_type) { 66b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo if (cmd) 67b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo dev_err(dev, "%s: unexpected event type 0x%02x " 68b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo "(expected 0x%02x)\n", cmd, 69b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo rceb->bEventType, expected_type); 701ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = -EINVAL; 711ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 721ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (le16_to_cpu(rceb->wEvent) != expected_event) { 73b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo if (cmd) 74b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo dev_err(dev, "%s: unexpected event 0x%04x " 75b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo "(expected 0x%04x)\n", cmd, 76b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo le16_to_cpu(rceb->wEvent), expected_event); 771ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = -EINVAL; 781ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 791ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez return result; 801ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez} 811ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(i1480_rceb_check); 821ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 831ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 84bce83697c5fe84a7a5d38c96fbbe43b4bc028c3eDavid Vrabel/* 851ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Execute a Radio Control Command 861ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 871ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * Command data has to be in i1480->cmd_buf. 881ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 891ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * @returns size of the reply data filled in i1480->evt_buf or < 0 errno 901ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * code on error. 911ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez */ 921ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size, 931ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez size_t reply_size) 941ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez{ 951ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez ssize_t result; 961ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez struct uwb_rceb *reply = i1480->evt_buf; 971ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez struct uwb_rccb *cmd = i1480->cmd_buf; 981ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez u16 expected_event = reply->wEvent; 991ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez u8 expected_type = reply->bEventType; 1001ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez u8 context; 1011ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 1021ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez init_completion(&i1480->evt_complete); 1031ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez i1480->evt_result = -EINPROGRESS; 1041ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez do { 1051ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez get_random_bytes(&context, 1); 1061ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } while (context == 0x00 || context == 0xff); 1071ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez cmd->bCommandContext = context; 1081ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = i1480->cmd(i1480, cmd_name, cmd_size); 1091ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result < 0) 1101ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1111ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez /* wait for the callback to report a event was received */ 1121ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = wait_for_completion_interruptible_timeout( 1131ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez &i1480->evt_complete, HZ); 1141ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result == 0) { 1151ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = -ETIMEDOUT; 1161ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1171ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 1181ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result < 0) 1191ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1201ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = i1480->evt_result; 1211ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result < 0) { 1221ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez dev_err(i1480->dev, "%s: command reply reception failed: %zd\n", 1231ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez cmd_name, result); 1241ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1251ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 126b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo /* 127b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * Firmware versions >= 1.4.12224 for IOGear GUWA100U generate a 128b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * spurious notification after firmware is downloaded. So check whether 129b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * the receibed RCEB is such notification before assuming that the 130b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo * command has failed. 131b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo */ 132b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo if (i1480_rceb_check(i1480, i1480->evt_buf, NULL, 133b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo 0, 0xfd, 0x0022) == 0) { 134b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo /* Now wait for the actual RCEB for this command. */ 135b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo result = i1480->wait_init_done(i1480); 136b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo if (result < 0) 137b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo goto error; 138b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo result = i1480->evt_result; 139b5784f10d559b3c7b25874b21702ad0907b6fcb7Anderson Lizardo } 1401ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result != reply_size) { 1411ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez dev_err(i1480->dev, "%s returned only %zu bytes, %zu expected\n", 1421ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez cmd_name, result, reply_size); 1431ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = -EINVAL; 1441ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1451ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 1461ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez /* Verify we got the right event in response */ 1471ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = i1480_rceb_check(i1480, i1480->evt_buf, cmd_name, context, 1481ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez expected_type, expected_event); 1491ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezerror: 1501ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez return result; 1511ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez} 1521ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(i1480_cmd); 1531ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 1541ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 1551ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezstatic 1561ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezint i1480_print_state(struct i1480 *i1480) 1571ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez{ 1581ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez int result; 1591ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez u32 *buf = (u32 *) i1480->cmd_buf; 1601ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 1611ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = i1480->read(i1480, 0x80080000, 2 * sizeof(*buf)); 1621ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result < 0) { 1631ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez dev_err(i1480->dev, "cannot read U & L states: %d\n", result); 1641ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1651ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 1661ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez dev_info(i1480->dev, "state U 0x%08x, L 0x%08x\n", buf[0], buf[1]); 1671ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezerror: 1681ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez return result; 1691ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez} 1701ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 1711ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 1721ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez/* 1731ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * PCI probe, firmware uploader 1741ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * 1751ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez * _mac_fw_upload() will call rc_setup(), which needs an rc_release(). 1761ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez */ 1771ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezint i1480_fw_upload(struct i1480 *i1480) 1781ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez{ 1791ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez int result; 1801ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez 1811ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = i1480_pre_fw_upload(i1480); /* PHY pre fw */ 1821ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result < 0 && result != -ENOENT) { 1831ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez i1480_print_state(i1480); 1841ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1851ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 1861ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = i1480_mac_fw_upload(i1480); /* MAC fw */ 1871ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result < 0) { 1881ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result == -ENOENT) 1891ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez dev_err(i1480->dev, "Cannot locate MAC FW file '%s'\n", 1901ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez i1480->mac_fw_name); 1911ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez else 1921ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez i1480_print_state(i1480); 1931ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error; 1941ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 1951ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = i1480_phy_fw_upload(i1480); /* PHY fw */ 1961ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (result < 0 && result != -ENOENT) { 1971ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez i1480_print_state(i1480); 1981ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez goto error_rc_release; 1991ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez } 2008c7e8cb85557cc500122f3e489936582b7d11a7cAnderson Lizardo /* 2018c7e8cb85557cc500122f3e489936582b7d11a7cAnderson Lizardo * FIXME: find some reliable way to check whether firmware is running 2028c7e8cb85557cc500122f3e489936582b7d11a7cAnderson Lizardo * properly. Maybe use some standard request that has no side effects? 2038c7e8cb85557cc500122f3e489936582b7d11a7cAnderson Lizardo */ 2041ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez dev_info(i1480->dev, "firmware uploaded successfully\n"); 2051ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezerror_rc_release: 2061ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez if (i1480->rc_release) 2071ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez i1480->rc_release(i1480); 2081ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez result = 0; 2091ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalezerror: 2101ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez return result; 2111ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-Gonzalez} 2121ba47da527121ff704f4e9f27a12c9f32db05022Inaky Perez-GonzalezEXPORT_SYMBOL_GPL(i1480_fw_upload); 213