Skip to content

Commit 8d8081c

Browse files
committed
cxl: Move mailbox related bits to the same context
Create a new 'struct cxl_mailbox' and move all mailbox related bits to it. This allows isolation of all CXL mailbox data in order to export some of the calls to external kernel callers and avoid exporting of CXL driver specific bits such has device states. The allocation of 'struct cxl_mailbox' is also split out with cxl_mailbox_init() so the mailbox can be created independently. Reviewed-by: Jonathan Cameron <[email protected]> Reviewed-by: Alejandro Lucero <[email protected]> Reviewed-by: Fan Ni <[email protected]> Reviewed-by: Alison Schofield <[email protected]> Reviewed-by: Ira Weiny <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Dave Jiang <[email protected]>
1 parent 40a895f commit 8d8081c

File tree

7 files changed

+177
-73
lines changed

7 files changed

+177
-73
lines changed

drivers/cxl/core/mbox.c

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -244,16 +244,17 @@ static const char *cxl_mem_opcode_to_name(u16 opcode)
244244
int cxl_internal_send_cmd(struct cxl_memdev_state *mds,
245245
struct cxl_mbox_cmd *mbox_cmd)
246246
{
247+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
247248
size_t out_size, min_out;
248249
int rc;
249250

250-
if (mbox_cmd->size_in > mds->payload_size ||
251-
mbox_cmd->size_out > mds->payload_size)
251+
if (mbox_cmd->size_in > cxl_mbox->payload_size ||
252+
mbox_cmd->size_out > cxl_mbox->payload_size)
252253
return -E2BIG;
253254

254255
out_size = mbox_cmd->size_out;
255256
min_out = mbox_cmd->min_out;
256-
rc = mds->mbox_send(mds, mbox_cmd);
257+
rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd);
257258
/*
258259
* EIO is reserved for a payload size mismatch and mbox_send()
259260
* may not return this error.
@@ -353,6 +354,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
353354
struct cxl_memdev_state *mds, u16 opcode,
354355
size_t in_size, size_t out_size, u64 in_payload)
355356
{
357+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
356358
*mbox = (struct cxl_mbox_cmd) {
357359
.opcode = opcode,
358360
.size_in = in_size,
@@ -374,7 +376,7 @@ static int cxl_mbox_cmd_ctor(struct cxl_mbox_cmd *mbox,
374376

375377
/* Prepare to handle a full payload for variable sized output */
376378
if (out_size == CXL_VARIABLE_PAYLOAD)
377-
mbox->size_out = mds->payload_size;
379+
mbox->size_out = cxl_mbox->payload_size;
378380
else
379381
mbox->size_out = out_size;
380382

