@@ -3857,14 +3857,10 @@ static int ufshcd_get_ref_clk_gating_wait(struct ufs_hba *hba)
*/
static int ufshcd_memory_alloc(struct ufs_hba *hba)
{
- size_t utmrdl_size, utrdl_size, ucdl_size;
-
/* Allocate memory for UTP command descriptors */
- ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs;
- hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev,
- ucdl_size,
- &hba->ucdl_dma_addr,
- GFP_KERNEL);
+ hba->ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs;
+ hba->ucdl_base_addr = dmam_alloc_coherent(
+ hba->dev, hba->ucdl_size, &hba->ucdl_dma_addr, GFP_KERNEL);
/*
* UFSHCI requires UTP command descriptor to be 128 byte aligned.
@@ -3880,11 +3876,9 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
* Allocate memory for UTP Transfer descriptors
* UFSHCI requires 1KB alignment of UTRD
*/
- utrdl_size = (sizeof(struct utp_transfer_req_desc) * hba->nutrs);
- hba->utrdl_base_addr = dmam_alloc_coherent(hba->dev,
- utrdl_size,
- &hba->utrdl_dma_addr,
- GFP_KERNEL);
+ hba->utrdl_size = sizeof(struct utp_transfer_req_desc) * hba->nutrs;
+ hba->utrdl_base_addr = dmam_alloc_coherent(
+ hba->dev, hba->utrdl_size, &hba->utrdl_dma_addr, GFP_KERNEL);
if (!hba->utrdl_base_addr ||
WARN_ON(hba->utrdl_dma_addr & (SZ_1K - 1))) {
dev_err(hba->dev,
@@ -3896,7 +3890,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
* Skip utmrdl allocation; it may have been
* allocated during first pass and not released during
* MCQ memory allocation.
- * See ufshcd_release_sdb_queue() and ufshcd_config_mcq()
+ * See ufshcd_memory_free() and ufshcd_config_mcq()
*/
if (hba->utmrdl_base_addr)
goto skip_utmrdl;
@@ -3904,11 +3898,9 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
* Allocate memory for UTP Task Management descriptors
* UFSHCI requires 1KB alignment of UTMRD
*/
- utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
- hba->utmrdl_base_addr = dmam_alloc_coherent(hba->dev,
- utmrdl_size,
- &hba->utmrdl_dma_addr,
- GFP_KERNEL);
+ hba->utmrdl_size = sizeof(struct utp_task_req_desc) * hba->nutmrs;
+ hba->utmrdl_base_addr = dmam_alloc_coherent(
+ hba->dev, hba->utmrdl_size, &hba->utmrdl_dma_addr, GFP_KERNEL);
if (!hba->utmrdl_base_addr ||
WARN_ON(hba->utmrdl_dma_addr & (SZ_1K - 1))) {
dev_err(hba->dev,
@@ -8705,20 +8697,30 @@ static int ufshcd_add_lus(struct ufs_hba *hba)
return ret;
}
-/* SDB - Single Doorbell */
-static void ufshcd_release_sdb_queue(struct ufs_hba *hba, int nutrs)
+/*
+ * Free the memory allocated by ufshcd_memory_alloc() except the utmrdl DMA
+ * memory.
+ */
+static void ufshcd_memory_free(struct ufs_hba *hba)
{
- size_t ucdl_size, utrdl_size;
-
- ucdl_size = ufshcd_get_ucd_size(hba) * nutrs;
- dmam_free_coherent(hba->dev, ucdl_size, hba->ucdl_base_addr,
- hba->ucdl_dma_addr);
+ if (hba->ucdl_base_addr) {
+ dmam_free_coherent(hba->dev, hba->ucdl_size,
+ hba->ucdl_base_addr, hba->ucdl_dma_addr);
+ hba->ucdl_base_addr = NULL;
+ hba->ucdl_dma_addr = 0;
+ }
- utrdl_size = sizeof(struct utp_transfer_req_desc) * nutrs;
- dmam_free_coherent(hba->dev, utrdl_size, hba->utrdl_base_addr,
- hba->utrdl_dma_addr);
+ if (hba->utrdl_base_addr) {
+ dmam_free_coherent(hba->dev, hba->utrdl_size,
+ hba->utrdl_base_addr, hba->utrdl_dma_addr);
+ hba->utrdl_base_addr = NULL;
+ hba->utrdl_dma_addr = 0;
+ }
- devm_kfree(hba->dev, hba->lrb);
+ if (hba->lrb) {
+ devm_kfree(hba->dev, hba->lrb);
+ hba->lrb = NULL;
+ }
}
static int ufshcd_alloc_mcq(struct ufs_hba *hba)
@@ -8740,7 +8742,7 @@ static int ufshcd_alloc_mcq(struct ufs_hba *hba)
* Number of supported tags in MCQ mode may be larger than SDB mode.
*/
if (hba->nutrs != old_nutrs) {
- ufshcd_release_sdb_queue(hba, old_nutrs);
+ ufshcd_memory_free(hba);
ret = ufshcd_memory_alloc(hba);
if (ret)
goto err;
@@ -847,6 +847,9 @@ enum ufshcd_mcq_opr {
/**
* struct ufs_hba - per adapter private structure
* @mmio_base: UFSHCI base register address
+ * @ucdl_size: Size of UFS Command Descriptor buffer
+ * @utrdl_size: Size of UTP Transfer Request Descriptor buffer
+ * @utmrdl_size: Size of UTP Task Management Descriptor buffer
* @ucdl_base_addr: UFS Command Descriptor base address
* @utrdl_base_addr: UTP Transfer Request Descriptor base address
* @utmrdl_base_addr: UTP Task Management Descriptor base address
@@ -975,6 +978,8 @@ enum ufshcd_mcq_opr {
struct ufs_hba {
void __iomem *mmio_base;
+ u32 ucdl_size, utrdl_size, utmrdl_size;
+
/* Virtual memory reference */
struct utp_transfer_cmd_desc *ucdl_base_addr;
struct utp_transfer_req_desc *utrdl_base_addr;
Prepare for supporting DMA buffer reallocation. Caching the DMA buffer sizes is essential because a later patch will modify hba->nutrs between the ufshcd_memory_alloc() and the ufshcd_memory_free() calls. Signed-off-by: Bart Van Assche <bvanassche@acm.org> --- drivers/ufs/core/ufshcd.c | 62 ++++++++++++++++++++------------------- include/ufs/ufshcd.h | 5 ++++ 2 files changed, 37 insertions(+), 30 deletions(-)