10612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/* 20612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Ultra Wide Band 30612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * UWB basic command support and radio reset 40612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 50612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Copyright (C) 2005-2006 Intel Corporation 60612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> 70612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 80612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This program is free software; you can redistribute it and/or 90612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * modify it under the terms of the GNU General Public License version 100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2 as published by the Free Software Foundation. 110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This program is distributed in the hope that it will be useful, 130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * but WITHOUT ANY WARRANTY; without even the implied warranty of 140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * GNU General Public License for more details. 160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * You should have received a copy of the GNU General Public License 180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * along with this program; if not, write to the Free Software 190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 02110-1301, USA. 210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * FIXME: 240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * - docs 260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * - Now we are serializing (using the uwb_dev->mutex) the command 280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * execution; it should be parallelized as much as possible some 290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * day. 300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez#include <linux/kernel.h> 320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez#include <linux/err.h> 335a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 340396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel#include <linux/delay.h> 35475c0a6b2cff037ca522d3aff839024ab30ed7ebPaul Gortmaker#include <linux/export.h> 360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez#include "uwb-internal.h" 380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Command result codes (WUSB1.0[T8-69]) 410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic 430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezconst char *__strerror[] = { 440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "success", 450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "failure", 460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "hardware failure", 470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "no more slots", 480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "beacon is too large", 490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "invalid parameter", 500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "unsupported power level", 510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "time out (wa) or invalid ie data (whci)", 520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "beacon size exceeded", 530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "cancelled", 540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "invalid state", 550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "invalid size", 5625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi "ack not received", 570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "no more asie notification", 580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez}; 590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** Return a string matching the given error code */ 620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezconst char *uwb_rc_strerror(unsigned code) 630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (code == 255) 650612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return "time out"; 660612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (code >= ARRAY_SIZE(__strerror)) 670612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return "unknown error"; 680612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return __strerror[code]; 690612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 700612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 710612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezint uwb_rc_cmd_async(struct uwb_rc *rc, const char *cmd_name, 720612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rccb *cmd, size_t cmd_size, 730612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u8 expected_type, u16 expected_event, 740612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_rc_cmd_cb_f cb, void *arg) 750612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 760612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct device *dev = &rc->uwb_dev.dev; 770612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rc_neh *neh; 780612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez int needtofree = 0; 790612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez int result; 800612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 810612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_dev_lock(&rc->uwb_dev); /* Protect against rc->priv being removed */ 820612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (rc->priv == NULL) { 830612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_dev_unlock(&rc->uwb_dev); 840612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return -ESHUTDOWN; 850612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 860612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 870612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (rc->filter_cmd) { 880612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez needtofree = rc->filter_cmd(rc, &cmd, &cmd_size); 890612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (needtofree < 0 && needtofree != -ENOANO) { 900612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez dev_err(dev, "%s: filter error: %d\n", 910612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez cmd_name, needtofree); 920612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_dev_unlock(&rc->uwb_dev); 930612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return needtofree; 940612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 950612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 960612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 970612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez neh = uwb_rc_neh_add(rc, cmd, expected_type, expected_event, cb, arg); 980612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (IS_ERR(neh)) { 990612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = PTR_ERR(neh); 1000612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto out; 1010612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 1020612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1030612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = rc->cmd(rc, cmd, cmd_size); 1040612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_dev_unlock(&rc->uwb_dev); 1050612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (result < 0) 1060612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_rc_neh_rm(rc, neh); 1070612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez else 1080612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_rc_neh_arm(rc, neh); 1090612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_rc_neh_put(neh); 1100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezout: 1110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (needtofree == 1) 1120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez kfree(cmd); 1130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return result < 0 ? result : 0; 1140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 1150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_rc_cmd_async); 1160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstruct uwb_rc_cmd_done_params { 1180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct completion completion; 1190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rceb *reply; 1200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez ssize_t reply_size; 1210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez}; 1220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic void uwb_rc_cmd_done(struct uwb_rc *rc, void *arg, 1240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rceb *reply, ssize_t reply_size) 1250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 1260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rc_cmd_done_params *p = (struct uwb_rc_cmd_done_params *)arg; 1270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (reply_size > 0) { 1290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (p->reply) 1300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez reply_size = min(p->reply_size, reply_size); 1310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez else 1320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez p->reply = kmalloc(reply_size, GFP_ATOMIC); 1330612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1340612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (p->reply) 1350612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez memcpy(p->reply, reply, reply_size); 1360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez else 1370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez reply_size = -ENOMEM; 1380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 1390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez p->reply_size = reply_size; 1400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez complete(&p->completion); 1410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 1420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 1450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Generic function for issuing commands to the Radio Control Interface 1460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 1470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc: UWB Radio Control descriptor 1480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd_name: Name of the command being issued (for error messages) 1490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd: Pointer to rccb structure containing the command; 1500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * normally you embed this structure as the first member of 1510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * the full command structure. 1520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd_size: Size of the whole command buffer pointed to by @cmd. 1530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @reply: Pointer to where to store the reply 1540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @reply_size: @reply's size 1550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @expected_type: Expected type in the return event 1560612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @expected_event: Expected event code in the return event 1570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @preply: Here a pointer to where the event data is received will 1580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * be stored. Once done with the data, free with kfree(). 1590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 1600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * This function is generic; it works for commands that return a fixed 1610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * and known size or for commands that return a variable amount of data. 1620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 1630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * If a buffer is provided, that is used, although it could be chopped 1640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * to the maximum size of the buffer. If the buffer is NULL, then one 1650612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * be allocated in *preply with the whole contents of the reply. 1660612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 1670612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc needs to be referenced 1680612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 1690612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezstatic 1700612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezssize_t __uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name, 1710612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rccb *cmd, size_t cmd_size, 1720612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rceb *reply, size_t reply_size, 1730612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u8 expected_type, u16 expected_event, 1740612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rceb **preply) 1750612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 1760612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez ssize_t result = 0; 1770612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct device *dev = &rc->uwb_dev.dev; 1780612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rc_cmd_done_params params; 1790612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1800612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez init_completion(¶ms.completion); 1810612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez params.reply = reply; 1820612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez params.reply_size = reply_size; 1830612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1840612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = uwb_rc_cmd_async(rc, cmd_name, cmd, cmd_size, 1850612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez expected_type, expected_event, 1860612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_rc_cmd_done, ¶ms); 1870612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (result) 1880612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return result; 1890612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1900612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez wait_for_completion(¶ms.completion); 1910612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1920612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (preply) 1930612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez *preply = params.reply; 1940612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 1950612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (params.reply_size < 0) 1960612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez dev_err(dev, "%s: confirmation event 0x%02x/%04x/%02x " 1970612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "reception failed: %d\n", cmd_name, 1980612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez expected_type, expected_event, cmd->bCommandContext, 1990612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez (int)params.reply_size); 2000612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return params.reply_size; 2010612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 2020612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2030612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2040612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 2050612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Generic function for issuing commands to the Radio Control Interface 2060612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2070612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc: UWB Radio Control descriptor 2080612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd_name: Name of the command being issued (for error messages) 2090612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd: Pointer to rccb structure containing the command; 2100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * normally you embed this structure as the first member of 2110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * the full command structure. 2120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd_size: Size of the whole command buffer pointed to by @cmd. 2130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @reply: Pointer to the beginning of the confirmation event 2140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * buffer. Normally bigger than an 'struct hwarc_rceb'. 2150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * You need to fill out reply->bEventType and reply->wEvent (in 2160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * cpu order) as the function will use them to verify the 2170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * confirmation event. 2180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @reply_size: Size of the reply buffer 2190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * The function checks that the length returned in the reply is at 2210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * least as big as @reply_size; if not, it will be deemed an error and 2220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * -EIO returned. 2230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc needs to be referenced 2250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 2260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezssize_t uwb_rc_cmd(struct uwb_rc *rc, const char *cmd_name, 2270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rccb *cmd, size_t cmd_size, 2280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rceb *reply, size_t reply_size) 2290612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 2300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct device *dev = &rc->uwb_dev.dev; 2310612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez ssize_t result; 2320612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2330612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = __uwb_rc_cmd(rc, cmd_name, 2340612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez cmd, cmd_size, reply, reply_size, 2350612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez reply->bEventType, reply->wEvent, NULL); 2360612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2370612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (result > 0 && result < reply_size) { 2380612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez dev_err(dev, "%s: not enough data returned for decoding reply " 2390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "(%zu bytes received vs at least %zu needed)\n", 2400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez cmd_name, result, reply_size); 2410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = -EIO; 2420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 2430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return result; 2440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 2450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_rc_cmd); 2460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 2490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Generic function for issuing commands to the Radio Control 2500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Interface that return an unknown amount of data 2510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc: UWB Radio Control descriptor 2530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd_name: Name of the command being issued (for error messages) 2540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd: Pointer to rccb structure containing the command; 2550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * normally you embed this structure as the first member of 2560612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * the full command structure. 2570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @cmd_size: Size of the whole command buffer pointed to by @cmd. 2580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @expected_type: Expected type in the return event 2590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @expected_event: Expected event code in the return event 2600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @preply: Here a pointer to where the event data is received will 2610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * be stored. Once done with the data, free with kfree(). 2620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * The function checks that the length returned in the reply is at 2640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * least as big as a 'struct uwb_rceb *'; if not, it will be deemed an 2650612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * error and -EIO returned. 2660612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2670612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc needs to be referenced 2680612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 2690612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezssize_t uwb_rc_vcmd(struct uwb_rc *rc, const char *cmd_name, 2700612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rccb *cmd, size_t cmd_size, 2710612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez u8 expected_type, u16 expected_event, 2720612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rceb **preply) 2730612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 2740612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return __uwb_rc_cmd(rc, cmd_name, cmd, cmd_size, NULL, 0, 2750612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez expected_type, expected_event, preply); 2760612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 2770612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_rc_vcmd); 2780612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2790612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2800612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 2810612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * Reset a UWB Host Controller (and all radio settings) 2820612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2830612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc: Host Controller descriptor 2840612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @returns: 0 if ok, < 0 errno code on error 2850612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 2860612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * We put the command on kmalloc'ed memory as some arches cannot do 2870612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * USB from the stack. The reply event is copied from an stage buffer, 2880612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * so it can be in the stack. See WUSB1.0[8.6.2.4] for more details. 2890612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 2900612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezint uwb_rc_reset(struct uwb_rc *rc) 2910612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 2920612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez int result = -ENOMEM; 2930612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rc_evt_confirm reply; 2940612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rccb *cmd; 2950612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez size_t cmd_size = sizeof(*cmd); 2960612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 2970612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez mutex_lock(&rc->uwb_dev.mutex); 2980612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 2990612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (cmd == NULL) 3000612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto error_kzalloc; 3010612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez cmd->bCommandType = UWB_RC_CET_GENERAL; 3020612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez cmd->wCommand = cpu_to_le16(UWB_RC_CMD_RESET); 3030612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez reply.rceb.bEventType = UWB_RC_CET_GENERAL; 3040612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez reply.rceb.wEvent = UWB_RC_CMD_RESET; 3050612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = uwb_rc_cmd(rc, "RESET", cmd, cmd_size, 3060612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez &reply.rceb, sizeof(reply)); 3070612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (result < 0) 3080612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez goto error_cmd; 3090612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (reply.bResultCode != UWB_RC_RES_SUCCESS) { 3100612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez dev_err(&rc->uwb_dev.dev, 3110612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez "RESET: command execution failed: %s (%d)\n", 3120612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwb_rc_strerror(reply.bResultCode), reply.bResultCode); 3130612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez result = -EIO; 3140612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez } 3150612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezerror_cmd: 3160612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez kfree(cmd); 3170612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezerror_kzalloc: 3180612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez mutex_unlock(&rc->uwb_dev.mutex); 3190612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return result; 3200612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 3210612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3220612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezint uwbd_msg_handle_reset(struct uwb_event *evt) 3230612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 3240612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_rc *rc = evt->rc; 3250612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez int ret; 3260612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3270612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez dev_info(&rc->uwb_dev.dev, "resetting radio controller\n"); 3280612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez ret = rc->reset(rc); 3290396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel if (ret < 0) { 3300612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez dev_err(&rc->uwb_dev.dev, "failed to reset hardware: %d\n", ret); 331307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel goto error; 332307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel } 333307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel return 0; 334307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabelerror: 3350396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel /* Nothing can be done except try the reset again. Wait a bit 3360396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel to avoid reset loops during probe() or remove(). */ 3370396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel msleep(1000); 338307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel uwb_rc_reset_all(rc); 3390612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return ret; 3400612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 3410612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3420612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez/** 3430612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * uwb_rc_reset_all - request a reset of the radio controller and PALs 3440612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * @rc: the radio controller of the hardware device to be reset. 3450612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * 3460612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * The full hardware reset of the radio controller and all the PALs 3470612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez * will be scheduled. 3480612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez */ 3490612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalezvoid uwb_rc_reset_all(struct uwb_rc *rc) 3500612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez{ 3510612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez struct uwb_event *evt; 3520612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3530612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez evt = kzalloc(sizeof(struct uwb_event), GFP_ATOMIC); 3540612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez if (unlikely(evt == NULL)) 3550612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez return; 3560612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3570612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez evt->rc = __uwb_rc_get(rc); /* will be put by uwbd's uwbd_event_handle() */ 3580612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez evt->ts_jiffies = jiffies; 3590612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez evt->type = UWB_EVT_TYPE_MSG; 3600612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez evt->message = UWB_EVT_MSG_RESET; 3610612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez 3620612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez uwbd_event_queue(evt); 3630612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-Gonzalez} 3640612edfd95ffe92201a2267e9e1b0fc68becf76dInaky Perez-GonzalezEXPORT_SYMBOL_GPL(uwb_rc_reset_all); 365307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel 366307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabelvoid uwb_rc_pre_reset(struct uwb_rc *rc) 367307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel{ 368307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel rc->stop(rc); 369307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel uwbd_flush(rc); 370307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel 3716fae35f9cea92793a98b2d9ab21235e5ae035581David Vrabel uwb_radio_reset_state(rc); 372307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel uwb_rsv_remove_all(rc); 373307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel} 374307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David VrabelEXPORT_SYMBOL_GPL(uwb_rc_pre_reset); 375307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel 3760396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabelint uwb_rc_post_reset(struct uwb_rc *rc) 377307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel{ 378307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel int ret; 379307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel 380307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel ret = rc->start(rc); 381307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel if (ret) 3820396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel goto out; 383307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel ret = uwb_rc_mac_addr_set(rc, &rc->uwb_dev.mac_addr); 384307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel if (ret) 3850396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel goto out; 386307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel ret = uwb_rc_dev_addr_set(rc, &rc->uwb_dev.dev_addr); 387307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel if (ret) 3880396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel goto out; 3890396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabelout: 3900396c215f301e92677d1e9a064b405e31501dc1dDavid Vrabel return ret; 391307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David Vrabel} 392307ba6dd73254fe7d2ce27db64ffd90e1bb3c6c0David VrabelEXPORT_SYMBOL_GPL(uwb_rc_post_reset); 393