Skip to content

Commit 27d37bc

Browse files
jannaumarcan
authored andcommitted
drm: apple: afk: Use linear array of services
"Channel numbers" as received by AFK/EPIC are constantly increasing over restarts of the endpoint. Use a linear array of services and match based on the channel number. The number of services per endpoint is too small to make a difference. Signed-off-by: Janne Grunau <j@jannau.net>
1 parent f237c83 commit 27d37bc

2 files changed

Lines changed: 54 additions & 19 deletions

File tree

drivers/gpu/drm/apple/afk.c

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -199,26 +199,43 @@ afk_match_service(struct apple_dcp_afkep *ep, const char *name)
199199
return NULL;
200200
}
201201

202+
static struct apple_epic_service *afk_epic_find_service(struct apple_dcp_afkep *ep,
203+
u32 channel)
204+
{
205+
for (u32 i = 0; i < ep->num_channels; i++)
206+
if (ep->services[i].enabled && ep->services[i].channel == channel)
207+
return &ep->services[i];
208+
209+
return NULL;
210+
}
211+
202212
static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
203213
u8 *payload, size_t payload_size)
204214
{
205215
char name[32];
206216
s64 epic_unit = -1;
217+
u32 ch_idx;
207218
const char *service_name = name;
208219
const char *epic_name = NULL, *epic_class = NULL;
209220
const struct apple_epic_service_ops *ops;
210221
struct dcp_parse_ctx ctx;
211222
u8 *props = payload + sizeof(name);
212223
size_t props_size = payload_size - sizeof(name);
213224

214-
WARN_ON(ep->services[channel].enabled);
225+
WARN_ON(afk_epic_find_service(ep, channel));
215226

216227
if (payload_size < sizeof(name)) {
217228
dev_err(ep->dcp->dev, "AFK[ep:%02x]: payload too small: %lx\n",
218229
ep->endpoint, payload_size);
219230
return;
220231
}
221232

233+
if (ep->num_channels >= AFK_MAX_CHANNEL) {
234+
dev_err(ep->dcp->dev, "AFK[ep:%02x]: too many enabled services!\n",
235+
ep->endpoint);
236+
return;
237+
}
238+
222239
strlcpy(name, payload, sizeof(name));
223240

224241
/*
@@ -255,13 +272,14 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
255272
goto free;
256273
}
257274

258-
spin_lock_init(&ep->services[channel].lock);
259-
ep->services[channel].enabled = true;
260-
ep->services[channel].ops = ops;
261-
ep->services[channel].ep = ep;
262-
ep->services[channel].channel = channel;
263-
ep->services[channel].cmd_tag = 0;
264-
ops->init(&ep->services[channel], epic_name, epic_class, epic_unit);
275+
ch_idx = ep->num_channels++;
276+
spin_lock_init(&ep->services[ch_idx].lock);
277+
ep->services[ch_idx].enabled = true;
278+
ep->services[ch_idx].ops = ops;
279+
ep->services[ch_idx].ep = ep;
280+
ep->services[ch_idx].channel = channel;
281+
ep->services[ch_idx].cmd_tag = 0;
282+
ops->init(&ep->services[ch_idx], epic_name, epic_class, epic_unit);
265283
dev_info(ep->dcp->dev, "AFK[ep:%02x]: new service %s on channel %d\n",
266284
ep->endpoint, service_name, channel);
267285
free:
@@ -271,11 +289,16 @@ static void afk_recv_handle_init(struct apple_dcp_afkep *ep, u32 channel,
271289

272290
static void afk_recv_handle_teardown(struct apple_dcp_afkep *ep, u32 channel)
273291
{
274-
struct apple_epic_service *service = &ep->services[channel];
292+
struct apple_epic_service *service;
275293
const struct apple_epic_service_ops *ops;
276294
unsigned long flags;
277295

278-
WARN_ON(!service->enabled);
296+
service = afk_epic_find_service(ep, channel);
297+
if (!service) {
298+
dev_warn(ep->dcp->dev, "AFK[ep:%02x]: teardown for disabled channel %u\n",
299+
ep->endpoint, channel);
300+
return;
301+
}
279302

280303
// TODO: think through what locking is necessary
281304
spin_lock_irqsave(&service->lock, flags);
@@ -291,13 +314,20 @@ static void afk_recv_handle_reply(struct apple_dcp_afkep *ep, u32 channel,
291314
u16 tag, void *payload, size_t payload_size)
292315
{
293316
struct epic_cmd *cmd = payload;
294-
struct apple_epic_service *service = &ep->services[channel];
317+
struct apple_epic_service *service;
295318
unsigned long flags;
296319
u8 idx = tag & 0xff;
297320
void *rxbuf, *txbuf;
298321
dma_addr_t rxbuf_dma, txbuf_dma;
299322
size_t rxlen, txlen;
300323

324+
service = afk_epic_find_service(ep, channel);
325+
if (!service) {
326+
dev_warn(ep->dcp->dev, "AFK[ep:%02x]: command reply on disabled channel %u\n",
327+
ep->endpoint, channel);
328+
return;
329+
}
330+
301331
if (payload_size < sizeof(*cmd)) {
302332
dev_err(ep->dcp->dev,
303333
"AFK[ep:%02x]: command reply on channel %d too small: %ld\n",
@@ -369,7 +399,14 @@ static void afk_recv_handle_std_service(struct apple_dcp_afkep *ep, u32 channel,
369399
struct epic_sub_hdr *eshdr,
370400
void *payload, size_t payload_size)
371401
{
372-
struct apple_epic_service *service = &ep->services[channel];
402+
struct apple_epic_service *service = afk_epic_find_service(ep, channel);
403+
404+
if (!service) {
405+
dev_warn(ep->dcp->dev,
406+
"AFK[ep:%02x]: std service notify on disabled channel %u\n",
407+
ep->endpoint, channel);
408+
return;
409+
}
373410

374411
if (type == EPIC_TYPE_NOTIFY && eshdr->category == EPIC_CAT_NOTIFY) {
375412
struct epic_std_service_ap_call *call = payload;
@@ -436,6 +473,7 @@ static void afk_recv_handle_std_service(struct apple_dcp_afkep *ep, u32 channel,
436473
static void afk_recv_handle(struct apple_dcp_afkep *ep, u32 channel, u32 type,
437474
u8 *data, size_t data_size)
438475
{
476+
struct apple_epic_service *service;
439477
struct epic_hdr *ehdr = (struct epic_hdr *)data;
440478
struct epic_sub_hdr *eshdr =
441479
(struct epic_sub_hdr *)(data + sizeof(*ehdr));
@@ -452,13 +490,9 @@ static void afk_recv_handle(struct apple_dcp_afkep *ep, u32 channel, u32 type,
452490

453491
trace_afk_recv_handle(ep, channel, type, data_size, ehdr, eshdr);
454492

455-
if (channel >= AFK_MAX_CHANNEL) {
456-
dev_err(ep->dcp->dev, "AFK[ep:%02x]: channel %d out of bounds\n",
457-
ep->endpoint, channel);
458-
return;
459-
}
493+
service = afk_epic_find_service(ep, channel);
460494

461-
if (!ep->services[channel].enabled) {
495+
if (!service) {
462496
if (type != EPIC_TYPE_NOTIFY) {
463497
dev_err(ep->dcp->dev,
464498
"AFK[ep:%02x]: expected notify but got 0x%x on channel %d\n",
@@ -481,7 +515,7 @@ static void afk_recv_handle(struct apple_dcp_afkep *ep, u32 channel, u32 type,
481515
return afk_recv_handle_init(ep, channel, payload, payload_size);
482516
}
483517

484-
if (!ep->services[channel].enabled) {
518+
if (!service) {
485519
dev_err(ep->dcp->dev, "AFK[ep:%02x]: channel %d has no service\n",
486520
ep->endpoint, channel);
487521
return;

drivers/gpu/drm/apple/afk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ struct apple_dcp_afkep {
169169

170170
const struct apple_epic_service_ops *ops;
171171
struct apple_epic_service services[AFK_MAX_CHANNEL];
172+
u32 num_channels;
172173
};
173174

174175
struct apple_dcp_afkep *afk_init(struct apple_dcp *dcp, u32 endpoint,

0 commit comments

Comments
 (0)