public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Parag Warudkar <kernel-stuff@comcast.net>
To: Parag Warudkar <kernel-stuff@comcast.net>
Cc: Andrew Morton <akpm@osdl.org>,
	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: Mon, 31 Jan 2005 18:26:58 -0500	[thread overview]
Message-ID: <41FEBEC2.5050501@comcast.net> (raw)
In-Reply-To: <41FD8796.2020509@comcast.net>

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

Forgot to attach ohci.h diff which is affected by this change as well.

Meanwhile, David Brownell suggested it would be much simpler to move the 
dma allocations to _probe and  deallocations to _remove.
I am working on it and so far haven't got it to work.

Andrew - What do you think? If you too feel allocating pci_pool for the 
legacy contexts (only disadvantage I see is that the pool will be 
allocated even if it is not used, that is if ISO_LISTEN_CHANNEL isn't 
called any time)  in _probe an removing it in _remove is a better thing 
to do, I will concentrate on getting that to work and we can forget 
about this patch. I feel there might be some reason why the current code 
treats the legacy IR and IT DMA ctxs differently (on-demand  
allocation).. Ben?

Parag

Parag Warudkar wrote:

> 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
>
>
>------------------------------------------------------------------------
>
>--- 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,
>  
>


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

--- drivers/ieee1394/ohci1394.h.orig	2004-12-24 16:34:00.000000000 -0500
+++ drivers/ieee1394/ohci1394.h	2005-01-31 18:16:31.000000000 -0500
@@ -197,6 +197,8 @@
 				   it is safe to free the legacy API context */
 
 	struct dma_rcv_ctx ir_legacy_context;
+	struct work_struct* irlc_free_dma;
+	
 	struct ohci1394_iso_tasklet ir_legacy_tasklet;
 
         /* iso transmit */

  reply	other threads:[~2005-01-31 23:31 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
2005-01-31 23:26         ` Parag Warudkar [this message]
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=41FEBEC2.5050501@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox