| .. | .. |
|---|
| 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 | |
|---|