* Re: [PATCH] ARM: mach-shmobile: ag5evm needs CONFIG_I2C
From: Paul Mundt @ 2011-09-05 4:19 UTC (permalink / raw)
To: linux-sh
On Tue, Aug 30, 2011 at 06:19:13PM +0200, Guennadi Liakhovetski wrote:
> ag5evm implements a backlight control, using an I2C controller, therefore
> it needs CONFIG_I2C to fix this make failure
>
> arch/arm/mach-shmobile/built-in.o: In function `lcd_on':
> pfc-sh73a0.c:(.text+0x2334): undefined reference to `i2c_get_adapter'
> pfc-sh73a0.c:(.text+0x2370): undefined reference to `i2c_transfer'
>
> (ignore pfc-sh73a0.c) and to build successfully.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH 0/2] mmc: sh_mmcif: simplify platform DMA configuration
From: Paul Mundt @ 2011-09-05 4:15 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <Pine.LNX.4.64.1108301819150.19151@axis700.grange>
On Tue, Aug 30, 2011 at 06:26:34PM +0200, Guennadi Liakhovetski wrote:
> A simple cosmetic clean-up, no functional changes. Patch 2/2 depends on
> patch 1/2 and can wait until 3.3. Paul, would you be able to put it under
> the carpet somewhere until then or shall I resend it after 3.2-rc1 is out?
> After both these patches have been applied, we can remove struct
> sh_mmcif_plat_data::dma around 3.4 or 4.0 or whatever;-)
>
It's not a problem, I'll just flag it as awaiting upstream in the
tracker. Anything flagged as such I generally give a once over after each
merge window to see if their dependencies have been worked out.
^ permalink raw reply
* Re: [PATCH] [RFC] sh: kexec: Register crashk_res
From: Paul Mundt @ 2011-09-05 3:23 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1314935232-1545-1-git-send-email-horms@verge.net.au>
On Fri, Sep 02, 2011 at 12:47:12PM +0900, Simon Horman wrote:
> Register crashk_res so that it can be used by kexec-tools
> via /proc/iomem.
>
> On x86 the registration occurs using
> insert_resource(&iomem_resource, &crashk_res).
> However that approach seems to result in the boot hanging on SH.
>
> Signed-off-by: Simon Horman <horms@verge.net.au>
x86 has a slightly more straightforward registration method. We end up
going through the same path for all memory ranges, which also
encapsulates the NUMA case. As such, we don't necessarily know which
range will contain the resource in question, so it's attempted on each
range addition, expecting the resource manager to work things out for us.
With the request_resource() in place you presumably see the crash kernel
resource where you expect it to in /proc/iomem?
^ permalink raw reply
* Re: [PATCH 3/5] PM / QoS: Add function dev_pm_qos_read_value()
From: Rafael J. Wysocki @ 2011-09-03 8:02 UTC (permalink / raw)
To: Jean Pihet
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <201109030155.28031.rjw@sisk.pl>
Hi,
On Saturday, September 03, 2011, Rafael J. Wysocki wrote:
> On Friday, September 02, 2011, Jean Pihet wrote:
> > On Fri, Sep 2, 2011 at 12:07 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
...
> > >> >
> > >> > - mutex_lock(&dev_pm_qos_mtx);
> > >> > req->dev = dev;
> > >> >
> > >> > - /* Return if the device has been removed */
> > >> > - if (req->dev->power.constraints_state = DEV_PM_QOS_NO_DEVICE) {
> > >> > - ret = -ENODEV;
> > >> > - goto out;
> > >> > - }
> > >> > + device_pm_lock();
> > >> > + mutex_lock(&dev_pm_qos_mtx);
> > >> >
> > >> > - /*
> > >> > - * Allocate the constraints data on the first call to add_request,
> > >> > - * i.e. only if the data is not already allocated and if the device has
> > >> > - * not been removed
> > >> > - */
> > >> > - if (dev->power.constraints_state = DEV_PM_QOS_DEVICE_PRESENT)
> > >> > - ret = dev_pm_qos_constraints_allocate(dev);
> > >> > + if (dev->power.constraints) {
> > >> > + device_pm_unlock();
> > >> > + } else {
> > >> > + if (list_empty(&dev->power.entry)) {
> > >> > + /* The device has been removed from the system. */
> > >> > + device_pm_unlock();
> > >> > + goto out;
> > >> 0 is silently returned in case the device has been removed. Is that
> > >> the intention?
> > >
> > > Pretty much it is. Is that a problem?
> > I think the caller needs to know if the constraint has been applied
> > correctly or not.
>
> However, the removal of the device is a special case. What would the caller
> be supposed to do when it learned that the device had been removed while it had
> been trying to add a QoS constraing for it? Not much I guess.
Anyway, since returning an error code in that case won't hurt either,
below is a v2 of the patch doing that and resetting the dev field in the
req structure.
Thanks,
Rafael
---
From: Rafael J. Wysocki <rjw@sisk.pl>
Subject: PM / QoS: Add function dev_pm_qos_read_value() (v2)
To read the current PM QoS value for a given device we need to
make sure that the device's power.constraints object won't be
removed while we're doing that. For this reason, put the
operation under dev->power.lock and acquire the lock
around the initialization and removal of power.constraints.
Moreover, since we're using the value of power.constraints to
determine whether or not the object is present, the
power.constraints_state field isn't necessary any more and may be
removed. However, dev_pm_qos_add_request() needs to check if the
device is being removed from the system before allocating a new
PM QoS constraints object for it, so it has to use device_pm_lock()
and the device PM QoS initialization and destruction should be done
under device_pm_lock() as well.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
drivers/base/power/main.c | 4 -
drivers/base/power/qos.c | 170 ++++++++++++++++++++++++++--------------------
include/linux/pm.h | 8 --
include/linux/pm_qos.h | 3
4 files changed, 104 insertions(+), 81 deletions(-)
Index: linux/drivers/base/power/qos.c
=================================--- linux.orig/drivers/base/power/qos.c
+++ linux/drivers/base/power/qos.c
@@ -30,15 +30,6 @@
* . To minimize the data usage by the per-device constraints, the data struct
* is only allocated at the first call to dev_pm_qos_add_request.
* . The data is later free'd when the device is removed from the system.
- * . The constraints_state variable from dev_pm_info tracks the data struct
- * allocation state:
- * DEV_PM_QOS_NO_DEVICE: No device present or device removed, no data
- * allocated,
- * DEV_PM_QOS_DEVICE_PRESENT: Device present, data not allocated and will be
- * allocated at the first call to dev_pm_qos_add_request,
- * DEV_PM_QOS_ALLOCATED: Device present, data allocated. The per-device
- * PM QoS constraints framework is operational and constraints can be
- * added, updated or removed using the dev_pm_qos_* API.
* . A global mutex protects the constraints users from the data being
* allocated and free'd.
*/
@@ -51,8 +42,30 @@
static DEFINE_MUTEX(dev_pm_qos_mtx);
+
static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
+/**
+ * dev_pm_qos_read_value - Get PM QoS constraint for a given device.
+ * @dev: Device to get the PM QoS constraint value for.
+ */
+s32 dev_pm_qos_read_value(struct device *dev)
+{
+ struct pm_qos_constraints *c;
+ unsigned long flags;
+ s32 ret = 0;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+
+ c = dev->power.constraints;
+ if (c)
+ ret = pm_qos_read_value(c);
+
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+
+ return ret;
+}
+
/*
* apply_constraint
* @req: constraint request to apply
@@ -105,27 +118,37 @@ static int dev_pm_qos_constraints_alloca
}
BLOCKING_INIT_NOTIFIER_HEAD(n);
+ plist_head_init(&c->list);
+ c->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+ c->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
+ c->type = PM_QOS_MIN;
+ c->notifiers = n;
+
+ spin_lock_irq(&dev->power.lock);
dev->power.constraints = c;
- plist_head_init(&dev->power.constraints->list);
- dev->power.constraints->target_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
- dev->power.constraints->default_value = PM_QOS_DEV_LAT_DEFAULT_VALUE;
- dev->power.constraints->type = PM_QOS_MIN;
- dev->power.constraints->notifiers = n;
- dev->power.constraints_state = DEV_PM_QOS_ALLOCATED;
+ spin_unlock_irq(&dev->power.lock);
return 0;
}
+static void __dev_pm_qos_constraints_init(struct device *dev)
+{
+ spin_lock_irq(&dev->power.lock);
+ dev->power.constraints = NULL;
+ spin_unlock_irq(&dev->power.lock);
+}
+
/**
- * dev_pm_qos_constraints_init
+ * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer.
* @dev: target device
*
- * Called from the device PM subsystem at device insertion
+ * Called from the device PM subsystem at device insertion under
+ * device_pm_lock().
*/
void dev_pm_qos_constraints_init(struct device *dev)
{
mutex_lock(&dev_pm_qos_mtx);
- dev->power.constraints_state = DEV_PM_QOS_DEVICE_PRESENT;
+ dev->power.constraints = NULL;
mutex_unlock(&dev_pm_qos_mtx);
}
@@ -133,34 +156,35 @@ void dev_pm_qos_constraints_init(struct
* dev_pm_qos_constraints_destroy
* @dev: target device
*
- * Called from the device PM subsystem at device removal
+ * Called from the device PM subsystem at device removal under device_pm_lock().
*/
void dev_pm_qos_constraints_destroy(struct device *dev)
{
struct dev_pm_qos_request *req, *tmp;
+ struct pm_qos_constraints *c;
mutex_lock(&dev_pm_qos_mtx);
- if (dev->power.constraints_state = DEV_PM_QOS_ALLOCATED) {
- /* Flush the constraints list for the device */
- plist_for_each_entry_safe(req, tmp,
- &dev->power.constraints->list,
- node) {
- /*
- * Update constraints list and call the notification
- * callbacks if needed
- */
- apply_constraint(req, PM_QOS_REMOVE_REQ,
- PM_QOS_DEFAULT_VALUE);
- memset(req, 0, sizeof(*req));
- }
+ c = dev->power.constraints;
+ if (!c)
+ goto out;
- kfree(dev->power.constraints->notifiers);
- kfree(dev->power.constraints);
- dev->power.constraints = NULL;
+ /* Flush the constraints list for the device */
+ plist_for_each_entry_safe(req, tmp, &c->list, node) {
+ /*
+ * Update constraints list and call the notification
+ * callbacks if needed
+ */
+ apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
+ memset(req, 0, sizeof(*req));
}
- dev->power.constraints_state = DEV_PM_QOS_NO_DEVICE;
+ __dev_pm_qos_constraints_init(dev);
+
+ kfree(c->notifiers);
+ kfree(c);
+
+ out:
mutex_unlock(&dev_pm_qos_mtx);
}
@@ -178,8 +202,9 @@ void dev_pm_qos_constraints_destroy(stru
*
* Returns 1 if the aggregated constraint value has changed,
* 0 if the aggregated constraint value has not changed,
- * -EINVAL in case of wrong parameters, -ENODEV if the device has been
- * removed from the system
+ * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
+ * to allocate for data structures, -ENODEV if the device has just been removed
+ * from the system.
*/
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
s32 value)
@@ -195,28 +220,37 @@ int dev_pm_qos_add_request(struct device
return -EINVAL;
}
- mutex_lock(&dev_pm_qos_mtx);
req->dev = dev;
- /* Return if the device has been removed */
- if (req->dev->power.constraints_state = DEV_PM_QOS_NO_DEVICE) {
- ret = -ENODEV;
- goto out;
- }
+ device_pm_lock();
+ mutex_lock(&dev_pm_qos_mtx);
- /*
- * Allocate the constraints data on the first call to add_request,
- * i.e. only if the data is not already allocated and if the device has
- * not been removed
- */
- if (dev->power.constraints_state = DEV_PM_QOS_DEVICE_PRESENT)
- ret = dev_pm_qos_constraints_allocate(dev);
+ if (dev->power.constraints) {
+ device_pm_unlock();
+ } else {
+ if (list_empty(&dev->power.entry)) {
+ /* The device has been removed from the system. */
+ device_pm_unlock();
+ req->dev = NULL;
+ ret = -ENODEV;
+ goto out;
+ } else {
+ device_pm_unlock();
+ /*
+ * Allocate the constraints data on the first call to
+ * add_request, i.e. only if the data is not already
+ * allocated and if the device has not been removed.
+ */
+ ret = dev_pm_qos_constraints_allocate(dev);
+ }
+ }
if (!ret)
ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
-out:
+ out:
mutex_unlock(&dev_pm_qos_mtx);
+
return ret;
}
EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
@@ -252,13 +286,13 @@ int dev_pm_qos_update_request(struct dev
mutex_lock(&dev_pm_qos_mtx);
- if (req->dev->power.constraints_state = DEV_PM_QOS_ALLOCATED) {
+ if (req->dev->power.constraints) {
if (new_value != req->node.prio)
ret = apply_constraint(req, PM_QOS_UPDATE_REQ,
new_value);
} else {
/* Return if the device has been removed */
- ret = -ENODEV;
+ ret = -EINVAL;
}
mutex_unlock(&dev_pm_qos_mtx);
@@ -293,7 +327,7 @@ int dev_pm_qos_remove_request(struct dev
mutex_lock(&dev_pm_qos_mtx);
- if (req->dev->power.constraints_state = DEV_PM_QOS_ALLOCATED) {
+ if (req->dev->power.constraints) {
ret = apply_constraint(req, PM_QOS_REMOVE_REQ,
PM_QOS_DEFAULT_VALUE);
memset(req, 0, sizeof(*req));
@@ -323,15 +357,12 @@ int dev_pm_qos_add_notifier(struct devic
mutex_lock(&dev_pm_qos_mtx);
- /* Silently return if the device has been removed */
- if (dev->power.constraints_state != DEV_PM_QOS_ALLOCATED)
- goto out;
-
- retval = blocking_notifier_chain_register(
- dev->power.constraints->notifiers,
- notifier);
+ /* Silently return if the constraints object is not present. */
+ if (dev->power.constraints)
+ retval = blocking_notifier_chain_register(
+ dev->power.constraints->notifiers,
+ notifier);
-out:
mutex_unlock(&dev_pm_qos_mtx);
return retval;
}
@@ -354,15 +385,12 @@ int dev_pm_qos_remove_notifier(struct de
mutex_lock(&dev_pm_qos_mtx);
- /* Silently return if the device has been removed */
- if (dev->power.constraints_state != DEV_PM_QOS_ALLOCATED)
- goto out;
-
- retval = blocking_notifier_chain_unregister(
- dev->power.constraints->notifiers,
- notifier);
+ /* Silently return if the constraints object is not present. */
+ if (dev->power.constraints)
+ retval = blocking_notifier_chain_unregister(
+ dev->power.constraints->notifiers,
+ notifier);
-out:
mutex_unlock(&dev_pm_qos_mtx);
return retval;
}
Index: linux/include/linux/pm_qos.h
=================================--- linux.orig/include/linux/pm_qos.h
+++ linux/include/linux/pm_qos.h
@@ -77,6 +77,7 @@ int pm_qos_remove_notifier(int pm_qos_cl
int pm_qos_request_active(struct pm_qos_request *req);
s32 pm_qos_read_value(struct pm_qos_constraints *c);
+s32 dev_pm_qos_read_value(struct device *dev);
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
s32 value);
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
@@ -117,6 +118,8 @@ static inline int pm_qos_request_active(
static inline s32 pm_qos_read_value(struct pm_qos_constraints *c)
{ return 0; }
+static inline s32 dev_pm_qos_read_value(struct device *dev)
+ { return 0; }
static inline int dev_pm_qos_add_request(struct device *dev,
struct dev_pm_qos_request *req,
s32 value)
Index: linux/drivers/base/power/main.c
=================================--- linux.orig/drivers/base/power/main.c
+++ linux/drivers/base/power/main.c
@@ -98,8 +98,8 @@ void device_pm_add(struct device *dev)
dev_warn(dev, "parent %s should not be sleeping\n",
dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list);
- mutex_unlock(&dpm_list_mtx);
dev_pm_qos_constraints_init(dev);
+ mutex_unlock(&dpm_list_mtx);
}
/**
@@ -110,9 +110,9 @@ void device_pm_remove(struct device *dev
{
pr_debug("PM: Removing info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
- dev_pm_qos_constraints_destroy(dev);
complete_all(&dev->power.completion);
mutex_lock(&dpm_list_mtx);
+ dev_pm_qos_constraints_destroy(dev);
list_del_init(&dev->power.entry);
mutex_unlock(&dpm_list_mtx);
device_wakeup_disable(dev);
Index: linux/include/linux/pm.h
=================================--- linux.orig/include/linux/pm.h
+++ linux/include/linux/pm.h
@@ -421,13 +421,6 @@ enum rpm_request {
RPM_REQ_RESUME,
};
-/* Per-device PM QoS constraints data struct state */
-enum dev_pm_qos_state {
- DEV_PM_QOS_NO_DEVICE, /* No device present */
- DEV_PM_QOS_DEVICE_PRESENT, /* Device present, data not allocated */
- DEV_PM_QOS_ALLOCATED, /* Device present, data allocated */
-};
-
struct wakeup_source;
struct pm_domain_data {
@@ -489,7 +482,6 @@ struct dev_pm_info {
#endif
struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */
struct pm_qos_constraints *constraints;
- enum dev_pm_qos_state constraints_state;
};
extern void update_pm_runtime_accounting(struct device *dev);
^ permalink raw reply
* 最新广交会买家库+500万海外买家资源+
From: 每天都有新买家 @ 2011-09-03 7:51 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <20110930043901506744@altoria.com.ua>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 13420 bytes --]
500���������������������������������������������������������������+������������������������������������������������������+������������������������������������Email���������������������������=���������������������������������������������������������������������������������
500���������������������������������������������������������������+������������������������������������������������������+������������������������������������Email���������������������������=���������������������������������������������������������������������������������
1���������500������������������������������������������������������ ���������������������������500��������������������������������������������������������������������������������� (������������������������������������������������������������������������������������������������������������������������������������������������������������������)���������
2���������������������������������������������������������������Email������������������������������������ ���������������������������600������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������1-2���������������������������������������������������������������EMAIL������������������������������������������������������
3������������������������������������������������������ ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������5���������������������������������������������
��������������������������������������������������������������������������������� (���������������������������������������������������������������������������������������������������������������������������������������������������������) ������������������������������������������������������ ���������������������������
������������������������������������
QQ:1339625218 email: 1339625218@qq.com
QQ:1339625218 email: 1339625218@qq.com
QQ:1339625218 email: 1339625218@qq.com
QQ:1339625218 email: 1339625218@qq.com
QQ:1339625218 email: 1339625218@qq.com
QQ:1339625218 email: 1339625218@qq.com
������������������������������������:
1������������������������������������������������������������������������������������������,��������������������������������������������������������������� 500-1000���������������������������Email������������������������������������������������������������������������������������������������������������
2���������2009���������������������������������������������������������������piers��������������������������� 1���������������������������
3���������2011������������������109���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
4���������2008������������������2010��������� ������������������+������������������������������������������������������������������������������������������103 104 105 106 107 108 ���������������������������������������������120.6������������������������������������
5������������������������������������������������������������������������,���������451660������������������������������������������������������������������������Email���������
6���������2010������������������������������������������������������������������������PPAI��������������������������������������������� PPAI Members Directory������������������������������������������������������������������������������������������
7���������2010���������������������������������������������������������������������������������������������������������������������(���������������������������������������������������������������)������������������7.2������������������������������������������������������������������������������������������������������������
8���������100���������������������������������������������������������������������������������������������������������������������Email���������
9���������������������������������������������������������������������������������������������������
���������������������������������������������
������������{.n���+���������������������+%���������������������\x17������w������{.n���+������������{���������������{ay���\x1d���������������,j\a������f���������h���������������������������z_������\x03(���������������������j"������\x1a���^[m������������\a������G������������������?���������������&���������~������
^ permalink raw reply
* Re: [PATCH 3/5] PM / QoS: Add function dev_pm_qos_read_value()
From: Rafael J. Wysocki @ 2011-09-02 23:55 UTC (permalink / raw)
To: Jean Pihet
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <CAORVsuVAzc8Q2tG0-WW+96Ad9GhR5OCq2bAuweggs1rimFMcqg@mail.gmail.com>
On Friday, September 02, 2011, Jean Pihet wrote:
> On Fri, Sep 2, 2011 at 12:07 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > Hi,
> >
> > On Thursday, September 01, 2011, Jean Pihet wrote:
> >> Hi Rafael,
> >>
> >> On Wed, Aug 31, 2011 at 12:21 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> >> > From: Rafael J. Wysocki <rjw@sisk.pl>
> >> >
> >> > To read the current PM QoS value for a given device we need to
> >> > make sure that the device's power.constraints object won't be
> >> > removed while we're doing that. For this reason, put the
> >> > operation under dev->power.lock and acquire the lock
> >> > around the initialization and removal of power.constraints.
> >> Ok.
> >>
> >> > Moreover, since we're using the value of power.constraints to
> >> > determine whether or not the object is present, the
> >> > power.constraints_state field isn't necessary any more and may be
> >> > removed. However, dev_pm_qos_add_request() needs to check if the
> >> > device is being removed from the system before allocating a new
> >> > PM QoS constraints object for it, so it has to use device_pm_lock()
> >> > and the device PM QoS initialization and destruction should be done
> >> > under device_pm_lock() as well.
> >> Ok that makes sense.
> >> The constraints_state field can be replaced by a combination of
> >> dev->power.constraints and list_empty(&dev->power.entry), which makes
> >> the code more compact and less redundant.
> >>
> >> >
> >> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> >> > ---
> >> > drivers/base/power/main.c | 4 -
> >> > drivers/base/power/qos.c | 167 ++++++++++++++++++++++++++--------------------
> >> > include/linux/pm.h | 8 --
> >> > include/linux/pm_qos.h | 3
> >> > 4 files changed, 101 insertions(+), 81 deletions(-)
> >> >
> >> > Index: linux/drivers/base/power/qos.c
> >> > =================================> >> > --- linux.orig/drivers/base/power/qos.c
> >> > +++ linux/drivers/base/power/qos.c
> >> > @@ -30,15 +30,6 @@
> >> ...
> >>
> >> >
> >> > @@ -178,8 +202,8 @@ void dev_pm_qos_constraints_destroy(stru
> >> > *
> >> > * Returns 1 if the aggregated constraint value has changed,
> >> > * 0 if the aggregated constraint value has not changed,
> >> > - * -EINVAL in case of wrong parameters, -ENODEV if the device has been
> >> > - * removed from the system
> >> > + * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
> >> > + * to allocate for data structures.
> >> Why not use -ENODEV in case there is no device?
> >
> > I don't think it's useful for the caller. If the device is gone, the
> > constraing simply doesn't matter, so there's no error to handle.
> >
> >> > */
> >> > int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
> >> > s32 value)
> >> > @@ -195,28 +219,35 @@ int dev_pm_qos_add_request(struct device
> >> > return -EINVAL;
> >> > }
> >> >
> >> > - mutex_lock(&dev_pm_qos_mtx);
> >> > req->dev = dev;
> >> >
> >> > - /* Return if the device has been removed */
> >> > - if (req->dev->power.constraints_state = DEV_PM_QOS_NO_DEVICE) {
> >> > - ret = -ENODEV;
> >> > - goto out;
> >> > - }
> >> > + device_pm_lock();
> >> > + mutex_lock(&dev_pm_qos_mtx);
> >> >
> >> > - /*
> >> > - * Allocate the constraints data on the first call to add_request,
> >> > - * i.e. only if the data is not already allocated and if the device has
> >> > - * not been removed
> >> > - */
> >> > - if (dev->power.constraints_state = DEV_PM_QOS_DEVICE_PRESENT)
> >> > - ret = dev_pm_qos_constraints_allocate(dev);
> >> > + if (dev->power.constraints) {
> >> > + device_pm_unlock();
> >> > + } else {
> >> > + if (list_empty(&dev->power.entry)) {
> >> > + /* The device has been removed from the system. */
> >> > + device_pm_unlock();
> >> > + goto out;
> >> 0 is silently returned in case the device has been removed. Is that
> >> the intention?
> >
> > Pretty much it is. Is that a problem?
> I think the caller needs to know if the constraint has been applied
> correctly or not.
However, the removal of the device is a special case. What would the caller
be supposed to do when it learned that the device had been removed while it had
been trying to add a QoS constraing for it? Not much I guess.
Thanks,
Rafael
^ permalink raw reply
* [PATCH 2/2] sh: use DMA with MSIOF SPI on the sh7724 ecovec board
From: Guennadi Liakhovetski @ 2011-09-02 15:13 UTC (permalink / raw)
To: spi-devel-general; +Cc: linux-sh, Grant Likely
In-Reply-To: <Pine.LNX.4.64.1109021706480.4731@axis700.grange>
On ecovec MSIOF0 is connected to an SD/MMC slot, this patch adds DMA
support on it.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/sh/boards/mach-ecovec24/setup.c | 8 +++++++-
arch/sh/include/cpu-sh4/cpu/sh7724.h | 4 ++++
arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 20 ++++++++++++++++++++
3 files changed, 31 insertions(+), 1 deletions(-)
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 22faf2a..16747a8 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
@@ -653,6 +654,8 @@ static struct spi_board_info spi_bus[] = {
/* MSIOF0 */
static struct sh_msiof_spi_info msiof0_data = {
.num_chipselect = 1,
+ .slave_id_tx = SHDMA_SLAVE_MSIOF0_TX,
+ .slave_id_rx = SHDMA_SLAVE_MSIOF0_RX,
};
static struct resource msiof0_resources[] = {
@@ -668,11 +671,14 @@ static struct resource msiof0_resources[] = {
},
};
+u64 msiof0_dmamask = DMA_BIT_MASK(32);
+
static struct platform_device msiof0_device = {
.name = "spi_sh_msiof",
.id = 0, /* MSIOF0 */
.dev = {
- .platform_data = &msiof0_data,
+ .platform_data = &msiof0_data,
+ .dma_mask = &msiof0_dmamask,
},
.num_resources = ARRAY_SIZE(msiof0_resources),
.resource = msiof0_resources,
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h
index cbc47e6..10f9292 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7724.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h
@@ -310,6 +310,10 @@ enum {
SHDMA_SLAVE_SDHI0_RX,
SHDMA_SLAVE_SDHI1_TX,
SHDMA_SLAVE_SDHI1_RX,
+ SHDMA_SLAVE_MSIOF0_TX,
+ SHDMA_SLAVE_MSIOF0_RX,
+ SHDMA_SLAVE_MSIOF1_TX,
+ SHDMA_SLAVE_MSIOF1_RX,
};
extern struct clk sh7724_fsimcka_clk;
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index a37dd72..d6626fe 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -152,6 +152,26 @@ static const struct sh_dmae_slave_config sh7724_dmae_slaves[] = {
.addr = 0x04cf0030,
.chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xca,
+ }, {
+ .slave_id = SHDMA_SLAVE_MSIOF0_TX,
+ .addr = 0xa4c40050,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x51,
+ }, {
+ .slave_id = SHDMA_SLAVE_MSIOF0_RX,
+ .addr = 0xa4c40060,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x52,
+ }, {
+ .slave_id = SHDMA_SLAVE_MSIOF1_TX,
+ .addr = 0xa4c50050,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x55,
+ }, {
+ .slave_id = SHDMA_SLAVE_MSIOF1_RX,
+ .addr = 0xa4c50060,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x56,
},
};
--
1.7.2.5
^ permalink raw reply related
* [PATCH 1/2] SPI: spi_sh_msiof: implement DMA support
From: Guennadi Liakhovetski @ 2011-09-02 15:13 UTC (permalink / raw)
To: spi-devel-general; +Cc: linux-sh, Grant Likely
In-Reply-To: <Pine.LNX.4.64.1109021706480.4731@axis700.grange>
Use the sh_dma dmaengine driver to support DMA on MSIOF.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/spi/spi-sh-msiof.c | 393 ++++++++++++++++++++++++++++++++++++++---
include/linux/spi/sh_msiof.h | 2 +
2 files changed, 366 insertions(+), 29 deletions(-)
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index e00d94b..8622b32 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -13,14 +13,18 @@
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/sh_dma.h>
#include <linux/spi/sh_msiof.h>
#include <linux/spi/spi.h>
@@ -28,6 +32,13 @@
#include <asm/unaligned.h>
+struct sh_msiof_dma {
+ struct sh_dmae_slave dma_slave;
+ struct dma_chan *chan;
+ struct sg_table sg;
+ struct dma_async_tx_descriptor *desc;
+};
+
struct sh_msiof_spi_priv {
struct spi_bitbang bitbang; /* must be first for spi_bitbang.c */
void __iomem *mapbase;
@@ -38,6 +49,10 @@ struct sh_msiof_spi_priv {
unsigned long flags;
int tx_fifo_size;
int rx_fifo_size;
+ struct sh_msiof_dma dma_tx;
+ struct sh_msiof_dma dma_rx;
+ struct completion dma_done;
+ struct page *dummypage;
};
#define TMDR1 0x00
@@ -64,8 +79,12 @@ struct sh_msiof_spi_priv {
#define CTR_TXE (1 << 9)
#define CTR_RXE (1 << 8)
-#define STR_TEOF (1 << 23)
-#define STR_REOF (1 << 7)
+#define IER_TDMA (1 << 31)
+#define IER_TDREQ (1 << 28)
+#define IER_TEOF (1 << 23)
+#define IER_RDMA (1 << 15)
+#define IER_RDREQ (1 << 12)
+#define IER_REOF (1 << 7)
static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
{
@@ -208,8 +227,6 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
if (rx_buf)
sh_msiof_write(p, RMDR2, dr2);
-
- sh_msiof_write(p, IER, STR_TEOF | STR_REOF);
}
static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
@@ -401,9 +418,9 @@ static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
/* chip select is active low unless SPI_CS_HIGH is set */
if (spi->mode & SPI_CS_HIGH)
- value = (is_on = BITBANG_CS_ACTIVE) ? 1 : 0;
+ value = is_on = BITBANG_CS_ACTIVE;
else
- value = (is_on = BITBANG_CS_ACTIVE) ? 0 : 1;
+ value = is_on != BITBANG_CS_ACTIVE;
if (is_on = BITBANG_CS_ACTIVE) {
if (!test_and_set_bit(0, &p->flags)) {
@@ -429,6 +446,36 @@ static void sh_msiof_spi_chipselect(struct spi_device *spi, int is_on)
}
}
+static int sh_msiof_spi_start(struct sh_msiof_spi_priv *p, void *rx_buf)
+{
+ /* setup clock and rx/tx signals */
+ int ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE);
+ if (rx_buf && !ret)
+ ret = sh_msiof_modify_ctr_wait(p, 0, CTR_RXE);
+ if (!ret)
+ ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TXE);
+
+ /* start by setting frame bit */
+ if (!ret)
+ ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE);
+
+ return ret;
+}
+
+static int sh_msiof_spi_stop(struct sh_msiof_spi_priv *p, void *rx_buf)
+{
+ /* shut down frame, tx/tx and clock signals */
+ int ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
+ if (!ret)
+ ret = sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
+ if (rx_buf && !ret)
+ ret = sh_msiof_modify_ctr_wait(p, CTR_RXE, 0);
+ if (!ret)
+ ret = sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0);
+
+ return ret;
+}
+
static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
void (*tx_fifo)(struct sh_msiof_spi_priv *,
const void *, int, int),
@@ -456,16 +503,11 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
if (tx_buf)
tx_fifo(p, tx_buf, words, fifo_shift);
- /* setup clock and rx/tx signals */
- ret = sh_msiof_modify_ctr_wait(p, 0, CTR_TSCKE);
- if (rx_buf)
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_RXE);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TXE);
-
- /* start by setting frame bit */
INIT_COMPLETION(p->done);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, 0, CTR_TFSE);
- if (ret) {
+ sh_msiof_write(p, IER, IER_TEOF | IER_REOF);
+
+ ret = sh_msiof_spi_start(p, rx_buf);
+ if (ret < 0) {
dev_err(&p->pdev->dev, "failed to start hardware\n");
goto err;
}
@@ -480,13 +522,8 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
/* clear status bits */
sh_msiof_reset_str(p);
- /* shut down frame, tx/tx and clock signals */
- ret = sh_msiof_modify_ctr_wait(p, CTR_TFSE, 0);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TXE, 0);
- if (rx_buf)
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_RXE, 0);
- ret = ret ? ret : sh_msiof_modify_ctr_wait(p, CTR_TSCKE, 0);
- if (ret) {
+ ret = sh_msiof_spi_stop(p, rx_buf);
+ if (ret < 0) {
dev_err(&p->pdev->dev, "failed to shut down hardware\n");
goto err;
}
@@ -498,6 +535,220 @@ static int sh_msiof_spi_txrx_once(struct sh_msiof_spi_priv *p,
return ret;
}
+static void sh_msiof_setup_sg(struct sh_msiof_spi_priv *p,
+ const void *buffer,
+ unsigned int length,
+ struct sg_table *sgtab)
+{
+ struct scatterlist *sg;
+ int bytesleft = length;
+ const void *bufp = buffer;
+ int mapbytes;
+ int i;
+
+ if (buffer) {
+ for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+ /*
+ * If there are fewer bytes left than what fits
+ * in the current page (plus page alignment offset)
+ * we just feed in this, else we stuff in as much
+ * as we can.
+ */
+ if (bytesleft < (PAGE_SIZE - offset_in_page(bufp)))
+ mapbytes = bytesleft;
+ else
+ mapbytes = PAGE_SIZE - offset_in_page(bufp);
+ sg_set_page(sg, virt_to_page(bufp),
+ mapbytes, offset_in_page(bufp));
+ bytesleft -= mapbytes;
+ bufp += mapbytes;
+ }
+ } else {
+ /* Map the dummy buffer on every page */
+ for_each_sg(sgtab->sgl, sg, sgtab->nents, i) {
+ if (bytesleft < PAGE_SIZE)
+ mapbytes = bytesleft;
+ else
+ mapbytes = PAGE_SIZE;
+ sg_set_page(sg, p->dummypage, mapbytes, 0);
+ bytesleft -= mapbytes;
+ }
+ }
+ BUG_ON(bytesleft);
+}
+
+static int sh_msiof_spi_setup_xfer_dma(struct sh_msiof_spi_priv *p, struct sh_msiof_dma *dma,
+ const void *buffer, size_t len, enum dma_data_direction dir)
+{
+ int ret, sglen;
+ unsigned int pages;
+ unsigned long flags = DMA_CTRL_ACK;
+
+ /* Create sglists for the transfers */
+ pages = (PAGE_ALIGN(len) >> PAGE_SHIFT);
+
+ ret = sg_alloc_table(&dma->sg, pages, GFP_KERNEL);
+ if (ret < 0)
+ return ret;
+
+ sh_msiof_setup_sg(p, buffer, len, &dma->sg);
+
+ /* Map DMA buffers */
+ sglen = dma_map_sg(&p->pdev->dev, dma->sg.sgl,
+ dma->sg.orig_nents, dir);
+ if (sglen < 0) {
+ ret = sglen;
+ goto emapsg;
+ } else if (!sglen) {
+ ret = -EINVAL;
+ goto emapsg;
+ }
+
+ if (dir = DMA_FROM_DEVICE)
+ flags |= DMA_PREP_INTERRUPT;
+
+ dma->desc = dma->chan->device->device_prep_slave_sg(dma->chan,
+ dma->sg.sgl, sglen, dir, flags);
+ if (!dma->desc) {
+ ret = -ENOMEM;
+ goto edmaprep;
+ }
+
+ dma->sg.nents = sglen;
+
+ return 0;
+
+edmaprep:
+ dma_unmap_sg(&p->pdev->dev, dma->sg.sgl, sglen, dir);
+emapsg:
+ sg_free_table(&dma->sg);
+
+ return ret;
+}
+
+static void sh_msiof_spi_free_xfer_dma(struct sh_msiof_spi_priv *p, struct sh_msiof_dma *dma,
+ enum dma_data_direction dir)
+{
+ dma_unmap_sg(&p->pdev->dev, dma->sg.sgl, dma->sg.nents, dir);
+ sg_free_table(&dma->sg);
+}
+
+static void sh_msiof_spi_dma_callback(void *arg)
+{
+ struct sh_msiof_spi_priv *p = arg;
+
+ dma_sync_sg_for_device(&p->pdev->dev, p->dma_rx.sg.sgl,
+ p->dma_rx.sg.nents, DMA_FROM_DEVICE);
+
+ sh_msiof_spi_free_xfer_dma(p, &p->dma_rx, DMA_FROM_DEVICE);
+ sh_msiof_spi_free_xfer_dma(p, &p->dma_tx, DMA_TO_DEVICE);
+
+ complete(&p->dma_done);
+}
+
+static int sh_msiof_spi_txrx_dma_single(struct sh_msiof_spi_priv *p, int bits,
+ const void *tx_buf, const void *rx_buf, size_t len)
+{
+ int ret, cookie, words;
+
+ if (bits <= 8)
+ words = len;
+ else if (bits <= 16)
+ words = len >> 1;
+ else
+ words = len >> 2;
+
+ ret = sh_msiof_spi_setup_xfer_dma(p, &p->dma_tx, tx_buf, len, DMA_TO_DEVICE);
+ if (ret < 0)
+ return ret;
+
+ dma_sync_sg_for_device(&p->pdev->dev, p->dma_tx.sg.sgl,
+ p->dma_tx.sg.nents, DMA_TO_DEVICE);
+
+ ret = sh_msiof_spi_setup_xfer_dma(p, &p->dma_rx, rx_buf, len, DMA_FROM_DEVICE);
+ if (ret < 0)
+ goto esdmarx;
+
+ /* Put the callback on the RX transfer only, that should finish last */
+ p->dma_rx.desc->callback = sh_msiof_spi_dma_callback;
+ p->dma_rx.desc->callback_param = p;
+
+ /* Submit and fire RX and TX with TX last so we're ready to read! */
+ cookie = p->dma_rx.desc->tx_submit(p->dma_rx.desc);
+ if (dma_submit_error(cookie)) {
+ ret = cookie;
+ goto esubmitrx;
+ }
+ p->dma_rx.chan->device->device_issue_pending(p->dma_rx.chan);
+
+ /* setup msiof transfer mode registers */
+ sh_msiof_spi_set_mode_regs(p, tx_buf, p->dummypage, bits, words);
+
+ cookie = p->dma_tx.desc->tx_submit(p->dma_tx.desc);
+ if (dma_submit_error(cookie)) {
+ ret = cookie;
+ goto esubmittx;
+ }
+ p->dma_tx.chan->device->device_issue_pending(p->dma_tx.chan);
+
+ INIT_COMPLETION(p->dma_done);
+ sh_msiof_write(p, IER, IER_RDREQ | IER_TDREQ | IER_RDMA | IER_TDMA);
+
+ /* As long as there's something to send, we'll also be receiving. */
+ ret = sh_msiof_spi_start(p, p->dummypage);
+ if (ret < 0) {
+ dev_err(&p->pdev->dev, "failed to start hardware: %d\n", ret);
+ goto espistart;
+ }
+
+ wait_for_completion(&p->dma_done);
+
+ /* clear status bits */
+ sh_msiof_reset_str(p);
+
+ ret = sh_msiof_spi_stop(p, p->dummypage);
+ if (ret < 0) {
+ dev_err(&p->pdev->dev, "failed to stop hardware: %d\n", ret);
+ goto espistop;
+ }
+
+ return len;
+
+espistop:
+espistart:
+ dmaengine_device_control(p->dma_tx.chan, DMA_TERMINATE_ALL, 0);
+esubmittx:
+ dmaengine_device_control(p->dma_rx.chan, DMA_TERMINATE_ALL, 0);
+esubmitrx:
+ sh_msiof_spi_free_xfer_dma(p, &p->dma_rx, DMA_FROM_DEVICE);
+esdmarx:
+ sh_msiof_spi_free_xfer_dma(p, &p->dma_tx, DMA_TO_DEVICE);
+
+ return ret;
+}
+
+static int sh_msiof_spi_txrx_dma(struct sh_msiof_spi_priv *p, struct spi_transfer *t, int bits)
+{
+ int i, ret = 0;
+ size_t left = t->len;
+ off_t offs = 0;
+
+ /* Up to 256 words per group, we only use a single group */
+ for (i = 0; i < (t->len + 255) / 256; i++) {
+ const void *rx_buf = t->rx_buf ? t->rx_buf + offs : NULL;
+ const void *tx_buf = t->tx_buf ? t->tx_buf + offs : NULL;
+
+ ret = sh_msiof_spi_txrx_dma_single(p, bits, tx_buf, rx_buf,
+ min_t(size_t, left, 256));
+ if (ret < 0)
+ return ret;
+ left -= ret;
+ offs += ret;
+ }
+
+ return ret <= 0 ? ret : t->len;
+}
+
static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
{
struct sh_msiof_spi_priv *p = spi_master_get_devdata(spi->master);
@@ -512,6 +763,19 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
bits = sh_msiof_spi_bits(spi, t);
+ /* setup clocks (clock already enabled in chipselect()) */
+ sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk),
+ sh_msiof_spi_hz(spi, t));
+
+ if (p->dma_rx.chan && p->dma_tx.chan && t->len > 15 &&
+ !(t->len & 3) && !((int)t->rx_buf & 3) && !((int)t->tx_buf & 3)) {
+ int ret = sh_msiof_spi_txrx_dma(p, t, bits);
+ if (ret < 0)
+ dev_warn(&spi->dev, "fall back to PIO: %d\n", ret);
+ else
+ return ret;
+ }
+
if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
bits = 32;
swab = true;
@@ -559,10 +823,6 @@ static int sh_msiof_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
rx_fifo = sh_msiof_spi_read_fifo_32;
}
- /* setup clocks (clock already enabled in chipselect()) */
- sh_msiof_spi_set_clk_regs(p, clk_get_rate(p->clk),
- sh_msiof_spi_hz(spi, t));
-
/* transfer in fifo sized chunks */
words = t->len / bytes_per_word;
bytes_done = 0;
@@ -591,6 +851,78 @@ static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
return 0;
}
+static bool sh_msiof_filter(struct dma_chan *chan, void *arg)
+{
+ dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
+ chan->private = arg;
+ return true;
+}
+
+static void sh_msiof_request_dma(struct sh_msiof_spi_priv *p)
+{
+ struct sh_dmae_slave *tx = &p->dma_tx.dma_slave,
+ *rx = &p->dma_rx.dma_slave;
+ dma_cap_mask_t mask;
+
+ tx->slave_id = p->info->slave_id_tx;
+ rx->slave_id = p->info->slave_id_rx;
+
+ /* We can only either use DMA for both Tx and Rx or not use it at all */
+ if (tx->slave_id <= 0 || rx->slave_id <= 0)
+ return;
+
+ dev_warn(&p->pdev->dev, "Experimental DMA support enabled.\n");
+
+ p->dummypage = alloc_page(GFP_KERNEL);
+ if (!p->dummypage)
+ return;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ p->dma_tx.chan = dma_request_channel(mask, sh_msiof_filter, tx);
+ dev_dbg(&p->pdev->dev, "%s: TX: got channel %p\n", __func__,
+ p->dma_tx.chan);
+
+ if (!p->dma_tx.chan)
+ goto echantx;
+
+ p->dma_rx.chan = dma_request_channel(mask, sh_msiof_filter, rx);
+ dev_dbg(&p->pdev->dev, "%s: RX: got channel %p\n", __func__,
+ p->dma_rx.chan);
+
+ if (!p->dma_rx.chan)
+ goto echanrx;
+
+ init_completion(&p->dma_done);
+
+ return;
+
+echanrx:
+ dma_release_channel(p->dma_tx.chan);
+ p->dma_tx.chan = NULL;
+echantx:
+ __free_pages(p->dummypage, 0);
+}
+
+static void sh_msiof_release_dma(struct sh_msiof_spi_priv *p)
+{
+ /* Descriptors are freed automatically */
+ if (p->dma_tx.chan) {
+ struct dma_chan *chan = p->dma_tx.chan;
+ p->dma_tx.chan = NULL;
+ dma_release_channel(chan);
+ }
+ if (p->dma_rx.chan) {
+ struct dma_chan *chan = p->dma_rx.chan;
+ p->dma_rx.chan = NULL;
+ dma_release_channel(chan);
+ }
+
+ if (p->dummypage)
+ __free_pages(p->dummypage, 0);
+}
+
static int sh_msiof_spi_probe(struct platform_device *pdev)
{
struct resource *r;
@@ -645,6 +977,8 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p->pdev = pdev;
pm_runtime_enable(&pdev->dev);
+ sh_msiof_request_dma(p);
+
/* The standard version of MSIOF use 64 word FIFOs */
p->tx_fifo_size = 64;
p->rx_fifo_size = 64;
@@ -656,8 +990,8 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p->rx_fifo_size = p->info->rx_fifo_override;
/* init master and bitbang code */
- master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
- master->mode_bits |= SPI_LSB_FIRST | SPI_3WIRE;
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH |
+ SPI_LSB_FIRST | SPI_3WIRE;
master->flags = 0;
master->bus_num = pdev->id;
master->num_chipselect = p->info->num_chipselect;
@@ -677,6 +1011,7 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
if (ret = 0)
return 0;
+ sh_msiof_release_dma(p);
pm_runtime_disable(&pdev->dev);
err3:
iounmap(p->mapbase);
@@ -695,11 +1030,11 @@ static int sh_msiof_spi_remove(struct platform_device *pdev)
ret = spi_bitbang_stop(&p->bitbang);
if (!ret) {
+ sh_msiof_release_dma(p);
pm_runtime_disable(&pdev->dev);
free_irq(platform_get_irq(pdev, 0), p);
iounmap(p->mapbase);
clk_put(p->clk);
- spi_master_put(p->bitbang.master);
}
return ret;
}
diff --git a/include/linux/spi/sh_msiof.h b/include/linux/spi/sh_msiof.h
index 2e8db3d..69c0f6e 100644
--- a/include/linux/spi/sh_msiof.h
+++ b/include/linux/spi/sh_msiof.h
@@ -5,6 +5,8 @@ struct sh_msiof_spi_info {
int tx_fifo_override;
int rx_fifo_override;
u16 num_chipselect;
+ unsigned int slave_id_tx;
+ unsigned int slave_id_rx;
};
#endif /* __SPI_SH_MSIOF_H__ */
--
1.7.2.5
^ permalink raw reply related
* [PATCH 0/2] SPI: spi-sh-msiof: add DMA support
From: Guennadi Liakhovetski @ 2011-09-02 15:13 UTC (permalink / raw)
To: spi-devel-general; +Cc: linux-sh, Grant Likely
This patch series adds DMA support for the MSIOF SPI controllers on
sh-mobile SoCs, e.g., on sh7724.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* [BUG] Bad page state on ecovec
From: Guennadi Liakhovetski @ 2011-09-02 12:54 UTC (permalink / raw)
To: linux-sh
Hi
After reverting the commits, mentioned in my previous mail, ecovec still
seems unstable with the current kernel, getting BUGs, similar to this one:
[ 782.108000] BUG: Bad page state in process modprobe pfn:0d274
[ 782.112000] page:8844ce80 count:-1 mapcount:0 mapping: (null) index:0x0
[ 782.120000] page flags: 0x0()
[ 782.124000] Stack: (0x8d389d2c to 0x8d38a000)
[ 782.128000] 9d20: 88255572 8d389d3c 00000000 8844ce80 8805686e
[ 782.140000] 9d40: 8d389d44 88057d18 8d389d54 00000000 00000001 00000000 8d269494 00000000
[ 782.156000] 9d60: 00000000 0000000c 00000000 8d389d70 88076d18 00000000 8836f61c ffffffff
[ 782.168000] 9d80: 00000000 00000000 8836f2d4 00000010 8844ce94 00000000 00000000 8836f28c
[ 782.184000] 9da0: 000202d2 8836f018 88057f12 8d389dd8 00000000 000000d2 8836f618 00000000
[ 782.196000] 9dc0: 00000000 000002d2 00000000 00000041 8836f018 00000000 00001fff ffffffff
[ 782.208000] 9de0: 8d389dec 00000000 8d389dfc 8d389df0 8806fc62 8d389e18 000000d2 00000010
[ 782.220000] 9e00: 8836f61c 00000002 8d389e0c 8806fcba 000202d2 8d389e18 00000000 8d389e30
[ 782.232000] 9e20: 8d389e24 88077054 8836f018 880707c4 8d389e4c ffffffff 000000d2 88057e48
[ 782.244000] 9e40: 000002d2 00000000 8d45aca0 00003810 0000050e 8d45a1e0 8807089a 8d389e8c
[ 782.256000] 9e60: 00000001 880407ac c0294000 c0290a44 c0290988 00003810 000000d2 0000050e
[ 782.268000] 9e80: 00003810 ffffffff 8804079e 8807096c 8d389ea4 0000050e 00003810 ffffffff
[ 782.280000] 9ea0: 8804079e 8804079e 8d389eb0 00000e73 880407bc 8d389eb8 88040ee6 8d389ec8
[ 782.292000] 9ec0: c0290988 8d389f28 0000004e c0290b0c 00000003 00000003 c0290988 c0290a50
[ 782.304000] 9ee0: 88041710 8d389f00 7bebbea7 0041c6f8 000035c7 c028f000 8d389f28 fffffff8
[ 782.316000] 9f00: 8e957eb8 00004000 00000004 00000000 00000000 8806c7f0 8d389f3c 0041b5a8
[ 782.332000] 9f20: 00000000 00004000 c028f000 000035c7 c0290be0 c0290b0c c0291e90 8d3b7380
[ 782.348000] 9f40: 000019b8 00001c58 00000000 00000000 00000015 00000016 0000000f 00000000
[ 782.360000] 9f60: 0000000b 00000000 000035c7 00000003 8d389f74 8800f580 8d389f90 29583004
[ 782.372000] 9f80: 29582e10 8800725a 7bebb9c8 7bebbea7 0041c6f8 00000000 00000071 00000100
[ 782.384000] 9fa0: 8804165c 00000000 00000000 0041c888 00000080 29576000 000035c7 0041b5a8
[ 782.396000] 9fc0: 7bebb9a8 0041b5c8 00401218 00402b20 00000000 0041c6f8 7bebbea7 7bebb9c8
[ 782.408000] 9fe0: 7bebb9c8 296613a6 004039ca 00008100 296e2678 00000000 0000002c 00000054
[ 782.424000]
[ 782.424000] Call trace:
[ 782.428000] [<88255572>] dump_stack+0xe/0x1c
[ 782.432000] [<8805686e>] bad_page+0x8a/0xd4
[ 782.436000] [<88057d18>] get_page_from_freelist+0x304/0x434
[ 782.440000] [<88076d18>] cache_alloc_refill+0x164/0x444
[ 782.444000] [<88057f12>] __alloc_pages_nodemask+0xca/0x4dc
[ 782.448000] [<8806fc62>] __get_vm_area_node+0xc2/0x18c
[ 782.452000] [<8806fcba>] __get_vm_area_node+0x11a/0x18c
[ 782.456000] [<88077054>] __kmalloc+0x5c/0xe8
[ 782.460000] [<880707c4>] __vmalloc_node_range+0xd4/0x184
[ 782.464000] [<88057e48>] __alloc_pages_nodemask+0x0/0x4dc
[ 782.468000] [<8807089a>] __vmalloc_node+0x26/0x3c
[ 782.472000] [<880407ac>] module_alloc_update_bounds+0x0/0x64
[ 782.476000] [<8804079e>] module_alloc+0x12/0x20
[ 782.480000] [<8807096c>] vmalloc_exec+0x20/0x34
[ 782.484000] [<8804079e>] module_alloc+0x12/0x20
[ 782.488000] [<8804079e>] module_alloc+0x12/0x20
[ 782.492000] [<880407bc>] module_alloc_update_bounds+0x10/0x64
[ 782.496000] [<88040ee6>] layout_and_allocate+0x6d6/0x7dc
[ 782.500000] [<88041710>] sys_init_module+0xb4/0xeb0
[ 782.504000] [<8806c7f0>] do_mmap_pgoff+0x230/0x284
[ 782.512000] [<8800f580>] handle_tlbmiss+0xd4/0x164
[ 782.520000] [<8800725a>] syscall_call+0xc/0x10
[ 782.528000] [<8804165c>] sys_init_module+0x0/0xeb0
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* Ecovec in current sh-latest
From: Guennadi Liakhovetski @ 2011-09-02 8:17 UTC (permalink / raw)
To: linux-sh
Hi
To get ecovec to run with today's sh-latest (pretty much the same with
Linux' tree) the following patches have to be reverted:
commit 794d78fea51504bad3880d14f354a9847f318f25
Author: Magnus Damm <damm@opensource.se>
Date: Tue Jun 21 07:55:12 2011 +0000
drivers: sh: late disabling of clocks V2
commit 3f9b8520b06013939ad247ba08b69529b5f14be1
Author: Paul Mundt <lethal@linux-sh.org>
Date: Tue May 31 14:38:29 2011 +0900
sh64: Move from P1SEG to CAC_ADDR for consistent sync.
commit cb3da5b837a410a1fb90019549b18178f3c87258
Author: Magnus Damm <damm@opensource.se>
Date: Wed Aug 3 12:47:36 2011 +0900
serial: sh-sci: console Runtime PM support
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* Re: [PATCH 3/5] PM / QoS: Add function dev_pm_qos_read_value()
From: Jean Pihet @ 2011-09-02 6:49 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <201109020007.22743.rjw@sisk.pl>
On Fri, Sep 2, 2011 at 12:07 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> Hi,
>
> On Thursday, September 01, 2011, Jean Pihet wrote:
>> Hi Rafael,
>>
>> On Wed, Aug 31, 2011 at 12:21 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
>> > From: Rafael J. Wysocki <rjw@sisk.pl>
>> >
>> > To read the current PM QoS value for a given device we need to
>> > make sure that the device's power.constraints object won't be
>> > removed while we're doing that. For this reason, put the
>> > operation under dev->power.lock and acquire the lock
>> > around the initialization and removal of power.constraints.
>> Ok.
>>
>> > Moreover, since we're using the value of power.constraints to
>> > determine whether or not the object is present, the
>> > power.constraints_state field isn't necessary any more and may be
>> > removed. However, dev_pm_qos_add_request() needs to check if the
>> > device is being removed from the system before allocating a new
>> > PM QoS constraints object for it, so it has to use device_pm_lock()
>> > and the device PM QoS initialization and destruction should be done
>> > under device_pm_lock() as well.
>> Ok that makes sense.
>> The constraints_state field can be replaced by a combination of
>> dev->power.constraints and list_empty(&dev->power.entry), which makes
>> the code more compact and less redundant.
>>
>> >
>> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
>> > ---
>> > drivers/base/power/main.c | 4 -
>> > drivers/base/power/qos.c | 167 ++++++++++++++++++++++++++--------------------
>> > include/linux/pm.h | 8 --
>> > include/linux/pm_qos.h | 3
>> > 4 files changed, 101 insertions(+), 81 deletions(-)
>> >
>> > Index: linux/drivers/base/power/qos.c
>> > =================================>> > --- linux.orig/drivers/base/power/qos.c
>> > +++ linux/drivers/base/power/qos.c
>> > @@ -30,15 +30,6 @@
>> ...
>>
>> >
>> > @@ -178,8 +202,8 @@ void dev_pm_qos_constraints_destroy(stru
>> > *
>> > * Returns 1 if the aggregated constraint value has changed,
>> > * 0 if the aggregated constraint value has not changed,
>> > - * -EINVAL in case of wrong parameters, -ENODEV if the device has been
>> > - * removed from the system
>> > + * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
>> > + * to allocate for data structures.
>> Why not use -ENODEV in case there is no device?
>
> I don't think it's useful for the caller. If the device is gone, the
> constraing simply doesn't matter, so there's no error to handle.
>
>> > */
>> > int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
>> > s32 value)
>> > @@ -195,28 +219,35 @@ int dev_pm_qos_add_request(struct device
>> > return -EINVAL;
>> > }
>> >
>> > - mutex_lock(&dev_pm_qos_mtx);
>> > req->dev = dev;
>> >
>> > - /* Return if the device has been removed */
>> > - if (req->dev->power.constraints_state = DEV_PM_QOS_NO_DEVICE) {
>> > - ret = -ENODEV;
>> > - goto out;
>> > - }
>> > + device_pm_lock();
>> > + mutex_lock(&dev_pm_qos_mtx);
>> >
>> > - /*
>> > - * Allocate the constraints data on the first call to add_request,
>> > - * i.e. only if the data is not already allocated and if the device has
>> > - * not been removed
>> > - */
>> > - if (dev->power.constraints_state = DEV_PM_QOS_DEVICE_PRESENT)
>> > - ret = dev_pm_qos_constraints_allocate(dev);
>> > + if (dev->power.constraints) {
>> > + device_pm_unlock();
>> > + } else {
>> > + if (list_empty(&dev->power.entry)) {
>> > + /* The device has been removed from the system. */
>> > + device_pm_unlock();
>> > + goto out;
>> 0 is silently returned in case the device has been removed. Is that
>> the intention?
>
> Pretty much it is. Is that a problem?
I think the caller needs to know if the constraint has been applied
correctly or not. That is why I changed the API functions to int.
Note: I still need to come with an API documentation patch after the
code is settled down.
>
> Rafael
>
Thanks,
Jean
^ permalink raw reply
* [PATCH] [RFC] sh: kexec: Register crashk_res
From: Simon Horman @ 2011-09-02 3:47 UTC (permalink / raw)
To: linux-sh
Register crashk_res so that it can be used by kexec-tools
via /proc/iomem.
On x86 the registration occurs using
insert_resource(&iomem_resource, &crashk_res).
However that approach seems to result in the boot hanging on SH.
Signed-off-by: Simon Horman <horms@verge.net.au>
---
arch/sh/kernel/setup.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 58bff45..6d566bb 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -211,13 +211,16 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
}
/*
- * We don't know which RAM region contains kernel data,
- * so we try it repeatedly and let the resource manager
- * test it.
+ * We don't know which RAM region contains kernel data or
+ * the reserved crashkernel region, so try it repeatedly
+ * and let the resource manager test it.
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
request_resource(res, &bss_resource);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
/*
* Also make sure that there is a PMB mapping that covers this
--
1.7.5.4
^ permalink raw reply related
* Re: [PATCH 0/5] PM: Generic PM domains and device PM QoS
From: Rafael J. Wysocki @ 2011-09-01 22:14 UTC (permalink / raw)
To: Jean Pihet
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <CAORVsuVJEbLRXLuQFUh3_rDf+DfNFpOhEuBr33SRKqxBos=6Bw@mail.gmail.com>
Hi,
On Thursday, September 01, 2011, Jean Pihet wrote:
> Rafael,
>
> On Wed, Aug 31, 2011 at 12:17 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > Hi,
> >
> > This patchset illustrates how device PM QoS may be used along with
> > PM domains in my view.
> >
> > Actually, it consists of two parts. Namely, patches [1-3/5] seem to be
> > suitable for 3.2, unless somebody hates them,
> The patches [1-3/5] are ok (reviewed only) excepted some remarks I have.
OK, thanks for the comments.
> > but patches [4-5/5] are
> > total RFC. They haven't been tested, only compiled, so the use of them
> > is not encouraged (they may kill your dog or make your cat go wild, or
> > do something equally nasty, so beware).
> That looks like a disclaimer ;p
>
> > Their purpose is to illustrate
> > an idea that I'd like to discuss at the PM miniconference during the
> > LPC.
> There is some code for OMAP that dynamically updates the worst case
> values for devices activation and de-activation;
> cf._omap_device_activate and _omap_device_deactivate in
> arch/arm/plat-omap/omap_device.c. The idea is to start with reference
> figures (worst case measured on board) at boot and then update the
> worst case values at runtime.
> Based on the PM QoS values and the worst case latency values the next
> power domains states can be determined. Unfortunately this is not
> (yet) implemented.
I thought about that too, but I'd like to discuss the basic idea first.
> I am wondering if the patches [4-5/5] are meant to replace the OMAP
> code, which would be really nice.
I certainly hope they will be useful for multiple platforms. Whether
or not OMAP turns out to be one of them I can't tell at the moment.
Thanks,
Rafael
^ permalink raw reply
* Re: [RFC][PATCH 5/5] PM / Domains: Add default power off governor function
From: Rafael J. Wysocki @ 2011-09-01 22:11 UTC (permalink / raw)
To: Jean Pihet
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <CAORVsuW7rFEN8u7RCpmWJamtG2iUbA_zz3ax4hgBjGAZW9vU=A@mail.gmail.com>
Hi,
On Thursday, September 01, 2011, Jean Pihet wrote:
> Rafael,
>
> On Wed, Aug 31, 2011 at 12:22 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rjw@sisk.pl>
> >
> > Add a function deciding whether or not a given PM domain should
> > be powered off on the basis of that domain's devices' PM QoS
> > constraints.
> >
> > ---
> > drivers/base/power/domain_governor.c | 96 +++++++++++++++++++++++++++++++++++
> > include/linux/pm_domain.h | 7 ++
> > 2 files changed, 103 insertions(+)
> >
> > Index: linux/include/linux/pm_domain.h
> > =================================> > --- linux.orig/include/linux/pm_domain.h
> > +++ linux/include/linux/pm_domain.h
> > @@ -49,6 +49,10 @@ struct generic_pm_domain {
> > int (*start_device)(struct device *dev);
> > int (*stop_device)(struct device *dev);
> > bool (*active_wakeup)(struct device *dev);
> > + ktime_t power_off_latency;
> > + ktime_t power_on_latency;
> > + s64 break_even_ns;
> > + s64 min_delta_ns;
> How are those values populated?
I'm not sure. There are a few possible ways to do that, but I simply
don't know which one is going to be the most useful. That's one of
the reasons why patches [4-5/5] are RFCs.
> Is there a mechanism that dynamically updates the values?
Obviously not at the moment.
Thanks,
Rafael
^ permalink raw reply
* Re: [PATCH 3/5] PM / QoS: Add function dev_pm_qos_read_value()
From: Rafael J. Wysocki @ 2011-09-01 22:07 UTC (permalink / raw)
To: Jean Pihet
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <CAORVsuX=vKiGxHrR4hZjeT4DV0vhUh+MXLwNjoOwgBDu1HRR5A@mail.gmail.com>
Hi,
On Thursday, September 01, 2011, Jean Pihet wrote:
> Hi Rafael,
>
> On Wed, Aug 31, 2011 at 12:21 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rjw@sisk.pl>
> >
> > To read the current PM QoS value for a given device we need to
> > make sure that the device's power.constraints object won't be
> > removed while we're doing that. For this reason, put the
> > operation under dev->power.lock and acquire the lock
> > around the initialization and removal of power.constraints.
> Ok.
>
> > Moreover, since we're using the value of power.constraints to
> > determine whether or not the object is present, the
> > power.constraints_state field isn't necessary any more and may be
> > removed. However, dev_pm_qos_add_request() needs to check if the
> > device is being removed from the system before allocating a new
> > PM QoS constraints object for it, so it has to use device_pm_lock()
> > and the device PM QoS initialization and destruction should be done
> > under device_pm_lock() as well.
> Ok that makes sense.
> The constraints_state field can be replaced by a combination of
> dev->power.constraints and list_empty(&dev->power.entry), which makes
> the code more compact and less redundant.
>
> >
> > Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> > ---
> > drivers/base/power/main.c | 4 -
> > drivers/base/power/qos.c | 167 ++++++++++++++++++++++++++--------------------
> > include/linux/pm.h | 8 --
> > include/linux/pm_qos.h | 3
> > 4 files changed, 101 insertions(+), 81 deletions(-)
> >
> > Index: linux/drivers/base/power/qos.c
> > =================================> > --- linux.orig/drivers/base/power/qos.c
> > +++ linux/drivers/base/power/qos.c
> > @@ -30,15 +30,6 @@
> ...
>
> >
> > @@ -178,8 +202,8 @@ void dev_pm_qos_constraints_destroy(stru
> > *
> > * Returns 1 if the aggregated constraint value has changed,
> > * 0 if the aggregated constraint value has not changed,
> > - * -EINVAL in case of wrong parameters, -ENODEV if the device has been
> > - * removed from the system
> > + * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
> > + * to allocate for data structures.
> Why not use -ENODEV in case there is no device?
I don't think it's useful for the caller. If the device is gone, the
constraing simply doesn't matter, so there's no error to handle.
> > */
> > int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
> > s32 value)
> > @@ -195,28 +219,35 @@ int dev_pm_qos_add_request(struct device
> > return -EINVAL;
> > }
> >
> > - mutex_lock(&dev_pm_qos_mtx);
> > req->dev = dev;
> >
> > - /* Return if the device has been removed */
> > - if (req->dev->power.constraints_state = DEV_PM_QOS_NO_DEVICE) {
> > - ret = -ENODEV;
> > - goto out;
> > - }
> > + device_pm_lock();
> > + mutex_lock(&dev_pm_qos_mtx);
> >
> > - /*
> > - * Allocate the constraints data on the first call to add_request,
> > - * i.e. only if the data is not already allocated and if the device has
> > - * not been removed
> > - */
> > - if (dev->power.constraints_state = DEV_PM_QOS_DEVICE_PRESENT)
> > - ret = dev_pm_qos_constraints_allocate(dev);
> > + if (dev->power.constraints) {
> > + device_pm_unlock();
> > + } else {
> > + if (list_empty(&dev->power.entry)) {
> > + /* The device has been removed from the system. */
> > + device_pm_unlock();
> > + goto out;
> 0 is silently returned in case the device has been removed. Is that
> the intention?
Pretty much it is. Is that a problem?
Rafael
^ permalink raw reply
* Re: [PATCH] sh: Fix implicit declaration of function numa_node_id
From: Nobuhiro Iwamatsu @ 2011-09-01 21:05 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <1314335141-15887-1-git-send-email-nobuhiro.iwamatsu.yj@renesas.com>
2011/8/29 Paul Mundt <lethal@linux-sh.org>:
> On Fri, Aug 26, 2011 at 02:05:41PM +0900, Nobuhiro Iwamatsu wrote:
>> CC arch/sh/kernel/topology.o
>> arch/sh/kernel/topology.c: In function ???topology_init???:
>> arch/sh/kernel/topology.c:77: error: implicit declaration of function ???numa_node_id???
>>
>> Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
>
> Against what tree? I don't have anything this applies to.
From linux-next. This problem is caused by the commit
d497d16880f15b3798c6e9c078ce7f9d70bbd6bc.
However, this patch is not yet applied in Linus-tree. Please apply in
my patch if applied.
^ permalink raw reply
* Re: [PATCH 0/5] PM: Generic PM domains and device PM QoS
From: Jean Pihet @ 2011-09-01 15:28 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <201108310017.03103.rjw@sisk.pl>
Rafael,
On Wed, Aug 31, 2011 at 12:17 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> Hi,
>
> This patchset illustrates how device PM QoS may be used along with
> PM domains in my view.
>
> Actually, it consists of two parts. Namely, patches [1-3/5] seem to be
> suitable for 3.2, unless somebody hates them,
The patches [1-3/5] are ok (reviewed only) excepted some remarks I have.
> but patches [4-5/5] are
> total RFC. They haven't been tested, only compiled, so the use of them
> is not encouraged (they may kill your dog or make your cat go wild, or
> do something equally nasty, so beware).
That looks like a disclaimer ;p
> Their purpose is to illustrate
> an idea that I'd like to discuss at the PM miniconference during the
> LPC.
There is some code for OMAP that dynamically updates the worst case
values for devices activation and de-activation;
cf._omap_device_activate and _omap_device_deactivate in
arch/arm/plat-omap/omap_device.c. The idea is to start with reference
figures (worst case measured on board) at boot and then update the
worst case values at runtime.
Based on the PM QoS values and the worst case latency values the next
power domains states can be determined. Unfortunately this is not
(yet) implemented.
I am wondering if the patches [4-5/5] are meant to replace the OMAP
code, which would be really nice.
>
> [1/5] - Split device PM domain data into a "base" and additional fields
> (one need_restore field at the moment, but the subsequent patches
> add more fields).
>
> [2/5] - Make runtime PM always release power.lock if power.irq_safe is set.
>
> [3/5] - Add function for reading device PM QoS values safely.
>
> [4/5] - Add governor function for stopping devices.
>
> [5/5] - Add generic PM domain power off governor function.
>
> Thanks,
> Rafael
>
>
Regards,
Jean
^ permalink raw reply
* Re: [RFC][PATCH 5/5] PM / Domains: Add default power off governor function
From: Jean Pihet @ 2011-09-01 15:17 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <201108310022.43850.rjw@sisk.pl>
Rafael,
On Wed, Aug 31, 2011 at 12:22 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
>
> Add a function deciding whether or not a given PM domain should
> be powered off on the basis of that domain's devices' PM QoS
> constraints.
>
> ---
> drivers/base/power/domain_governor.c | 96 +++++++++++++++++++++++++++++++++++
> include/linux/pm_domain.h | 7 ++
> 2 files changed, 103 insertions(+)
>
> Index: linux/include/linux/pm_domain.h
> =================================> --- linux.orig/include/linux/pm_domain.h
> +++ linux/include/linux/pm_domain.h
> @@ -49,6 +49,10 @@ struct generic_pm_domain {
> int (*start_device)(struct device *dev);
> int (*stop_device)(struct device *dev);
> bool (*active_wakeup)(struct device *dev);
> + ktime_t power_off_latency;
> + ktime_t power_on_latency;
> + s64 break_even_ns;
> + s64 min_delta_ns;
How are those values populated? Is there a mechanism that dynamically
updates the values?
> };
>
> static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
> @@ -64,6 +68,9 @@ struct gpd_link {
> };
>
> struct gpd_gov_dev_data {
> + ktime_t start_latency;
> + ktime_t suspend_latency;
> + ktime_t resume_latency;
Same question here.
> s64 break_even_ns;
> };
>
...
Regards,
Jean
^ permalink raw reply
* Re: [PATCH 3/5] PM / QoS: Add function dev_pm_qos_read_value()
From: Jean Pihet @ 2011-09-01 15:13 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Linux PM mailing list, LKML, Linux-sh list, Magnus Damm,
Kevin Hilman
In-Reply-To: <201108310021.13800.rjw@sisk.pl>
Hi Rafael,
On Wed, Aug 31, 2011 at 12:21 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rjw@sisk.pl>
>
> To read the current PM QoS value for a given device we need to
> make sure that the device's power.constraints object won't be
> removed while we're doing that. For this reason, put the
> operation under dev->power.lock and acquire the lock
> around the initialization and removal of power.constraints.
Ok.
> Moreover, since we're using the value of power.constraints to
> determine whether or not the object is present, the
> power.constraints_state field isn't necessary any more and may be
> removed. However, dev_pm_qos_add_request() needs to check if the
> device is being removed from the system before allocating a new
> PM QoS constraints object for it, so it has to use device_pm_lock()
> and the device PM QoS initialization and destruction should be done
> under device_pm_lock() as well.
Ok that makes sense.
The constraints_state field can be replaced by a combination of
dev->power.constraints and list_empty(&dev->power.entry), which makes
the code more compact and less redundant.
>
> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
> ---
> drivers/base/power/main.c | 4 -
> drivers/base/power/qos.c | 167 ++++++++++++++++++++++++++--------------------
> include/linux/pm.h | 8 --
> include/linux/pm_qos.h | 3
> 4 files changed, 101 insertions(+), 81 deletions(-)
>
> Index: linux/drivers/base/power/qos.c
> =================================> --- linux.orig/drivers/base/power/qos.c
> +++ linux/drivers/base/power/qos.c
> @@ -30,15 +30,6 @@
...
>
> @@ -178,8 +202,8 @@ void dev_pm_qos_constraints_destroy(stru
> *
> * Returns 1 if the aggregated constraint value has changed,
> * 0 if the aggregated constraint value has not changed,
> - * -EINVAL in case of wrong parameters, -ENODEV if the device has been
> - * removed from the system
> + * -EINVAL in case of wrong parameters, -ENOMEM if there's not enough memory
> + * to allocate for data structures.
Why not use -ENODEV in case there is no device?
> */
> int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
> s32 value)
> @@ -195,28 +219,35 @@ int dev_pm_qos_add_request(struct device
> return -EINVAL;
> }
>
> - mutex_lock(&dev_pm_qos_mtx);
> req->dev = dev;
>
> - /* Return if the device has been removed */
> - if (req->dev->power.constraints_state = DEV_PM_QOS_NO_DEVICE) {
> - ret = -ENODEV;
> - goto out;
> - }
> + device_pm_lock();
> + mutex_lock(&dev_pm_qos_mtx);
>
> - /*
> - * Allocate the constraints data on the first call to add_request,
> - * i.e. only if the data is not already allocated and if the device has
> - * not been removed
> - */
> - if (dev->power.constraints_state = DEV_PM_QOS_DEVICE_PRESENT)
> - ret = dev_pm_qos_constraints_allocate(dev);
> + if (dev->power.constraints) {
> + device_pm_unlock();
> + } else {
> + if (list_empty(&dev->power.entry)) {
> + /* The device has been removed from the system. */
> + device_pm_unlock();
> + goto out;
0 is silently returned in case the device has been removed. Is that
the intention?
> + } else {
> + device_pm_unlock();
> + /*
> + * Allocate the constraints data on the first call to
> + * add_request, i.e. only if the data is not already
> + * allocated and if the device has not been removed.
> + */
> + ret = dev_pm_qos_constraints_allocate(dev);
> + }
> + }
>
> if (!ret)
> ret = apply_constraint(req, PM_QOS_ADD_REQ, value);
>
> -out:
> + out:
> mutex_unlock(&dev_pm_qos_mtx);
> +
> return ret;
> }
> EXPORT_SYMBOL_GPL(dev_pm_qos_add_request);
...
Thanks,
Jean
^ permalink raw reply
* Re: Ecovec (SH7724) board doesn't work on latest linus tree
From: Kuninori Morimoto @ 2011-09-01 1:45 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <w3pvcwf5xuu.wl%kuninori.morimoto.gx@renesas.com>
Hi Paul
> I guess your patch tried to share code for sh32/sh64.
> and CAC_ADDR() should be equal P1SEGADDR(), correct ?
>
> I'm not filmier with memory control, but
> on Ecovec case, 1st (and crash case) dma_cache_sync() caller is
> ${LINUX}/arch/sh/mm/consistent.c :: dma_generic_alloc_coherent()
>
> it tried
>
> ret = (void *)__get_free_pages(gfp, order);
> (snip)
> dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
>
> This "ret" is "8e000000" for now.
>
> but CAC_ADDR(xx)/P1SEGADDR(xx) is defined as below
>
> CAC_ADDR(addr) ((addr) - uncached_start + PAGE_OFFSET)
> P1SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P1SEG))
>
> I guess this "ret" should be uncached area if dma_cache_sync(xx) use CAC_ADDR(xx).
>
> If I apply below patch, Ecovec start works without crash, but I'm not sure.
> Is this correct patch ?
>
> --------------------
> diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
> index f251b5f..198234a 100644
> --- a/arch/sh/mm/consistent.c
> +++ b/arch/sh/mm/consistent.c
> @@ -48,7 +48,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t si
> * Pages from the page allocator may have data present in
> * cache. So flush the cache before using uncached memory.
> */
> - dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
> + dma_cache_sync(dev, UNCAC_ADDR(ret), size, DMA_BIDIRECTIONAL);
>
> ret_nocache = (void __force *)ioremap_nocache(virt_to_phys(ret), size);
> if (!ret_nocache) {
> -------------------------
>
> But I'm afraid below comment of dma_generic_alloc_coherent()
>
> /*
> * Pages from the page allocator may have data present in
> * cache. So flush the cache before using uncached memory.
> */
> dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
dma_cache_sync(xx) should not expect vaddr is in uncached area ?
Best regards
---
Kuninori Morimoto
^ permalink raw reply
* Re: Ecovec (SH7724) board doesn't work on latest linus tree
From: Kuninori Morimoto @ 2011-09-01 1:28 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <w3pvcwf5xuu.wl%kuninori.morimoto.gx@renesas.com>
Hi Ebihara-san, and Paul
Thank you for your report.
> i think you can run linux-3.0.4 kernel on your Ecovec (SH7724) board
> in this debug-code.
>
>
> void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
> enum dma_data_direction direction)
> {
> void *addr;
>
> addr = __in_29bit_mode() ?
> - (void *)CAC_ADDR((unsigned long)vaddr) : vaddr;
> + (void *)P1SEGADDR((unsigned long)vaddr) : vaddr;
Paul
I guess your patch tried to share code for sh32/sh64.
and CAC_ADDR() should be equal P1SEGADDR(), correct ?
I'm not filmier with memory control, but
on Ecovec case, 1st (and crash case) dma_cache_sync() caller is
${LINUX}/arch/sh/mm/consistent.c :: dma_generic_alloc_coherent()
it tried
ret = (void *)__get_free_pages(gfp, order);
(snip)
dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
This "ret" is "8e000000" for now.
but CAC_ADDR(xx)/P1SEGADDR(xx) is defined as below
CAC_ADDR(addr) ((addr) - uncached_start + PAGE_OFFSET)
P1SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P1SEG))
I guess this "ret" should be uncached area if dma_cache_sync(xx) use CAC_ADDR(xx).
If I apply below patch, Ecovec start works without crash, but I'm not sure.
Is this correct patch ?
--------------------
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index f251b5f..198234a 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -48,7 +48,7 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t si
* Pages from the page allocator may have data present in
* cache. So flush the cache before using uncached memory.
*/
- dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
+ dma_cache_sync(dev, UNCAC_ADDR(ret), size, DMA_BIDIRECTIONAL);
ret_nocache = (void __force *)ioremap_nocache(virt_to_phys(ret), size);
if (!ret_nocache) {
-------------------------
But I'm afraid below comment of dma_generic_alloc_coherent()
/*
* Pages from the page allocator may have data present in
* cache. So flush the cache before using uncached memory.
*/
dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
Best regards
---
Kuninori Morimoto
^ permalink raw reply related
* Re: Ecovec (SH7724) board doesn't work on latest linus tree
From: Yutaro Ebihara @ 2011-08-31 15:07 UTC (permalink / raw)
To: linux-sh
In-Reply-To: <w3pvcwf5xuu.wl%kuninori.morimoto.gx@renesas.com>
hello.
i think you can run linux-3.0.4 kernel on your Ecovec (SH7724) board
in this debug-code.
void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction)
{
void *addr;
addr = __in_29bit_mode() ?
- (void *)CAC_ADDR((unsigned long)vaddr) : vaddr;
+ (void *)P1SEGADDR((unsigned long)vaddr) : vaddr;
CAC_ADDR((unsigned long)vaddr) : vaddr;
must be fail.
>@@ -84,6 +84,10 @@ void dma_cache_sync(struct device *dev, void *vaddr,
>size_t size,
> addr = __in_29bit_mode() ?
> (void *)CAC_ADDR((unsigned long)vaddr) : vaddr;
>
>Dear Paul
>
>Ecovec board still doesn't work on latest linus tree.
>Because of below commit.
>
>----------------
>commit 3f9b8520b06013939ad247ba08b69529b5f14be1
>Author: Paul Mundt <lethal@linux-sh.org>
>Date: Tue May 31 14:38:29 2011 +0900
>
> sh64: Move from P1SEG to CAC_ADDR for consistent sync.
>
> sh64 doesn't define a P1SEGADDR, resulting in a build failure. The proper
> mapping can be attained for both sh32 and 64 via the CAC_ADDR macro, so
> switch to that instead.
>
> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
>----------------
>
>The output of below patch was
>
>dma_cache_sync: vaddr 8e000000, CAC 6e000000, P1SEG 8e000000
>
>------
>diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
>index f251b5f..01bb4ee 100644
>--- a/arch/sh/mm/consistent.c
>+++ b/arch/sh/mm/consistent.c
>@@ -84,6 +84,10 @@ void dma_cache_sync(struct device *dev, void *vaddr,
>size_t size,
> addr = __in_29bit_mode() ?
> (void *)CAC_ADDR((unsigned long)vaddr) : vaddr;
>
>+ printk_once("%s: vaddr %p, CAC %08lx, P1SEG %08lx\n", __func__, vaddr,
>+ CAC_ADDR((unsigned long)vaddr),
>+ P1SEGADDR((unsigned long)vaddr));
>+
> switch (direction) {
> case DMA_FROM_DEVICE: /* invalidate only */
> __flush_invalidate_region(addr, size);
>
>
>Best regards
>---
>Kuninori Morimoto
>--
>To unsubscribe from this list: send the line "unsubscribe linux-sh" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PULL] SH mobile LCDC cleanups and fixes
From: Laurent Pinchart @ 2011-08-31 11:01 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <201108191044.52130.laurent.pinchart@ideasonboard.com>
Hi Florian,
On Tuesday 30 August 2011 22:41:39 Florian Tobias Schandinat wrote:
> On 08/19/2011 08:44 AM, Laurent Pinchart wrote:
> > Hi Florian,
> >
> > Here are the latest SH mobile LCDC and MERAM cleanups and fixes based on
> > top of v3.1-rc2. All the patches have been posted to the list. I've
> > incorporated acked-by and tested-by lines when available, but most of
> > the patches received no comment.
> >
> > The following changes since commit
93ee7a9340d64f20295aacc3fb6a22b759323280:
> > Linux 3.1-rc2 (2011-08-14 15:09:08 -0700)
> >
> > are available in the git repository at:
> > git://linuxtv.org/pinchartl/fbdev.git sh-mobile-lcdc
>
> Pulled, thanks.
Thanks you.
Do you plan to pull the "sh_mobile_lcdc: Support format changes at runtime"
patch set as well ? I've just submitted a v2 that includes an additional patch
to fix a MERAM issue.
> It looks good to me, as far as I can tell.
> Just the first commits that were not your own ones should have had more
> verbose commit messages and I think they should have had your Signed-off
> as you received them via e-mail?
I've just picked them from the list, as I needed them to build the other
patches.
> And on another note:
> Would you mind adding yourself as maintainer of drivers/video/sh_mobile_*
> in MAINTAINERS? I can't find any entry for it yet and having me as primary
> source for review for a driver I don't know is a bad idea, at least if
> there are people that know it better.
I don't know the driver *that* well :-) I'm not sure how long I will work on
that driver, so maybe it would be a better idea to list Magnus as the
maintainer. Magnus, what's your opinion ?
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH v2 8/8] fbdev: sh_mobile_lcdc: Remove sh_mobile_lcdc_set_bpp()
From: Laurent Pinchart @ 2011-08-31 11:00 UTC (permalink / raw)
To: linux-fbdev
The function duplicates code found in sh_mobile_check_var(). Remove
sh_mobile_lcdc_set_bpp() and call sh_mobile_check_var() instead.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
drivers/video/sh_mobile_lcdcfb.c | 87 +++++++------------------------------
1 files changed, 17 insertions(+), 70 deletions(-)
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index d1576e2..97ab8ba 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -1291,66 +1291,6 @@ static void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev)
backlight_device_unregister(bdev);
}
-static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp,
- int nonstd)
-{
- if (nonstd) {
- switch (bpp) {
- case 12:
- case 16:
- case 24:
- var->bits_per_pixel = bpp;
- var->nonstd = nonstd;
- return 0;
- default:
- return -EINVAL;
- }
- }
-
- switch (bpp) {
- case 16: /* PKF[4:0] = 00011 - RGB 565 */
- var->red.offset = 11;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 6;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
-
- case 24: /* PKF[4:0] = 01011 - RGB 888 */
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
-
- case 32: /* PKF[4:0] = 00000 - RGBA 888 */
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- break;
- default:
- return -EINVAL;
- }
- var->bits_per_pixel = bpp;
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.msb_right = 0;
- return 0;
-}
-
static int sh_mobile_lcdc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1499,6 +1439,9 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
int ret;
int i;
+ mutex_init(&ch->open_lock);
+
+ /* Allocate the frame buffer device. */
ch->info = framebuffer_alloc(0, dev);
if (!ch->info) {
dev_err(dev, "unable to allocate fb_info\n");
@@ -1506,11 +1449,10 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
}
info = ch->info;
- var = &info->var;
info->fbops = &sh_mobile_lcdc_ops;
info->par = ch;
-
- mutex_init(&ch->open_lock);
+ info->pseudo_palette = &ch->pseudo_palette;
+ info->flags = FBINFO_FLAG_DEFAULT;
/* Iterate through the modes to validate them and find the highest
* resolution.
@@ -1541,13 +1483,15 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
dev_dbg(dev, "Found largest videomode %ux%u\n",
max_mode->xres, max_mode->yres);
+ /* Initialize fixed screen information. Restrict pan to 2 lines steps
+ * for NV12.
+ */
info->fix = sh_mobile_lcdc_fix;
info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
-
- /* Only pan in 2 line steps for NV12 */
if (cfg->nonstd && cfg->bpp = 12)
info->fix.ypanstep = 2;
+ /* Create the mode list. */
if (cfg->lcd_cfg = NULL) {
mode = &default_720p;
num_cfg = 1;
@@ -1558,17 +1502,23 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
+ /* Initialize variable screen information using the first mode as
+ * default. The default Y virtual resolution is twice the panel size to
+ * allow for double-buffering.
+ */
+ var = &info->var;
fb_videomode_to_var(var, mode);
+ var->bits_per_pixel = cfg->bpp;
var->width = cfg->lcd_size_cfg.width;
var->height = cfg->lcd_size_cfg.height;
- /* Default Y virtual resolution is 2x panel size */
var->yres_virtual = var->yres * 2;
var->activate = FB_ACTIVATE_NOW;
- ret = sh_mobile_lcdc_set_bpp(var, cfg->bpp, cfg->nonstd);
+ ret = sh_mobile_check_var(var, info);
if (ret)
return ret;
+ /* Allocate frame buffer memory and color map. */
buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle,
GFP_KERNEL);
if (!buf) {
@@ -1576,9 +1526,6 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
return -ENOMEM;
}
- info->pseudo_palette = &ch->pseudo_palette;
- info->flags = FBINFO_FLAG_DEFAULT;
-
ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
if (ret < 0) {
dev_err(dev, "unable to allocate cmap\n");
--
1.7.3.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox