[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [XEN PATCH v10 1/5] xen/vpci: Clear all vpci status of device
On 2024/6/18 16:33, Jan Beulich wrote: > On 18.06.2024 08:25, Chen, Jiqian wrote: >> On 2024/6/17 22:17, Jan Beulich wrote: >>> On 17.06.2024 11:00, Jiqian Chen wrote: >>>> --- a/xen/drivers/pci/physdev.c >>>> +++ b/xen/drivers/pci/physdev.c >>>> @@ -2,11 +2,17 @@ >>>> #include <xen/guest_access.h> >>>> #include <xen/hypercall.h> >>>> #include <xen/init.h> >>>> +#include <xen/vpci.h> >>>> >>>> #ifndef COMPAT >>>> typedef long ret_t; >>>> #endif >>>> >>>> +static const struct pci_device_state_reset_method >>>> + pci_device_state_reset_methods[] = { >>>> + [ DEVICE_RESET_FLR ].reset_fn = vpci_reset_device_state, >>>> +}; >>> >>> What about the other three DEVICE_RESET_*? In particular ... >> I don't know how to implement the other three types of reset. >> This is a design form so that corresponding processing functions can be >> added later if necessary. Do I need to set them to NULL pointers in this >> array? > > No. > >> Does this form conform to your previous suggestion of using only one >> hypercall to handle all types of resets? > > Yes, at least in principle. Question here is: To be on the safe side, > wouldn't we better reset state for all forms of reset, leaving possible > relaxation of that for later? At which point the function wouldn't need > calling indirectly, and instead would be passed the reset type as an > argument. If I understood correctly, next version should be? Use macros to represent different reset types. Add switch cases in PHYSDEVOP_pci_device_state_reset to handle different reset functions. Add reset_type as a function parameter to vpci_reset_device_state for possible future use. + case PHYSDEVOP_pci_device_state_reset: + { + struct pci_device_state_reset dev_reset; + struct pci_dev *pdev; + pci_sbdf_t sbdf; + + if ( !is_pci_passthrough_enabled() ) + return -EOPNOTSUPP; + + ret = -EFAULT; + if ( copy_from_guest(&dev_reset, arg, 1) != 0 ) + break; + + sbdf = PCI_SBDF(dev_reset.dev.seg, + dev_reset.dev.bus, + dev_reset.dev.evfn); + + ret = xsm_resource_setup_pci(XSM_PRIV, sbdf.sbdf); + if ( ret ) + break; + + pcidevs_lock(); + pdev = pci_get_pdev(NULL, sbdf); + if ( !pdev ) + { + pcidevs_unlock(); + ret = -ENODEV; + break; + } + + write_lock(&pdev->domain->pci_lock); + pcidevs_unlock(); + /* Implement FLR, other reset types may be implemented in future */ + switch ( dev_reset.reset_type ) + { + case PCI_DEVICE_STATE_RESET_COLD: + case PCI_DEVICE_STATE_RESET_WARM: + case PCI_DEVICE_STATE_RESET_HOT: + case PCI_DEVICE_STATE_RESET_FLR: + ret = vpci_reset_device_state(pdev, dev_reset.reset_type); + break; + } + write_unlock(&pdev->domain->pci_lock); + + if ( ret ) + dprintk(XENLOG_ERR, + "%pp: failed to reset vPCI device state\n", &sbdf); + break; + } > >>> Also, nit (further up): Opening figure braces for a new scope go onto their >> OK, will change in next version. >>> own line. Then again I notice that apparenly _all_ other instances in this >>> file are doing it the wrong way, too. >> Do I need to change them in this patch? > > No. > >>>> --- a/xen/drivers/vpci/vpci.c >>>> +++ b/xen/drivers/vpci/vpci.c >>>> @@ -172,6 +172,15 @@ int vpci_assign_device(struct pci_dev *pdev) >>>> >>>> return rc; >>>> } >>>> + >>>> +int vpci_reset_device_state(struct pci_dev *pdev) >>> >>> As a target of an indirect call this needs to be annotated cf_check (both >>> here and in the declaration, unlike __must_check, which is sufficient to >>> have on just the declaration). >> OK, will add cf_check in next version. > > Which may not be necessary if you go the route suggested above. > >>>> --- a/xen/include/xen/pci.h >>>> +++ b/xen/include/xen/pci.h >>>> @@ -156,6 +156,22 @@ struct pci_dev { >>>> struct vpci *vpci; >>>> }; >>>> >>>> +struct pci_device_state_reset_method { >>>> + int (*reset_fn)(struct pci_dev *pdev); >>>> +}; >>>> + >>>> +enum pci_device_state_reset_type { >>>> + DEVICE_RESET_FLR, >>>> + DEVICE_RESET_COLD, >>>> + DEVICE_RESET_WARM, >>>> + DEVICE_RESET_HOT, >>>> +}; >>>> + >>>> +struct pci_device_state_reset { >>>> + struct physdev_pci_device dev; >>>> + enum pci_device_state_reset_type reset_type; >>>> +}; >>> >>> This is the struct to use as hypercall argument. How can it live outside of >>> any public header? Also, when moving it there, beware that you should not >>> use enum-s there. Only handles and fixed-width types are permitted.t >> Yes, I put them there before, but enum is not permitted. >> Then, do you have other suggested type to use to distinguish different types >> of resets, because enum can't work in the public header? > > Do like we do everywhere else: Use a set of #define-s. > >>>> --- a/xen/include/xen/vpci.h >>>> +++ b/xen/include/xen/vpci.h >>>> @@ -38,6 +38,7 @@ int __must_check vpci_assign_device(struct pci_dev >>>> *pdev); >>>> >>>> /* Remove all handlers and free vpci related structures. */ >>>> void vpci_deassign_device(struct pci_dev *pdev); >>>> +int __must_check vpci_reset_device_state(struct pci_dev *pdev); >>> >>> What's the purpose of this __must_check, when the sole caller is calling >>> this through a function pointer, which isn't similarly annotated? >> This is what I added before introducing function pointers, but after >> modifying the implementation, it was not taken into account. >> I will remove __must_check > > Why remove? Is it relevant for the return value to be checked? Or if it > isn't, why would there be a return value? > > Jan > >> and change to cf_check, according to your above comment. > -- Best regards, Jiqian Chen.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |