Synopsis:
If speed of link between two devices is slower than the reported max speed of both endpoints, the current driver will fail and be unable to negotiate. Summary: Test negotiated speed by reading the CSRROM into a dummy variable. If that read fails, decrement our speed and retry. If all else fails, go to lowest speed possible(0). Report speed to the user. Add display of the Bus Info Block when debug.firewire_debug > 1 Support the Bus Info Block(1394a-2000) method of speed detection. I also should note that I am moving "hold_count" to 0 for future releases. This variable determines how many bus resets to "hold" a removed firewire device before deletion. I don't feel this is useful and will probably drop support for this sysctl in the future. Reviewed by: scottl(mentor) MFC after: 2 weeks
This commit is contained in:
parent
993b1ae273
commit
ebe234793b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188704
@ -77,7 +77,7 @@ struct crom_src_buf {
|
||||
struct crom_chunk hw;
|
||||
};
|
||||
|
||||
int firewire_debug=0, try_bmr=1, hold_count=3;
|
||||
int firewire_debug=0, try_bmr=1, hold_count=0;
|
||||
SYSCTL_INT(_debug, OID_AUTO, firewire_debug, CTLFLAG_RW, &firewire_debug, 0,
|
||||
"FireWire driver debug flag");
|
||||
SYSCTL_NODE(_hw, OID_AUTO, firewire, CTLFLAG_RD, 0, "FireWire Subsystem");
|
||||
@ -1503,7 +1503,8 @@ fw_explore_node(struct fw_device *dfwdev)
|
||||
uint32_t *csr;
|
||||
struct csrhdr *hdr;
|
||||
struct bus_info *binfo;
|
||||
int err, node, spd;
|
||||
int err, node;
|
||||
uint32_t speed_test = 0;
|
||||
|
||||
fc = dfwdev->fc;
|
||||
csr = dfwdev->csrrom;
|
||||
@ -1511,8 +1512,12 @@ fw_explore_node(struct fw_device *dfwdev)
|
||||
|
||||
/* First quad */
|
||||
err = fw_explore_read_quads(dfwdev, CSRROMOFF, &csr[0], 1);
|
||||
if (err)
|
||||
if (err) {
|
||||
device_printf(fc->bdev, "%s: node%d: explore_read_quads failure\n",
|
||||
__func__, node);
|
||||
dfwdev->status = FWDEVINVAL;
|
||||
return (-1);
|
||||
}
|
||||
hdr = (struct csrhdr *)&csr[0];
|
||||
if (hdr->info_len != 4) {
|
||||
if (firewire_debug)
|
||||
@ -1532,7 +1537,18 @@ fw_explore_node(struct fw_device *dfwdev)
|
||||
node, binfo->bus_name);
|
||||
return (-1);
|
||||
}
|
||||
spd = fc->speed_map->speed[fc->nodeid][node];
|
||||
|
||||
if (firewire_debug)
|
||||
device_printf(fc->bdev, "%s: node(%d) BUS INFO BLOCK:\n"
|
||||
"irmc(%d) cmc(%d) isc(%d) bmc(%d) pmc(%d) "
|
||||
"cyc_clk_acc(%d) max_rec(%d) max_rom(%d) "
|
||||
"generation(%d) link_spd(%d)\n",
|
||||
__func__, node,
|
||||
binfo->irmc, binfo->cmc, binfo->isc,
|
||||
binfo->bmc, binfo->pmc, binfo->cyc_clk_acc,
|
||||
binfo->max_rec, binfo->max_rom,
|
||||
binfo->generation, binfo->link_spd);
|
||||
|
||||
STAILQ_FOREACH(fwdev, &fc->devices, link)
|
||||
if (FW_EUI64_EQUAL(fwdev->eui, binfo->eui64))
|
||||
break;
|
||||
@ -1547,6 +1563,40 @@ fw_explore_node(struct fw_device *dfwdev)
|
||||
}
|
||||
fwdev->fc = fc;
|
||||
fwdev->eui = binfo->eui64;
|
||||
/*
|
||||
* Pre-1394a-2000 didn't have link_spd in
|
||||
* the Bus Info block, so try and use the
|
||||
* speed map value.
|
||||
* 1394a-2000 compliant devices only use
|
||||
* the Bus Info Block link spd value, so
|
||||
* ignore the speed map alltogether. SWB
|
||||
*/
|
||||
if ( binfo->link_spd == FWSPD_S100 /* 0 */) {
|
||||
device_printf(fc->bdev, "%s"
|
||||
"Pre 1394a-2000 detected\n",
|
||||
__func__);
|
||||
fwdev->speed = fc->speed_map->speed[fc->nodeid][node];
|
||||
} else
|
||||
fwdev->speed = binfo->link_spd;
|
||||
/*
|
||||
* Test this speed with a read to the CSRROM.
|
||||
* If it fails, slow down the speed and retry.
|
||||
*/
|
||||
while (fwdev->speed > 0) {
|
||||
err = fw_explore_read_quads(fwdev, CSRROMOFF,
|
||||
&speed_test, 1);
|
||||
if (err)
|
||||
fwdev->speed--;
|
||||
else
|
||||
break;
|
||||
|
||||
}
|
||||
if (fwdev->speed != binfo->link_spd)
|
||||
device_printf(fc->bdev, "%s: fwdev->speed(%s)"
|
||||
" set lower than binfo->link_spd(%s)\n",
|
||||
__func__,
|
||||
linkspeed[fwdev->speed],
|
||||
linkspeed[binfo->link_spd]);
|
||||
/* inesrt into sorted fwdev list */
|
||||
pfwdev = NULL;
|
||||
STAILQ_FOREACH(tfwdev, &fc->devices, link) {
|
||||
@ -1562,12 +1612,11 @@ fw_explore_node(struct fw_device *dfwdev)
|
||||
STAILQ_INSERT_AFTER(&fc->devices, pfwdev, fwdev, link);
|
||||
|
||||
device_printf(fc->bdev, "New %s device ID:%08x%08x\n",
|
||||
linkspeed[spd],
|
||||
linkspeed[fwdev->speed],
|
||||
fwdev->eui.hi, fwdev->eui.lo);
|
||||
}
|
||||
fwdev->dst = node;
|
||||
fwdev->status = FWDEVINIT;
|
||||
fwdev->speed = spd;
|
||||
|
||||
/* unchanged ? */
|
||||
if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user