All of lore.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 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.