no_room:
afu->read_room = true;
+ kref_get(&cfg->afu->mapcount);
schedule_work(&cfg->work_q);
rc = SCSI_MLQUEUE_HOST_BUSY;
goto out;
return rc;
}
+static void afu_unmap(struct kref *ref)
+{
+ struct afu *afu = container_of(ref, struct afu, mapcount);
+
+ if (likely(afu->afu_map)) {
+ cxl_psa_unmap((void __iomem *)afu->afu_map);
+ afu->afu_map = NULL;
+ }
+}
+
/**
* cxlflash_driver_info() - information handler for this host driver
* @host: SCSI host associated with device.
ulong lock_flags;
short lflag = 0;
int rc = 0;
+ int kref_got = 0;
dev_dbg_ratelimited(dev, "%s: (scp=%p) %d/%d/%d/%llu "
"cdb=(%08X-%08X-%08X-%08X)\n",
goto out;
}
+ kref_get(&cfg->afu->mapcount);
+ kref_got = 1;
+
cmd->rcb.ctx_id = afu->ctx_hndl;
cmd->rcb.port_sel = port_sel;
cmd->rcb.lun_id = lun_to_lunid(scp->device->lun);
}
out:
+ if (kref_got)
+ kref_put(&afu->mapcount, afu_unmap);
pr_devel("%s: returning rc=%d\n", __func__, rc);
return rc;
}
cxl_psa_unmap((void __iomem *)afu->afu_map);
afu->afu_map = NULL;
}
+ kref_put(&afu->mapcount, afu_unmap);
}
}
scsi_remove_host(cfg->host);
/* fall through */
case INIT_STATE_AFU:
- term_afu(cfg);
cancel_work_sync(&cfg->work_q);
+ term_afu(cfg);
case INIT_STATE_PCI:
pci_release_regions(cfg->dev);
pci_disable_device(pdev);
__func__, port);
cfg->lr_state = LINK_RESET_REQUIRED;
cfg->lr_port = port;
+ kref_get(&cfg->afu->mapcount);
schedule_work(&cfg->work_q);
}
if (info->action & SCAN_HOST) {
atomic_inc(&cfg->scan_host_needed);
+ kref_get(&cfg->afu->mapcount);
schedule_work(&cfg->work_q);
}
}
rc = -ENOMEM;
goto err1;
}
+ kref_init(&afu->mapcount);
/* No byte reverse on reading afu_version or string will be backwards */
reg = readq(&afu->afu_map->global.regs.afu_version);
return rc;
err2:
- cxl_psa_unmap((void __iomem *)afu->afu_map);
- afu->afu_map = NULL;
+ kref_put(&afu->mapcount, afu_unmap);
err1:
term_mc(cfg, UNDO_START);
goto out;
if (atomic_dec_if_positive(&cfg->scan_host_needed) >= 0)
scsi_scan_host(cfg->host);
+ kref_put(&afu->mapcount, afu_unmap);
}
/**