diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-17 23:58:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-17 23:58:12 -0500 |
commit | 848b81415c42ff3dc9a4204749087b015c37ef66 (patch) | |
tree | 391da3a73aea48632248220d2d6b8d45a88f7eae /drivers | |
parent | 992956189de58cae9f2be40585bc25105cd7c5ad (diff) | |
parent | 6fd59a83b9261fa53eaf98fb5514abba504a3ea3 (diff) |
Merge branch 'akpm' (Andrew's patch-bomb)
Merge misc patches from Andrew Morton:
"Incoming:
- lots of misc stuff
- backlight tree updates
- lib/ updates
- Oleg's percpu-rwsem changes
- checkpatch
- rtc
- aoe
- more checkpoint/restart support
I still have a pile of MM stuff pending - Pekka should be merging
later today after which that is good to go. A number of other things
are twiddling thumbs awaiting maintainer merges."
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (180 commits)
scatterlist: don't BUG when we can trivially return a proper error.
docs: update documentation about /proc/<pid>/fdinfo/<fd> fanotify output
fs, fanotify: add @mflags field to fanotify output
docs: add documentation about /proc/<pid>/fdinfo/<fd> output
fs, notify: add procfs fdinfo helper
fs, exportfs: add exportfs_encode_inode_fh() helper
fs, exportfs: escape nil dereference if no s_export_op present
fs, epoll: add procfs fdinfo helper
fs, eventfd: add procfs fdinfo helper
procfs: add ability to plug in auxiliary fdinfo providers
tools/testing/selftests/kcmp/kcmp_test.c: print reason for failure in kcmp_test
breakpoint selftests: print failure status instead of cause make error
kcmp selftests: print fail status instead of cause make error
kcmp selftests: make run_tests fix
mem-hotplug selftests: print failure status instead of cause make error
cpu-hotplug selftests: print failure status instead of cause make error
mqueue selftests: print failure status instead of cause make error
vm selftests: print failure status instead of cause make error
ubifs: use prandom_bytes
mtd: nandsim: use prandom_bytes
...
Diffstat (limited to 'drivers')
59 files changed, 1978 insertions, 710 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index d2ed7f18d1ac..175649468c95 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | #define VERSION "50" | 2 | #define VERSION "81" |
3 | #define AOE_MAJOR 152 | 3 | #define AOE_MAJOR 152 |
4 | #define DEVICE_NAME "aoe" | 4 | #define DEVICE_NAME "aoe" |
5 | 5 | ||
@@ -10,7 +10,7 @@ | |||
10 | #define AOE_PARTITIONS (16) | 10 | #define AOE_PARTITIONS (16) |
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | #define WHITESPACE " \t\v\f\n" | 13 | #define WHITESPACE " \t\v\f\n," |
14 | 14 | ||
15 | enum { | 15 | enum { |
16 | AOECMD_ATA, | 16 | AOECMD_ATA, |
@@ -73,21 +73,29 @@ enum { | |||
73 | DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */ | 73 | DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */ |
74 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ | 74 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ |
75 | DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */ | 75 | DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */ |
76 | DEVFL_KICKME = (1<<4), /* slow polling network card catch */ | 76 | DEVFL_GD_NOW = (1<<4), /* allocating gendisk */ |
77 | DEVFL_NEWSIZE = (1<<5), /* need to update dev size in block layer */ | 77 | DEVFL_KICKME = (1<<5), /* slow polling network card catch */ |
78 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ | ||
79 | DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */ | ||
80 | DEVFL_FREED = (1<<8), /* device has been cleaned up */ | ||
78 | }; | 81 | }; |
79 | 82 | ||
80 | enum { | 83 | enum { |
81 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ | 84 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ |
82 | MIN_BUFS = 16, | 85 | MIN_BUFS = 16, |
83 | NTARGETS = 8, | 86 | NTARGETS = 4, |
84 | NAOEIFS = 8, | 87 | NAOEIFS = 8, |
85 | NSKBPOOLMAX = 256, | 88 | NSKBPOOLMAX = 256, |
86 | NFACTIVE = 61, | 89 | NFACTIVE = 61, |
87 | 90 | ||
88 | TIMERTICK = HZ / 10, | 91 | TIMERTICK = HZ / 10, |
89 | MINTIMER = HZ >> 2, | 92 | RTTSCALE = 8, |
90 | MAXTIMER = HZ << 1, | 93 | RTTDSCALE = 3, |
94 | RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE, | ||
95 | RTTDEV_INIT = RTTAVG_INIT / 4, | ||
96 | |||
97 | HARD_SCORN_SECS = 10, /* try another remote port after this */ | ||
98 | MAX_TAINT = 1000, /* cap on aoetgt taint */ | ||
91 | }; | 99 | }; |
92 | 100 | ||
93 | struct buf { | 101 | struct buf { |
@@ -100,10 +108,17 @@ struct buf { | |||
100 | struct request *rq; | 108 | struct request *rq; |
101 | }; | 109 | }; |
102 | 110 | ||
111 | enum frame_flags { | ||
112 | FFL_PROBE = 1, | ||
113 | }; | ||
114 | |||
103 | struct frame { | 115 | struct frame { |
104 | struct list_head head; | 116 | struct list_head head; |
105 | u32 tag; | 117 | u32 tag; |
118 | struct timeval sent; /* high-res time packet was sent */ | ||
119 | u32 sent_jiffs; /* low-res jiffies-based sent time */ | ||
106 | ulong waited; | 120 | ulong waited; |
121 | ulong waited_total; | ||
107 | struct aoetgt *t; /* parent target I belong to */ | 122 | struct aoetgt *t; /* parent target I belong to */ |
108 | sector_t lba; | 123 | sector_t lba; |
109 | struct sk_buff *skb; /* command skb freed on module exit */ | 124 | struct sk_buff *skb; /* command skb freed on module exit */ |
@@ -112,6 +127,7 @@ struct frame { | |||
112 | struct bio_vec *bv; | 127 | struct bio_vec *bv; |
113 | ulong bcnt; | 128 | ulong bcnt; |
114 | ulong bv_off; | 129 | ulong bv_off; |
130 | char flags; | ||
115 | }; | 131 | }; |
116 | 132 | ||
117 | struct aoeif { | 133 | struct aoeif { |
@@ -122,28 +138,31 @@ struct aoeif { | |||
122 | 138 | ||
123 | struct aoetgt { | 139 | struct aoetgt { |
124 | unsigned char addr[6]; | 140 | unsigned char addr[6]; |
125 | ushort nframes; | 141 | ushort nframes; /* cap on frames to use */ |
126 | struct aoedev *d; /* parent device I belong to */ | 142 | struct aoedev *d; /* parent device I belong to */ |
127 | struct list_head ffree; /* list of free frames */ | 143 | struct list_head ffree; /* list of free frames */ |
128 | struct aoeif ifs[NAOEIFS]; | 144 | struct aoeif ifs[NAOEIFS]; |
129 | struct aoeif *ifp; /* current aoeif in use */ | 145 | struct aoeif *ifp; /* current aoeif in use */ |
130 | ushort nout; | 146 | ushort nout; /* number of AoE commands outstanding */ |
131 | ushort maxout; | 147 | ushort maxout; /* current value for max outstanding */ |
132 | ulong falloc; | 148 | ushort next_cwnd; /* incr maxout after decrementing to zero */ |
133 | ulong lastwadj; /* last window adjustment */ | 149 | ushort ssthresh; /* slow start threshold */ |
150 | ulong falloc; /* number of allocated frames */ | ||
151 | int taint; /* how much we want to avoid this aoetgt */ | ||
134 | int minbcnt; | 152 | int minbcnt; |
135 | int wpkts, rpkts; | 153 | int wpkts, rpkts; |
154 | char nout_probes; | ||
136 | }; | 155 | }; |
137 | 156 | ||
138 | struct aoedev { | 157 | struct aoedev { |
139 | struct aoedev *next; | 158 | struct aoedev *next; |
140 | ulong sysminor; | 159 | ulong sysminor; |
141 | ulong aoemajor; | 160 | ulong aoemajor; |
161 | u32 rttavg; /* scaled AoE round trip time average */ | ||
162 | u32 rttdev; /* scaled round trip time mean deviation */ | ||
142 | u16 aoeminor; | 163 | u16 aoeminor; |
143 | u16 flags; | 164 | u16 flags; |
144 | u16 nopen; /* (bd_openers isn't available without sleeping) */ | 165 | u16 nopen; /* (bd_openers isn't available without sleeping) */ |
145 | u16 rttavg; /* round trip average of requests/responses */ | ||
146 | u16 mintimer; | ||
147 | u16 fw_ver; /* version of blade's firmware */ | 166 | u16 fw_ver; /* version of blade's firmware */ |
148 | u16 lasttag; /* last tag sent */ | 167 | u16 lasttag; /* last tag sent */ |
149 | u16 useme; | 168 | u16 useme; |
@@ -151,7 +170,7 @@ struct aoedev { | |||
151 | struct work_struct work;/* disk create work struct */ | 170 | struct work_struct work;/* disk create work struct */ |
152 | struct gendisk *gd; | 171 | struct gendisk *gd; |
153 | struct request_queue *blkq; | 172 | struct request_queue *blkq; |
154 | struct hd_geometry geo; | 173 | struct hd_geometry geo; |
155 | sector_t ssize; | 174 | sector_t ssize; |
156 | struct timer_list timer; | 175 | struct timer_list timer; |
157 | spinlock_t lock; | 176 | spinlock_t lock; |
@@ -164,11 +183,12 @@ struct aoedev { | |||
164 | } ip; | 183 | } ip; |
165 | ulong maxbcnt; | 184 | ulong maxbcnt; |
166 | struct list_head factive[NFACTIVE]; /* hash of active frames */ | 185 | struct list_head factive[NFACTIVE]; /* hash of active frames */ |
167 | struct aoetgt *targets[NTARGETS]; | 186 | struct list_head rexmitq; /* deferred retransmissions */ |
187 | struct aoetgt **targets; | ||
188 | ulong ntargets; /* number of allocated aoetgt pointers */ | ||
168 | struct aoetgt **tgt; /* target in use when working */ | 189 | struct aoetgt **tgt; /* target in use when working */ |
169 | struct aoetgt *htgt; /* target needing rexmit assistance */ | ||
170 | ulong ntargets; | ||
171 | ulong kicked; | 190 | ulong kicked; |
191 | char ident[512]; | ||
172 | }; | 192 | }; |
173 | 193 | ||
174 | /* kthread tracking */ | 194 | /* kthread tracking */ |
@@ -195,6 +215,7 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); | |||
195 | struct sk_buff *aoecmd_ata_rsp(struct sk_buff *); | 215 | struct sk_buff *aoecmd_ata_rsp(struct sk_buff *); |
196 | void aoecmd_cfg_rsp(struct sk_buff *); | 216 | void aoecmd_cfg_rsp(struct sk_buff *); |
197 | void aoecmd_sleepwork(struct work_struct *); | 217 | void aoecmd_sleepwork(struct work_struct *); |
218 | void aoecmd_wreset(struct aoetgt *t); | ||
198 | void aoecmd_cleanslate(struct aoedev *); | 219 | void aoecmd_cleanslate(struct aoedev *); |
199 | void aoecmd_exit(void); | 220 | void aoecmd_exit(void); |
200 | int aoecmd_init(void); | 221 | int aoecmd_init(void); |
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 00dfc5008ad4..a129f8c8073d 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
@@ -16,11 +16,19 @@ | |||
16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/export.h> | 18 | #include <linux/export.h> |
19 | #include <linux/moduleparam.h> | ||
20 | #include <scsi/sg.h> | ||
19 | #include "aoe.h" | 21 | #include "aoe.h" |
20 | 22 | ||
21 | static DEFINE_MUTEX(aoeblk_mutex); | 23 | static DEFINE_MUTEX(aoeblk_mutex); |
22 | static struct kmem_cache *buf_pool_cache; | 24 | static struct kmem_cache *buf_pool_cache; |
23 | 25 | ||
26 | /* GPFS needs a larger value than the default. */ | ||
27 | static int aoe_maxsectors; | ||
28 | module_param(aoe_maxsectors, int, 0644); | ||
29 | MODULE_PARM_DESC(aoe_maxsectors, | ||
30 | "When nonzero, set the maximum number of sectors per I/O request"); | ||
31 | |||
24 | static ssize_t aoedisk_show_state(struct device *dev, | 32 | static ssize_t aoedisk_show_state(struct device *dev, |
25 | struct device_attribute *attr, char *page) | 33 | struct device_attribute *attr, char *page) |
26 | { | 34 | { |
@@ -59,7 +67,7 @@ static ssize_t aoedisk_show_netif(struct device *dev, | |||
59 | nd = nds; | 67 | nd = nds; |
60 | ne = nd + ARRAY_SIZE(nds); | 68 | ne = nd + ARRAY_SIZE(nds); |
61 | t = d->targets; | 69 | t = d->targets; |
62 | te = t + NTARGETS; | 70 | te = t + d->ntargets; |
63 | for (; t < te && *t; t++) { | 71 | for (; t < te && *t; t++) { |
64 | ifp = (*t)->ifs; | 72 | ifp = (*t)->ifs; |
65 | e = ifp + NAOEIFS; | 73 | e = ifp + NAOEIFS; |
@@ -91,6 +99,14 @@ static ssize_t aoedisk_show_fwver(struct device *dev, | |||
91 | 99 | ||
92 | return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver); | 100 | return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver); |
93 | } | 101 | } |
102 | static ssize_t aoedisk_show_payload(struct device *dev, | ||
103 | struct device_attribute *attr, char *page) | ||
104 | { | ||
105 | struct gendisk *disk = dev_to_disk(dev); | ||
106 | struct aoedev *d = disk->private_data; | ||
107 | |||
108 | return snprintf(page, PAGE_SIZE, "%lu\n", d->maxbcnt); | ||
109 | } | ||
94 | 110 | ||
95 | static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL); | 111 | static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL); |
96 | static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL); | 112 | static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL); |
@@ -99,12 +115,14 @@ static struct device_attribute dev_attr_firmware_version = { | |||
99 | .attr = { .name = "firmware-version", .mode = S_IRUGO }, | 115 | .attr = { .name = "firmware-version", .mode = S_IRUGO }, |
100 | .show = aoedisk_show_fwver, | 116 | .show = aoedisk_show_fwver, |
101 | }; | 117 | }; |
118 | static DEVICE_ATTR(payload, S_IRUGO, aoedisk_show_payload, NULL); | ||
102 | 119 | ||
103 | static struct attribute *aoe_attrs[] = { | 120 | static struct attribute *aoe_attrs[] = { |
104 | &dev_attr_state.attr, | 121 | &dev_attr_state.attr, |
105 | &dev_attr_mac.attr, | 122 | &dev_attr_mac.attr, |
106 | &dev_attr_netif.attr, | 123 | &dev_attr_netif.attr, |
107 | &dev_attr_firmware_version.attr, | 124 | &dev_attr_firmware_version.attr, |
125 | &dev_attr_payload.attr, | ||
108 | NULL, | 126 | NULL, |
109 | }; | 127 | }; |
110 | 128 | ||
@@ -129,9 +147,18 @@ aoeblk_open(struct block_device *bdev, fmode_t mode) | |||
129 | struct aoedev *d = bdev->bd_disk->private_data; | 147 | struct aoedev *d = bdev->bd_disk->private_data; |
130 | ulong flags; | 148 | ulong flags; |
131 | 149 | ||
150 | if (!virt_addr_valid(d)) { | ||
151 | pr_crit("aoe: invalid device pointer in %s\n", | ||
152 | __func__); | ||
153 | WARN_ON(1); | ||
154 | return -ENODEV; | ||
155 | } | ||
156 | if (!(d->flags & DEVFL_UP) || d->flags & DEVFL_TKILL) | ||
157 | return -ENODEV; | ||
158 | |||
132 | mutex_lock(&aoeblk_mutex); | 159 | mutex_lock(&aoeblk_mutex); |
133 | spin_lock_irqsave(&d->lock, flags); | 160 | spin_lock_irqsave(&d->lock, flags); |
134 | if (d->flags & DEVFL_UP) { | 161 | if (d->flags & DEVFL_UP && !(d->flags & DEVFL_TKILL)) { |
135 | d->nopen++; | 162 | d->nopen++; |
136 | spin_unlock_irqrestore(&d->lock, flags); | 163 | spin_unlock_irqrestore(&d->lock, flags); |
137 | mutex_unlock(&aoeblk_mutex); | 164 | mutex_unlock(&aoeblk_mutex); |
@@ -195,9 +222,38 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
195 | return 0; | 222 | return 0; |
196 | } | 223 | } |
197 | 224 | ||
225 | static int | ||
226 | aoeblk_ioctl(struct block_device *bdev, fmode_t mode, uint cmd, ulong arg) | ||
227 | { | ||
228 | struct aoedev *d; | ||
229 | |||
230 | if (!arg) | ||
231 | return -EINVAL; | ||
232 | |||
233 | d = bdev->bd_disk->private_data; | ||
234 | if ((d->flags & DEVFL_UP) == 0) { | ||
235 | pr_err("aoe: disk not up\n"); | ||
236 | return -ENODEV; | ||
237 | } | ||
238 | |||
239 | if (cmd == HDIO_GET_IDENTITY) { | ||
240 | if (!copy_to_user((void __user *) arg, &d->ident, | ||
241 | sizeof(d->ident))) | ||
242 | return 0; | ||
243 | return -EFAULT; | ||
244 | } | ||
245 | |||
246 | /* udev calls scsi_id, which uses SG_IO, resulting in noise */ | ||
247 | if (cmd != SG_IO) | ||
248 | pr_info("aoe: unknown ioctl 0x%x\n", cmd); | ||
249 | |||
250 | return -ENOTTY; | ||
251 | } | ||
252 | |||
198 | static const struct block_device_operations aoe_bdops = { | 253 | static const struct block_device_operations aoe_bdops = { |
199 | .open = aoeblk_open, | 254 | .open = aoeblk_open, |
200 | .release = aoeblk_release, | 255 | .release = aoeblk_release, |
256 | .ioctl = aoeblk_ioctl, | ||
201 | .getgeo = aoeblk_getgeo, | 257 | .getgeo = aoeblk_getgeo, |
202 | .owner = THIS_MODULE, | 258 | .owner = THIS_MODULE, |
203 | }; | 259 | }; |
@@ -212,6 +268,18 @@ aoeblk_gdalloc(void *vp) | |||
212 | struct request_queue *q; | 268 | struct request_queue *q; |
213 | enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, }; | 269 | enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, }; |
214 | ulong flags; | 270 | ulong flags; |
271 | int late = 0; | ||
272 | |||
273 | spin_lock_irqsave(&d->lock, flags); | ||
274 | if (d->flags & DEVFL_GDALLOC | ||
275 | && !(d->flags & DEVFL_TKILL) | ||
276 | && !(d->flags & DEVFL_GD_NOW)) | ||
277 | d->flags |= DEVFL_GD_NOW; | ||
278 | else | ||
279 | late = 1; | ||
280 | spin_unlock_irqrestore(&d->lock, flags); | ||
281 | if (late) | ||
282 | return; | ||
215 | 283 | ||
216 | gd = alloc_disk(AOE_PARTITIONS); | 284 | gd = alloc_disk(AOE_PARTITIONS); |
217 | if (gd == NULL) { | 285 | if (gd == NULL) { |
@@ -231,23 +299,24 @@ aoeblk_gdalloc(void *vp) | |||
231 | if (q == NULL) { | 299 | if (q == NULL) { |
232 | pr_err("aoe: cannot allocate block queue for %ld.%d\n", | 300 | pr_err("aoe: cannot allocate block queue for %ld.%d\n", |
233 | d->aoemajor, d->aoeminor); | 301 | d->aoemajor, d->aoeminor); |
234 | mempool_destroy(mp); | 302 | goto err_mempool; |
235 | goto err_disk; | ||
236 | } | 303 | } |
237 | 304 | ||
238 | d->blkq = blk_alloc_queue(GFP_KERNEL); | ||
239 | if (!d->blkq) | ||
240 | goto err_mempool; | ||
241 | d->blkq->backing_dev_info.name = "aoe"; | ||
242 | if (bdi_init(&d->blkq->backing_dev_info)) | ||
243 | goto err_blkq; | ||
244 | spin_lock_irqsave(&d->lock, flags); | 305 | spin_lock_irqsave(&d->lock, flags); |
245 | blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); | 306 | WARN_ON(!(d->flags & DEVFL_GD_NOW)); |
307 | WARN_ON(!(d->flags & DEVFL_GDALLOC)); | ||
308 | WARN_ON(d->flags & DEVFL_TKILL); | ||
309 | WARN_ON(d->gd); | ||
310 | WARN_ON(d->flags & DEVFL_UP); | ||
311 | blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS); | ||
312 | q->backing_dev_info.name = "aoe"; | ||
246 | q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; | 313 | q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; |
247 | d->bufpool = mp; | 314 | d->bufpool = mp; |
248 | d->blkq = gd->queue = q; | 315 | d->blkq = gd->queue = q; |
249 | q->queuedata = d; | 316 | q->queuedata = d; |
250 | d->gd = gd; | 317 | d->gd = gd; |
318 | if (aoe_maxsectors) | ||
319 | blk_queue_max_hw_sectors(q, aoe_maxsectors); | ||
251 | gd->major = AOE_MAJOR; | 320 | gd->major = AOE_MAJOR; |
252 | gd->first_minor = d->sysminor; | 321 | gd->first_minor = d->sysminor; |
253 | gd->fops = &aoe_bdops; | 322 | gd->fops = &aoe_bdops; |
@@ -263,18 +332,21 @@ aoeblk_gdalloc(void *vp) | |||
263 | 332 | ||
264 | add_disk(gd); | 333 | add_disk(gd); |
265 | aoedisk_add_sysfs(d); | 334 | aoedisk_add_sysfs(d); |
335 | |||
336 | spin_lock_irqsave(&d->lock, flags); | ||
337 | WARN_ON(!(d->flags & DEVFL_GD_NOW)); | ||
338 | d->flags &= ~DEVFL_GD_NOW; | ||
339 | spin_unlock_irqrestore(&d->lock, flags); | ||
266 | return; | 340 | return; |
267 | 341 | ||
268 | err_blkq: | ||
269 | blk_cleanup_queue(d->blkq); | ||
270 | d->blkq = NULL; | ||
271 | err_mempool: | 342 | err_mempool: |
272 | mempool_destroy(d->bufpool); | 343 | mempool_destroy(mp); |
273 | err_disk: | 344 | err_disk: |
274 | put_disk(gd); | 345 | put_disk(gd); |
275 | err: | 346 | err: |
276 | spin_lock_irqsave(&d->lock, flags); | 347 | spin_lock_irqsave(&d->lock, flags); |
277 | d->flags &= ~DEVFL_GDALLOC; | 348 | d->flags &= ~DEVFL_GD_NOW; |
349 | schedule_work(&d->work); | ||
278 | spin_unlock_irqrestore(&d->lock, flags); | 350 | spin_unlock_irqrestore(&d->lock, flags); |
279 | } | 351 | } |
280 | 352 | ||
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index ed57a890c643..42e67ad6bd20 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -39,6 +39,11 @@ struct ErrMsg { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | static DEFINE_MUTEX(aoechr_mutex); | 41 | static DEFINE_MUTEX(aoechr_mutex); |
42 | |||
43 | /* A ring buffer of error messages, to be read through | ||
44 | * "/dev/etherd/err". When no messages are present, | ||
45 | * readers will block waiting for messages to appear. | ||
46 | */ | ||
42 | static struct ErrMsg emsgs[NMSG]; | 47 | static struct ErrMsg emsgs[NMSG]; |
43 | static int emsgs_head_idx, emsgs_tail_idx; | 48 | static int emsgs_head_idx, emsgs_tail_idx; |
44 | static struct completion emsgs_comp; | 49 | static struct completion emsgs_comp; |
@@ -282,7 +287,7 @@ aoechr_init(void) | |||
282 | int n, i; | 287 | int n, i; |
283 | 288 | ||
284 | n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); | 289 | n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); |
285 | if (n < 0) { | 290 | if (n < 0) { |
286 | printk(KERN_ERR "aoe: can't register char device\n"); | 291 | printk(KERN_ERR "aoe: can't register char device\n"); |
287 | return n; | 292 | return n; |
288 | } | 293 | } |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 9fe4f1865558..25ef5c014fca 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #define MAXIOC (8192) /* default meant to avoid most soft lockups */ | 22 | #define MAXIOC (8192) /* default meant to avoid most soft lockups */ |
23 | 23 | ||
24 | static void ktcomplete(struct frame *, struct sk_buff *); | 24 | static void ktcomplete(struct frame *, struct sk_buff *); |
25 | static int count_targets(struct aoedev *d, int *untainted); | ||
25 | 26 | ||
26 | static struct buf *nextbuf(struct aoedev *); | 27 | static struct buf *nextbuf(struct aoedev *); |
27 | 28 | ||
@@ -29,7 +30,7 @@ static int aoe_deadsecs = 60 * 3; | |||
29 | module_param(aoe_deadsecs, int, 0644); | 30 | module_param(aoe_deadsecs, int, 0644); |
30 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | 31 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); |
31 | 32 | ||
32 | static int aoe_maxout = 16; | 33 | static int aoe_maxout = 64; |
33 | module_param(aoe_maxout, int, 0644); | 34 | module_param(aoe_maxout, int, 0644); |
34 | MODULE_PARM_DESC(aoe_maxout, | 35 | MODULE_PARM_DESC(aoe_maxout, |
35 | "Only aoe_maxout outstanding packets for every MAC on eX.Y."); | 36 | "Only aoe_maxout outstanding packets for every MAC on eX.Y."); |
@@ -43,6 +44,8 @@ static struct { | |||
43 | spinlock_t lock; | 44 | spinlock_t lock; |
44 | } iocq; | 45 | } iocq; |
45 | 46 | ||
47 | static struct page *empty_page; | ||
48 | |||
46 | static struct sk_buff * | 49 | static struct sk_buff * |
47 | new_skb(ulong len) | 50 | new_skb(ulong len) |
48 | { | 51 | { |
@@ -59,6 +62,23 @@ new_skb(ulong len) | |||
59 | } | 62 | } |
60 | 63 | ||
61 | static struct frame * | 64 | static struct frame * |
65 | getframe_deferred(struct aoedev *d, u32 tag) | ||
66 | { | ||
67 | struct list_head *head, *pos, *nx; | ||
68 | struct frame *f; | ||
69 | |||
70 | head = &d->rexmitq; | ||
71 | list_for_each_safe(pos, nx, head) { | ||
72 | f = list_entry(pos, struct frame, head); | ||
73 | if (f->tag == tag) { | ||
74 | list_del(pos); | ||
75 | return f; | ||
76 | } | ||
77 | } | ||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | static struct frame * | ||
62 | getframe(struct aoedev *d, u32 tag) | 82 | getframe(struct aoedev *d, u32 tag) |
63 | { | 83 | { |
64 | struct frame *f; | 84 | struct frame *f; |
@@ -162,8 +182,10 @@ aoe_freetframe(struct frame *f) | |||
162 | 182 | ||
163 | t = f->t; | 183 | t = f->t; |
164 | f->buf = NULL; | 184 | f->buf = NULL; |
185 | f->lba = 0; | ||
165 | f->bv = NULL; | 186 | f->bv = NULL; |
166 | f->r_skb = NULL; | 187 | f->r_skb = NULL; |
188 | f->flags = 0; | ||
167 | list_add(&f->head, &t->ffree); | 189 | list_add(&f->head, &t->ffree); |
168 | } | 190 | } |
169 | 191 | ||
@@ -217,20 +239,25 @@ newframe(struct aoedev *d) | |||
217 | struct frame *f; | 239 | struct frame *f; |
218 | struct aoetgt *t, **tt; | 240 | struct aoetgt *t, **tt; |
219 | int totout = 0; | 241 | int totout = 0; |
242 | int use_tainted; | ||
243 | int has_untainted; | ||
220 | 244 | ||
221 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ | 245 | if (!d->targets || !d->targets[0]) { |
222 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); | 246 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); |
223 | return NULL; | 247 | return NULL; |
224 | } | 248 | } |
225 | tt = d->tgt; /* last used target */ | 249 | tt = d->tgt; /* last used target */ |
226 | for (;;) { | 250 | for (use_tainted = 0, has_untainted = 0;;) { |
227 | tt++; | 251 | tt++; |
228 | if (tt >= &d->targets[NTARGETS] || !*tt) | 252 | if (tt >= &d->targets[d->ntargets] || !*tt) |
229 | tt = d->targets; | 253 | tt = d->targets; |
230 | t = *tt; | 254 | t = *tt; |
231 | totout += t->nout; | 255 | if (!t->taint) { |
256 | has_untainted = 1; | ||
257 | totout += t->nout; | ||
258 | } | ||
232 | if (t->nout < t->maxout | 259 | if (t->nout < t->maxout |
233 | && t != d->htgt | 260 | && (use_tainted || !t->taint) |
234 | && t->ifp->nd) { | 261 | && t->ifp->nd) { |
235 | f = newtframe(d, t); | 262 | f = newtframe(d, t); |
236 | if (f) { | 263 | if (f) { |
@@ -239,8 +266,12 @@ newframe(struct aoedev *d) | |||
239 | return f; | 266 | return f; |
240 | } | 267 | } |
241 | } | 268 | } |
242 | if (tt == d->tgt) /* we've looped and found nada */ | 269 | if (tt == d->tgt) { /* we've looped and found nada */ |
243 | break; | 270 | if (!use_tainted && !has_untainted) |
271 | use_tainted = 1; | ||
272 | else | ||
273 | break; | ||
274 | } | ||
244 | } | 275 | } |
245 | if (totout == 0) { | 276 | if (totout == 0) { |
246 | d->kicked++; | 277 | d->kicked++; |
@@ -277,21 +308,68 @@ fhash(struct frame *f) | |||
277 | list_add_tail(&f->head, &d->factive[n]); | 308 | list_add_tail(&f->head, &d->factive[n]); |
278 | } | 309 | } |
279 | 310 | ||
311 | static void | ||
312 | ata_rw_frameinit(struct frame *f) | ||
313 | { | ||
314 | struct aoetgt *t; | ||
315 | struct aoe_hdr *h; | ||
316 | struct aoe_atahdr *ah; | ||
317 | struct sk_buff *skb; | ||
318 | char writebit, extbit; | ||
319 | |||
320 | skb = f->skb; | ||
321 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
322 | ah = (struct aoe_atahdr *) (h + 1); | ||
323 | skb_put(skb, sizeof(*h) + sizeof(*ah)); | ||
324 | memset(h, 0, skb->len); | ||
325 | |||
326 | writebit = 0x10; | ||
327 | extbit = 0x4; | ||
328 | |||
329 | t = f->t; | ||
330 | f->tag = aoehdr_atainit(t->d, t, h); | ||
331 | fhash(f); | ||
332 | t->nout++; | ||
333 | f->waited = 0; | ||
334 | f->waited_total = 0; | ||
335 | if (f->buf) | ||
336 | f->lba = f->buf->sector; | ||
337 | |||
338 | /* set up ata header */ | ||
339 | ah->scnt = f->bcnt >> 9; | ||
340 | put_lba(ah, f->lba); | ||
341 | if (t->d->flags & DEVFL_EXT) { | ||
342 | ah->aflags |= AOEAFL_EXT; | ||
343 | } else { | ||
344 | extbit = 0; | ||
345 | ah->lba3 &= 0x0f; | ||
346 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ | ||
347 | } | ||
348 | if (f->buf && bio_data_dir(f->buf->bio) == WRITE) { | ||
349 | skb_fillup(skb, f->bv, f->bv_off, f->bcnt); | ||
350 | ah->aflags |= AOEAFL_WRITE; | ||
351 | skb->len += f->bcnt; | ||
352 | skb->data_len = f->bcnt; | ||
353 | skb->truesize += f->bcnt; | ||
354 | t->wpkts++; | ||
355 | } else { | ||
356 | t->rpkts++; | ||
357 | writebit = 0; | ||
358 | } | ||
359 | |||
360 | ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; | ||
361 | skb->dev = t->ifp->nd; | ||
362 | } | ||
363 | |||
280 | static int | 364 | static int |
281 | aoecmd_ata_rw(struct aoedev *d) | 365 | aoecmd_ata_rw(struct aoedev *d) |
282 | { | 366 | { |
283 | struct frame *f; | 367 | struct frame *f; |
284 | struct aoe_hdr *h; | ||
285 | struct aoe_atahdr *ah; | ||
286 | struct buf *buf; | 368 | struct buf *buf; |
287 | struct aoetgt *t; | 369 | struct aoetgt *t; |
288 | struct sk_buff *skb; | 370 | struct sk_buff *skb; |
289 | struct sk_buff_head queue; | 371 | struct sk_buff_head queue; |
290 | ulong bcnt, fbcnt; | 372 | ulong bcnt, fbcnt; |
291 | char writebit, extbit; | ||
292 | |||
293 | writebit = 0x10; | ||
294 | extbit = 0x4; | ||
295 | 373 | ||
296 | buf = nextbuf(d); | 374 | buf = nextbuf(d); |
297 | if (buf == NULL) | 375 | if (buf == NULL) |
@@ -326,50 +404,18 @@ aoecmd_ata_rw(struct aoedev *d) | |||
326 | } while (fbcnt); | 404 | } while (fbcnt); |
327 | 405 | ||
328 | /* initialize the headers & frame */ | 406 | /* initialize the headers & frame */ |
329 | skb = f->skb; | ||
330 | h = (struct aoe_hdr *) skb_mac_header(skb); | ||
331 | ah = (struct aoe_atahdr *) (h+1); | ||
332 | skb_put(skb, sizeof *h + sizeof *ah); | ||
333 | memset(h, 0, skb->len); | ||
334 | f->tag = aoehdr_atainit(d, t, h); | ||
335 | fhash(f); | ||
336 | t->nout++; | ||
337 | f->waited = 0; | ||
338 | f->buf = buf; | 407 | f->buf = buf; |
339 | f->bcnt = bcnt; | 408 | f->bcnt = bcnt; |
340 | f->lba = buf->sector; | 409 | ata_rw_frameinit(f); |
341 | |||
342 | /* set up ata header */ | ||
343 | ah->scnt = bcnt >> 9; | ||
344 | put_lba(ah, buf->sector); | ||
345 | if (d->flags & DEVFL_EXT) { | ||
346 | ah->aflags |= AOEAFL_EXT; | ||
347 | } else { | ||
348 | extbit = 0; | ||
349 | ah->lba3 &= 0x0f; | ||
350 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ | ||
351 | } | ||
352 | if (bio_data_dir(buf->bio) == WRITE) { | ||
353 | skb_fillup(skb, f->bv, f->bv_off, bcnt); | ||
354 | ah->aflags |= AOEAFL_WRITE; | ||
355 | skb->len += bcnt; | ||
356 | skb->data_len = bcnt; | ||
357 | skb->truesize += bcnt; | ||
358 | t->wpkts++; | ||
359 | } else { | ||
360 | t->rpkts++; | ||
361 | writebit = 0; | ||
362 | } | ||
363 | |||
364 | ah->cmdstat = ATA_CMD_PIO_READ | writebit | extbit; | ||
365 | 410 | ||
366 | /* mark all tracking fields and load out */ | 411 | /* mark all tracking fields and load out */ |
367 | buf->nframesout += 1; | 412 | buf->nframesout += 1; |
368 | buf->sector += bcnt >> 9; | 413 | buf->sector += bcnt >> 9; |
369 | 414 | ||
370 | skb->dev = t->ifp->nd; | 415 | skb = skb_clone(f->skb, GFP_ATOMIC); |
371 | skb = skb_clone(skb, GFP_ATOMIC); | ||
372 | if (skb) { | 416 | if (skb) { |
417 | do_gettimeofday(&f->sent); | ||
418 | f->sent_jiffs = (u32) jiffies; | ||
373 | __skb_queue_head_init(&queue); | 419 | __skb_queue_head_init(&queue); |
374 | __skb_queue_tail(&queue, skb); | 420 | __skb_queue_tail(&queue, skb); |
375 | aoenet_xmit(&queue); | 421 | aoenet_xmit(&queue); |
@@ -442,11 +488,14 @@ resend(struct aoedev *d, struct frame *f) | |||
442 | h = (struct aoe_hdr *) skb_mac_header(skb); | 488 | h = (struct aoe_hdr *) skb_mac_header(skb); |
443 | ah = (struct aoe_atahdr *) (h+1); | 489 | ah = (struct aoe_atahdr *) (h+1); |
444 | 490 | ||
445 | snprintf(buf, sizeof buf, | 491 | if (!(f->flags & FFL_PROBE)) { |
446 | "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n", | 492 | snprintf(buf, sizeof(buf), |
447 | "retransmit", d->aoemajor, d->aoeminor, f->tag, jiffies, n, | 493 | "%15s e%ld.%d oldtag=%08x@%08lx newtag=%08x s=%pm d=%pm nout=%d\n", |
448 | h->src, h->dst, t->nout); | 494 | "retransmit", d->aoemajor, d->aoeminor, |
449 | aoechr_error(buf); | 495 | f->tag, jiffies, n, |
496 | h->src, h->dst, t->nout); | ||
497 | aoechr_error(buf); | ||
498 | } | ||
450 | 499 | ||
451 | f->tag = n; | 500 | f->tag = n; |
452 | fhash(f); | 501 | fhash(f); |
@@ -458,12 +507,46 @@ resend(struct aoedev *d, struct frame *f) | |||
458 | skb = skb_clone(skb, GFP_ATOMIC); | 507 | skb = skb_clone(skb, GFP_ATOMIC); |
459 | if (skb == NULL) | 508 | if (skb == NULL) |
460 | return; | 509 | return; |
510 | do_gettimeofday(&f->sent); | ||
511 | f->sent_jiffs = (u32) jiffies; | ||
461 | __skb_queue_head_init(&queue); | 512 | __skb_queue_head_init(&queue); |
462 | __skb_queue_tail(&queue, skb); | 513 | __skb_queue_tail(&queue, skb); |
463 | aoenet_xmit(&queue); | 514 | aoenet_xmit(&queue); |
464 | } | 515 | } |
465 | 516 | ||
466 | static int | 517 | static int |
518 | tsince_hr(struct frame *f) | ||
519 | { | ||
520 | struct timeval now; | ||
521 | int n; | ||
522 | |||
523 | do_gettimeofday(&now); | ||
524 | n = now.tv_usec - f->sent.tv_usec; | ||
525 | n += (now.tv_sec - f->sent.tv_sec) * USEC_PER_SEC; | ||
526 | |||
527 | if (n < 0) | ||
528 | n = -n; | ||
529 | |||
530 | /* For relatively long periods, use jiffies to avoid | ||
531 | * discrepancies caused by updates to the system time. | ||
532 | * | ||
533 | * On system with HZ of 1000, 32-bits is over 49 days | ||
534 | * worth of jiffies, or over 71 minutes worth of usecs. | ||
535 | * | ||
536 | * Jiffies overflow is handled by subtraction of unsigned ints: | ||
537 | * (gdb) print (unsigned) 2 - (unsigned) 0xfffffffe | ||
538 | * $3 = 4 | ||
539 | * (gdb) | ||
540 | */ | ||
541 | if (n > USEC_PER_SEC / 4) { | ||
542 | n = ((u32) jiffies) - f->sent_jiffs; | ||
543 | n *= USEC_PER_SEC / HZ; | ||
544 | } | ||
545 | |||
546 | return n; | ||
547 | } | ||
548 | |||
549 | static int | ||
467 | tsince(u32 tag) | 550 | tsince(u32 tag) |
468 | { | 551 | { |
469 | int n; | 552 | int n; |
@@ -472,7 +555,7 @@ tsince(u32 tag) | |||
472 | n -= tag & 0xffff; | 555 | n -= tag & 0xffff; |
473 | if (n < 0) | 556 | if (n < 0) |
474 | n += 1<<16; | 557 | n += 1<<16; |
475 | return n; | 558 | return jiffies_to_usecs(n + 1); |
476 | } | 559 | } |
477 | 560 | ||
478 | static struct aoeif * | 561 | static struct aoeif * |
@@ -503,70 +586,189 @@ ejectif(struct aoetgt *t, struct aoeif *ifp) | |||
503 | dev_put(nd); | 586 | dev_put(nd); |
504 | } | 587 | } |
505 | 588 | ||
506 | static int | 589 | static struct frame * |
507 | sthtith(struct aoedev *d) | 590 | reassign_frame(struct frame *f) |
508 | { | 591 | { |
509 | struct frame *f, *nf; | 592 | struct frame *nf; |
510 | struct list_head *nx, *pos, *head; | ||
511 | struct sk_buff *skb; | 593 | struct sk_buff *skb; |
512 | struct aoetgt *ht = d->htgt; | ||
513 | int i; | ||
514 | 594 | ||
515 | for (i = 0; i < NFACTIVE; i++) { | 595 | nf = newframe(f->t->d); |
516 | head = &d->factive[i]; | 596 | if (!nf) |
517 | list_for_each_safe(pos, nx, head) { | 597 | return NULL; |
518 | f = list_entry(pos, struct frame, head); | 598 | if (nf->t == f->t) { |
519 | if (f->t != ht) | 599 | aoe_freetframe(nf); |
520 | continue; | 600 | return NULL; |
601 | } | ||
521 | 602 | ||
522 | nf = newframe(d); | 603 | skb = nf->skb; |
523 | if (!nf) | 604 | nf->skb = f->skb; |
524 | return 0; | 605 | nf->buf = f->buf; |
606 | nf->bcnt = f->bcnt; | ||
607 | nf->lba = f->lba; | ||
608 | nf->bv = f->bv; | ||
609 | nf->bv_off = f->bv_off; | ||
610 | nf->waited = 0; | ||
611 | nf->waited_total = f->waited_total; | ||
612 | nf->sent = f->sent; | ||
613 | nf->sent_jiffs = f->sent_jiffs; | ||
614 | f->skb = skb; | ||
615 | |||
616 | return nf; | ||
617 | } | ||
525 | 618 | ||
526 | /* remove frame from active list */ | 619 | static void |
527 | list_del(pos); | 620 | probe(struct aoetgt *t) |
621 | { | ||
622 | struct aoedev *d; | ||
623 | struct frame *f; | ||
624 | struct sk_buff *skb; | ||
625 | struct sk_buff_head queue; | ||
626 | size_t n, m; | ||
627 | int frag; | ||
528 | 628 | ||
529 | /* reassign all pertinent bits to new outbound frame */ | 629 | d = t->d; |
530 | skb = nf->skb; | 630 | f = newtframe(d, t); |
531 | nf->skb = f->skb; | 631 | if (!f) { |
532 | nf->buf = f->buf; | 632 | pr_err("%s %pm for e%ld.%d: %s\n", |
533 | nf->bcnt = f->bcnt; | 633 | "aoe: cannot probe remote address", |
534 | nf->lba = f->lba; | 634 | t->addr, |
535 | nf->bv = f->bv; | 635 | (long) d->aoemajor, d->aoeminor, |
536 | nf->bv_off = f->bv_off; | 636 | "no frame available"); |
537 | nf->waited = 0; | 637 | return; |
538 | f->skb = skb; | 638 | } |
639 | f->flags |= FFL_PROBE; | ||
640 | ifrotate(t); | ||
641 | f->bcnt = t->d->maxbcnt ? t->d->maxbcnt : DEFAULTBCNT; | ||
642 | ata_rw_frameinit(f); | ||
643 | skb = f->skb; | ||
644 | for (frag = 0, n = f->bcnt; n > 0; ++frag, n -= m) { | ||
645 | if (n < PAGE_SIZE) | ||
646 | m = n; | ||
647 | else | ||
648 | m = PAGE_SIZE; | ||
649 | skb_fill_page_desc(skb, frag, empty_page, 0, m); | ||
650 | } | ||
651 | skb->len += f->bcnt; | ||
652 | skb->data_len = f->bcnt; | ||
653 | skb->truesize += f->bcnt; | ||
654 | |||
655 | skb = skb_clone(f->skb, GFP_ATOMIC); | ||
656 | if (skb) { | ||
657 | do_gettimeofday(&f->sent); | ||
658 | f->sent_jiffs = (u32) jiffies; | ||
659 | __skb_queue_head_init(&queue); | ||
660 | __skb_queue_tail(&queue, skb); | ||
661 | aoenet_xmit(&queue); | ||
662 | } | ||
663 | } | ||
664 | |||
665 | static long | ||
666 | rto(struct aoedev *d) | ||
667 | { | ||
668 | long t; | ||
669 | |||
670 | t = 2 * d->rttavg >> RTTSCALE; | ||
671 | t += 8 * d->rttdev >> RTTDSCALE; | ||
672 | if (t == 0) | ||
673 | t = 1; | ||
674 | |||
675 | return t; | ||
676 | } | ||
677 | |||
678 | static void | ||
679 | rexmit_deferred(struct aoedev *d) | ||
680 | { | ||
681 | struct aoetgt *t; | ||
682 | struct frame *f; | ||
683 | struct frame *nf; | ||
684 | struct list_head *pos, *nx, *head; | ||
685 | int since; | ||
686 | int untainted; | ||
687 | |||
688 | count_targets(d, &untainted); | ||
689 | |||
690 | head = &d->rexmitq; | ||
691 | list_for_each_safe(pos, nx, head) { | ||
692 | f = list_entry(pos, struct frame, head); | ||
693 | t = f->t; | ||
694 | if (t->taint) { | ||
695 | if (!(f->flags & FFL_PROBE)) { | ||
696 | nf = reassign_frame(f); | ||
697 | if (nf) { | ||
698 | if (t->nout_probes == 0 | ||
699 | && untainted > 0) { | ||
700 | probe(t); | ||
701 | t->nout_probes++; | ||
702 | } | ||
703 | list_replace(&f->head, &nf->head); | ||
704 | pos = &nf->head; | ||
705 | aoe_freetframe(f); | ||
706 | f = nf; | ||
707 | t = f->t; | ||
708 | } | ||
709 | } else if (untainted < 1) { | ||
710 | /* don't probe w/o other untainted aoetgts */ | ||
711 | goto stop_probe; | ||
712 | } else if (tsince_hr(f) < t->taint * rto(d)) { | ||
713 | /* reprobe slowly when taint is high */ | ||
714 | continue; | ||
715 | } | ||
716 | } else if (f->flags & FFL_PROBE) { | ||
717 | stop_probe: /* don't probe untainted aoetgts */ | ||
718 | list_del(pos); | ||
539 | aoe_freetframe(f); | 719 | aoe_freetframe(f); |
540 | ht->nout--; | 720 | /* leaving d->kicked, because this is routine */ |
541 | nf->t->nout++; | 721 | f->t->d->flags |= DEVFL_KICKME; |
542 | resend(d, nf); | 722 | continue; |
543 | } | 723 | } |
724 | if (t->nout >= t->maxout) | ||
725 | continue; | ||
726 | list_del(pos); | ||
727 | t->nout++; | ||
728 | if (f->flags & FFL_PROBE) | ||
729 | t->nout_probes++; | ||
730 | since = tsince_hr(f); | ||
731 | f->waited += since; | ||
732 | f->waited_total += since; | ||
733 | resend(d, f); | ||
544 | } | 734 | } |
545 | /* We've cleaned up the outstanding so take away his | ||
546 | * interfaces so he won't be used. We should remove him from | ||
547 | * the target array here, but cleaning up a target is | ||
548 | * involved. PUNT! | ||
549 | */ | ||
550 | memset(ht->ifs, 0, sizeof ht->ifs); | ||
551 | d->htgt = NULL; | ||
552 | return 1; | ||
553 | } | 735 | } |
554 | 736 | ||
555 | static inline unsigned char | 737 | /* An aoetgt accumulates demerits quickly, and successful |
556 | ata_scnt(unsigned char *packet) { | 738 | * probing redeems the aoetgt slowly. |
557 | struct aoe_hdr *h; | 739 | */ |
558 | struct aoe_atahdr *ah; | 740 | static void |
741 | scorn(struct aoetgt *t) | ||
742 | { | ||
743 | int n; | ||
559 | 744 | ||
560 | h = (struct aoe_hdr *) packet; | 745 | n = t->taint++; |
561 | ah = (struct aoe_atahdr *) (h+1); | 746 | t->taint += t->taint * 2; |
562 | return ah->scnt; | 747 | if (n > t->taint) |
748 | t->taint = n; | ||
749 | if (t->taint > MAX_TAINT) | ||
750 | t->taint = MAX_TAINT; | ||
751 | } | ||
752 | |||
753 | static int | ||
754 | count_targets(struct aoedev *d, int *untainted) | ||
755 | { | ||
756 | int i, good; | ||
757 | |||
758 | for (i = good = 0; i < d->ntargets && d->targets[i]; ++i) | ||
759 | if (d->targets[i]->taint == 0) | ||
760 | good++; | ||
761 | |||
762 | if (untainted) | ||
763 | *untainted = good; | ||
764 | return i; | ||
563 | } | 765 | } |
564 | 766 | ||
565 | static void | 767 | static void |
566 | rexmit_timer(ulong vp) | 768 | rexmit_timer(ulong vp) |
567 | { | 769 | { |
568 | struct aoedev *d; | 770 | struct aoedev *d; |
569 | struct aoetgt *t, **tt, **te; | 771 | struct aoetgt *t; |
570 | struct aoeif *ifp; | 772 | struct aoeif *ifp; |
571 | struct frame *f; | 773 | struct frame *f; |
572 | struct list_head *head, *pos, *nx; | 774 | struct list_head *head, *pos, *nx; |
@@ -574,15 +776,18 @@ rexmit_timer(ulong vp) | |||
574 | register long timeout; | 776 | register long timeout; |
575 | ulong flags, n; | 777 | ulong flags, n; |
576 | int i; | 778 | int i; |
779 | int utgts; /* number of aoetgt descriptors (not slots) */ | ||
780 | int since; | ||
577 | 781 | ||
578 | d = (struct aoedev *) vp; | 782 | d = (struct aoedev *) vp; |
579 | 783 | ||
580 | /* timeout is always ~150% of the moving average */ | ||
581 | timeout = d->rttavg; | ||
582 | timeout += timeout >> 1; | ||
583 | |||
584 | spin_lock_irqsave(&d->lock, flags); | 784 | spin_lock_irqsave(&d->lock, flags); |
585 | 785 | ||
786 | /* timeout based on observed timings and variations */ | ||
787 | timeout = rto(d); | ||
788 | |||
789 | utgts = count_targets(d, NULL); | ||
790 | |||
586 | if (d->flags & DEVFL_TKILL) { | 791 | if (d->flags & DEVFL_TKILL) { |
587 | spin_unlock_irqrestore(&d->lock, flags); | 792 | spin_unlock_irqrestore(&d->lock, flags); |
588 | return; | 793 | return; |
@@ -593,67 +798,61 @@ rexmit_timer(ulong vp) | |||
593 | head = &d->factive[i]; | 798 | head = &d->factive[i]; |
594 | list_for_each_safe(pos, nx, head) { | 799 | list_for_each_safe(pos, nx, head) { |
595 | f = list_entry(pos, struct frame, head); | 800 | f = list_entry(pos, struct frame, head); |
596 | if (tsince(f->tag) < timeout) | 801 | if (tsince_hr(f) < timeout) |
597 | break; /* end of expired frames */ | 802 | break; /* end of expired frames */ |
598 | /* move to flist for later processing */ | 803 | /* move to flist for later processing */ |
599 | list_move_tail(pos, &flist); | 804 | list_move_tail(pos, &flist); |
600 | } | 805 | } |
601 | } | 806 | } |
602 | /* window check */ | ||
603 | tt = d->targets; | ||
604 | te = tt + d->ntargets; | ||
605 | for (; tt < te && (t = *tt); tt++) { | ||
606 | if (t->nout == t->maxout | ||
607 | && t->maxout < t->nframes | ||
608 | && (jiffies - t->lastwadj)/HZ > 10) { | ||
609 | t->maxout++; | ||
610 | t->lastwadj = jiffies; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | if (!list_empty(&flist)) { /* retransmissions necessary */ | ||
615 | n = d->rttavg <<= 1; | ||
616 | if (n > MAXTIMER) | ||
617 | d->rttavg = MAXTIMER; | ||
618 | } | ||
619 | 807 | ||
620 | /* process expired frames */ | 808 | /* process expired frames */ |
621 | while (!list_empty(&flist)) { | 809 | while (!list_empty(&flist)) { |
622 | pos = flist.next; | 810 | pos = flist.next; |
623 | f = list_entry(pos, struct frame, head); | 811 | f = list_entry(pos, struct frame, head); |
624 | n = f->waited += timeout; | 812 | since = tsince_hr(f); |
625 | n /= HZ; | 813 | n = f->waited_total + since; |
626 | if (n > aoe_deadsecs) { | 814 | n /= USEC_PER_SEC; |
815 | if (aoe_deadsecs | ||
816 | && n > aoe_deadsecs | ||
817 | && !(f->flags & FFL_PROBE)) { | ||
627 | /* Waited too long. Device failure. | 818 | /* Waited too long. Device failure. |
628 | * Hang all frames on first hash bucket for downdev | 819 | * Hang all frames on first hash bucket for downdev |
629 | * to clean up. | 820 | * to clean up. |
630 | */ | 821 | */ |
631 | list_splice(&flist, &d->factive[0]); | 822 | list_splice(&flist, &d->factive[0]); |
632 | aoedev_downdev(d); | 823 | aoedev_downdev(d); |
633 | break; | 824 | goto out; |
634 | } | 825 | } |
635 | list_del(pos); | ||
636 | 826 | ||
637 | t = f->t; | 827 | t = f->t; |
638 | if (n > aoe_deadsecs/2) | 828 | n = f->waited + since; |
639 | d->htgt = t; /* see if another target can help */ | 829 | n /= USEC_PER_SEC; |
640 | 830 | if (aoe_deadsecs && utgts > 0 | |
641 | if (t->nout == t->maxout) { | 831 | && (n > aoe_deadsecs / utgts || n > HARD_SCORN_SECS)) |
642 | if (t->maxout > 1) | 832 | scorn(t); /* avoid this target */ |
643 | t->maxout--; | 833 | |
644 | t->lastwadj = jiffies; | 834 | if (t->maxout != 1) { |
835 | t->ssthresh = t->maxout / 2; | ||
836 | t->maxout = 1; | ||
645 | } | 837 | } |
646 | 838 | ||
647 | ifp = getif(t, f->skb->dev); | 839 | if (f->flags & FFL_PROBE) { |
648 | if (ifp && ++ifp->lost > (t->nframes << 1) | 840 | t->nout_probes--; |
649 | && (ifp != t->ifs || t->ifs[1].nd)) { | 841 | } else { |
650 | ejectif(t, ifp); | 842 | ifp = getif(t, f->skb->dev); |
651 | ifp = NULL; | 843 | if (ifp && ++ifp->lost > (t->nframes << 1) |
844 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
845 | ejectif(t, ifp); | ||
846 | ifp = NULL; | ||
847 | } | ||
652 | } | 848 | } |
653 | resend(d, f); | 849 | list_move_tail(pos, &d->rexmitq); |
850 | t->nout--; | ||
654 | } | 851 | } |
852 | rexmit_deferred(d); | ||
655 | 853 | ||
656 | if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) { | 854 | out: |
855 | if ((d->flags & DEVFL_KICKME) && d->blkq) { | ||
657 | d->flags &= ~DEVFL_KICKME; | 856 | d->flags &= ~DEVFL_KICKME; |
658 | d->blkq->request_fn(d->blkq); | 857 | d->blkq->request_fn(d->blkq); |
659 | } | 858 | } |
@@ -774,8 +973,7 @@ nextbuf(struct aoedev *d) | |||
774 | void | 973 | void |
775 | aoecmd_work(struct aoedev *d) | 974 | aoecmd_work(struct aoedev *d) |
776 | { | 975 | { |
777 | if (d->htgt && !sthtith(d)) | 976 | rexmit_deferred(d); |
778 | return; | ||
779 | while (aoecmd_ata_rw(d)) | 977 | while (aoecmd_ata_rw(d)) |
780 | ; | 978 | ; |
781 | } | 979 | } |
@@ -809,6 +1007,17 @@ aoecmd_sleepwork(struct work_struct *work) | |||
809 | } | 1007 | } |
810 | 1008 | ||
811 | static void | 1009 | static void |
1010 | ata_ident_fixstring(u16 *id, int ns) | ||
1011 | { | ||
1012 | u16 s; | ||
1013 | |||
1014 | while (ns-- > 0) { | ||
1015 | s = *id; | ||
1016 | *id++ = s >> 8 | s << 8; | ||
1017 | } | ||
1018 | } | ||
1019 | |||
1020 | static void | ||
812 | ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) | 1021 | ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) |
813 | { | 1022 | { |
814 | u64 ssize; | 1023 | u64 ssize; |
@@ -843,6 +1052,11 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) | |||
843 | d->geo.sectors = get_unaligned_le16(&id[56 << 1]); | 1052 | d->geo.sectors = get_unaligned_le16(&id[56 << 1]); |
844 | } | 1053 | } |
845 | 1054 | ||
1055 | ata_ident_fixstring((u16 *) &id[10<<1], 10); /* serial */ | ||
1056 | ata_ident_fixstring((u16 *) &id[23<<1], 4); /* firmware */ | ||
1057 | ata_ident_fixstring((u16 *) &id[27<<1], 20); /* model */ | ||
1058 | memcpy(d->ident, id, sizeof(d->ident)); | ||
1059 | |||
846 | if (d->ssize != ssize) | 1060 | if (d->ssize != ssize) |
847 | printk(KERN_INFO | 1061 | printk(KERN_INFO |
848 | "aoe: %pm e%ld.%d v%04x has %llu sectors\n", | 1062 | "aoe: %pm e%ld.%d v%04x has %llu sectors\n", |
@@ -862,26 +1076,28 @@ ataid_complete(struct aoedev *d, struct aoetgt *t, unsigned char *id) | |||
862 | } | 1076 | } |
863 | 1077 | ||
864 | static void | 1078 | static void |
865 | calc_rttavg(struct aoedev *d, int rtt) | 1079 | calc_rttavg(struct aoedev *d, struct aoetgt *t, int rtt) |
866 | { | 1080 | { |
867 | register long n; | 1081 | register long n; |
868 | 1082 | ||
869 | n = rtt; | 1083 | n = rtt; |
870 | if (n < 0) { | 1084 | |
871 | n = -rtt; | 1085 | /* cf. Congestion Avoidance and Control, Jacobson & Karels, 1988 */ |
872 | if (n < MINTIMER) | 1086 | n -= d->rttavg >> RTTSCALE; |
873 | n = MINTIMER; | 1087 | d->rttavg += n; |
874 | else if (n > MAXTIMER) | 1088 | if (n < 0) |
875 | n = MAXTIMER; | 1089 | n = -n; |
876 | d->mintimer += (n - d->mintimer) >> 1; | 1090 | n -= d->rttdev >> RTTDSCALE; |
877 | } else if (n < d->mintimer) | 1091 | d->rttdev += n; |
878 | n = d->mintimer; | 1092 | |
879 | else if (n > MAXTIMER) | 1093 | if (!t || t->maxout >= t->nframes) |
880 | n = MAXTIMER; | 1094 | return; |
881 | 1095 | if (t->maxout < t->ssthresh) | |
882 | /* g == .25; cf. Congestion Avoidance and Control, Jacobson & Karels; 1988 */ | 1096 | t->maxout += 1; |
883 | n -= d->rttavg; | 1097 | else if (t->nout == t->maxout && t->next_cwnd-- == 0) { |
884 | d->rttavg += n >> 2; | 1098 | t->maxout += 1; |
1099 | t->next_cwnd = t->maxout; | ||
1100 | } | ||
885 | } | 1101 | } |
886 | 1102 | ||
887 | static struct aoetgt * | 1103 | static struct aoetgt * |
@@ -890,7 +1106,7 @@ gettgt(struct aoedev *d, char *addr) | |||
890 | struct aoetgt **t, **e; | 1106 | struct aoetgt **t, **e; |
891 | 1107 | ||
892 | t = d->targets; | 1108 | t = d->targets; |
893 | e = t + NTARGETS; | 1109 | e = t + d->ntargets; |
894 | for (; t < e && *t; t++) | 1110 | for (; t < e && *t; t++) |
895 | if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0) | 1111 | if (memcmp((*t)->addr, addr, sizeof((*t)->addr)) == 0) |
896 | return *t; | 1112 | return *t; |
@@ -966,19 +1182,22 @@ ktiocomplete(struct frame *f) | |||
966 | struct aoeif *ifp; | 1182 | struct aoeif *ifp; |
967 | struct aoedev *d; | 1183 | struct aoedev *d; |
968 | long n; | 1184 | long n; |
1185 | int untainted; | ||
969 | 1186 | ||
970 | if (f == NULL) | 1187 | if (f == NULL) |
971 | return; | 1188 | return; |
972 | 1189 | ||
973 | t = f->t; | 1190 | t = f->t; |
974 | d = t->d; | 1191 | d = t->d; |
1192 | skb = f->r_skb; | ||
1193 | buf = f->buf; | ||
1194 | if (f->flags & FFL_PROBE) | ||
1195 | goto out; | ||
1196 | if (!skb) /* just fail the buf. */ | ||
1197 | goto noskb; | ||
975 | 1198 | ||
976 | hout = (struct aoe_hdr *) skb_mac_header(f->skb); | 1199 | hout = (struct aoe_hdr *) skb_mac_header(f->skb); |
977 | ahout = (struct aoe_atahdr *) (hout+1); | 1200 | ahout = (struct aoe_atahdr *) (hout+1); |
978 | buf = f->buf; | ||
979 | skb = f->r_skb; | ||
980 | if (skb == NULL) | ||
981 | goto noskb; /* just fail the buf. */ | ||
982 | 1201 | ||
983 | hin = (struct aoe_hdr *) skb->data; | 1202 | hin = (struct aoe_hdr *) skb->data; |
984 | skb_pull(skb, sizeof(*hin)); | 1203 | skb_pull(skb, sizeof(*hin)); |
@@ -988,9 +1207,9 @@ ktiocomplete(struct frame *f) | |||
988 | pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", | 1207 | pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", |
989 | ahout->cmdstat, ahin->cmdstat, | 1208 | ahout->cmdstat, ahin->cmdstat, |
990 | d->aoemajor, d->aoeminor); | 1209 | d->aoemajor, d->aoeminor); |
991 | noskb: if (buf) | 1210 | noskb: if (buf) |
992 | clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); | 1211 | clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); |
993 | goto badrsp; | 1212 | goto out; |
994 | } | 1213 | } |
995 | 1214 | ||
996 | n = ahout->scnt << 9; | 1215 | n = ahout->scnt << 9; |
@@ -998,8 +1217,10 @@ noskb: if (buf) | |||
998 | case ATA_CMD_PIO_READ: | 1217 | case ATA_CMD_PIO_READ: |
999 | case ATA_CMD_PIO_READ_EXT: | 1218 | case ATA_CMD_PIO_READ_EXT: |
1000 | if (skb->len < n) { | 1219 | if (skb->len < n) { |
1001 | pr_err("aoe: runt data size in read. skb->len=%d need=%ld\n", | 1220 | pr_err("%s e%ld.%d. skb->len=%d need=%ld\n", |
1002 | skb->len, n); | 1221 | "aoe: runt data size in read from", |
1222 | (long) d->aoemajor, d->aoeminor, | ||
1223 | skb->len, n); | ||
1003 | clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); | 1224 | clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); |
1004 | break; | 1225 | break; |
1005 | } | 1226 | } |
@@ -1010,13 +1231,13 @@ noskb: if (buf) | |||
1010 | ifp = getif(t, skb->dev); | 1231 | ifp = getif(t, skb->dev); |
1011 | if (ifp) | 1232 | if (ifp) |
1012 | ifp->lost = 0; | 1233 | ifp->lost = 0; |
1013 | if (d->htgt == t) /* I'll help myself, thank you. */ | ||
1014 | d->htgt = NULL; | ||
1015 | spin_unlock_irq(&d->lock); | 1234 | spin_unlock_irq(&d->lock); |
1016 | break; | 1235 | break; |
1017 | case ATA_CMD_ID_ATA: | 1236 | case ATA_CMD_ID_ATA: |
1018 | if (skb->len < 512) { | 1237 | if (skb->len < 512) { |
1019 | pr_info("aoe: runt data size in ataid. skb->len=%d\n", | 1238 | pr_info("%s e%ld.%d. skb->len=%d need=512\n", |
1239 | "aoe: runt data size in ataid from", | ||
1240 | (long) d->aoemajor, d->aoeminor, | ||
1020 | skb->len); | 1241 | skb->len); |
1021 | break; | 1242 | break; |
1022 | } | 1243 | } |
@@ -1032,16 +1253,23 @@ noskb: if (buf) | |||
1032 | be16_to_cpu(get_unaligned(&hin->major)), | 1253 | be16_to_cpu(get_unaligned(&hin->major)), |
1033 | hin->minor); | 1254 | hin->minor); |
1034 | } | 1255 | } |
1035 | badrsp: | 1256 | out: |
1036 | spin_lock_irq(&d->lock); | 1257 | spin_lock_irq(&d->lock); |
1258 | if (t->taint > 0 | ||
1259 | && --t->taint > 0 | ||
1260 | && t->nout_probes == 0) { | ||
1261 | count_targets(d, &untainted); | ||
1262 | if (untainted > 0) { | ||
1263 | probe(t); | ||
1264 | t->nout_probes++; | ||
1265 | } | ||
1266 | } | ||
1037 | 1267 | ||
1038 | aoe_freetframe(f); | 1268 | aoe_freetframe(f); |
1039 | 1269 | ||
1040 | if (buf && --buf->nframesout == 0 && buf->resid == 0) | 1270 | if (buf && --buf->nframesout == 0 && buf->resid == 0) |
1041 | aoe_end_buf(d, buf); | 1271 | aoe_end_buf(d, buf); |
1042 | 1272 | ||
1043 | aoecmd_work(d); | ||
1044 | |||
1045 | spin_unlock_irq(&d->lock); | 1273 | spin_unlock_irq(&d->lock); |
1046 | aoedev_put(d); | 1274 | aoedev_put(d); |
1047 | dev_kfree_skb(skb); | 1275 | dev_kfree_skb(skb); |
@@ -1141,7 +1369,6 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
1141 | struct aoedev *d; | 1369 | struct aoedev *d; |
1142 | struct aoe_hdr *h; | 1370 | struct aoe_hdr *h; |
1143 | struct frame *f; | 1371 | struct frame *f; |
1144 | struct aoetgt *t; | ||
1145 | u32 n; | 1372 | u32 n; |
1146 | ulong flags; | 1373 | ulong flags; |
1147 | char ebuf[128]; | 1374 | char ebuf[128]; |
@@ -1162,23 +1389,32 @@ aoecmd_ata_rsp(struct sk_buff *skb) | |||
1162 | 1389 | ||
1163 | n = be32_to_cpu(get_unaligned(&h->tag)); | 1390 | n = be32_to_cpu(get_unaligned(&h->tag)); |
1164 | f = getframe(d, n); | 1391 | f = getframe(d, n); |
1165 | if (f == NULL) { | 1392 | if (f) { |
1166 | calc_rttavg(d, -tsince(n)); | 1393 | calc_rttavg(d, f->t, tsince_hr(f)); |
1167 | spin_unlock_irqrestore(&d->lock, flags); | 1394 | f->t->nout--; |
1168 | aoedev_put(d); | 1395 | if (f->flags & FFL_PROBE) |
1169 | snprintf(ebuf, sizeof ebuf, | 1396 | f->t->nout_probes--; |
1170 | "%15s e%d.%d tag=%08x@%08lx\n", | 1397 | } else { |
1171 | "unexpected rsp", | 1398 | f = getframe_deferred(d, n); |
1172 | get_unaligned_be16(&h->major), | 1399 | if (f) { |
1173 | h->minor, | 1400 | calc_rttavg(d, NULL, tsince_hr(f)); |
1174 | get_unaligned_be32(&h->tag), | 1401 | } else { |
1175 | jiffies); | 1402 | calc_rttavg(d, NULL, tsince(n)); |
1176 | aoechr_error(ebuf); | 1403 | spin_unlock_irqrestore(&d->lock, flags); |
1177 | return skb; | 1404 | aoedev_put(d); |
1405 | snprintf(ebuf, sizeof(ebuf), | ||
1406 | "%15s e%d.%d tag=%08x@%08lx s=%pm d=%pm\n", | ||
1407 | "unexpected rsp", | ||
1408 | get_unaligned_be16(&h->major), | ||
1409 | h->minor, | ||
1410 | get_unaligned_be32(&h->tag), | ||
1411 | jiffies, | ||
1412 | h->src, | ||
1413 | h->dst); | ||
1414 | aoechr_error(ebuf); | ||
1415 | return skb; | ||
1416 | } | ||
1178 | } | 1417 | } |
1179 | t = f->t; | ||
1180 | calc_rttavg(d, tsince(f->tag)); | ||
1181 | t->nout--; | ||
1182 | aoecmd_work(d); | 1418 | aoecmd_work(d); |
1183 | 1419 | ||
1184 | spin_unlock_irqrestore(&d->lock, flags); | 1420 | spin_unlock_irqrestore(&d->lock, flags); |
@@ -1201,7 +1437,7 @@ aoecmd_cfg(ushort aoemajor, unsigned char aoeminor) | |||
1201 | aoecmd_cfg_pkts(aoemajor, aoeminor, &queue); | 1437 | aoecmd_cfg_pkts(aoemajor, aoeminor, &queue); |
1202 | aoenet_xmit(&queue); | 1438 | aoenet_xmit(&queue); |
1203 | } | 1439 | } |
1204 | 1440 | ||
1205 | struct sk_buff * | 1441 | struct sk_buff * |
1206 | aoecmd_ata_id(struct aoedev *d) | 1442 | aoecmd_ata_id(struct aoedev *d) |
1207 | { | 1443 | { |
@@ -1227,6 +1463,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
1227 | fhash(f); | 1463 | fhash(f); |
1228 | t->nout++; | 1464 | t->nout++; |
1229 | f->waited = 0; | 1465 | f->waited = 0; |
1466 | f->waited_total = 0; | ||
1230 | 1467 | ||
1231 | /* set up ata header */ | 1468 | /* set up ata header */ |
1232 | ah->scnt = 1; | 1469 | ah->scnt = 1; |
@@ -1235,41 +1472,69 @@ aoecmd_ata_id(struct aoedev *d) | |||
1235 | 1472 | ||
1236 | skb->dev = t->ifp->nd; | 1473 | skb->dev = t->ifp->nd; |
1237 | 1474 | ||
1238 | d->rttavg = MAXTIMER; | 1475 | d->rttavg = RTTAVG_INIT; |
1476 | d->rttdev = RTTDEV_INIT; | ||
1239 | d->timer.function = rexmit_timer; | 1477 | d->timer.function = rexmit_timer; |
1240 | 1478 | ||
1241 | return skb_clone(skb, GFP_ATOMIC); | 1479 | skb = skb_clone(skb, GFP_ATOMIC); |
1480 | if (skb) { | ||
1481 | do_gettimeofday(&f->sent); | ||
1482 | f->sent_jiffs = (u32) jiffies; | ||
1483 | } | ||
1484 | |||
1485 | return skb; | ||
1242 | } | 1486 | } |
1243 | 1487 | ||
1488 | static struct aoetgt ** | ||
1489 | grow_targets(struct aoedev *d) | ||
1490 | { | ||
1491 | ulong oldn, newn; | ||
1492 | struct aoetgt **tt; | ||
1493 | |||
1494 | oldn = d->ntargets; | ||
1495 | newn = oldn * 2; | ||
1496 | tt = kcalloc(newn, sizeof(*d->targets), GFP_ATOMIC); | ||
1497 | if (!tt) | ||
1498 | return NULL; | ||
1499 | memmove(tt, d->targets, sizeof(*d->targets) * oldn); | ||
1500 | d->tgt = tt + (d->tgt - d->targets); | ||
1501 | kfree(d->targets); | ||
1502 | d->targets = tt; | ||
1503 | d->ntargets = newn; | ||
1504 | |||
1505 | return &d->targets[oldn]; | ||
1506 | } | ||
1507 | |||
1244 | static struct aoetgt * | 1508 | static struct aoetgt * |
1245 | addtgt(struct aoedev *d, char *addr, ulong nframes) | 1509 | addtgt(struct aoedev *d, char *addr, ulong nframes) |
1246 | { | 1510 | { |
1247 | struct aoetgt *t, **tt, **te; | 1511 | struct aoetgt *t, **tt, **te; |
1248 | 1512 | ||
1249 | tt = d->targets; | 1513 | tt = d->targets; |
1250 | te = tt + NTARGETS; | 1514 | te = tt + d->ntargets; |
1251 | for (; tt < te && *tt; tt++) | 1515 | for (; tt < te && *tt; tt++) |
1252 | ; | 1516 | ; |
1253 | 1517 | ||
1254 | if (tt == te) { | 1518 | if (tt == te) { |
1255 | printk(KERN_INFO | 1519 | tt = grow_targets(d); |
1256 | "aoe: device addtgt failure; too many targets\n"); | 1520 | if (!tt) |
1257 | return NULL; | 1521 | goto nomem; |
1258 | } | 1522 | } |
1259 | t = kzalloc(sizeof(*t), GFP_ATOMIC); | 1523 | t = kzalloc(sizeof(*t), GFP_ATOMIC); |
1260 | if (!t) { | 1524 | if (!t) |
1261 | printk(KERN_INFO "aoe: cannot allocate memory to add target\n"); | 1525 | goto nomem; |
1262 | return NULL; | ||
1263 | } | ||
1264 | |||
1265 | d->ntargets++; | ||
1266 | t->nframes = nframes; | 1526 | t->nframes = nframes; |
1267 | t->d = d; | 1527 | t->d = d; |
1268 | memcpy(t->addr, addr, sizeof t->addr); | 1528 | memcpy(t->addr, addr, sizeof t->addr); |
1269 | t->ifp = t->ifs; | 1529 | t->ifp = t->ifs; |
1270 | t->maxout = t->nframes; | 1530 | aoecmd_wreset(t); |
1531 | t->maxout = t->nframes / 2; | ||
1271 | INIT_LIST_HEAD(&t->ffree); | 1532 | INIT_LIST_HEAD(&t->ffree); |
1272 | return *tt = t; | 1533 | return *tt = t; |
1534 | |||
1535 | nomem: | ||
1536 | pr_info("aoe: cannot allocate memory to add target\n"); | ||
1537 | return NULL; | ||
1273 | } | 1538 | } |
1274 | 1539 | ||
1275 | static void | 1540 | static void |
@@ -1279,7 +1544,7 @@ setdbcnt(struct aoedev *d) | |||
1279 | int bcnt = 0; | 1544 | int bcnt = 0; |
1280 | 1545 | ||
1281 | t = d->targets; | 1546 | t = d->targets; |
1282 | e = t + NTARGETS; | 1547 | e = t + d->ntargets; |
1283 | for (; t < e && *t; t++) | 1548 | for (; t < e && *t; t++) |
1284 | if (bcnt == 0 || bcnt > (*t)->minbcnt) | 1549 | if (bcnt == 0 || bcnt > (*t)->minbcnt) |
1285 | bcnt = (*t)->minbcnt; | 1550 | bcnt = (*t)->minbcnt; |
@@ -1373,7 +1638,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
1373 | spin_lock_irqsave(&d->lock, flags); | 1638 | spin_lock_irqsave(&d->lock, flags); |
1374 | 1639 | ||
1375 | t = gettgt(d, h->src); | 1640 | t = gettgt(d, h->src); |
1376 | if (!t) { | 1641 | if (t) { |
1642 | t->nframes = n; | ||
1643 | if (n < t->maxout) | ||
1644 | aoecmd_wreset(t); | ||
1645 | } else { | ||
1377 | t = addtgt(d, h->src, n); | 1646 | t = addtgt(d, h->src, n); |
1378 | if (!t) | 1647 | if (!t) |
1379 | goto bail; | 1648 | goto bail; |
@@ -1402,17 +1671,26 @@ bail: | |||
1402 | } | 1671 | } |
1403 | 1672 | ||
1404 | void | 1673 | void |
1674 | aoecmd_wreset(struct aoetgt *t) | ||
1675 | { | ||
1676 | t->maxout = 1; | ||
1677 | t->ssthresh = t->nframes / 2; | ||
1678 | t->next_cwnd = t->nframes; | ||
1679 | } | ||
1680 | |||
1681 | void | ||
1405 | aoecmd_cleanslate(struct aoedev *d) | 1682 | aoecmd_cleanslate(struct aoedev *d) |
1406 | { | 1683 | { |
1407 | struct aoetgt **t, **te; | 1684 | struct aoetgt **t, **te; |
1408 | 1685 | ||
1409 | d->mintimer = MINTIMER; | 1686 | d->rttavg = RTTAVG_INIT; |
1687 | d->rttdev = RTTDEV_INIT; | ||
1410 | d->maxbcnt = 0; | 1688 | d->maxbcnt = 0; |
1411 | 1689 | ||
1412 | t = d->targets; | 1690 | t = d->targets; |
1413 | te = t + NTARGETS; | 1691 | te = t + d->ntargets; |
1414 | for (; t < te && *t; t++) | 1692 | for (; t < te && *t; t++) |
1415 | (*t)->maxout = (*t)->nframes; | 1693 | aoecmd_wreset(*t); |
1416 | } | 1694 | } |
1417 | 1695 | ||
1418 | void | 1696 | void |
@@ -1460,6 +1738,14 @@ aoe_flush_iocq(void) | |||
1460 | int __init | 1738 | int __init |
1461 | aoecmd_init(void) | 1739 | aoecmd_init(void) |
1462 | { | 1740 | { |
1741 | void *p; | ||
1742 | |||
1743 | /* get_zeroed_page returns page with ref count 1 */ | ||
1744 | p = (void *) get_zeroed_page(GFP_KERNEL | __GFP_REPEAT); | ||
1745 | if (!p) | ||
1746 | return -ENOMEM; | ||
1747 | empty_page = virt_to_page(p); | ||
1748 | |||
1463 | INIT_LIST_HEAD(&iocq.head); | 1749 | INIT_LIST_HEAD(&iocq.head); |
1464 | spin_lock_init(&iocq.lock); | 1750 | spin_lock_init(&iocq.lock); |
1465 | init_waitqueue_head(&ktiowq); | 1751 | init_waitqueue_head(&ktiowq); |
@@ -1475,4 +1761,7 @@ aoecmd_exit(void) | |||
1475 | { | 1761 | { |
1476 | aoe_ktstop(&kts); | 1762 | aoe_ktstop(&kts); |
1477 | aoe_flush_iocq(); | 1763 | aoe_flush_iocq(); |
1764 | |||
1765 | free_page((unsigned long) page_address(empty_page)); | ||
1766 | empty_page = NULL; | ||
1478 | } | 1767 | } |
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 90e5b537f94b..98f2965778b9 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include "aoe.h" | 15 | #include "aoe.h" |
16 | 16 | ||
17 | static void dummy_timer(ulong); | 17 | static void dummy_timer(ulong); |
18 | static void aoedev_freedev(struct aoedev *); | ||
19 | static void freetgt(struct aoedev *d, struct aoetgt *t); | 18 | static void freetgt(struct aoedev *d, struct aoetgt *t); |
20 | static void skbpoolfree(struct aoedev *d); | 19 | static void skbpoolfree(struct aoedev *d); |
21 | 20 | ||
@@ -69,25 +68,34 @@ minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin) | |||
69 | NPERSHELF = 16, | 68 | NPERSHELF = 16, |
70 | }; | 69 | }; |
71 | 70 | ||
71 | if (aoemin >= NPERSHELF) { | ||
72 | pr_err("aoe: %s %d slots per shelf\n", | ||
73 | "static minor device numbers support only", | ||
74 | NPERSHELF); | ||
75 | error = -1; | ||
76 | goto out; | ||
77 | } | ||
78 | |||
72 | n = aoemaj * NPERSHELF + aoemin; | 79 | n = aoemaj * NPERSHELF + aoemin; |
73 | if (aoemin >= NPERSHELF || n >= N_DEVS) { | 80 | if (n >= N_DEVS) { |
74 | pr_err("aoe: %s with e%ld.%d\n", | 81 | pr_err("aoe: %s with e%ld.%d\n", |
75 | "cannot use static minor device numbers", | 82 | "cannot use static minor device numbers", |
76 | aoemaj, aoemin); | 83 | aoemaj, aoemin); |
77 | error = -1; | 84 | error = -1; |
78 | } else { | 85 | goto out; |
79 | spin_lock_irqsave(&used_minors_lock, flags); | ||
80 | if (test_bit(n, used_minors)) { | ||
81 | pr_err("aoe: %s %lu\n", | ||
82 | "existing device already has static minor number", | ||
83 | n); | ||
84 | error = -1; | ||
85 | } else | ||
86 | set_bit(n, used_minors); | ||
87 | spin_unlock_irqrestore(&used_minors_lock, flags); | ||
88 | } | 86 | } |
89 | 87 | ||
90 | *sysminor = n; | 88 | spin_lock_irqsave(&used_minors_lock, flags); |
89 | if (test_bit(n, used_minors)) { | ||
90 | pr_err("aoe: %s %lu\n", | ||
91 | "existing device already has static minor number", | ||
92 | n); | ||
93 | error = -1; | ||
94 | } else | ||
95 | set_bit(n, used_minors); | ||
96 | spin_unlock_irqrestore(&used_minors_lock, flags); | ||
97 | *sysminor = n * AOE_PARTITIONS; | ||
98 | out: | ||
91 | return error; | 99 | return error; |
92 | } | 100 | } |
93 | 101 | ||
@@ -170,41 +178,50 @@ aoe_failip(struct aoedev *d) | |||
170 | aoe_end_request(d, rq, 0); | 178 | aoe_end_request(d, rq, 0); |
171 | } | 179 | } |
172 | 180 | ||
181 | static void | ||
182 | downdev_frame(struct list_head *pos) | ||
183 | { | ||
184 | struct frame *f; | ||
185 | |||
186 | f = list_entry(pos, struct frame, head); | ||
187 | list_del(pos); | ||
188 | if (f->buf) { | ||
189 | f->buf->nframesout--; | ||
190 | aoe_failbuf(f->t->d, f->buf); | ||
191 | } | ||
192 | aoe_freetframe(f); | ||
193 | } | ||
194 | |||
173 | void | 195 | void |
174 | aoedev_downdev(struct aoedev *d) | 196 | aoedev_downdev(struct aoedev *d) |
175 | { | 197 | { |
176 | struct aoetgt *t, **tt, **te; | 198 | struct aoetgt *t, **tt, **te; |
177 | struct frame *f; | ||
178 | struct list_head *head, *pos, *nx; | 199 | struct list_head *head, *pos, *nx; |
179 | struct request *rq; | 200 | struct request *rq; |
180 | int i; | 201 | int i; |
181 | 202 | ||
182 | d->flags &= ~DEVFL_UP; | 203 | d->flags &= ~DEVFL_UP; |
183 | 204 | ||
184 | /* clean out active buffers */ | 205 | /* clean out active and to-be-retransmitted buffers */ |
185 | for (i = 0; i < NFACTIVE; i++) { | 206 | for (i = 0; i < NFACTIVE; i++) { |
186 | head = &d->factive[i]; | 207 | head = &d->factive[i]; |
187 | list_for_each_safe(pos, nx, head) { | 208 | list_for_each_safe(pos, nx, head) |
188 | f = list_entry(pos, struct frame, head); | 209 | downdev_frame(pos); |
189 | list_del(pos); | ||
190 | if (f->buf) { | ||
191 | f->buf->nframesout--; | ||
192 | aoe_failbuf(d, f->buf); | ||
193 | } | ||
194 | aoe_freetframe(f); | ||
195 | } | ||
196 | } | 210 | } |
211 | head = &d->rexmitq; | ||
212 | list_for_each_safe(pos, nx, head) | ||
213 | downdev_frame(pos); | ||
214 | |||
197 | /* reset window dressings */ | 215 | /* reset window dressings */ |
198 | tt = d->targets; | 216 | tt = d->targets; |
199 | te = tt + NTARGETS; | 217 | te = tt + d->ntargets; |
200 | for (; tt < te && (t = *tt); tt++) { | 218 | for (; tt < te && (t = *tt); tt++) { |
201 | t->maxout = t->nframes; | 219 | aoecmd_wreset(t); |
202 | t->nout = 0; | 220 | t->nout = 0; |
203 | } | 221 | } |
204 | 222 | ||
205 | /* clean out the in-process request (if any) */ | 223 | /* clean out the in-process request (if any) */ |
206 | aoe_failip(d); | 224 | aoe_failip(d); |
207 | d->htgt = NULL; | ||
208 | 225 | ||
209 | /* fast fail all pending I/O */ | 226 | /* fast fail all pending I/O */ |
210 | if (d->blkq) { | 227 | if (d->blkq) { |
@@ -218,12 +235,48 @@ aoedev_downdev(struct aoedev *d) | |||
218 | set_capacity(d->gd, 0); | 235 | set_capacity(d->gd, 0); |
219 | } | 236 | } |
220 | 237 | ||
238 | /* return whether the user asked for this particular | ||
239 | * device to be flushed | ||
240 | */ | ||
241 | static int | ||
242 | user_req(char *s, size_t slen, struct aoedev *d) | ||
243 | { | ||
244 | char *p; | ||
245 | size_t lim; | ||
246 | |||
247 | if (!d->gd) | ||
248 | return 0; | ||
249 | p = strrchr(d->gd->disk_name, '/'); | ||
250 | if (!p) | ||
251 | p = d->gd->disk_name; | ||
252 | else | ||
253 | p += 1; | ||
254 | lim = sizeof(d->gd->disk_name); | ||
255 | lim -= p - d->gd->disk_name; | ||
256 | if (slen < lim) | ||
257 | lim = slen; | ||
258 | |||
259 | return !strncmp(s, p, lim); | ||
260 | } | ||
261 | |||
221 | static void | 262 | static void |
222 | aoedev_freedev(struct aoedev *d) | 263 | freedev(struct aoedev *d) |
223 | { | 264 | { |
224 | struct aoetgt **t, **e; | 265 | struct aoetgt **t, **e; |
266 | int freeing = 0; | ||
267 | unsigned long flags; | ||
268 | |||
269 | spin_lock_irqsave(&d->lock, flags); | ||
270 | if (d->flags & DEVFL_TKILL | ||
271 | && !(d->flags & DEVFL_FREEING)) { | ||
272 | d->flags |= DEVFL_FREEING; | ||
273 | freeing = 1; | ||
274 | } | ||
275 | spin_unlock_irqrestore(&d->lock, flags); | ||
276 | if (!freeing) | ||
277 | return; | ||
225 | 278 | ||
226 | cancel_work_sync(&d->work); | 279 | del_timer_sync(&d->timer); |
227 | if (d->gd) { | 280 | if (d->gd) { |
228 | aoedisk_rm_sysfs(d); | 281 | aoedisk_rm_sysfs(d); |
229 | del_gendisk(d->gd); | 282 | del_gendisk(d->gd); |
@@ -231,61 +284,113 @@ aoedev_freedev(struct aoedev *d) | |||
231 | blk_cleanup_queue(d->blkq); | 284 | blk_cleanup_queue(d->blkq); |
232 | } | 285 | } |
233 | t = d->targets; | 286 | t = d->targets; |
234 | e = t + NTARGETS; | 287 | e = t + d->ntargets; |
235 | for (; t < e && *t; t++) | 288 | for (; t < e && *t; t++) |
236 | freetgt(d, *t); | 289 | freetgt(d, *t); |
237 | if (d->bufpool) | 290 | if (d->bufpool) |
238 | mempool_destroy(d->bufpool); | 291 | mempool_destroy(d->bufpool); |
239 | skbpoolfree(d); | 292 | skbpoolfree(d); |
240 | minor_free(d->sysminor); | 293 | minor_free(d->sysminor); |
241 | kfree(d); | 294 | |
295 | spin_lock_irqsave(&d->lock, flags); | ||
296 | d->flags |= DEVFL_FREED; | ||
297 | spin_unlock_irqrestore(&d->lock, flags); | ||
242 | } | 298 | } |
243 | 299 | ||
244 | int | 300 | enum flush_parms { |
245 | aoedev_flush(const char __user *str, size_t cnt) | 301 | NOT_EXITING = 0, |
302 | EXITING = 1, | ||
303 | }; | ||
304 | |||
305 | static int | ||
306 | flush(const char __user *str, size_t cnt, int exiting) | ||
246 | { | 307 | { |
247 | ulong flags; | 308 | ulong flags; |
248 | struct aoedev *d, **dd; | 309 | struct aoedev *d, **dd; |
249 | struct aoedev *rmd = NULL; | ||
250 | char buf[16]; | 310 | char buf[16]; |
251 | int all = 0; | 311 | int all = 0; |
312 | int specified = 0; /* flush a specific device */ | ||
313 | unsigned int skipflags; | ||
314 | |||
315 | skipflags = DEVFL_GDALLOC | DEVFL_NEWSIZE | DEVFL_TKILL; | ||
252 | 316 | ||
253 | if (cnt >= 3) { | 317 | if (!exiting && cnt >= 3) { |
254 | if (cnt > sizeof buf) | 318 | if (cnt > sizeof buf) |
255 | cnt = sizeof buf; | 319 | cnt = sizeof buf; |
256 | if (copy_from_user(buf, str, cnt)) | 320 | if (copy_from_user(buf, str, cnt)) |
257 | return -EFAULT; | 321 | return -EFAULT; |
258 | all = !strncmp(buf, "all", 3); | 322 | all = !strncmp(buf, "all", 3); |
323 | if (!all) | ||
324 | specified = 1; | ||
259 | } | 325 | } |
260 | 326 | ||
327 | flush_scheduled_work(); | ||
328 | /* pass one: without sleeping, do aoedev_downdev */ | ||
261 | spin_lock_irqsave(&devlist_lock, flags); | 329 | spin_lock_irqsave(&devlist_lock, flags); |
262 | dd = &devlist; | 330 | for (d = devlist; d; d = d->next) { |
263 | while ((d = *dd)) { | ||
264 | spin_lock(&d->lock); | 331 | spin_lock(&d->lock); |
265 | if ((!all && (d->flags & DEVFL_UP)) | 332 | if (exiting) { |
266 | || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) | 333 | /* unconditionally take each device down */ |
334 | } else if (specified) { | ||
335 | if (!user_req(buf, cnt, d)) | ||
336 | goto cont; | ||
337 | } else if ((!all && (d->flags & DEVFL_UP)) | ||
338 | || d->flags & skipflags | ||
267 | || d->nopen | 339 | || d->nopen |
268 | || d->ref) { | 340 | || d->ref) |
269 | spin_unlock(&d->lock); | 341 | goto cont; |
270 | dd = &d->next; | 342 | |
271 | continue; | ||
272 | } | ||
273 | *dd = d->next; | ||
274 | aoedev_downdev(d); | 343 | aoedev_downdev(d); |
275 | d->flags |= DEVFL_TKILL; | 344 | d->flags |= DEVFL_TKILL; |
345 | cont: | ||
276 | spin_unlock(&d->lock); | 346 | spin_unlock(&d->lock); |
277 | d->next = rmd; | ||
278 | rmd = d; | ||
279 | } | 347 | } |
280 | spin_unlock_irqrestore(&devlist_lock, flags); | 348 | spin_unlock_irqrestore(&devlist_lock, flags); |
281 | while ((d = rmd)) { | 349 | |
282 | rmd = d->next; | 350 | /* pass two: call freedev, which might sleep, |
283 | del_timer_sync(&d->timer); | 351 | * for aoedevs marked with DEVFL_TKILL |
284 | aoedev_freedev(d); /* must be able to sleep */ | 352 | */ |
353 | restart: | ||
354 | spin_lock_irqsave(&devlist_lock, flags); | ||
355 | for (d = devlist; d; d = d->next) { | ||
356 | spin_lock(&d->lock); | ||
357 | if (d->flags & DEVFL_TKILL | ||
358 | && !(d->flags & DEVFL_FREEING)) { | ||
359 | spin_unlock(&d->lock); | ||
360 | spin_unlock_irqrestore(&devlist_lock, flags); | ||
361 | freedev(d); | ||
362 | goto restart; | ||
363 | } | ||
364 | spin_unlock(&d->lock); | ||
285 | } | 365 | } |
366 | |||
367 | /* pass three: remove aoedevs marked with DEVFL_FREED */ | ||
368 | for (dd = &devlist, d = *dd; d; d = *dd) { | ||
369 | struct aoedev *doomed = NULL; | ||
370 | |||
371 | spin_lock(&d->lock); | ||
372 | if (d->flags & DEVFL_FREED) { | ||
373 | *dd = d->next; | ||
374 | doomed = d; | ||
375 | } else { | ||
376 | dd = &d->next; | ||
377 | } | ||
378 | spin_unlock(&d->lock); | ||
379 | if (doomed) | ||
380 | kfree(doomed->targets); | ||
381 | kfree(doomed); | ||
382 | } | ||
383 | spin_unlock_irqrestore(&devlist_lock, flags); | ||
384 | |||
286 | return 0; | 385 | return 0; |
287 | } | 386 | } |
288 | 387 | ||
388 | int | ||
389 | aoedev_flush(const char __user *str, size_t cnt) | ||
390 | { | ||
391 | return flush(str, cnt, NOT_EXITING); | ||
392 | } | ||
393 | |||
289 | /* This has been confirmed to occur once with Tms=3*1000 due to the | 394 | /* This has been confirmed to occur once with Tms=3*1000 due to the |
290 | * driver changing link and not processing its transmit ring. The | 395 | * driver changing link and not processing its transmit ring. The |
291 | * problem is hard enough to solve by returning an error that I'm | 396 | * problem is hard enough to solve by returning an error that I'm |
@@ -332,13 +437,20 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) | |||
332 | struct aoedev *d; | 437 | struct aoedev *d; |
333 | int i; | 438 | int i; |
334 | ulong flags; | 439 | ulong flags; |
335 | ulong sysminor; | 440 | ulong sysminor = 0; |
336 | 441 | ||
337 | spin_lock_irqsave(&devlist_lock, flags); | 442 | spin_lock_irqsave(&devlist_lock, flags); |
338 | 443 | ||
339 | for (d=devlist; d; d=d->next) | 444 | for (d=devlist; d; d=d->next) |
340 | if (d->aoemajor == maj && d->aoeminor == min) { | 445 | if (d->aoemajor == maj && d->aoeminor == min) { |
446 | spin_lock(&d->lock); | ||
447 | if (d->flags & DEVFL_TKILL) { | ||
448 | spin_unlock(&d->lock); | ||
449 | d = NULL; | ||
450 | goto out; | ||
451 | } | ||
341 | d->ref++; | 452 | d->ref++; |
453 | spin_unlock(&d->lock); | ||
342 | break; | 454 | break; |
343 | } | 455 | } |
344 | if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0) | 456 | if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0) |
@@ -346,6 +458,13 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) | |||
346 | d = kcalloc(1, sizeof *d, GFP_ATOMIC); | 458 | d = kcalloc(1, sizeof *d, GFP_ATOMIC); |
347 | if (!d) | 459 | if (!d) |
348 | goto out; | 460 | goto out; |
461 | d->targets = kcalloc(NTARGETS, sizeof(*d->targets), GFP_ATOMIC); | ||
462 | if (!d->targets) { | ||
463 | kfree(d); | ||
464 | d = NULL; | ||
465 | goto out; | ||
466 | } | ||
467 | d->ntargets = NTARGETS; | ||
349 | INIT_WORK(&d->work, aoecmd_sleepwork); | 468 | INIT_WORK(&d->work, aoecmd_sleepwork); |
350 | spin_lock_init(&d->lock); | 469 | spin_lock_init(&d->lock); |
351 | skb_queue_head_init(&d->skbpool); | 470 | skb_queue_head_init(&d->skbpool); |
@@ -359,10 +478,12 @@ aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) | |||
359 | d->ref = 1; | 478 | d->ref = 1; |
360 | for (i = 0; i < NFACTIVE; i++) | 479 | for (i = 0; i < NFACTIVE; i++) |
361 | INIT_LIST_HEAD(&d->factive[i]); | 480 | INIT_LIST_HEAD(&d->factive[i]); |
481 | INIT_LIST_HEAD(&d->rexmitq); | ||
362 | d->sysminor = sysminor; | 482 | d->sysminor = sysminor; |
363 | d->aoemajor = maj; | 483 | d->aoemajor = maj; |
364 | d->aoeminor = min; | 484 | d->aoeminor = min; |
365 | d->mintimer = MINTIMER; | 485 | d->rttavg = RTTAVG_INIT; |
486 | d->rttdev = RTTDEV_INIT; | ||
366 | d->next = devlist; | 487 | d->next = devlist; |
367 | devlist = d; | 488 | devlist = d; |
368 | out: | 489 | out: |
@@ -396,21 +517,9 @@ freetgt(struct aoedev *d, struct aoetgt *t) | |||
396 | void | 517 | void |
397 | aoedev_exit(void) | 518 | aoedev_exit(void) |
398 | { | 519 | { |
399 | struct aoedev *d; | 520 | flush_scheduled_work(); |
400 | ulong flags; | ||
401 | |||
402 | aoe_flush_iocq(); | 521 | aoe_flush_iocq(); |
403 | while ((d = devlist)) { | 522 | flush(NULL, 0, EXITING); |
404 | devlist = d->next; | ||
405 | |||
406 | spin_lock_irqsave(&d->lock, flags); | ||
407 | aoedev_downdev(d); | ||
408 | d->flags |= DEVFL_TKILL; | ||
409 | spin_unlock_irqrestore(&d->lock, flags); | ||
410 | |||
411 | del_timer_sync(&d->timer); | ||
412 | aoedev_freedev(d); | ||
413 | } | ||
414 | } | 523 | } |
415 | 524 | ||
416 | int __init | 525 | int __init |
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 04793c2c701b..4b987c2fefbe 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c | |||
@@ -105,7 +105,7 @@ aoe_init(void) | |||
105 | aoechr_exit(); | 105 | aoechr_exit(); |
106 | chr_fail: | 106 | chr_fail: |
107 | aoedev_exit(); | 107 | aoedev_exit(); |
108 | 108 | ||
109 | printk(KERN_INFO "aoe: initialisation failure.\n"); | 109 | printk(KERN_INFO "aoe: initialisation failure.\n"); |
110 | return ret; | 110 | return ret; |
111 | } | 111 | } |
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 162c6471275c..71d3ea8d3006 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
@@ -31,7 +31,7 @@ enum { | |||
31 | 31 | ||
32 | static char aoe_iflist[IFLISTSZ]; | 32 | static char aoe_iflist[IFLISTSZ]; |
33 | module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600); | 33 | module_param_string(aoe_iflist, aoe_iflist, IFLISTSZ, 0600); |
34 | MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=\"dev1 [dev2 ...]\""); | 34 | MODULE_PARM_DESC(aoe_iflist, "aoe_iflist=dev1[,dev2...]"); |
35 | 35 | ||
36 | static wait_queue_head_t txwq; | 36 | static wait_queue_head_t txwq; |
37 | static struct ktstate kts; | 37 | static struct ktstate kts; |
@@ -52,13 +52,18 @@ static struct sk_buff_head skbtxq; | |||
52 | 52 | ||
53 | /* enters with txlock held */ | 53 | /* enters with txlock held */ |
54 | static int | 54 | static int |
55 | tx(void) | 55 | tx(void) __must_hold(&txlock) |
56 | { | 56 | { |
57 | struct sk_buff *skb; | 57 | struct sk_buff *skb; |
58 | struct net_device *ifp; | ||
58 | 59 | ||
59 | while ((skb = skb_dequeue(&skbtxq))) { | 60 | while ((skb = skb_dequeue(&skbtxq))) { |
60 | spin_unlock_irq(&txlock); | 61 | spin_unlock_irq(&txlock); |
61 | dev_queue_xmit(skb); | 62 | ifp = skb->dev; |
63 | if (dev_queue_xmit(skb) == NET_XMIT_DROP && net_ratelimit()) | ||
64 | pr_warn("aoe: packet could not be sent on %s. %s\n", | ||
65 | ifp ? ifp->name : "netif", | ||
66 | "consider increasing tx_queue_len"); | ||
62 | spin_lock_irq(&txlock); | 67 | spin_lock_irq(&txlock); |
63 | } | 68 | } |
64 | return 0; | 69 | return 0; |
@@ -119,8 +124,8 @@ aoenet_xmit(struct sk_buff_head *queue) | |||
119 | } | 124 | } |
120 | } | 125 | } |
121 | 126 | ||
122 | /* | 127 | /* |
123 | * (1) len doesn't include the header by default. I want this. | 128 | * (1) len doesn't include the header by default. I want this. |
124 | */ | 129 | */ |
125 | static int | 130 | static int |
126 | aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) | 131 | aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) |
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 24225f0fdcd8..64b048d7fba7 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c | |||
@@ -228,6 +228,20 @@ static void dmatest_callback(void *arg) | |||
228 | wake_up_all(done->wait); | 228 | wake_up_all(done->wait); |
229 | } | 229 | } |
230 | 230 | ||
231 | static inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len, | ||
232 | unsigned int count) | ||
233 | { | ||
234 | while (count--) | ||
235 | dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE); | ||
236 | } | ||
237 | |||
238 | static inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len, | ||
239 | unsigned int count) | ||
240 | { | ||
241 | while (count--) | ||
242 | dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL); | ||
243 | } | ||
244 | |||
231 | /* | 245 | /* |
232 | * This function repeatedly tests DMA transfers of various lengths and | 246 | * This function repeatedly tests DMA transfers of various lengths and |
233 | * offsets for a given operation type until it is told to exit by | 247 | * offsets for a given operation type until it is told to exit by |
@@ -353,15 +367,35 @@ static int dmatest_func(void *data) | |||
353 | 367 | ||
354 | dma_srcs[i] = dma_map_single(dev->dev, buf, len, | 368 | dma_srcs[i] = dma_map_single(dev->dev, buf, len, |
355 | DMA_TO_DEVICE); | 369 | DMA_TO_DEVICE); |
370 | ret = dma_mapping_error(dev->dev, dma_srcs[i]); | ||
371 | if (ret) { | ||
372 | unmap_src(dev->dev, dma_srcs, len, i); | ||
373 | pr_warn("%s: #%u: mapping error %d with " | ||
374 | "src_off=0x%x len=0x%x\n", | ||
375 | thread_name, total_tests - 1, ret, | ||
376 | src_off, len); | ||
377 | failed_tests++; | ||
378 | continue; | ||
379 | } | ||
356 | } | 380 | } |
357 | /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ | 381 | /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ |
358 | for (i = 0; i < dst_cnt; i++) { | 382 | for (i = 0; i < dst_cnt; i++) { |
359 | dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], | 383 | dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], |
360 | test_buf_size, | 384 | test_buf_size, |
361 | DMA_BIDIRECTIONAL); | 385 | DMA_BIDIRECTIONAL); |
386 | ret = dma_mapping_error(dev->dev, dma_dsts[i]); | ||
387 | if (ret) { | ||
388 | unmap_src(dev->dev, dma_srcs, len, src_cnt); | ||
389 | unmap_dst(dev->dev, dma_dsts, test_buf_size, i); | ||
390 | pr_warn("%s: #%u: mapping error %d with " | ||
391 | "dst_off=0x%x len=0x%x\n", | ||
392 | thread_name, total_tests - 1, ret, | ||
393 | dst_off, test_buf_size); | ||
394 | failed_tests++; | ||
395 | continue; | ||
396 | } | ||
362 | } | 397 | } |
363 | 398 | ||
364 | |||
365 | if (thread->type == DMA_MEMCPY) | 399 | if (thread->type == DMA_MEMCPY) |
366 | tx = dev->device_prep_dma_memcpy(chan, | 400 | tx = dev->device_prep_dma_memcpy(chan, |
367 | dma_dsts[0] + dst_off, | 401 | dma_dsts[0] + dst_off, |
@@ -383,13 +417,8 @@ static int dmatest_func(void *data) | |||
383 | } | 417 | } |
384 | 418 | ||
385 | if (!tx) { | 419 | if (!tx) { |
386 | for (i = 0; i < src_cnt; i++) | 420 | unmap_src(dev->dev, dma_srcs, len, src_cnt); |
387 | dma_unmap_single(dev->dev, dma_srcs[i], len, | 421 | unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); |
388 | DMA_TO_DEVICE); | ||
389 | for (i = 0; i < dst_cnt; i++) | ||
390 | dma_unmap_single(dev->dev, dma_dsts[i], | ||
391 | test_buf_size, | ||
392 | DMA_BIDIRECTIONAL); | ||
393 | pr_warning("%s: #%u: prep error with src_off=0x%x " | 422 | pr_warning("%s: #%u: prep error with src_off=0x%x " |
394 | "dst_off=0x%x len=0x%x\n", | 423 | "dst_off=0x%x len=0x%x\n", |
395 | thread_name, total_tests - 1, | 424 | thread_name, total_tests - 1, |
@@ -443,9 +472,7 @@ static int dmatest_func(void *data) | |||
443 | } | 472 | } |
444 | 473 | ||
445 | /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ | 474 | /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ |
446 | for (i = 0; i < dst_cnt; i++) | 475 | unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); |
447 | dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size, | ||
448 | DMA_BIDIRECTIONAL); | ||
449 | 476 | ||
450 | error_count = 0; | 477 | error_count = 0; |
451 | 478 | ||
diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index a932c485eb04..c3c13e64a2f0 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c | |||
@@ -1397,10 +1397,7 @@ int do_read_error(struct nandsim *ns, int num) | |||
1397 | unsigned int page_no = ns->regs.row; | 1397 | unsigned int page_no = ns->regs.row; |
1398 | 1398 | ||
1399 | if (read_error(page_no)) { | 1399 | if (read_error(page_no)) { |
1400 | int i; | 1400 | prandom_bytes(ns->buf.byte, num); |
1401 | memset(ns->buf.byte, 0xFF, num); | ||
1402 | for (i = 0; i < num; ++i) | ||
1403 | ns->buf.byte[i] = random32(); | ||
1404 | NS_WARN("simulating read error in page %u\n", page_no); | 1401 | NS_WARN("simulating read error in page %u\n", page_no); |
1405 | return 1; | 1402 | return 1; |
1406 | } | 1403 | } |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index a2998bea5d4b..01588b66a38c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -1832,7 +1832,6 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, | |||
1832 | bool config_hash) | 1832 | bool config_hash) |
1833 | { | 1833 | { |
1834 | struct bnx2x_config_rss_params params = {NULL}; | 1834 | struct bnx2x_config_rss_params params = {NULL}; |
1835 | int i; | ||
1836 | 1835 | ||
1837 | /* Although RSS is meaningless when there is a single HW queue we | 1836 | /* Although RSS is meaningless when there is a single HW queue we |
1838 | * still need it enabled in order to have HW Rx hash generated. | 1837 | * still need it enabled in order to have HW Rx hash generated. |
@@ -1864,9 +1863,7 @@ int bnx2x_config_rss_pf(struct bnx2x *bp, struct bnx2x_rss_config_obj *rss_obj, | |||
1864 | 1863 | ||
1865 | if (config_hash) { | 1864 | if (config_hash) { |
1866 | /* RSS keys */ | 1865 | /* RSS keys */ |
1867 | for (i = 0; i < sizeof(params.rss_key) / 4; i++) | 1866 | prandom_bytes(params.rss_key, sizeof(params.rss_key)); |
1868 | params.rss_key[i] = random32(); | ||
1869 | |||
1870 | __set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags); | 1867 | __set_bit(BNX2X_RSS_SET_SRCH, ¶ms.rss_flags); |
1871 | } | 1868 | } |
1872 | 1869 | ||
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 6deaae18db57..28aa05f60c26 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -156,11 +156,7 @@ config PRISM54 | |||
156 | ---help--- | 156 | ---help--- |
157 | This enables support for FullMAC PCI/Cardbus prism54 devices. This | 157 | This enables support for FullMAC PCI/Cardbus prism54 devices. This |
158 | driver is now deprecated in favor for the SoftMAC driver, p54pci. | 158 | driver is now deprecated in favor for the SoftMAC driver, p54pci. |
159 | p54pci supports FullMAC PCI/Cardbus devices as well. For details on | 159 | p54pci supports FullMAC PCI/Cardbus devices as well. |
160 | the scheduled removal of this driver on the kernel see the feature | ||
161 | removal schedule: | ||
162 | |||
163 | Documentation/feature-removal-schedule.txt | ||
164 | 160 | ||
165 | For more information refer to the p54 wiki: | 161 | For more information refer to the p54 wiki: |
166 | 162 | ||
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index a65c39c473bf..808be06bb67e 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c | |||
@@ -488,14 +488,8 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, | |||
488 | depth++; | 488 | depth++; |
489 | pathp = (char *)p; | 489 | pathp = (char *)p; |
490 | p = ALIGN(p + strlen(pathp) + 1, 4); | 490 | p = ALIGN(p + strlen(pathp) + 1, 4); |
491 | if ((*pathp) == '/') { | 491 | if (*pathp == '/') |
492 | const char *lp, *np; | 492 | pathp = kbasename(pathp); |
493 | for (lp = NULL, np = pathp; *np; np++) | ||
494 | if ((*np) == '/') | ||
495 | lp = np+1; | ||
496 | if (lp != NULL) | ||
497 | pathp = lp; | ||
498 | } | ||
499 | rc = it(p, pathp, depth, data); | 493 | rc = it(p, pathp, depth, data); |
500 | if (rc != 0) | 494 | if (rc != 0) |
501 | break; | 495 | break; |
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 6b0ebdeae916..be790402e0f1 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #define ASUS_NB_WMI_FILE "asus-nb-wmi" | 33 | #define ASUS_NB_WMI_FILE "asus-nb-wmi" |
34 | 34 | ||
35 | MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>"); | 35 | MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>"); |
36 | MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver"); | 36 | MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver"); |
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | 38 | ||
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index c0e9ff489b24..f80ae4d10f68 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | #include "asus-wmi.h" | 52 | #include "asus-wmi.h" |
53 | 53 | ||
54 | MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, " | 54 | MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>, " |
55 | "Yong Wang <yong.y.wang@intel.com>"); | 55 | "Yong Wang <yong.y.wang@intel.com>"); |
56 | MODULE_DESCRIPTION("Asus Generic WMI Driver"); | 56 | MODULE_DESCRIPTION("Asus Generic WMI Driver"); |
57 | MODULE_LICENSE("GPL"); | 57 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 5838332ea5bd..60cb76a5b513 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #define EEEPC_WMI_FILE "eeepc-wmi" | 40 | #define EEEPC_WMI_FILE "eeepc-wmi" |
41 | 41 | ||
42 | MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>"); | 42 | MODULE_AUTHOR("Corentin Chary <corentin.chary@gmail.com>"); |
43 | MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); | 43 | MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver"); |
44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
45 | 45 | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 19c03ab2bdcb..d0cea02b5dfc 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -269,6 +269,15 @@ config RTC_DRV_X1205 | |||
269 | This driver can also be built as a module. If so, the module | 269 | This driver can also be built as a module. If so, the module |
270 | will be called rtc-x1205. | 270 | will be called rtc-x1205. |
271 | 271 | ||
272 | config RTC_DRV_PCF8523 | ||
273 | tristate "NXP PCF8523" | ||
274 | help | ||
275 | If you say yes here you get support for the NXP PCF8523 RTC | ||
276 | chips. | ||
277 | |||
278 | This driver can also be built as a module. If so, the module | ||
279 | will be called rtc-pcf8523. | ||
280 | |||
272 | config RTC_DRV_PCF8563 | 281 | config RTC_DRV_PCF8563 |
273 | tristate "Philips PCF8563/Epson RTC8564" | 282 | tristate "Philips PCF8563/Epson RTC8564" |
274 | help | 283 | help |
@@ -600,6 +609,16 @@ config RTC_DRV_DA9052 | |||
600 | Say y here to support the RTC driver for Dialog Semiconductor | 609 | Say y here to support the RTC driver for Dialog Semiconductor |
601 | DA9052-BC and DA9053-AA/Bx PMICs. | 610 | DA9052-BC and DA9053-AA/Bx PMICs. |
602 | 611 | ||
612 | config RTC_DRV_DA9055 | ||
613 | tristate "Dialog Semiconductor DA9055 RTC" | ||
614 | depends on MFD_DA9055 | ||
615 | help | ||
616 | If you say yes here you will get support for the | ||
617 | RTC of the Dialog DA9055 PMIC. | ||
618 | |||
619 | This driver can also be built as a module. If so, the module | ||
620 | will be called rtc-da9055 | ||
621 | |||
603 | config RTC_DRV_EFI | 622 | config RTC_DRV_EFI |
604 | tristate "EFI RTC" | 623 | tristate "EFI RTC" |
605 | depends on IA64 | 624 | depends on IA64 |
@@ -768,7 +787,7 @@ config RTC_DRV_DAVINCI | |||
768 | 787 | ||
769 | config RTC_DRV_IMXDI | 788 | config RTC_DRV_IMXDI |
770 | tristate "Freescale IMX DryIce Real Time Clock" | 789 | tristate "Freescale IMX DryIce Real Time Clock" |
771 | depends on SOC_IMX25 | 790 | depends on ARCH_MXC |
772 | help | 791 | help |
773 | Support for Freescale IMX DryIce RTC | 792 | Support for Freescale IMX DryIce RTC |
774 | 793 | ||
@@ -777,11 +796,13 @@ config RTC_DRV_IMXDI | |||
777 | 796 | ||
778 | config RTC_DRV_OMAP | 797 | config RTC_DRV_OMAP |
779 | tristate "TI OMAP1" | 798 | tristate "TI OMAP1" |
780 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX | 799 | depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX || SOC_AM33XX |
781 | help | 800 | help |
782 | Say "yes" here to support the real time clock on TI OMAP1 and | 801 | Say "yes" here to support the on chip real time clock |
783 | DA8xx/OMAP-L13x chips. This driver can also be built as a | 802 | present on TI OMAP1, AM33xx and DA8xx/OMAP-L13x. |
784 | module called rtc-omap. | 803 | |
804 | This driver can also be built as a module, if so, module | ||
805 | will be called rtc-omap. | ||
785 | 806 | ||
786 | config HAVE_S3C_RTC | 807 | config HAVE_S3C_RTC |
787 | bool | 808 | bool |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 56297f0fd388..c3f62c80dc06 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -29,6 +29,7 @@ obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | |||
29 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 29 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
30 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o | 30 | obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o |
31 | obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o | 31 | obj-$(CONFIG_RTC_DRV_DA9052) += rtc-da9052.o |
32 | obj-$(CONFIG_RTC_DRV_DA9055) += rtc-da9055.o | ||
32 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o | 33 | obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o |
33 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o | 34 | obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o |
34 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o | 35 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o |
@@ -76,6 +77,7 @@ obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o | |||
76 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o | 77 | obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o |
77 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 78 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
78 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o | 79 | obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o |
80 | obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o | ||
79 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 81 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
80 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 82 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
81 | obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o | 83 | obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o |
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c new file mode 100644 index 000000000000..96bafc5c3bf8 --- /dev/null +++ b/drivers/rtc/rtc-da9055.c | |||
@@ -0,0 +1,413 @@ | |||
1 | /* | ||
2 | * Real time clock driver for DA9055 | ||
3 | * | ||
4 | * Copyright(c) 2012 Dialog Semiconductor Ltd. | ||
5 | * | ||
6 | * Author: Dajun Dajun Chen <dajun.chen@diasemi.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/rtc.h> | ||
18 | |||
19 | #include <linux/mfd/da9055/core.h> | ||
20 | #include <linux/mfd/da9055/reg.h> | ||
21 | #include <linux/mfd/da9055/pdata.h> | ||
22 | |||
23 | struct da9055_rtc { | ||
24 | struct rtc_device *rtc; | ||
25 | struct da9055 *da9055; | ||
26 | int alarm_enable; | ||
27 | }; | ||
28 | |||
29 | static int da9055_rtc_enable_alarm(struct da9055_rtc *rtc, bool enable) | ||
30 | { | ||
31 | int ret; | ||
32 | if (enable) { | ||
33 | ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y, | ||
34 | DA9055_RTC_ALM_EN, | ||
35 | DA9055_RTC_ALM_EN); | ||
36 | if (ret != 0) | ||
37 | dev_err(rtc->da9055->dev, "Failed to enable ALM: %d\n", | ||
38 | ret); | ||
39 | rtc->alarm_enable = 1; | ||
40 | } else { | ||
41 | ret = da9055_reg_update(rtc->da9055, DA9055_REG_ALARM_Y, | ||
42 | DA9055_RTC_ALM_EN, 0); | ||
43 | if (ret != 0) | ||
44 | dev_err(rtc->da9055->dev, | ||
45 | "Failed to disable ALM: %d\n", ret); | ||
46 | rtc->alarm_enable = 0; | ||
47 | } | ||
48 | return ret; | ||
49 | } | ||
50 | |||
51 | static irqreturn_t da9055_rtc_alm_irq(int irq, void *data) | ||
52 | { | ||
53 | struct da9055_rtc *rtc = data; | ||
54 | |||
55 | da9055_rtc_enable_alarm(rtc, 0); | ||
56 | rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF); | ||
57 | |||
58 | return IRQ_HANDLED; | ||
59 | } | ||
60 | |||
61 | static int da9055_read_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) | ||
62 | { | ||
63 | int ret; | ||
64 | uint8_t v[5]; | ||
65 | |||
66 | ret = da9055_group_read(da9055, DA9055_REG_ALARM_MI, 5, v); | ||
67 | if (ret != 0) { | ||
68 | dev_err(da9055->dev, "Failed to group read ALM: %d\n", ret); | ||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | rtc_tm->tm_year = (v[4] & DA9055_RTC_ALM_YEAR) + 100; | ||
73 | rtc_tm->tm_mon = (v[3] & DA9055_RTC_ALM_MONTH) - 1; | ||
74 | rtc_tm->tm_mday = v[2] & DA9055_RTC_ALM_DAY; | ||
75 | rtc_tm->tm_hour = v[1] & DA9055_RTC_ALM_HOUR; | ||
76 | rtc_tm->tm_min = v[0] & DA9055_RTC_ALM_MIN; | ||
77 | |||
78 | return rtc_valid_tm(rtc_tm); | ||
79 | } | ||
80 | |||
81 | static int da9055_set_alarm(struct da9055 *da9055, struct rtc_time *rtc_tm) | ||
82 | { | ||
83 | int ret; | ||
84 | uint8_t v[2]; | ||
85 | |||
86 | rtc_tm->tm_year -= 100; | ||
87 | rtc_tm->tm_mon += 1; | ||
88 | |||
89 | ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MI, | ||
90 | DA9055_RTC_ALM_MIN, rtc_tm->tm_min); | ||
91 | if (ret != 0) { | ||
92 | dev_err(da9055->dev, "Failed to write ALRM MIN: %d\n", ret); | ||
93 | return ret; | ||
94 | } | ||
95 | |||
96 | v[0] = rtc_tm->tm_hour; | ||
97 | v[1] = rtc_tm->tm_mday; | ||
98 | |||
99 | ret = da9055_group_write(da9055, DA9055_REG_ALARM_H, 2, v); | ||
100 | if (ret < 0) | ||
101 | return ret; | ||
102 | |||
103 | ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO, | ||
104 | DA9055_RTC_ALM_MONTH, rtc_tm->tm_mon); | ||
105 | if (ret < 0) | ||
106 | dev_err(da9055->dev, "Failed to write ALM Month:%d\n", ret); | ||
107 | |||
108 | ret = da9055_reg_update(da9055, DA9055_REG_ALARM_Y, | ||
109 | DA9055_RTC_ALM_YEAR, rtc_tm->tm_year); | ||
110 | if (ret < 0) | ||
111 | dev_err(da9055->dev, "Failed to write ALM Year:%d\n", ret); | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static int da9055_rtc_get_alarm_status(struct da9055 *da9055) | ||
117 | { | ||
118 | int ret; | ||
119 | |||
120 | ret = da9055_reg_read(da9055, DA9055_REG_ALARM_Y); | ||
121 | if (ret < 0) { | ||
122 | dev_err(da9055->dev, "Failed to read ALM: %d\n", ret); | ||
123 | return ret; | ||
124 | } | ||
125 | ret &= DA9055_RTC_ALM_EN; | ||
126 | return (ret > 0) ? 1 : 0; | ||
127 | } | ||
128 | |||
129 | static int da9055_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | ||
130 | { | ||
131 | struct da9055_rtc *rtc = dev_get_drvdata(dev); | ||
132 | uint8_t v[6]; | ||
133 | int ret; | ||
134 | |||
135 | ret = da9055_reg_read(rtc->da9055, DA9055_REG_COUNT_S); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | /* | ||
140 | * Registers are only valid when RTC_READ | ||
141 | * status bit is asserted | ||
142 | */ | ||
143 | if (!(ret & DA9055_RTC_READ)) | ||
144 | return -EBUSY; | ||
145 | |||
146 | ret = da9055_group_read(rtc->da9055, DA9055_REG_COUNT_S, 6, v); | ||
147 | if (ret < 0) { | ||
148 | dev_err(rtc->da9055->dev, "Failed to read RTC time : %d\n", | ||
149 | ret); | ||
150 | return ret; | ||
151 | } | ||
152 | |||
153 | rtc_tm->tm_year = (v[5] & DA9055_RTC_YEAR) + 100; | ||
154 | rtc_tm->tm_mon = (v[4] & DA9055_RTC_MONTH) - 1; | ||
155 | rtc_tm->tm_mday = v[3] & DA9055_RTC_DAY; | ||
156 | rtc_tm->tm_hour = v[2] & DA9055_RTC_HOUR; | ||
157 | rtc_tm->tm_min = v[1] & DA9055_RTC_MIN; | ||
158 | rtc_tm->tm_sec = v[0] & DA9055_RTC_SEC; | ||
159 | |||
160 | return rtc_valid_tm(rtc_tm); | ||
161 | } | ||
162 | |||
163 | static int da9055_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
164 | { | ||
165 | struct da9055_rtc *rtc; | ||
166 | uint8_t v[6]; | ||
167 | |||
168 | rtc = dev_get_drvdata(dev); | ||
169 | |||
170 | v[0] = tm->tm_sec; | ||
171 | v[1] = tm->tm_min; | ||
172 | v[2] = tm->tm_hour; | ||
173 | v[3] = tm->tm_mday; | ||
174 | v[4] = tm->tm_mon + 1; | ||
175 | v[5] = tm->tm_year - 100; | ||
176 | |||
177 | return da9055_group_write(rtc->da9055, DA9055_REG_COUNT_S, 6, v); | ||
178 | } | ||
179 | |||
180 | static int da9055_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
181 | { | ||
182 | int ret; | ||
183 | struct rtc_time *tm = &alrm->time; | ||
184 | struct da9055_rtc *rtc = dev_get_drvdata(dev); | ||
185 | |||
186 | ret = da9055_read_alarm(rtc->da9055, tm); | ||
187 | |||
188 | if (ret) | ||
189 | return ret; | ||
190 | |||
191 | alrm->enabled = da9055_rtc_get_alarm_status(rtc->da9055); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int da9055_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
197 | { | ||
198 | int ret; | ||
199 | struct rtc_time *tm = &alrm->time; | ||
200 | struct da9055_rtc *rtc = dev_get_drvdata(dev); | ||
201 | |||
202 | ret = da9055_rtc_enable_alarm(rtc, 0); | ||
203 | if (ret < 0) | ||
204 | return ret; | ||
205 | |||
206 | ret = da9055_set_alarm(rtc->da9055, tm); | ||
207 | if (ret) | ||
208 | return ret; | ||
209 | |||
210 | ret = da9055_rtc_enable_alarm(rtc, 1); | ||
211 | |||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | static int da9055_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | ||
216 | { | ||
217 | struct da9055_rtc *rtc = dev_get_drvdata(dev); | ||
218 | |||
219 | return da9055_rtc_enable_alarm(rtc, enabled); | ||
220 | } | ||
221 | |||
222 | static const struct rtc_class_ops da9055_rtc_ops = { | ||
223 | .read_time = da9055_rtc_read_time, | ||
224 | .set_time = da9055_rtc_set_time, | ||
225 | .read_alarm = da9055_rtc_read_alarm, | ||
226 | .set_alarm = da9055_rtc_set_alarm, | ||
227 | .alarm_irq_enable = da9055_rtc_alarm_irq_enable, | ||
228 | }; | ||
229 | |||
230 | static int __init da9055_rtc_device_init(struct da9055 *da9055, | ||
231 | struct da9055_pdata *pdata) | ||
232 | { | ||
233 | int ret; | ||
234 | |||
235 | /* Enable RTC and the internal Crystal */ | ||
236 | ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, | ||
237 | DA9055_RTC_EN, DA9055_RTC_EN); | ||
238 | if (ret < 0) | ||
239 | return ret; | ||
240 | ret = da9055_reg_update(da9055, DA9055_REG_EN_32K, | ||
241 | DA9055_CRYSTAL_EN, DA9055_CRYSTAL_EN); | ||
242 | if (ret < 0) | ||
243 | return ret; | ||
244 | |||
245 | /* Enable RTC in Power Down mode */ | ||
246 | ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, | ||
247 | DA9055_RTC_MODE_PD, DA9055_RTC_MODE_PD); | ||
248 | if (ret < 0) | ||
249 | return ret; | ||
250 | |||
251 | /* Enable RTC in Reset mode */ | ||
252 | if (pdata && pdata->reset_enable) { | ||
253 | ret = da9055_reg_update(da9055, DA9055_REG_CONTROL_B, | ||
254 | DA9055_RTC_MODE_SD, | ||
255 | DA9055_RTC_MODE_SD << | ||
256 | DA9055_RTC_MODE_SD_SHIFT); | ||
257 | if (ret < 0) | ||
258 | return ret; | ||
259 | } | ||
260 | |||
261 | /* Disable the RTC TICK ALM */ | ||
262 | ret = da9055_reg_update(da9055, DA9055_REG_ALARM_MO, | ||
263 | DA9055_RTC_TICK_WAKE_MASK, 0); | ||
264 | if (ret < 0) | ||
265 | return ret; | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int da9055_rtc_probe(struct platform_device *pdev) | ||
271 | { | ||
272 | struct da9055_rtc *rtc; | ||
273 | struct da9055_pdata *pdata = NULL; | ||
274 | int ret, alm_irq; | ||
275 | |||
276 | rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9055_rtc), GFP_KERNEL); | ||
277 | if (!rtc) | ||
278 | return -ENOMEM; | ||
279 | |||
280 | rtc->da9055 = dev_get_drvdata(pdev->dev.parent); | ||
281 | pdata = rtc->da9055->dev->platform_data; | ||
282 | platform_set_drvdata(pdev, rtc); | ||
283 | |||
284 | ret = da9055_rtc_device_init(rtc->da9055, pdata); | ||
285 | if (ret < 0) | ||
286 | goto err_rtc; | ||
287 | |||
288 | ret = da9055_reg_read(rtc->da9055, DA9055_REG_ALARM_Y); | ||
289 | if (ret < 0) | ||
290 | goto err_rtc; | ||
291 | |||
292 | if (ret & DA9055_RTC_ALM_EN) | ||
293 | rtc->alarm_enable = 1; | ||
294 | |||
295 | device_init_wakeup(&pdev->dev, 1); | ||
296 | |||
297 | rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
298 | &da9055_rtc_ops, THIS_MODULE); | ||
299 | if (IS_ERR(rtc->rtc)) { | ||
300 | ret = PTR_ERR(rtc->rtc); | ||
301 | goto err_rtc; | ||
302 | } | ||
303 | |||
304 | alm_irq = platform_get_irq_byname(pdev, "ALM"); | ||
305 | alm_irq = regmap_irq_get_virq(rtc->da9055->irq_data, alm_irq); | ||
306 | ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, | ||
307 | da9055_rtc_alm_irq, | ||
308 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, | ||
309 | "ALM", rtc); | ||
310 | if (ret != 0) | ||
311 | dev_err(rtc->da9055->dev, "irq registration failed: %d\n", ret); | ||
312 | |||
313 | err_rtc: | ||
314 | return ret; | ||
315 | |||
316 | } | ||
317 | |||
318 | static int da9055_rtc_remove(struct platform_device *pdev) | ||
319 | { | ||
320 | struct da9055_rtc *rtc = pdev->dev.platform_data; | ||
321 | |||
322 | rtc_device_unregister(rtc->rtc); | ||
323 | platform_set_drvdata(pdev, NULL); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | #ifdef CONFIG_PM | ||
329 | /* Turn off the alarm if it should not be a wake source. */ | ||
330 | static int da9055_rtc_suspend(struct device *dev) | ||
331 | { | ||
332 | struct platform_device *pdev = to_platform_device(dev); | ||
333 | struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
334 | int ret; | ||
335 | |||
336 | if (!device_may_wakeup(&pdev->dev)) { | ||
337 | /* Disable the ALM IRQ */ | ||
338 | ret = da9055_rtc_enable_alarm(rtc, 0); | ||
339 | if (ret < 0) | ||
340 | dev_err(&pdev->dev, "Failed to disable RTC ALM\n"); | ||
341 | } | ||
342 | |||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | /* Enable the alarm if it should be enabled (in case it was disabled to | ||
347 | * prevent use as a wake source). | ||
348 | */ | ||
349 | static int da9055_rtc_resume(struct device *dev) | ||
350 | { | ||
351 | struct platform_device *pdev = to_platform_device(dev); | ||
352 | struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
353 | int ret; | ||
354 | |||
355 | if (!device_may_wakeup(&pdev->dev)) { | ||
356 | if (rtc->alarm_enable) { | ||
357 | ret = da9055_rtc_enable_alarm(rtc, 1); | ||
358 | if (ret < 0) | ||
359 | dev_err(&pdev->dev, | ||
360 | "Failed to restart RTC ALM\n"); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | /* Unconditionally disable the alarm */ | ||
368 | static int da9055_rtc_freeze(struct device *dev) | ||
369 | { | ||
370 | struct platform_device *pdev = to_platform_device(dev); | ||
371 | struct da9055_rtc *rtc = dev_get_drvdata(&pdev->dev); | ||
372 | int ret; | ||
373 | |||
374 | ret = da9055_rtc_enable_alarm(rtc, 0); | ||
375 | if (ret < 0) | ||
376 | dev_err(&pdev->dev, "Failed to freeze RTC ALMs\n"); | ||
377 | |||
378 | return 0; | ||
379 | |||
380 | } | ||
381 | #else | ||
382 | #define da9055_rtc_suspend NULL | ||
383 | #define da9055_rtc_resume NULL | ||
384 | #define da9055_rtc_freeze NULL | ||
385 | #endif | ||
386 | |||
387 | static const struct dev_pm_ops da9055_rtc_pm_ops = { | ||
388 | .suspend = da9055_rtc_suspend, | ||
389 | .resume = da9055_rtc_resume, | ||
390 | |||
391 | .freeze = da9055_rtc_freeze, | ||
392 | .thaw = da9055_rtc_resume, | ||
393 | .restore = da9055_rtc_resume, | ||
394 | |||
395 | .poweroff = da9055_rtc_suspend, | ||
396 | }; | ||
397 | |||
398 | static struct platform_driver da9055_rtc_driver = { | ||
399 | .probe = da9055_rtc_probe, | ||
400 | .remove = da9055_rtc_remove, | ||
401 | .driver = { | ||
402 | .name = "da9055-rtc", | ||
403 | .owner = THIS_MODULE, | ||
404 | .pm = &da9055_rtc_pm_ops, | ||
405 | }, | ||
406 | }; | ||
407 | |||
408 | module_platform_driver(da9055_rtc_driver); | ||
409 | |||
410 | MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>"); | ||
411 | MODULE_DESCRIPTION("RTC driver for Dialog DA9055 PMIC"); | ||
412 | MODULE_LICENSE("GPL"); | ||
413 | MODULE_ALIAS("platform:da9055-rtc"); | ||
diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index 14c2109dbaa3..07cd03eae606 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c | |||
@@ -485,7 +485,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
485 | struct resource *res, *mem; | 485 | struct resource *res, *mem; |
486 | int ret = 0; | 486 | int ret = 0; |
487 | 487 | ||
488 | davinci_rtc = kzalloc(sizeof(struct davinci_rtc), GFP_KERNEL); | 488 | davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL); |
489 | if (!davinci_rtc) { | 489 | if (!davinci_rtc) { |
490 | dev_dbg(dev, "could not allocate memory for private data\n"); | 490 | dev_dbg(dev, "could not allocate memory for private data\n"); |
491 | return -ENOMEM; | 491 | return -ENOMEM; |
@@ -494,15 +494,13 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
494 | davinci_rtc->irq = platform_get_irq(pdev, 0); | 494 | davinci_rtc->irq = platform_get_irq(pdev, 0); |
495 | if (davinci_rtc->irq < 0) { | 495 | if (davinci_rtc->irq < 0) { |
496 | dev_err(dev, "no RTC irq\n"); | 496 | dev_err(dev, "no RTC irq\n"); |
497 | ret = davinci_rtc->irq; | 497 | return davinci_rtc->irq; |
498 | goto fail1; | ||
499 | } | 498 | } |
500 | 499 | ||
501 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 500 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
502 | if (!res) { | 501 | if (!res) { |
503 | dev_err(dev, "no mem resource\n"); | 502 | dev_err(dev, "no mem resource\n"); |
504 | ret = -EINVAL; | 503 | return -EINVAL; |
505 | goto fail1; | ||
506 | } | 504 | } |
507 | 505 | ||
508 | davinci_rtc->pbase = res->start; | 506 | davinci_rtc->pbase = res->start; |
@@ -513,8 +511,7 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
513 | if (!mem) { | 511 | if (!mem) { |
514 | dev_err(dev, "RTC registers at %08x are not free\n", | 512 | dev_err(dev, "RTC registers at %08x are not free\n", |
515 | davinci_rtc->pbase); | 513 | davinci_rtc->pbase); |
516 | ret = -EBUSY; | 514 | return -EBUSY; |
517 | goto fail1; | ||
518 | } | 515 | } |
519 | 516 | ||
520 | davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); | 517 | davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size); |
@@ -529,8 +526,9 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) | |||
529 | davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | 526 | davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, |
530 | &davinci_rtc_ops, THIS_MODULE); | 527 | &davinci_rtc_ops, THIS_MODULE); |
531 | if (IS_ERR(davinci_rtc->rtc)) { | 528 | if (IS_ERR(davinci_rtc->rtc)) { |
532 | dev_err(dev, "unable to register RTC device, err %ld\n", | 529 | ret = PTR_ERR(davinci_rtc->rtc); |
533 | PTR_ERR(davinci_rtc->rtc)); | 530 | dev_err(dev, "unable to register RTC device, err %d\n", |
531 | ret); | ||
534 | goto fail3; | 532 | goto fail3; |
535 | } | 533 | } |
536 | 534 | ||
@@ -566,9 +564,6 @@ fail3: | |||
566 | iounmap(davinci_rtc->base); | 564 | iounmap(davinci_rtc->base); |
567 | fail2: | 565 | fail2: |
568 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); | 566 | release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size); |
569 | fail1: | ||
570 | kfree(davinci_rtc); | ||
571 | |||
572 | return ret; | 567 | return ret; |
573 | } | 568 | } |
574 | 569 | ||
@@ -589,8 +584,6 @@ static int __devexit davinci_rtc_remove(struct platform_device *pdev) | |||
589 | 584 | ||
590 | platform_set_drvdata(pdev, NULL); | 585 | platform_set_drvdata(pdev, NULL); |
591 | 586 | ||
592 | kfree(davinci_rtc); | ||
593 | |||
594 | return 0; | 587 | return 0; |
595 | } | 588 | } |
596 | 589 | ||
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index cace6d3aed9a..9a86b4bd8699 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -379,25 +379,6 @@ static long rtc_dev_ioctl(struct file *file, | |||
379 | err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); | 379 | err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); |
380 | break; | 380 | break; |
381 | 381 | ||
382 | #if 0 | ||
383 | case RTC_EPOCH_SET: | ||
384 | #ifndef rtc_epoch | ||
385 | /* | ||
386 | * There were no RTC clocks before 1900. | ||
387 | */ | ||
388 | if (arg < 1900) { | ||
389 | err = -EINVAL; | ||
390 | break; | ||
391 | } | ||
392 | rtc_epoch = arg; | ||
393 | err = 0; | ||
394 | #endif | ||
395 | break; | ||
396 | |||
397 | case RTC_EPOCH_READ: | ||
398 | err = put_user(rtc_epoch, (unsigned long __user *)uarg); | ||
399 | break; | ||
400 | #endif | ||
401 | case RTC_WKALM_SET: | 382 | case RTC_WKALM_SET: |
402 | mutex_unlock(&rtc->ops_lock); | 383 | mutex_unlock(&rtc->ops_lock); |
403 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) | 384 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) |
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 4eed51044c5d..18a4f0dd78a3 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/rtc.h> | 37 | #include <linux/rtc.h> |
38 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
39 | #include <linux/workqueue.h> | 39 | #include <linux/workqueue.h> |
40 | #include <linux/of.h> | ||
40 | 41 | ||
41 | /* DryIce Register Definitions */ | 42 | /* DryIce Register Definitions */ |
42 | 43 | ||
@@ -495,10 +496,20 @@ static int __devexit dryice_rtc_remove(struct platform_device *pdev) | |||
495 | return 0; | 496 | return 0; |
496 | } | 497 | } |
497 | 498 | ||
499 | #ifdef CONFIG_OF | ||
500 | static const struct of_device_id dryice_dt_ids[] = { | ||
501 | { .compatible = "fsl,imx25-rtc" }, | ||
502 | { /* sentinel */ } | ||
503 | }; | ||
504 | |||
505 | MODULE_DEVICE_TABLE(of, dryice_dt_ids); | ||
506 | #endif | ||
507 | |||
498 | static struct platform_driver dryice_rtc_driver = { | 508 | static struct platform_driver dryice_rtc_driver = { |
499 | .driver = { | 509 | .driver = { |
500 | .name = "imxdi_rtc", | 510 | .name = "imxdi_rtc", |
501 | .owner = THIS_MODULE, | 511 | .owner = THIS_MODULE, |
512 | .of_match_table = of_match_ptr(dryice_dt_ids), | ||
502 | }, | 513 | }, |
503 | .remove = __devexit_p(dryice_rtc_remove), | 514 | .remove = __devexit_p(dryice_rtc_remove), |
504 | }; | 515 | }; |
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 0b614e32653d..600971407aac 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <linux/rtc.h> | 20 | #include <linux/rtc.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_device.h> | ||
25 | #include <linux/pm_runtime.h> | ||
23 | 26 | ||
24 | #include <asm/io.h> | 27 | #include <asm/io.h> |
25 | 28 | ||
@@ -38,6 +41,8 @@ | |||
38 | * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. | 41 | * the SoC). See the BOARD-SPECIFIC CUSTOMIZATION comment. |
39 | */ | 42 | */ |
40 | 43 | ||
44 | #define DRIVER_NAME "omap_rtc" | ||
45 | |||
41 | #define OMAP_RTC_BASE 0xfffb4800 | 46 | #define OMAP_RTC_BASE 0xfffb4800 |
42 | 47 | ||
43 | /* RTC registers */ | 48 | /* RTC registers */ |
@@ -64,6 +69,9 @@ | |||
64 | #define OMAP_RTC_COMP_MSB_REG 0x50 | 69 | #define OMAP_RTC_COMP_MSB_REG 0x50 |
65 | #define OMAP_RTC_OSC_REG 0x54 | 70 | #define OMAP_RTC_OSC_REG 0x54 |
66 | 71 | ||
72 | #define OMAP_RTC_KICK0_REG 0x6c | ||
73 | #define OMAP_RTC_KICK1_REG 0x70 | ||
74 | |||
67 | /* OMAP_RTC_CTRL_REG bit fields: */ | 75 | /* OMAP_RTC_CTRL_REG bit fields: */ |
68 | #define OMAP_RTC_CTRL_SPLIT (1<<7) | 76 | #define OMAP_RTC_CTRL_SPLIT (1<<7) |
69 | #define OMAP_RTC_CTRL_DISABLE (1<<6) | 77 | #define OMAP_RTC_CTRL_DISABLE (1<<6) |
@@ -88,10 +96,18 @@ | |||
88 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) | 96 | #define OMAP_RTC_INTERRUPTS_IT_ALARM (1<<3) |
89 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) | 97 | #define OMAP_RTC_INTERRUPTS_IT_TIMER (1<<2) |
90 | 98 | ||
99 | /* OMAP_RTC_KICKER values */ | ||
100 | #define KICK0_VALUE 0x83e70b13 | ||
101 | #define KICK1_VALUE 0x95a4f1e0 | ||
102 | |||
103 | #define OMAP_RTC_HAS_KICKER 0x1 | ||
104 | |||
91 | static void __iomem *rtc_base; | 105 | static void __iomem *rtc_base; |
92 | 106 | ||
93 | #define rtc_read(addr) __raw_readb(rtc_base + (addr)) | 107 | #define rtc_read(addr) readb(rtc_base + (addr)) |
94 | #define rtc_write(val, addr) __raw_writeb(val, rtc_base + (addr)) | 108 | #define rtc_write(val, addr) writeb(val, rtc_base + (addr)) |
109 | |||
110 | #define rtc_writel(val, addr) writel(val, rtc_base + (addr)) | ||
95 | 111 | ||
96 | 112 | ||
97 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), | 113 | /* we rely on the rtc framework to handle locking (rtc->ops_lock), |
@@ -285,11 +301,38 @@ static struct rtc_class_ops omap_rtc_ops = { | |||
285 | static int omap_rtc_alarm; | 301 | static int omap_rtc_alarm; |
286 | static int omap_rtc_timer; | 302 | static int omap_rtc_timer; |
287 | 303 | ||
304 | #define OMAP_RTC_DATA_DA830_IDX 1 | ||
305 | |||
306 | static struct platform_device_id omap_rtc_devtype[] = { | ||
307 | { | ||
308 | .name = DRIVER_NAME, | ||
309 | }, { | ||
310 | .name = "da830-rtc", | ||
311 | .driver_data = OMAP_RTC_HAS_KICKER, | ||
312 | }, | ||
313 | {}, | ||
314 | }; | ||
315 | MODULE_DEVICE_TABLE(platform, omap_rtc_devtype); | ||
316 | |||
317 | static const struct of_device_id omap_rtc_of_match[] = { | ||
318 | { .compatible = "ti,da830-rtc", | ||
319 | .data = &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX], | ||
320 | }, | ||
321 | {}, | ||
322 | }; | ||
323 | MODULE_DEVICE_TABLE(of, omap_rtc_of_match); | ||
324 | |||
288 | static int __init omap_rtc_probe(struct platform_device *pdev) | 325 | static int __init omap_rtc_probe(struct platform_device *pdev) |
289 | { | 326 | { |
290 | struct resource *res, *mem; | 327 | struct resource *res, *mem; |
291 | struct rtc_device *rtc; | 328 | struct rtc_device *rtc; |
292 | u8 reg, new_ctrl; | 329 | u8 reg, new_ctrl; |
330 | const struct platform_device_id *id_entry; | ||
331 | const struct of_device_id *of_id; | ||
332 | |||
333 | of_id = of_match_device(omap_rtc_of_match, &pdev->dev); | ||
334 | if (of_id) | ||
335 | pdev->id_entry = of_id->data; | ||
293 | 336 | ||
294 | omap_rtc_timer = platform_get_irq(pdev, 0); | 337 | omap_rtc_timer = platform_get_irq(pdev, 0); |
295 | if (omap_rtc_timer <= 0) { | 338 | if (omap_rtc_timer <= 0) { |
@@ -322,6 +365,16 @@ static int __init omap_rtc_probe(struct platform_device *pdev) | |||
322 | goto fail; | 365 | goto fail; |
323 | } | 366 | } |
324 | 367 | ||
368 | /* Enable the clock/module so that we can access the registers */ | ||
369 | pm_runtime_enable(&pdev->dev); | ||
370 | pm_runtime_get_sync(&pdev->dev); | ||
371 | |||
372 | id_entry = platform_get_device_id(pdev); | ||
373 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) { | ||
374 | rtc_writel(KICK0_VALUE, OMAP_RTC_KICK0_REG); | ||
375 | rtc_writel(KICK1_VALUE, OMAP_RTC_KICK1_REG); | ||
376 | } | ||
377 | |||
325 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 378 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
326 | &omap_rtc_ops, THIS_MODULE); | 379 | &omap_rtc_ops, THIS_MODULE); |
327 | if (IS_ERR(rtc)) { | 380 | if (IS_ERR(rtc)) { |
@@ -398,6 +451,10 @@ fail2: | |||
398 | fail1: | 451 | fail1: |
399 | rtc_device_unregister(rtc); | 452 | rtc_device_unregister(rtc); |
400 | fail0: | 453 | fail0: |
454 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) | ||
455 | rtc_writel(0, OMAP_RTC_KICK0_REG); | ||
456 | pm_runtime_put_sync(&pdev->dev); | ||
457 | pm_runtime_disable(&pdev->dev); | ||
401 | iounmap(rtc_base); | 458 | iounmap(rtc_base); |
402 | fail: | 459 | fail: |
403 | release_mem_region(mem->start, resource_size(mem)); | 460 | release_mem_region(mem->start, resource_size(mem)); |
@@ -408,6 +465,8 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
408 | { | 465 | { |
409 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 466 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
410 | struct resource *mem = dev_get_drvdata(&rtc->dev); | 467 | struct resource *mem = dev_get_drvdata(&rtc->dev); |
468 | const struct platform_device_id *id_entry = | ||
469 | platform_get_device_id(pdev); | ||
411 | 470 | ||
412 | device_init_wakeup(&pdev->dev, 0); | 471 | device_init_wakeup(&pdev->dev, 0); |
413 | 472 | ||
@@ -420,6 +479,13 @@ static int __exit omap_rtc_remove(struct platform_device *pdev) | |||
420 | free_irq(omap_rtc_alarm, rtc); | 479 | free_irq(omap_rtc_alarm, rtc); |
421 | 480 | ||
422 | rtc_device_unregister(rtc); | 481 | rtc_device_unregister(rtc); |
482 | if (id_entry && (id_entry->driver_data & OMAP_RTC_HAS_KICKER)) | ||
483 | rtc_writel(0, OMAP_RTC_KICK0_REG); | ||
484 | |||
485 | /* Disable the clock/module */ | ||
486 | pm_runtime_put_sync(&pdev->dev); | ||
487 | pm_runtime_disable(&pdev->dev); | ||
488 | |||
423 | iounmap(rtc_base); | 489 | iounmap(rtc_base); |
424 | release_mem_region(mem->start, resource_size(mem)); | 490 | release_mem_region(mem->start, resource_size(mem)); |
425 | return 0; | 491 | return 0; |
@@ -442,11 +508,17 @@ static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state) | |||
442 | else | 508 | else |
443 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); | 509 | rtc_write(0, OMAP_RTC_INTERRUPTS_REG); |
444 | 510 | ||
511 | /* Disable the clock/module */ | ||
512 | pm_runtime_put_sync(&pdev->dev); | ||
513 | |||
445 | return 0; | 514 | return 0; |
446 | } | 515 | } |
447 | 516 | ||
448 | static int omap_rtc_resume(struct platform_device *pdev) | 517 | static int omap_rtc_resume(struct platform_device *pdev) |
449 | { | 518 | { |
519 | /* Enable the clock/module so that we can access the registers */ | ||
520 | pm_runtime_get_sync(&pdev->dev); | ||
521 | |||
450 | if (device_may_wakeup(&pdev->dev)) | 522 | if (device_may_wakeup(&pdev->dev)) |
451 | disable_irq_wake(omap_rtc_alarm); | 523 | disable_irq_wake(omap_rtc_alarm); |
452 | else | 524 | else |
@@ -471,9 +543,11 @@ static struct platform_driver omap_rtc_driver = { | |||
471 | .resume = omap_rtc_resume, | 543 | .resume = omap_rtc_resume, |
472 | .shutdown = omap_rtc_shutdown, | 544 | .shutdown = omap_rtc_shutdown, |
473 | .driver = { | 545 | .driver = { |
474 | .name = "omap_rtc", | 546 | .name = DRIVER_NAME, |
475 | .owner = THIS_MODULE, | 547 | .owner = THIS_MODULE, |
548 | .of_match_table = of_match_ptr(omap_rtc_of_match), | ||
476 | }, | 549 | }, |
550 | .id_table = omap_rtc_devtype, | ||
477 | }; | 551 | }; |
478 | 552 | ||
479 | static int __init rtc_init(void) | 553 | static int __init rtc_init(void) |
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c new file mode 100644 index 000000000000..be05a645f99e --- /dev/null +++ b/drivers/rtc/rtc-pcf8523.c | |||
@@ -0,0 +1,326 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Avionic Design GmbH | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/bcd.h> | ||
10 | #include <linux/i2c.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/rtc.h> | ||
13 | #include <linux/of.h> | ||
14 | |||
15 | #define DRIVER_NAME "rtc-pcf8523" | ||
16 | |||
17 | #define REG_CONTROL1 0x00 | ||
18 | #define REG_CONTROL1_CAP_SEL (1 << 7) | ||
19 | #define REG_CONTROL1_STOP (1 << 5) | ||
20 | |||
21 | #define REG_CONTROL3 0x02 | ||
22 | #define REG_CONTROL3_PM_BLD (1 << 7) /* battery low detection disabled */ | ||
23 | #define REG_CONTROL3_PM_VDD (1 << 6) /* switch-over disabled */ | ||
24 | #define REG_CONTROL3_PM_DSM (1 << 5) /* direct switching mode */ | ||
25 | #define REG_CONTROL3_PM_MASK 0xe0 | ||
26 | |||
27 | #define REG_SECONDS 0x03 | ||
28 | #define REG_SECONDS_OS (1 << 7) | ||
29 | |||
30 | #define REG_MINUTES 0x04 | ||
31 | #define REG_HOURS 0x05 | ||
32 | #define REG_DAYS 0x06 | ||
33 | #define REG_WEEKDAYS 0x07 | ||
34 | #define REG_MONTHS 0x08 | ||
35 | #define REG_YEARS 0x09 | ||
36 | |||
37 | struct pcf8523 { | ||
38 | struct rtc_device *rtc; | ||
39 | }; | ||
40 | |||
41 | static int pcf8523_read(struct i2c_client *client, u8 reg, u8 *valuep) | ||
42 | { | ||
43 | struct i2c_msg msgs[2]; | ||
44 | u8 value = 0; | ||
45 | int err; | ||
46 | |||
47 | msgs[0].addr = client->addr; | ||
48 | msgs[0].flags = 0; | ||
49 | msgs[0].len = sizeof(reg); | ||
50 | msgs[0].buf = ® | ||
51 | |||
52 | msgs[1].addr = client->addr; | ||
53 | msgs[1].flags = I2C_M_RD; | ||
54 | msgs[1].len = sizeof(value); | ||
55 | msgs[1].buf = &value; | ||
56 | |||
57 | err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
58 | if (err < 0) | ||
59 | return err; | ||
60 | |||
61 | *valuep = value; | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value) | ||
67 | { | ||
68 | u8 buffer[2] = { reg, value }; | ||
69 | struct i2c_msg msg; | ||
70 | int err; | ||
71 | |||
72 | msg.addr = client->addr; | ||
73 | msg.flags = 0; | ||
74 | msg.len = sizeof(buffer); | ||
75 | msg.buf = buffer; | ||
76 | |||
77 | err = i2c_transfer(client->adapter, &msg, 1); | ||
78 | if (err < 0) | ||
79 | return err; | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static int pcf8523_select_capacitance(struct i2c_client *client, bool high) | ||
85 | { | ||
86 | u8 value; | ||
87 | int err; | ||
88 | |||
89 | err = pcf8523_read(client, REG_CONTROL1, &value); | ||
90 | if (err < 0) | ||
91 | return err; | ||
92 | |||
93 | if (!high) | ||
94 | value &= ~REG_CONTROL1_CAP_SEL; | ||
95 | else | ||
96 | value |= REG_CONTROL1_CAP_SEL; | ||
97 | |||
98 | err = pcf8523_write(client, REG_CONTROL1, value); | ||
99 | if (err < 0) | ||
100 | return err; | ||
101 | |||
102 | return err; | ||
103 | } | ||
104 | |||
105 | static int pcf8523_set_pm(struct i2c_client *client, u8 pm) | ||
106 | { | ||
107 | u8 value; | ||
108 | int err; | ||
109 | |||
110 | err = pcf8523_read(client, REG_CONTROL3, &value); | ||
111 | if (err < 0) | ||
112 | return err; | ||
113 | |||
114 | value = (value & ~REG_CONTROL3_PM_MASK) | pm; | ||
115 | |||
116 | err = pcf8523_write(client, REG_CONTROL3, value); | ||
117 | if (err < 0) | ||
118 | return err; | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int pcf8523_stop_rtc(struct i2c_client *client) | ||
124 | { | ||
125 | u8 value; | ||
126 | int err; | ||
127 | |||
128 | err = pcf8523_read(client, REG_CONTROL1, &value); | ||
129 | if (err < 0) | ||
130 | return err; | ||
131 | |||
132 | value |= REG_CONTROL1_STOP; | ||
133 | |||
134 | err = pcf8523_write(client, REG_CONTROL1, value); | ||
135 | if (err < 0) | ||
136 | return err; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int pcf8523_start_rtc(struct i2c_client *client) | ||
142 | { | ||
143 | u8 value; | ||
144 | int err; | ||
145 | |||
146 | err = pcf8523_read(client, REG_CONTROL1, &value); | ||
147 | if (err < 0) | ||
148 | return err; | ||
149 | |||
150 | value &= ~REG_CONTROL1_STOP; | ||
151 | |||
152 | err = pcf8523_write(client, REG_CONTROL1, value); | ||
153 | if (err < 0) | ||
154 | return err; | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
160 | { | ||
161 | struct i2c_client *client = to_i2c_client(dev); | ||
162 | u8 start = REG_SECONDS, regs[7]; | ||
163 | struct i2c_msg msgs[2]; | ||
164 | int err; | ||
165 | |||
166 | msgs[0].addr = client->addr; | ||
167 | msgs[0].flags = 0; | ||
168 | msgs[0].len = 1; | ||
169 | msgs[0].buf = &start; | ||
170 | |||
171 | msgs[1].addr = client->addr; | ||
172 | msgs[1].flags = I2C_M_RD; | ||
173 | msgs[1].len = sizeof(regs); | ||
174 | msgs[1].buf = regs; | ||
175 | |||
176 | err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
177 | if (err < 0) | ||
178 | return err; | ||
179 | |||
180 | if (regs[0] & REG_SECONDS_OS) { | ||
181 | /* | ||
182 | * If the oscillator was stopped, try to clear the flag. Upon | ||
183 | * power-up the flag is always set, but if we cannot clear it | ||
184 | * the oscillator isn't running properly for some reason. The | ||
185 | * sensible thing therefore is to return an error, signalling | ||
186 | * that the clock cannot be assumed to be correct. | ||
187 | */ | ||
188 | |||
189 | regs[0] &= ~REG_SECONDS_OS; | ||
190 | |||
191 | err = pcf8523_write(client, REG_SECONDS, regs[0]); | ||
192 | if (err < 0) | ||
193 | return err; | ||
194 | |||
195 | err = pcf8523_read(client, REG_SECONDS, ®s[0]); | ||
196 | if (err < 0) | ||
197 | return err; | ||
198 | |||
199 | if (regs[0] & REG_SECONDS_OS) | ||
200 | return -EAGAIN; | ||
201 | } | ||
202 | |||
203 | tm->tm_sec = bcd2bin(regs[0] & 0x7f); | ||
204 | tm->tm_min = bcd2bin(regs[1] & 0x7f); | ||
205 | tm->tm_hour = bcd2bin(regs[2] & 0x3f); | ||
206 | tm->tm_mday = bcd2bin(regs[3] & 0x3f); | ||
207 | tm->tm_wday = regs[4] & 0x7; | ||
208 | tm->tm_mon = bcd2bin(regs[5] & 0x1f); | ||
209 | tm->tm_year = bcd2bin(regs[6]) + 100; | ||
210 | |||
211 | return rtc_valid_tm(tm); | ||
212 | } | ||
213 | |||
214 | static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
215 | { | ||
216 | struct i2c_client *client = to_i2c_client(dev); | ||
217 | struct i2c_msg msg; | ||
218 | u8 regs[8]; | ||
219 | int err; | ||
220 | |||
221 | err = pcf8523_stop_rtc(client); | ||
222 | if (err < 0) | ||
223 | return err; | ||
224 | |||
225 | regs[0] = REG_SECONDS; | ||
226 | regs[1] = bin2bcd(tm->tm_sec); | ||
227 | regs[2] = bin2bcd(tm->tm_min); | ||
228 | regs[3] = bin2bcd(tm->tm_hour); | ||
229 | regs[4] = bin2bcd(tm->tm_mday); | ||
230 | regs[5] = tm->tm_wday; | ||
231 | regs[6] = bin2bcd(tm->tm_mon); | ||
232 | regs[7] = bin2bcd(tm->tm_year - 100); | ||
233 | |||
234 | msg.addr = client->addr; | ||
235 | msg.flags = 0; | ||
236 | msg.len = sizeof(regs); | ||
237 | msg.buf = regs; | ||
238 | |||
239 | err = i2c_transfer(client->adapter, &msg, 1); | ||
240 | if (err < 0) { | ||
241 | /* | ||
242 | * If the time cannot be set, restart the RTC anyway. Note | ||
243 | * that errors are ignored if the RTC cannot be started so | ||
244 | * that we have a chance to propagate the original error. | ||
245 | */ | ||
246 | pcf8523_start_rtc(client); | ||
247 | return err; | ||
248 | } | ||
249 | |||
250 | return pcf8523_start_rtc(client); | ||
251 | } | ||
252 | |||
253 | static const struct rtc_class_ops pcf8523_rtc_ops = { | ||
254 | .read_time = pcf8523_rtc_read_time, | ||
255 | .set_time = pcf8523_rtc_set_time, | ||
256 | }; | ||
257 | |||
258 | static int pcf8523_probe(struct i2c_client *client, | ||
259 | const struct i2c_device_id *id) | ||
260 | { | ||
261 | struct pcf8523 *pcf; | ||
262 | int err; | ||
263 | |||
264 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) | ||
265 | return -ENODEV; | ||
266 | |||
267 | pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL); | ||
268 | if (!pcf) | ||
269 | return -ENOMEM; | ||
270 | |||
271 | err = pcf8523_select_capacitance(client, true); | ||
272 | if (err < 0) | ||
273 | return err; | ||
274 | |||
275 | err = pcf8523_set_pm(client, 0); | ||
276 | if (err < 0) | ||
277 | return err; | ||
278 | |||
279 | pcf->rtc = rtc_device_register(DRIVER_NAME, &client->dev, | ||
280 | &pcf8523_rtc_ops, THIS_MODULE); | ||
281 | if (IS_ERR(pcf->rtc)) | ||
282 | return PTR_ERR(pcf->rtc); | ||
283 | |||
284 | i2c_set_clientdata(client, pcf); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int pcf8523_remove(struct i2c_client *client) | ||
290 | { | ||
291 | struct pcf8523 *pcf = i2c_get_clientdata(client); | ||
292 | |||
293 | rtc_device_unregister(pcf->rtc); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static const struct i2c_device_id pcf8523_id[] = { | ||
299 | { "pcf8523", 0 }, | ||
300 | { } | ||
301 | }; | ||
302 | MODULE_DEVICE_TABLE(i2c, pcf8523_id); | ||
303 | |||
304 | #ifdef CONFIG_OF | ||
305 | static const struct of_device_id pcf8523_of_match[] = { | ||
306 | { .compatible = "nxp,pcf8523" }, | ||
307 | { } | ||
308 | }; | ||
309 | MODULE_DEVICE_TABLE(of, pcf8523_of_match); | ||
310 | #endif | ||
311 | |||
312 | static struct i2c_driver pcf8523_driver = { | ||
313 | .driver = { | ||
314 | .name = DRIVER_NAME, | ||
315 | .owner = THIS_MODULE, | ||
316 | .of_match_table = of_match_ptr(pcf8523_of_match), | ||
317 | }, | ||
318 | .probe = pcf8523_probe, | ||
319 | .remove = pcf8523_remove, | ||
320 | .id_table = pcf8523_id, | ||
321 | }; | ||
322 | module_i2c_driver(pcf8523_driver); | ||
323 | |||
324 | MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>"); | ||
325 | MODULE_DESCRIPTION("NXP PCF8523 RTC driver"); | ||
326 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index a7a2a998fa91..4bd9414aee65 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -47,8 +47,6 @@ struct s3c_rtc_drv_data { | |||
47 | /* I have yet to find an S3C implementation with more than one | 47 | /* I have yet to find an S3C implementation with more than one |
48 | * of these rtc blocks in */ | 48 | * of these rtc blocks in */ |
49 | 49 | ||
50 | static struct resource *s3c_rtc_mem; | ||
51 | |||
52 | static struct clk *rtc_clk; | 50 | static struct clk *rtc_clk; |
53 | static void __iomem *s3c_rtc_base; | 51 | static void __iomem *s3c_rtc_base; |
54 | static int s3c_rtc_alarmno = NO_IRQ; | 52 | static int s3c_rtc_alarmno = NO_IRQ; |
@@ -427,21 +425,13 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev) | |||
427 | { | 425 | { |
428 | struct rtc_device *rtc = platform_get_drvdata(dev); | 426 | struct rtc_device *rtc = platform_get_drvdata(dev); |
429 | 427 | ||
430 | free_irq(s3c_rtc_alarmno, rtc); | ||
431 | free_irq(s3c_rtc_tickno, rtc); | ||
432 | |||
433 | platform_set_drvdata(dev, NULL); | 428 | platform_set_drvdata(dev, NULL); |
434 | rtc_device_unregister(rtc); | 429 | rtc_device_unregister(rtc); |
435 | 430 | ||
436 | s3c_rtc_setaie(&dev->dev, 0); | 431 | s3c_rtc_setaie(&dev->dev, 0); |
437 | 432 | ||
438 | clk_put(rtc_clk); | ||
439 | rtc_clk = NULL; | 433 | rtc_clk = NULL; |
440 | 434 | ||
441 | iounmap(s3c_rtc_base); | ||
442 | release_resource(s3c_rtc_mem); | ||
443 | kfree(s3c_rtc_mem); | ||
444 | |||
445 | return 0; | 435 | return 0; |
446 | } | 436 | } |
447 | 437 | ||
@@ -496,28 +486,18 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
496 | return -ENOENT; | 486 | return -ENOENT; |
497 | } | 487 | } |
498 | 488 | ||
499 | s3c_rtc_mem = request_mem_region(res->start, resource_size(res), | 489 | s3c_rtc_base = devm_request_and_ioremap(&pdev->dev, res); |
500 | pdev->name); | ||
501 | |||
502 | if (s3c_rtc_mem == NULL) { | ||
503 | dev_err(&pdev->dev, "failed to reserve memory region\n"); | ||
504 | ret = -ENOENT; | ||
505 | goto err_nores; | ||
506 | } | ||
507 | |||
508 | s3c_rtc_base = ioremap(res->start, resource_size(res)); | ||
509 | if (s3c_rtc_base == NULL) { | 490 | if (s3c_rtc_base == NULL) { |
510 | dev_err(&pdev->dev, "failed ioremap()\n"); | 491 | dev_err(&pdev->dev, "failed to ioremap memory region\n"); |
511 | ret = -EINVAL; | 492 | return -EINVAL; |
512 | goto err_nomap; | ||
513 | } | 493 | } |
514 | 494 | ||
515 | rtc_clk = clk_get(&pdev->dev, "rtc"); | 495 | rtc_clk = devm_clk_get(&pdev->dev, "rtc"); |
516 | if (IS_ERR(rtc_clk)) { | 496 | if (IS_ERR(rtc_clk)) { |
517 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); | 497 | dev_err(&pdev->dev, "failed to find rtc clock source\n"); |
518 | ret = PTR_ERR(rtc_clk); | 498 | ret = PTR_ERR(rtc_clk); |
519 | rtc_clk = NULL; | 499 | rtc_clk = NULL; |
520 | goto err_clk; | 500 | return ret; |
521 | } | 501 | } |
522 | 502 | ||
523 | clk_enable(rtc_clk); | 503 | clk_enable(rtc_clk); |
@@ -576,28 +556,24 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
576 | 556 | ||
577 | s3c_rtc_setfreq(&pdev->dev, 1); | 557 | s3c_rtc_setfreq(&pdev->dev, 1); |
578 | 558 | ||
579 | ret = request_irq(s3c_rtc_alarmno, s3c_rtc_alarmirq, | 559 | ret = devm_request_irq(&pdev->dev, s3c_rtc_alarmno, s3c_rtc_alarmirq, |
580 | 0, "s3c2410-rtc alarm", rtc); | 560 | 0, "s3c2410-rtc alarm", rtc); |
581 | if (ret) { | 561 | if (ret) { |
582 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); | 562 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_alarmno, ret); |
583 | goto err_alarm_irq; | 563 | goto err_alarm_irq; |
584 | } | 564 | } |
585 | 565 | ||
586 | ret = request_irq(s3c_rtc_tickno, s3c_rtc_tickirq, | 566 | ret = devm_request_irq(&pdev->dev, s3c_rtc_tickno, s3c_rtc_tickirq, |
587 | 0, "s3c2410-rtc tick", rtc); | 567 | 0, "s3c2410-rtc tick", rtc); |
588 | if (ret) { | 568 | if (ret) { |
589 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); | 569 | dev_err(&pdev->dev, "IRQ%d error %d\n", s3c_rtc_tickno, ret); |
590 | free_irq(s3c_rtc_alarmno, rtc); | 570 | goto err_alarm_irq; |
591 | goto err_tick_irq; | ||
592 | } | 571 | } |
593 | 572 | ||
594 | clk_disable(rtc_clk); | 573 | clk_disable(rtc_clk); |
595 | 574 | ||
596 | return 0; | 575 | return 0; |
597 | 576 | ||
598 | err_tick_irq: | ||
599 | free_irq(s3c_rtc_alarmno, rtc); | ||
600 | |||
601 | err_alarm_irq: | 577 | err_alarm_irq: |
602 | platform_set_drvdata(pdev, NULL); | 578 | platform_set_drvdata(pdev, NULL); |
603 | rtc_device_unregister(rtc); | 579 | rtc_device_unregister(rtc); |
@@ -605,15 +581,7 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
605 | err_nortc: | 581 | err_nortc: |
606 | s3c_rtc_enable(pdev, 0); | 582 | s3c_rtc_enable(pdev, 0); |
607 | clk_disable(rtc_clk); | 583 | clk_disable(rtc_clk); |
608 | clk_put(rtc_clk); | ||
609 | 584 | ||
610 | err_clk: | ||
611 | iounmap(s3c_rtc_base); | ||
612 | |||
613 | err_nomap: | ||
614 | release_resource(s3c_rtc_mem); | ||
615 | |||
616 | err_nores: | ||
617 | return ret; | 585 | return ret; |
618 | } | 586 | } |
619 | 587 | ||
@@ -695,8 +663,6 @@ static const struct of_device_id s3c_rtc_dt_match[] = { | |||
695 | {}, | 663 | {}, |
696 | }; | 664 | }; |
697 | MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); | 665 | MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match); |
698 | #else | ||
699 | #define s3c_rtc_dt_match NULL | ||
700 | #endif | 666 | #endif |
701 | 667 | ||
702 | static struct platform_device_id s3c_rtc_driver_ids[] = { | 668 | static struct platform_device_id s3c_rtc_driver_ids[] = { |
@@ -727,7 +693,7 @@ static struct platform_driver s3c_rtc_driver = { | |||
727 | .driver = { | 693 | .driver = { |
728 | .name = "s3c-rtc", | 694 | .name = "s3c-rtc", |
729 | .owner = THIS_MODULE, | 695 | .owner = THIS_MODULE, |
730 | .of_match_table = s3c_rtc_dt_match, | 696 | .of_match_table = of_match_ptr(s3c_rtc_dt_match), |
731 | }, | 697 | }, |
732 | }; | 698 | }; |
733 | 699 | ||
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index bb507d23f6ce..141fc945295f 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c | |||
@@ -363,35 +363,42 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) | |||
363 | dev_err(&pdev->dev, "no resource defined\n"); | 363 | dev_err(&pdev->dev, "no resource defined\n"); |
364 | return -EBUSY; | 364 | return -EBUSY; |
365 | } | 365 | } |
366 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | ||
367 | dev_err(&pdev->dev, "rtc region already claimed\n"); | ||
368 | return -EBUSY; | ||
369 | } | ||
370 | 366 | ||
371 | config = kzalloc(sizeof(*config), GFP_KERNEL); | 367 | config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); |
372 | if (!config) { | 368 | if (!config) { |
373 | dev_err(&pdev->dev, "out of memory\n"); | 369 | dev_err(&pdev->dev, "out of memory\n"); |
374 | status = -ENOMEM; | 370 | return -ENOMEM; |
375 | goto err_release_region; | ||
376 | } | 371 | } |
377 | 372 | ||
378 | config->clk = clk_get(&pdev->dev, NULL); | 373 | /* alarm irqs */ |
379 | if (IS_ERR(config->clk)) { | 374 | irq = platform_get_irq(pdev, 0); |
380 | status = PTR_ERR(config->clk); | 375 | if (irq < 0) { |
381 | goto err_kfree; | 376 | dev_err(&pdev->dev, "no update irq?\n"); |
377 | return irq; | ||
382 | } | 378 | } |
383 | 379 | ||
384 | status = clk_enable(config->clk); | 380 | status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name, |
385 | if (status < 0) | 381 | config); |
386 | goto err_clk_put; | 382 | if (status) { |
383 | dev_err(&pdev->dev, "Alarm interrupt IRQ%d already claimed\n", | ||
384 | irq); | ||
385 | return status; | ||
386 | } | ||
387 | 387 | ||
388 | config->ioaddr = ioremap(res->start, resource_size(res)); | 388 | config->ioaddr = devm_request_and_ioremap(&pdev->dev, res); |
389 | if (!config->ioaddr) { | 389 | if (!config->ioaddr) { |
390 | dev_err(&pdev->dev, "ioremap fail\n"); | 390 | dev_err(&pdev->dev, "request-ioremap fail\n"); |
391 | status = -ENOMEM; | 391 | return -ENOMEM; |
392 | goto err_disable_clock; | ||
393 | } | 392 | } |
394 | 393 | ||
394 | config->clk = devm_clk_get(&pdev->dev, NULL); | ||
395 | if (IS_ERR(config->clk)) | ||
396 | return PTR_ERR(config->clk); | ||
397 | |||
398 | status = clk_prepare_enable(config->clk); | ||
399 | if (status < 0) | ||
400 | return status; | ||
401 | |||
395 | spin_lock_init(&config->lock); | 402 | spin_lock_init(&config->lock); |
396 | platform_set_drvdata(pdev, config); | 403 | platform_set_drvdata(pdev, config); |
397 | 404 | ||
@@ -401,42 +408,19 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) | |||
401 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", | 408 | dev_err(&pdev->dev, "can't register RTC device, err %ld\n", |
402 | PTR_ERR(config->rtc)); | 409 | PTR_ERR(config->rtc)); |
403 | status = PTR_ERR(config->rtc); | 410 | status = PTR_ERR(config->rtc); |
404 | goto err_iounmap; | 411 | goto err_disable_clock; |
405 | } | ||
406 | |||
407 | /* alarm irqs */ | ||
408 | irq = platform_get_irq(pdev, 0); | ||
409 | if (irq < 0) { | ||
410 | dev_err(&pdev->dev, "no update irq?\n"); | ||
411 | status = irq; | ||
412 | goto err_clear_platdata; | ||
413 | } | 412 | } |
414 | 413 | ||
415 | status = request_irq(irq, spear_rtc_irq, 0, pdev->name, config); | 414 | config->rtc->uie_unsupported = 1; |
416 | if (status) { | ||
417 | dev_err(&pdev->dev, "Alarm interrupt IRQ%d already \ | ||
418 | claimed\n", irq); | ||
419 | goto err_clear_platdata; | ||
420 | } | ||
421 | 415 | ||
422 | if (!device_can_wakeup(&pdev->dev)) | 416 | if (!device_can_wakeup(&pdev->dev)) |
423 | device_init_wakeup(&pdev->dev, 1); | 417 | device_init_wakeup(&pdev->dev, 1); |
424 | 418 | ||
425 | return 0; | 419 | return 0; |
426 | 420 | ||
427 | err_clear_platdata: | ||
428 | platform_set_drvdata(pdev, NULL); | ||
429 | rtc_device_unregister(config->rtc); | ||
430 | err_iounmap: | ||
431 | iounmap(config->ioaddr); | ||
432 | err_disable_clock: | 421 | err_disable_clock: |
433 | clk_disable(config->clk); | 422 | platform_set_drvdata(pdev, NULL); |
434 | err_clk_put: | 423 | clk_disable_unprepare(config->clk); |
435 | clk_put(config->clk); | ||
436 | err_kfree: | ||
437 | kfree(config); | ||
438 | err_release_region: | ||
439 | release_mem_region(res->start, resource_size(res)); | ||
440 | 424 | ||
441 | return status; | 425 | return status; |
442 | } | 426 | } |
@@ -444,24 +428,11 @@ err_release_region: | |||
444 | static int __devexit spear_rtc_remove(struct platform_device *pdev) | 428 | static int __devexit spear_rtc_remove(struct platform_device *pdev) |
445 | { | 429 | { |
446 | struct spear_rtc_config *config = platform_get_drvdata(pdev); | 430 | struct spear_rtc_config *config = platform_get_drvdata(pdev); |
447 | int irq; | ||
448 | struct resource *res; | ||
449 | 431 | ||
450 | /* leave rtc running, but disable irqs */ | 432 | rtc_device_unregister(config->rtc); |
451 | spear_rtc_disable_interrupt(config); | 433 | spear_rtc_disable_interrupt(config); |
434 | clk_disable_unprepare(config->clk); | ||
452 | device_init_wakeup(&pdev->dev, 0); | 435 | device_init_wakeup(&pdev->dev, 0); |
453 | irq = platform_get_irq(pdev, 0); | ||
454 | if (irq) | ||
455 | free_irq(irq, pdev); | ||
456 | clk_disable(config->clk); | ||
457 | clk_put(config->clk); | ||
458 | iounmap(config->ioaddr); | ||
459 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
460 | if (res) | ||
461 | release_mem_region(res->start, resource_size(res)); | ||
462 | platform_set_drvdata(pdev, NULL); | ||
463 | rtc_device_unregister(config->rtc); | ||
464 | kfree(config); | ||
465 | 436 | ||
466 | return 0; | 437 | return 0; |
467 | } | 438 | } |
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 7e96254bd365..974b9ae252ab 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c | |||
@@ -152,24 +152,24 @@ static int __init test_init(void) | |||
152 | 152 | ||
153 | if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { | 153 | if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) { |
154 | err = -ENOMEM; | 154 | err = -ENOMEM; |
155 | goto exit_free_test0; | 155 | goto exit_put_test0; |
156 | } | 156 | } |
157 | 157 | ||
158 | if ((err = platform_device_add(test0))) | 158 | if ((err = platform_device_add(test0))) |
159 | goto exit_free_test1; | 159 | goto exit_put_test1; |
160 | 160 | ||
161 | if ((err = platform_device_add(test1))) | 161 | if ((err = platform_device_add(test1))) |
162 | goto exit_device_unregister; | 162 | goto exit_del_test0; |
163 | 163 | ||
164 | return 0; | 164 | return 0; |
165 | 165 | ||
166 | exit_device_unregister: | 166 | exit_del_test0: |
167 | platform_device_unregister(test0); | 167 | platform_device_del(test0); |
168 | 168 | ||
169 | exit_free_test1: | 169 | exit_put_test1: |
170 | platform_device_put(test1); | 170 | platform_device_put(test1); |
171 | 171 | ||
172 | exit_free_test0: | 172 | exit_put_test0: |
173 | platform_device_put(test0); | 173 | platform_device_put(test0); |
174 | 174 | ||
175 | exit_driver_unregister: | 175 | exit_driver_unregister: |
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 073108dcf9e7..22eb4ebfa1a6 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c | |||
@@ -247,6 +247,13 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev) | |||
247 | return ret; | 247 | return ret; |
248 | 248 | ||
249 | dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); | 249 | dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); |
250 | |||
251 | /* Enable RTC digital power domain */ | ||
252 | ret = regmap_update_bits(tps65910->regmap, TPS65910_DEVCTRL, | ||
253 | DEVCTRL_RTC_PWDN_MASK, 0 << DEVCTRL_RTC_PWDN_SHIFT); | ||
254 | if (ret < 0) | ||
255 | return ret; | ||
256 | |||
250 | rtc_reg = TPS65910_RTC_CTRL_STOP_RTC; | 257 | rtc_reg = TPS65910_RTC_CTRL_STOP_RTC; |
251 | ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg); | 258 | ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg); |
252 | if (ret < 0) | 259 | if (ret < 0) |
@@ -261,7 +268,7 @@ static int __devinit tps65910_rtc_probe(struct platform_device *pdev) | |||
261 | 268 | ||
262 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 269 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
263 | tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, | 270 | tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, |
264 | "rtc-tps65910", &pdev->dev); | 271 | dev_name(&pdev->dev), &pdev->dev); |
265 | if (ret < 0) { | 272 | if (ret < 0) { |
266 | dev_err(&pdev->dev, "IRQ is not free.\n"); | 273 | dev_err(&pdev->dev, "IRQ is not free.\n"); |
267 | return ret; | 274 | return ret; |
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 07bf19364a74..14e2d8cfcc83 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c | |||
@@ -210,7 +210,8 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) | |||
210 | struct vt8500_rtc *vt8500_rtc; | 210 | struct vt8500_rtc *vt8500_rtc; |
211 | int ret; | 211 | int ret; |
212 | 212 | ||
213 | vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL); | 213 | vt8500_rtc = devm_kzalloc(&pdev->dev, |
214 | sizeof(struct vt8500_rtc), GFP_KERNEL); | ||
214 | if (!vt8500_rtc) | 215 | if (!vt8500_rtc) |
215 | return -ENOMEM; | 216 | return -ENOMEM; |
216 | 217 | ||
@@ -220,15 +221,13 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) | |||
220 | vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 221 | vt8500_rtc->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
221 | if (!vt8500_rtc->res) { | 222 | if (!vt8500_rtc->res) { |
222 | dev_err(&pdev->dev, "No I/O memory resource defined\n"); | 223 | dev_err(&pdev->dev, "No I/O memory resource defined\n"); |
223 | ret = -ENXIO; | 224 | return -ENXIO; |
224 | goto err_free; | ||
225 | } | 225 | } |
226 | 226 | ||
227 | vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0); | 227 | vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0); |
228 | if (vt8500_rtc->irq_alarm < 0) { | 228 | if (vt8500_rtc->irq_alarm < 0) { |
229 | dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); | 229 | dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); |
230 | ret = -ENXIO; | 230 | return -ENXIO; |
231 | goto err_free; | ||
232 | } | 231 | } |
233 | 232 | ||
234 | vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, | 233 | vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start, |
@@ -236,8 +235,7 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) | |||
236 | "vt8500-rtc"); | 235 | "vt8500-rtc"); |
237 | if (vt8500_rtc->res == NULL) { | 236 | if (vt8500_rtc->res == NULL) { |
238 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | 237 | dev_err(&pdev->dev, "failed to request I/O memory\n"); |
239 | ret = -EBUSY; | 238 | return -EBUSY; |
240 | goto err_free; | ||
241 | } | 239 | } |
242 | 240 | ||
243 | vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start, | 241 | vt8500_rtc->regbase = ioremap(vt8500_rtc->res->start, |
@@ -278,8 +276,6 @@ err_unmap: | |||
278 | err_release: | 276 | err_release: |
279 | release_mem_region(vt8500_rtc->res->start, | 277 | release_mem_region(vt8500_rtc->res->start, |
280 | resource_size(vt8500_rtc->res)); | 278 | resource_size(vt8500_rtc->res)); |
281 | err_free: | ||
282 | kfree(vt8500_rtc); | ||
283 | return ret; | 279 | return ret; |
284 | } | 280 | } |
285 | 281 | ||
@@ -297,7 +293,6 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev) | |||
297 | release_mem_region(vt8500_rtc->res->start, | 293 | release_mem_region(vt8500_rtc->res->start, |
298 | resource_size(vt8500_rtc->res)); | 294 | resource_size(vt8500_rtc->res)); |
299 | 295 | ||
300 | kfree(vt8500_rtc); | ||
301 | platform_set_drvdata(pdev, NULL); | 296 | platform_set_drvdata(pdev, NULL); |
302 | 297 | ||
303 | return 0; | 298 | return 0; |
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 2ebe03a4b51d..4a909d7cfde1 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c | |||
@@ -2144,7 +2144,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) | |||
2144 | */ | 2144 | */ |
2145 | port_id = fip->port_id; | 2145 | port_id = fip->port_id; |
2146 | if (fip->probe_tries) | 2146 | if (fip->probe_tries) |
2147 | port_id = prandom32(&fip->rnd_state) & 0xffff; | 2147 | port_id = prandom_u32_state(&fip->rnd_state) & 0xffff; |
2148 | else if (!port_id) | 2148 | else if (!port_id) |
2149 | port_id = fip->lp->wwpn & 0xffff; | 2149 | port_id = fip->lp->wwpn & 0xffff; |
2150 | if (!port_id || port_id == 0xffff) | 2150 | if (!port_id || port_id == 0xffff) |
@@ -2169,7 +2169,7 @@ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) | |||
2169 | static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) | 2169 | static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) |
2170 | { | 2170 | { |
2171 | fip->probe_tries = 0; | 2171 | fip->probe_tries = 0; |
2172 | prandom32_seed(&fip->rnd_state, fip->lp->wwpn); | 2172 | prandom_seed_state(&fip->rnd_state, fip->lp->wwpn); |
2173 | fcoe_ctlr_vn_restart(fip); | 2173 | fcoe_ctlr_vn_restart(fip); |
2174 | } | 2174 | } |
2175 | 2175 | ||
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 57cc9c6eaa9f..f1c6c5470b92 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -251,7 +251,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) | |||
251 | /* best case is 32bit-aligned source address */ | 251 | /* best case is 32bit-aligned source address */ |
252 | if ((0x02 & (unsigned long) src) == 0) { | 252 | if ((0x02 & (unsigned long) src) == 0) { |
253 | if (len >= 4) { | 253 | if (len >= 4) { |
254 | writesl(fifo, src + index, len >> 2); | 254 | iowrite32_rep(fifo, src + index, len >> 2); |
255 | index += len & ~0x03; | 255 | index += len & ~0x03; |
256 | } | 256 | } |
257 | if (len & 0x02) { | 257 | if (len & 0x02) { |
@@ -260,7 +260,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) | |||
260 | } | 260 | } |
261 | } else { | 261 | } else { |
262 | if (len >= 2) { | 262 | if (len >= 2) { |
263 | writesw(fifo, src + index, len >> 1); | 263 | iowrite16_rep(fifo, src + index, len >> 1); |
264 | index += len & ~0x01; | 264 | index += len & ~0x01; |
265 | } | 265 | } |
266 | } | 266 | } |
@@ -268,7 +268,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) | |||
268 | musb_writeb(fifo, 0, src[index]); | 268 | musb_writeb(fifo, 0, src[index]); |
269 | } else { | 269 | } else { |
270 | /* byte aligned */ | 270 | /* byte aligned */ |
271 | writesb(fifo, src, len); | 271 | iowrite8_rep(fifo, src, len); |
272 | } | 272 | } |
273 | } | 273 | } |
274 | 274 | ||
@@ -294,7 +294,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | |||
294 | /* best case is 32bit-aligned destination address */ | 294 | /* best case is 32bit-aligned destination address */ |
295 | if ((0x02 & (unsigned long) dst) == 0) { | 295 | if ((0x02 & (unsigned long) dst) == 0) { |
296 | if (len >= 4) { | 296 | if (len >= 4) { |
297 | readsl(fifo, dst, len >> 2); | 297 | ioread32_rep(fifo, dst, len >> 2); |
298 | index = len & ~0x03; | 298 | index = len & ~0x03; |
299 | } | 299 | } |
300 | if (len & 0x02) { | 300 | if (len & 0x02) { |
@@ -303,7 +303,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | |||
303 | } | 303 | } |
304 | } else { | 304 | } else { |
305 | if (len >= 2) { | 305 | if (len >= 2) { |
306 | readsw(fifo, dst, len >> 1); | 306 | ioread16_rep(fifo, dst, len >> 1); |
307 | index = len & ~0x01; | 307 | index = len & ~0x01; |
308 | } | 308 | } |
309 | } | 309 | } |
@@ -311,7 +311,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) | |||
311 | dst[index] = musb_readb(fifo, 0); | 311 | dst[index] = musb_readb(fifo, 0); |
312 | } else { | 312 | } else { |
313 | /* byte aligned */ | 313 | /* byte aligned */ |
314 | readsb(fifo, dst, len); | 314 | ioread8_rep(fifo, dst, len); |
315 | } | 315 | } |
316 | } | 316 | } |
317 | #endif | 317 | #endif |
diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 565ad1617832..eebeed78edd6 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h | |||
@@ -37,27 +37,6 @@ | |||
37 | 37 | ||
38 | #include <linux/io.h> | 38 | #include <linux/io.h> |
39 | 39 | ||
40 | #if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ | ||
41 | && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ | ||
42 | && !defined(CONFIG_PPC64) && !defined(CONFIG_BLACKFIN) \ | ||
43 | && !defined(CONFIG_MIPS) && !defined(CONFIG_M68K) \ | ||
44 | && !defined(CONFIG_XTENSA) | ||
45 | static inline void readsl(const void __iomem *addr, void *buf, int len) | ||
46 | { insl((unsigned long)addr, buf, len); } | ||
47 | static inline void readsw(const void __iomem *addr, void *buf, int len) | ||
48 | { insw((unsigned long)addr, buf, len); } | ||
49 | static inline void readsb(const void __iomem *addr, void *buf, int len) | ||
50 | { insb((unsigned long)addr, buf, len); } | ||
51 | |||
52 | static inline void writesl(const void __iomem *addr, const void *buf, int len) | ||
53 | { outsl((unsigned long)addr, buf, len); } | ||
54 | static inline void writesw(const void __iomem *addr, const void *buf, int len) | ||
55 | { outsw((unsigned long)addr, buf, len); } | ||
56 | static inline void writesb(const void __iomem *addr, const void *buf, int len) | ||
57 | { outsb((unsigned long)addr, buf, len); } | ||
58 | |||
59 | #endif | ||
60 | |||
61 | #ifndef CONFIG_BLACKFIN | 40 | #ifndef CONFIG_BLACKFIN |
62 | 41 | ||
63 | /* NOTE: these offsets are all in bytes */ | 42 | /* NOTE: these offsets are all in bytes */ |
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 8bde6fc5eb75..3969813c217d 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/prefetch.h> | 22 | #include <linux/prefetch.h> |
23 | #include <linux/usb.h> | 23 | #include <linux/usb.h> |
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/io.h> | ||
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
26 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
27 | #include <linux/usb/nop-usb-xceiv.h> | 28 | #include <linux/usb/nop-usb-xceiv.h> |
@@ -198,7 +199,7 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf) | |||
198 | /* Best case is 32bit-aligned destination address */ | 199 | /* Best case is 32bit-aligned destination address */ |
199 | if ((0x02 & (unsigned long) buf) == 0) { | 200 | if ((0x02 & (unsigned long) buf) == 0) { |
200 | if (len >= 4) { | 201 | if (len >= 4) { |
201 | writesl(fifo, buf, len >> 2); | 202 | iowrite32_rep(fifo, buf, len >> 2); |
202 | buf += (len & ~0x03); | 203 | buf += (len & ~0x03); |
203 | len &= 0x03; | 204 | len &= 0x03; |
204 | } | 205 | } |
@@ -245,7 +246,7 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *buf) | |||
245 | /* Best case is 32bit-aligned destination address */ | 246 | /* Best case is 32bit-aligned destination address */ |
246 | if ((0x02 & (unsigned long) buf) == 0) { | 247 | if ((0x02 & (unsigned long) buf) == 0) { |
247 | if (len >= 4) { | 248 | if (len >= 4) { |
248 | readsl(fifo, buf, len >> 2); | 249 | ioread32_rep(fifo, buf, len >> 2); |
249 | buf += (len & ~0x03); | 250 | buf += (len & ~0x03); |
250 | len &= 0x03; | 251 | len &= 0x03; |
251 | } | 252 | } |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index b7ec34c57f46..c072ed9aea36 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
@@ -117,8 +117,8 @@ static int pm860x_backlight_set(struct backlight_device *bl, int brightness) | |||
117 | data->current_brightness = value; | 117 | data->current_brightness = value; |
118 | return 0; | 118 | return 0; |
119 | out: | 119 | out: |
120 | dev_dbg(chip->dev, "set brightness %d failure with return " | 120 | dev_dbg(chip->dev, "set brightness %d failure with return value: %d\n", |
121 | "value:%d\n", value, ret); | 121 | value, ret); |
122 | return ret; | 122 | return ret; |
123 | } | 123 | } |
124 | 124 | ||
@@ -208,22 +208,19 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
208 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle"); | 208 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "duty cycle"); |
209 | if (!res) { | 209 | if (!res) { |
210 | dev_err(&pdev->dev, "No REG resource for duty cycle\n"); | 210 | dev_err(&pdev->dev, "No REG resource for duty cycle\n"); |
211 | ret = -ENXIO; | 211 | return -ENXIO; |
212 | goto out; | ||
213 | } | 212 | } |
214 | data->reg_duty_cycle = res->start; | 213 | data->reg_duty_cycle = res->start; |
215 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on"); | 214 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "always on"); |
216 | if (!res) { | 215 | if (!res) { |
217 | dev_err(&pdev->dev, "No REG resorce for always on\n"); | 216 | dev_err(&pdev->dev, "No REG resorce for always on\n"); |
218 | ret = -ENXIO; | 217 | return -ENXIO; |
219 | goto out; | ||
220 | } | 218 | } |
221 | data->reg_always_on = res->start; | 219 | data->reg_always_on = res->start; |
222 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current"); | 220 | res = platform_get_resource_byname(pdev, IORESOURCE_REG, "current"); |
223 | if (!res) { | 221 | if (!res) { |
224 | dev_err(&pdev->dev, "No REG resource for current\n"); | 222 | dev_err(&pdev->dev, "No REG resource for current\n"); |
225 | ret = -ENXIO; | 223 | return -ENXIO; |
226 | goto out; | ||
227 | } | 224 | } |
228 | data->reg_current = res->start; | 225 | data->reg_current = res->start; |
229 | 226 | ||
@@ -231,8 +228,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
231 | sprintf(name, "backlight-%d", pdev->id); | 228 | sprintf(name, "backlight-%d", pdev->id); |
232 | data->port = pdev->id; | 229 | data->port = pdev->id; |
233 | data->chip = chip; | 230 | data->chip = chip; |
234 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client \ | 231 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; |
235 | : chip->companion; | ||
236 | data->current_brightness = MAX_BRIGHTNESS; | 232 | data->current_brightness = MAX_BRIGHTNESS; |
237 | if (pm860x_backlight_dt_init(pdev, data, name)) { | 233 | if (pm860x_backlight_dt_init(pdev, data, name)) { |
238 | if (pdata) { | 234 | if (pdata) { |
@@ -263,8 +259,6 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
263 | return 0; | 259 | return 0; |
264 | out_brt: | 260 | out_brt: |
265 | backlight_device_unregister(bl); | 261 | backlight_device_unregister(bl); |
266 | out: | ||
267 | devm_kfree(&pdev->dev, data); | ||
268 | return ret; | 262 | return ret; |
269 | } | 263 | } |
270 | 264 | ||
diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index df1cbb7ef6ca..de5e5e74e2a7 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c | |||
@@ -106,10 +106,9 @@ static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl) | |||
106 | pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD, | 106 | pwm_channel_writel(&pwmbl->pwmc, PWM_CPRD, |
107 | pwmbl->pdata->pwm_compare_max); | 107 | pwmbl->pdata->pwm_compare_max); |
108 | 108 | ||
109 | dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver " | 109 | dev_info(&pwmbl->pdev->dev, "Atmel PWM backlight driver (%lu Hz)\n", |
110 | "(%lu Hz)\n", pwmbl->pwmc.mck / | 110 | pwmbl->pwmc.mck / pwmbl->pdata->pwm_compare_max / |
111 | pwmbl->pdata->pwm_compare_max / | 111 | (1 << prescale)); |
112 | (1 << prescale)); | ||
113 | 112 | ||
114 | return pwm_channel_enable(&pwmbl->pwmc); | 113 | return pwm_channel_enable(&pwmbl->pwmc); |
115 | } | 114 | } |
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 297db2fa91f5..345f6660d4b3 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c | |||
@@ -370,6 +370,35 @@ void backlight_device_unregister(struct backlight_device *bd) | |||
370 | } | 370 | } |
371 | EXPORT_SYMBOL(backlight_device_unregister); | 371 | EXPORT_SYMBOL(backlight_device_unregister); |
372 | 372 | ||
373 | #ifdef CONFIG_OF | ||
374 | static int of_parent_match(struct device *dev, void *data) | ||
375 | { | ||
376 | return dev->parent && dev->parent->of_node == data; | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * of_find_backlight_by_node() - find backlight device by device-tree node | ||
381 | * @node: device-tree node of the backlight device | ||
382 | * | ||
383 | * Returns a pointer to the backlight device corresponding to the given DT | ||
384 | * node or NULL if no such backlight device exists or if the device hasn't | ||
385 | * been probed yet. | ||
386 | * | ||
387 | * This function obtains a reference on the backlight device and it is the | ||
388 | * caller's responsibility to drop the reference by calling put_device() on | ||
389 | * the backlight device's .dev field. | ||
390 | */ | ||
391 | struct backlight_device *of_find_backlight_by_node(struct device_node *node) | ||
392 | { | ||
393 | struct device *dev; | ||
394 | |||
395 | dev = class_find_device(backlight_class, NULL, node, of_parent_match); | ||
396 | |||
397 | return dev ? to_backlight_device(dev) : NULL; | ||
398 | } | ||
399 | EXPORT_SYMBOL(of_find_backlight_by_node); | ||
400 | #endif | ||
401 | |||
373 | static void __exit backlight_class_exit(void) | 402 | static void __exit backlight_class_exit(void) |
374 | { | 403 | { |
375 | class_destroy(backlight_class); | 404 | class_destroy(backlight_class); |
diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index eaaebf21993e..e323fcbe884e 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c | |||
@@ -6,8 +6,8 @@ | |||
6 | * Based on Sharp's 2.4 Backlight Driver | 6 | * Based on Sharp's 2.4 Backlight Driver |
7 | * | 7 | * |
8 | * Copyright (c) 2008 Marvell International Ltd. | 8 | * Copyright (c) 2008 Marvell International Ltd. |
9 | * Converted to SPI device based LCD/Backlight device driver | 9 | * Converted to SPI device based LCD/Backlight device driver |
10 | * by Eric Miao <eric.miao@marvell.com> | 10 | * by Eric Miao <eric.miao@marvell.com> |
11 | * | 11 | * |
12 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License version 2 as | 13 | * it under the terms of the GNU General Public License version 2 as |
@@ -192,7 +192,7 @@ static void lcdtg_set_phadadj(struct corgi_lcd *lcd, int mode) | |||
192 | { | 192 | { |
193 | int adj; | 193 | int adj; |
194 | 194 | ||
195 | switch(mode) { | 195 | switch (mode) { |
196 | case CORGI_LCD_MODE_VGA: | 196 | case CORGI_LCD_MODE_VGA: |
197 | /* Setting for VGA */ | 197 | /* Setting for VGA */ |
198 | adj = sharpsl_param.phadadj; | 198 | adj = sharpsl_param.phadadj; |
@@ -409,10 +409,10 @@ static int corgi_bl_set_intensity(struct corgi_lcd *lcd, int intensity) | |||
409 | cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted; | 409 | cont = !!(intensity & 0x20) ^ lcd->gpio_backlight_cont_inverted; |
410 | 410 | ||
411 | if (gpio_is_valid(lcd->gpio_backlight_cont)) | 411 | if (gpio_is_valid(lcd->gpio_backlight_cont)) |
412 | gpio_set_value(lcd->gpio_backlight_cont, cont); | 412 | gpio_set_value_cansleep(lcd->gpio_backlight_cont, cont); |
413 | 413 | ||
414 | if (gpio_is_valid(lcd->gpio_backlight_on)) | 414 | if (gpio_is_valid(lcd->gpio_backlight_on)) |
415 | gpio_set_value(lcd->gpio_backlight_on, intensity); | 415 | gpio_set_value_cansleep(lcd->gpio_backlight_on, intensity); |
416 | 416 | ||
417 | if (lcd->kick_battery) | 417 | if (lcd->kick_battery) |
418 | lcd->kick_battery(); | 418 | lcd->kick_battery(); |
@@ -495,8 +495,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, | |||
495 | err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on, | 495 | err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_on, |
496 | "BL_ON"); | 496 | "BL_ON"); |
497 | if (err) { | 497 | if (err) { |
498 | dev_err(&spi->dev, "failed to request GPIO%d for " | 498 | dev_err(&spi->dev, |
499 | "backlight_on\n", pdata->gpio_backlight_on); | 499 | "failed to request GPIO%d for backlight_on\n", |
500 | pdata->gpio_backlight_on); | ||
500 | return err; | 501 | return err; |
501 | } | 502 | } |
502 | 503 | ||
@@ -508,8 +509,9 @@ static int setup_gpio_backlight(struct corgi_lcd *lcd, | |||
508 | err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont, | 509 | err = devm_gpio_request(&spi->dev, pdata->gpio_backlight_cont, |
509 | "BL_CONT"); | 510 | "BL_CONT"); |
510 | if (err) { | 511 | if (err) { |
511 | dev_err(&spi->dev, "failed to request GPIO%d for " | 512 | dev_err(&spi->dev, |
512 | "backlight_cont\n", pdata->gpio_backlight_cont); | 513 | "failed to request GPIO%d for backlight_cont\n", |
514 | pdata->gpio_backlight_cont); | ||
513 | return err; | 515 | return err; |
514 | } | 516 | } |
515 | 517 | ||
diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 573c7ece0fde..8179cef0730f 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c | |||
@@ -2,10 +2,10 @@ | |||
2 | * Backlight driver for Dialog Semiconductor DA9030/DA9034 | 2 | * Backlight driver for Dialog Semiconductor DA9030/DA9034 |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Compulab, Ltd. | 4 | * Copyright (C) 2008 Compulab, Ltd. |
5 | * Mike Rapoport <mike@compulab.co.il> | 5 | * Mike Rapoport <mike@compulab.co.il> |
6 | * | 6 | * |
7 | * Copyright (C) 2006-2008 Marvell International Ltd. | 7 | * Copyright (C) 2006-2008 Marvell International Ltd. |
8 | * Eric Miao <eric.miao@marvell.com> | 8 | * Eric Miao <eric.miao@marvell.com> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
@@ -164,15 +164,14 @@ static int da903x_backlight_remove(struct platform_device *pdev) | |||
164 | #ifdef CONFIG_PM | 164 | #ifdef CONFIG_PM |
165 | static int da903x_backlight_suspend(struct device *dev) | 165 | static int da903x_backlight_suspend(struct device *dev) |
166 | { | 166 | { |
167 | struct platform_device *pdev = to_platform_device(dev); | 167 | struct backlight_device *bl = dev_get_drvdata(dev); |
168 | struct backlight_device *bl = platform_get_drvdata(pdev); | 168 | |
169 | return da903x_backlight_set(bl, 0); | 169 | return da903x_backlight_set(bl, 0); |
170 | } | 170 | } |
171 | 171 | ||
172 | static int da903x_backlight_resume(struct device *dev) | 172 | static int da903x_backlight_resume(struct device *dev) |
173 | { | 173 | { |
174 | struct platform_device *pdev = to_platform_device(dev); | 174 | struct backlight_device *bl = dev_get_drvdata(dev); |
175 | struct backlight_device *bl = platform_get_drvdata(pdev); | ||
176 | 175 | ||
177 | backlight_update_status(bl); | 176 | backlight_update_status(bl); |
178 | return 0; | 177 | return 0; |
@@ -199,7 +198,7 @@ static struct platform_driver da903x_backlight_driver = { | |||
199 | module_platform_driver(da903x_backlight_driver); | 198 | module_platform_driver(da903x_backlight_driver); |
200 | 199 | ||
201 | MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); | 200 | MODULE_DESCRIPTION("Backlight Driver for Dialog Semiconductor DA9030/DA9034"); |
202 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" | 201 | MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); |
203 | "Mike Rapoport <mike@compulab.co.il>"); | 202 | MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); |
204 | MODULE_LICENSE("GPL"); | 203 | MODULE_LICENSE("GPL"); |
205 | MODULE_ALIAS("platform:da903x-backlight"); | 204 | MODULE_ALIAS("platform:da903x-backlight"); |
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c index ac196181fe45..842da5a3ac4f 100644 --- a/drivers/video/backlight/da9052_bl.c +++ b/drivers/video/backlight/da9052_bl.c | |||
@@ -34,7 +34,7 @@ enum { | |||
34 | DA9052_TYPE_WLED3, | 34 | DA9052_TYPE_WLED3, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static unsigned char wled_bank[] = { | 37 | static const unsigned char wled_bank[] = { |
38 | DA9052_LED1_CONF_REG, | 38 | DA9052_LED1_CONF_REG, |
39 | DA9052_LED2_CONF_REG, | 39 | DA9052_LED2_CONF_REG, |
40 | DA9052_LED3_CONF_REG, | 40 | DA9052_LED3_CONF_REG, |
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c index 8c660fcd250d..0ae155be9c89 100644 --- a/drivers/video/backlight/generic_bl.c +++ b/drivers/video/backlight/generic_bl.c | |||
@@ -97,8 +97,8 @@ static int genericbl_probe(struct platform_device *pdev) | |||
97 | props.max_brightness = machinfo->max_intensity; | 97 | props.max_brightness = machinfo->max_intensity; |
98 | bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops, | 98 | bd = backlight_device_register(name, &pdev->dev, NULL, &genericbl_ops, |
99 | &props); | 99 | &props); |
100 | if (IS_ERR (bd)) | 100 | if (IS_ERR(bd)) |
101 | return PTR_ERR (bd); | 101 | return PTR_ERR(bd); |
102 | 102 | ||
103 | platform_set_drvdata(pdev, bd); | 103 | platform_set_drvdata(pdev, bd); |
104 | 104 | ||
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index c99966342448..5cefd73526f8 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #define HP680_DEFAULT_INTENSITY 10 | 26 | #define HP680_DEFAULT_INTENSITY 10 |
27 | 27 | ||
28 | static int hp680bl_suspended; | 28 | static int hp680bl_suspended; |
29 | static int current_intensity = 0; | 29 | static int current_intensity; |
30 | static DEFINE_SPINLOCK(bl_lock); | 30 | static DEFINE_SPINLOCK(bl_lock); |
31 | 31 | ||
32 | static void hp680bl_send_intensity(struct backlight_device *bd) | 32 | static void hp680bl_send_intensity(struct backlight_device *bd) |
@@ -168,7 +168,7 @@ static int __init hp680bl_init(void) | |||
168 | static void __exit hp680bl_exit(void) | 168 | static void __exit hp680bl_exit(void) |
169 | { | 169 | { |
170 | platform_device_unregister(hp680bl_device); | 170 | platform_device_unregister(hp680bl_device); |
171 | platform_driver_unregister(&hp680bl_driver); | 171 | platform_driver_unregister(&hp680bl_driver); |
172 | } | 172 | } |
173 | 173 | ||
174 | module_init(hp680bl_init); | 174 | module_init(hp680bl_init); |
diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c index 66cc313185ad..1235bf9defc4 100644 --- a/drivers/video/backlight/ili9320.c +++ b/drivers/video/backlight/ili9320.c | |||
@@ -45,7 +45,7 @@ static inline int ili9320_write_spi(struct ili9320 *ili, | |||
45 | /* second message is the data to transfer */ | 45 | /* second message is the data to transfer */ |
46 | 46 | ||
47 | data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE; | 47 | data[0] = spi->id | ILI9320_SPI_DATA | ILI9320_SPI_WRITE; |
48 | data[1] = value >> 8; | 48 | data[1] = value >> 8; |
49 | data[2] = value; | 49 | data[2] = value; |
50 | 50 | ||
51 | return spi_sync(spi->dev, &spi->message); | 51 | return spi_sync(spi->dev, &spi->message); |
@@ -56,11 +56,10 @@ int ili9320_write(struct ili9320 *ili, unsigned int reg, unsigned int value) | |||
56 | dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value); | 56 | dev_dbg(ili->dev, "write: reg=%02x, val=%04x\n", reg, value); |
57 | return ili->write(ili, reg, value); | 57 | return ili->write(ili, reg, value); |
58 | } | 58 | } |
59 | |||
60 | EXPORT_SYMBOL_GPL(ili9320_write); | 59 | EXPORT_SYMBOL_GPL(ili9320_write); |
61 | 60 | ||
62 | int ili9320_write_regs(struct ili9320 *ili, | 61 | int ili9320_write_regs(struct ili9320 *ili, |
63 | struct ili9320_reg *values, | 62 | const struct ili9320_reg *values, |
64 | int nr_values) | 63 | int nr_values) |
65 | { | 64 | { |
66 | int index; | 65 | int index; |
@@ -74,7 +73,6 @@ int ili9320_write_regs(struct ili9320 *ili, | |||
74 | 73 | ||
75 | return 0; | 74 | return 0; |
76 | } | 75 | } |
77 | |||
78 | EXPORT_SYMBOL_GPL(ili9320_write_regs); | 76 | EXPORT_SYMBOL_GPL(ili9320_write_regs); |
79 | 77 | ||
80 | static void ili9320_reset(struct ili9320 *lcd) | 78 | static void ili9320_reset(struct ili9320 *lcd) |
@@ -260,7 +258,6 @@ int ili9320_probe_spi(struct spi_device *spi, | |||
260 | 258 | ||
261 | return ret; | 259 | return ret; |
262 | } | 260 | } |
263 | |||
264 | EXPORT_SYMBOL_GPL(ili9320_probe_spi); | 261 | EXPORT_SYMBOL_GPL(ili9320_probe_spi); |
265 | 262 | ||
266 | int ili9320_remove(struct ili9320 *ili) | 263 | int ili9320_remove(struct ili9320 *ili) |
@@ -271,7 +268,6 @@ int ili9320_remove(struct ili9320 *ili) | |||
271 | 268 | ||
272 | return 0; | 269 | return 0; |
273 | } | 270 | } |
274 | |||
275 | EXPORT_SYMBOL_GPL(ili9320_remove); | 271 | EXPORT_SYMBOL_GPL(ili9320_remove); |
276 | 272 | ||
277 | #ifdef CONFIG_PM | 273 | #ifdef CONFIG_PM |
@@ -296,20 +292,17 @@ int ili9320_suspend(struct ili9320 *lcd, pm_message_t state) | |||
296 | 292 | ||
297 | return 0; | 293 | return 0; |
298 | } | 294 | } |
299 | |||
300 | EXPORT_SYMBOL_GPL(ili9320_suspend); | 295 | EXPORT_SYMBOL_GPL(ili9320_suspend); |
301 | 296 | ||
302 | int ili9320_resume(struct ili9320 *lcd) | 297 | int ili9320_resume(struct ili9320 *lcd) |
303 | { | 298 | { |
304 | dev_info(lcd->dev, "resuming from power state %d\n", lcd->power); | 299 | dev_info(lcd->dev, "resuming from power state %d\n", lcd->power); |
305 | 300 | ||
306 | if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) { | 301 | if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) |
307 | ili9320_write(lcd, ILI9320_POWER1, 0x00); | 302 | ili9320_write(lcd, ILI9320_POWER1, 0x00); |
308 | } | ||
309 | 303 | ||
310 | return ili9320_power(lcd, FB_BLANK_UNBLANK); | 304 | return ili9320_power(lcd, FB_BLANK_UNBLANK); |
311 | } | 305 | } |
312 | |||
313 | EXPORT_SYMBOL_GPL(ili9320_resume); | 306 | EXPORT_SYMBOL_GPL(ili9320_resume); |
314 | #endif | 307 | #endif |
315 | 308 | ||
@@ -318,7 +311,6 @@ void ili9320_shutdown(struct ili9320 *lcd) | |||
318 | { | 311 | { |
319 | ili9320_power(lcd, FB_BLANK_POWERDOWN); | 312 | ili9320_power(lcd, FB_BLANK_POWERDOWN); |
320 | } | 313 | } |
321 | |||
322 | EXPORT_SYMBOL_GPL(ili9320_shutdown); | 314 | EXPORT_SYMBOL_GPL(ili9320_shutdown); |
323 | 315 | ||
324 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); | 316 | MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); |
diff --git a/drivers/video/backlight/ili9320.h b/drivers/video/backlight/ili9320.h index e388eca7cac5..e0db738f7bb9 100644 --- a/drivers/video/backlight/ili9320.h +++ b/drivers/video/backlight/ili9320.h | |||
@@ -63,7 +63,7 @@ extern int ili9320_write(struct ili9320 *ili, | |||
63 | unsigned int reg, unsigned int value); | 63 | unsigned int reg, unsigned int value); |
64 | 64 | ||
65 | extern int ili9320_write_regs(struct ili9320 *ili, | 65 | extern int ili9320_write_regs(struct ili9320 *ili, |
66 | struct ili9320_reg *values, | 66 | const struct ili9320_reg *values, |
67 | int nr_values); | 67 | int nr_values); |
68 | 68 | ||
69 | /* Device probe */ | 69 | /* Device probe */ |
diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index 16f593b64427..fef6ce4fad71 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c | |||
@@ -48,7 +48,7 @@ static int jornada_bl_get_brightness(struct backlight_device *bd) | |||
48 | 48 | ||
49 | jornada_ssp_end(); | 49 | jornada_ssp_end(); |
50 | 50 | ||
51 | return (BL_MAX_BRIGHT - ret); | 51 | return BL_MAX_BRIGHT - ret; |
52 | } | 52 | } |
53 | 53 | ||
54 | static int jornada_bl_update_status(struct backlight_device *bd) | 54 | static int jornada_bl_update_status(struct backlight_device *bd) |
@@ -77,18 +77,23 @@ static int jornada_bl_update_status(struct backlight_device *bd) | |||
77 | goto out; | 77 | goto out; |
78 | } | 78 | } |
79 | 79 | ||
80 | /* at this point we expect that the mcu has accepted | 80 | /* |
81 | our command and is waiting for our new value | 81 | * at this point we expect that the mcu has accepted |
82 | please note that maximum brightness is 255, | 82 | * our command and is waiting for our new value |
83 | but due to physical layout it is equal to 0, so we simply | 83 | * please note that maximum brightness is 255, |
84 | invert the value (MAX VALUE - NEW VALUE). */ | 84 | * but due to physical layout it is equal to 0, so we simply |
85 | if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) != TXDUMMY) { | 85 | * invert the value (MAX VALUE - NEW VALUE). |
86 | */ | ||
87 | if (jornada_ssp_byte(BL_MAX_BRIGHT - bd->props.brightness) | ||
88 | != TXDUMMY) { | ||
86 | pr_err("set brightness failed\n"); | 89 | pr_err("set brightness failed\n"); |
87 | ret = -ETIMEDOUT; | 90 | ret = -ETIMEDOUT; |
88 | } | 91 | } |
89 | 92 | ||
90 | /* If infact we get an TXDUMMY as output we are happy and dont | 93 | /* |
91 | make any further comments about it */ | 94 | * If infact we get an TXDUMMY as output we are happy and dont |
95 | * make any further comments about it | ||
96 | */ | ||
92 | out: | 97 | out: |
93 | jornada_ssp_end(); | 98 | jornada_ssp_end(); |
94 | 99 | ||
@@ -121,9 +126,11 @@ static int jornada_bl_probe(struct platform_device *pdev) | |||
121 | 126 | ||
122 | bd->props.power = FB_BLANK_UNBLANK; | 127 | bd->props.power = FB_BLANK_UNBLANK; |
123 | bd->props.brightness = BL_DEF_BRIGHT; | 128 | bd->props.brightness = BL_DEF_BRIGHT; |
124 | /* note. make sure max brightness is set otherwise | 129 | /* |
125 | you will get seemingly non-related errors when | 130 | * note. make sure max brightness is set otherwise |
126 | trying to change brightness */ | 131 | * you will get seemingly non-related errors when |
132 | * trying to change brightness | ||
133 | */ | ||
127 | jornada_bl_update_status(bd); | 134 | jornada_bl_update_status(bd); |
128 | 135 | ||
129 | platform_set_drvdata(pdev, bd); | 136 | platform_set_drvdata(pdev, bd); |
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index f5aa0a5961d6..9a35196d12d7 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved. | 4 | * Copyright 2007-2009 Freescale Semiconductor, Inc. All Rights Reserved. |
5 | * | 5 | * |
6 | * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> | 6 | * Copyright (c) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> |
7 | * Inspired by Marek Vasut work in l4f00242t03.c | 7 | * Inspired by Marek Vasut work in l4f00242t03.c |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License version 2 as | 10 | * it under the terms of the GNU General Public License version 2 as |
@@ -33,7 +33,6 @@ struct l4f00242t03_priv { | |||
33 | struct regulator *core_reg; | 33 | struct regulator *core_reg; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | |||
37 | static void l4f00242t03_reset(unsigned int gpio) | 36 | static void l4f00242t03_reset(unsigned int gpio) |
38 | { | 37 | { |
39 | pr_debug("l4f00242t03_reset.\n"); | 38 | pr_debug("l4f00242t03_reset.\n"); |
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index a5d0d024bb92..34fb6bd798c8 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c | |||
@@ -108,7 +108,7 @@ static ssize_t lcd_show_power(struct device *dev, struct device_attribute *attr, | |||
108 | static ssize_t lcd_store_power(struct device *dev, | 108 | static ssize_t lcd_store_power(struct device *dev, |
109 | struct device_attribute *attr, const char *buf, size_t count) | 109 | struct device_attribute *attr, const char *buf, size_t count) |
110 | { | 110 | { |
111 | int rc = -ENXIO; | 111 | int rc; |
112 | struct lcd_device *ld = to_lcd_device(dev); | 112 | struct lcd_device *ld = to_lcd_device(dev); |
113 | unsigned long power; | 113 | unsigned long power; |
114 | 114 | ||
@@ -116,6 +116,8 @@ static ssize_t lcd_store_power(struct device *dev, | |||
116 | if (rc) | 116 | if (rc) |
117 | return rc; | 117 | return rc; |
118 | 118 | ||
119 | rc = -ENXIO; | ||
120 | |||
119 | mutex_lock(&ld->ops_lock); | 121 | mutex_lock(&ld->ops_lock); |
120 | if (ld->ops && ld->ops->set_power) { | 122 | if (ld->ops && ld->ops->set_power) { |
121 | pr_debug("set power to %lu\n", power); | 123 | pr_debug("set power to %lu\n", power); |
@@ -144,7 +146,7 @@ static ssize_t lcd_show_contrast(struct device *dev, | |||
144 | static ssize_t lcd_store_contrast(struct device *dev, | 146 | static ssize_t lcd_store_contrast(struct device *dev, |
145 | struct device_attribute *attr, const char *buf, size_t count) | 147 | struct device_attribute *attr, const char *buf, size_t count) |
146 | { | 148 | { |
147 | int rc = -ENXIO; | 149 | int rc; |
148 | struct lcd_device *ld = to_lcd_device(dev); | 150 | struct lcd_device *ld = to_lcd_device(dev); |
149 | unsigned long contrast; | 151 | unsigned long contrast; |
150 | 152 | ||
@@ -152,6 +154,8 @@ static ssize_t lcd_store_contrast(struct device *dev, | |||
152 | if (rc) | 154 | if (rc) |
153 | return rc; | 155 | return rc; |
154 | 156 | ||
157 | rc = -ENXIO; | ||
158 | |||
155 | mutex_lock(&ld->ops_lock); | 159 | mutex_lock(&ld->ops_lock); |
156 | if (ld->ops && ld->ops->set_contrast) { | 160 | if (ld->ops && ld->ops->set_contrast) { |
157 | pr_debug("set contrast to %lu\n", contrast); | 161 | pr_debug("set contrast to %lu\n", contrast); |
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c index 0207bc0a4407..a6d637b5c68f 100644 --- a/drivers/video/backlight/lm3630_bl.c +++ b/drivers/video/backlight/lm3630_bl.c | |||
@@ -37,7 +37,7 @@ enum lm3630_leds { | |||
37 | BLED_2 | 37 | BLED_2 |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static const char *bled_name[] = { | 40 | static const char * const bled_name[] = { |
41 | [BLED_ALL] = "lm3630_bled", /*Bank1 controls all string */ | 41 | [BLED_ALL] = "lm3630_bled", /*Bank1 controls all string */ |
42 | [BLED_1] = "lm3630_bled1", /*Bank1 controls bled1 */ | 42 | [BLED_1] = "lm3630_bled1", /*Bank1 controls bled1 */ |
43 | [BLED_2] = "lm3630_bled2", /*Bank1 or 2 controls bled2 */ | 43 | [BLED_2] = "lm3630_bled2", /*Bank1 or 2 controls bled2 */ |
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index b0e1e8ba4d9f..7ab2d2a04e41 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c | |||
@@ -214,7 +214,7 @@ out_input: | |||
214 | 214 | ||
215 | } | 215 | } |
216 | 216 | ||
217 | static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store); | 217 | static DEVICE_ATTR(bled_mode, S_IWUSR, NULL, lm3639_bled_mode_store); |
218 | 218 | ||
219 | /* torch */ | 219 | /* torch */ |
220 | static void lm3639_torch_brightness_set(struct led_classdev *cdev, | 220 | static void lm3639_torch_brightness_set(struct led_classdev *cdev, |
diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index b29c7071c9db..55819b384701 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c | |||
@@ -31,7 +31,7 @@ struct lms283gf05_seq { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | /* Magic sequences supplied by manufacturer, for details refer to datasheet */ | 33 | /* Magic sequences supplied by manufacturer, for details refer to datasheet */ |
34 | static struct lms283gf05_seq disp_initseq[] = { | 34 | static const struct lms283gf05_seq disp_initseq[] = { |
35 | /* REG, VALUE, DELAY */ | 35 | /* REG, VALUE, DELAY */ |
36 | { 0x07, 0x0000, 0 }, | 36 | { 0x07, 0x0000, 0 }, |
37 | { 0x13, 0x0000, 10 }, | 37 | { 0x13, 0x0000, 10 }, |
@@ -78,7 +78,7 @@ static struct lms283gf05_seq disp_initseq[] = { | |||
78 | { 0x22, 0x0000, 0 } | 78 | { 0x22, 0x0000, 0 } |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static struct lms283gf05_seq disp_pdwnseq[] = { | 81 | static const struct lms283gf05_seq disp_pdwnseq[] = { |
82 | { 0x07, 0x0016, 30 }, | 82 | { 0x07, 0x0016, 30 }, |
83 | 83 | ||
84 | { 0x07, 0x0004, 0 }, | 84 | { 0x07, 0x0004, 0 }, |
@@ -104,7 +104,7 @@ static void lms283gf05_reset(unsigned long gpio, bool inverted) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | static void lms283gf05_toggle(struct spi_device *spi, | 106 | static void lms283gf05_toggle(struct spi_device *spi, |
107 | struct lms283gf05_seq *seq, int sz) | 107 | const struct lms283gf05_seq *seq, int sz) |
108 | { | 108 | { |
109 | char buf[3]; | 109 | char buf[3]; |
110 | int i; | 110 | int i; |
@@ -158,13 +158,10 @@ static int lms283gf05_probe(struct spi_device *spi) | |||
158 | int ret = 0; | 158 | int ret = 0; |
159 | 159 | ||
160 | if (pdata != NULL) { | 160 | if (pdata != NULL) { |
161 | ret = devm_gpio_request(&spi->dev, pdata->reset_gpio, | 161 | ret = devm_gpio_request_one(&spi->dev, pdata->reset_gpio, |
162 | "LMS285GF05 RESET"); | 162 | GPIOF_DIR_OUT | (!pdata->reset_inverted ? |
163 | if (ret) | 163 | GPIOF_INIT_HIGH : GPIOF_INIT_LOW), |
164 | return ret; | 164 | "LMS285GF05 RESET"); |
165 | |||
166 | ret = gpio_direction_output(pdata->reset_gpio, | ||
167 | !pdata->reset_inverted); | ||
168 | if (ret) | 165 | if (ret) |
169 | return ret; | 166 | return ret; |
170 | } | 167 | } |
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c index fd985e0681e9..6e4db0c874c8 100644 --- a/drivers/video/backlight/lp855x_bl.c +++ b/drivers/video/backlight/lp855x_bl.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/backlight.h> | 15 | #include <linux/backlight.h> |
16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
17 | #include <linux/platform_data/lp855x.h> | 17 | #include <linux/platform_data/lp855x.h> |
18 | #include <linux/pwm.h> | ||
18 | 19 | ||
19 | /* Registers */ | 20 | /* Registers */ |
20 | #define BRIGHTNESS_CTRL 0x00 | 21 | #define BRIGHTNESS_CTRL 0x00 |
@@ -34,22 +35,19 @@ struct lp855x { | |||
34 | struct i2c_client *client; | 35 | struct i2c_client *client; |
35 | struct backlight_device *bl; | 36 | struct backlight_device *bl; |
36 | struct device *dev; | 37 | struct device *dev; |
37 | struct mutex xfer_lock; | ||
38 | struct lp855x_platform_data *pdata; | 38 | struct lp855x_platform_data *pdata; |
39 | struct pwm_device *pwm; | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) | 42 | static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) |
42 | { | 43 | { |
43 | int ret; | 44 | int ret; |
44 | 45 | ||
45 | mutex_lock(&lp->xfer_lock); | ||
46 | ret = i2c_smbus_read_byte_data(lp->client, reg); | 46 | ret = i2c_smbus_read_byte_data(lp->client, reg); |
47 | if (ret < 0) { | 47 | if (ret < 0) { |
48 | mutex_unlock(&lp->xfer_lock); | ||
49 | dev_err(lp->dev, "failed to read 0x%.2x\n", reg); | 48 | dev_err(lp->dev, "failed to read 0x%.2x\n", reg); |
50 | return ret; | 49 | return ret; |
51 | } | 50 | } |
52 | mutex_unlock(&lp->xfer_lock); | ||
53 | 51 | ||
54 | *data = (u8)ret; | 52 | *data = (u8)ret; |
55 | return 0; | 53 | return 0; |
@@ -57,13 +55,7 @@ static int lp855x_read_byte(struct lp855x *lp, u8 reg, u8 *data) | |||
57 | 55 | ||
58 | static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) | 56 | static int lp855x_write_byte(struct lp855x *lp, u8 reg, u8 data) |
59 | { | 57 | { |
60 | int ret; | 58 | return i2c_smbus_write_byte_data(lp->client, reg, data); |
61 | |||
62 | mutex_lock(&lp->xfer_lock); | ||
63 | ret = i2c_smbus_write_byte_data(lp->client, reg, data); | ||
64 | mutex_unlock(&lp->xfer_lock); | ||
65 | |||
66 | return ret; | ||
67 | } | 59 | } |
68 | 60 | ||
69 | static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) | 61 | static bool lp855x_is_valid_rom_area(struct lp855x *lp, u8 addr) |
@@ -121,6 +113,28 @@ static int lp855x_init_registers(struct lp855x *lp) | |||
121 | return ret; | 113 | return ret; |
122 | } | 114 | } |
123 | 115 | ||
116 | static void lp855x_pwm_ctrl(struct lp855x *lp, int br, int max_br) | ||
117 | { | ||
118 | unsigned int period = lp->pdata->period_ns; | ||
119 | unsigned int duty = br * period / max_br; | ||
120 | struct pwm_device *pwm; | ||
121 | |||
122 | /* request pwm device with the consumer name */ | ||
123 | if (!lp->pwm) { | ||
124 | pwm = devm_pwm_get(lp->dev, lp->chipname); | ||
125 | if (IS_ERR(pwm)) | ||
126 | return; | ||
127 | |||
128 | lp->pwm = pwm; | ||
129 | } | ||
130 | |||
131 | pwm_config(lp->pwm, duty, period); | ||
132 | if (duty) | ||
133 | pwm_enable(lp->pwm); | ||
134 | else | ||
135 | pwm_disable(lp->pwm); | ||
136 | } | ||
137 | |||
124 | static int lp855x_bl_update_status(struct backlight_device *bl) | 138 | static int lp855x_bl_update_status(struct backlight_device *bl) |
125 | { | 139 | { |
126 | struct lp855x *lp = bl_get_data(bl); | 140 | struct lp855x *lp = bl_get_data(bl); |
@@ -130,12 +144,10 @@ static int lp855x_bl_update_status(struct backlight_device *bl) | |||
130 | bl->props.brightness = 0; | 144 | bl->props.brightness = 0; |
131 | 145 | ||
132 | if (mode == PWM_BASED) { | 146 | if (mode == PWM_BASED) { |
133 | struct lp855x_pwm_data *pd = &lp->pdata->pwm_data; | ||
134 | int br = bl->props.brightness; | 147 | int br = bl->props.brightness; |
135 | int max_br = bl->props.max_brightness; | 148 | int max_br = bl->props.max_brightness; |
136 | 149 | ||
137 | if (pd->pwm_set_intensity) | 150 | lp855x_pwm_ctrl(lp, br, max_br); |
138 | pd->pwm_set_intensity(br, max_br); | ||
139 | 151 | ||
140 | } else if (mode == REGISTER_BASED) { | 152 | } else if (mode == REGISTER_BASED) { |
141 | u8 val = bl->props.brightness; | 153 | u8 val = bl->props.brightness; |
@@ -150,14 +162,7 @@ static int lp855x_bl_get_brightness(struct backlight_device *bl) | |||
150 | struct lp855x *lp = bl_get_data(bl); | 162 | struct lp855x *lp = bl_get_data(bl); |
151 | enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode; | 163 | enum lp855x_brightness_ctrl_mode mode = lp->pdata->mode; |
152 | 164 | ||
153 | if (mode == PWM_BASED) { | 165 | if (mode == REGISTER_BASED) { |
154 | struct lp855x_pwm_data *pd = &lp->pdata->pwm_data; | ||
155 | int max_br = bl->props.max_brightness; | ||
156 | |||
157 | if (pd->pwm_get_intensity) | ||
158 | bl->props.brightness = pd->pwm_get_intensity(max_br); | ||
159 | |||
160 | } else if (mode == REGISTER_BASED) { | ||
161 | u8 val = 0; | 166 | u8 val = 0; |
162 | 167 | ||
163 | lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val); | 168 | lp855x_read_byte(lp, BRIGHTNESS_CTRL, &val); |
@@ -266,8 +271,6 @@ static int lp855x_probe(struct i2c_client *cl, const struct i2c_device_id *id) | |||
266 | lp->chip_id = id->driver_data; | 271 | lp->chip_id = id->driver_data; |
267 | i2c_set_clientdata(cl, lp); | 272 | i2c_set_clientdata(cl, lp); |
268 | 273 | ||
269 | mutex_init(&lp->xfer_lock); | ||
270 | |||
271 | ret = lp855x_init_registers(lp); | 274 | ret = lp855x_init_registers(lp); |
272 | if (ret) { | 275 | if (ret) { |
273 | dev_err(lp->dev, "i2c communication err: %d", ret); | 276 | dev_err(lp->dev, "i2c communication err: %d", ret); |
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index c6bec7aab87b..2c9bce050aa9 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c | |||
@@ -120,15 +120,13 @@ static int max8925_backlight_probe(struct platform_device *pdev) | |||
120 | res = platform_get_resource(pdev, IORESOURCE_REG, 0); | 120 | res = platform_get_resource(pdev, IORESOURCE_REG, 0); |
121 | if (!res) { | 121 | if (!res) { |
122 | dev_err(&pdev->dev, "No REG resource for mode control!\n"); | 122 | dev_err(&pdev->dev, "No REG resource for mode control!\n"); |
123 | ret = -ENXIO; | 123 | return -ENXIO; |
124 | goto out; | ||
125 | } | 124 | } |
126 | data->reg_mode_cntl = res->start; | 125 | data->reg_mode_cntl = res->start; |
127 | res = platform_get_resource(pdev, IORESOURCE_REG, 1); | 126 | res = platform_get_resource(pdev, IORESOURCE_REG, 1); |
128 | if (!res) { | 127 | if (!res) { |
129 | dev_err(&pdev->dev, "No REG resource for control!\n"); | 128 | dev_err(&pdev->dev, "No REG resource for control!\n"); |
130 | ret = -ENXIO; | 129 | return -ENXIO; |
131 | goto out; | ||
132 | } | 130 | } |
133 | data->reg_cntl = res->start; | 131 | data->reg_cntl = res->start; |
134 | 132 | ||
@@ -142,8 +140,7 @@ static int max8925_backlight_probe(struct platform_device *pdev) | |||
142 | &max8925_backlight_ops, &props); | 140 | &max8925_backlight_ops, &props); |
143 | if (IS_ERR(bl)) { | 141 | if (IS_ERR(bl)) { |
144 | dev_err(&pdev->dev, "failed to register backlight\n"); | 142 | dev_err(&pdev->dev, "failed to register backlight\n"); |
145 | ret = PTR_ERR(bl); | 143 | return PTR_ERR(bl); |
146 | goto out; | ||
147 | } | 144 | } |
148 | bl->props.brightness = MAX_BRIGHTNESS; | 145 | bl->props.brightness = MAX_BRIGHTNESS; |
149 | 146 | ||
@@ -166,8 +163,6 @@ static int max8925_backlight_probe(struct platform_device *pdev) | |||
166 | return 0; | 163 | return 0; |
167 | out_brt: | 164 | out_brt: |
168 | backlight_device_unregister(bl); | 165 | backlight_device_unregister(bl); |
169 | out: | ||
170 | devm_kfree(&pdev->dev, data); | ||
171 | return ret; | 166 | return ret; |
172 | } | 167 | } |
173 | 168 | ||
diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 9a046a4c98f5..af31c269baa6 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c | |||
@@ -42,12 +42,12 @@ struct omap_backlight { | |||
42 | struct omap_backlight_config *pdata; | 42 | struct omap_backlight_config *pdata; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static void inline omapbl_send_intensity(int intensity) | 45 | static inline void omapbl_send_intensity(int intensity) |
46 | { | 46 | { |
47 | omap_writeb(intensity, OMAP_PWL_ENABLE); | 47 | omap_writeb(intensity, OMAP_PWL_ENABLE); |
48 | } | 48 | } |
49 | 49 | ||
50 | static void inline omapbl_send_enable(int enable) | 50 | static inline void omapbl_send_enable(int enable) |
51 | { | 51 | { |
52 | omap_writeb(enable, OMAP_PWL_CLK_ENABLE); | 52 | omap_writeb(enable, OMAP_PWL_CLK_ENABLE); |
53 | } | 53 | } |
diff --git a/drivers/video/backlight/pandora_bl.c b/drivers/video/backlight/pandora_bl.c index 4ec30748b447..633b0a22fd64 100644 --- a/drivers/video/backlight/pandora_bl.c +++ b/drivers/video/backlight/pandora_bl.c | |||
@@ -71,8 +71,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl) | |||
71 | * set PWM duty cycle to max. TPS61161 seems to use this | 71 | * set PWM duty cycle to max. TPS61161 seems to use this |
72 | * to calibrate it's PWM sensitivity when it starts. | 72 | * to calibrate it's PWM sensitivity when it starts. |
73 | */ | 73 | */ |
74 | twl_i2c_write_u8(TWL4030_MODULE_PWM0, MAX_VALUE, | 74 | twl_i2c_write_u8(TWL_MODULE_PWM, MAX_VALUE, TWL_PWM0_OFF); |
75 | TWL_PWM0_OFF); | ||
76 | 75 | ||
77 | /* first enable clock, then PWM0 out */ | 76 | /* first enable clock, then PWM0 out */ |
78 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1); | 77 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &r, TWL_INTBR_GPBR1); |
@@ -90,8 +89,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl) | |||
90 | usleep_range(2000, 10000); | 89 | usleep_range(2000, 10000); |
91 | } | 90 | } |
92 | 91 | ||
93 | twl_i2c_write_u8(TWL4030_MODULE_PWM0, MIN_VALUE + brightness, | 92 | twl_i2c_write_u8(TWL_MODULE_PWM, MIN_VALUE + brightness, TWL_PWM0_OFF); |
94 | TWL_PWM0_OFF); | ||
95 | 93 | ||
96 | done: | 94 | done: |
97 | if (brightness != 0) | 95 | if (brightness != 0) |
@@ -132,7 +130,7 @@ static int pandora_backlight_probe(struct platform_device *pdev) | |||
132 | platform_set_drvdata(pdev, bl); | 130 | platform_set_drvdata(pdev, bl); |
133 | 131 | ||
134 | /* 64 cycle period, ON position 0 */ | 132 | /* 64 cycle period, ON position 0 */ |
135 | twl_i2c_write_u8(TWL4030_MODULE_PWM0, 0x80, TWL_PWM0_ON); | 133 | twl_i2c_write_u8(TWL_MODULE_PWM, 0x80, TWL_PWM0_ON); |
136 | 134 | ||
137 | bl->props.state |= PANDORABL_WAS_OFF; | 135 | bl->props.state |= PANDORABL_WAS_OFF; |
138 | bl->props.brightness = MAX_USER_VALUE; | 136 | bl->props.brightness = MAX_USER_VALUE; |
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c index 0087396007e4..e87c7a3394f3 100644 --- a/drivers/video/backlight/pcf50633-backlight.c +++ b/drivers/video/backlight/pcf50633-backlight.c | |||
@@ -52,7 +52,7 @@ int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit) | |||
52 | pcf_bl->brightness_limit = limit & 0x3f; | 52 | pcf_bl->brightness_limit = limit & 0x3f; |
53 | backlight_update_status(pcf_bl->bl); | 53 | backlight_update_status(pcf_bl->bl); |
54 | 54 | ||
55 | return 0; | 55 | return 0; |
56 | } | 56 | } |
57 | 57 | ||
58 | static int pcf50633_bl_update_status(struct backlight_device *bl) | 58 | static int pcf50633_bl_update_status(struct backlight_device *bl) |
@@ -136,8 +136,10 @@ static int pcf50633_bl_probe(struct platform_device *pdev) | |||
136 | 136 | ||
137 | pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time); | 137 | pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time); |
138 | 138 | ||
139 | /* Should be different from bl_props.brightness, so we do not exit | 139 | /* |
140 | * update_status early the first time it's called */ | 140 | * Should be different from bl_props.brightness, so we do not exit |
141 | * update_status early the first time it's called | ||
142 | */ | ||
141 | pcf_bl->brightness = pcf_bl->bl->props.brightness + 1; | 143 | pcf_bl->brightness = pcf_bl->bl->props.brightness + 1; |
142 | 144 | ||
143 | backlight_update_status(pcf_bl->bl); | 145 | backlight_update_status(pcf_bl->bl); |
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index 894bfc5ce422..17a6b83f97af 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c | |||
@@ -27,7 +27,7 @@ struct platform_lcd { | |||
27 | struct plat_lcd_data *pdata; | 27 | struct plat_lcd_data *pdata; |
28 | 28 | ||
29 | unsigned int power; | 29 | unsigned int power; |
30 | unsigned int suspended : 1; | 30 | unsigned int suspended:1; |
31 | }; | 31 | }; |
32 | 32 | ||
33 | static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd) | 33 | static inline struct platform_lcd *to_our_lcd(struct lcd_device *lcd) |
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c index 484e10dd1a8e..3e1c1135f6df 100644 --- a/drivers/video/backlight/s6e63m0.c +++ b/drivers/video/backlight/s6e63m0.c | |||
@@ -757,7 +757,7 @@ static int s6e63m0_probe(struct spi_device *spi) | |||
757 | lcd->spi = spi; | 757 | lcd->spi = spi; |
758 | lcd->dev = &spi->dev; | 758 | lcd->dev = &spi->dev; |
759 | 759 | ||
760 | lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data; | 760 | lcd->lcd_pd = spi->dev.platform_data; |
761 | if (!lcd->lcd_pd) { | 761 | if (!lcd->lcd_pd) { |
762 | dev_err(&spi->dev, "platform data is NULL.\n"); | 762 | dev_err(&spi->dev, "platform data is NULL.\n"); |
763 | return -EFAULT; | 763 | return -EFAULT; |
diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 146ffb9404d1..ad2325f3d652 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels | 2 | * tdo24m - SPI-based drivers for Toppoly TDO24M series LCD panels |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Marvell International Ltd. | 4 | * Copyright (C) 2008 Marvell International Ltd. |
5 | * Eric Miao <eric.miao@marvell.com> | 5 | * Eric Miao <eric.miao@marvell.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -47,7 +47,7 @@ struct tdo24m { | |||
47 | ((x1) << 9) | 0x100 | (x2)) | 47 | ((x1) << 9) | 0x100 | (x2)) |
48 | #define CMD_NULL (-1) | 48 | #define CMD_NULL (-1) |
49 | 49 | ||
50 | static uint32_t lcd_panel_reset[] = { | 50 | static const uint32_t lcd_panel_reset[] = { |
51 | CMD0(0x1), /* reset */ | 51 | CMD0(0x1), /* reset */ |
52 | CMD0(0x0), /* nop */ | 52 | CMD0(0x0), /* nop */ |
53 | CMD0(0x0), /* nop */ | 53 | CMD0(0x0), /* nop */ |
@@ -55,7 +55,7 @@ static uint32_t lcd_panel_reset[] = { | |||
55 | CMD_NULL, | 55 | CMD_NULL, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static uint32_t lcd_panel_on[] = { | 58 | static const uint32_t lcd_panel_on[] = { |
59 | CMD0(0x29), /* Display ON */ | 59 | CMD0(0x29), /* Display ON */ |
60 | CMD2(0xB8, 0xFF, 0xF9), /* Output Control */ | 60 | CMD2(0xB8, 0xFF, 0xF9), /* Output Control */ |
61 | CMD0(0x11), /* Sleep out */ | 61 | CMD0(0x11), /* Sleep out */ |
@@ -63,7 +63,7 @@ static uint32_t lcd_panel_on[] = { | |||
63 | CMD_NULL, | 63 | CMD_NULL, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static uint32_t lcd_panel_off[] = { | 66 | static const uint32_t lcd_panel_off[] = { |
67 | CMD0(0x28), /* Display OFF */ | 67 | CMD0(0x28), /* Display OFF */ |
68 | CMD2(0xB8, 0x80, 0x02), /* Output Control */ | 68 | CMD2(0xB8, 0x80, 0x02), /* Output Control */ |
69 | CMD0(0x10), /* Sleep in */ | 69 | CMD0(0x10), /* Sleep in */ |
@@ -71,7 +71,7 @@ static uint32_t lcd_panel_off[] = { | |||
71 | CMD_NULL, | 71 | CMD_NULL, |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static uint32_t lcd_vga_pass_through_tdo24m[] = { | 74 | static const uint32_t lcd_vga_pass_through_tdo24m[] = { |
75 | CMD1(0xB0, 0x16), | 75 | CMD1(0xB0, 0x16), |
76 | CMD1(0xBC, 0x80), | 76 | CMD1(0xBC, 0x80), |
77 | CMD1(0xE1, 0x00), | 77 | CMD1(0xE1, 0x00), |
@@ -80,7 +80,7 @@ static uint32_t lcd_vga_pass_through_tdo24m[] = { | |||
80 | CMD_NULL, | 80 | CMD_NULL, |
81 | }; | 81 | }; |
82 | 82 | ||
83 | static uint32_t lcd_qvga_pass_through_tdo24m[] = { | 83 | static const uint32_t lcd_qvga_pass_through_tdo24m[] = { |
84 | CMD1(0xB0, 0x16), | 84 | CMD1(0xB0, 0x16), |
85 | CMD1(0xBC, 0x81), | 85 | CMD1(0xBC, 0x81), |
86 | CMD1(0xE1, 0x00), | 86 | CMD1(0xE1, 0x00), |
@@ -89,8 +89,8 @@ static uint32_t lcd_qvga_pass_through_tdo24m[] = { | |||
89 | CMD_NULL, | 89 | CMD_NULL, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | static uint32_t lcd_vga_transfer_tdo24m[] = { | 92 | static const uint32_t lcd_vga_transfer_tdo24m[] = { |
93 | CMD1(0xcf, 0x02), /* Blanking period control (1) */ | 93 | CMD1(0xcf, 0x02), /* Blanking period control (1) */ |
94 | CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ | 94 | CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ |
95 | CMD1(0xd1, 0x01), /* CKV timing control on/off */ | 95 | CMD1(0xd1, 0x01), /* CKV timing control on/off */ |
96 | CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */ | 96 | CMD2(0xd2, 0x14, 0x00), /* CKV 1,2 timing control */ |
@@ -102,7 +102,7 @@ static uint32_t lcd_vga_transfer_tdo24m[] = { | |||
102 | CMD_NULL, | 102 | CMD_NULL, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static uint32_t lcd_qvga_transfer[] = { | 105 | static const uint32_t lcd_qvga_transfer[] = { |
106 | CMD1(0xd6, 0x02), /* Blanking period control (1) */ | 106 | CMD1(0xd6, 0x02), /* Blanking period control (1) */ |
107 | CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */ | 107 | CMD2(0xd7, 0x08, 0x04), /* Blanking period control (2) */ |
108 | CMD1(0xd8, 0x01), /* CKV timing control on/off */ | 108 | CMD1(0xd8, 0x01), /* CKV timing control on/off */ |
@@ -115,7 +115,7 @@ static uint32_t lcd_qvga_transfer[] = { | |||
115 | CMD_NULL, | 115 | CMD_NULL, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static uint32_t lcd_vga_pass_through_tdo35s[] = { | 118 | static const uint32_t lcd_vga_pass_through_tdo35s[] = { |
119 | CMD1(0xB0, 0x16), | 119 | CMD1(0xB0, 0x16), |
120 | CMD1(0xBC, 0x80), | 120 | CMD1(0xBC, 0x80), |
121 | CMD1(0xE1, 0x00), | 121 | CMD1(0xE1, 0x00), |
@@ -123,7 +123,7 @@ static uint32_t lcd_vga_pass_through_tdo35s[] = { | |||
123 | CMD_NULL, | 123 | CMD_NULL, |
124 | }; | 124 | }; |
125 | 125 | ||
126 | static uint32_t lcd_qvga_pass_through_tdo35s[] = { | 126 | static const uint32_t lcd_qvga_pass_through_tdo35s[] = { |
127 | CMD1(0xB0, 0x16), | 127 | CMD1(0xB0, 0x16), |
128 | CMD1(0xBC, 0x81), | 128 | CMD1(0xBC, 0x81), |
129 | CMD1(0xE1, 0x00), | 129 | CMD1(0xE1, 0x00), |
@@ -131,8 +131,8 @@ static uint32_t lcd_qvga_pass_through_tdo35s[] = { | |||
131 | CMD_NULL, | 131 | CMD_NULL, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static uint32_t lcd_vga_transfer_tdo35s[] = { | 134 | static const uint32_t lcd_vga_transfer_tdo35s[] = { |
135 | CMD1(0xcf, 0x02), /* Blanking period control (1) */ | 135 | CMD1(0xcf, 0x02), /* Blanking period control (1) */ |
136 | CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ | 136 | CMD2(0xd0, 0x08, 0x04), /* Blanking period control (2) */ |
137 | CMD1(0xd1, 0x01), /* CKV timing control on/off */ | 137 | CMD1(0xd1, 0x01), /* CKV timing control on/off */ |
138 | CMD2(0xd2, 0x00, 0x1e), /* CKV 1,2 timing control */ | 138 | CMD2(0xd2, 0x00, 0x1e), /* CKV 1,2 timing control */ |
@@ -144,7 +144,7 @@ static uint32_t lcd_vga_transfer_tdo35s[] = { | |||
144 | CMD_NULL, | 144 | CMD_NULL, |
145 | }; | 145 | }; |
146 | 146 | ||
147 | static uint32_t lcd_panel_config[] = { | 147 | static const uint32_t lcd_panel_config[] = { |
148 | CMD2(0xb8, 0xff, 0xf9), /* Output control */ | 148 | CMD2(0xb8, 0xff, 0xf9), /* Output control */ |
149 | CMD0(0x11), /* sleep out */ | 149 | CMD0(0x11), /* sleep out */ |
150 | CMD1(0xba, 0x01), /* Display mode (1) */ | 150 | CMD1(0xba, 0x01), /* Display mode (1) */ |
@@ -175,10 +175,11 @@ static uint32_t lcd_panel_config[] = { | |||
175 | CMD_NULL, | 175 | CMD_NULL, |
176 | }; | 176 | }; |
177 | 177 | ||
178 | static int tdo24m_writes(struct tdo24m *lcd, uint32_t *array) | 178 | static int tdo24m_writes(struct tdo24m *lcd, const uint32_t *array) |
179 | { | 179 | { |
180 | struct spi_transfer *x = &lcd->xfer; | 180 | struct spi_transfer *x = &lcd->xfer; |
181 | uint32_t data, *p = array; | 181 | const uint32_t *p = array; |
182 | uint32_t data; | ||
182 | int nparams, err = 0; | 183 | int nparams, err = 0; |
183 | 184 | ||
184 | for (; *p != CMD_NULL; p++) { | 185 | for (; *p != CMD_NULL; p++) { |
diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index a0521abdcd8a..588682cc1614 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c | |||
@@ -92,14 +92,12 @@ static int tosa_bl_probe(struct i2c_client *client, | |||
92 | 92 | ||
93 | data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; | 93 | data->comadj = sharpsl_param.comadj == -1 ? COMADJ_DEFAULT : sharpsl_param.comadj; |
94 | 94 | ||
95 | ret = devm_gpio_request(&client->dev, TOSA_GPIO_BL_C20MA, "backlight"); | 95 | ret = devm_gpio_request_one(&client->dev, TOSA_GPIO_BL_C20MA, |
96 | GPIOF_OUT_INIT_LOW, "backlight"); | ||
96 | if (ret) { | 97 | if (ret) { |
97 | dev_dbg(&data->bl->dev, "Unable to request gpio!\n"); | 98 | dev_dbg(&data->bl->dev, "Unable to request gpio!\n"); |
98 | return ret; | 99 | return ret; |
99 | } | 100 | } |
100 | ret = gpio_direction_output(TOSA_GPIO_BL_C20MA, 0); | ||
101 | if (ret) | ||
102 | return ret; | ||
103 | 101 | ||
104 | i2c_set_clientdata(client, data); | 102 | i2c_set_clientdata(client, data); |
105 | data->i2c = client; | 103 | data->i2c = client; |
@@ -163,7 +161,6 @@ static const struct i2c_device_id tosa_bl_id[] = { | |||
163 | { }, | 161 | { }, |
164 | }; | 162 | }; |
165 | 163 | ||
166 | |||
167 | static struct i2c_driver tosa_bl_driver = { | 164 | static struct i2c_driver tosa_bl_driver = { |
168 | .driver = { | 165 | .driver = { |
169 | .name = "tosa-bl", | 166 | .name = "tosa-bl", |
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 86fff88c2e4a..96bae941585a 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c | |||
@@ -63,7 +63,7 @@ static int tosa_tg_send(struct spi_device *spi, int adrs, uint8_t data) | |||
63 | int tosa_bl_enable(struct spi_device *spi, int enable) | 63 | int tosa_bl_enable(struct spi_device *spi, int enable) |
64 | { | 64 | { |
65 | /* bl_enable GP04=1 otherwise GP04=0*/ | 65 | /* bl_enable GP04=1 otherwise GP04=0*/ |
66 | return tosa_tg_send(spi, TG_GPODR2, enable? 0x01 : 0x00); | 66 | return tosa_tg_send(spi, TG_GPODR2, enable ? 0x01 : 0x00); |
67 | } | 67 | } |
68 | EXPORT_SYMBOL(tosa_bl_enable); | 68 | EXPORT_SYMBOL(tosa_bl_enable); |
69 | 69 | ||
@@ -91,15 +91,17 @@ static void tosa_lcd_tg_on(struct tosa_lcd_data *data) | |||
91 | tosa_tg_send(spi, TG_PNLCTL, value); | 91 | tosa_tg_send(spi, TG_PNLCTL, value); |
92 | 92 | ||
93 | /* TG LCD pannel power up */ | 93 | /* TG LCD pannel power up */ |
94 | tosa_tg_send(spi, TG_PINICTL,0x4); | 94 | tosa_tg_send(spi, TG_PINICTL, 0x4); |
95 | mdelay(50); | 95 | mdelay(50); |
96 | 96 | ||
97 | /* TG LCD GVSS */ | 97 | /* TG LCD GVSS */ |
98 | tosa_tg_send(spi, TG_PINICTL,0x0); | 98 | tosa_tg_send(spi, TG_PINICTL, 0x0); |
99 | 99 | ||
100 | if (!data->i2c) { | 100 | if (!data->i2c) { |
101 | /* after the pannel is powered up the first time, we can access the i2c bus */ | 101 | /* |
102 | /* so probe for the DAC */ | 102 | * after the pannel is powered up the first time, |
103 | * we can access the i2c bus so probe for the DAC | ||
104 | */ | ||
103 | struct i2c_adapter *adap = i2c_get_adapter(0); | 105 | struct i2c_adapter *adap = i2c_get_adapter(0); |
104 | struct i2c_board_info info = { | 106 | struct i2c_board_info info = { |
105 | .type = "tosa-bl", | 107 | .type = "tosa-bl", |
@@ -115,11 +117,11 @@ static void tosa_lcd_tg_off(struct tosa_lcd_data *data) | |||
115 | struct spi_device *spi = data->spi; | 117 | struct spi_device *spi = data->spi; |
116 | 118 | ||
117 | /* TG LCD VHSA off */ | 119 | /* TG LCD VHSA off */ |
118 | tosa_tg_send(spi, TG_PINICTL,0x4); | 120 | tosa_tg_send(spi, TG_PINICTL, 0x4); |
119 | mdelay(50); | 121 | mdelay(50); |
120 | 122 | ||
121 | /* TG LCD signal off */ | 123 | /* TG LCD signal off */ |
122 | tosa_tg_send(spi, TG_PINICTL,0x6); | 124 | tosa_tg_send(spi, TG_PINICTL, 0x6); |
123 | mdelay(50); | 125 | mdelay(50); |
124 | 126 | ||
125 | /* TG Off */ | 127 | /* TG Off */ |
@@ -193,17 +195,13 @@ static int tosa_lcd_probe(struct spi_device *spi) | |||
193 | data->spi = spi; | 195 | data->spi = spi; |
194 | dev_set_drvdata(&spi->dev, data); | 196 | dev_set_drvdata(&spi->dev, data); |
195 | 197 | ||
196 | ret = devm_gpio_request(&spi->dev, TOSA_GPIO_TG_ON, "tg #pwr"); | 198 | ret = devm_gpio_request_one(&spi->dev, TOSA_GPIO_TG_ON, |
199 | GPIOF_OUT_INIT_LOW, "tg #pwr"); | ||
197 | if (ret < 0) | 200 | if (ret < 0) |
198 | goto err_gpio_tg; | 201 | goto err_gpio_tg; |
199 | 202 | ||
200 | mdelay(60); | 203 | mdelay(60); |
201 | 204 | ||
202 | ret = gpio_direction_output(TOSA_GPIO_TG_ON, 0); | ||
203 | if (ret < 0) | ||
204 | goto err_gpio_tg; | ||
205 | |||
206 | mdelay(60); | ||
207 | tosa_lcd_tg_init(data); | 205 | tosa_lcd_tg_init(data); |
208 | 206 | ||
209 | tosa_lcd_tg_on(data); | 207 | tosa_lcd_tg_on(data); |
diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index 712b0acfd339..45e81b4cf8b4 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | /* Device initialisation sequences */ | 27 | /* Device initialisation sequences */ |
28 | 28 | ||
29 | static struct ili9320_reg vgg_init1[] = { | 29 | static const struct ili9320_reg vgg_init1[] = { |
30 | { | 30 | { |
31 | .address = ILI9320_POWER1, | 31 | .address = ILI9320_POWER1, |
32 | .value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0), | 32 | .value = ILI9320_POWER1_AP(0) | ILI9320_POWER1_BT(0), |
@@ -43,7 +43,7 @@ static struct ili9320_reg vgg_init1[] = { | |||
43 | }, | 43 | }, |
44 | }; | 44 | }; |
45 | 45 | ||
46 | static struct ili9320_reg vgg_init2[] = { | 46 | static const struct ili9320_reg vgg_init2[] = { |
47 | { | 47 | { |
48 | .address = ILI9320_POWER1, | 48 | .address = ILI9320_POWER1, |
49 | .value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE | | 49 | .value = (ILI9320_POWER1_AP(3) | ILI9320_POWER1_APE | |
@@ -54,7 +54,7 @@ static struct ili9320_reg vgg_init2[] = { | |||
54 | } | 54 | } |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static struct ili9320_reg vgg_gamma[] = { | 57 | static const struct ili9320_reg vgg_gamma[] = { |
58 | { | 58 | { |
59 | .address = ILI9320_GAMMA1, | 59 | .address = ILI9320_GAMMA1, |
60 | .value = 0x0000, | 60 | .value = 0x0000, |
@@ -89,7 +89,7 @@ static struct ili9320_reg vgg_gamma[] = { | |||
89 | 89 | ||
90 | }; | 90 | }; |
91 | 91 | ||
92 | static struct ili9320_reg vgg_init0[] = { | 92 | static const struct ili9320_reg vgg_init0[] = { |
93 | [0] = { | 93 | [0] = { |
94 | /* set direction and scan mode gate */ | 94 | /* set direction and scan mode gate */ |
95 | .address = ILI9320_DRIVER, | 95 | .address = ILI9320_DRIVER, |
@@ -217,7 +217,7 @@ static int vgg2432a4_resume(struct spi_device *spi) | |||
217 | } | 217 | } |
218 | #else | 218 | #else |
219 | #define vgg2432a4_suspend NULL | 219 | #define vgg2432a4_suspend NULL |
220 | #define vgg2432a4_resume NULL | 220 | #define vgg2432a4_resume NULL |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | static struct ili9320_client vgg2432a4_client = { | 223 | static struct ili9320_client vgg2432a4_client = { |