fcp.c (10527B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Function Control Protocol (IEC 61883-1) helper functions 4 * 5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de> 6 */ 7 8#include <linux/device.h> 9#include <linux/firewire.h> 10#include <linux/firewire-constants.h> 11#include <linux/list.h> 12#include <linux/module.h> 13#include <linux/slab.h> 14#include <linux/sched.h> 15#include <linux/spinlock.h> 16#include <linux/wait.h> 17#include <linux/delay.h> 18#include "fcp.h" 19#include "lib.h" 20#include "amdtp-stream.h" 21 22#define CTS_AVC 0x00 23 24#define ERROR_RETRIES 3 25#define ERROR_DELAY_MS 5 26#define FCP_TIMEOUT_MS 125 27 28int avc_general_set_sig_fmt(struct fw_unit *unit, unsigned int rate, 29 enum avc_general_plug_dir dir, 30 unsigned short pid) 31{ 32 unsigned int sfc; 33 u8 *buf; 34 bool flag; 35 int err; 36 37 flag = false; 38 for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) { 39 if (amdtp_rate_table[sfc] == rate) { 40 flag = true; 41 break; 42 } 43 } 44 if (!flag) 45 return -EINVAL; 46 47 buf = kzalloc(8, GFP_KERNEL); 48 if (buf == NULL) 49 return -ENOMEM; 50 51 buf[0] = 0x00; /* AV/C CONTROL */ 52 buf[1] = 0xff; /* UNIT */ 53 if (dir == AVC_GENERAL_PLUG_DIR_IN) 54 buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ 55 else 56 buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */ 57 buf[3] = 0xff & pid; /* plug id */ 58 buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */ 59 buf[5] = 0x07 & sfc; /* FDF-hi. AM824, frequency */ 60 buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used)*/ 61 buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */ 62 63 /* do transaction and check buf[1-5] are the same against command */ 64 err = fcp_avc_transaction(unit, buf, 8, buf, 8, 65 BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5)); 66 if (err < 0) 67 ; 68 else if (err < 8) 69 err = -EIO; 70 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 71 err = -ENOSYS; 72 else if (buf[0] == 0x0a) /* REJECTED */ 73 err = -EINVAL; 74 if (err < 0) 75 goto end; 76 77 err = 0; 78end: 79 kfree(buf); 80 return err; 81} 82EXPORT_SYMBOL(avc_general_set_sig_fmt); 83 84int avc_general_get_sig_fmt(struct fw_unit *unit, unsigned int *rate, 85 enum avc_general_plug_dir dir, 86 unsigned short pid) 87{ 88 unsigned int sfc; 89 u8 *buf; 90 int err; 91 92 buf = kzalloc(8, GFP_KERNEL); 93 if (buf == NULL) 94 return -ENOMEM; 95 96 buf[0] = 0x01; /* AV/C STATUS */ 97 buf[1] = 0xff; /* Unit */ 98 if (dir == AVC_GENERAL_PLUG_DIR_IN) 99 buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */ 100 else 101 buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */ 102 buf[3] = 0xff & pid; /* plug id */ 103 buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */ 104 buf[5] = 0xff; /* FDF-hi. AM824, frequency */ 105 buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used) */ 106 buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */ 107 108 /* do transaction and check buf[1-4] are the same against command */ 109 err = fcp_avc_transaction(unit, buf, 8, buf, 8, 110 BIT(1) | BIT(2) | BIT(3) | BIT(4)); 111 if (err < 0) 112 ; 113 else if (err < 8) 114 err = -EIO; 115 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 116 err = -ENOSYS; 117 else if (buf[0] == 0x0a) /* REJECTED */ 118 err = -EINVAL; 119 else if (buf[0] == 0x0b) /* IN TRANSITION */ 120 err = -EAGAIN; 121 if (err < 0) 122 goto end; 123 124 /* check sfc field and pick up rate */ 125 sfc = 0x07 & buf[5]; 126 if (sfc >= CIP_SFC_COUNT) { 127 err = -EAGAIN; /* also in transition */ 128 goto end; 129 } 130 131 *rate = amdtp_rate_table[sfc]; 132 err = 0; 133end: 134 kfree(buf); 135 return err; 136} 137EXPORT_SYMBOL(avc_general_get_sig_fmt); 138 139int avc_general_get_plug_info(struct fw_unit *unit, unsigned int subunit_type, 140 unsigned int subunit_id, unsigned int subfunction, 141 u8 info[AVC_PLUG_INFO_BUF_BYTES]) 142{ 143 u8 *buf; 144 int err; 145 146 /* extended subunit in spec.4.2 is not supported */ 147 if ((subunit_type == 0x1E) || (subunit_id == 5)) 148 return -EINVAL; 149 150 buf = kzalloc(8, GFP_KERNEL); 151 if (buf == NULL) 152 return -ENOMEM; 153 154 buf[0] = 0x01; /* AV/C STATUS */ 155 /* UNIT or Subunit, Functionblock */ 156 buf[1] = ((subunit_type & 0x1f) << 3) | (subunit_id & 0x7); 157 buf[2] = 0x02; /* PLUG INFO */ 158 buf[3] = 0xff & subfunction; 159 160 err = fcp_avc_transaction(unit, buf, 8, buf, 8, BIT(1) | BIT(2)); 161 if (err < 0) 162 ; 163 else if (err < 8) 164 err = -EIO; 165 else if (buf[0] == 0x08) /* NOT IMPLEMENTED */ 166 err = -ENOSYS; 167 else if (buf[0] == 0x0a) /* REJECTED */ 168 err = -EINVAL; 169 else if (buf[0] == 0x0b) /* IN TRANSITION */ 170 err = -EAGAIN; 171 if (err < 0) 172 goto end; 173 174 info[0] = buf[4]; 175 info[1] = buf[5]; 176 info[2] = buf[6]; 177 info[3] = buf[7]; 178 179 err = 0; 180end: 181 kfree(buf); 182 return err; 183} 184EXPORT_SYMBOL(avc_general_get_plug_info); 185 186static DEFINE_SPINLOCK(transactions_lock); 187static LIST_HEAD(transactions); 188 189enum fcp_state { 190 STATE_PENDING, 191 STATE_BUS_RESET, 192 STATE_COMPLETE, 193 STATE_DEFERRED, 194}; 195 196struct fcp_transaction { 197 struct list_head list; 198 struct fw_unit *unit; 199 void *response_buffer; 200 unsigned int response_size; 201 unsigned int response_match_bytes; 202 enum fcp_state state; 203 wait_queue_head_t wait; 204 bool deferrable; 205}; 206 207/** 208 * fcp_avc_transaction - send an AV/C command and wait for its response 209 * @unit: a unit on the target device 210 * @command: a buffer containing the command frame; must be DMA-able 211 * @command_size: the size of @command 212 * @response: a buffer for the response frame 213 * @response_size: the maximum size of @response 214 * @response_match_bytes: a bitmap specifying the bytes used to detect the 215 * correct response frame 216 * 217 * This function sends a FCP command frame to the target and waits for the 218 * corresponding response frame to be returned. 219 * 220 * Because it is possible for multiple FCP transactions to be active at the 221 * same time, the correct response frame is detected by the value of certain 222 * bytes. These bytes must be set in @response before calling this function, 223 * and the corresponding bits must be set in @response_match_bytes. 224 * 225 * @command and @response can point to the same buffer. 226 * 227 * Returns the actual size of the response frame, or a negative error code. 228 */ 229int fcp_avc_transaction(struct fw_unit *unit, 230 const void *command, unsigned int command_size, 231 void *response, unsigned int response_size, 232 unsigned int response_match_bytes) 233{ 234 struct fcp_transaction t; 235 int tcode, ret, tries = 0; 236 237 t.unit = unit; 238 t.response_buffer = response; 239 t.response_size = response_size; 240 t.response_match_bytes = response_match_bytes; 241 t.state = STATE_PENDING; 242 init_waitqueue_head(&t.wait); 243 t.deferrable = (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03); 244 245 spin_lock_irq(&transactions_lock); 246 list_add_tail(&t.list, &transactions); 247 spin_unlock_irq(&transactions_lock); 248 249 for (;;) { 250 tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST 251 : TCODE_WRITE_BLOCK_REQUEST; 252 ret = snd_fw_transaction(t.unit, tcode, 253 CSR_REGISTER_BASE + CSR_FCP_COMMAND, 254 (void *)command, command_size, 0); 255 if (ret < 0) 256 break; 257deferred: 258 wait_event_timeout(t.wait, t.state != STATE_PENDING, 259 msecs_to_jiffies(FCP_TIMEOUT_MS)); 260 261 if (t.state == STATE_DEFERRED) { 262 /* 263 * 'AV/C General Specification' define no time limit 264 * on command completion once an INTERIM response has 265 * been sent. but we promise to finish this function 266 * for a caller. Here we use FCP_TIMEOUT_MS for next 267 * interval. This is not in the specification. 268 */ 269 t.state = STATE_PENDING; 270 goto deferred; 271 } else if (t.state == STATE_COMPLETE) { 272 ret = t.response_size; 273 break; 274 } else if (t.state == STATE_BUS_RESET) { 275 msleep(ERROR_DELAY_MS); 276 } else if (++tries >= ERROR_RETRIES) { 277 dev_err(&t.unit->device, "FCP command timed out\n"); 278 ret = -EIO; 279 break; 280 } 281 } 282 283 spin_lock_irq(&transactions_lock); 284 list_del(&t.list); 285 spin_unlock_irq(&transactions_lock); 286 287 return ret; 288} 289EXPORT_SYMBOL(fcp_avc_transaction); 290 291/** 292 * fcp_bus_reset - inform the target handler about a bus reset 293 * @unit: the unit that might be used by fcp_avc_transaction() 294 * 295 * This function must be called from the driver's .update handler to inform 296 * the FCP transaction handler that a bus reset has happened. Any pending FCP 297 * transactions are retried. 298 */ 299void fcp_bus_reset(struct fw_unit *unit) 300{ 301 struct fcp_transaction *t; 302 303 spin_lock_irq(&transactions_lock); 304 list_for_each_entry(t, &transactions, list) { 305 if (t->unit == unit && 306 (t->state == STATE_PENDING || 307 t->state == STATE_DEFERRED)) { 308 t->state = STATE_BUS_RESET; 309 wake_up(&t->wait); 310 } 311 } 312 spin_unlock_irq(&transactions_lock); 313} 314EXPORT_SYMBOL(fcp_bus_reset); 315 316/* checks whether the response matches the masked bytes in response_buffer */ 317static bool is_matching_response(struct fcp_transaction *transaction, 318 const void *response, size_t length) 319{ 320 const u8 *p1, *p2; 321 unsigned int mask, i; 322 323 p1 = response; 324 p2 = transaction->response_buffer; 325 mask = transaction->response_match_bytes; 326 327 for (i = 0; ; ++i) { 328 if ((mask & 1) && p1[i] != p2[i]) 329 return false; 330 mask >>= 1; 331 if (!mask) 332 return true; 333 if (--length == 0) 334 return false; 335 } 336} 337 338static void fcp_response(struct fw_card *card, struct fw_request *request, 339 int tcode, int destination, int source, 340 int generation, unsigned long long offset, 341 void *data, size_t length, void *callback_data) 342{ 343 struct fcp_transaction *t; 344 unsigned long flags; 345 346 if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC) 347 return; 348 349 spin_lock_irqsave(&transactions_lock, flags); 350 list_for_each_entry(t, &transactions, list) { 351 struct fw_device *device = fw_parent_device(t->unit); 352 if (device->card != card || 353 device->generation != generation) 354 continue; 355 smp_rmb(); /* node_id vs. generation */ 356 if (device->node_id != source) 357 continue; 358 359 if (t->state == STATE_PENDING && 360 is_matching_response(t, data, length)) { 361 if (t->deferrable && *(const u8 *)data == 0x0f) { 362 t->state = STATE_DEFERRED; 363 } else { 364 t->state = STATE_COMPLETE; 365 t->response_size = min_t(unsigned int, length, 366 t->response_size); 367 memcpy(t->response_buffer, data, 368 t->response_size); 369 } 370 wake_up(&t->wait); 371 } 372 } 373 spin_unlock_irqrestore(&transactions_lock, flags); 374} 375 376static struct fw_address_handler response_register_handler = { 377 .length = 0x200, 378 .address_callback = fcp_response, 379}; 380 381static int __init fcp_module_init(void) 382{ 383 static const struct fw_address_region response_register_region = { 384 .start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE, 385 .end = CSR_REGISTER_BASE + CSR_FCP_END, 386 }; 387 388 fw_core_add_address_handler(&response_register_handler, 389 &response_register_region); 390 391 return 0; 392} 393 394static void __exit fcp_module_exit(void) 395{ 396 WARN_ON(!list_empty(&transactions)); 397 fw_core_remove_address_handler(&response_register_handler); 398} 399 400module_init(fcp_module_init); 401module_exit(fcp_module_exit);