Linux-USB Archive on lore.kernel.org
 help / color / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Heikki Krogerus <heikki.krogerus@linux.intel.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Ajay Gupta <ajayg@nvidia.com>, linux-usb@vger.kernel.org
Subject: Re: [PATCH v4 13/18] usb: typec: ucsi: ccg: Move to the new API
Date: Mon, 4 Nov 2019 06:36:44 -0800
Message-ID: <1a404105-8872-7377-465c-cf792f2fad58@roeck-us.net> (raw)
In-Reply-To: <20191104142435.29960-14-heikki.krogerus@linux.intel.com>

On 11/4/19 6:24 AM, Heikki Krogerus wrote:
> Replacing the old "cmd" and "sync" callbacks with an
> implementation of struct ucsi_operations. The interrupt
> handler will from now on read the CCI (Command Status and
> Connector Change Indication) register, and call
> ucsi_connector_change() function and/or complete pending
> command completions based on it.
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Tested-by: Ajay Gupta <ajayg@nvidia.com>

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>   drivers/usb/typec/ucsi/ucsi_ccg.c | 166 +++++++++++++++---------------
>   1 file changed, 81 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
> index d772fce51905..3370b3fc37b1 100644
> --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> @@ -176,8 +176,8 @@ struct ccg_resp {
>   struct ucsi_ccg {
>   	struct device *dev;
>   	struct ucsi *ucsi;
> -	struct ucsi_ppm ppm;
>   	struct i2c_client *client;
> +
>   	struct ccg_dev_info info;
>   	/* version info for boot, primary and secondary */
>   	struct version_info version[FW2 + 1];
> @@ -196,6 +196,8 @@ struct ucsi_ccg {
>   	/* fw build with vendor information */
>   	u16 fw_build;
>   	struct work_struct pm_work;
> +
> +	struct completion complete;
>   };
>   
>   static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
> @@ -243,7 +245,7 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
>   	return 0;
>   }
>   
> -static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
> +static int ccg_write(struct ucsi_ccg *uc, u16 rab, const u8 *data, u32 len)
>   {
>   	struct i2c_client *client = uc->client;
>   	unsigned char *buf;
> @@ -317,88 +319,85 @@ static int ucsi_ccg_init(struct ucsi_ccg *uc)
>   	return -ETIMEDOUT;
>   }
>   
> -static int ucsi_ccg_send_data(struct ucsi_ccg *uc)
> +static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,
> +			 void *val, size_t val_len)
>   {
> -	u8 *ppm = (u8 *)uc->ppm.data;
> -	int status;
> -	u16 rab;
> +	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
>   
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_out));
> -	status = ccg_write(uc, rab, ppm +
> -			   offsetof(struct ucsi_data, message_out),
> -			   sizeof(uc->ppm.data->message_out));
> -	if (status < 0)
> -		return status;
> -
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, ctrl));
> -	return ccg_write(uc, rab, ppm + offsetof(struct ucsi_data, ctrl),
> -			 sizeof(uc->ppm.data->ctrl));
> +	return ccg_read(ucsi_get_drvdata(ucsi), reg, val, val_len);
>   }
>   
> -static int ucsi_ccg_recv_data(struct ucsi_ccg *uc)
> +static int ucsi_ccg_async_write(struct ucsi *ucsi, unsigned int offset,
> +				const void *val, size_t val_len)
>   {
> -	u8 *ppm = (u8 *)uc->ppm.data;
> -	int status;
> -	u16 rab;
> +	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
>   
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, cci));
> -	status = ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, cci),
> -			  sizeof(uc->ppm.data->cci));
> -	if (status < 0)
> -		return status;
> -
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_in));
> -	return ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, message_in),
> -			sizeof(uc->ppm.data->message_in));
> +	return ccg_write(ucsi_get_drvdata(ucsi), reg, val, val_len);
>   }
>   
> -static int ucsi_ccg_ack_interrupt(struct ucsi_ccg *uc)
> +static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,
> +			       const void *val, size_t val_len)
>   {
> -	int status;
> -	unsigned char data;
> +	struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi);
> +	int ret;
>   
> -	status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
> -	if (status < 0)
> -		return status;
> +	mutex_lock(&uc->lock);
> +	pm_runtime_get_sync(uc->dev);
> +	set_bit(DEV_CMD_PENDING, &uc->flags);
>   
> -	return ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
> -}
> +	ret = ucsi_ccg_async_write(ucsi, offset, val, val_len);
> +	if (ret)
> +		goto err_clear_bit;
>   
> -static int ucsi_ccg_sync(struct ucsi_ppm *ppm)
> -{
> -	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
> -	int status;
> +	if (!wait_for_completion_timeout(&uc->complete, msecs_to_jiffies(5000)))
> +		ret = -ETIMEDOUT;
>   
> -	status = ucsi_ccg_recv_data(uc);
> -	if (status < 0)
> -		return status;
> +err_clear_bit:
> +	clear_bit(DEV_CMD_PENDING, &uc->flags);
> +	pm_runtime_put_sync(uc->dev);
> +	mutex_unlock(&uc->lock);
>   
> -	/* ack interrupt to allow next command to run */
> -	return ucsi_ccg_ack_interrupt(uc);
> +	return ret;
>   }
>   
> -static int ucsi_ccg_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl)
> -{
> -	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
> -
> -	ppm->data->ctrl.raw_cmd = ctrl->raw_cmd;
> -	return ucsi_ccg_send_data(uc);
> -}
> +static const struct ucsi_operations ucsi_ccg_ops = {
> +	.read = ucsi_ccg_read,
> +	.sync_write = ucsi_ccg_sync_write,
> +	.async_write = ucsi_ccg_async_write
> +};
>   
>   static irqreturn_t ccg_irq_handler(int irq, void *data)
>   {
> +	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_CCI);
>   	struct ucsi_ccg *uc = data;
> +	u8 intr_reg;
> +	u32 cci;
> +	int ret;
> +
> +	ret = ccg_read(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
> +	if (ret)
> +		return ret;
> +
> +	ret = ccg_read(uc, reg, (void *)&cci, sizeof(cci));
> +	if (ret)
> +		goto err_clear_irq;
> +
> +	if (UCSI_CCI_CONNECTOR(cci))
> +		ucsi_connector_change(uc->ucsi, UCSI_CCI_CONNECTOR(cci));
> +
> +	if (test_bit(DEV_CMD_PENDING, &uc->flags) &&
> +	    cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
> +		complete(&uc->complete);
>   
> -	ucsi_notify(uc->ucsi);
> +err_clear_irq:
> +	ccg_write(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
>   
>   	return IRQ_HANDLED;
>   }
>   
>   static void ccg_pm_workaround_work(struct work_struct *pm_work)
>   {
> -	struct ucsi_ccg *uc = container_of(pm_work, struct ucsi_ccg, pm_work);
> -
> -	ucsi_notify(uc->ucsi);
> +	ccg_irq_handler(0, container_of(pm_work, struct ucsi_ccg, pm_work));
>   }
>   
>   static int get_fw_info(struct ucsi_ccg *uc)
> @@ -1027,10 +1026,10 @@ static int ccg_restart(struct ucsi_ccg *uc)
>   		return status;
>   	}
>   
> -	uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
> -	if (IS_ERR(uc->ucsi)) {
> -		dev_err(uc->dev, "ucsi_register_ppm failed\n");
> -		return PTR_ERR(uc->ucsi);
> +	status = ucsi_register(uc->ucsi);
> +	if (status) {
> +		dev_err(uc->dev, "failed to register the interface\n");
> +		return status;
>   	}
>   
>   	return 0;
> @@ -1047,7 +1046,7 @@ static void ccg_update_firmware(struct work_struct *work)
>   		return;
>   
>   	if (flash_mode != FLASH_NOT_NEEDED) {
> -		ucsi_unregister_ppm(uc->ucsi);
> +		ucsi_unregister(uc->ucsi);
>   		free_irq(uc->irq, uc);
>   
>   		ccg_fw_update(uc, flash_mode);
> @@ -1091,21 +1090,15 @@ static int ucsi_ccg_probe(struct i2c_client *client,
>   	struct device *dev = &client->dev;
>   	struct ucsi_ccg *uc;
>   	int status;
> -	u16 rab;
>   
>   	uc = devm_kzalloc(dev, sizeof(*uc), GFP_KERNEL);
>   	if (!uc)
>   		return -ENOMEM;
>   
> -	uc->ppm.data = devm_kzalloc(dev, sizeof(struct ucsi_data), GFP_KERNEL);
> -	if (!uc->ppm.data)
> -		return -ENOMEM;
> -
> -	uc->ppm.cmd = ucsi_ccg_cmd;
> -	uc->ppm.sync = ucsi_ccg_sync;
>   	uc->dev = dev;
>   	uc->client = client;
>   	mutex_init(&uc->lock);
> +	init_completion(&uc->complete);
>   	INIT_WORK(&uc->work, ccg_update_firmware);
>   	INIT_WORK(&uc->pm_work, ccg_pm_workaround_work);
>   
> @@ -1133,30 +1126,25 @@ static int ucsi_ccg_probe(struct i2c_client *client,
>   	if (uc->info.mode & CCG_DEVINFO_PDPORTS_MASK)
>   		uc->port_num++;
>   
> +	uc->ucsi = ucsi_create(dev, &ucsi_ccg_ops);
> +	if (IS_ERR(uc->ucsi))
> +		return PTR_ERR(uc->ucsi);
> +
> +	ucsi_set_drvdata(uc->ucsi, uc);
> +
>   	status = request_threaded_irq(client->irq, NULL, ccg_irq_handler,
>   				      IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
>   				      dev_name(dev), uc);
>   	if (status < 0) {
>   		dev_err(uc->dev, "request_threaded_irq failed - %d\n", status);
> -		return status;
> +		goto out_ucsi_destroy;
>   	}
>   
>   	uc->irq = client->irq;
>   
> -	uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
> -	if (IS_ERR(uc->ucsi)) {
> -		dev_err(uc->dev, "ucsi_register_ppm failed\n");
> -		return PTR_ERR(uc->ucsi);
> -	}
> -
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, version));
> -	status = ccg_read(uc, rab, (u8 *)(uc->ppm.data) +
> -			  offsetof(struct ucsi_data, version),
> -			  sizeof(uc->ppm.data->version));
> -	if (status < 0) {
> -		ucsi_unregister_ppm(uc->ucsi);
> -		return status;
> -	}
> +	status = ucsi_register(uc->ucsi);
> +	if (status)
> +		goto out_free_irq;
>   
>   	i2c_set_clientdata(client, uc);
>   
> @@ -1167,6 +1155,13 @@ static int ucsi_ccg_probe(struct i2c_client *client,
>   	pm_runtime_idle(uc->dev);
>   
>   	return 0;
> +
> +out_free_irq:
> +	free_irq(uc->irq, uc);
> +out_ucsi_destroy:
> +	ucsi_destroy(uc->ucsi);
> +
> +	return status;
>   }
>   
>   static int ucsi_ccg_remove(struct i2c_client *client)
> @@ -1175,8 +1170,9 @@ static int ucsi_ccg_remove(struct i2c_client *client)
>   
>   	cancel_work_sync(&uc->pm_work);
>   	cancel_work_sync(&uc->work);
> -	ucsi_unregister_ppm(uc->ucsi);
>   	pm_runtime_disable(uc->dev);
> +	ucsi_unregister(uc->ucsi);
> +	ucsi_destroy(uc->ucsi);
>   	free_irq(uc->irq, uc);
>   
>   	return 0;
> 


  reply index

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-04 14:24 [PATCH v4 00/18] usb: typec: API improvements Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 01/18] usb: typec: Copy everything from struct typec_capability during registration Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 02/18] usb: typec: Introduce typec_get_drvdata() Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 03/18] usb: typec: Separate the operations vector Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 04/18] usb: typec: tcpm: Start using struct typec_operations Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 05/18] usb: typec: tps6598x: " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 06/18] usb: typec: ucsi: " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 07/18] usb: typec: hd3ss3220: " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 08/18] usb: typec: Remove the callback members from struct typec_capability Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 09/18] usb: typec: Remove unused " Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 10/18] usb: typec: hd3ss3220: Give the connector fwnode to the port device Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 11/18] usb: typec: ucsi: Simplified registration and I/O API Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 12/18] usb: typec: ucsi: acpi: Move to the new API Heikki Krogerus
2019-11-04 14:35   ` Guenter Roeck
2019-11-04 18:54   ` Guenter Roeck
2019-11-05  8:46     ` Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 13/18] usb: typec: ucsi: ccg: " Heikki Krogerus
2019-11-04 14:36   ` Guenter Roeck [this message]
2019-11-04 14:24 ` [PATCH v4 14/18] usb: typec: ucsi: Remove the old API Heikki Krogerus
2019-11-04 14:38   ` Guenter Roeck
2019-11-04 14:24 ` [PATCH v4 15/18] usb: typec: ucsi: Remove struct ucsi_control Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 16/18] usb: typec: ucsi: Remove all bit-fields Heikki Krogerus
2019-11-04 14:24 ` [PATCH v4 17/18] usb: typec: ucsi: New error codes Heikki Krogerus
2019-11-04 14:41   ` Guenter Roeck
2019-11-04 14:24 ` [PATCH v4 18/18] usb: typec: ucsi: Optimise ucsi_unregister() Heikki Krogerus
2019-11-04 14:42   ` Guenter Roeck
2019-11-04 15:05 ` [PATCH v4 00/18] usb: typec: API improvements Greg Kroah-Hartman
2019-11-04 18:53   ` Guenter Roeck
2019-11-04 20:53     ` Greg Kroah-Hartman
2019-11-04 20:54   ` Greg Kroah-Hartman

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1a404105-8872-7377-465c-cf792f2fad58@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=ajayg@nvidia.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=heikki.krogerus@linux.intel.com \
    --cc=linux-usb@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-USB Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-usb/0 linux-usb/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-usb linux-usb/ https://lore.kernel.org/linux-usb \
		linux-usb@vger.kernel.org
	public-inbox-index linux-usb

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-usb


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git