* Re: [PATCH 1/6] mdev: class id support
From: Alex Williamson @ 2019-09-23 16:05 UTC (permalink / raw)
To: Jason Wang
Cc: kvm, linux-s390, linux-kernel, dri-devel, intel-gfx,
intel-gvt-dev, kwankhede, mst, tiwei.bie, virtualization, netdev,
cohuck, maxime.coquelin, cunming.liang, zhihong.wang, rob.miller,
xiao.w.wang, haotian.wang, zhenyuw, zhi.a.wang, jani.nikula,
joonas.lahtinen, rodrigo.vivi, airlied, daniel, farman, pasic,
sebott, oberpar, heiko.carstens, gor, borntraeger, akrowiak,
freude, lingshan.zhu, idos, eperezma, lulu, parav
In-Reply-To: <20190923130331.29324-2-jasowang@redhat.com>
On Mon, 23 Sep 2019 21:03:26 +0800
Jason Wang <jasowang@redhat.com> wrote:
> Mdev bus only supports vfio driver right now, so it doesn't implement
> match method. But in the future, we may add drivers other than vfio,
> one example is virtio-mdev[1] driver. This means we need to add device
> class id support in bus match method to pair the mdev device and mdev
> driver correctly.
>
> So this patch adds id_table to mdev_driver and class_id for mdev
> parent with the match method for mdev bus.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> Documentation/driver-api/vfio-mediated-device.rst | 7 +++++--
> drivers/gpu/drm/i915/gvt/kvmgt.c | 2 +-
> drivers/s390/cio/vfio_ccw_ops.c | 2 +-
> drivers/s390/crypto/vfio_ap_ops.c | 3 ++-
> drivers/vfio/mdev/mdev_core.c | 14 ++++++++++++--
> drivers/vfio/mdev/mdev_driver.c | 14 ++++++++++++++
> drivers/vfio/mdev/mdev_private.h | 1 +
> drivers/vfio/mdev/vfio_mdev.c | 6 ++++++
> include/linux/mdev.h | 7 ++++++-
> include/linux/mod_devicetable.h | 8 ++++++++
> samples/vfio-mdev/mbochs.c | 2 +-
> samples/vfio-mdev/mdpy.c | 2 +-
> samples/vfio-mdev/mtty.c | 2 +-
> 13 files changed, 59 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
> index 25eb7d5b834b..0e052072e1d8 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -102,12 +102,14 @@ structure to represent a mediated device's driver::
> * @probe: called when new device created
> * @remove: called when device removed
> * @driver: device driver structure
> + * @id_table: the ids serviced by this driver.
> */
> struct mdev_driver {
> const char *name;
> int (*probe) (struct device *dev);
> void (*remove) (struct device *dev);
> struct device_driver driver;
> + const struct mdev_class_id *id_table;
> };
>
> A mediated bus driver for mdev should use this structure in the function calls
> @@ -116,7 +118,7 @@ to register and unregister itself with the core driver:
> * Register::
>
> extern int mdev_register_driver(struct mdev_driver *drv,
> - struct module *owner);
> + struct module *owner);
>
> * Unregister::
>
> @@ -163,7 +165,8 @@ A driver should use the mdev_parent_ops structure in the function call to
> register itself with the mdev core driver::
>
> extern int mdev_register_device(struct device *dev,
> - const struct mdev_parent_ops *ops);
> + const struct mdev_parent_ops *ops,
> + u8 class_id);
>
> However, the mdev_parent_ops structure is not required in the function call
> that a driver should use to unregister itself with the mdev core driver::
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 23aa3e50cbf8..19d51a35f019 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -1625,7 +1625,7 @@ static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
> return -EFAULT;
> intel_vgpu_ops.supported_type_groups = kvm_vgpu_type_groups;
>
> - return mdev_register_device(dev, &intel_vgpu_ops);
> + return mdev_register_vfio_device(dev, &intel_vgpu_ops);
> }
>
> static void kvmgt_host_exit(struct device *dev)
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
> index f0d71ab77c50..246ff0f80944 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -588,7 +588,7 @@ static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
>
> int vfio_ccw_mdev_reg(struct subchannel *sch)
> {
> - return mdev_register_device(&sch->dev, &vfio_ccw_mdev_ops);
> + return mdev_register_vfio_device(&sch->dev, &vfio_ccw_mdev_ops);
> }
>
> void vfio_ccw_mdev_unreg(struct subchannel *sch)
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
> index 5c0f53c6dde7..7487fc39d2c5 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -1295,7 +1295,8 @@ int vfio_ap_mdev_register(void)
> {
> atomic_set(&matrix_dev->available_instances, MAX_ZDEV_ENTRIES_EXT);
>
> - return mdev_register_device(&matrix_dev->device, &vfio_ap_matrix_ops);
> + return mdev_register_vfio_device(&matrix_dev->device,
> + &vfio_ap_matrix_ops);
> }
>
> void vfio_ap_mdev_unregister(void)
> diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
> index b558d4cfd082..a02c256a3514 100644
> --- a/drivers/vfio/mdev/mdev_core.c
> +++ b/drivers/vfio/mdev/mdev_core.c
> @@ -135,11 +135,14 @@ static int mdev_device_remove_cb(struct device *dev, void *data)
> * mdev_register_device : Register a device
> * @dev: device structure representing parent device.
> * @ops: Parent device operation structure to be registered.
> + * @id: device id.
> *
> * Add device to list of registered parent devices.
> * Returns a negative value on error, otherwise 0.
> */
> -int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
> +int mdev_register_device(struct device *dev,
> + const struct mdev_parent_ops *ops,
> + u8 class_id)
> {
> int ret;
> struct mdev_parent *parent;
> @@ -175,6 +178,7 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
>
> parent->dev = dev;
> parent->ops = ops;
> + parent->class_id = class_id;
>
I don't think we want to tie the class_id to the parent. mdev parent
devices can create various types of devices, some might be virtio, some
might be vfio. I think the cover letter even suggests that's a
direction these virtio devices might be headed. It seems the class
should be on the resulting device itself. That also suggests that at
the parent we cannot have a single device_ops, the ops used will depend
on the type of device created. Perhaps that means we need vfio_ops
alongside virtio_ops, rather than a common device_ops. Thanks,
Alex
> if (!mdev_bus_compat_class) {
> mdev_bus_compat_class = class_compat_register("mdev_bus");
> @@ -208,7 +212,13 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
> put_device(dev);
> return ret;
> }
> -EXPORT_SYMBOL(mdev_register_device);
> +
> +int mdev_register_vfio_device(struct device *dev,
> + const struct mdev_parent_ops *ops)
> +{
> + return mdev_register_device(dev, ops, MDEV_ID_VFIO);
> +}
> +EXPORT_SYMBOL(mdev_register_vfio_device);
>
> /*
> * mdev_unregister_device : Unregister a parent device
> diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
> index 0d3223aee20b..b70bbebc9dd3 100644
> --- a/drivers/vfio/mdev/mdev_driver.c
> +++ b/drivers/vfio/mdev/mdev_driver.c
> @@ -69,8 +69,22 @@ static int mdev_remove(struct device *dev)
> return 0;
> }
>
> +static int mdev_match(struct device *dev, struct device_driver *drv)
> +{
> + unsigned int i;
> + struct mdev_device *mdev = to_mdev_device(dev);
> + struct mdev_driver *mdrv = to_mdev_driver(drv);
> + const struct mdev_class_id *ids = mdrv->id_table;
> +
> + for (i = 0; ids[i].id; i++)
> + if (ids[i].id == mdev->parent->class_id)
> + return 1;
> + return 0;
> +}
> +
> struct bus_type mdev_bus_type = {
> .name = "mdev",
> + .match = mdev_match,
> .probe = mdev_probe,
> .remove = mdev_remove,
> };
> diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
> index 7d922950caaf..e58b07c866b1 100644
> --- a/drivers/vfio/mdev/mdev_private.h
> +++ b/drivers/vfio/mdev/mdev_private.h
> @@ -22,6 +22,7 @@ struct mdev_parent {
> struct list_head type_list;
> /* Synchronize device creation/removal with parent unregistration */
> struct rw_semaphore unreg_sem;
> + u8 class_id;
> };
>
> struct mdev_device {
> diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
> index 30964a4e0a28..fd2a4d9a3f26 100644
> --- a/drivers/vfio/mdev/vfio_mdev.c
> +++ b/drivers/vfio/mdev/vfio_mdev.c
> @@ -120,10 +120,16 @@ static void vfio_mdev_remove(struct device *dev)
> vfio_del_group_dev(dev);
> }
>
> +static struct mdev_class_id id_table[] = {
> + { MDEV_ID_VFIO },
> + { 0 },
> +};
> +
> static struct mdev_driver vfio_mdev_driver = {
> .name = "vfio_mdev",
> .probe = vfio_mdev_probe,
> .remove = vfio_mdev_remove,
> + .id_table = id_table,
> };
>
> static int __init vfio_mdev_init(void)
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index 0ce30ca78db0..3ebae310f599 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -118,6 +118,7 @@ struct mdev_type_attribute mdev_type_attr_##_name = \
> * @probe: called when new device created
> * @remove: called when device removed
> * @driver: device driver structure
> + * @id_table: the ids serviced by this driver.
> *
> **/
> struct mdev_driver {
> @@ -125,6 +126,7 @@ struct mdev_driver {
> int (*probe)(struct device *dev);
> void (*remove)(struct device *dev);
> struct device_driver driver;
> + const struct mdev_class_id *id_table;
> };
>
> #define to_mdev_driver(drv) container_of(drv, struct mdev_driver, driver)
> @@ -135,7 +137,8 @@ const guid_t *mdev_uuid(struct mdev_device *mdev);
>
> extern struct bus_type mdev_bus_type;
>
> -int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops);
> +int mdev_register_vfio_device(struct device *dev,
> + const struct mdev_parent_ops *ops);
> void mdev_unregister_device(struct device *dev);
>
> int mdev_register_driver(struct mdev_driver *drv, struct module *owner);
> @@ -145,4 +148,6 @@ struct device *mdev_parent_dev(struct mdev_device *mdev);
> struct device *mdev_dev(struct mdev_device *mdev);
> struct mdev_device *mdev_from_dev(struct device *dev);
>
> +#define MDEV_ID_VFIO 1 /* VFIO device */
> +
> #endif /* MDEV_H */
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 5714fd35a83c..f32c6e44fb1a 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -821,4 +821,12 @@ struct wmi_device_id {
> const void *context;
> };
>
> +/**
> + * struct mdev_class_id - MDEV device class identifier
> + * @id: Used to identify a specific class of device, e.g vfio-mdev device.
> + */
> +struct mdev_class_id {
> + __u16 id;
> +};
> +
> #endif /* LINUX_MOD_DEVICETABLE_H */
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index ac5c8c17b1ff..71a4469be85d 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -1468,7 +1468,7 @@ static int __init mbochs_dev_init(void)
> if (ret)
> goto failed2;
>
> - ret = mdev_register_device(&mbochs_dev, &mdev_fops);
> + ret = mdev_register_vfio_device(&mbochs_dev, &mdev_fops);
> if (ret)
> goto failed3;
>
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index cc86bf6566e4..d3029dd27d91 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -775,7 +775,7 @@ static int __init mdpy_dev_init(void)
> if (ret)
> goto failed2;
>
> - ret = mdev_register_device(&mdpy_dev, &mdev_fops);
> + ret = mdev_register_vfio_device(&mdpy_dev, &mdev_fops);
> if (ret)
> goto failed3;
>
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index 92e770a06ea2..744c88a6b22c 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -1468,7 +1468,7 @@ static int __init mtty_dev_init(void)
> if (ret)
> goto failed2;
>
> - ret = mdev_register_device(&mtty_dev.dev, &mdev_fops);
> + ret = mdev_register_vfio_device(&mtty_dev.dev, &mdev_fops);
> if (ret)
> goto failed3;
>
^ permalink raw reply
* Re: [PATCH net-next] tuntap: Fallback to automq on TUNSETSTEERINGEBPF prog negative return
From: Matt Cover @ 2019-09-23 16:31 UTC (permalink / raw)
To: Jason Wang
Cc: Michael S. Tsirkin, davem, ast, daniel, kafai, songliubraving,
yhs, Eric Dumazet, Stanislav Fomichev, Matthew Cover, mail,
pabeni, Nicolas Dichtel, wangli39, lifei.shirley, tglx, netdev,
linux-kernel, bpf
In-Reply-To: <b96ecf36-8f13-4a52-5355-7d88ec9e4a98@redhat.com>
On Sun, Sep 22, 2019 at 10:16 PM Jason Wang <jasowang@redhat.com> wrote:
>
>
> On 2019/9/23 上午11:18, Matt Cover wrote:
> > On Sun, Sep 22, 2019 at 7:34 PM Jason Wang <jasowang@redhat.com> wrote:
> >>
> >> On 2019/9/23 上午9:15, Matt Cover wrote:
> >>> On Sun, Sep 22, 2019 at 5:51 PM Jason Wang <jasowang@redhat.com> wrote:
> >>>> On 2019/9/23 上午6:30, Matt Cover wrote:
> >>>>> On Sun, Sep 22, 2019 at 1:36 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >>>>>> On Sun, Sep 22, 2019 at 10:43:19AM -0700, Matt Cover wrote:
> >>>>>>> On Sun, Sep 22, 2019 at 5:37 AM Michael S. Tsirkin <mst@redhat.com> wrote:
> >>>>>>>> On Fri, Sep 20, 2019 at 11:58:43AM -0700, Matthew Cover wrote:
> >>>>>>>>> Treat a negative return from a TUNSETSTEERINGEBPF bpf prog as a signal
> >>>>>>>>> to fallback to tun_automq_select_queue() for tx queue selection.
> >>>>>>>>>
> >>>>>>>>> Compilation of this exact patch was tested.
> >>>>>>>>>
> >>>>>>>>> For functional testing 3 additional printk()s were added.
> >>>>>>>>>
> >>>>>>>>> Functional testing results (on 2 txq tap device):
> >>>>>>>>>
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] ========== tun no prog ==========
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: tun_ebpf_select_queue() returned '-1'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: tun_automq_select_queue() ran
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] ========== tun prog -1 ==========
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: bpf_prog_run_clear_cb() returned '-1'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: tun_ebpf_select_queue() returned '-1'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: tun_automq_select_queue() ran
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] ========== tun prog 0 ==========
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: bpf_prog_run_clear_cb() returned '0'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: tun_ebpf_select_queue() returned '0'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] ========== tun prog 1 ==========
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: bpf_prog_run_clear_cb() returned '1'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: tun_ebpf_select_queue() returned '1'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] ========== tun prog 2 ==========
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: bpf_prog_run_clear_cb() returned '2'
> >>>>>>>>> [Fri Sep 20 18:33:27 2019] tuntap: tun_ebpf_select_queue() returned '0'
> >>>>>>>>>
> >>>>>>>>> Signed-off-by: Matthew Cover <matthew.cover@stackpath.com>
> >>>>>>>> Could you add a bit more motivation data here?
> >>>>>>> Thank you for these questions Michael.
> >>>>>>>
> >>>>>>> I'll plan on adding the below information to the
> >>>>>>> commit message and submitting a v2 of this patch
> >>>>>>> when net-next reopens. In the meantime, it would
> >>>>>>> be very helpful to know if these answers address
> >>>>>>> some of your concerns.
> >>>>>>>
> >>>>>>>> 1. why is this a good idea
> >>>>>>> This change allows TUNSETSTEERINGEBPF progs to
> >>>>>>> do any of the following.
> >>>>>>> 1. implement queue selection for a subset of
> >>>>>>> traffic (e.g. special queue selection logic
> >>>>>>> for ipv4, but return negative and use the
> >>>>>>> default automq logic for ipv6)
> >>>>>>> 2. determine there isn't sufficient information
> >>>>>>> to do proper queue selection; return
> >>>>>>> negative and use the default automq logic
> >>>>>>> for the unknown
> >>>>>>> 3. implement a noop prog (e.g. do
> >>>>>>> bpf_trace_printk() then return negative and
> >>>>>>> use the default automq logic for everything)
> >>>>>>>
> >>>>>>>> 2. how do we know existing userspace does not rely on existing behaviour
> >>>>>>> Prior to this change a negative return from a
> >>>>>>> TUNSETSTEERINGEBPF prog would have been cast
> >>>>>>> into a u16 and traversed netdev_cap_txqueue().
> >>>>>>>
> >>>>>>> In most cases netdev_cap_txqueue() would have
> >>>>>>> found this value to exceed real_num_tx_queues
> >>>>>>> and queue_index would be updated to 0.
> >>>>>>>
> >>>>>>> It is possible that a TUNSETSTEERINGEBPF prog
> >>>>>>> return a negative value which when cast into a
> >>>>>>> u16 results in a positive queue_index less than
> >>>>>>> real_num_tx_queues. For example, on x86_64, a
> >>>>>>> return value of -65535 results in a queue_index
> >>>>>>> of 1; which is a valid queue for any multiqueue
> >>>>>>> device.
> >>>>>>>
> >>>>>>> It seems unlikely, however as stated above is
> >>>>>>> unfortunately possible, that existing
> >>>>>>> TUNSETSTEERINGEBPF programs would choose to
> >>>>>>> return a negative value rather than return the
> >>>>>>> positive value which holds the same meaning.
> >>>>>>>
> >>>>>>> It seems more likely that future
> >>>>>>> TUNSETSTEERINGEBPF programs would leverage a
> >>>>>>> negative return and potentially be loaded into
> >>>>>>> a kernel with the old behavior.
> >>>>>> OK if we are returning a special
> >>>>>> value, shouldn't we limit it? How about a special
> >>>>>> value with this meaning?
> >>>>>> If we are changing an ABI let's at least make it
> >>>>>> extensible.
> >>>>>>
> >>>>> A special value with this meaning sounds
> >>>>> good to me. I'll plan on adding a define
> >>>>> set to -1 to cause the fallback to automq.
> >>>> Can it really return -1?
> >>>>
> >>>> I see:
> >>>>
> >>>> static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
> >>>> struct sk_buff *skb)
> >>>> ...
> >>>>
> >>>>
> >>>>> The way I was initially viewing the old
> >>>>> behavior was that returning negative was
> >>>>> undefined; it happened to have the
> >>>>> outcomes I walked through, but not
> >>>>> necessarily by design.
> >>>> Having such fallback may bring extra troubles, it requires the eBPF
> >>>> program know the existence of the behavior which is not a part of kernel
> >>>> ABI actually. And then some eBPF program may start to rely on that which
> >>>> is pretty dangerous. Note, one important consideration is to have
> >>>> macvtap support where does not have any stuffs like automq.
> >>>>
> >>>> Thanks
> >>>>
> >>> How about we call this TUN_SSE_ABORT
> >>> instead of TUN_SSE_DO_AUTOMQ?
> >>>
> >>> TUN_SSE_ABORT could be documented as
> >>> falling back to the default queue
> >>> selection method in either space
> >>> (presumably macvtap has some queue
> >>> selection method when there is no prog).
> >>
> >> This looks like a more complex API, we don't want userspace to differ
> >> macvtap from tap too much.
> >>
> >> Thanks
> >>
> > This is barely more complex and provides
> > similar to what is done in many places.
> > For xdp, an XDP_PASS enacts what the
> > kernel would do if there was no bpf prog.
> > For tc cls in da mode, TC_ACT_OK enacts
> > what the kernel would do if there was
> > no bpf prog. For xt_bpf, false enacts
> > what the kernel would do if there was
> > no bpf prog (as long as negation
> > isn't in play in the rule, I believe).
>
>
> I think this is simply because you can't implement e.g
> XDP_PASS/TC_ACT_OK through eBPF itself which is not the case of steering
> prog here.
>
>
> >
> > I know that this is somewhat of an
> > oversimplification and that each of
> > these also means something else in
> > the respective hookpoint, but I standby
> > seeing value in this change.
> >
> > macvtap must have some default (i.e the
> > action which it takes when no prog is
> > loaded), even if that is just use queue
> > 0. We can provide the same TUN_SSE_ABORT
> > in userspace which does the same thing;
> > enacts the default when returned. Any
> > differences left between tap and macvtap
> > would be in what the default is, not in
> > these changes. And that difference already
> > exists today.
>
>
> I think it's better to safe to just drop the packet instead of trying to
> workaround it.
>
This patch aside, dropping the packet here
seems like the wrong choice. Loading a
prog at this hookpoint "configures"
steering. The action of configuring
steering should not result in dropped
packets.
Suboptimal delivery is generally preferable
to no delivery. Leaving the behavior as-is
(i.e. relying on netdev_cap_txqueue()) or
making any return which doesn't fit in a
u16 simply use queue 0 would be highly
preferable to dropping the packet.
> Thanks
>
>
> >
> >>>>> In order to keep the new behavior
> >>>>> extensible, how should we state that a
> >>>>> negative return other than -1 is
> >>>>> undefined and therefore subject to
> >>>>> change. Is something like this
> >>>>> sufficient?
> >>>>>
> >>>>> Documentation/networking/tc-actions-env-rules.txt
> >>>>>
> >>>>> Additionally, what should the new
> >>>>> behavior implement when a negative other
> >>>>> than -1 is returned? I would like to have
> >>>>> it do the same thing as -1 for now, but
> >>>>> with the understanding that this behavior
> >>>>> is undefined. Does this sound reasonable?
> >>>>>
> >>>>>>>> 3. why doesn't userspace need a way to figure out whether it runs on a kernel with and
> >>>>>>>> without this patch
> >>>>>>> There may be some value in exposing this fact
> >>>>>>> to the ebpf prog loader. What is the standard
> >>>>>>> practice here, a define?
> >>>>>> We'll need something at runtime - people move binaries between kernels
> >>>>>> without rebuilding then. An ioctl is one option.
> >>>>>> A sysfs attribute is another, an ethtool flag yet another.
> >>>>>> A combination of these is possible.
> >>>>>>
> >>>>>> And if we are doing this anyway, maybe let userspace select
> >>>>>> the new behaviour? This way we can stay compatible with old
> >>>>>> userspace...
> >>>>>>
> >>>>> Understood. I'll look into adding an
> >>>>> ioctl to activate the new behavior. And
> >>>>> perhaps a method of checking which is
> >>>>> behavior is currently active (in case we
> >>>>> ever want to change the default, say
> >>>>> after some suitably long transition
> >>>>> period).
> >>>>>
> >>>>>>>> thanks,
> >>>>>>>> MST
> >>>>>>>>
> >>>>>>>>> ---
> >>>>>>>>> drivers/net/tun.c | 20 +++++++++++---------
> >>>>>>>>> 1 file changed, 11 insertions(+), 9 deletions(-)
> >>>>>>>>>
> >>>>>>>>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> >>>>>>>>> index aab0be4..173d159 100644
> >>>>>>>>> --- a/drivers/net/tun.c
> >>>>>>>>> +++ b/drivers/net/tun.c
> >>>>>>>>> @@ -583,35 +583,37 @@ static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb)
> >>>>>>>>> return txq;
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> -static u16 tun_ebpf_select_queue(struct tun_struct *tun, struct sk_buff *skb)
> >>>>>>>>> +static int tun_ebpf_select_queue(struct tun_struct *tun, struct sk_buff *skb)
> >>>>>>>>> {
> >>>>>>>>> struct tun_prog *prog;
> >>>>>>>>> u32 numqueues;
> >>>>>>>>> - u16 ret = 0;
> >>>>>>>>> + int ret = -1;
> >>>>>>>>>
> >>>>>>>>> numqueues = READ_ONCE(tun->numqueues);
> >>>>>>>>> if (!numqueues)
> >>>>>>>>> return 0;
> >>>>>>>>>
> >>>>>>>>> + rcu_read_lock();
> >>>>>>>>> prog = rcu_dereference(tun->steering_prog);
> >>>>>>>>> if (prog)
> >>>>>>>>> ret = bpf_prog_run_clear_cb(prog->prog, skb);
> >>>>>>>>> + rcu_read_unlock();
> >>>>>>>>>
> >>>>>>>>> - return ret % numqueues;
> >>>>>>>>> + if (ret >= 0)
> >>>>>>>>> + ret %= numqueues;
> >>>>>>>>> +
> >>>>>>>>> + return ret;
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
> >>>>>>>>> struct net_device *sb_dev)
> >>>>>>>>> {
> >>>>>>>>> struct tun_struct *tun = netdev_priv(dev);
> >>>>>>>>> - u16 ret;
> >>>>>>>>> + int ret;
> >>>>>>>>>
> >>>>>>>>> - rcu_read_lock();
> >>>>>>>>> - if (rcu_dereference(tun->steering_prog))
> >>>>>>>>> - ret = tun_ebpf_select_queue(tun, skb);
> >>>>>>>>> - else
> >>>>>>>>> + ret = tun_ebpf_select_queue(tun, skb);
> >>>>>>>>> + if (ret < 0)
> >>>>>>>>> ret = tun_automq_select_queue(tun, skb);
> >>>>>>>>> - rcu_read_unlock();
> >>>>>>>>>
> >>>>>>>>> return ret;
> >>>>>>>>> }
> >>>>>>>>> --
> >>>>>>>>> 1.8.3.1
^ permalink raw reply
* Re: [PATCH bpf] selftests/bpf: test_progs: fix client/server race in tcp_rtt
From: Andrii Nakryiko @ 2019-09-23 16:41 UTC (permalink / raw)
To: Stanislav Fomichev
Cc: Stanislav Fomichev, Networking, bpf, David S. Miller,
Alexei Starovoitov, Daniel Borkmann
In-Reply-To: <20190923153819.GA21441@mini-arch>
On Mon, Sep 23, 2019 at 8:38 AM Stanislav Fomichev <sdf@fomichev.me> wrote:
>
> On 09/22, Andrii Nakryiko wrote:
> > On Sun, Sep 22, 2019 at 12:10 PM Stanislav Fomichev <sdf@google.com> wrote:
> > >
> > > This is the same problem I found earlier in test_sockopt_inherit:
> > > there is a race between server thread doing accept() and client
> > > thread doing connect(). Let's explicitly synchronize them via
> > > pthread conditional variable.
> > >
> > > Fixes: b55873984dab ("selftests/bpf: test BPF_SOCK_OPS_RTT_CB")
> > > Signed-off-by: Stanislav Fomichev <sdf@google.com>
> > > ---
> > > tools/testing/selftests/bpf/prog_tests/tcp_rtt.c | 16 +++++++++++++++-
> > > 1 file changed, 15 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c
> > > index fdc0b3614a9e..e64058906bcd 100644
> > > --- a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c
> > > +++ b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c
> > > @@ -203,6 +203,9 @@ static int start_server(void)
> > > return fd;
> > > }
> > >
> > > +static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER;
> > > +static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER;
> > > +
> > > static void *server_thread(void *arg)
> > > {
> > > struct sockaddr_storage addr;
> > > @@ -215,6 +218,10 @@ static void *server_thread(void *arg)
> > > return NULL;
> > > }
> > >
> > > + pthread_mutex_lock(&server_started_mtx);
> > > + pthread_cond_signal(&server_started);
> > > + pthread_mutex_unlock(&server_started_mtx);
> > > +
> > > client_fd = accept(fd, (struct sockaddr *)&addr, &len);
> > > if (CHECK_FAIL(client_fd < 0)) {
> > > perror("Failed to accept client");
> > > @@ -248,7 +255,14 @@ void test_tcp_rtt(void)
> > > if (CHECK_FAIL(server_fd < 0))
> > > goto close_cgroup_fd;
> > >
> > > - pthread_create(&tid, NULL, server_thread, (void *)&server_fd);
> > > + if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread,
> > > + (void *)&server_fd)))
> > > + goto close_cgroup_fd;
> > > +
> > > + pthread_mutex_lock(&server_started_mtx);
> > > + pthread_cond_wait(&server_started, &server_started_mtx);
> > > + pthread_mutex_unlock(&server_started_mtx);
> >
> >
> > If the server fails to listen, then we'll never get a signal, right?
> > Let's use timedwait instead to avoid test getting stuck forever in
> > such cases?
> Good point. How about I do the same thing I do in sockopt_inherit tests:
> https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/tree/tools/testing/selftests/bpf/prog_tests/sockopt_inherit.c#n73
>
> err = listen()
> pthread_cond_signal()
> if (CHECK_FAIL(err)) {
> return;
> }
>
> Should fix the problem of getting stuck forever without any timeouts.
> I'll send a v2 later today.
Sounds good.
>
> > > +
> > > CHECK_FAIL(run_test(cgroup_fd, server_fd));
> > > close(server_fd);
> > > close_cgroup_fd:
> > > --
> > > 2.23.0.351.gc4317032e6-goog
> > >
^ permalink raw reply
* Re: CONFIG_NET_TC_SKB_EXT
From: Paul Blakey @ 2019-09-23 16:56 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Pravin Shelar, Daniel Borkmann, Vlad Buslov, David Miller,
netdev@vger.kernel.org, Jiri Pirko, Cong Wang, Jamal Hadi Salim,
Simon Horman, Or Gerlitz
In-Reply-To: <20190922144715.37f71fbf@cakuba.netronome.com>
On 9/23/2019 12:47 AM, Jakub Kicinski wrote:
> On Sun, 22 Sep 2019 14:51:44 +0300, Paul Blakey wrote:
>> The skb extension is currently used for miss path of software offloading OvS rules with recirculation to tc.
>> However, we are also preparing patches to support the hardware side of things.
>>
>> After the userspace OvS patches to support connection tracking, we'll have two users for
>> tc multi chain rules, one from those actually using tc and those translated from OvS rules.
>>
>> With both of these use cases, there is similar issue of 'miss', from hardware to tc and tc to OvS and the skb
>> extension will serve to recover from both.
>>
>> Consider, for example, the following multi chain tc rules:
>>
>> tc filter add dev1 ... chain 0 flower dst_mac aa:bb:cc:dd:ee:ff action pedit munge ex set mac dst 02:a0:98:4e:8f:d1 pipe action goto chain 1
>> tc filter add dev1 ... chain 1 flower ip_dst 1.1.1.1 action mirred egress redirect dev2
>> tc filter add dev1 ... chain 1 flower ip_dst 2.2.2.2 action mirred egress redirect dev2
>>
>> It's possible we offload the first two rules, but fail to offload the third rule, because of some hardware failure (e.g unsupported match or action).
>> If a packet with (dst_mac=aa:bb:cc:dd:ee:ff) and (dst ip=2.2.2.2) arrives,
>> we execute the goto chain 1 in hardware (and the pedit), and continue in chain 1, where we miss.
>>
>> Currently we re-start the processing in tc from chain 0, even though we already did part of the processing in hardware.
>> The match on the dst_mac will fail as we already modified it, and we won't execute the third rule action.
>> In addition, if we did manage to execute any software tc rules, the packet will be counted twice.
>>
>> We'll re-use this extension to solve this issue that currently exists by letting drivers tell tc on which chain to start the classification.
>>
>> Regarding the config, we suggest changing the default to N and letting users decide to enable it, see attached patch.
> Partial offloads are very hard. Could we possibly take a page out of
> routing offload's book and do a all or nothing offload in presence of
> multiple chains?
Hi,
Routing is a narrow scenario which this approach might work, but the
other way of offloading everything or nothing has it's disadvantages too.
Even following this approach in tc only is challenging for some
scenarios, consider the following tc rules:
tc filter add dev1 ... chain 0 flower <match1> action goto chain 1
tc filter add dev1 ... chain 0 flower <match2> action goto chain 1
tc filter add dev1 ... chain 0 flower <match3> action goto chain 1
..
..
tc filter add dev1 ... chain 0 flower ip_dst <match1000> action goto chain 1
tc filter add dev1 ... chain 1 flower ip_proto tcp action tunnel_key set dst_ip 8.8.8.8 action mirred egress redirect dev2
Now, you could offload 1000 'merged' rules that do the equivalent of:
tc filter add dev1 ... chain 0 flower <match1> ip_proto tcp action tunnel_key set dst_ip 8.8.8.8 action mirred egress redirect dev2
tc filter add dev1 ... chain 0 flower <match2> ip_proto tcp action tunnel_key set dst_ip 8.8.8.8 action mirred egress redirect dev2
...
tc filter add dev1 ... chain 0 flower <match1000> ip_proto tcp action tunnel_key set dst_ip 8.8.8.8 action mirred egress redirect dev2
And each of this hardware rule will update the correct software action counter, so the first hardware rule updates both the chain 1 rule counter and
chain 0 match1 rule counter.
This will work, but now you take dependencies on each of the children rules, so if you delete the chain 1 rule, you need
to invalidate all the 1000 hardware rules. And what about route updates or neigh updates for the encap header dst_ip 8.8.8.8?
Any change to that, and you update all the 1000 rules with the new mac address (hardware encapsulation needs to set outer mac address not supplied but tunnel key).
What if we had a depth of 10 chains?
You'd also have to keep track of what fields were originally on the packet, and not a match resulting from a modifications,
See the following set of rules:
tc filter add dev1 ... chain 0 prio 1 flower src_mac <mac1> action pedit munge ex set dst mac <mac2> pipe action goto chain 1
tc filter add dev1 ... chain 0 prio 2 flower dst_mac <mac2> action goto chain 1
tc filter add dev1 ... chain 1 prio 1 flower dst_mac <mac3> action <action3>
tc filter add dev1 ... chain 1 prio 2 flower src_mac <mac1> action <action4>
How would you offload that at the time of adding this rules, and not tracing the actual packet route?
can you tell that the third rule won't be hit? Will you flatten all possible routes and offload that?
Now take what other datapath (ovs, bridges, netfilter) blocks besides tc can do, or actions like ct that need software backing (unless you merge the ct table) and add them to the mix.
A single point of unsupported match/action between those, and we won't be able to offload the entire path, we might
even spend a lot of resources (trying to merge) before we even know it can't be offloaded, instead of doing what we can support.
>> ------------------------------------------------------------
>>
>> Subject: [PATCH net-next] net/sched: Set default of CONFIG_NET_TC_SKB_EXT to N
>>
>> This a new feature, it is prefered that it defaults to N.
>>
>> Fixes: 95a7233c452a ('net: openvswitch: Set OvS recirc_id from tc chain index')
>> Signed-off-by: Paul Blakey<paulb@mellanox.com>
>> ---
>> net/sched/Kconfig | 1 -
>> 1 file changed, 1 deletion(-)
>>
>> diff --git a/net/sched/Kconfig b/net/sched/Kconfig
>> index b3faafe..4bb10b7 100644
>> --- a/net/sched/Kconfig
>> +++ b/net/sched/Kconfig
>> @@ -966,7 +966,6 @@ config NET_IFE_SKBTCINDEX
>> config NET_TC_SKB_EXT
>> bool "TC recirculation support"
>> depends on NET_CLS_ACT
>> - default y if NET_CLS_ACT
>> select SKB_EXTENSIONS
>>
>> help
> - Linus suggested we hide this option from user and autoselect if
> possible.
> - As Daniel said all distros will enable this.
> - If correctness is really our concern, giving users an option to
> select whether they want something to behave correctly seems like
> a hack of lowest kind. Perhaps it's time to add a CONFIG for TC
> offload in general? That's a meaningful set of functionality.
As I understand, Linus prefers this new feature to be default N and
that's the what the attached patch.
The changes to the OVS datapath (static key and DP_SET command) with the
userspace probe will ensure the correctness when the extension is disabled,
patch that I've yet to send is here:
https://www.spinics.net/lists/netdev/msg594175.html
This was going to be a part OvS userspace connection tracking offload
patches to OvS userspace.
Paul.
^ permalink raw reply
* Re: CONFIG_NET_TC_SKB_EXT
From: Edward Cree @ 2019-09-23 17:17 UTC (permalink / raw)
To: Paul Blakey, Jakub Kicinski
Cc: Pravin Shelar, Daniel Borkmann, Vlad Buslov, David Miller,
netdev@vger.kernel.org, Jiri Pirko, Cong Wang, Jamal Hadi Salim,
Simon Horman, Or Gerlitz
In-Reply-To: <68c6668c-f316-2ceb-31b0-8197d22990ae@mellanox.com>
On 23/09/2019 17:56, Paul Blakey wrote:
> Even following this approach in tc only is challenging for some
> scenarios, consider the following tc rules:
>
> tc filter add dev1 ... chain 0 flower <match1> action goto chain 1
> tc filter add dev1 ... chain 0 flower <match2> action goto chain 1
> tc filter add dev1 ... chain 0 flower <match3> action goto chain 1
> ..
> ..
> tc filter add dev1 ... chain 0 flower ip_dst <match1000> action goto chain 1
>
> tc filter add dev1 ... chain 1 flower ip_proto tcp action tunnel_key set dst_ip 8.8.8.8 action mirred egress redirect dev2
This one is easy, if a packet gets to the end of a chain without matching any rules then it just gets delivered to the uplink (PF), and software TC starts over from the beginning of chain 0. AFAICT this is the natural hardware behaviour for any design of offload, and it's inherently all-or-nothing.
> You'd also have to keep track of what fields were originally on the packet, and not a match resulting from a modifications,
> See the following set of rules:
> tc filter add dev1 ... chain 0 prio 1 flower src_mac <mac1> action pedit munge ex set dst mac <mac2> pipe action goto chain 1
> tc filter add dev1 ... chain 0 prio 2 flower dst_mac <mac2> action goto chain 1
> tc filter add dev1 ... chain 1 prio 1 flower dst_mac <mac3> action <action3>
> tc filter add dev1 ... chain 1 prio 2 flower src_mac <mac1> action <action4>
This one is slightly harder in that you have to either essentially 'gather up' actions as you go and only 'commit' them at the end of your processing pipeline (in which case you have to deal with the data hazard you cleverly included in your example), or keep a copy of the original packet around. But I don't see the data-hazard case as having any realistic use-cases (does anyone actually put actions other than ct before a goto chain?) and it's easy enough to detect it in SW at rule-insertion time.
FWIW I think the only way this infra will ever be used is: chain 0 rules match <blah> action ct zone <n> goto chain <m>; chain <m> rules match ct_state +xyz <blah> action <actually do stuff to packet>. This can be supported with a hardware pipeline with three tables in series in a fairly natural way — and since all the actions that modify the packet (rather than just directing subsequent matching) are at the end, the natural miss behaviour is deliver-unmodified.
I tried to explain this back on your [v3] net: openvswitch: Set OvS recirc_id from tc chain index, but you seemed set on your approach so I didn't persist. Now it looks like maybe I should have...
^ permalink raw reply
* Re: [PATCH trivial 1/2] net: Fix Kconfig indentation
From: Sven Eckelmann @ 2019-09-23 17:56 UTC (permalink / raw)
To: b.a.t.m.a.n
Cc: Krzysztof Kozlowski, David S. Miller, Michael Grzeschik,
Wolfgang Grandegger, Marc Kleine-Budde, Andrew Lunn,
Florian Fainelli, Heiner Kallweit, Alexey Kuznetsov,
Hideaki YOSHIFUJI, Pablo Neira Ayuso, Jozsef Kadlecsik,
Florian Westphal, Jiri Kosina, netdev, linux-kernel, linux-can,
linux-rdma, linux-wireless, netfilter-devel, coreteam, lvs-devel,
rds-devel
In-Reply-To: <20190923155243.6997-1-krzk@kernel.org>
[-- Attachment #1: Type: text/plain, Size: 967 bytes --]
On Monday, 23 September 2019 17:52:42 CEST Krzysztof Kozlowski wrote:
> --- a/net/batman-adv/Kconfig
> +++ b/net/batman-adv/Kconfig
> @@ -12,11 +12,11 @@ config BATMAN_ADV
> depends on NET
> select LIBCRC32C
> help
> - B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
> - a routing protocol for multi-hop ad-hoc mesh networks. The
> - networks may be wired or wireless. See
> - https://www.open-mesh.org/ for more information and user space
> - tools.
> + B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
> + a routing protocol for multi-hop ad-hoc mesh networks. The
> + networks may be wired or wireless. See
> + https://www.open-mesh.org/ for more information and user space
> + tools.
>
> config BATMAN_ADV_BATMAN_V
> bool "B.A.T.M.A.N. V protocol"
Acked-by: Sven Eckelmann <sven@narfation.org>
Kind regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* general protection fault in finish_writeback_work
From: syzbot @ 2019-09-23 18:26 UTC (permalink / raw)
To: linux-fsdevel, linux-kernel, netdev, syzkaller-bugs, viro
Hello,
syzbot found the following crash on:
HEAD commit: 24ccb0ab qede: qede_fp: simplify a bit 'qede_rx_build_skb()'
git tree: net
console output: https://syzkaller.appspot.com/x/log.txt?x=11a5b229600000
kernel config: https://syzkaller.appspot.com/x/.config?x=dfcf592db22b9132
dashboard link: https://syzkaller.appspot.com/bug?extid=828abc56e48ada4b0195
compiler: gcc (GCC) 9.0.0 20181231 (experimental)
Unfortunately, I don't have any reproducer for this crash yet.
IMPORTANT: if you fix the bug, please add the following tag to the commit:
Reported-by: syzbot+828abc56e48ada4b0195@syzkaller.appspotmail.com
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] PREEMPT SMP KASAN
CPU: 1 PID: 8777 Comm: kworker/u4:5 Not tainted 5.3.0+ #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS
Google 01/01/2011
Workqueue: writeback wb_workfn (flush-8:0)
RIP: 0010:__lock_acquire+0x1265/0x4e70 kernel/locking/lockdep.c:3828
Code: 00 0f 85 0e 26 00 00 48 81 c4 e8 00 00 00 5b 41 5c 41 5d 41 5e 41 5f
5d c3 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f
85 dd 2a 00 00 49 81 3e a0 25 06 8a 0f 84 4e ee ff
RSP: 0018:ffff88806930f938 EFLAGS: 00010007
RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: 03fffe22022b47e2 RSI: 0000000000000000 RDI: 0000000000000001
RBP: ffff88806930fa48 R08: 0000000000000001 R09: 0000000000000001
R10: fffffbfff138cf90 R11: ffff8880693002c0 R12: 1ffff110115a3f15
R13: 0000000000000000 R14: 1ffff110115a3f15 R15: 0000000000000001
FS: 0000000000000000(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f2136820ea0 CR3: 000000008ab86000 CR4: 00000000001406e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
lock_acquire+0x190/0x410 kernel/locking/lockdep.c:4487
__raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:110 [inline]
_raw_spin_lock_irqsave+0x95/0xcd kernel/locking/spinlock.c:159
__wake_up_common_lock+0xc8/0x150 kernel/sched/wait.c:122
__wake_up+0xe/0x10 kernel/sched/wait.c:142
finish_writeback_work.isra.0+0xf6/0x120 fs/fs-writeback.c:168
wb_do_writeback fs/fs-writeback.c:2030 [inline]
wb_workfn+0x34f/0x11e0 fs/fs-writeback.c:2070
process_one_work+0x9af/0x1740 kernel/workqueue.c:2269
worker_thread+0x98/0xe40 kernel/workqueue.c:2415
kthread+0x361/0x430 kernel/kthread.c:255
ret_from_fork+0x24/0x30 arch/x86/entry/entry_64.S:352
Modules linked in:
---[ end trace b7a1091622454beb ]---
RIP: 0010:__lock_acquire+0x1265/0x4e70 kernel/locking/lockdep.c:3828
Code: 00 0f 85 0e 26 00 00 48 81 c4 e8 00 00 00 5b 41 5c 41 5d 41 5e 41 5f
5d c3 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f
85 dd 2a 00 00 49 81 3e a0 25 06 8a 0f 84 4e ee ff
RSP: 0018:ffff88806930f938 EFLAGS: 00010007
RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: 03fffe22022b47e2 RSI: 0000000000000000 RDI: 0000000000000001
RBP: ffff88806930fa48 R08: 0000000000000001 R09: 0000000000000001
R10: fffffbfff138cf90 R11: ffff8880693002c0 R12: 1ffff110115a3f15
R13: 0000000000000000 R14: 1ffff110115a3f15 R15: 0000000000000001
FS: 0000000000000000(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f2136820ea0 CR3: 000000008ab86000 CR4: 00000000001406e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
---
This bug is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this bug report. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
^ permalink raw reply
* DSA driver kernel extension for dsa mv88e6190 switch
From: Zoran Stojsavljevic @ 2019-09-23 18:38 UTC (permalink / raw)
To: netdev
Hello Community,
We have interesting problem to solve using our HW platform. And I hope
somebody has the similar example, and some patches, which need to be
applied to the kernel (directory .../drivers/net/dsa/) to make this
application to work.
We have the configuration problem with the Marvell 88E6190 switch.
What the our problem is... Is the switch is NOT configured with the
EEPROM (24C512), which does not exist on the board. It is put in
autoconfig by HW straps (NOCPU mode). Once the MDIO command, issued to
probe the switch and read the make of it, the switch jumps out of the
autoconfig mode. There are some commands issued from the DSA to
configure the switch (to apply to switch TXC and RXC RGMII delays -
RGMII-ID mode), but this is not enough to make it work properly.
Once the configuration is not properly applied (NOT configured via
EEPROM 24C512). We have problems when the Linux booting phase comes to
LIBPHY. Since switch should be transparent to the PHYs at that time,
but my best guess, it is not!
Once LIBPHY starts writing to the switch (since MDIO commands are not
reaching PHYs), switch blocks. Exists from auto config mode and
refuses to respond (my best guess). So no ping possible on the
MV88E61890 MACs and through after Linux boots.
If we physically cut the MDIO line and put the switch in autoconfig
mode, then switch stays in autoconfig mode (by HW straps), but then it
is impossible to do RGMII TxC and RxC clock skew, since i.MX6 has the
silicon bug which does NOT allow this skew to be applied to i.MX6 (1.5
ns skew MUST be applied to the both clocks). If this done from the
DSA, (having MDIO fully in effect), the switch goes out of autoconfig
and does not finish the proper config.
I have here three questions, I hope there are some educated suggestions?
[1] Does this, what I wrote here, sound resonable (Google has very
little on it)?
[2] Does this problem with MV88E6190 switch could be solved
introducing some MV88E6190 configuration via RGMII mode in U-Boot
(setting the switch in U-boot and letting kernel do what it does, at
the end everything works seamlessly)?
[3] Does anybody have pointer to some similar patches for the DSA
driver addendum (NO U-boot involved), how to properly deal with this
problem and fully configure the switch from Linux DSA driver (chip.c
as switch config, and port.c files)??
Any advice is appreciated!
Thank you in advance,
Zoran
_______
^ permalink raw reply
* [PATCH bpf v2] selftests/bpf: test_progs: fix client/server race in tcp_rtt
From: Stanislav Fomichev @ 2019-09-23 18:41 UTC (permalink / raw)
To: netdev, bpf; +Cc: davem, ast, daniel, Stanislav Fomichev
This is the same problem I found earlier in test_sockopt_inherit:
there is a race between server thread doing accept() and client
thread doing connect(). Let's explicitly synchronize them via
pthread conditional variable.
v2:
* don't exit from server_thread without signaling condvar,
fixes possible issue where main() would wait forever (Andrii Nakryiko)
Fixes: b55873984dab ("selftests/bpf: test BPF_SOCK_OPS_RTT_CB")
Signed-off-by: Stanislav Fomichev <sdf@google.com>
---
.../selftests/bpf/prog_tests/tcp_rtt.c | 21 +++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c
index fdc0b3614a9e..a82da555b1b0 100644
--- a/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c
+++ b/tools/testing/selftests/bpf/prog_tests/tcp_rtt.c
@@ -203,14 +203,24 @@ static int start_server(void)
return fd;
}
+static pthread_mutex_t server_started_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t server_started = PTHREAD_COND_INITIALIZER;
+
static void *server_thread(void *arg)
{
struct sockaddr_storage addr;
socklen_t len = sizeof(addr);
int fd = *(int *)arg;
int client_fd;
+ int err;
+
+ err = listen(fd, 1);
+
+ pthread_mutex_lock(&server_started_mtx);
+ pthread_cond_signal(&server_started);
+ pthread_mutex_unlock(&server_started_mtx);
- if (CHECK_FAIL(listen(fd, 1)) < 0) {
+ if (CHECK_FAIL(err < 0)) {
perror("Failed to listed on socket");
return NULL;
}
@@ -248,7 +258,14 @@ void test_tcp_rtt(void)
if (CHECK_FAIL(server_fd < 0))
goto close_cgroup_fd;
- pthread_create(&tid, NULL, server_thread, (void *)&server_fd);
+ if (CHECK_FAIL(pthread_create(&tid, NULL, server_thread,
+ (void *)&server_fd)))
+ goto close_cgroup_fd;
+
+ pthread_mutex_lock(&server_started_mtx);
+ pthread_cond_wait(&server_started, &server_started_mtx);
+ pthread_mutex_unlock(&server_started_mtx);
+
CHECK_FAIL(run_test(cgroup_fd, server_fd));
close(server_fd);
close_cgroup_fd:
--
2.23.0.351.gc4317032e6-goog
^ permalink raw reply related
* Re: CONFIG_NET_TC_SKB_EXT
From: Marcelo Ricardo Leitner @ 2019-09-23 18:46 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Paul Blakey, Pravin Shelar, Daniel Borkmann, Vlad Buslov,
David Miller, netdev@vger.kernel.org, Jiri Pirko, Cong Wang,
Jamal Hadi Salim, Simon Horman, Or Gerlitz
In-Reply-To: <20190922144715.37f71fbf@cakuba.netronome.com>
On Sun, Sep 22, 2019 at 02:47:15PM -0700, Jakub Kicinski wrote:
> On Sun, 22 Sep 2019 14:51:44 +0300, Paul Blakey wrote:
...
> > ------------------------------------------------------------
> >
> > Subject: [PATCH net-next] net/sched: Set default of CONFIG_NET_TC_SKB_EXT to N
> >
> > This a new feature, it is prefered that it defaults to N.
> >
> > Fixes: 95a7233c452a ('net: openvswitch: Set OvS recirc_id from tc chain index')
> > Signed-off-by: Paul Blakey <paulb@mellanox.com>
> > ---
> > net/sched/Kconfig | 1 -
> > 1 file changed, 1 deletion(-)
> >
> > diff --git a/net/sched/Kconfig b/net/sched/Kconfig
> > index b3faafe..4bb10b7 100644
> > --- a/net/sched/Kconfig
> > +++ b/net/sched/Kconfig
> > @@ -966,7 +966,6 @@ config NET_IFE_SKBTCINDEX
> > config NET_TC_SKB_EXT
> > bool "TC recirculation support"
> > depends on NET_CLS_ACT
> > - default y if NET_CLS_ACT
> > select SKB_EXTENSIONS
> >
> > help
>
> - Linus suggested we hide this option from user and autoselect if
> possible.
> - As Daniel said all distros will enable this.
> - If correctness is really our concern, giving users an option to
> select whether they want something to behave correctly seems like
> a hack of lowest kind. Perhaps it's time to add a CONFIG for TC
> offload in general? That's a meaningful set of functionality.
Now that we have the static branch in place on OvS code, maybe we can
remove this option and rely just on NET_CLS_ACT instead (such as in
cls_api.c and skbuff.h).
Probing by OvS userspace is still somewhat possible, as the flag
OVS_DP_F_TC_RECIRC_SHARING wouldn't be known and be rejected
otherwise. 'somewhat because there is a limitation, as prior versions
(prior to this commit) didn't validate if the flags being set were at
least known. But this is not news.
General OvS performance won't suffer, thanks to the static branch.
Drivers won't allocate the skb extension just because. They will only
do it when tc offloading is being done and, as already explained in
the thread and other places, it's needed for correct operation. So
general performance is also ok here.
For tc sw datapath, maybe we can have another static branch in there,
more specifically at tcf_classify(). Not sure how to control/toggle
it, though.
^ permalink raw reply
* Re: [RFC] VSOCK: add support for MSG_PEEK
From: Matias Ezequiel Vara Larsen @ 2019-09-23 19:16 UTC (permalink / raw)
To: Stefano Garzarella
Cc: stefanha, davem, kvm, virtualization, netdev, linux-kernel
In-Reply-To: <20190923075830.a6sjwffnkljmyyqm@steredhat>
On Mon, Sep 23, 2019 at 09:58:30AM +0200, Stefano Garzarella wrote:
> Hi Matias,
> thanks for this patch!
>
> Since this patch only concerns virtio_transport,
> I'd use the 'vsock/virtio' prefix in the commit title:
> "vsock/virtio: add support for MSG_PEEK"
>
> Some comments below:
>
> On Sun, Sep 22, 2019 at 05:48:27PM +0000, Matias Ezequiel Vara Larsen wrote:
> > This patch adds support for MSG_PEEK. In such a case, packets are not
> > removed from the rx_queue and credit updates are not sent.
> >
> > Signed-off-by: Matias Ezequiel Vara Larsen <matiasevara@gmail.com>
> > ---
> > net/vmw_vsock/virtio_transport_common.c | 59 +++++++++++++++++++++++++++++++--
> > 1 file changed, 56 insertions(+), 3 deletions(-)
> >
> > diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
> > index 94cc0fa..830e890 100644
> > --- a/net/vmw_vsock/virtio_transport_common.c
> > +++ b/net/vmw_vsock/virtio_transport_common.c
> > @@ -264,6 +264,59 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk,
> > }
> >
> > static ssize_t
> > +virtio_transport_stream_do_peek(struct vsock_sock *vsk,
> > + struct msghdr *msg,
> > + size_t len)
> > +{
> > + struct virtio_vsock_sock *vvs = vsk->trans;
> > + struct virtio_vsock_pkt *pkt;
> > + size_t bytes, off = 0, total = 0;
> > + int err = -EFAULT;
> > +
> > + spin_lock_bh(&vvs->rx_lock);
> > +
>
> What about using list_for_each_entry() to cycle through the queued packets?
>
> > + if (list_empty(&vvs->rx_queue)) {
> > + spin_unlock_bh(&vvs->rx_lock);
> > + return 0;
> > + }
> > +
> > + pkt = list_first_entry(&vvs->rx_queue,
> > + struct virtio_vsock_pkt, list);
> > + do {
>
> pkt->off contains the offset inside the packet where the unread data starts.
> So here we should initialize 'off':
>
> off = pkt->off;
>
> Or just use pkt->off later (without increasing it as in the dequeue).
>
> > + bytes = len - total;
> > + if (bytes > pkt->len - off)
> > + bytes = pkt->len - off;
> > +
> > + /* sk_lock is held by caller so no one else can dequeue.
> > + * Unlock rx_lock since memcpy_to_msg() may sleep.
> > + */
> > + spin_unlock_bh(&vvs->rx_lock);
> > +
> > + err = memcpy_to_msg(msg, pkt->buf + off, bytes);
> > + if (err)
> > + goto out;
> > +
> > + spin_lock_bh(&vvs->rx_lock);
> > +
> > + total += bytes;
>
> Using list_for_each_entry(), here we can just do:
> (or better, at the beginning of the cycle)
>
> if (total == len)
> break;
>
> removing the next part...
>
> > + off += bytes;
> > + if (off == pkt->len) {
> > + pkt = list_next_entry(pkt, list);
> > + off = 0;
> > + }
> > + } while ((total < len) && !list_is_first(&pkt->list, &vvs->rx_queue));
>
> ...until here.
>
> > +
> > + spin_unlock_bh(&vvs->rx_lock);
> > +
> > + return total;
> > +
> > +out:
> > + if (total)
> > + err = total;
> > + return err;
> > +}
> > +
> > +static ssize_t
> > virtio_transport_stream_do_dequeue(struct vsock_sock *vsk,
> > struct msghdr *msg,
> > size_t len)
> > @@ -330,9 +383,9 @@ virtio_transport_stream_dequeue(struct vsock_sock *vsk,
> > size_t len, int flags)
> > {
> > if (flags & MSG_PEEK)
> > - return -EOPNOTSUPP;
> > -
> > - return virtio_transport_stream_do_dequeue(vsk, msg, len);
> > + return virtio_transport_stream_do_peek(vsk, msg, len);
> > + else
> > + return virtio_transport_stream_do_dequeue(vsk, msg, len);
> > }
> > EXPORT_SYMBOL_GPL(virtio_transport_stream_dequeue);
> >
>
> The rest looks good to me!
>
> Thanks,
> Stefano
Thanks Stefano. Based on your comments, I will modify the patch and
resubmit it.
Matias
^ permalink raw reply
* Re: DSA driver kernel extension for dsa mv88e6190 switch
From: Andrew Lunn @ 2019-09-23 19:17 UTC (permalink / raw)
To: Zoran Stojsavljevic; +Cc: netdev
In-Reply-To: <CAGAf8LzeyrMSHCYMxn1FNtMQVyhhLYbJaczhe2AMj+7T_nBt7Q@mail.gmail.com>
> We have the configuration problem with the Marvell 88E6190 switch.
> What the our problem is... Is the switch is NOT configured with the
> EEPROM (24C512), which does not exist on the board.
That is pretty normal. If there is a EEPROM, i generally recommend it
is left empty. We want Linux to configure the switch, and if it finds
it already partially configured, things can get confused.
> It is put in autoconfig by HW straps (NOCPU mode).
So dumb switch mode. All ports are switched between each other.
> Once the MDIO command, issued to
> probe the switch and read the make of it, the switch jumps out of the
> autoconfig mode.
Correct. Dumb switch mode is dangerous. There is no STP, etc.
Depending on what you have in device tree, the ports are either
configured down, or separated.
> There are some commands issued from the DSA to
> configure the switch (to apply to switch TXC and RXC RGMII delays -
> RGMII-ID mode), but this is not enough to make it work properly.
Define 'work properly'. How are you configuring the interfaces? Do
you remember to bring the master interface up? Are you adding the
interfaces to a bridge?
Andrew
^ permalink raw reply
* Re: [PATCH] Bluetooth: hidp: Fix assumptions on the return value of hidp_send_message
From: Andrey Smirnov @ 2019-09-23 20:33 UTC (permalink / raw)
To: Marcel Holtmann
Cc: Andrey Smirnov, Pierre-Loup A . Griffais, linux-input,
linux-kernel, linux-bluetooth, netdev
In-Reply-To: <3D70AB75-FEFB-4EB3-9AC8-3BCE90F5458D@holtmann.org>
> I am taking this through my tree. And yes, I applied the updated patch, but answered the other ;)
>
> Regards
>
> Marcel
Are you also going to mark this patch for inclusion to stable tree? I haven't seen it in any of the stable queues (netdev, Greg's), so just wanted to check.
Thanks,
Andrey Smirnov
^ permalink raw reply
* RE: [PATCH 1/6] mdev: class id support
From: Parav Pandit @ 2019-09-23 20:58 UTC (permalink / raw)
To: Jason Wang, kvm@vger.kernel.org, linux-s390@vger.kernel.org,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org,
intel-gvt-dev@lists.freedesktop.org, kwankhede@nvidia.com,
alex.williamson@redhat.com, mst@redhat.com, tiwei.bie@intel.com
Cc: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org,
cohuck@redhat.com, maxime.coquelin@redhat.com,
cunming.liang@intel.com, zhihong.wang@intel.com,
rob.miller@broadcom.com, xiao.w.wang@intel.com,
haotian.wang@sifive.com, zhenyuw@linux.intel.com,
zhi.a.wang@intel.com, jani.nikula@linux.intel.com,
joonas.lahtinen@linux.intel.com, rodrigo.vivi@intel.com,
airlied@linux.ie, daniel@ffwll.ch, farman@linux.ibm.com,
pasic@linux.ibm.com, sebott@linux.ibm.com, oberpar@linux.ibm.com,
heiko.carstens@de.ibm.com, gor@linux.ibm.com,
borntraeger@de.ibm.com, akrowiak@linux.ibm.com,
freude@linux.ibm.com, lingshan.zhu@intel.com, Ido Shamay,
eperezma@redhat.com, lulu@redhat.com
In-Reply-To: <20190923130331.29324-2-jasowang@redhat.com>
Hi Jason,
> -----Original Message-----
> From: Jason Wang <jasowang@redhat.com>
> Sent: Monday, September 23, 2019 8:03 AM
> To: kvm@vger.kernel.org; linux-s390@vger.kernel.org; linux-
> kernel@vger.kernel.org; dri-devel@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; intel-gvt-dev@lists.freedesktop.org;
> kwankhede@nvidia.com; alex.williamson@redhat.com; mst@redhat.com;
> tiwei.bie@intel.com
> Cc: virtualization@lists.linux-foundation.org; netdev@vger.kernel.org;
> cohuck@redhat.com; maxime.coquelin@redhat.com;
> cunming.liang@intel.com; zhihong.wang@intel.com;
> rob.miller@broadcom.com; xiao.w.wang@intel.com;
> haotian.wang@sifive.com; zhenyuw@linux.intel.com; zhi.a.wang@intel.com;
> jani.nikula@linux.intel.com; joonas.lahtinen@linux.intel.com;
> rodrigo.vivi@intel.com; airlied@linux.ie; daniel@ffwll.ch;
> farman@linux.ibm.com; pasic@linux.ibm.com; sebott@linux.ibm.com;
> oberpar@linux.ibm.com; heiko.carstens@de.ibm.com; gor@linux.ibm.com;
> borntraeger@de.ibm.com; akrowiak@linux.ibm.com; freude@linux.ibm.com;
> lingshan.zhu@intel.com; Ido Shamay <idos@mellanox.com>;
> eperezma@redhat.com; lulu@redhat.com; Parav Pandit
> <parav@mellanox.com>; Jason Wang <jasowang@redhat.com>
> Subject: [PATCH 1/6] mdev: class id support
>
> Mdev bus only supports vfio driver right now, so it doesn't implement match
> method. But in the future, we may add drivers other than vfio, one example is
> virtio-mdev[1] driver. This means we need to add device class id support in bus
> match method to pair the mdev device and mdev driver correctly.
>
> So this patch adds id_table to mdev_driver and class_id for mdev parent with
> the match method for mdev bus.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> Documentation/driver-api/vfio-mediated-device.rst | 7 +++++--
> drivers/gpu/drm/i915/gvt/kvmgt.c | 2 +-
> drivers/s390/cio/vfio_ccw_ops.c | 2 +-
> drivers/s390/crypto/vfio_ap_ops.c | 3 ++-
> drivers/vfio/mdev/mdev_core.c | 14 ++++++++++++--
> drivers/vfio/mdev/mdev_driver.c | 14 ++++++++++++++
> drivers/vfio/mdev/mdev_private.h | 1 +
> drivers/vfio/mdev/vfio_mdev.c | 6 ++++++
> include/linux/mdev.h | 7 ++++++-
> include/linux/mod_devicetable.h | 8 ++++++++
> samples/vfio-mdev/mbochs.c | 2 +-
> samples/vfio-mdev/mdpy.c | 2 +-
> samples/vfio-mdev/mtty.c | 2 +-
> 13 files changed, 59 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index 25eb7d5b834b..0e052072e1d8 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -102,12 +102,14 @@ structure to represent a mediated device's driver::
> * @probe: called when new device created
> * @remove: called when device removed
> * @driver: device driver structure
> + * @id_table: the ids serviced by this driver.
No full stop at the end.
> */
> struct mdev_driver {
> const char *name;
> int (*probe) (struct device *dev);
> void (*remove) (struct device *dev);
> struct device_driver driver;
> + const struct mdev_class_id *id_table;
> };
>
> A mediated bus driver for mdev should use this structure in the function calls
> @@ -116,7 +118,7 @@ to register and unregister itself with the core driver:
> * Register::
>
> extern int mdev_register_driver(struct mdev_driver *drv,
> - struct module *owner);
> + struct module *owner);
>
Unrelated change in this patch.
> * Unregister::
>
> @@ -163,7 +165,8 @@ A driver should use the mdev_parent_ops structure in
> the function call to register itself with the mdev core driver::
>
> extern int mdev_register_device(struct device *dev,
> - const struct mdev_parent_ops *ops);
> + const struct mdev_parent_ops *ops,
> + u8 class_id);
>
Cover letter from Change-V2 says that it class_id changed from " use u16 instead u8 for class id"
But it is still u8 here?
> However, the mdev_parent_ops structure is not required in the function call
> that a driver should use to unregister itself with the mdev core driver::
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 23aa3e50cbf8..19d51a35f019 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -1625,7 +1625,7 @@ static int kvmgt_host_init(struct device *dev, void
> *gvt, const void *ops)
> return -EFAULT;
> intel_vgpu_ops.supported_type_groups = kvm_vgpu_type_groups;
>
> - return mdev_register_device(dev, &intel_vgpu_ops);
> + return mdev_register_vfio_device(dev, &intel_vgpu_ops);
> }
>
> static void kvmgt_host_exit(struct device *dev) diff --git
> a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index
> f0d71ab77c50..246ff0f80944 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -588,7 +588,7 @@ static const struct mdev_parent_ops
> vfio_ccw_mdev_ops = {
>
> int vfio_ccw_mdev_reg(struct subchannel *sch) {
> - return mdev_register_device(&sch->dev, &vfio_ccw_mdev_ops);
> + return mdev_register_vfio_device(&sch->dev, &vfio_ccw_mdev_ops);
> }
>
> void vfio_ccw_mdev_unreg(struct subchannel *sch) diff --git
> a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
> index 5c0f53c6dde7..7487fc39d2c5 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -1295,7 +1295,8 @@ int vfio_ap_mdev_register(void) {
> atomic_set(&matrix_dev->available_instances,
> MAX_ZDEV_ENTRIES_EXT);
>
> - return mdev_register_device(&matrix_dev->device,
> &vfio_ap_matrix_ops);
> + return mdev_register_vfio_device(&matrix_dev->device,
> + &vfio_ap_matrix_ops);
> }
>
> void vfio_ap_mdev_unregister(void)
> diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
> index b558d4cfd082..a02c256a3514 100644
> --- a/drivers/vfio/mdev/mdev_core.c
> +++ b/drivers/vfio/mdev/mdev_core.c
> @@ -135,11 +135,14 @@ static int mdev_device_remove_cb(struct device
> *dev, void *data)
> * mdev_register_device : Register a device
> * @dev: device structure representing parent device.
> * @ops: Parent device operation structure to be registered.
> + * @id: device id.
> *
It device id here, but in below its class_id. Please make them uniform.
> * Add device to list of registered parent devices.
> * Returns a negative value on error, otherwise 0.
> */
> -int mdev_register_device(struct device *dev, const struct mdev_parent_ops
> *ops)
> +int mdev_register_device(struct device *dev,
> + const struct mdev_parent_ops *ops,
> + u8 class_id)
> {
u16 class_id?
> int ret;
> struct mdev_parent *parent;
> @@ -175,6 +178,7 @@ int mdev_register_device(struct device *dev, const
> struct mdev_parent_ops *ops)
>
> parent->dev = dev;
> parent->ops = ops;
> + parent->class_id = class_id;
>
> if (!mdev_bus_compat_class) {
> mdev_bus_compat_class =
> class_compat_register("mdev_bus");
> @@ -208,7 +212,13 @@ int mdev_register_device(struct device *dev, const
> struct mdev_parent_ops *ops)
> put_device(dev);
> return ret;
> }
> -EXPORT_SYMBOL(mdev_register_device);
> +
> +int mdev_register_vfio_device(struct device *dev,
> + const struct mdev_parent_ops *ops) {
> + return mdev_register_device(dev, ops, MDEV_ID_VFIO); }
> +EXPORT_SYMBOL(mdev_register_vfio_device);
>
> /*
> * mdev_unregister_device : Unregister a parent device diff --git
> a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c index
> 0d3223aee20b..b70bbebc9dd3 100644
> --- a/drivers/vfio/mdev/mdev_driver.c
> +++ b/drivers/vfio/mdev/mdev_driver.c
> @@ -69,8 +69,22 @@ static int mdev_remove(struct device *dev)
> return 0;
> }
>
> +static int mdev_match(struct device *dev, struct device_driver *drv) {
> + unsigned int i;
> + struct mdev_device *mdev = to_mdev_device(dev);
> + struct mdev_driver *mdrv = to_mdev_driver(drv);
> + const struct mdev_class_id *ids = mdrv->id_table;
> +
> + for (i = 0; ids[i].id; i++)
> + if (ids[i].id == mdev->parent->class_id)
> + return 1;
> + return 0;
> +}
> +
> struct bus_type mdev_bus_type = {
> .name = "mdev",
> + .match = mdev_match,
> .probe = mdev_probe,
> .remove = mdev_remove,
> };
> diff --git a/drivers/vfio/mdev/mdev_private.h
> b/drivers/vfio/mdev/mdev_private.h
> index 7d922950caaf..e58b07c866b1 100644
> --- a/drivers/vfio/mdev/mdev_private.h
> +++ b/drivers/vfio/mdev/mdev_private.h
> @@ -22,6 +22,7 @@ struct mdev_parent {
> struct list_head type_list;
> /* Synchronize device creation/removal with parent unregistration */
> struct rw_semaphore unreg_sem;
> + u8 class_id;
> };
>
> struct mdev_device {
> diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
> index 30964a4e0a28..fd2a4d9a3f26 100644
> --- a/drivers/vfio/mdev/vfio_mdev.c
> +++ b/drivers/vfio/mdev/vfio_mdev.c
> @@ -120,10 +120,16 @@ static void vfio_mdev_remove(struct device *dev)
> vfio_del_group_dev(dev);
> }
>
> +static struct mdev_class_id id_table[] = {
> + { MDEV_ID_VFIO },
> + { 0 },
> +};
> +
> static struct mdev_driver vfio_mdev_driver = {
> .name = "vfio_mdev",
> .probe = vfio_mdev_probe,
> .remove = vfio_mdev_remove,
> + .id_table = id_table,
> };
>
> static int __init vfio_mdev_init(void)
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h index
> 0ce30ca78db0..3ebae310f599 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -118,6 +118,7 @@ struct mdev_type_attribute mdev_type_attr_##_name
> = \
> * @probe: called when new device created
> * @remove: called when device removed
> * @driver: device driver structure
> + * @id_table: the ids serviced by this driver.
> *
> **/
> struct mdev_driver {
> @@ -125,6 +126,7 @@ struct mdev_driver {
> int (*probe)(struct device *dev);
> void (*remove)(struct device *dev);
> struct device_driver driver;
> + const struct mdev_class_id *id_table;
> };
>
> #define to_mdev_driver(drv) container_of(drv, struct mdev_driver, driver)
> @@ -135,7 +137,8 @@ const guid_t *mdev_uuid(struct mdev_device *mdev);
>
> extern struct bus_type mdev_bus_type;
>
> -int mdev_register_device(struct device *dev, const struct mdev_parent_ops
> *ops);
> +int mdev_register_vfio_device(struct device *dev,
> + const struct mdev_parent_ops *ops);
> void mdev_unregister_device(struct device *dev);
>
> int mdev_register_driver(struct mdev_driver *drv, struct module *owner);
> @@ -145,4 +148,6 @@ struct device *mdev_parent_dev(struct mdev_device
> *mdev); struct device *mdev_dev(struct mdev_device *mdev); struct
> mdev_device *mdev_from_dev(struct device *dev);
>
> +#define MDEV_ID_VFIO 1 /* VFIO device */
> +
Instead of define, please put them as enum
enum mdev_class/device_id {
MDEV_ID_VFIO = 1,
/* New entries must be added here */
};
> #endif /* MDEV_H */
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 5714fd35a83c..f32c6e44fb1a 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -821,4 +821,12 @@ struct wmi_device_id {
> const void *context;
> };
>
> +/**
> + * struct mdev_class_id - MDEV device class identifier
> + * @id: Used to identify a specific class of device, e.g vfio-mdev device.
> + */
> +struct mdev_class_id {
> + __u16 id;
> +};
This is u16 as I guess you wanted as opposed to u8 in other places in patch.
> +
> #endif /* LINUX_MOD_DEVICETABLE_H */
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c index
> ac5c8c17b1ff..71a4469be85d 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -1468,7 +1468,7 @@ static int __init mbochs_dev_init(void)
> if (ret)
> goto failed2;
>
> - ret = mdev_register_device(&mbochs_dev, &mdev_fops);
> + ret = mdev_register_vfio_device(&mbochs_dev, &mdev_fops);
> if (ret)
> goto failed3;
>
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c index
> cc86bf6566e4..d3029dd27d91 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -775,7 +775,7 @@ static int __init mdpy_dev_init(void)
> if (ret)
> goto failed2;
>
> - ret = mdev_register_device(&mdpy_dev, &mdev_fops);
> + ret = mdev_register_vfio_device(&mdpy_dev, &mdev_fops);
> if (ret)
> goto failed3;
>
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c index
> 92e770a06ea2..744c88a6b22c 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -1468,7 +1468,7 @@ static int __init mtty_dev_init(void)
> if (ret)
> goto failed2;
>
> - ret = mdev_register_device(&mtty_dev.dev, &mdev_fops);
> + ret = mdev_register_vfio_device(&mtty_dev.dev, &mdev_fops);
> if (ret)
> goto failed3;
>
> --
> 2.19.1
^ permalink raw reply
* RE: [PATCH 1/6] mdev: class id support
From: Parav Pandit @ 2019-09-23 21:02 UTC (permalink / raw)
To: Jason Wang, kvm@vger.kernel.org, linux-s390@vger.kernel.org,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org,
intel-gvt-dev@lists.freedesktop.org, kwankhede@nvidia.com,
alex.williamson@redhat.com, mst@redhat.com, tiwei.bie@intel.com
Cc: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org,
cohuck@redhat.com, maxime.coquelin@redhat.com,
cunming.liang@intel.com, zhihong.wang@intel.com,
rob.miller@broadcom.com, xiao.w.wang@intel.com,
haotian.wang@sifive.com, zhenyuw@linux.intel.com,
zhi.a.wang@intel.com, jani.nikula@linux.intel.com,
joonas.lahtinen@linux.intel.com, rodrigo.vivi@intel.com,
airlied@linux.ie, daniel@ffwll.ch, farman@linux.ibm.com,
pasic@linux.ibm.com, sebott@linux.ibm.com, oberpar@linux.ibm.com,
heiko.carstens@de.ibm.com, gor@linux.ibm.com,
borntraeger@de.ibm.com, akrowiak@linux.ibm.com,
freude@linux.ibm.com, lingshan.zhu@intel.com, Ido Shamay,
eperezma@redhat.com, lulu@redhat.com
In-Reply-To: <20190923130331.29324-2-jasowang@redhat.com>
Hi Jason,
> -----Original Message-----
> From: Jason Wang <jasowang@redhat.com>
> Sent: Monday, September 23, 2019 8:03 AM
> To: kvm@vger.kernel.org; linux-s390@vger.kernel.org; linux-
> kernel@vger.kernel.org; dri-devel@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; intel-gvt-dev@lists.freedesktop.org;
> kwankhede@nvidia.com; alex.williamson@redhat.com; mst@redhat.com;
> tiwei.bie@intel.com
> Cc: virtualization@lists.linux-foundation.org; netdev@vger.kernel.org;
> cohuck@redhat.com; maxime.coquelin@redhat.com;
> cunming.liang@intel.com; zhihong.wang@intel.com;
> rob.miller@broadcom.com; xiao.w.wang@intel.com;
> haotian.wang@sifive.com; zhenyuw@linux.intel.com; zhi.a.wang@intel.com;
> jani.nikula@linux.intel.com; joonas.lahtinen@linux.intel.com;
> rodrigo.vivi@intel.com; airlied@linux.ie; daniel@ffwll.ch;
> farman@linux.ibm.com; pasic@linux.ibm.com; sebott@linux.ibm.com;
> oberpar@linux.ibm.com; heiko.carstens@de.ibm.com; gor@linux.ibm.com;
> borntraeger@de.ibm.com; akrowiak@linux.ibm.com; freude@linux.ibm.com;
> lingshan.zhu@intel.com; Ido Shamay <idos@mellanox.com>;
> eperezma@redhat.com; lulu@redhat.com; Parav Pandit
> <parav@mellanox.com>; Jason Wang <jasowang@redhat.com>
> Subject: [PATCH 1/6] mdev: class id support
>
> Mdev bus only supports vfio driver right now, so it doesn't implement match
> method. But in the future, we may add drivers other than vfio, one example is
> virtio-mdev[1] driver. This means we need to add device class id support in bus
> match method to pair the mdev device and mdev driver correctly.
>
> So this patch adds id_table to mdev_driver and class_id for mdev parent with
> the match method for mdev bus.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> Documentation/driver-api/vfio-mediated-device.rst | 7 +++++--
> drivers/gpu/drm/i915/gvt/kvmgt.c | 2 +-
> drivers/s390/cio/vfio_ccw_ops.c | 2 +-
> drivers/s390/crypto/vfio_ap_ops.c | 3 ++-
> drivers/vfio/mdev/mdev_core.c | 14 ++++++++++++--
> drivers/vfio/mdev/mdev_driver.c | 14 ++++++++++++++
> drivers/vfio/mdev/mdev_private.h | 1 +
> drivers/vfio/mdev/vfio_mdev.c | 6 ++++++
> include/linux/mdev.h | 7 ++++++-
> include/linux/mod_devicetable.h | 8 ++++++++
> samples/vfio-mdev/mbochs.c | 2 +-
> samples/vfio-mdev/mdpy.c | 2 +-
> samples/vfio-mdev/mtty.c | 2 +-
> 13 files changed, 59 insertions(+), 11 deletions(-)
>
You additionally need modpost support for id table integration to modifo, modprobe and other tools.
A small patch similar to this one [1] is needed.
Please include in the series.
[1] https://lore.kernel.org/patchwork/patch/1046991/
^ permalink raw reply
* Re: [PATCH net] net: sched: fix possible crash in tcf_action_destroy()
From: Cong Wang @ 2019-09-23 21:10 UTC (permalink / raw)
To: Eric Dumazet
Cc: Jakub Kicinski, Eric Dumazet, David S . Miller, netdev, syzbot,
Vlad Buslov, Jiri Pirko
In-Reply-To: <4e2ff069-e1f5-492f-14eb-5348e2cab907@gmail.com>
On Mon, Sep 23, 2019 at 8:44 AM Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
>
>
> On 9/21/19 7:08 PM, Jakub Kicinski wrote:
> > On Wed, 18 Sep 2019 14:37:21 -0700, Cong Wang wrote:
> >> On Wed, Sep 18, 2019 at 12:57 PM 'Eric Dumazet' via syzkaller
> >> <syzkaller@googlegroups.com> wrote:
> >>>
> >>> If the allocation done in tcf_exts_init() failed,
> >>> we end up with a NULL pointer in exts->actions.
> >> ...
> >>> diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
> >>> index efd3cfb80a2ad775dc8ab3c4900bd73d52c7aaad..9aef93300f1c11791acbb9262dfe77996872eafe 100644
> >>> --- a/net/sched/cls_api.c
> >>> +++ b/net/sched/cls_api.c
> >>> @@ -3027,8 +3027,10 @@ static int tc_dump_chain(struct sk_buff *skb, struct netlink_callback *cb)
> >>> void tcf_exts_destroy(struct tcf_exts *exts)
> >>> {
> >>> #ifdef CONFIG_NET_CLS_ACT
> >>> - tcf_action_destroy(exts->actions, TCA_ACT_UNBIND);
> >>> - kfree(exts->actions);
> >>> + if (exts->actions) {
> >>
> >> I think it is _slightly_ better to check exts->nr_actions!=0 here,
> >> as it would help exts->actions!=NULL&& exts->nr_actions==0
> >> cases too.
> >>
> >> What do you think?
> >
> > Alternatively, since tcf_exts_destroy() now takes NULL, and so
> > obviously does kfree() - perhaps tcf_action_destroy() should
> > return early if actions are NULL?
> >
>
> I do not have any preference really, this is slow path and was trying to
> fix a crash.
>
> tcf_action_destroy() makes me nervous, since it seems to be able to break its loop
> in case __tcf_idr_release() returns an error. This means that some actions will
> never be release.
Good point. Seems we can just continue the loop even when
-EPERM is returned, there is in fact no harm to leave those still
bound to filters there until the filers release them. Not sure if we
should still propagate -EPERM to users in this partially failure
case.
^ permalink raw reply
* Re: [PATCH] kcm: use BPF_PROG_RUN
From: Eric Dumazet @ 2019-09-23 21:31 UTC (permalink / raw)
To: Alexei Starovoitov, Yonghong Song
Cc: Sami Tolvanen, David S. Miller, Tom Herbert,
netdev@vger.kernel.org, bpf@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <CAADnVQJxrPDZtKAik4VEzvw=TwY6PoWytfp7HcQt5Jsaja7mxw@mail.gmail.com>
On 9/6/19 10:06 AM, Alexei Starovoitov wrote:
> On Fri, Sep 6, 2019 at 3:03 AM Yonghong Song <yhs@fb.com> wrote:
>>
>>
>>
>> On 9/5/19 2:15 PM, Sami Tolvanen wrote:
>>> Instead of invoking struct bpf_prog::bpf_func directly, use the
>>> BPF_PROG_RUN macro.
>>>
>>> Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
>>
>> Acked-by: Yonghong Song <yhs@fb.com>
>
> Applied. Thanks
>
Then we probably need this as well, what do you think ?
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 8f12f5c6ab875ebaa6c59c6268c337919fb43bb9..6508e88efdaf57f206b84307f5ad5915a2ed21f7 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -378,8 +378,13 @@ static int kcm_parse_func_strparser(struct strparser *strp, struct sk_buff *skb)
{
struct kcm_psock *psock = container_of(strp, struct kcm_psock, strp);
struct bpf_prog *prog = psock->bpf_prog;
+ int res;
- return BPF_PROG_RUN(prog, skb);
+ preempt_disable();
+ res = BPF_PROG_RUN(prog, skb);
+ preempt_enable();
+
+ return res;
}
static int kcm_read_sock_done(struct strparser *strp, int err)
^ permalink raw reply related
* [linux-firmware][pull request] ice: Add package file for Intel E800 series driver
From: Jeff Kirsher @ 2019-09-23 21:56 UTC (permalink / raw)
To: linux-firmware
Cc: Tony Nguyen, netdev, nhorman, sassmann, poswald, Andrew Bowers,
Jeff Kirsher
From: Tony Nguyen <anthony.l.nguyen@intel.com>
The ice driver must load a package file to the firmware to utilize full
functionality; add the package file to /lib/firmware/intel/ice/ddp. Also
add a symlink, ice.pkg, so the driver can refer to the package by a
consistent name.
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---
The following are changes since commit 417a9c6e197a8d3eec792494efc87a2b42f76324:
amdgpu: add initial navi10 firmware
and are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/firmware dev-queue
LICENSE.ice | 39 ++++++++++++++++++++++++++++++++++
WHENCE | 9 ++++++++
intel/ice/ddp/ice-1.3.4.0.pkg | Bin 0 -> 577796 bytes
intel/ice/ddp/ice.pkg | 1 +
4 files changed, 49 insertions(+)
create mode 100644 LICENSE.ice
create mode 100644 intel/ice/ddp/ice-1.3.4.0.pkg
create mode 120000 intel/ice/ddp/ice.pkg
diff --git a/LICENSE.ice b/LICENSE.ice
new file mode 100644
index 0000000..497ee18
--- /dev/null
+++ b/LICENSE.ice
@@ -0,0 +1,39 @@
+Copyright (c) 2019, Intel Corporation.
+All rights reserved.
+
+Redistribution. Redistribution and use in binary form, without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions must reproduce the above copyright notice and the
+ following disclaimer in the documentation and/or other materials
+ provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its suppliers
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+* No reverse engineering, decompilation, or disassembly of this software
+ is permitted.
+
+Limited patent license. Intel Corporation grants a world-wide,
+royalty-free, non-exclusive license under patents it now or hereafter
+owns or controls to make, have made, use, import, offer to sell and
+sell ("Utilize") this software, but solely to the extent that any
+such patent is necessary to Utilize the software alone, or in
+combination with an operating system licensed under an approved Open
+Source license as listed by the Open Source Initiative at
+http://opensource.org/licenses. The patent license shall not apply to
+any other combinations which include this software. No hardware per
+se is licensed hereunder.
+
+DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
diff --git a/WHENCE b/WHENCE
index 55ab617..5f9abb1 100644
--- a/WHENCE
+++ b/WHENCE
@@ -4585,3 +4585,12 @@ File: meson/vdec/gxl_mpeg4_5.bin
File: meson/vdec/gxm_h264.bin
Licence: Redistributable. See LICENSE.amlogic_vdec for details.
+
+--------------------------------------------------------------------------
+
+Driver: ice - Intel(R) Ethernet Connection E800 Series
+
+File: intel/ice/ddp/ice-1.3.4.0.pkg
+Link: intel/ice/ddp/ice.pkg -> intel/ice/ddp/ice-1.3.4.0.pkg
+
+License: Redistributable. See LICENSE.ice for details
diff --git a/intel/ice/ddp/ice-1.3.4.0.pkg b/intel/ice/ddp/ice-1.3.4.0.pkg
new file mode 100644
index 0000000000000000000000000000000000000000..67443c3ccc5c37efe6ded702beceec60bdf7b792
GIT binary patch
literal 577796
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
apf#X1pf#X1pf#X1pf#X1pf%9D2L2zPeQI0)
literal 0
HcmV?d00001
diff --git a/intel/ice/ddp/ice.pkg b/intel/ice/ddp/ice.pkg
new file mode 120000
index 0000000..ec0ab09
--- /dev/null
+++ b/intel/ice/ddp/ice.pkg
@@ -0,0 +1 @@
+ice-1.3.4.0.pkg
\ No newline at end of file
--
2.21.0
^ permalink raw reply related
* [PATCH v2 net] net: sched: fix possible crash in tcf_action_destroy()
From: Eric Dumazet @ 2019-09-23 22:18 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Eric Dumazet, Eric Dumazet, syzbot, Cong Wang,
Vlad Buslov, Jiri Pirko
If the allocation done in tcf_exts_init() failed,
we end up with a NULL pointer in exts->actions.
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] PREEMPT SMP KASAN
CPU: 1 PID: 8198 Comm: syz-executor.3 Not tainted 5.3.0-rc8+ #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
RIP: 0010:tcf_action_destroy+0x71/0x160 net/sched/act_api.c:705
Code: c3 08 44 89 ee e8 4f cb bb fb 41 83 fd 20 0f 84 c9 00 00 00 e8 c0 c9 bb fb 48 89 d8 48 b9 00 00 00 00 00 fc ff df 48 c1 e8 03 <80> 3c 08 00 0f 85 c0 00 00 00 4c 8b 33 4d 85 f6 0f 84 9d 00 00 00
RSP: 0018:ffff888096e16ff0 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 0000000000000000 RCX: dffffc0000000000
RDX: 0000000000040000 RSI: ffffffff85b6ab30 RDI: 0000000000000000
RBP: ffff888096e17020 R08: ffff8880993f6140 R09: fffffbfff11cae67
R10: fffffbfff11cae66 R11: ffffffff88e57333 R12: 0000000000000000
R13: 0000000000000000 R14: ffff888096e177a0 R15: 0000000000000001
FS: 00007f62bc84a700(0000) GS:ffff8880ae900000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000758040 CR3: 0000000088b64000 CR4: 00000000001426e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
tcf_exts_destroy+0x38/0xb0 net/sched/cls_api.c:3030
tcindex_set_parms+0xf7f/0x1e50 net/sched/cls_tcindex.c:488
tcindex_change+0x230/0x318 net/sched/cls_tcindex.c:519
tc_new_tfilter+0xa4b/0x1c70 net/sched/cls_api.c:2152
rtnetlink_rcv_msg+0x838/0xb00 net/core/rtnetlink.c:5214
netlink_rcv_skb+0x177/0x450 net/netlink/af_netlink.c:2477
rtnetlink_rcv+0x1d/0x30 net/core/rtnetlink.c:5241
netlink_unicast_kernel net/netlink/af_netlink.c:1302 [inline]
netlink_unicast+0x531/0x710 net/netlink/af_netlink.c:1328
netlink_sendmsg+0x8a5/0xd60 net/netlink/af_netlink.c:1917
sock_sendmsg_nosec net/socket.c:637 [inline]
sock_sendmsg+0xd7/0x130 net/socket.c:657
___sys_sendmsg+0x3e2/0x920 net/socket.c:2311
__sys_sendmmsg+0x1bf/0x4d0 net/socket.c:2413
__do_sys_sendmmsg net/socket.c:2442 [inline]
Fixes: 90b73b77d08e ("net: sched: change action API to use array of pointers to actions")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Cc: Cong Wang <xiyou.wangcong@gmail.com>
Cc: Vlad Buslov <vladbu@mellanox.com>
Cc: Jiri Pirko <jiri@mellanox.com>
---
net/sched/act_api.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 2558f00f6b3eda64a87f63c32592c15b7a0a2bfe..b58742e22afb8c40badc64f4d7c4e676839d7d07 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -702,6 +702,9 @@ int tcf_action_destroy(struct tc_action *actions[], int bind)
struct tc_action *a;
int ret = 0, i;
+ if (!actions)
+ return 0;
+
for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
a = actions[i];
actions[i] = NULL;
--
2.23.0.351.gc4317032e6-goog
^ permalink raw reply related
* Re: linux-next: Tree for Aug 7 (net/bridge/netfilter/nf_conntrack_bridge.c)
From: Ivan Kalvachev @ 2019-09-23 22:26 UTC (permalink / raw)
To: Jeremy Sowden
Cc: Randy Dunlap, Stephen Rothwell, Linux Next Mailing List,
Linux Kernel Mailing List, netdev@vger.kernel.org, bridge
In-Reply-To: <20190807155738.GA9394@azazel.net>
On 8/7/19, Jeremy Sowden <jeremy@azazel.net> wrote:
> On 2019-08-07, at 08:29:44 -0700, Randy Dunlap wrote:
>> On 8/7/19 1:36 AM, Stephen Rothwell wrote:
>> > Hi all,
>> >
>> > Changes since 20190806:
>>
>> on i386:
>> when CONFIG_NF_TABLES is not set/enabled:
>>
>> CC net/bridge/netfilter/nf_conntrack_bridge.o
>> In file included from
>> ../net/bridge/netfilter/nf_conntrack_bridge.c:21:0:
>> ../include/net/netfilter/nf_tables.h: In function
>> ‘nft_gencursor_next’:
>> ../include/net/netfilter/nf_tables.h:1224:14: error: ‘const struct
>> net’ has no member named ‘nft’; did you mean ‘nf’?
>> return net->nft.gencursor + 1 == 1 ? 1 : 0;
>> ^~~
>
> I've just posted a series of fixes for netfilter header compilation
> failures, and I think it includes the fix for that:
>
>
> https://lore.kernel.org/netdev/20190807141705.4864-5-jeremy@azazel.net/T/#u
Have these patches been committed?
I just hit the same bug in linux-5.3.1 release.
^ permalink raw reply
* [PATCH] r8152: Use guard clause and fix comment typos
From: Prashant Malani @ 2019-09-23 22:26 UTC (permalink / raw)
To: hayeswang; +Cc: grundler, netdev, nic_swsd, Prashant Malani
Use a guard clause in tx_bottom() to reduce the indentation of the
do-while loop. In doing so, convert the do-while to a while to make the
guard clause checks consistent.
Also, fix a couple of spelling and grammatical mistakes in the
r8152_csum_workaround() function comment.
Change-Id: I460befde150ad92248fd85b0f189ec2df2ab8431
Signed-off-by: Prashant Malani <pmalani@chromium.org>
Reviewed-by: Grant Grundler <grundler@chromium.org>
---
drivers/net/usb/r8152.c | 36 ++++++++++++++++++------------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 08726090570e1..82bc69a5b24fb 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1688,7 +1688,7 @@ static struct tx_agg *r8152_get_tx_agg(struct r8152 *tp)
}
/* r8152_csum_workaround()
- * The hw limites the value the transport offset. When the offset is out of the
+ * The hw limits the value of the transport offset. When the offset is out of
* range, calculate the checksum by sw.
*/
static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
@@ -2177,8 +2177,9 @@ static void tx_bottom(struct r8152 *tp)
{
int res;
- do {
+ while (1) {
struct tx_agg *agg;
+ struct net_device *netdev = tp->netdev;
if (skb_queue_empty(&tp->tx_queue))
break;
@@ -2188,26 +2189,25 @@ static void tx_bottom(struct r8152 *tp)
break;
res = r8152_tx_agg_fill(tp, agg);
- if (res) {
- struct net_device *netdev = tp->netdev;
+ if (!res)
+ break;
- if (res == -ENODEV) {
- rtl_set_unplug(tp);
- netif_device_detach(netdev);
- } else {
- struct net_device_stats *stats = &netdev->stats;
- unsigned long flags;
+ if (res == -ENODEV) {
+ rtl_set_unplug(tp);
+ netif_device_detach(netdev);
+ } else {
+ struct net_device_stats *stats = &netdev->stats;
+ unsigned long flags;
- netif_warn(tp, tx_err, netdev,
- "failed tx_urb %d\n", res);
- stats->tx_dropped += agg->skb_num;
+ netif_warn(tp, tx_err, netdev,
+ "failed tx_urb %d\n", res);
+ stats->tx_dropped += agg->skb_num;
- spin_lock_irqsave(&tp->tx_lock, flags);
- list_add_tail(&agg->list, &tp->tx_free);
- spin_unlock_irqrestore(&tp->tx_lock, flags);
- }
+ spin_lock_irqsave(&tp->tx_lock, flags);
+ list_add_tail(&agg->list, &tp->tx_free);
+ spin_unlock_irqrestore(&tp->tx_lock, flags);
}
- } while (res == 0);
+ }
}
static void bottom_half(unsigned long data)
--
2.23.0.351.gc4317032e6-goog
^ permalink raw reply related
* RE: [PATCH 4/6] virtio: introduce a mdev based transport
From: Parav Pandit @ 2019-09-23 22:28 UTC (permalink / raw)
To: Jason Wang, kvm@vger.kernel.org, linux-s390@vger.kernel.org,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org,
intel-gvt-dev@lists.freedesktop.org, kwankhede@nvidia.com,
alex.williamson@redhat.com, mst@redhat.com, tiwei.bie@intel.com
Cc: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org,
cohuck@redhat.com, maxime.coquelin@redhat.com,
cunming.liang@intel.com, zhihong.wang@intel.com,
rob.miller@broadcom.com, xiao.w.wang@intel.com,
haotian.wang@sifive.com, zhenyuw@linux.intel.com,
zhi.a.wang@intel.com, jani.nikula@linux.intel.com,
joonas.lahtinen@linux.intel.com, rodrigo.vivi@intel.com,
airlied@linux.ie, daniel@ffwll.ch, farman@linux.ibm.com,
pasic@linux.ibm.com, sebott@linux.ibm.com, oberpar@linux.ibm.com,
heiko.carstens@de.ibm.com, gor@linux.ibm.com,
borntraeger@de.ibm.com, akrowiak@linux.ibm.com,
freude@linux.ibm.com, lingshan.zhu@intel.com, Ido Shamay,
eperezma@redhat.com, lulu@redhat.com
In-Reply-To: <20190923130331.29324-5-jasowang@redhat.com>
> -----Original Message-----
> From: Jason Wang <jasowang@redhat.com>
> Sent: Monday, September 23, 2019 8:03 AM
> To: kvm@vger.kernel.org; linux-s390@vger.kernel.org; linux-
> kernel@vger.kernel.org; dri-devel@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; intel-gvt-dev@lists.freedesktop.org;
> kwankhede@nvidia.com; alex.williamson@redhat.com; mst@redhat.com;
> tiwei.bie@intel.com
> Cc: virtualization@lists.linux-foundation.org; netdev@vger.kernel.org;
> cohuck@redhat.com; maxime.coquelin@redhat.com;
> cunming.liang@intel.com; zhihong.wang@intel.com;
> rob.miller@broadcom.com; xiao.w.wang@intel.com;
> haotian.wang@sifive.com; zhenyuw@linux.intel.com; zhi.a.wang@intel.com;
> jani.nikula@linux.intel.com; joonas.lahtinen@linux.intel.com;
> rodrigo.vivi@intel.com; airlied@linux.ie; daniel@ffwll.ch;
> farman@linux.ibm.com; pasic@linux.ibm.com; sebott@linux.ibm.com;
> oberpar@linux.ibm.com; heiko.carstens@de.ibm.com; gor@linux.ibm.com;
> borntraeger@de.ibm.com; akrowiak@linux.ibm.com; freude@linux.ibm.com;
> lingshan.zhu@intel.com; Ido Shamay <idos@mellanox.com>;
> eperezma@redhat.com; lulu@redhat.com; Parav Pandit
> <parav@mellanox.com>; Jason Wang <jasowang@redhat.com>
> Subject: [PATCH 4/6] virtio: introduce a mdev based transport
>
> This patch introduces a new mdev transport for virtio. This is used to use kernel
> virtio driver to drive the mediated device that is capable of populating
> virtqueue directly.
>
> A new virtio-mdev driver will be registered to the mdev bus, when a new virtio-
> mdev device is probed, it will register the device with mdev based config ops.
> This means it is a software transport between mdev driver and mdev device.
> The transport was implemented through device specific opswhich is a part of
> mdev_parent_ops now.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> MAINTAINERS | 1 +
> drivers/vfio/mdev/Kconfig | 7 +
> drivers/vfio/mdev/Makefile | 1 +
> drivers/vfio/mdev/virtio_mdev.c | 416 ++++++++++++++++++++++++++++++++
> 4 files changed, 425 insertions(+)
> create mode 100644 drivers/vfio/mdev/virtio_mdev.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 89832b316500..820ec250cc52 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17202,6 +17202,7 @@ F: include/linux/virtio*.h
> F: include/uapi/linux/virtio_*.h
> F: drivers/crypto/virtio/
> F: mm/balloon_compaction.c
> +F: drivers/vfio/mdev/virtio_mdev.c
>
> VIRTIO BLOCK AND SCSI DRIVERS
> M: "Michael S. Tsirkin" <mst@redhat.com>
> diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig index
> 5da27f2100f9..c488c31fc137 100644
> --- a/drivers/vfio/mdev/Kconfig
> +++ b/drivers/vfio/mdev/Kconfig
> @@ -16,3 +16,10 @@ config VFIO_MDEV_DEVICE
> default n
> help
> VFIO based driver for Mediated devices.
> +
> +config VIRTIO_MDEV_DEVICE
> + tristate "VIRTIO driver for Mediated devices"
> + depends on VFIO_MDEV && VIRTIO
> + default n
> + help
> + VIRTIO based driver for Mediated devices.
> diff --git a/drivers/vfio/mdev/Makefile b/drivers/vfio/mdev/Makefile index
> 101516fdf375..99d31e29c23e 100644
> --- a/drivers/vfio/mdev/Makefile
> +++ b/drivers/vfio/mdev/Makefile
> @@ -4,3 +4,4 @@ mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o
>
> obj-$(CONFIG_VFIO_MDEV) += mdev.o
> obj-$(CONFIG_VFIO_MDEV_DEVICE) += vfio_mdev.o
> +obj-$(CONFIG_VIRTIO_MDEV_DEVICE) += virtio_mdev.o
> diff --git a/drivers/vfio/mdev/virtio_mdev.c b/drivers/vfio/mdev/virtio_mdev.c
> new file mode 100644 index 000000000000..919a082adc9c
> --- /dev/null
> +++ b/drivers/vfio/mdev/virtio_mdev.c
> @@ -0,0 +1,416 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * VIRTIO based driver for Mediated device
> + *
> + * Copyright (c) 2019, Red Hat. All rights reserved.
> + * Author: Jason Wang <jasowang@redhat.com>
> + *
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/uuid.h>
> +#include <linux/mdev.h>
> +#include <linux/virtio_mdev.h>
> +#include <linux/virtio.h>
> +#include <linux/virtio_config.h>
> +#include <linux/virtio_ring.h>
> +#include "mdev_private.h"
> +
> +#define DRIVER_VERSION "0.1"
> +#define DRIVER_AUTHOR "Red Hat Corporation"
> +#define DRIVER_DESC "VIRTIO based driver for Mediated device"
> +
> +#define to_virtio_mdev_device(dev) \
> + container_of(dev, struct virtio_mdev_device, vdev)
> +
> +struct virtio_mdev_device {
> + struct virtio_device vdev;
> + struct mdev_device *mdev;
> + unsigned long version;
> +
> + struct virtqueue **vqs;
Every lock must need a comment to describe what it locks.
I don't see this lock is used in this patch. Please introduce in the patch that uses it.
> + spinlock_t lock;
> +};
> +
> +struct virtio_mdev_vq_info {
> + /* the actual virtqueue */
> + struct virtqueue *vq;
> +
> + /* the list node for the virtqueues list */
> + struct list_head node;
> +};
> +
> +static struct mdev_device *vm_get_mdev(struct virtio_device *vdev) {
> + struct virtio_mdev_device *vm_dev = to_virtio_mdev_device(vdev);
> + struct mdev_device *mdev = vm_dev->mdev;
> +
> + return mdev;
> +}
> +
> +static const struct virtio_mdev_parent_ops *mdev_get_parent_ops(struct
> +mdev_device *mdev) {
> + struct mdev_parent *parent = mdev->parent;
> +
> + return parent->ops->device_ops;
> +}
> +
> +static void virtio_mdev_get(struct virtio_device *vdev, unsigned offset,
> + void *buf, unsigned len)
> +{
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + ops->get_config(mdev, offset, buf, len); }
> +
> +static void virtio_mdev_set(struct virtio_device *vdev, unsigned offset,
> + const void *buf, unsigned len)
> +{
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + ops->set_config(mdev, offset, buf, len); }
> +
> +static u32 virtio_mdev_generation(struct virtio_device *vdev) {
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + return ops->get_generation(mdev);
> +}
> +
> +static u8 virtio_mdev_get_status(struct virtio_device *vdev) {
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + return ops->get_status(mdev);
> +}
> +
> +static void virtio_mdev_set_status(struct virtio_device *vdev, u8
> +status) {
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + return ops->set_status(mdev, status);
> +}
> +
> +static void virtio_mdev_reset(struct virtio_device *vdev) {
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + return ops->set_status(mdev, 0);
> +}
> +
> +static bool virtio_mdev_notify(struct virtqueue *vq) {
> + struct mdev_device *mdev = vm_get_mdev(vq->vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + ops->kick_vq(mdev, vq->index);
> +
> + return true;
> +}
> +
> +static irqreturn_t virtio_mdev_config_cb(void *private) {
> + struct virtio_mdev_device *vm_dev = private;
> +
> + virtio_config_changed(&vm_dev->vdev);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t virtio_mdev_virtqueue_cb(void *private) {
> + struct virtio_mdev_vq_info *info = private;
> +
> + return vring_interrupt(0, info->vq);
> +}
> +
> +static struct virtqueue *
> +virtio_mdev_setup_vq(struct virtio_device *vdev, unsigned index,
> + void (*callback)(struct virtqueue *vq),
> + const char *name, bool ctx)
> +{
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> + struct virtio_mdev_vq_info *info;
> + struct virtio_mdev_callback cb;
> + struct virtqueue *vq;
> + u32 align, num;
> + u64 desc_addr, driver_addr, device_addr;
> + int err;
> +
> + if (!name)
> + return NULL;
> +
> + /* Queue shouldn't already be set up. */
> + if (ops->get_vq_ready(mdev, index)) {
> + err = -ENOENT;
> + goto error_available;
> + }
> +
No need for a goto, to single return done later.
Just do
if (ops->get_vq_ready(mdev, index))
return -ENOENT;
> + /* Allocate and fill out our active queue description */
> + info = kmalloc(sizeof(*info), GFP_KERNEL);
> + if (!info) {
> + err = -ENOMEM;
> + goto error_kmalloc;
> + }
> +
Similar to above one.
> + num = ops->get_queue_max(mdev);
> + if (num == 0) {
> + err = -ENOENT;
> + goto error_new_virtqueue;
> + }
> +
> + /* Create the vring */
> + align = ops->get_vq_align(mdev);
> + vq = vring_create_virtqueue(index, num, align, vdev,
> + true, true, ctx,
> + virtio_mdev_notify, callback, name);
> + if (!vq) {
> + err = -ENOMEM;
> + goto error_new_virtqueue;
> + }
> +
> + /* Setup virtqueue callback */
> + cb.callback = virtio_mdev_virtqueue_cb;
> + cb.private = info;
> + ops->set_vq_cb(mdev, index, &cb);
> + ops->set_vq_num(mdev, index, virtqueue_get_vring_size(vq));
> +
> + desc_addr = virtqueue_get_desc_addr(vq);
> + driver_addr = virtqueue_get_avail_addr(vq);
> + device_addr = virtqueue_get_used_addr(vq);
> +
> + if (ops->set_vq_address(mdev, index,
> + desc_addr, driver_addr,
> + device_addr)) {
> + err = -EINVAL;
> + goto err_vq;
> + }
> +
> + ops->set_vq_ready(mdev, index, 1);
> +
> + vq->priv = info;
> + info->vq = vq;
> +
> + return vq;
> +
> +err_vq:
> + vring_del_virtqueue(vq);
> +error_new_virtqueue:
> + ops->set_vq_ready(mdev, index, 0);
> + WARN_ON(ops->get_vq_ready(mdev, index));
> + kfree(info);
> +error_kmalloc:
> +error_available:
> + return ERR_PTR(err);
> +
> +}
> +
> +static void virtio_mdev_del_vq(struct virtqueue *vq) {
> + struct mdev_device *mdev = vm_get_mdev(vq->vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> + struct virtio_mdev_vq_info *info = vq->priv;
> + unsigned int index = vq->index;
> +
> + /* Select and deactivate the queue */
> + ops->set_vq_ready(mdev, index, 0);
> + WARN_ON(ops->get_vq_ready(mdev, index));
> +
> + vring_del_virtqueue(vq);
> +
> + kfree(info);
> +}
> +
> +static void virtio_mdev_del_vqs(struct virtio_device *vdev) {
> + struct virtqueue *vq, *n;
> +
> + list_for_each_entry_safe(vq, n, &vdev->vqs, list)
> + virtio_mdev_del_vq(vq);
> +}
> +
> +static int virtio_mdev_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> + struct virtqueue *vqs[],
> + vq_callback_t *callbacks[],
> + const char * const names[],
> + const bool *ctx,
> + struct irq_affinity *desc)
> +{
> + struct virtio_mdev_device *vm_dev = to_virtio_mdev_device(vdev);
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> + struct virtio_mdev_callback cb;
> + int i, err, queue_idx = 0;
> +
> + vm_dev->vqs = kmalloc_array(queue_idx, sizeof(*vm_dev->vqs),
> + GFP_KERNEL);
> + if (!vm_dev->vqs)
> + return -ENOMEM;
> +
> + for (i = 0; i < nvqs; ++i) {
> + if (!names[i]) {
> + vqs[i] = NULL;
> + continue;
> + }
> +
> + vqs[i] = virtio_mdev_setup_vq(vdev, queue_idx++,
> + callbacks[i], names[i], ctx ?
> + ctx[i] : false);
> + if (IS_ERR(vqs[i])) {
> + err = PTR_ERR(vqs[i]);
> + goto err_setup_vq;
> + }
> + }
> +
> + cb.callback = virtio_mdev_config_cb;
> + cb.private = vm_dev;
> + ops->set_config_cb(mdev, &cb);
> +
> + return 0;
> +
> +err_setup_vq:
> + kfree(vm_dev->vqs);
> + virtio_mdev_del_vqs(vdev);
> + return err;
> +}
> +
> +static u64 virtio_mdev_get_features(struct virtio_device *vdev) {
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + return ops->get_features(mdev);
> +}
> +
> +static int virtio_mdev_finalize_features(struct virtio_device *vdev) {
> + struct mdev_device *mdev = vm_get_mdev(vdev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> +
> + /* Give virtio_ring a chance to accept features. */
> + vring_transport_features(vdev);
> +
> + return ops->set_features(mdev, vdev->features); }
> +
> +static const char *virtio_mdev_bus_name(struct virtio_device *vdev) {
> + struct virtio_mdev_device *vm_dev = to_virtio_mdev_device(vdev);
> + struct mdev_device *mdev = vm_dev->mdev;
> +
> + return dev_name(&mdev->dev);
> +}
> +
> +static const struct virtio_config_ops virtio_mdev_config_ops = {
> + .get = virtio_mdev_get,
> + .set = virtio_mdev_set,
> + .generation = virtio_mdev_generation,
> + .get_status = virtio_mdev_get_status,
> + .set_status = virtio_mdev_set_status,
> + .reset = virtio_mdev_reset,
> + .find_vqs = virtio_mdev_find_vqs,
> + .del_vqs = virtio_mdev_del_vqs,
> + .get_features = virtio_mdev_get_features,
> + .finalize_features = virtio_mdev_finalize_features,
> + .bus_name = virtio_mdev_bus_name,
> +};
> +
> +static void virtio_mdev_release_dev(struct device *_d) {
> + struct virtio_device *vdev =
> + container_of(_d, struct virtio_device, dev);
> + struct virtio_mdev_device *vm_dev =
> + container_of(vdev, struct virtio_mdev_device, vdev);
> +
> + devm_kfree(_d, vm_dev);
> +}
> +
> +static int virtio_mdev_probe(struct device *dev) {
> + struct mdev_device *mdev = to_mdev_device(dev);
> + const struct virtio_mdev_parent_ops *ops =
> mdev_get_parent_ops(mdev);
> + struct virtio_mdev_device *vm_dev;
> + int rc;
> +
> + vm_dev = devm_kzalloc(dev, sizeof(*vm_dev), GFP_KERNEL);
> + if (!vm_dev)
> + return -ENOMEM;
> +
> + vm_dev->vdev.dev.parent = dev;
> + vm_dev->vdev.dev.release = virtio_mdev_release_dev;
> + vm_dev->vdev.config = &virtio_mdev_config_ops;
> + vm_dev->mdev = mdev;
> + vm_dev->vqs = NULL;
> + spin_lock_init(&vm_dev->lock);
> +
> + vm_dev->version = ops->get_version(mdev);
> + if (vm_dev->version != 1) {
> + dev_err(dev, "Version %ld not supported!\n",
> + vm_dev->version);
> + return -ENXIO;
> + }
> +
> + vm_dev->vdev.id.device = ops->get_device_id(mdev);
> + if (vm_dev->vdev.id.device == 0)
> + return -ENODEV;
> +
> + vm_dev->vdev.id.vendor = ops->get_vendor_id(mdev);
> + rc = register_virtio_device(&vm_dev->vdev);
> + if (rc)
> + put_device(dev);
> +
> + dev_set_drvdata(dev, vm_dev);
No need to set drvdata when there is error returned from register_virtio_device().
> +
> + return rc;
> +
Extra line not needed.
> +}
> +
> +static void virtio_mdev_remove(struct device *dev) {
> + struct virtio_mdev_device *vm_dev = dev_get_drvdata(dev);
> +
> + unregister_virtio_device(&vm_dev->vdev);
> +}
> +
> +static struct mdev_class_id id_table[] = {
> + { MDEV_ID_VIRTIO },
> + { 0 },
> +};
> +
> +static struct mdev_driver virtio_mdev_driver = {
> + .name = "virtio_mdev",
> + .probe = virtio_mdev_probe,
> + .remove = virtio_mdev_remove,
No need for tab, just do single white space.
> + .id_table = id_table,
> +};
> +
> +static int __init virtio_mdev_init(void) {
> + return mdev_register_driver(&virtio_mdev_driver, THIS_MODULE); }
> +
> +static void __exit virtio_mdev_exit(void) {
> + mdev_unregister_driver(&virtio_mdev_driver);
> +}
> +
> +module_init(virtio_mdev_init)
> +module_exit(virtio_mdev_exit)
> +
> +MODULE_VERSION(DRIVER_VERSION);
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR(DRIVER_AUTHOR);
> +MODULE_DESCRIPTION(DRIVER_DESC);
> --
> 2.19.1
^ permalink raw reply
* Re: linux-next: Tree for Aug 7 (net/bridge/netfilter/nf_conntrack_bridge.c)
From: Jeremy Sowden @ 2019-09-23 22:48 UTC (permalink / raw)
To: Ivan Kalvachev
Cc: Randy Dunlap, Stephen Rothwell, Linux Next Mailing List,
Linux Kernel Mailing List, netdev@vger.kernel.org, bridge
In-Reply-To: <CABA=pqeES0C2+7GpAOYuCOqd5DrbZhjS1Tkrxn4kGxXQJkrAfg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1376 bytes --]
On 2019-09-24, at 01:26:22 +0300, Ivan Kalvachev wrote:
> On 8/7/19, Jeremy Sowden <jeremy@azazel.net> wrote:
> > On 2019-08-07, at 08:29:44 -0700, Randy Dunlap wrote:
> > > On 8/7/19 1:36 AM, Stephen Rothwell wrote:
> > > > Changes since 20190806:
> > >
> > > on i386:
> > > when CONFIG_NF_TABLES is not set/enabled:
> > >
> > > CC net/bridge/netfilter/nf_conntrack_bridge.o
> > > In file included from
> > > ../net/bridge/netfilter/nf_conntrack_bridge.c:21:0:
> > > ../include/net/netfilter/nf_tables.h: In function
> > > ‘nft_gencursor_next’:
> > > ../include/net/netfilter/nf_tables.h:1224:14: error: ‘const struct
> > > net’ has no member named ‘nft’; did you mean ‘nf’?
> > > return net->nft.gencursor + 1 == 1 ? 1 : 0;
> > > ^~~
> >
> > I've just posted a series of fixes for netfilter header compilation
> > failures, and I think it includes the fix for that:
> >
> >
> > https://lore.kernel.org/netdev/20190807141705.4864-5-jeremy@azazel.net/T/#u
>
> Have these patches been committed?
>
> I just hit the same bug in linux-5.3.1 release.
The series is now in the mainline (and will form part of 5.4-rc1). Greg
has queued the patch that fixes this build-failure for 5.3-stable:
https://lore.kernel.org/netfilter-devel/20190921112145.GA2408749@kroah.com/T/
so it should be in 5.3.2.
J.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: general protection fault in xsk_map_update_elem
From: Daniel Borkmann @ 2019-09-23 22:50 UTC (permalink / raw)
To: syzbot
Cc: ast, bjorn.topel, bpf, davem, hawk, jakub.kicinski,
john.fastabend, jonathan.lemon, kafai, linux-kernel,
magnus.karlsson, netdev, songliubraving, syzkaller-bugs, yhs
In-Reply-To: <0000000000006a3a2f05933a5c53@google.com>
On Mon, Sep 23, 2019 at 08:49:11AM -0700, syzbot wrote:
> Hello,
>
> syzbot found the following crash on:
>
> HEAD commit: b41dae06 Merge tag 'xfs-5.4-merge-7' of git://git.kernel.o..
> git tree: net-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=130b25ad600000
> kernel config: https://syzkaller.appspot.com/x/.config?x=dfcf592db22b9132
> dashboard link: https://syzkaller.appspot.com/bug?extid=491c1b7565ba9069ecae
> compiler: gcc (GCC) 9.0.0 20181231 (experimental)
> syz repro: https://syzkaller.appspot.com/x/repro.syz?x=155a0c29600000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=172bf6d9600000
>
> The bug was bisected to:
>
> commit 0402acd683c678874df6bdbc23530ca07ea19353
> Author: Björn Töpel <bjorn.topel@intel.com>
> Date: Thu Aug 15 09:30:13 2019 +0000
>
> xsk: remove AF_XDP socket from map when the socket is released
Bjorn, PTAL, thanks.
^ permalink raw reply
* RE: [PATCH 2/6] mdev: introduce device specific ops
From: Parav Pandit @ 2019-09-23 22:59 UTC (permalink / raw)
To: Jason Wang, kvm@vger.kernel.org, linux-s390@vger.kernel.org,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
intel-gfx@lists.freedesktop.org,
intel-gvt-dev@lists.freedesktop.org, kwankhede@nvidia.com,
alex.williamson@redhat.com, mst@redhat.com, tiwei.bie@intel.com
Cc: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org,
cohuck@redhat.com, maxime.coquelin@redhat.com,
cunming.liang@intel.com, zhihong.wang@intel.com,
rob.miller@broadcom.com, xiao.w.wang@intel.com,
haotian.wang@sifive.com, zhenyuw@linux.intel.com,
zhi.a.wang@intel.com, jani.nikula@linux.intel.com,
joonas.lahtinen@linux.intel.com, rodrigo.vivi@intel.com,
airlied@linux.ie, daniel@ffwll.ch, farman@linux.ibm.com,
pasic@linux.ibm.com, sebott@linux.ibm.com, oberpar@linux.ibm.com,
heiko.carstens@de.ibm.com, gor@linux.ibm.com,
borntraeger@de.ibm.com, akrowiak@linux.ibm.com,
freude@linux.ibm.com, lingshan.zhu@intel.com, Ido Shamay,
eperezma@redhat.com, lulu@redhat.com
In-Reply-To: <20190923130331.29324-3-jasowang@redhat.com>
> -----Original Message-----
> From: Jason Wang <jasowang@redhat.com>
> Sent: Monday, September 23, 2019 8:03 AM
> To: kvm@vger.kernel.org; linux-s390@vger.kernel.org; linux-
> kernel@vger.kernel.org; dri-devel@lists.freedesktop.org; intel-
> gfx@lists.freedesktop.org; intel-gvt-dev@lists.freedesktop.org;
> kwankhede@nvidia.com; alex.williamson@redhat.com; mst@redhat.com;
> tiwei.bie@intel.com
> Cc: virtualization@lists.linux-foundation.org; netdev@vger.kernel.org;
> cohuck@redhat.com; maxime.coquelin@redhat.com;
> cunming.liang@intel.com; zhihong.wang@intel.com;
> rob.miller@broadcom.com; xiao.w.wang@intel.com;
> haotian.wang@sifive.com; zhenyuw@linux.intel.com; zhi.a.wang@intel.com;
> jani.nikula@linux.intel.com; joonas.lahtinen@linux.intel.com;
> rodrigo.vivi@intel.com; airlied@linux.ie; daniel@ffwll.ch;
> farman@linux.ibm.com; pasic@linux.ibm.com; sebott@linux.ibm.com;
> oberpar@linux.ibm.com; heiko.carstens@de.ibm.com; gor@linux.ibm.com;
> borntraeger@de.ibm.com; akrowiak@linux.ibm.com; freude@linux.ibm.com;
> lingshan.zhu@intel.com; Ido Shamay <idos@mellanox.com>;
> eperezma@redhat.com; lulu@redhat.com; Parav Pandit
> <parav@mellanox.com>; Jason Wang <jasowang@redhat.com>
> Subject: [PATCH 2/6] mdev: introduce device specific ops
>
> Currently, except for the create and remove. The rest of mdev_parent_ops is
> designed for vfio-mdev driver only and may not help for kernel mdev driver.
> Follow the class id support by previous patch, this patch introduces device
> specific ops pointer inside parent ops which points to device specific ops (e.g
> vfio ops). This allows the future drivers like virtio-mdev to implement its own
> device specific ops.
>
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> .../driver-api/vfio-mediated-device.rst | 4 +-
> MAINTAINERS | 1 +
> drivers/gpu/drm/i915/gvt/kvmgt.c | 15 +++---
> drivers/s390/cio/vfio_ccw_ops.c | 15 ++++--
> drivers/s390/crypto/vfio_ap_ops.c | 11 ++--
> drivers/vfio/mdev/vfio_mdev.c | 31 ++++++-----
> include/linux/mdev.h | 36 ++-----------
> include/linux/vfio_mdev.h | 53 +++++++++++++++++++
> samples/vfio-mdev/mbochs.c | 17 +++---
> samples/vfio-mdev/mdpy.c | 17 +++---
> samples/vfio-mdev/mtty.c | 15 ++++--
> 11 files changed, 138 insertions(+), 77 deletions(-) create mode 100644
> include/linux/vfio_mdev.h
>
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index 0e052072e1d8..3ab00e48212f 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -152,7 +152,9 @@ callbacks per mdev parent device, per mdev type, or
> any other categorization.
> Vendor drivers are expected to be fully asynchronous in this respect or
> provide their own internal resource protection.)
>
> -The callbacks in the mdev_parent_ops structure are as follows:
> +The device specific callbacks are referred through device_ops pointer
> +in mdev_parent_ops. For vfio-mdev device, its callbacks in device_ops
> +are as follows:
>
> * open: open callback of mediated device
> * close: close callback of mediated device diff --git a/MAINTAINERS
> b/MAINTAINERS index b2326dece28e..89832b316500 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17075,6 +17075,7 @@ S: Maintained
> F: Documentation/driver-api/vfio-mediated-device.rst
> F: drivers/vfio/mdev/
> F: include/linux/mdev.h
> +F: include/linux/vfio_mdev.h
> F: samples/vfio-mdev/
>
> VFIO PLATFORM DRIVER
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 19d51a35f019..8ea86b1e69f1 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -42,6 +42,7 @@
> #include <linux/kvm_host.h>
> #include <linux/vfio.h>
> #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
> #include <linux/debugfs.h>
>
> #include <linux/nospec.h>
> @@ -1600,20 +1601,22 @@ static const struct attribute_group
> *intel_vgpu_groups[] = {
> NULL,
> };
>
> -static struct mdev_parent_ops intel_vgpu_ops = {
> - .mdev_attr_groups = intel_vgpu_groups,
> - .create = intel_vgpu_create,
> - .remove = intel_vgpu_remove,
> -
> +static struct vfio_mdev_parent_ops intel_vfio_vgpu_ops = {
Naming it with _dev prefix as intel_vfio_vgpu_dev_ops is better to differentiate with parent_ops.
> .open = intel_vgpu_open,
> .release = intel_vgpu_release,
> -
> .read = intel_vgpu_read,
> .write = intel_vgpu_write,
> .mmap = intel_vgpu_mmap,
> .ioctl = intel_vgpu_ioctl,
> };
>
> +static struct mdev_parent_ops intel_vgpu_ops = {
> + .mdev_attr_groups = intel_vgpu_groups,
> + .create = intel_vgpu_create,
> + .remove = intel_vgpu_remove,
> + .device_ops = &intel_vfio_vgpu_ops,
> +};
> +
> static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops) {
> struct attribute **kvm_type_attrs;
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
> index 246ff0f80944..02122bbc213e 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -12,6 +12,7 @@
>
> #include <linux/vfio.h>
> #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
> #include <linux/nospec.h>
> #include <linux/slab.h>
>
> @@ -574,11 +575,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct
> mdev_device *mdev,
> }
> }
>
> -static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
> - .owner = THIS_MODULE,
> - .supported_type_groups = mdev_type_groups,
> - .create = vfio_ccw_mdev_create,
> - .remove = vfio_ccw_mdev_remove,
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
> .open = vfio_ccw_mdev_open,
> .release = vfio_ccw_mdev_release,
> .read = vfio_ccw_mdev_read,
> @@ -586,6 +583,14 @@ static const struct mdev_parent_ops
> vfio_ccw_mdev_ops = {
> .ioctl = vfio_ccw_mdev_ioctl,
> };
>
> +static const struct mdev_parent_ops vfio_ccw_mdev_ops = {
> + .owner = THIS_MODULE,
> + .supported_type_groups = mdev_type_groups,
> + .create = vfio_ccw_mdev_create,
> + .remove = vfio_ccw_mdev_remove,
> + .device_ops = &vfio_mdev_ops,
> +};
> +
> int vfio_ccw_mdev_reg(struct subchannel *sch) {
> return mdev_register_vfio_device(&sch->dev, &vfio_ccw_mdev_ops);
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 7487fc39d2c5..4251becc7a6d 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -16,6 +16,7 @@
> #include <linux/bitops.h>
> #include <linux/kvm_host.h>
> #include <linux/module.h>
> +#include <linux/vfio_mdev.h>
> #include <asm/kvm.h>
> #include <asm/zcrypt.h>
>
> @@ -1280,15 +1281,19 @@ static ssize_t vfio_ap_mdev_ioctl(struct
> mdev_device *mdev,
> return ret;
> }
>
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
> + .open = vfio_ap_mdev_open,
> + .release = vfio_ap_mdev_release,
> + .ioctl = vfio_ap_mdev_ioctl,
> +};
> +
> static const struct mdev_parent_ops vfio_ap_matrix_ops = {
> .owner = THIS_MODULE,
> .supported_type_groups = vfio_ap_mdev_type_groups,
> .mdev_attr_groups = vfio_ap_mdev_attr_groups,
> .create = vfio_ap_mdev_create,
> .remove = vfio_ap_mdev_remove,
> - .open = vfio_ap_mdev_open,
> - .release = vfio_ap_mdev_release,
> - .ioctl = vfio_ap_mdev_ioctl,
> + .device_ops = &vfio_mdev_ops,
> };
>
> int vfio_ap_mdev_register(void)
> diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
> index fd2a4d9a3f26..d23c9f58c84f 100644
> --- a/drivers/vfio/mdev/vfio_mdev.c
> +++ b/drivers/vfio/mdev/vfio_mdev.c
> @@ -14,6 +14,7 @@
> #include <linux/slab.h>
> #include <linux/vfio.h>
> #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
>
> #include "mdev_private.h"
>
> @@ -25,15 +26,16 @@ static int vfio_mdev_open(void *device_data) {
> struct mdev_device *mdev = device_data;
> struct mdev_parent *parent = mdev->parent;
> + const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
> int ret;
>
> - if (unlikely(!parent->ops->open))
> + if (unlikely(!ops->open))
> return -EINVAL;
>
device_ops is optional and can be NULL for mdev devices which are not required to be mapped via vfio.
So please change to,
If (!ops || !ops->open)
return -EINVAL;
and rest of the below places.
> if (!try_module_get(THIS_MODULE))
> return -ENODEV;
>
> - ret = parent->ops->open(mdev);
> + ret = ops->open(mdev);
> if (ret)
> module_put(THIS_MODULE);
>
> @@ -44,9 +46,10 @@ static void vfio_mdev_release(void *device_data) {
> struct mdev_device *mdev = device_data;
> struct mdev_parent *parent = mdev->parent;
> + const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>
> - if (likely(parent->ops->release))
> - parent->ops->release(mdev);
> + if (likely(ops->release))
> + ops->release(mdev);
>
> module_put(THIS_MODULE);
> }
> @@ -56,11 +59,12 @@ static long vfio_mdev_unlocked_ioctl(void
> *device_data, {
> struct mdev_device *mdev = device_data;
> struct mdev_parent *parent = mdev->parent;
> + const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>
> - if (unlikely(!parent->ops->ioctl))
> + if (unlikely(!ops->ioctl))
> return -EINVAL;
>
> - return parent->ops->ioctl(mdev, cmd, arg);
> + return ops->ioctl(mdev, cmd, arg);
> }
>
> static ssize_t vfio_mdev_read(void *device_data, char __user *buf, @@ -68,11
> +72,12 @@ static ssize_t vfio_mdev_read(void *device_data, char __user *buf,
> {
> struct mdev_device *mdev = device_data;
> struct mdev_parent *parent = mdev->parent;
> + const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>
> - if (unlikely(!parent->ops->read))
> + if (unlikely(!ops->read))
> return -EINVAL;
>
> - return parent->ops->read(mdev, buf, count, ppos);
> + return ops->read(mdev, buf, count, ppos);
> }
>
> static ssize_t vfio_mdev_write(void *device_data, const char __user *buf, @@
> -80,22 +85,24 @@ static ssize_t vfio_mdev_write(void *device_data, const char
> __user *buf, {
> struct mdev_device *mdev = device_data;
> struct mdev_parent *parent = mdev->parent;
> + const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>
> - if (unlikely(!parent->ops->write))
> + if (unlikely(!ops->write))
> return -EINVAL;
>
> - return parent->ops->write(mdev, buf, count, ppos);
> + return ops->write(mdev, buf, count, ppos);
> }
>
> static int vfio_mdev_mmap(void *device_data, struct vm_area_struct *vma) {
> struct mdev_device *mdev = device_data;
> struct mdev_parent *parent = mdev->parent;
> + const struct vfio_mdev_parent_ops *ops = parent->ops->device_ops;
>
> - if (unlikely(!parent->ops->mmap))
> + if (unlikely(!ops->mmap))
> return -EINVAL;
>
> - return parent->ops->mmap(mdev, vma);
> + return ops->mmap(mdev, vma);
> }
>
> static const struct vfio_device_ops vfio_mdev_dev_ops = { diff --git
> a/include/linux/mdev.h b/include/linux/mdev.h index
> 3ebae310f599..fa167bcb81e1 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -48,30 +48,8 @@ struct device *mdev_get_iommu_device(struct device
> *dev);
> * @mdev: mdev_device device structure which is being
> * destroyed
> * Returns integer: success (0) or error (< 0)
> - * @open: Open mediated device.
> - * @mdev: mediated device.
> - * Returns integer: success (0) or error (< 0)
> - * @release: release mediated device
> - * @mdev: mediated device.
> - * @read: Read emulation callback
> - * @mdev: mediated device structure
> - * @buf: read buffer
> - * @count: number of bytes to read
> - * @ppos: address.
> - * Retuns number on bytes read on success or error.
> - * @write: Write emulation callback
> - * @mdev: mediated device structure
> - * @buf: write buffer
> - * @count: number of bytes to be written
> - * @ppos: address.
> - * Retuns number on bytes written on success or error.
> - * @ioctl: IOCTL callback
> - * @mdev: mediated device structure
> - * @cmd: ioctl command
> - * @arg: arguments to ioctl
> - * @mmap: mmap callback
> - * @mdev: mediated device structure
> - * @vma: vma structure
> + * @device_ops: Device specific emulation callback.
> + *
> * Parent device that support mediated device should be registered with mdev
> * module with mdev_parent_ops structure.
> **/
> @@ -83,15 +61,7 @@ struct mdev_parent_ops {
>
> int (*create)(struct kobject *kobj, struct mdev_device *mdev);
> int (*remove)(struct mdev_device *mdev);
> - int (*open)(struct mdev_device *mdev);
> - void (*release)(struct mdev_device *mdev);
> - ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
> - size_t count, loff_t *ppos);
> - ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
> - size_t count, loff_t *ppos);
> - long (*ioctl)(struct mdev_device *mdev, unsigned int cmd,
> - unsigned long arg);
> - int (*mmap)(struct mdev_device *mdev, struct vm_area_struct
> *vma);
> + const void *device_ops;
> };
>
> /* interface for exporting mdev supported type attributes */ diff --git
> a/include/linux/vfio_mdev.h b/include/linux/vfio_mdev.h new file mode
> 100644 index 000000000000..0c1b34f98f5d
> --- /dev/null
> +++ b/include/linux/vfio_mdev.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * VFIO Mediated device definition
> + */
> +
> +#ifndef VFIO_MDEV_H
> +#define VFIO_MDEV_H
> +
> +#include <linux/types.h>
> +#include <linux/mdev.h>
> +
> +/**
> + * struct vfio_mdev_parent_ops - Structure to be registered for each
> + * parent device to register the device to vfio-mdev module.
> + *
> + * @open: Open mediated device.
> + * @mdev: mediated device.
> + * Returns integer: success (0) or error (< 0)
> + * @release: release mediated device
> + * @mdev: mediated device.
> + * @read: Read emulation callback
> + * @mdev: mediated device structure
> + * @buf: read buffer
> + * @count: number of bytes to read
> + * @ppos: address.
> + * Retuns number on bytes read on success or error.
> + * @write: Write emulation callback
> + * @mdev: mediated device structure
> + * @buf: write buffer
> + * @count: number of bytes to be written
> + * @ppos: address.
> + * Retuns number on bytes written on success or error.
> + * @ioctl: IOCTL callback
> + * @mdev: mediated device structure
> + * @cmd: ioctl command
> + * @arg: arguments to ioctl
> + * @mmap: mmap callback
> + * @mdev: mediated device structure
> + * @vma: vma structure
> + */
> +struct vfio_mdev_parent_ops {
> + int (*open)(struct mdev_device *mdev);
> + void (*release)(struct mdev_device *mdev);
> + ssize_t (*read)(struct mdev_device *mdev, char __user *buf,
> + size_t count, loff_t *ppos);
> + ssize_t (*write)(struct mdev_device *mdev, const char __user *buf,
> + size_t count, loff_t *ppos);
> + long (*ioctl)(struct mdev_device *mdev, unsigned int cmd,
> + unsigned long arg);
> + int (*mmap)(struct mdev_device *mdev, struct vm_area_struct
> *vma);
> +};
> +
> +#endif
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c index
> 71a4469be85d..107cc30d0f45 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -30,6 +30,7 @@
> #include <linux/iommu.h>
> #include <linux/sysfs.h>
> #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
> #include <linux/pci.h>
> #include <linux/dma-buf.h>
> #include <linux/highmem.h>
> @@ -1418,12 +1419,7 @@ static struct attribute_group *mdev_type_groups[]
> = {
> NULL,
> };
>
> -static const struct mdev_parent_ops mdev_fops = {
> - .owner = THIS_MODULE,
> - .mdev_attr_groups = mdev_dev_groups,
> - .supported_type_groups = mdev_type_groups,
> - .create = mbochs_create,
> - .remove = mbochs_remove,
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
> .open = mbochs_open,
> .release = mbochs_close,
> .read = mbochs_read,
> @@ -1432,6 +1428,15 @@ static const struct mdev_parent_ops mdev_fops = {
> .mmap = mbochs_mmap,
> };
>
> +static const struct mdev_parent_ops mdev_fops = {
> + .owner = THIS_MODULE,
> + .mdev_attr_groups = mdev_dev_groups,
> + .supported_type_groups = mdev_type_groups,
> + .create = mbochs_create,
> + .remove = mbochs_remove,
> + .device_ops = &vfio_mdev_ops,
> +};
> +
> static const struct file_operations vd_fops = {
> .owner = THIS_MODULE,
> };
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c index
> d3029dd27d91..2cd2018a53f9 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -26,6 +26,7 @@
> #include <linux/iommu.h>
> #include <linux/sysfs.h>
> #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
> #include <linux/pci.h>
> #include <drm/drm_fourcc.h>
> #include "mdpy-defs.h"
> @@ -725,12 +726,7 @@ static struct attribute_group *mdev_type_groups[] = {
> NULL,
> };
>
> -static const struct mdev_parent_ops mdev_fops = {
> - .owner = THIS_MODULE,
> - .mdev_attr_groups = mdev_dev_groups,
> - .supported_type_groups = mdev_type_groups,
> - .create = mdpy_create,
> - .remove = mdpy_remove,
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
> .open = mdpy_open,
> .release = mdpy_close,
> .read = mdpy_read,
> @@ -739,6 +735,15 @@ static const struct mdev_parent_ops mdev_fops = {
> .mmap = mdpy_mmap,
> };
>
> +static const struct mdev_parent_ops mdev_fops = {
> + .owner = THIS_MODULE,
> + .mdev_attr_groups = mdev_dev_groups,
> + .supported_type_groups = mdev_type_groups,
> + .create = mdpy_create,
> + .remove = mdpy_remove,
> + .device_ops = &vfio_mdev_ops,
> +};
> +
> static const struct file_operations vd_fops = {
> .owner = THIS_MODULE,
> };
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c index
> 744c88a6b22c..e427425b5daf 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -27,6 +27,7 @@
> #include <linux/ctype.h>
> #include <linux/file.h>
> #include <linux/mdev.h>
> +#include <linux/vfio_mdev.h>
> #include <linux/pci.h>
> #include <linux/serial.h>
> #include <uapi/linux/serial_reg.h>
> @@ -1410,6 +1411,14 @@ static struct attribute_group *mdev_type_groups[]
> = {
> NULL,
> };
>
> +static const struct vfio_mdev_parent_ops vfio_mdev_ops = {
> + .open = mtty_open,
> + .release = mtty_close,
> + .read = mtty_read,
> + .write = mtty_write,
> + .ioctl = mtty_ioctl,
> +};
> +
> static const struct mdev_parent_ops mdev_fops = {
> .owner = THIS_MODULE,
> .dev_attr_groups = mtty_dev_groups,
> @@ -1417,11 +1426,7 @@ static const struct mdev_parent_ops mdev_fops = {
> .supported_type_groups = mdev_type_groups,
> .create = mtty_create,
> .remove = mtty_remove,
> - .open = mtty_open,
> - .release = mtty_close,
> - .read = mtty_read,
> - .write = mtty_write,
> - .ioctl = mtty_ioctl,
> + .device_ops = &vfio_mdev_ops,
> };
>
> static void mtty_device_release(struct device *dev)
> --
> 2.19.1
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox