All of lore.kernel.org
 help / color / mirror / Atom feed
* Longhaul - infrastructure(?) proposal
@ 2006-06-29 15:05 Rafał Bilski
  2006-06-29 19:28 ` Dave Jones
  0 siblings, 1 reply; 3+ messages in thread
From: Rafał Bilski @ 2006-06-29 15:05 UTC (permalink / raw)
  To: Dave Jones; +Cc: cpufreq

Hello!

In case that flushing and disabling caches will not work.
It is possible that I do above in wrong way.
Would this code below be acceptable as infrastructure?
Is this infrastructure or maybe hack?
This is draft/proposal.
Can I continue in this way or I shouldn't?

Rafa³

---

/*
 * Longhaul "infrastructure" for bus master DMA
 */

struct longhaul_work {
	struct list_head entry;
	struct work_struct work;
	struct longhaul_data *data;
	void (*device_func) (void *data);
	void *device_data;
};

struct longhaul_data {
	struct workqueue_struct *wq;
	spinlock_t lock;
	struct list_head work_unused;
	struct list_head work_inuse;
	struct list_head work_used;
};

/* Access control for PCI bus */
static struct rw_semaphore longhaul_sem;

struct longhaul_data *longhaul_bmdma_register(char *name)
{
	struct longhaul_data *longdata;
	struct longhaul_work *longwork;
	struct workqueue_struct *workqueue;

	longdata = kmalloc(sizeof(struct longhaul_data), GFP_KERNEL);
	if (longdata == NULL)
		return NULL;
	spin_lock_init(&longdata->lock);
	INIT_LIST_HEAD(&longdata->work_unused);
	INIT_LIST_HEAD(&longdata->work_inuse);
	INIT_LIST_HEAD(&longdata->work_used);

	longwork = kmalloc(sizeof(struct longhaul_work), GFP_KERNEL);
	if (longwork == NULL) {
		goto free_longdata;
	}
	INIT_WORK(&longwork->work, &longhaul_bmdma_work, NULL);
	list_add(longwork, &longdata->work_unused);
	longwork->data = longdata;

	workqueue = create_singlethread_workqueue(name);
	if (workqueue == NULL) {
		printk(KERN_ERR PFX "Can't create workqueue \"%s\".\n", name);
		goto free_longwork;
	}
	longdata->wq = workqueue;

	return longdata;

free_longwork:
	kfree(longwork);
free_longdata:
	kfree(longdata);
	return NULL;
}
EXPORT_SYMBOL(longhaul_bmdma_register);


void longhaul_bmdma_unregister(struct longhaul_data *longdata)
{
}
EXPORT_SYMBOL(longhaul_bmdma_unregister);


static void longhaul_bmdma_work(void *data)
{
	struct longhaul_work *longwork = data;
	struct longhaul_data *longdata = longwork->data;
	unsigned long flags;

	down_read(&longhaul_sem);

	longdata->device_func(longdata->device_data);

	spin_lock_irqsave(&longdata->lock, flags);
	list_move(longwork, &longdata->work_used);
	spin_unlock_irqrestore(&longdata->lock, flags);
}

int longhaul_bmdma_begin(struct longhaul_data *longdata,
			void (*device_func) (void *data),
			void *device_data);
{
	struct longhaul_work *longwork;
	unsigned long flags;

	spin_lock_irqsave(&longdata->lock, flags);

	if ( list_empty(&longdata->work_unused) ) {
		longwork = kmalloc(sizeof(struct longhaul_work), GFP_ATOMIC);
		if (longwork == NULL) {
			spin_unlock_irqrestore(&longdata->lock, flags);
			return -ENOMEM;
		}
		INIT_WORK(&longwork->work, &longhaul_bmdma_work, NULL);
		longwork->data = longdata;
		list_add(longwork, &longdata->work_inuse);
	} else {
		longwork = longdata->work_unused->next;
		list_move(longwork, &longdata->work_inuse);
	}

	spin_unlock_irqrestore(&longdata->lock, flags);

	longwork->device_func = device_func;
	longwork->device_data = device_data;
	PREPARE_WORK(longwork, &longhaul_bmdma_work, (void*)longwork);
	queue_work(longdata->wq, longwork);

	return 0;
}
EXPORT_SYMBOL(longhaul_bmdma_begin);


void longhaul_bmdma_end(struct longhaul_data *longdata)
{
	struct list_head pos;
	unsigned long flags;

	spin_lock_irqsave(&longdata->lock, flags);

	if ( !list_empty(&longdata->work_used) ) {
		list_for_each(pos, &longdata->work_used) {
			list_move(longwork, &longdata->work_unused);
		}
	}

	spin_unlock_irqrestore(&longdata->lock, flags);

	up_read(&longhaul_sem);
}
EXPORT_SYMBOL(longhaul_bmdma_end);


----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Longhaul - infrastructure(?) proposal
  2006-06-29 15:05 Longhaul - infrastructure(?) proposal Rafał Bilski
@ 2006-06-29 19:28 ` Dave Jones
  0 siblings, 0 replies; 3+ messages in thread
