Skip to content

Commit e36b289

Browse files
author
Maxim Levitsky
committed
net: mana: Add support for auxiliary device servicing events
JIRA: https://issues.redhat.com/browse/RHEL-80096 commit 505cc26 Author: Shiraz Saleem <shirazsaleem@microsoft.com> Date: Wed May 7 08:59:05 2025 -0700 net: mana: Add support for auxiliary device servicing events Handle soc servicing events which require the rdma auxiliary device resources to be cleaned up during a suspend, and re-initialized during a resume. Signed-off-by: Shiraz Saleem <shirazsaleem@microsoft.com> Signed-off-by: Konstantin Taranov <kotaranov@microsoft.com> Link: https://patch.msgid.link/1746633545-17653-5-git-send-email-kotaranov@linux.microsoft.com Signed-off-by: Leon Romanovsky <leon@kernel.org> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
1 parent 9c758ad commit e36b289

File tree

5 files changed

+126
-1
lines changed

5 files changed

+126
-1
lines changed

drivers/net/ethernet/microsoft/mana/gdma_main.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ static void mana_gd_process_eqe(struct gdma_queue *eq)
392392
case GDMA_EQE_HWC_INIT_EQ_ID_DB:
393393
case GDMA_EQE_HWC_INIT_DATA:
394394
case GDMA_EQE_HWC_INIT_DONE:
395+
case GDMA_EQE_HWC_SOC_SERVICE:
395396
case GDMA_EQE_RNIC_QP_FATAL:
396397
if (!eq->eq.callback)
397398
break;
@@ -1469,10 +1470,14 @@ static int mana_gd_setup(struct pci_dev *pdev)
14691470
mana_gd_init_registers(pdev);
14701471
mana_smc_init(&gc->shm_channel, gc->dev, gc->shm_base);
14711472

1473+
gc->service_wq = alloc_ordered_workqueue("gdma_service_wq", 0);
1474+
if (!gc->service_wq)
1475+
return -ENOMEM;
1476+
14721477
err = mana_gd_setup_irqs(pdev);
14731478
if (err) {
14741479
dev_err(gc->dev, "Failed to setup IRQs: %d\n", err);
1475-
return err;
1480+
goto free_workqueue;
14761481
}
14771482

14781483
err = mana_hwc_create_channel(gc);
@@ -1498,6 +1503,8 @@ static int mana_gd_setup(struct pci_dev *pdev)
14981503
mana_hwc_destroy_channel(gc);
14991504
remove_irq:
15001505
mana_gd_remove_irqs(pdev);
1506+
free_workqueue:
1507+
destroy_workqueue(gc->service_wq);
15011508
dev_err(&pdev->dev, "%s failed (error %d)\n", __func__, err);
15021509
return err;
15031510
}
@@ -1509,6 +1516,8 @@ static void mana_gd_cleanup(struct pci_dev *pdev)
15091516
mana_hwc_destroy_channel(gc);
15101517

15111518
mana_gd_remove_irqs(pdev);
1519+
1520+
destroy_workqueue(gc->service_wq);
15121521
dev_dbg(&pdev->dev, "mana gdma cleanup successful\n");
15131522
}
15141523

drivers/net/ethernet/microsoft/mana/hw_channel.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,13 @@ static void mana_hwc_handle_resp(struct hw_channel_context *hwc, u32 resp_len,
111111
static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self,
112112
struct gdma_event *event)
113113
{
114+
union hwc_init_soc_service_type service_data;
114115
struct hw_channel_context *hwc = ctx;
115116
struct gdma_dev *gd = hwc->gdma_dev;
116117
union hwc_init_type_data type_data;
117118
union hwc_init_eq_id_db eq_db;
118119
u32 type, val;
120+
int ret;
119121

120122
switch (event->type) {
121123
case GDMA_EQE_HWC_INIT_EQ_ID_DB:
@@ -198,7 +200,24 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self,
198200
}
199201

200202
break;
203+
case GDMA_EQE_HWC_SOC_SERVICE:
204+
service_data.as_uint32 = event->details[0];
205+
type = service_data.type;
201206

207+
switch (type) {
208+
case GDMA_SERVICE_TYPE_RDMA_SUSPEND:
209+
case GDMA_SERVICE_TYPE_RDMA_RESUME:
210+
ret = mana_rdma_service_event(gd->gdma_context, type);
211+
if (ret)
212+
dev_err(hwc->dev, "Failed to schedule adev service event: %d\n",
213+
ret);
214+
break;
215+
default:
216+
dev_warn(hwc->dev, "Received unknown SOC service type %u\n", type);
217+
break;
218+
}
219+
220+
break;
202221
default:
203222
dev_warn(hwc->dev, "Received unknown gdma event %u\n", event->type);
204223
/* Ignore unknown events, which should never happen. */

drivers/net/ethernet/microsoft/mana/mana_en.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2991,6 +2991,70 @@ static int add_adev(struct gdma_dev *gd, const char *name)
29912991
return ret;
29922992
}
29932993

