Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c2522d8 authored by Eli Sennesh's avatar Eli Sennesh Committed by Greg Kroah-Hartman
Browse files

greybus: update UniPro Set Interface Power Mode operation to match spec



Bring the gb_svc_intf_set_power_mode() up-to-date with the current Greybus
specification.  This largely involves adding more members to the structure
sent across the wire.  Also change the camera code to use the new
operation properly, with default values passed for the new necessary
arguments.  The correctness of these default values is confirmed via testing
and by asking Rob Johnson.

We must make sure to zero the request structure sent across the wire, lest
bite us most cruelly, and we fix by changing the Set Power Mode
Response structure to use a __u8 rather than a __le16.

Testing Done: Took a picture with a camera module, received error code
when passing deliberately incorrect values for new parameters, got proper
-EIO and Greybus result code printed when operation stopped halfway
through.  Could induce error by initializing request struct with random
nonsense, and can stop it by initializing request struct with zeroes.

Associated Firmware Changes: 1669-1671 on Android N Gerrit for SW-2945

Signed-off-by: default avatarEli Sennesh <esennesh@leaflabs.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 62e04623
Loading
Loading
Loading
Loading
+8 −2
Original line number Original line Diff line number Diff line
@@ -128,17 +128,23 @@ static int gb_camera_set_intf_power_mode(struct gb_camera *gcam, u8 intf_id,
		ret = gb_svc_intf_set_power_mode(svc, intf_id,
		ret = gb_svc_intf_set_power_mode(svc, intf_id,
						 GB_SVC_UNIPRO_HS_SERIES_A,
						 GB_SVC_UNIPRO_HS_SERIES_A,
						 GB_SVC_UNIPRO_FAST_MODE, 2, 2,
						 GB_SVC_UNIPRO_FAST_MODE, 2, 2,
						 GB_SVC_SMALL_AMPLITUDE,
						 GB_SVC_NO_DE_EMPHASIS,
						 GB_SVC_UNIPRO_FAST_MODE, 2, 2,
						 GB_SVC_UNIPRO_FAST_MODE, 2, 2,
						 GB_SVC_PWRM_RXTERMINATION |
						 GB_SVC_PWRM_RXTERMINATION |
						 GB_SVC_PWRM_TXTERMINATION, 0);
						 GB_SVC_PWRM_TXTERMINATION, 0,
						 NULL, NULL);
	else
	else
		ret = gb_svc_intf_set_power_mode(svc, intf_id,
		ret = gb_svc_intf_set_power_mode(svc, intf_id,
						 GB_SVC_UNIPRO_HS_SERIES_A,
						 GB_SVC_UNIPRO_HS_SERIES_A,
						 GB_SVC_UNIPRO_SLOW_AUTO_MODE,
						 GB_SVC_UNIPRO_SLOW_AUTO_MODE,
						 2, 1,
						 2, 1,
						 GB_SVC_SMALL_AMPLITUDE,
						 GB_SVC_NO_DE_EMPHASIS,
						 GB_SVC_UNIPRO_SLOW_AUTO_MODE,
						 GB_SVC_UNIPRO_SLOW_AUTO_MODE,
						 2, 1,
						 2, 1,
						 0, 0);
						 0, 0,
						 NULL, NULL);


	return ret;
	return ret;
}
}
+29 −1
Original line number Original line Diff line number Diff line
@@ -1100,6 +1100,13 @@ struct gb_svc_timesync_ping_response {
#define GB_SVC_UNIPRO_HIBERNATE_MODE		0x11
#define GB_SVC_UNIPRO_HIBERNATE_MODE		0x11
#define GB_SVC_UNIPRO_OFF_MODE			0x12
#define GB_SVC_UNIPRO_OFF_MODE			0x12


#define GB_SVC_SMALL_AMPLITUDE          0x01
#define GB_SVC_LARGE_AMPLITUDE          0x02

#define GB_SVC_NO_DE_EMPHASIS           0x00
#define GB_SVC_SMALL_DE_EMPHASIS        0x01
#define GB_SVC_LARGE_DE_EMPHASIS        0x02

#define GB_SVC_PWRM_RXTERMINATION		0x01
#define GB_SVC_PWRM_RXTERMINATION		0x01
#define GB_SVC_PWRM_TXTERMINATION		0x02
#define GB_SVC_PWRM_TXTERMINATION		0x02
#define GB_SVC_PWRM_LINE_RESET			0x04
#define GB_SVC_PWRM_LINE_RESET			0x04
@@ -1110,21 +1117,42 @@ struct gb_svc_timesync_ping_response {
#define GB_SVC_UNIPRO_HS_SERIES_A		0x01
#define GB_SVC_UNIPRO_HS_SERIES_A		0x01
#define GB_SVC_UNIPRO_HS_SERIES_B		0x02
#define GB_SVC_UNIPRO_HS_SERIES_B		0x02


#define GB_SVC_SETPWRM_PWR_OK           0x00
#define GB_SVC_SETPWRM_PWR_LOCAL        0x01
#define GB_SVC_SETPWRM_PWR_REMOTE       0x02
#define GB_SVC_SETPWRM_PWR_BUSY         0x03
#define GB_SVC_SETPWRM_PWR_ERROR_CAP    0x04
#define GB_SVC_SETPWRM_PWR_FATAL_ERROR  0x05

struct gb_svc_l2_timer_cfg {
	__le16 tsb_fc0_protection_timeout;
	__le16 tsb_tc0_replay_timeout;
	__le16 tsb_afc0_req_timeout;
	__le16 tsb_fc1_protection_timeout;
	__le16 tsb_tc1_replay_timeout;
	__le16 tsb_afc1_req_timeout;
	__le16 reserved_for_tc2[3];
	__le16 reserved_for_tc3[3];
} __packed;

struct gb_svc_intf_set_pwrm_request {
struct gb_svc_intf_set_pwrm_request {
	__u8	intf_id;
	__u8	intf_id;
	__u8	hs_series;
	__u8	hs_series;
	__u8	tx_mode;
	__u8	tx_mode;
	__u8	tx_gear;
	__u8	tx_gear;
	__u8	tx_nlanes;
	__u8	tx_nlanes;
	__u8	tx_amplitude;
	__u8	tx_hs_equalizer;
	__u8	rx_mode;
	__u8	rx_mode;
	__u8	rx_gear;
	__u8	rx_gear;
	__u8	rx_nlanes;
	__u8	rx_nlanes;
	__u8	flags;
	__u8	flags;
	__le32	quirks;
	__le32	quirks;
	struct gb_svc_l2_timer_cfg local_l2timerdata, remote_l2timerdata;
} __packed;
} __packed;


struct gb_svc_intf_set_pwrm_response {
struct gb_svc_intf_set_pwrm_response {
	__le16	result_code;
	__u8	result_code;
} __packed;
} __packed;


struct gb_svc_key_event_request {
struct gb_svc_key_event_request {
+23 −3
Original line number Original line Diff line number Diff line
@@ -616,23 +616,35 @@ void gb_svc_route_destroy(struct gb_svc *svc, u8 intf1_id, u8 intf2_id)


int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
			       u8 tx_mode, u8 tx_gear, u8 tx_nlanes,
			       u8 tx_mode, u8 tx_gear, u8 tx_nlanes,
			       u8 tx_amplitude, u8 tx_hs_equalizer,
			       u8 rx_mode, u8 rx_gear, u8 rx_nlanes,
			       u8 rx_mode, u8 rx_gear, u8 rx_nlanes,
			       u8 flags, u32 quirks)
			       u8 flags, u32 quirks,
			       struct gb_svc_l2_timer_cfg *local,
			       struct gb_svc_l2_timer_cfg *remote)
{
{
	struct gb_svc_intf_set_pwrm_request request;
	struct gb_svc_intf_set_pwrm_request request;
	struct gb_svc_intf_set_pwrm_response response;
	struct gb_svc_intf_set_pwrm_response response;
	int ret;
	int ret;
	u16 result_code;

	memset(&request, 0, sizeof(request));


	request.intf_id = intf_id;
	request.intf_id = intf_id;
	request.hs_series = hs_series;
	request.hs_series = hs_series;
	request.tx_mode = tx_mode;
	request.tx_mode = tx_mode;
	request.tx_gear = tx_gear;
	request.tx_gear = tx_gear;
	request.tx_nlanes = tx_nlanes;
	request.tx_nlanes = tx_nlanes;
	request.tx_amplitude = tx_amplitude;
	request.tx_hs_equalizer = tx_hs_equalizer;
	request.rx_mode = rx_mode;
	request.rx_mode = rx_mode;
	request.rx_gear = rx_gear;
	request.rx_gear = rx_gear;
	request.rx_nlanes = rx_nlanes;
	request.rx_nlanes = rx_nlanes;
	request.flags = flags;
	request.flags = flags;
	request.quirks = cpu_to_le32(quirks);
	request.quirks = cpu_to_le32(quirks);
	if (local)
		request.local_l2timerdata = *local;
	if (remote)
		request.remote_l2timerdata = *remote;


	ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM,
	ret = gb_operation_sync(svc->connection, GB_SVC_TYPE_INTF_SET_PWRM,
				&request, sizeof(request),
				&request, sizeof(request),
@@ -640,7 +652,13 @@ int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
	if (ret < 0)
	if (ret < 0)
		return ret;
		return ret;


	return le16_to_cpu(response.result_code);
	result_code = response.result_code;
	if (result_code != GB_SVC_SETPWRM_PWR_LOCAL) {
		dev_err(&svc->dev, "set power mode = %d\n", result_code);
		return -EIO;
	}

	return 0;
}
}
EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode);
EXPORT_SYMBOL_GPL(gb_svc_intf_set_power_mode);


@@ -954,9 +972,11 @@ static void gb_svc_process_hello_deferred(struct gb_operation *operation)
					GB_SVC_UNIPRO_HS_SERIES_A,
					GB_SVC_UNIPRO_HS_SERIES_A,
					GB_SVC_UNIPRO_SLOW_AUTO_MODE,
					GB_SVC_UNIPRO_SLOW_AUTO_MODE,
					2, 1,
					2, 1,
					GB_SVC_SMALL_AMPLITUDE, GB_SVC_NO_DE_EMPHASIS,
					GB_SVC_UNIPRO_SLOW_AUTO_MODE,
					GB_SVC_UNIPRO_SLOW_AUTO_MODE,
					2, 1,
					2, 1,
					0, 0);
					0, 0,
					NULL, NULL);


	if (ret)
	if (ret)
		dev_warn(&svc->dev,
		dev_warn(&svc->dev,
+4 −1
Original line number Original line Diff line number Diff line
@@ -79,8 +79,11 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector,
			u32 value);
			u32 value);
int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
int gb_svc_intf_set_power_mode(struct gb_svc *svc, u8 intf_id, u8 hs_series,
			       u8 tx_mode, u8 tx_gear, u8 tx_nlanes,
			       u8 tx_mode, u8 tx_gear, u8 tx_nlanes,
			       u8 tx_amplitude, u8 tx_hs_equalizer,
			       u8 rx_mode, u8 rx_gear, u8 rx_nlanes,
			       u8 rx_mode, u8 rx_gear, u8 rx_nlanes,
			       u8 flags, u32 quirks);
			       u8 flags, u32 quirks,
			       struct gb_svc_l2_timer_cfg *local,
			       struct gb_svc_l2_timer_cfg *remote);
int gb_svc_ping(struct gb_svc *svc);
int gb_svc_ping(struct gb_svc *svc);
int gb_svc_watchdog_create(struct gb_svc *svc);
int gb_svc_watchdog_create(struct gb_svc *svc);
void gb_svc_watchdog_destroy(struct gb_svc *svc);
void gb_svc_watchdog_destroy(struct gb_svc *svc);