forked from Minki/linux
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: Jarod Wilson <jwilson@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (silenced sparse)
This commit is contained in:
parent
a4c379c197
commit
384170da93
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user