Page MenuHomeFreeBSD

D58658.diff
No OneTemporary

D58658.diff

diff --git a/sys/dev/ufshci/ufshci_ctrlr.c b/sys/dev/ufshci/ufshci_ctrlr.c
--- a/sys/dev/ufshci/ufshci_ctrlr.c
+++ b/sys/dev/ufshci/ufshci_ctrlr.c
@@ -448,6 +448,8 @@
bus_release_resource(ctrlr->dev, SYS_RES_IRQ,
rman_get_rid(ctrlr->res), ctrlr->res);
+ ufshci_sim_release_wlun_periph(ctrlr);
+
mtx_lock(&ctrlr->sc_mtx);
ufshci_sim_detach(ctrlr);
diff --git a/sys/dev/ufshci/ufshci_dev.c b/sys/dev/ufshci/ufshci_dev.c
--- a/sys/dev/ufshci/ufshci_dev.c
+++ b/sys/dev/ufshci/ufshci_dev.c
@@ -508,12 +508,15 @@
if (ctrlr->quirks & UFSHCI_QUIRK_SKIP_WELL_KNOWN_LUNS)
return (0);
- ctrlr->ufs_device_wlun_periph = ufshci_sim_find_periph(ctrlr,
- UFSHCI_WLUN_UFS_DEVICE);
if (ctrlr->ufs_device_wlun_periph == NULL) {
- ufshci_printf(ctrlr,
- "Well-known LUN `UFS Device (0x50)` not found\n");
- return (0);
+ /* The returned reference is kept by the cached pointer. */
+ ctrlr->ufs_device_wlun_periph = ufshci_sim_find_periph(ctrlr,
+ UFSHCI_WLUN_UFS_DEVICE);
+ if (ctrlr->ufs_device_wlun_periph == NULL) {
+ ufshci_printf(ctrlr,
+ "Well-known LUN `UFS Device (0x50)` not found\n");
+ return (0);
+ }
}
ctrlr->ufs_dev.power_mode_supported = true;
diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h
--- a/sys/dev/ufshci/ufshci_private.h
+++ b/sys/dev/ufshci/ufshci_private.h
@@ -434,6 +434,7 @@
uint64_t ufshci_sim_translate_ufs_to_scsi_lun(uint8_t ufs_lun);
int ufshci_sim_attach(struct ufshci_controller *ctrlr);
void ufshci_sim_detach(struct ufshci_controller *ctrlr);
+void ufshci_sim_release_wlun_periph(struct ufshci_controller *ctrlr);
struct cam_periph *ufshci_sim_find_periph(struct ufshci_controller *ctrlr,
uint8_t wlun);
int ufshci_sim_send_ssu(struct ufshci_controller *ctrlr, bool start,
diff --git a/sys/dev/ufshci/ufshci_sim.c b/sys/dev/ufshci/ufshci_sim.c
--- a/sys/dev/ufshci/ufshci_sim.c
+++ b/sys/dev/ufshci/ufshci_sim.c
@@ -393,6 +393,20 @@
return (0);
}
+/*
+ * Drop the cached WLUN periph reference. cam_periph_release() takes the
+ * CAM device lock itself, so call this without sc_mtx held: CAM takes
+ * the device lock before the SIM lock, not the other way around.
+ */
+void
+ufshci_sim_release_wlun_periph(struct ufshci_controller *ctrlr)
+{
+ if (ctrlr->ufs_device_wlun_periph != NULL) {
+ cam_periph_release(ctrlr->ufs_device_wlun_periph);
+ ctrlr->ufs_device_wlun_periph = NULL;
+ }
+}
+
void
ufshci_sim_detach(struct ufshci_controller *ctrlr)
{
@@ -425,6 +439,10 @@
}
}
+/*
+ * On success this returns a referenced periph; the caller is responsible
+ * for dropping the reference with cam_periph_release().
+ */
struct cam_periph *
ufshci_sim_find_periph(struct ufshci_controller *ctrlr, uint8_t wlun)
{
@@ -446,6 +464,8 @@
while (1) {
xpt_path_lock(path);
periph = cam_periph_find(path, "pass");
+ if (periph != NULL && cam_periph_acquire(periph) != 0)
+ periph = NULL;
xpt_path_unlock(path);
if (periph)
@@ -474,17 +494,23 @@
union ccb *ccb;
int err;
- /* Acquire periph reference */
- if (periph && cam_periph_acquire(periph) != 0) {
+ /* Acquire a periph reference for the duration of this call. */
+ if (periph != NULL && cam_periph_acquire(periph) != 0) {
+ /* The cached periph is going away; drop its reference. */
+ cam_periph_release(periph);
+ ctrlr->ufs_device_wlun_periph = NULL;
periph = NULL;
}
if (periph == NULL) {
- /* If the periph device does not exist, it will try to find it
- * again */
+ /*
+ * If the periph device does not exist, try to find it again.
+ * The reference returned by ufshci_sim_find_periph() is used
+ * for this call; take an extra one for the cached pointer.
+ */
periph = ufshci_sim_find_periph(ctrlr,
(uint8_t)UFSHCI_WLUN_UFS_DEVICE);
- if (periph)
+ if (periph != NULL && cam_periph_acquire(periph) == 0)
ctrlr->ufs_device_wlun_periph = periph;
}

File Metadata

Mime Type
text/plain
Expires
Wed, Sep 2, 8:23 PM (17 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37969516
Default Alt Text
D58658.diff (3 KB)

Event Timeline