From: Ian Munsie <hidden> Date: 2016-03-08 01:50:03
From: Ian Munsie <redacted>
This adds an afu_driver_ops structure with event_pending and
deliver_event callbacks. An AFU driver such as cxlflash can fill these
out and associate it with a context to enable passing custom AFU
specific events to userspace.
The cxl driver will call event_pending() during poll, select, read, etc.
calls to check if an AFU driver specific event is pending, and will call
deliver_event() to deliver that event. This way, the cxl driver takes
care of all the usual locking semantics around these calls and handles
all the generic cxl events, so that the AFU driver only needs to worry
about it's own events.
The deliver_event() call is passed a struct cxl_event buffer to fill in.
The header will already be filled in for an AFU driver event, and the
AFU driver is expected to expand the header.size as necessary (up to
max_size, defined by struct cxl_event_afu_driver_reserved) and fill out
it's own information.
Since AFU drivers provide their own means for userspace to obtain the
AFU file descriptor (i.e. cxlflash uses an ioctl on their scsi file
descriptor to obtain the AFU file descriptor) and the generic cxl driver
will never use this event, the ABI of the event is up to each individual
AFU driver.
Signed-off-by: Ian Munsie <redacted>
---
Changes since v2:
- Fixed some typos spotted by Matt Ochs
Changes since v1:
- Rebased on upstream
- Bumped cxl api version to 3
- Addressed comments from mpe:
- Clarified commit message & some comments
- Mentioned 'cxlflash' as a possible user of this event
- Check driver ops on registration and warn if missing calls
- Remove redundant checks where driver ops is used
- Simplified ctx_event_pending and removed underscore version
- Changed deliver_event to take the context as the first argument
drivers/misc/cxl/Kconfig | 5 +++++
drivers/misc/cxl/api.c | 8 ++++++++
drivers/misc/cxl/cxl.h | 6 +++++-
drivers/misc/cxl/file.c | 36 +++++++++++++++++++++++++-----------
include/misc/cxl.h | 29 +++++++++++++++++++++++++++++
include/uapi/misc/cxl.h | 22 ++++++++++++++++++++++
6 files changed, 94 insertions(+), 12 deletions(-)
@@ -485,6 +486,9 @@ struct cxl_context {boolpending_fault;boolpending_afu_err;+/* Used by AFU drivers for driver specific event delivery */+structcxl_afu_driver_ops*afu_driver_ops;+structrcu_headrcu;};
@@ -307,8 +318,7 @@ unsigned int afu_poll(struct file *file, struct poll_table_struct *poll)pr_devel("afu_poll wait done pe: %i\n",ctx->pe);spin_lock_irqsave(&ctx->lock,flags);-if(ctx->pending_irq||ctx->pending_fault||-ctx->pending_afu_err)+if(ctx_event_pending(ctx))mask|=POLLIN|POLLRDNORM;elseif(ctx->status==CLOSED)/* Only error on closed when there are no futher events pending
From: Ian Munsie <hidden> Date: 2016-03-08 01:50:11
From: Michael Neuling <redacted>
This provides AFU drivers a means to associate private data with a cxl
context. This is particularly intended for make the new callbacks for
driver specific events easier for AFU drivers to use, as they can easily
get back to any private data structures they may use.
Signed-off-by: Michael Neuling <redacted>
Signed-off-by: Ian Munsie <redacted>
Reviewed-by: Matthew R. Ochs <redacted>
---
No changes since v1, added Matt Ochs reviewed-by tag.
drivers/misc/cxl/api.c | 21 +++++++++++++++++++++
drivers/misc/cxl/cxl.h | 3 +++
include/misc/cxl.h | 7 +++++++
3 files changed, 31 insertions(+)
@@ -454,6 +454,9 @@ struct cxl_context {/* Only used in PR mode */u64process_token;+/* driver private data */+void*priv;+unsignedlong*irq_bitmap;/* Accessed from IRQ context */structcxl_irq_rangesirqs;structlist_headirq_names;
From: Matt Ochs <hidden> Date: 2016-03-08 04:06:44
On Mar 7, 2016, at 7:48 PM, Ian Munsie [off-list ref] wrote:
From: Ian Munsie <redacted>
This adds an afu_driver_ops structure with event_pending and
deliver_event callbacks. An AFU driver such as cxlflash can fill these
out and associate it with a context to enable passing custom AFU
specific events to userspace.
The cxl driver will call event_pending() during poll, select, read, etc.
calls to check if an AFU driver specific event is pending, and will call
deliver_event() to deliver that event. This way, the cxl driver takes
care of all the usual locking semantics around these calls and handles
all the generic cxl events, so that the AFU driver only needs to worry
about it's own events.
The deliver_event() call is passed a struct cxl_event buffer to fill in.
The header will already be filled in for an AFU driver event, and the
AFU driver is expected to expand the header.size as necessary (up to
max_size, defined by struct cxl_event_afu_driver_reserved) and fill out
it's own information.
Since AFU drivers provide their own means for userspace to obtain the
AFU file descriptor (i.e. cxlflash uses an ioctl on their scsi file
descriptor to obtain the AFU file descriptor) and the generic cxl driver
will never use this event, the ABI of the event is up to each individual
AFU driver.
Signed-off-by: Ian Munsie <redacted>
From: Andrew Donnellan <hidden> Date: 2016-03-08 08:01:08
On 08/03/16 12:48, Ian Munsie wrote:
From: Ian Munsie <redacted>
This adds an afu_driver_ops structure with event_pending and
deliver_event callbacks. An AFU driver such as cxlflash can fill these
out and associate it with a context to enable passing custom AFU
specific events to userspace.
The cxl driver will call event_pending() during poll, select, read, etc.
calls to check if an AFU driver specific event is pending, and will call
deliver_event() to deliver that event. This way, the cxl driver takes
care of all the usual locking semantics around these calls and handles
all the generic cxl events, so that the AFU driver only needs to worry
about it's own events.
The deliver_event() call is passed a struct cxl_event buffer to fill in.
The header will already be filled in for an AFU driver event, and the
AFU driver is expected to expand the header.size as necessary (up to
max_size, defined by struct cxl_event_afu_driver_reserved) and fill out
it's own information.
Since AFU drivers provide their own means for userspace to obtain the
AFU file descriptor (i.e. cxlflash uses an ioctl on their scsi file
descriptor to obtain the AFU file descriptor) and the generic cxl driver
will never use this event, the ABI of the event is up to each individual
AFU driver.
Signed-off-by: Ian Munsie <redacted>
Reviewed-by: Andrew Donnellan <redacted>
--
Andrew Donnellan Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com Australia Development Lab, Canberra
+61 2 6201 8874 (work) IBM Australia Limited
From: Andrew Donnellan <hidden> Date: 2016-03-08 08:01:30
On 08/03/16 12:48, Ian Munsie wrote:
From: Michael Neuling <redacted>
This provides AFU drivers a means to associate private data with a cxl
context. This is particularly intended for make the new callbacks for
driver specific events easier for AFU drivers to use, as they can easily
get back to any private data structures they may use.
Signed-off-by: Michael Neuling <redacted>
Signed-off-by: Ian Munsie <redacted>
Reviewed-by: Matthew R. Ochs <redacted>
Looks good to me.
Reviewed-by: Andrew Donnellan <redacted>
--
Andrew Donnellan Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com Australia Development Lab, Canberra
+61 2 6201 8874 (work) IBM Australia Limited
So on afu_read(), we may call afu_driver_ops->event_pending() twice
before calling afu_driver_ops->deliver_event(). Actually, in the
(likely) scenario where there's only an afu_driver event pending, we
*will* call afu_driver_ops->event_pending() twice. Wouldn't it make
sense to cache it then?
It would also avoid entering
WARN(1, "afu_read must be buggy\n");
if the driver changes its mind between the 2 calls :-)
Fred
I would recommend adding a "struct module *" member to afu_driver_ops
and doing a __module_get on to it here and module_put when we destroy
the context. Since these callbacks will be residing within an external
module .text region hence it should stay in the memory until the context
is alive.
Should also check if ctx->afu_driver_ops->event_pending is NULL before
calling it.
+/*
+ * AFU driver ops allows an AFU driver to create their own events to pass to
+ * userspace through the file descriptor as a simpler alternative to overriding
+ * the read() and poll() calls that works with the generic cxl events. These
+ * events are given priority over the generic cxl events, so they will be
+ * delivered first if multiple types of events are pending.
+ *
+ * event_pending() will be called by the cxl driver to check if an event is
+ * pending (e.g. in select/poll/read calls).
+ *
+ * deliver_event() will be called to fill out a cxl_event structure with the
+ * driver specific event. The header will already have the type and
+ * process_element fields filled in, and header.size will be set to
+ * sizeof(struct cxl_event_header). The AFU driver can extend that size up to
+ * max_size (if an afu driver requires more space, they should submit a patch
+ * increasing the size in the struct cxl_event_afu_driver_reserved definition).
+ *
+ * Both of these calls are made with a spin lock held, so they must not sleep.
+ */
+struct cxl_afu_driver_ops {
+ bool (*event_pending) (struct cxl_context *ctx);
+ void (*deliver_event) (struct cxl_context *ctx,
+ struct cxl_event *event, size_t max_size);
+};
+
I would propose these two apis.
/*
* fetches an event from the driver event queue. NULL means that queue
* is empty. Can sleep if needed. The memory for cxl_event is allocated
* by module being called. Hence it can be potentially be larger then
* sizeof(struct cxl_event). Multiple calls to this should return same
* pointer untill ack_event is called.
*/
struct cxl_event * fetch_event(struct cxl_context * ctx);
/*
* Returns and acknowledge the struct cxl_event * back to the driver
* which can then free it or maybe put it back in a kmem_cache. This
* should be called once we have completely returned the current
* struct cxl_event from the readcall
*/
void ack_event(struct cxl_context * ctx, struct cxl_event *);
I think above apis would give us more flexbility in the future when
drivers would want to send larger events without breaking the abi.
Cheers,
~ Vaibhav
From: Matt Ochs <hidden> Date: 2016-03-09 16:44:02
On Mar 9, 2016, at 8:37 AM, Vaibhav Jain [off-list ref] =
wrote:
quoted
+/*
+ * AFU driver ops allows an AFU driver to create their own events to =
pass to
quoted
+ * userspace through the file descriptor as a simpler alternative to =
overriding
quoted
+ * the read() and poll() calls that works with the generic cxl =
events. These
quoted
+ * events are given priority over the generic cxl events, so they =
will be
quoted
+ * delivered first if multiple types of events are pending.
+ *
+ * event_pending() will be called by the cxl driver to check if an =
event is
quoted
+ * pending (e.g. in select/poll/read calls).
+ *
+ * deliver_event() will be called to fill out a cxl_event structure =
with the
quoted
+ * driver specific event. The header will already have the type and
+ * process_element fields filled in, and header.size will be set to
+ * sizeof(struct cxl_event_header). The AFU driver can extend that =
size up to
quoted
+ * max_size (if an afu driver requires more space, they should =
submit a patch
quoted
+ * increasing the size in the struct cxl_event_afu_driver_reserved =
definition).
quoted
+ *
+ * Both of these calls are made with a spin lock held, so they must =
=20
I would propose these two apis.
=20
/*
* fetches an event from the driver event queue. NULL means that queue
* is empty. Can sleep if needed. The memory for cxl_event is =
allocated
* by module being called. Hence it can be potentially be larger then
* sizeof(struct cxl_event). Multiple calls to this should return same
* pointer untill ack_event is called.
*/
struct cxl_event * fetch_event(struct cxl_context * ctx);
=20
/*
* Returns and acknowledge the struct cxl_event * back to the driver
* which can then free it or maybe put it back in a kmem_cache. This
* should be called once we have completely returned the current
* struct cxl_event from the readcall
*/
void ack_event(struct cxl_context * ctx, struct cxl_event *);
=20
I think above apis would give us more flexbility in the future when
drivers would want to send larger events without breaking the abi.
=46rom a cxlflash perspective, I think we'd be fine with this model as
long as the driver events are still prioritized. I do like the removal =
of
the no-sleep requirement and this would allow us to simply hand off
an already populated event reference.
Hi Vaibhav,
Le 09/03/2016 15:37, Vaibhav Jain a écrit :
I would propose these two apis.
/*
* fetches an event from the driver event queue. NULL means that queue
* is empty. Can sleep if needed. The memory for cxl_event is allocated
* by module being called. Hence it can be potentially be larger then
* sizeof(struct cxl_event). Multiple calls to this should return same
* pointer untill ack_event is called.
*/
struct cxl_event * fetch_event(struct cxl_context * ctx);
/*
* Returns and acknowledge the struct cxl_event * back to the driver
* which can then free it or maybe put it back in a kmem_cache. This
* should be called once we have completely returned the current
* struct cxl_event from the readcall
*/
void ack_event(struct cxl_context * ctx, struct cxl_event *);
How would you implement polling on those APIs?
How would you implement afu_read? There are several sources of events.
Fred
From: Ian Munsie <hidden> Date: 2016-03-10 00:47:43
Excerpts from Frederic Barrat's message of 2016-03-09 20:27:20 +1100:
So on afu_read(), we may call afu_driver_ops->event_pending() twice
before calling afu_driver_ops->deliver_event(). Actually, in the
(likely) scenario where there's only an afu_driver event pending, we
*will* call afu_driver_ops->event_pending() twice. Wouldn't it make
sense to cache it then?
From: Ian Munsie <hidden> Date: 2016-03-10 01:21:36
Excerpts from Vaibhav Jain's message of 2016-03-10 01:37:56 +1100:
quoted
+ select CXL_AFU_DRIVER_OPS
I suggest wrapping the driver_ops struct definition and other related
functions inside a #ifdef CONFIG_CXL_AFU_DRIVER_OPS.
No, the kconfig option is there so that cxlflash can add support for
this and not have to worry about breaking any builds if their code is
merged into the scsi tree that doesn't have our code yet.
There is nothing optional about this within our driver, which is why
this is a select and has no configuration choice of it's own.
On a related matter, we should send a patch to remove some of the
leftover config options that were added to smooth the merging of
cxlflash in the first place (CXL_KERNEL_API, CXL_EEH).
I would recommend adding a "struct module *" member to afu_driver_ops
and doing a __module_get on to it here and module_put when we destroy
the context. Since these callbacks will be residing within an external
module .text region hence it should stay in the memory until the context
is alive.
Should also check if ctx->afu_driver_ops->event_pending is NULL before
calling it.
The v1 patch did exactly that and mpe rejected it as it made this code
too ugly - we now check that event_pending field is valid when it is
registered and WARN if it is not.
I would propose these two apis.
/*
* fetches an event from the driver event queue. NULL means that queue
* is empty. Can sleep if needed. The memory for cxl_event is allocated
* by module being called. Hence it can be potentially be larger then
* sizeof(struct cxl_event). Multiple calls to this should return same
* pointer untill ack_event is called.
*/
struct cxl_event * fetch_event(struct cxl_context * ctx);
/*
* Returns and acknowledge the struct cxl_event * back to the driver
* which can then free it or maybe put it back in a kmem_cache. This
* should be called once we have completely returned the current
* struct cxl_event from the readcall
*/
void ack_event(struct cxl_context * ctx, struct cxl_event *);
I think above apis would give us more flexbility in the future when
drivers would want to send larger events without breaking the abi.
I'm very reluctant to make this kind of change - while nice on paper,
poll() and read() are already very easy calls to screw up, and we have
seen that happen countless times in the past from different drivers that
e.g. and end up in a situation where poll says there is an event but
then read blocks, or poll blocks even though there is an event already
pending.
The API at the moment fits into the poll() / read() model and has
appropriate locking and the correct waiting semantics to avoid those
kind of issues (provided that the afu driver doesn't do something that
violates these semantics like sleep in one of these calls, but the
kernel has debug features to detect that), but any deviation from this
is too risky in my view.
Cheers,
-Ian
From: Ian Munsie <hidden> Date: 2016-03-10 01:27:37
Excerpts from Frederic Barrat's message of 2016-03-09 20:27:20 +1100:
It would also avoid entering
WARN(1, "afu_read must be buggy\n");
if the driver changes its mind between the 2 calls :-)
Honestly, it had better not - that would be a gross violation of the
poll & read semantics and the kind of thing that leads to application
hangs.
Cheers,
-Ian
=20
+config CXL_AFU_DRIVER_OPS
+ bool
+ default n
+
config CXL
tristate "Support for IBM Coherent Accelerators (CXL)"
depends on PPC_POWERNV && PCI_MSI && EEH
select CXL_BASE
select CXL_KERNEL_API
select CXL_EEH
+ select CXL_AFU_DRIVER_OPS
I suggest wrapping the driver_ops struct definition and other related
functions inside a #ifdef CONFIG_CXL_AFU_DRIVER_OPS.
These are here to enable the feature in other drivers. So the cxlflash
(or whoever) can put their code in via the linux-scsi tree but that new
piece is only enabled when CXL_AFU_DRIVER_OPS is present (ie. when
merged upstream). But if it's not, their code can still compile. =20
Hence their code compiles in linux-scsi and our code compiles in linux
-ppc, but only once they're together do they actually enable the full
feature. We don't have a nasty dependency of linux-scsi having to pull
in linux-ppc or visa versa before the merge window. Everyone works
independently and it all gets fixed in linus tree.
Eventually, when everyone has the all the code in merged upstream, we
can remove these config options. We should be able to remove
CXL_KERNEL_API and CXL_EEH now actually!
So no, we shouldn't wrap the actual code.
Mikey
Hi Vaibhav,
Le 09/03/2016 15:37, Vaibhav Jain a =C3=A9crit :
quoted
I would propose these two apis.
/*
* fetches an event from the driver event queue. NULL means that queue
* is empty. Can sleep if needed. The memory for cxl_event is allocated
* by module being called. Hence it can be potentially be larger then
* sizeof(struct cxl_event). Multiple calls to this should return same
* pointer untill ack_event is called.
*/
struct cxl_event * fetch_event(struct cxl_context * ctx);
/*
* Returns and acknowledge the struct cxl_event * back to the driver
* which can then free it or maybe put it back in a kmem_cache. This
* should be called once we have completely returned the current
* struct cxl_event from the readcall
*/
void ack_event(struct cxl_context * ctx, struct cxl_event *);
How would you implement polling on those APIs?
Hi Fred. I am looking at an implementation similar to this:
static inline bool ctx_event_pending(struct cxl_context *ctx)
{
typeof (ctx->afu_driver_ops->fetch_event) fn_events =3D
(ctx->afu_driver_ops !=3D NULL) ? ctx->afu_driver_ops->fetch_event : NULL;
if (ctx->pending_irq || ctx->pending_fault || ctx->pending_afu_err)
return true;
/*
* if fn_event returns a not null then its gauranteed to return
* the same pointer on next call
*/
if (fn_events)
return fn_events(ctx) !=3D NULL;
return false;
}
unsigned int afu_poll(struct file *file, struct poll_table_struct *poll)
{
struct cxl_context *ctx =3D file->private_data;
int mask =3D 0;
unsigned long flags;
poll_wait(file, &ctx->wq, poll);
pr_devel("afu_poll wait done pe: %i\n", ctx->pe);
spin_lock_irqsave(&ctx->lock, flags);
if (ctx_event_pending(ctx))
mask |=3D POLLIN | POLLRDNORM;
else if (ctx->status =3D=3D CLOSED)
/* Only error on closed when there are no futher events pending
*/
mask |=3D POLLERR;
spin_unlock_irqrestore(&ctx->lock, flags);
pr_devel("afu_poll pe: %i returning %#x\n", ctx->pe, mask);
return mask;
}
How would you implement afu_read? There are several sources of events.
Looking at an implementation similar to this:
ssize_t afu_read(struct file *file, char __user *buf, size_t count,
loff_t *off)
{
unsigned long flags;
ssize_t rc =3D 0;
struct cxl_context *ctx =3D file->private_data;
struct cxl_event *ptr_event, event =3D {
.header.process_element =3D ctx->pe,
.header.size =3D sizeof(struct cxl_event_header)
};
typeof (ctx->afu_driver_ops->fetch_event) fn_fetch_event =3D
(ctx->afu_driver_ops !=3D NULL) ? ctx->afu_driver_ops->fetch_event : NULL;
typeof (ctx->afu_driver_ops->ack_event) fn_ack_event =3D
(ctx->afu_driver_ops !=3D NULL) ? ctx->afu_driver_ops->ack_event : NULL;
=20
if (count < CXL_READ_MIN_SIZE)
return -EINVAL;
if (!cxl_adapter_link_ok(ctx->afu->adapter) ||
ctx->status =3D=3D CLOSED)
return -EIO;
if (signal_pending(current))
return -ERESTARTSYS;
/* if no events then wait */
if (!ctx_event_pending(ctx)) {
=09=20=20=20=20=20=20=20
if ((file->f_flags & O_NONBLOCK))
return -EAGAIN;
pr_devel("afu_read going to sleep...\n");
rc =3D wait_event_interruptible(ctx->wq,
(ctx->status =3D=3D CLOSED) ||
cxl_adapter_link_ok(ctx->afu->adapter) ||
ctx_event_pending(ctx));
pr_devel("afu_read woken up\n");
}
=20=20=20=20=20=20=20
/* did we get interrupted during wait sleep */
if (rc)
return rc;
/* get driver events if any */
ptr_event =3D fn_fetch_event ? fn_fetch_event(ctx) : NULL;
/* In case of error feching driver specific event */
if (IS_ERR(ptr_event)) {
pr_warn("Error fetching driver specific event %ld", PTR_ERR(ptr_eve=
nt));
ptr_event =3D NULL;
}
/* code below manipulates ctx so take a spin lock */
spin_lock_irqsave(&ctx->lock, flags);
/* give driver events first priority */
if (ptr_event) {
pr_devel("afu_read delivering AFU driver specific event\n");
/* populate the header type and pe in the event struct */
ptr_event->header.type =3D CXL_EVENT_AFU_DRIVER;
ptr_event->header.process_element =3D ctx->pe;
WARN_ON(event.header.size > count);
} else if (ctx->pending_irq) {
pr_devel("afu_read delivering AFU interrupt\n");
event.header.size +=3D sizeof(struct cxl_event_afu_interrupt);
event.header.type =3D CXL_EVENT_AFU_INTERRUPT;
event.irq.irq =3D find_first_bit(ctx->irq_bitmap, ctx->irq_count) + 1;
clear_bit(event.irq.irq - 1, ctx->irq_bitmap);
if (bitmap_empty(ctx->irq_bitmap, ctx->irq_count))
ctx->pending_irq =3D false;
} else if (ctx->pending_fault) {
pr_devel("afu_read delivering data storage fault\n");
event.header.size +=3D sizeof(struct cxl_event_data_storage);
event.header.type =3D CXL_EVENT_DATA_STORAGE;
event.fault.addr =3D ctx->fault_addr;
event.fault.dsisr =3D ctx->fault_dsisr;
ctx->pending_fault =3D false;
} else if (ctx->pending_afu_err) {
pr_devel("afu_read delivering afu error\n");
event.header.size +=3D sizeof(struct cxl_event_afu_error);
event.header.type =3D CXL_EVENT_AFU_ERROR;
event.afu_error.error =3D ctx->afu_err;
ctx->pending_afu_err =3D false;
} else if (ctx->status =3D=3D CLOSED) {
pr_devel("afu_read fatal error\n");
rc =3D -EIO;
} else
WARN(1, "afu_read must be buggy\n");
spin_unlock_irqrestore(&ctx->lock, flags);
if (!rc) {
/* if we dont have a driver event then use 'event' var */
ptr_event =3D ptr_event ? ptr_event : &event;
=09
rc =3D min(((size_t)ptr_event->header.size), count);
=09
if (copy_to_user(buf, ptr_event, rc))
rc =3D -EFAULT;
}
/* if its a driver event ack it back to the driver */
if (fn_ack_event && (ptr_event !=3D &event))
fn_ack_event(ctx, ptr_event);
=09=09
return rc;
}
Cheers,
~ Vaibhav
These are here to enable the feature in other drivers. So the cxlflash
(or whoever) can put their code in via the linux-scsi tree but that new
piece is only enabled when CXL_AFU_DRIVER_OPS is present (ie. when
merged upstream). But if it's not, their code can still compile.
Hence their code compiles in linux-scsi and our code compiles in linux
-ppc, but only once they're together do they actually enable the full
feature. We don't have a nasty dependency of linux-scsi having to pull
in linux-ppc or visa versa before the merge window. Everyone works
independently and it all gets fixed in linus tree.
Eventually, when everyone has the all the code in merged upstream, we
can remove these config options. We should be able to remove
CXL_KERNEL_API and CXL_EEH now actually!
So no, we shouldn't wrap the actual code.
Mikey & Ian,
Agree on the point made. Thanks for detailed explaination.
~ Vaibhav
No, the kconfig option is there so that cxlflash can add support for
this and not have to worry about breaking any builds if their code is
merged into the scsi tree that doesn't have our code yet.
There is nothing optional about this within our driver, which is why
this is a select and has no configuration choice of it's own.
On a related matter, we should send a patch to remove some of the
leftover config options that were added to smooth the merging of
cxlflash in the first place (CXL_KERNEL_API, CXL_EEH).
Should also check if ctx->afu_driver_ops->event_pending is NULL before
calling it.
The v1 patch did exactly that and mpe rejected it as it made this code
too ugly - we now check that event_pending field is valid when it is
registered and WARN if it is not.
The driver_ops struct pointer being passed is still owned by the
external module and its free change it even after calling this
function. We can mitigate this to some extent by accepting a const
pointer to the struct or by copying this struct to the context object.
I'm very reluctant to make this kind of change - while nice on paper,
poll() and read() are already very easy calls to screw up, and we have
seen that happen countless times in the past from different drivers that
e.g. and end up in a situation where poll says there is an event but
then read blocks, or poll blocks even though there is an event already
pending.
The API at the moment fits into the poll() / read() model and has
appropriate locking and the correct waiting semantics to avoid those
kind of issues (provided that the afu driver doesn't do something that
violates these semantics like sleep in one of these calls, but the
kernel has debug features to detect that), but any deviation from this
is too risky in my view.
Ian I have responded to Fred with an example implementation of these
calls. Requesting you to please take a look.
Cheers,
~ Vaibhav
From: Andrew Donnellan <hidden> Date: 2016-03-11 01:50:01
On 10/03/16 12:18, Ian Munsie wrote:
On a related matter, we should send a patch to remove some of the
leftover config options that were added to smooth the merging of
cxlflash in the first place (CXL_KERNEL_API, CXL_EEH).
I'm happy to do that after this series is merged.
--
Andrew Donnellan Software Engineer, OzLabs
andrew.donnellan@au1.ibm.com Australia Development Lab, Canberra
+61 2 6201 8874 (work) IBM Australia Limited