@@ -398,6 +400,8 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
398400
const struct cxl_send_command *send_cmd,
399401
struct cxl_memdev_state *mds)
400402
{
403+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
404+
401405
if (send_cmd->raw.rsvd)
402406
return -EINVAL;
403407

@@ -406,7 +410,7 @@ static int cxl_to_mem_cmd_raw(struct cxl_mem_command *mem_cmd,
406410
* gets passed along without further checking, so it must be
407411
* validated here.
408412
*/
409-
if (send_cmd->out.size > mds->payload_size)
413+
if (send_cmd->out.size > cxl_mbox->payload_size)
410414
return -EINVAL;
411415

412416
if (!cxl_mem_raw_command_allowed(send_cmd->raw.opcode))
@@ -494,6 +498,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
494498
struct cxl_memdev_state *mds,
495499
const struct cxl_send_command *send_cmd)
496500
{
501+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
497502
struct cxl_mem_command mem_cmd;
498503
int rc;
499504

@@ -505,7 +510,7 @@ static int cxl_validate_cmd_from_user(struct cxl_mbox_cmd *mbox_cmd,
505510
* supports, but output can be arbitrarily large (simply write out as
506511
* much data as the hardware provides).
507512
*/
508-
if (send_cmd->in.size > mds->payload_size)
513+
if (send_cmd->in.size > cxl_mbox->payload_size)
509514
return -EINVAL;
510515

511516
/* Sanitize and construct a cxl_mem_command */
@@ -591,6 +596,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds,
591596
u64 out_payload, s32 *size_out,
592597
u32 *retval)
593598
{
599+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
594600
struct device *dev = mds->cxlds.dev;
595601
int rc;
596602

@@ -601,7 +607,7 @@ static int handle_mailbox_cmd_from_user(struct cxl_memdev_state *mds,
601607
cxl_mem_opcode_to_name(mbox_cmd->opcode),
602608
mbox_cmd->opcode, mbox_cmd->size_in);
603609

604-
rc = mds->mbox_send(mds, mbox_cmd);
610+
rc = cxl_mbox->mbox_send(cxl_mbox, mbox_cmd);
605611
if (rc)
606612
goto out;
607613

@@ -659,11 +665,12 @@ int cxl_send_cmd(struct cxl_memdev *cxlmd, struct cxl_send_command __user *s)
659665
static int cxl_xfer_log(struct cxl_memdev_state *mds, uuid_t *uuid,
660666
u32 *size, u8 *out)
661667
{
668+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
662669
u32 remaining = *size;
663670
u32 offset = 0;
664671

665672
while (remaining) {
666-
u32 xfer_size = min_t(u32, remaining, mds->payload_size);
673+
u32 xfer_size = min_t(u32, remaining, cxl_mbox->payload_size);
667674
struct cxl_mbox_cmd mbox_cmd;
668675
struct cxl_mbox_get_log log;
669676
int rc;
@@ -752,17 +759,18 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
752759

753760
static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_memdev_state *mds)
754761
{
762+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
755763
struct cxl_mbox_get_supported_logs *ret;
756764
struct cxl_mbox_cmd mbox_cmd;
757765
int rc;
758766

759-
ret = kvmalloc(mds->payload_size, GFP_KERNEL);
767+
ret = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL);
760768
if (!ret)
761769
return ERR_PTR(-ENOMEM);
762770

763771
mbox_cmd = (struct cxl_mbox_cmd) {
764772
.opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS,
765-
.size_out = mds->payload_size,
773+
.size_out = cxl_mbox->payload_size,
766774
.payload_out = ret,
767775
/* At least the record number field must be valid */
768776
.min_out = 2,
@@ -910,6 +918,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds,
910918
enum cxl_event_log_type log,
911919
struct cxl_get_event_payload *get_pl)
912920
{
921+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
913922
struct cxl_mbox_clear_event_payload *payload;
914923
u16 total = le16_to_cpu(get_pl->record_count);
915924
u8 max_handles = CXL_CLEAR_EVENT_MAX_HANDLES;
@@ -920,8 +929,8 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds,
920929
int i;
921930

922931
/* Payload size may limit the max handles */
923-
if (pl_size > mds->payload_size) {
924-
max_handles = (mds->payload_size - sizeof(*payload)) /
932+
if (pl_size > cxl_mbox->payload_size) {
933+
max_handles = (cxl_mbox->payload_size - sizeof(*payload)) /
925934
sizeof(__le16);
926935
pl_size = struct_size(payload, handles, max_handles);
927936
}
@@ -979,6 +988,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds,
979988
static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
980989
enum cxl_event_log_type type)
981990
{
991+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
982992
struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
983993
struct device *dev = mds->cxlds.dev;
984994
struct cxl_get_event_payload *payload;
@@ -995,7 +1005,7 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
9951005
.payload_in = &log_type,
9961006
.size_in = sizeof(log_type),
9971007
.payload_out = payload,
998-
.size_out = mds->payload_size,
1008+
.size_out = cxl_mbox->payload_size,
9991009
.min_out = struct_size(payload, records, 0),
10001010
};
10011011

@@ -1327,6 +1337,7 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
13271337
struct cxl_region *cxlr)
13281338
{
13291339
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
1340+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
13301341
struct cxl_mbox_poison_out *po;
13311342
struct cxl_mbox_poison_in pi;
13321343
int nr_records = 0;
@@ -1345,7 +1356,7 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
13451356
.opcode = CXL_MBOX_OP_GET_POISON,
13461357
.size_in = sizeof(pi),
13471358
.payload_in = &pi,
1348-
.size_out = mds->payload_size,
1359+
.size_out = cxl_mbox->payload_size,
13491360
.payload_out = po,
13501361
.min_out = struct_size(po, record, 0),
13511362
};
@@ -1381,7 +1392,9 @@ static void free_poison_buf(void *buf)
13811392
/* Get Poison List output buffer is protected by mds->poison.lock */
13821393
static int cxl_poison_alloc_buf(struct cxl_memdev_state *mds)
13831394
{
1384-
mds->poison.list_out = kvmalloc(mds->payload_size, GFP_KERNEL);
1395+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
1396+
1397+
mds->poison.list_out = kvmalloc(cxl_mbox->payload_size, GFP_KERNEL);
13851398
if (!mds->poison.list_out)
13861399
return -ENOMEM;
13871400

@@ -1407,6 +1420,19 @@ int cxl_poison_state_init(struct cxl_memdev_state *mds)
14071420
}
14081421
EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL);
14091422

1423+
int cxl_mailbox_init(struct cxl_mailbox *cxl_mbox, struct device *host)
1424+
{
1425+
if (!cxl_mbox || !host)
1426+
return -EINVAL;
1427+
1428+
cxl_mbox->host = host;
1429+
mutex_init(&cxl_mbox->mbox_mutex);
1430+
rcuwait_init(&cxl_mbox->mbox_wait);
1431+
1432+
return 0;
1433+
}
1434+
EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, CXL);
1435+
14101436
struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
14111437
{
14121438
struct cxl_memdev_state *mds;
@@ -1417,7 +1443,6 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
14171443
return ERR_PTR(-ENOMEM);
14181444
}
14191445

1420-
mutex_init(&mds->mbox_mutex);
14211446
mutex_init(&mds->event.log_lock);
14221447
mds->cxlds.dev = dev;
14231448
mds->cxlds.reg_map.host = dev;

drivers/cxl/core/memdev.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static ssize_t payload_max_show(struct device *dev,
5858

5959
if (!mds)
6060
return sysfs_emit(buf, "\n");
61-
return sysfs_emit(buf, "%zu\n", mds->payload_size);
61+
return sysfs_emit(buf, "%zu\n", cxlds->cxl_mbox.payload_size);
6262
}
6363
static DEVICE_ATTR_RO(payload_max);
6464

@@ -124,15 +124,16 @@ static ssize_t security_state_show(struct device *dev,
124124
{
125125
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
126126
struct cxl_dev_state *cxlds = cxlmd->cxlds;
127+
struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox;
127128
struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds);
128129
unsigned long state = mds->security.state;
129130
int rc = 0;
130131

131132
/* sync with latest submission state */
132-
mutex_lock(&mds->mbox_mutex);
133+
mutex_lock(&cxl_mbox->mbox_mutex);
133134
if (mds->security.sanitize_active)
134135
rc = sysfs_emit(buf, "sanitize\n");
135-
mutex_unlock(&mds->mbox_mutex);
136+
mutex_unlock(&cxl_mbox->mbox_mutex);
136137
if (rc)
137138
return rc;
138139

@@ -829,12 +830,13 @@ static enum fw_upload_err cxl_fw_prepare(struct fw_upload *fwl, const u8 *data,
829830
{
830831
struct cxl_memdev_state *mds = fwl->dd_handle;
831832
struct cxl_mbox_transfer_fw *transfer;
833+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
832834

833835
if (!size)
834836
return FW_UPLOAD_ERR_INVALID_SIZE;
835837

836838
mds->fw.oneshot = struct_size(transfer, data, size) <
837-
mds->payload_size;
839+
cxl_mbox->payload_size;
838840

839841
if (cxl_mem_get_fw_info(mds))
840842
return FW_UPLOAD_ERR_HW_ERROR;
@@ -854,6 +856,7 @@ static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data,
854856
{
855857
struct cxl_memdev_state *mds = fwl->dd_handle;
856858
struct cxl_dev_state *cxlds = &mds->cxlds;
859+
struct cxl_mailbox *cxl_mbox = &cxlds->cxl_mbox;
857860
struct cxl_memdev *cxlmd = cxlds->cxlmd;
858861
struct cxl_mbox_transfer_fw *transfer;
859862
struct cxl_mbox_cmd mbox_cmd;
@@ -877,7 +880,7 @@ static enum fw_upload_err cxl_fw_write(struct fw_upload *fwl, const u8 *data,
877880
* sizeof(*transfer) is 128. These constraints imply that @cur_size
878881
* will always be 128b aligned.
879882
*/
880-
cur_size = min_t(size_t, size, mds->payload_size - sizeof(*transfer));
883+
cur_size = min_t(size_t, size, cxl_mbox->payload_size - sizeof(*transfer));
881884

882885
remaining = size - cur_size;
883886
size_in = struct_size(transfer, data, cur_size);
@@ -1059,16 +1062,17 @@ EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, CXL);
10591062
static void sanitize_teardown_notifier(void *data)
10601063
{
10611064
struct cxl_memdev_state *mds = data;
1065+
struct cxl_mailbox *cxl_mbox = &mds->cxlds.cxl_mbox;
10621066
struct kernfs_node *state;
10631067

10641068
/*
10651069
* Prevent new irq triggered invocations of the workqueue and
10661070
* flush inflight invocations.
10671071
*/
1068-
mutex_lock(&mds->mbox_mutex);
1072+
mutex_lock(&cxl_mbox->mbox_mutex);
10691073
state = mds->security.sanitize_node;
10701074
mds->security.sanitize_node = NULL;
1071-
mutex_unlock(&mds->mbox_mutex);
1075+
mutex_unlock(&cxl_mbox->mbox_mutex);
10721076

10731077
cancel_delayed_work_sync(&mds->security.poll_dwork);
10741078
sysfs_put(state);

drivers/cxl/cxlmem.h

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
#ifndef __CXL_MEM_H__
44
#define __CXL_MEM_H__
55
#include <uapi/linux/cxl_mem.h>
6+
#include <linux/pci.h>
67
#include <linux/cdev.h>
78
#include <linux/uuid.h>
8-
#include <linux/rcuwait.h>
99
#include <linux/node.h>
1010
#include <cxl/event.h>
11+
#include <cxl/mailbox.h>
1112
#include "cxl.h"
1213

1314
/* CXL 2.0 8.2.8.5.1.1 Memory Device Status Register */
@@ -424,6 +425,7 @@ struct cxl_dpa_perf {
424425
* @ram_res: Active Volatile memory capacity configuration
425426
* @serial: PCIe Device Serial Number
426427
* @type: Generic Memory Class device or Vendor Specific Memory device
428+
* @cxl_mbox: CXL mailbox context
427429
*/
428430
struct cxl_dev_state {
429431
struct device *dev;
@@ -438,8 +440,14 @@ struct cxl_dev_state {
438440
struct resource ram_res;
439441
u64 serial;
440442
enum cxl_devtype type;
443+
struct cxl_mailbox cxl_mbox;
441444
};
442445

446+
static inline struct cxl_dev_state *mbox_to_cxlds(struct cxl_mailbox *cxl_mbox)
447+
{
448+
return dev_get_drvdata(cxl_mbox->host);
449+
}
450+
443451
/**
444452
* struct cxl_memdev_state - Generic Type-3 Memory Device Class driver data
445453
*
@@ -448,11 +456,8 @@ struct cxl_dev_state {
448456
* the functionality related to that like Identify Memory Device and Get
449457
* Partition Info
450458
* @cxlds: Core driver state common across Type-2 and Type-3 devices
451-
* @payload_size: Size of space for payload
452-
* (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register)
453459
* @lsa_size: Size of Label Storage Area
454460
* (CXL 2.0 8.2.9.5.1.1 Identify Memory Device)
455-
* @mbox_mutex: Mutex to synchronize mailbox access.
456461
* @firmware_version: Firmware version for the memory device.
457462
* @enabled_cmds: Hardware commands found enabled in CEL.
458463
* @exclusive_cmds: Commands that are kernel-internal only
@@ -470,17 +475,13 @@ struct cxl_dev_state {
470475
* @poison: poison driver state info
471476
* @security: security driver state info
472477
* @fw: firmware upload / activation state
473-
* @mbox_wait: RCU wait for mbox send completely
474-
* @mbox_send: @dev specific transport for transmitting mailbox commands
475478
*
476479
* See CXL 3.0 8.2.9.8.2 Capacity Configuration and Label Storage for
477480
* details on capacity parameters.
478481
*/
479482
struct cxl_memdev_state {
480483
struct cxl_dev_state cxlds;
481-
size_t payload_size;
482484
size_t lsa_size;
483-
struct mutex mbox_mutex; /* Protects device mailbox and firmware */
484485
char firmware_version[0x10];
485486
DECLARE_BITMAP(enabled_cmds, CXL_MEM_COMMAND_ID_MAX);
486487
DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
@@ -500,10 +501,6 @@ struct cxl_memdev_state {
500501
struct cxl_poison_state poison;
501502
struct cxl_security_state security;
502503
struct cxl_fw_state fw;
503-
504-
struct rcuwait mbox_wait;
505-
int (*mbox_send)(struct cxl_memdev_state *mds,
506-
struct cxl_mbox_cmd *cmd);
507504
};
508505

509506
static inline struct cxl_memdev_state *

0 commit comments

Comments
 (0)