All of lore.kernel.org
 help / color / mirror / Atom feed
From: Parag Warudkar <kernel-stuff@comcast.net>
To: Andrew Morton <akpm@osdl.org>
Cc: bcollins@debian.org, linux-kernel@vger.kernel.org,
	linux1394-devel@lists.sourceforge.net
Subject: Re: [PATCH] ohci1394: dma_pool_destroy while in_atomic() && irqs_disabled()
Date: Sun, 30 Jan 2005 20:19:18 -0500	[thread overview]
Message-ID: <41FD8796.2020509@comcast.net> (raw)
In-Reply-To: <20050130150224.33299170.akpm@osdl.org>

[-- Attachment #1: Type: text/plain, Size: 1210 bytes --]

Attached is the reworked patch to take care of Andrew's suggestions -

1) Allocate the work struct dynamically in struct ti_ohci during  device 
probe, free it during device remove
2) In ohci1394_pci_remove, ensure queued work, if any, is flushed before 
the device is removed (As I understand, this should work for both device 
removal cases as well as module removal - correct?)
3) Rework the free_dma_rcv_ctx  - It is called in multiple contexts by 
different callers - teach it to free the dma according to caller's wish 
- either direct free where caller determines the context is safe to 
sleep OR delayed via schedule_work when caller wants to call it from a 
context where it cannot sleep.  So it now takes 2 extra arguments - 
method to free - direct or delayed and if it is to be  freed delayed, an 
appropriate work_struct.

Andrew - flush_scheduled_work does not touch work which isn't shceduled 
- so I don't think INIT_WORK in setup is necessary. Let me know if I am 
missing something here. (I tried INIT_WORK in ochi1394_pci_probe and 
putting flush_scheduled_work in ohci1394_pci_remove - It did not result 
in calling the work function after I did rmmod, since it wasn't scheduled.)

Parag



[-- Attachment #2: patch-ohci1394 --]
[-- Type: text/plain, Size: 5918 bytes --]

--- drivers/ieee1394/ohci1394.c.orig	2004-12-24 16:35:25.000000000 -0500
+++ drivers/ieee1394/ohci1394.c	2005-01-30 20:00:42.000000000 -0500
@@ -99,6 +99,7 @@
 #include <asm/uaccess.h>
 #include <linux/delay.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
@@ -161,6 +162,10 @@
 #define PRINT(level, fmt, args...) \
 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
 
+/* Instruct free_dma_rcv_ctx how to free dma pools */
+#define OHCI_FREE_DMA_CTX_DIRECT 0
+#define OHCI_FREE_DMA_CTX_DELAYED 1
+
 static char version[] __devinitdata =
 	"$Rev: 1223 $ Ben Collins <bcollins@debian.org>";
 
@@ -176,7 +181,8 @@
 			     enum context_type type, int ctx, int num_desc,
 			     int buf_size, int split_buf_size, int context_base);
 static void stop_dma_rcv_ctx(struct dma_rcv_ctx *d);
-static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
+static void free_dma_rcv_ctx(struct dma_rcv_ctx *d , int method,
+			     struct work_struct* work);
 
 static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
 			     enum context_type type, int ctx, int num_desc,
@@ -184,6 +190,8 @@
 
 static void ohci1394_pci_remove(struct pci_dev *pdev);
 
+static void ohci_free_irlc_pci_pool(void* data);
+
 #ifndef __LITTLE_ENDIAN
 static unsigned hdr_sizes[] =
 {
@@ -1117,7 +1125,8 @@
 
 		if (ohci->ir_legacy_channels == 0) {
 			stop_dma_rcv_ctx(&ohci->ir_legacy_context);
-			free_dma_rcv_ctx(&ohci->ir_legacy_context);
+			INIT_WORK(ohci->irlc_free_dma, ohci_free_irlc_pci_pool, ohci->ir_legacy_context.prg_pool);
+			free_dma_rcv_ctx(&ohci->ir_legacy_context, OHCI_FREE_DMA_CTX_DELAYED, ohci->irlc_free_dma);
 			DBGMSG("ISO receive legacy context deactivated");
 		}
                 break;
@@ -2876,7 +2885,8 @@
 }
 
 
-static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
+static void free_dma_rcv_ctx(struct dma_rcv_ctx *d, int method,
+		struct work_struct* work)
 {
 	int i;
 	struct ti_ohci *ohci = d->ohci;
@@ -2903,8 +2913,20 @@
 				pci_pool_free(d->prg_pool, d->prg_cpu[i], d->prg_bus[i]);
 				OHCI_DMA_FREE("consistent dma_rcv prg[%d]", i);
 			}
-		pci_pool_destroy(d->prg_pool);
-		OHCI_DMA_FREE("dma_rcv prg pool");
+		if(method == OHCI_FREE_DMA_CTX_DIRECT)
+		{
+			pci_pool_destroy(d->prg_pool);
+			OHCI_DMA_FREE("dma_rcv prg pool");
+		}
+		
+		else if(method == OHCI_FREE_DMA_CTX_DELAYED)
+		{
+			schedule_work(work);
+		}
+
+		else
+			PRINT(KERN_ERR, "Invalid method passed - %d", method);
+
 		kfree(d->prg_cpu);
 		kfree(d->prg_bus);
 	}
@@ -2938,7 +2960,7 @@
 
 	if (d->buf_cpu == NULL || d->buf_bus == NULL) {
 		PRINT(KERN_ERR, "Failed to allocate dma buffer");
-		free_dma_rcv_ctx(d);
+		free_dma_rcv_ctx(d, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 		return -ENOMEM;
 	}
 	memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*));