2994+
static void mana_rdma_service_handle(struct work_struct *work)
2995+
{
2996+
struct mana_service_work *serv_work =
2997+
container_of(work, struct mana_service_work, work);
2998+
struct gdma_dev *gd = serv_work->gdma_dev;
2999+
struct device *dev = gd->gdma_context->dev;
3000+
int ret;
3001+
3002+
if (READ_ONCE(gd->rdma_teardown))
3003+
goto out;
3004+
3005+
switch (serv_work->event) {
3006+
case GDMA_SERVICE_TYPE_RDMA_SUSPEND:
3007+
if (!gd->adev || gd->is_suspended)
3008+
break;
3009+
3010+
remove_adev(gd);
3011+
gd->is_suspended = true;
3012+
break;
3013+
3014+
case GDMA_SERVICE_TYPE_RDMA_RESUME:
3015+
if (!gd->is_suspended)
3016+
break;
3017+
3018+
ret = add_adev(gd, "rdma");
3019+
if (ret)
3020+
dev_err(dev, "Failed to add adev on resume: %d\n", ret);
3021+
else
3022+
gd->is_suspended = false;
3023+
break;
3024+
3025+
default:
3026+
dev_warn(dev, "unknown adev service event %u\n",
3027+
serv_work->event);
3028+
break;
3029+
}
3030+
3031+
out:
3032+
kfree(serv_work);
3033+
}
3034+
3035+
int mana_rdma_service_event(struct gdma_context *gc, enum gdma_service_type event)
3036+
{
3037+
struct gdma_dev *gd = &gc->mana_ib;
3038+
struct mana_service_work *serv_work;
3039+
3040+
if (gd->dev_id.type != GDMA_DEVICE_MANA_IB) {
3041+
/* RDMA device is not detected on pci */
3042+
return 0;
3043+
}
3044+
3045+
serv_work = kzalloc(sizeof(*serv_work), GFP_ATOMIC);
3046+
if (!serv_work)
3047+
return -ENOMEM;
3048+
3049+
serv_work->event = event;
3050+
serv_work->gdma_dev = gd;
3051+
3052+
INIT_WORK(&serv_work->work, mana_rdma_service_handle);
3053+
queue_work(gc->service_wq, &serv_work->work);
3054+
3055+
return 0;
3056+
}
3057+
29943058
int mana_probe(struct gdma_dev *gd, bool resuming)
29953059
{
29963060
struct gdma_context *gc = gd->gdma_context;
@@ -3171,11 +3235,16 @@ int mana_rdma_probe(struct gdma_dev *gd)
31713235

31723236
void mana_rdma_remove(struct gdma_dev *gd)
31733237
{
3238+
struct gdma_context *gc = gd->gdma_context;
3239+
31743240
if (gd->dev_id.type != GDMA_DEVICE_MANA_IB) {
31753241
/* RDMA device is not detected on pci */
31763242
return;
31773243
}
31783244

3245+
WRITE_ONCE(gd->rdma_teardown, true);
3246+
flush_workqueue(gc->service_wq);
3247+
31793248
if (gd->adev)
31803249
remove_adev(gd);
31813250

include/net/mana/gdma.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ enum gdma_eqe_type {
6060
GDMA_EQE_HWC_INIT_DONE = 131,
6161
GDMA_EQE_HWC_SOC_RECONFIG = 132,
6262
GDMA_EQE_HWC_SOC_RECONFIG_DATA = 133,
63+
GDMA_EQE_HWC_SOC_SERVICE = 134,
6364
GDMA_EQE_RNIC_QP_FATAL = 176,
6465
};
6566

@@ -70,6 +71,18 @@ enum {
7071
GDMA_DEVICE_MANA_IB = 3,
7172
};
7273

74+
enum gdma_service_type {
75+
GDMA_SERVICE_TYPE_NONE = 0,
76+
GDMA_SERVICE_TYPE_RDMA_SUSPEND = 1,
77+
GDMA_SERVICE_TYPE_RDMA_RESUME = 2,
78+
};
79+
80+
struct mana_service_work {
81+
struct work_struct work;
82+
struct gdma_dev *gdma_dev;
83+
enum gdma_service_type event;
84+
};
85+
7386
struct gdma_resource {
7487
/* Protect the bitmap */
7588
spinlock_t lock;
@@ -224,6 +237,8 @@ struct gdma_dev {
224237
void *driver_data;
225238

226239
struct auxiliary_device *adev;
240+
bool is_suspended;
241+
bool rdma_teardown;
227242
};
228243

229244
/* MANA_PAGE_SIZE is the DMA unit */
@@ -409,6 +424,8 @@ struct gdma_context {
409424
struct gdma_dev mana_ib;
410425

411426
u64 pf_cap_flags1;
427+
428+
struct workqueue_struct *service_wq;
412429
};
413430

414431
static inline bool mana_gd_is_mana(struct gdma_dev *gd)
@@ -891,4 +908,6 @@ int mana_gd_destroy_dma_region(struct gdma_context *gc, u64 dma_region_handle);
891908
void mana_register_debugfs(void);
892909
void mana_unregister_debugfs(void);
893910

911+
int mana_rdma_service_event(struct gdma_context *gc, enum gdma_service_type event);
912+
894913
#endif /* _GDMA_H */

include/net/mana/hw_channel.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ union hwc_init_type_data {
4949
};
5050
}; /* HW DATA */
5151

52+
union hwc_init_soc_service_type {
53+
u32 as_uint32;
54+
55+
struct {
56+
u32 value : 28;
57+
u32 type : 4;
58+
};
59+
}; /* HW DATA */
60+
5261
struct hwc_rx_oob {
5362
u32 type : 6;
5463
u32 eom : 1;

0 commit comments

Comments
 (0)