From: Dave Jones @ 2006-06-29 19:28 UTC (permalink / raw)
  To: Rafał Bilski; +Cc: Dave Jones, cpufreq

On Thu, Jun 29, 2006 at 05:05:19PM +0200, Rafał Bilski wrote:
 > Hello!
 > 
 > In case that flushing and disabling caches will not work.
 > It is possible that I do above in wrong way.
 > Would this code below be acceptable as infrastructure?
 > Is this infrastructure or maybe hack?
 > This is draft/proposal.
 > Can I continue in this way or I shouldn't?

I suggest to keep talking with Greg, as any work on quiescing dma will
need cooperation from both USB & PCI layers, and he's one of the
more knowledgable people in the area of the driver model.

		Dave

-- 
http://www.codemonkey.org.uk

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Longhaul - infrastructure(?) proposal
@ 2006-06-29 20:26 Rafał Bilski
  0 siblings, 0 replies; 3+ messages in thread
From: Rafał Bilski @ 2006-06-29 20:26 UTC (permalink / raw)
  To: linux-kernel

In case that flushing and disabling caches will not work.
(but it is possible that I do above in wrong way).
Would this code below be acceptable as infrastructure?
Is this infrastructure or maybe hack? Are there any HOWTO 
write correct infrastructure?
This is draft/proposal.
Can I continue in this way or I shouldn't?

This code (more correct version) will be included in 
longhaul.c. There should be include file "cpufreq_longhaul.h"
for drivers knowing about "longhaul problem".

Driver would have all code for longhaul in
"#ifdef CONFIG_X86_LONGHAUL / #else / #endif".

Basic support for longhaul in driver:
1. driver calls longhaul_bmdma_register("driver_name_wq")
   at init,
2. driver calls longhaul_bmdma_begin before starting BMDMA
   with function that is starting DMA for this driver
   (or in case of via-rhine driver with function which queues
   packet in hardware queue). You can do it multiple times 
   before calling longhaul_bmdma_end for the first time,
3. driver calls longhaul_bmdma_end after BMDMA transfer is 
   completed (via-rhine - after packet was send).

Longhaul would simply lock write longhaul_sem before 
CPU frequency change.
 
Sorry to bother You all again.

Rafał

---

/*
 * Longhaul "infrastructure" for bus master DMA
 */

struct longhaul_work {
	struct list_head entry;
	struct work_struct work;
	struct longhaul_data *data;
	void (*device_func) (void *data);
	void *device_data;
};

struct longhaul_data {
	struct workqueue_struct *wq;
	spinlock_t lock;
	struct list_head work_unused;
	struct list_head work_inuse;
	struct list_head work_used;
};

/* Access control for PCI bus */
static struct rw_semaphore longhaul_sem;