@@ -2950,7 +2972,7 @@
 
 	if (d->prg_cpu == NULL || d->prg_bus == NULL) {
 		PRINT(KERN_ERR, "Failed to allocate dma prg");
-		free_dma_rcv_ctx(d);
+		free_dma_rcv_ctx(d, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 		return -ENOMEM;
 	}
 	memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*));
@@ -2960,7 +2982,7 @@
 
 	if (d->spb == NULL) {
 		PRINT(KERN_ERR, "Failed to allocate split buffer");
-		free_dma_rcv_ctx(d);
+		free_dma_rcv_ctx(d, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 		return -ENOMEM;
 	}
 
@@ -2979,7 +3001,7 @@
 		} else {
 			PRINT(KERN_ERR,
 			      "Failed to allocate dma buffer");
-			free_dma_rcv_ctx(d);
+			free_dma_rcv_ctx(d, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 			return -ENOMEM;
 		}
 
@@ -2991,7 +3013,7 @@
 		} else {
 			PRINT(KERN_ERR,
 			      "Failed to allocate dma prg");
-			free_dma_rcv_ctx(d);
+			free_dma_rcv_ctx(d, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 			return -ENOMEM;
 		}
 	}
@@ -3005,7 +3027,7 @@
 		if (ohci1394_register_iso_tasklet(ohci,
 						  &ohci->ir_legacy_tasklet) < 0) {
 			PRINT(KERN_ERR, "No IR DMA context available");
-			free_dma_rcv_ctx(d);
+			free_dma_rcv_ctx(d, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 			return -EBUSY;
 		}
 
@@ -3355,6 +3377,7 @@
 
 	/* the IR DMA context is allocated on-demand; mark it inactive */
 	ohci->ir_legacy_context.ohci = NULL;
+	ohci->ir_legacy_context.prg_pool = NULL;
 
 	/* same for the IT DMA context */
 	ohci->it_legacy_context.ohci = NULL;
@@ -3377,16 +3400,32 @@
 	if (hpsb_add_host(host))
 		FAIL(-ENOMEM, "Failed to register host with highlevel");
 
+	ohci->irlc_free_dma = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
+	if(ohci->irlc_free_dma == NULL)
+		FAIL(-ENOMEM, "Failed to allocate memory for ohci->irlc_free_dma");
+
 	ohci->init_state = OHCI_INIT_DONE;
 
 	return 0;
 #undef FAIL
 }
 
+static void ohci_free_irlc_pci_pool(void *data)
+{
+	if(data == NULL)
+		return;
+	pci_pool_destroy(data);
+	OHCI_DMA_FREE("dma_rcv prg pool");
+	return;
+}
+	
 static void ohci1394_pci_remove(struct pci_dev *pdev)
 {
 	struct ti_ohci *ohci;
 	struct device *dev;
+	
+	/* Ensure all dma ctx are freed */
+	flush_scheduled_work();
 
 	ohci = pci_get_drvdata(pdev);
 	if (!ohci)
@@ -3432,18 +3471,21 @@
 		/* The ohci_soft_reset() stops all DMA contexts, so we
 		 * dont need to do this.  */
 		/* Free AR dma */
-		free_dma_rcv_ctx(&ohci->ar_req_context);
-		free_dma_rcv_ctx(&ohci->ar_resp_context);
+		free_dma_rcv_ctx(&ohci->ar_req_context, OHCI_FREE_DMA_CTX_DIRECT, NULL);
+		free_dma_rcv_ctx(&ohci->ar_resp_context, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 
 		/* Free AT dma */
 		free_dma_trm_ctx(&ohci->at_req_context);
 		free_dma_trm_ctx(&ohci->at_resp_context);
 
 		/* Free IR dma */
-		free_dma_rcv_ctx(&ohci->ir_legacy_context);
+		free_dma_rcv_ctx(&ohci->ir_legacy_context, OHCI_FREE_DMA_CTX_DIRECT, NULL);
 
 		/* Free IT dma */
 		free_dma_trm_ctx(&ohci->it_legacy_context);
+		
+		/* Free work struct for IR Legacy DMA */
+		kfree(ohci->irlc_free_dma);
 
 	case OHCI_INIT_HAVE_SELFID_BUFFER:
 		pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,

  reply	other threads:[~2005-01-31  1:19 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-30 20:54 [PATCH] ohci1394: dma_pool_destroy while in_atomic() && irqs_disabled() Parag Warudkar
2005-01-30 21:17 ` Andrew Morton
2005-01-30 22:49   ` Parag Warudkar
2005-01-30 23:02     ` Andrew Morton
2005-01-31  1:19       ` Parag Warudkar [this message]
2005-01-31 23:26         ` Parag Warudkar
2005-02-11 15:35         ` Dan Dennedy
2005-02-11 18:43           ` Jody McIntyre
2005-02-12  3:54             ` Parag Warudkar
2005-02-18 15:32               ` Dan Dennedy
2005-02-18 15:42                 ` Parag Warudkar
2005-02-19  6:36                   ` Jody McIntyre
2005-02-19 15:06                     ` Parag Warudkar
  -- strict thread matches above, loose matches on Subject: below --
2005-02-19 19:36 David Brownell
2005-02-19 20:50 ` Parag Warudkar
2005-02-19 21:13   ` David Brownell
2005-02-19 22:55 ` Jody McIntyre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=41FD8796.2020509@comcast.net \
    --to=kernel-stuff@comcast.net \
    --cc=akpm@osdl.org \
    --cc=bcollins@debian.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux1394-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.