Lines Matching full:c
5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
46 void cmp_error(struct cmp_connection *c, const char *fmt, ...) in cmp_error() argument
51 dev_err(&c->resources.unit->device, "%cPCR%u: %pV", in cmp_error()
52 (c->direction == CMP_INPUT) ? 'i' : 'o', in cmp_error()
53 c->pcr_index, &(struct va_format){ fmt, &va }); in cmp_error()
57 static u64 mpr_address(struct cmp_connection *c) in mpr_address() argument
59 if (c->direction == CMP_INPUT) in mpr_address()
65 static u64 pcr_address(struct cmp_connection *c) in pcr_address() argument
67 if (c->direction == CMP_INPUT) in pcr_address()
68 return CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index); in pcr_address()
70 return CSR_REGISTER_BASE + CSR_OPCR(c->pcr_index); in pcr_address()
73 static int pcr_modify(struct cmp_connection *c, in pcr_modify() argument
74 __be32 (*modify)(struct cmp_connection *c, __be32 old), in pcr_modify() argument
75 int (*check)(struct cmp_connection *c, __be32 pcr), in pcr_modify() argument
81 buffer[0] = c->last_pcr_value; in pcr_modify()
84 buffer[1] = modify(c, buffer[0]); in pcr_modify()
87 c->resources.unit, TCODE_LOCK_COMPARE_SWAP, in pcr_modify()
88 pcr_address(c), buffer, 8, in pcr_modify()
89 FW_FIXED_GENERATION | c->resources.generation); in pcr_modify()
102 err = check(c, buffer[0]); in pcr_modify()
107 c->last_pcr_value = buffer[1]; in pcr_modify()
115 * @c: the connection manager to initialize
120 int cmp_connection_init(struct cmp_connection *c, in cmp_connection_init() argument
129 c->direction = direction; in cmp_connection_init()
131 mpr_address(c), &mpr_be, 4, 0); in cmp_connection_init()
139 err = fw_iso_resources_init(&c->resources, unit); in cmp_connection_init()
143 c->connected = false; in cmp_connection_init()
144 mutex_init(&c->mutex); in cmp_connection_init()
145 c->last_pcr_value = cpu_to_be32(0x80000000); in cmp_connection_init()
146 c->pcr_index = pcr_index; in cmp_connection_init()
147 c->max_speed = (mpr & MPR_SPEED_MASK) >> MPR_SPEED_SHIFT; in cmp_connection_init()
148 if (c->max_speed == SCODE_BETA) in cmp_connection_init()
149 c->max_speed += (mpr & MPR_XSPEED_MASK) >> MPR_XSPEED_SHIFT; in cmp_connection_init()
157 * @c: the connection manager to be checked
160 int cmp_connection_check_used(struct cmp_connection *c, bool *used) in cmp_connection_check_used() argument
166 c->resources.unit, TCODE_READ_QUADLET_REQUEST, in cmp_connection_check_used()
167 pcr_address(c), &pcr, 4, 0); in cmp_connection_check_used()
178 * @c: the connection manager
180 void cmp_connection_destroy(struct cmp_connection *c) in cmp_connection_destroy() argument
182 WARN_ON(c->connected); in cmp_connection_destroy()
183 mutex_destroy(&c->mutex); in cmp_connection_destroy()
184 fw_iso_resources_destroy(&c->resources); in cmp_connection_destroy()
188 int cmp_connection_reserve(struct cmp_connection *c, in cmp_connection_reserve() argument
193 mutex_lock(&c->mutex); in cmp_connection_reserve()
195 if (WARN_ON(c->resources.allocated)) { in cmp_connection_reserve()
200 c->speed = min(c->max_speed, in cmp_connection_reserve()
201 fw_parent_device(c->resources.unit)->max_speed); in cmp_connection_reserve()
203 err = fw_iso_resources_allocate(&c->resources, max_payload_bytes, in cmp_connection_reserve()
204 c->speed); in cmp_connection_reserve()
206 mutex_unlock(&c->mutex); in cmp_connection_reserve()
212 void cmp_connection_release(struct cmp_connection *c) in cmp_connection_release() argument
214 mutex_lock(&c->mutex); in cmp_connection_release()
215 fw_iso_resources_free(&c->resources); in cmp_connection_release()
216 mutex_unlock(&c->mutex); in cmp_connection_release()
220 static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) in ipcr_set_modify() argument
226 ipcr |= cpu_to_be32(c->resources.channel << PCR_CHANNEL_SHIFT); in ipcr_set_modify()
231 static int get_overhead_id(struct cmp_connection *c) in get_overhead_id() argument
241 if (c->resources.bandwidth_overhead < (id << 5)) in get_overhead_id()
250 static __be32 opcr_set_modify(struct cmp_connection *c, __be32 opcr) in opcr_set_modify() argument
255 if (c->speed > SCODE_400) { in opcr_set_modify()
257 xspd = c->speed - SCODE_800; in opcr_set_modify()
259 spd = c->speed; in opcr_set_modify()
271 opcr |= cpu_to_be32(c->resources.channel << PCR_CHANNEL_SHIFT); in opcr_set_modify()
273 opcr |= cpu_to_be32(get_overhead_id(c) << OPCR_OVERHEAD_ID_SHIFT); in opcr_set_modify()
278 static int pcr_set_check(struct cmp_connection *c, __be32 pcr) in pcr_set_check() argument
282 cmp_error(c, "plug is already in use\n"); in pcr_set_check()
286 cmp_error(c, "plug is not on-line\n"); in pcr_set_check()
295 * @c: the connection manager
303 int cmp_connection_establish(struct cmp_connection *c) in cmp_connection_establish() argument
307 mutex_lock(&c->mutex); in cmp_connection_establish()
309 if (WARN_ON(c->connected)) { in cmp_connection_establish()
310 mutex_unlock(&c->mutex); in cmp_connection_establish()
315 if (c->direction == CMP_OUTPUT) in cmp_connection_establish()
316 err = pcr_modify(c, opcr_set_modify, pcr_set_check, in cmp_connection_establish()
319 err = pcr_modify(c, ipcr_set_modify, pcr_set_check, in cmp_connection_establish()
323 err = fw_iso_resources_update(&c->resources); in cmp_connection_establish()
328 c->connected = true; in cmp_connection_establish()
330 mutex_unlock(&c->mutex); in cmp_connection_establish()
338 * @c: the connection manager
346 int cmp_connection_update(struct cmp_connection *c) in cmp_connection_update() argument
350 mutex_lock(&c->mutex); in cmp_connection_update()
352 if (!c->connected) { in cmp_connection_update()
353 mutex_unlock(&c->mutex); in cmp_connection_update()
357 err = fw_iso_resources_update(&c->resources); in cmp_connection_update()
361 if (c->direction == CMP_OUTPUT) in cmp_connection_update()
362 err = pcr_modify(c, opcr_set_modify, pcr_set_check, in cmp_connection_update()
365 err = pcr_modify(c, ipcr_set_modify, pcr_set_check, in cmp_connection_update()
371 mutex_unlock(&c->mutex); in cmp_connection_update()
376 c->connected = false; in cmp_connection_update()
377 mutex_unlock(&c->mutex); in cmp_connection_update()
383 static __be32 pcr_break_modify(struct cmp_connection *c, __be32 pcr) in pcr_break_modify() argument
390 * @c: the connection manager
396 void cmp_connection_break(struct cmp_connection *c) in cmp_connection_break() argument
400 mutex_lock(&c->mutex); in cmp_connection_break()
402 if (!c->connected) { in cmp_connection_break()
403 mutex_unlock(&c->mutex); in cmp_connection_break()
407 err = pcr_modify(c, pcr_break_modify, NULL, SUCCEED_ON_BUS_RESET); in cmp_connection_break()
409 cmp_error(c, "plug is still connected\n"); in cmp_connection_break()
411 c->connected = false; in cmp_connection_break()
413 mutex_unlock(&c->mutex); in cmp_connection_break()