[PATCH linux dev-4.7 2/5] drivers/fsi: Initialize hub master engine

Jeremy Kerr jk at ozlabs.org
Fri Feb 17 18:42:31 AEDT 2017


Hi Chris,

> Define hub master probe and add definitions for general
> master registers and bitfields.

I think some background on what a hub master is (and how it differs from
a cascaded master) would be useful - either here or in Documentation/.

>  struct fsi_slave {
>  	struct list_head	list_link;	/* Master's list of slaves */
>  	struct list_head	my_engines;
>  	struct device		dev;
> -	struct fsi_master	*master;
> +	struct fsi_master	*master;	/* Upstream master */
> +	struct fsi_master	*next_master;	/* Downstream master */
>  	int			link;
>  	uint8_t			id;
> +	uint32_t		base;		/* Base address */
>  };

[...]

> @@ -26,6 +75,10 @@ struct fsi_master {
>  	int		idx;
>  	int		n_links;
>  	uint32_t	ipoll;
> +	struct fsi_device *engine;
> +	struct fsi_device *link;
> +	uint8_t		type;
> +	uint32_t	link_size;
>  	int		(*read)(struct fsi_master *, int link,
>  				uint8_t slave, uint32_t addr,
>  				void *val, size_t size);

It seems to me that you've added a lot of hub-specific definitions to
multiple parts of the generic FSI core code. I would much rather see
this contained to code that supports just the hub.

However, the hub functionality doesn't seem to fit within the
slave-engine device model - as a slave-engine driver (binding on the
0x1c/0x1d entries in the configuration table), the hub driver violates
the device model in that it performs accesses to addresses *way* outside
of the allocations described in the configuration table.

[that's why you've altered fsi_dev->size in the master driver, and can
potentially lead to conflicts with other drivers in future]

>From what I can glean from the docs, the hub master has a couple of
interfaces:

 - the control register set described in the slave configuration table
   as type 0x1d

 - a description of the links, as entries in the slave configuration
   table as type 0x1c

 - the actual FSI master address space, provided underneath a *slave*
   (and not a *slave engine* - that distinction is important).

To me, it sounds like we should not make this a slave engine driver, but
a part of the core *slave* code, because the hub masters are attached
directly to the slaves. This would involve:

  - struct fsi_master_hub {
        struct fsi_master master;
        struct fsi_slave *slave;
	uint32_t          control_regs;  /* slave-relative addr of regs */
	uint32_t          base;          /* slave-relative addr of
					    master address space */
    }

  - in fsi_slave_scan():

     - suppressing the 0x1c and 0x1d devices from creating slave engines

     - if we find an 0x1d type in the configuration table:
        - struct fsi_master_hub *hub = kzalloc(...);
	  hub->base = /* pre-defined */
	  hub->control_regs = /* parsed from config table */
	  hub->slave = slave;

     - if (hub) {
          use a count of the 0x1c types to populate n_links
	  fsi_master_register(&hub->master);
       }

  - the read() and write() callbacks of fsi_master_hub just pass through
    to the slave (at offset ->base), and the enable/break will access the
    control_regs.

This means that we keep the hub code encapsulated, and the hub
implementation doesn't leak out to the core fsi_master or fsi_slave
structs.

For cascaded masters, we can probably keep this model of using a slave
engine driver, but I just don't think it's suitable for the hubs.

Regards,


Jeremy


More information about the openbmc mailing list