On 27-02-20, 16:31, Pierre-Louis Bossart wrote: > In the existing SoundWire code, Master Devices are not explicitly > represented - only SoundWire Slave Devices are exposed (the use of > capital letters follows the SoundWire specification conventions). > > The SoundWire Master Device provides the clock, synchronization > information and command/control channels. When multiple links are > supported, a Controller may expose more than one Master Device; they > are typically embedded inside a larger audio cluster (be it in an > SOC/chipset or an external audio codec), and we need to describe it > using the Linux device and driver model. This will allow for > configuration functions to account for external dependencies such as > power rails, clock sources or wake-up mechanisms. This transition will I dont not see that as a soundwire issue. The external dependencies should be handled as any device would do in Linux kernel with subsystem specific things for soundwire mechanisms like wake-up Intel has a big controller with HDA, DSP and Soundwire clubbed together, I dont think we should burden the susbstem due to hw design > also allow for better sysfs support without the reference count issues > mentioned in the initial reviews. > > In this patch, we convert the existing code to use an explicit > sdw_slave_type, then define new objects (sdw_master_device and > sdw_master_driver). Thanks for sdw_master_device, that is required and fully agreed upon. What is not agreed is the sdw_master_driver. We do not need that. As we have discussed your proposal with Greg and aligned (quoting that here) on following device model for Intel and ARM: > - For DT cases we will have: > -> soundwire DT device (soundwire DT driver) > -> soundwire master device > -> soundwire slave device (slave drivers) > - For Intel case, you would have: > -> HDA PCI device (SOF driver + soundwire module) > -> soundwire master device > -> soundwire slave device (slave drivers) But you have gone ahead and kept the sdw_master_driver which does not fit into rest of the world except Intel. I think I am okay with rest of proposal, except this one, so can you remove this and we can make progress. This issue is lingering since Oct! > A parent (such as the Intel audio controller or its equivalent on > Qualcomm devices) would use sdw_master_device_add() to create the > device, passing a driver name as a parameter. The master device would > be released when device_unregister() is invoked by the parent. We already have a DT driver for soundwire master! We dont need another layer which does not add value! > Note that since there is no standard for the Master host-facing > interface, so the bus matching relies on a simple string matching (as > previously done with platform devices). > > The 'Master Device' driver exposes callbacks for > probe/startup/shutdown/remove/process_wake. The startup and process > wake need to be called by the parent directly (using wrappers), while > the probe/shutdown/remove are handled by the SoundWire bus core upon > device creation and release. these are added to handle intel DSP and sequencing issue, rest of the world does not have these issues and does not needs them! > Additional callbacks will be added in the future for e.g. autonomous > clock stop modes. Yes these would be required, these can be added in sdw_master_device too, I dont see them requiring a dummy driver layer.. > @@ -113,8 +152,6 @@ static int sdw_drv_probe(struct device *dev) > slave->probed = true; > complete(&slave->probe_complete); > > - dev_dbg(dev, "probe complete\n"); > - This does not seem to belong to this patch. > +struct device_type sdw_master_type = { > + .name = "soundwire_master", > + .release = sdw_master_device_release, > +}; > + > +struct sdw_master_device > +*sdw_master_device_add(const char *master_name, > + struct device *parent, > + struct fwnode_handle *fwnode, > + int link_id, > + void *pdata) > +{ > + struct sdw_master_device *md; > + int ret; > + > + md = kzalloc(sizeof(*md), GFP_KERNEL); > + if (!md) > + return ERR_PTR(-ENOMEM); > + > + md->link_id = link_id; > + md->pdata = pdata; > + md->master_name = master_name; should we not allocate the memory here for master_name? > + > + init_completion(&md->probe_complete); > + > + md->dev.parent = parent; > + md->dev.fwnode = fwnode; > + md->dev.bus = &sdw_bus_type; > + md->dev.type = &sdw_master_type; > + md->dev.dma_mask = md->dev.parent->dma_mask; > + dev_set_name(&md->dev, "sdw-master-%d", md->link_id); why do we need master_name if we are setting this here? > + > + ret = device_register(&md->dev); > + if (ret) { > + dev_err(parent, "Failed to add master: ret %d\n", ret); > + /* > + * On err, don't free but drop ref as this will be freed > + * when release method is invoked. > + */ > + put_device(&md->dev); > + return ERR_PTR(-ENOMEM); ENOMEM? > +int sdw_master_device_startup(struct sdw_master_device *md) > +{ > + struct sdw_master_driver *mdrv; > + struct device *dev; > + int ret = 0; > + > + if (IS_ERR_OR_NULL(md)) > + return -EINVAL; > + > + dev = &md->dev; > + mdrv = drv_to_sdw_master_driver(dev->driver); > + > + if (mdrv && mdrv->startup) > + ret = mdrv->startup(md); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(sdw_master_device_startup); who invokes this and when, can you add kernel-doc style documentation to all APIs exported > +int sdw_master_device_process_wake_event(struct sdw_master_device *md) > +{ > + struct sdw_master_driver *mdrv; > + struct device *dev; > + int ret = 0; > + > + if (IS_ERR_OR_NULL(md)) > + return -EINVAL; > + > + dev = &md->dev; > + mdrv = drv_to_sdw_master_driver(dev->driver); > + > + if (mdrv && mdrv->process_wake_event) > + ret = mdrv->process_wake_event(md); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(sdw_master_device_process_wake_event); Documentation required > +/** > + * struct sdw_master_device - SoundWire 'Master Device' representation > + * > + * @dev: Linux device for this Master > + * @master_name: Linux driver name > + * @driver: Linux driver for this Master (set by SoundWire core during probe) > + * @probe_complete: used by parent if synchronous probe behavior is needed > + * @link_id: link index as defined by MIPI DisCo specification > + * @pm_runtime_suspended: flag to restore pm_runtime state after system resume > + * @pdata: private data typically provided with sdw_master_device_add() > + */ > + > +struct sdw_master_device { > + struct device dev; > + const char *master_name; > + struct sdw_master_driver *driver; > + struct completion probe_complete; > + int link_id; > + bool pm_runtime_suspended; why not use runtime_pm apis like pm_runtime_suspended() > +/** > + * sdw_master_device_add() - create a Linux Master Device representation. > + * > + * @master_name: Linux driver name > + * @parent: the parent Linux device (e.g. a PCI device) > + * @fwnode: the parent fwnode (e.g. an ACPI companion device to the parent) > + * @link_id: link index as defined by MIPI DisCo specification > + * @pdata: private data (e.g. register base, offsets, platform quirks, etc). > + */ > +struct sdw_master_device > +*sdw_master_device_add(const char *master_name, > + struct device *parent, > + struct fwnode_handle *fwnode, > + int link_id, > + void *pdata); > + > +/** > + * sdw_master_device_startup() - startup hardware > + * > + * @md: Linux Soundwire master device Please add more useful comments like when this API would be invoked and what shall be expected outcome > + */ > +int sdw_master_device_startup(struct sdw_master_device *md); > + > +/** > + * sdw_master_device_process_wake_event() - handle external wake > + * event, e.g. handled at the PCI level > + * > + * @md: Linux Soundwire master device > + */ > +int sdw_master_device_process_wake_event(struct sdw_master_device *md); > + If you look at existing headers the documentation is in C files for APIs, so can you move them over. When adding stuff please look at the rest of the code as an example. -- ~Vinod