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

Commit 384170da authored by Jarod Wilson's avatar Jarod Wilson Committed by Stefan Richter
Browse files

firewire: fw-sbp2: Use sbp2 device-provided mgt orb timeout for logins



To be more compliant with section 7.4.8 of the SBP-2 specification,
use the mgt_ORB_timeout specified in the SBP-2 device's config rom
for login ORB attempts (though with some sanity checks). A happy
side-effect is that certain device and controller combinations that
sometimes take more than 20 seconds to get synced up (like my laptop
with just about any SBP-2 device) now function more reliably.

Signed-off-by: default avatarJarod Wilson <jwilson@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (silenced sparse)
parent a4c379c1
Loading
Loading
Loading
Loading
+24 −5
Original line number Diff line number Diff line
@@ -149,15 +149,17 @@ struct sbp2_target {

	unsigned workarounds;
	struct list_head lu_list;

	unsigned int mgt_orb_timeout;
};

/*
 * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
 * provided in the config rom.  A high timeout value really only matters
 * on initial login, where we'll just use 20s rather than hassling with
 * reading the config rom, since it really wouldn't buy us much.
 * provided in the config rom. Most devices do provide a value, which
 * we'll use for login management orbs, but with some sane limits.
 */
#define SBP2_LOGIN_ORB_TIMEOUT		20000	/* Timeout in ms */
#define SBP2_MIN_LOGIN_ORB_TIMEOUT	5000U	/* Timeout in ms */
#define SBP2_MAX_LOGIN_ORB_TIMEOUT	40000U	/* Timeout in ms */
#define SBP2_ORB_TIMEOUT		2000	/* Timeout in ms */
#define SBP2_ORB_NULL			0x80000000
#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
@@ -166,6 +168,7 @@ struct sbp2_target {
#define SBP2_DIRECTION_FROM_MEDIA	0x1

/* Unit directory keys */
#define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
#define SBP2_CSR_FIRMWARE_REVISION	0x3c
#define SBP2_CSR_LOGICAL_UNIT_NUMBER	0x14
#define SBP2_CSR_LOGICAL_UNIT_DIRECTORY	0xd4
@@ -527,7 +530,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
		orb->request.misc |=
			MANAGEMENT_ORB_RECONNECT(2) |
			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
		timeout = SBP2_LOGIN_ORB_TIMEOUT;
		timeout = lu->tgt->mgt_orb_timeout;
	} else {
		timeout = SBP2_ORB_TIMEOUT;
	}
@@ -777,6 +780,7 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
{
	struct fw_csr_iterator ci;
	int key, value;
	unsigned int timeout;

	fw_csr_iterator_init(&ci, directory);
	while (fw_csr_iterator_next(&ci, &key, &value)) {
@@ -799,6 +803,21 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
			*firmware_revision = value;
			break;

		case SBP2_CSR_UNIT_CHARACTERISTICS:
			/* the timeout value is stored in 500ms units */
			timeout = ((unsigned int) value >> 8 & 0xff) * 500;
			timeout = max(timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT);
			tgt->mgt_orb_timeout =
				  min(timeout, SBP2_MAX_LOGIN_ORB_TIMEOUT);

			if (timeout > tgt->mgt_orb_timeout)
				fw_notify("%s: config rom contains %ds "
					  "management ORB timeout, limiting "
					  "to %ds\n", tgt->unit->device.bus_id,
					  timeout / 1000,
					  tgt->mgt_orb_timeout / 1000);
			break;

		case SBP2_CSR_LOGICAL_UNIT_NUMBER:
			if (sbp2_add_logical_unit(tgt, value) < 0)
				return -ENOMEM;