.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Connection Management Procedures (IEC 61883-1) helper functions |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
---|
5 | | - * Licensed under the terms of the GNU General Public License, version 2. |
---|
6 | 6 | */ |
---|
7 | 7 | |
---|
8 | 8 | #include <linux/device.h> |
---|
.. | .. |
---|
185 | 185 | } |
---|
186 | 186 | EXPORT_SYMBOL(cmp_connection_destroy); |
---|
187 | 187 | |
---|
| 188 | +int cmp_connection_reserve(struct cmp_connection *c, |
---|
| 189 | + unsigned int max_payload_bytes) |
---|
| 190 | +{ |
---|
| 191 | + int err; |
---|
| 192 | + |
---|
| 193 | + mutex_lock(&c->mutex); |
---|
| 194 | + |
---|
| 195 | + if (WARN_ON(c->resources.allocated)) { |
---|
| 196 | + err = -EBUSY; |
---|
| 197 | + goto end; |
---|
| 198 | + } |
---|
| 199 | + |
---|
| 200 | + c->speed = min(c->max_speed, |
---|
| 201 | + fw_parent_device(c->resources.unit)->max_speed); |
---|
| 202 | + |
---|
| 203 | + err = fw_iso_resources_allocate(&c->resources, max_payload_bytes, |
---|
| 204 | + c->speed); |
---|
| 205 | +end: |
---|
| 206 | + mutex_unlock(&c->mutex); |
---|
| 207 | + |
---|
| 208 | + return err; |
---|
| 209 | +} |
---|
| 210 | +EXPORT_SYMBOL(cmp_connection_reserve); |
---|
| 211 | + |
---|
| 212 | +void cmp_connection_release(struct cmp_connection *c) |
---|
| 213 | +{ |
---|
| 214 | + mutex_lock(&c->mutex); |
---|
| 215 | + fw_iso_resources_free(&c->resources); |
---|
| 216 | + mutex_unlock(&c->mutex); |
---|
| 217 | +} |
---|
| 218 | +EXPORT_SYMBOL(cmp_connection_release); |
---|
188 | 219 | |
---|
189 | 220 | static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) |
---|
190 | 221 | { |
---|
.. | .. |
---|
262 | 293 | /** |
---|
263 | 294 | * cmp_connection_establish - establish a connection to the target |
---|
264 | 295 | * @c: the connection manager |
---|
265 | | - * @max_payload_bytes: the amount of data (including CIP headers) per packet |
---|
266 | 296 | * |
---|
267 | 297 | * This function establishes a point-to-point connection from the local |
---|
268 | 298 | * computer to the target by allocating isochronous resources (channel and |
---|
.. | .. |
---|
270 | 300 | * When this function succeeds, the caller is responsible for starting |
---|
271 | 301 | * transmitting packets. |
---|
272 | 302 | */ |
---|
273 | | -int cmp_connection_establish(struct cmp_connection *c, |
---|
274 | | - unsigned int max_payload_bytes) |
---|
| 303 | +int cmp_connection_establish(struct cmp_connection *c) |
---|
275 | 304 | { |
---|
276 | 305 | int err; |
---|
277 | 306 | |
---|
278 | | - if (WARN_ON(c->connected)) |
---|
279 | | - return -EISCONN; |
---|
280 | | - |
---|
281 | | - c->speed = min(c->max_speed, |
---|
282 | | - fw_parent_device(c->resources.unit)->max_speed); |
---|
283 | | - |
---|
284 | 307 | mutex_lock(&c->mutex); |
---|
285 | 308 | |
---|
286 | | -retry_after_bus_reset: |
---|
287 | | - err = fw_iso_resources_allocate(&c->resources, |
---|
288 | | - max_payload_bytes, c->speed); |
---|
289 | | - if (err < 0) |
---|
290 | | - goto err_mutex; |
---|
| 309 | + if (WARN_ON(c->connected)) { |
---|
| 310 | + mutex_unlock(&c->mutex); |
---|
| 311 | + return -EISCONN; |
---|
| 312 | + } |
---|
291 | 313 | |
---|
| 314 | +retry_after_bus_reset: |
---|
292 | 315 | if (c->direction == CMP_OUTPUT) |
---|
293 | 316 | err = pcr_modify(c, opcr_set_modify, pcr_set_check, |
---|
294 | 317 | ABORT_ON_BUS_RESET); |
---|
.. | .. |
---|
297 | 320 | ABORT_ON_BUS_RESET); |
---|
298 | 321 | |
---|
299 | 322 | if (err == -EAGAIN) { |
---|
300 | | - fw_iso_resources_free(&c->resources); |
---|
301 | | - goto retry_after_bus_reset; |
---|
| 323 | + err = fw_iso_resources_update(&c->resources); |
---|
| 324 | + if (err >= 0) |
---|
| 325 | + goto retry_after_bus_reset; |
---|
302 | 326 | } |
---|
303 | | - if (err < 0) |
---|
304 | | - goto err_resources; |
---|
| 327 | + if (err >= 0) |
---|
| 328 | + c->connected = true; |
---|
305 | 329 | |
---|
306 | | - c->connected = true; |
---|
307 | | - |
---|
308 | | - mutex_unlock(&c->mutex); |
---|
309 | | - |
---|
310 | | - return 0; |
---|
311 | | - |
---|
312 | | -err_resources: |
---|
313 | | - fw_iso_resources_free(&c->resources); |
---|
314 | | -err_mutex: |
---|
315 | 330 | mutex_unlock(&c->mutex); |
---|
316 | 331 | |
---|
317 | 332 | return err; |
---|
.. | .. |
---|
351 | 366 | SUCCEED_ON_BUS_RESET); |
---|
352 | 367 | |
---|
353 | 368 | if (err < 0) |
---|
354 | | - goto err_resources; |
---|
| 369 | + goto err_unconnect; |
---|
355 | 370 | |
---|
356 | 371 | mutex_unlock(&c->mutex); |
---|
357 | 372 | |
---|
358 | 373 | return 0; |
---|
359 | 374 | |
---|
360 | | -err_resources: |
---|
361 | | - fw_iso_resources_free(&c->resources); |
---|
362 | 375 | err_unconnect: |
---|
363 | 376 | c->connected = false; |
---|
364 | 377 | mutex_unlock(&c->mutex); |
---|
.. | .. |
---|
394 | 407 | err = pcr_modify(c, pcr_break_modify, NULL, SUCCEED_ON_BUS_RESET); |
---|
395 | 408 | if (err < 0) |
---|
396 | 409 | cmp_error(c, "plug is still connected\n"); |
---|
397 | | - |
---|
398 | | - fw_iso_resources_free(&c->resources); |
---|
399 | 410 | |
---|
400 | 411 | c->connected = false; |
---|
401 | 412 | |
---|