struct longhaul_data *longhaul_bmdma_register(char *name)
{
	struct longhaul_data *longdata;
	struct longhaul_work *longwork;
	struct workqueue_struct *workqueue;

	longdata = kmalloc(sizeof(struct longhaul_data), GFP_KERNEL);
	if (longdata == NULL)
		return NULL;
	spin_lock_init(&longdata->lock);
	INIT_LIST_HEAD(&longdata->work_unused);
	INIT_LIST_HEAD(&longdata->work_inuse);
	INIT_LIST_HEAD(&longdata->work_used);

	longwork = kmalloc(sizeof(struct longhaul_work), GFP_KERNEL);
	if (longwork == NULL) {
		goto free_longdata;
	}
	INIT_WORK(&longwork->work, &longhaul_bmdma_work, NULL);
	list_add(longwork, &longdata->work_unused);
	longwork->data = longdata;

	workqueue = create_singlethread_workqueue(name);
	if (workqueue == NULL) {
		printk(KERN_ERR PFX "Can't create workqueue \"%s\".\n", name);
		goto free_longwork;
	}
	longdata->wq = workqueue;

	return longdata;

free_longwork:
	kfree(longwork);
free_longdata:
	kfree(longdata);
	return NULL;
}
EXPORT_SYMBOL(longhaul_bmdma_register);


void longhaul_bmdma_unregister(struct longhaul_data *longdata)
{
}
EXPORT_SYMBOL(longhaul_bmdma_unregister);


static void longhaul_bmdma_work(void *data)
{
	struct longhaul_work *longwork = data;
	struct longhaul_data *longdata = longwork->data;
	unsigned long flags;

	down_read(&longhaul_sem);

	longdata->device_func(longdata->device_data);

	spin_lock_irqsave(&longdata->lock, flags);
	list_move(longwork, &longdata->work_used);
	spin_unlock_irqrestore(&longdata->lock, flags);
}

int longhaul_bmdma_begin(struct longhaul_data *longdata,
			void (*device_func) (void *data),
			void *device_data);
{
	struct longhaul_work *longwork;
	unsigned long flags;

	spin_lock_irqsave(&longdata->lock, flags);

	if ( list_empty(&longdata->work_unused) ) {
		longwork = kmalloc(sizeof(struct longhaul_work), GFP_ATOMIC);
		if (longwork == NULL) {
			spin_unlock_irqrestore(&longdata->lock, flags);
			return -ENOMEM;
		}
		INIT_WORK(&longwork->work, &longhaul_bmdma_work, NULL);
		longwork->data = longdata;
		list_add(longwork, &longdata->work_inuse);
	} else {
		longwork = longdata->work_unused->next;
		list_move(longwork, &longdata->work_inuse);
	}

	spin_unlock_irqrestore(&longdata->lock, flags);

	longwork->device_func = device_func;
	longwork->device_data = device_data;
	PREPARE_WORK(longwork, &longhaul_bmdma_work, (void*)longwork);
	queue_work(longdata->wq, longwork);

	return 0;
}
EXPORT_SYMBOL(longhaul_bmdma_begin);


void longhaul_bmdma_end(struct longhaul_data *longdata)
{
	struct list_head pos;
	unsigned long flags;

	spin_lock_irqsave(&longdata->lock, flags);

	if ( !list_empty(&longdata->work_used) ) {
		list_for_each(pos, &longdata->work_used) {
			list_move(longwork, &longdata->work_unused);
		}
	}

	spin_unlock_irqrestore(&longdata->lock, flags);

	up_read(&longhaul_sem);
}
EXPORT_SYMBOL(longhaul_bmdma_end);



----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-06-29 20:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-29 15:05 Longhaul - infrastructure(?) proposal Rafał Bilski
2006-06-29 19:28 ` Dave Jones
  -- strict thread matches above, loose matches on Subject: below --
2006-06-29 20:26 Rafał Bilski

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.