diff options
Diffstat (limited to 'drivers')
134 files changed, 4741 insertions, 1342 deletions
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 2059ee460b0c..81e44f7b0ab6 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c | |||
@@ -1567,7 +1567,7 @@ tx_complete++; | |||
1567 | /*--------------------------------- entries ---------------------------------*/ | 1567 | /*--------------------------------- entries ---------------------------------*/ |
1568 | 1568 | ||
1569 | 1569 | ||
1570 | static const char *media_name[] __devinitdata = { | 1570 | static char * const media_name[] __devinitconst = { |
1571 | "MMF", "SMF", "MMF", "03?", /* 0- 3 */ | 1571 | "MMF", "SMF", "MMF", "03?", /* 0- 3 */ |
1572 | "UTP", "05?", "06?", "07?", /* 4- 7 */ | 1572 | "UTP", "05?", "06?", "07?", /* 4- 7 */ |
1573 | "TAXI","09?", "10?", "11?", /* 8-11 */ | 1573 | "TAXI","09?", "10?", "11?", /* 8-11 */ |
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index db195abad698..d2ed7f18d1ac 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | #define VERSION "47" | 2 | #define VERSION "50" |
3 | #define AOE_MAJOR 152 | 3 | #define AOE_MAJOR 152 |
4 | #define DEVICE_NAME "aoe" | 4 | #define DEVICE_NAME "aoe" |
5 | 5 | ||
@@ -10,9 +10,6 @@ | |||
10 | #define AOE_PARTITIONS (16) | 10 | #define AOE_PARTITIONS (16) |
11 | #endif | 11 | #endif |
12 | 12 | ||
13 | #define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor)) | ||
14 | #define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF) | ||
15 | #define AOEMINOR(sysminor) ((sysminor) % NPERSHELF) | ||
16 | #define WHITESPACE " \t\v\f\n" | 13 | #define WHITESPACE " \t\v\f\n" |
17 | 14 | ||
18 | enum { | 15 | enum { |
@@ -75,72 +72,67 @@ enum { | |||
75 | DEVFL_UP = 1, /* device is installed in system and ready for AoE->ATA commands */ | 72 | DEVFL_UP = 1, /* device is installed in system and ready for AoE->ATA commands */ |
76 | 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 */ |
77 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ | 74 | DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ |
78 | DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */ | 75 | DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */ |
79 | DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ | 76 | DEVFL_KICKME = (1<<4), /* slow polling network card catch */ |
80 | DEVFL_KICKME = (1<<5), /* slow polling network card catch */ | 77 | DEVFL_NEWSIZE = (1<<5), /* need to update dev size in block layer */ |
81 | DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ | ||
82 | |||
83 | BUFFL_FAIL = 1, | ||
84 | }; | 78 | }; |
85 | 79 | ||
86 | enum { | 80 | enum { |
87 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ | 81 | DEFAULTBCNT = 2 * 512, /* 2 sectors */ |
88 | NPERSHELF = 16, /* number of slots per shelf address */ | ||
89 | FREETAG = -1, | ||
90 | MIN_BUFS = 16, | 82 | MIN_BUFS = 16, |
91 | NTARGETS = 8, | 83 | NTARGETS = 8, |
92 | NAOEIFS = 8, | 84 | NAOEIFS = 8, |
93 | NSKBPOOLMAX = 128, | 85 | NSKBPOOLMAX = 256, |
86 | NFACTIVE = 61, | ||
94 | 87 | ||
95 | TIMERTICK = HZ / 10, | 88 | TIMERTICK = HZ / 10, |
96 | MINTIMER = HZ >> 2, | 89 | MINTIMER = HZ >> 2, |
97 | MAXTIMER = HZ << 1, | 90 | MAXTIMER = HZ << 1, |
98 | HELPWAIT = 20, | ||
99 | }; | 91 | }; |
100 | 92 | ||
101 | struct buf { | 93 | struct buf { |
102 | struct list_head bufs; | ||
103 | ulong stime; /* for disk stats */ | ||
104 | ulong flags; | ||
105 | ulong nframesout; | 94 | ulong nframesout; |
106 | ulong resid; | 95 | ulong resid; |
107 | ulong bv_resid; | 96 | ulong bv_resid; |
108 | ulong bv_off; | ||
109 | sector_t sector; | 97 | sector_t sector; |
110 | struct bio *bio; | 98 | struct bio *bio; |
111 | struct bio_vec *bv; | 99 | struct bio_vec *bv; |
100 | struct request *rq; | ||
112 | }; | 101 | }; |
113 | 102 | ||
114 | struct frame { | 103 | struct frame { |
115 | int tag; | 104 | struct list_head head; |
105 | u32 tag; | ||
116 | ulong waited; | 106 | ulong waited; |
107 | struct aoetgt *t; /* parent target I belong to */ | ||
108 | sector_t lba; | ||
109 | struct sk_buff *skb; /* command skb freed on module exit */ | ||
110 | struct sk_buff *r_skb; /* response skb for async processing */ | ||
117 | struct buf *buf; | 111 | struct buf *buf; |
118 | char *bufaddr; | 112 | struct bio_vec *bv; |
119 | ulong bcnt; | 113 | ulong bcnt; |
120 | sector_t lba; | 114 | ulong bv_off; |
121 | struct sk_buff *skb; | ||
122 | }; | 115 | }; |
123 | 116 | ||
124 | struct aoeif { | 117 | struct aoeif { |
125 | struct net_device *nd; | 118 | struct net_device *nd; |
126 | unsigned char lost; | 119 | ulong lost; |
127 | unsigned char lostjumbo; | 120 | int bcnt; |
128 | ushort maxbcnt; | ||
129 | }; | 121 | }; |
130 | 122 | ||
131 | struct aoetgt { | 123 | struct aoetgt { |
132 | unsigned char addr[6]; | 124 | unsigned char addr[6]; |
133 | ushort nframes; | 125 | ushort nframes; |
134 | struct frame *frames; | 126 | struct aoedev *d; /* parent device I belong to */ |
127 | struct list_head ffree; /* list of free frames */ | ||
135 | struct aoeif ifs[NAOEIFS]; | 128 | struct aoeif ifs[NAOEIFS]; |
136 | struct aoeif *ifp; /* current aoeif in use */ | 129 | struct aoeif *ifp; /* current aoeif in use */ |
137 | ushort nout; | 130 | ushort nout; |
138 | ushort maxout; | 131 | ushort maxout; |
139 | u16 lasttag; /* last tag sent */ | 132 | ulong falloc; |
140 | u16 useme; | ||
141 | ulong lastwadj; /* last window adjustment */ | 133 | ulong lastwadj; /* last window adjustment */ |
134 | int minbcnt; | ||
142 | int wpkts, rpkts; | 135 | int wpkts, rpkts; |
143 | int dataref; | ||
144 | }; | 136 | }; |
145 | 137 | ||
146 | struct aoedev { | 138 | struct aoedev { |
@@ -153,6 +145,9 @@ struct aoedev { | |||
153 | u16 rttavg; /* round trip average of requests/responses */ | 145 | u16 rttavg; /* round trip average of requests/responses */ |
154 | u16 mintimer; | 146 | u16 mintimer; |
155 | u16 fw_ver; /* version of blade's firmware */ | 147 | u16 fw_ver; /* version of blade's firmware */ |
148 | u16 lasttag; /* last tag sent */ | ||
149 | u16 useme; | ||
150 | ulong ref; | ||
156 | struct work_struct work;/* disk create work struct */ | 151 | struct work_struct work;/* disk create work struct */ |
157 | struct gendisk *gd; | 152 | struct gendisk *gd; |
158 | struct request_queue *blkq; | 153 | struct request_queue *blkq; |
@@ -160,16 +155,31 @@ struct aoedev { | |||
160 | sector_t ssize; | 155 | sector_t ssize; |
161 | struct timer_list timer; | 156 | struct timer_list timer; |
162 | spinlock_t lock; | 157 | spinlock_t lock; |
163 | struct sk_buff_head sendq; | ||
164 | struct sk_buff_head skbpool; | 158 | struct sk_buff_head skbpool; |
165 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ | 159 | mempool_t *bufpool; /* for deadlock-free Buf allocation */ |
166 | struct list_head bufq; /* queue of bios to work on */ | 160 | struct { /* pointers to work in progress */ |
167 | struct buf *inprocess; /* the one we're currently working on */ | 161 | struct buf *buf; |
162 | struct bio *nxbio; | ||
163 | struct request *rq; | ||
164 | } ip; | ||
165 | ulong maxbcnt; | ||
166 | struct list_head factive[NFACTIVE]; /* hash of active frames */ | ||
168 | struct aoetgt *targets[NTARGETS]; | 167 | struct aoetgt *targets[NTARGETS]; |
169 | struct aoetgt **tgt; /* target in use when working */ | 168 | struct aoetgt **tgt; /* target in use when working */ |
170 | struct aoetgt **htgt; /* target needing rexmit assistance */ | 169 | struct aoetgt *htgt; /* target needing rexmit assistance */ |
170 | ulong ntargets; | ||
171 | ulong kicked; | ||
171 | }; | 172 | }; |
172 | 173 | ||
174 | /* kthread tracking */ | ||
175 | struct ktstate { | ||
176 | struct completion rendez; | ||
177 | struct task_struct *task; | ||
178 | wait_queue_head_t *waitq; | ||
179 | int (*fn) (void); | ||
180 | char *name; | ||
181 | spinlock_t *lock; | ||
182 | }; | ||
173 | 183 | ||
174 | int aoeblk_init(void); | 184 | int aoeblk_init(void); |
175 | void aoeblk_exit(void); | 185 | void aoeblk_exit(void); |
@@ -182,22 +192,29 @@ void aoechr_error(char *); | |||
182 | 192 | ||
183 | void aoecmd_work(struct aoedev *d); | 193 | void aoecmd_work(struct aoedev *d); |
184 | void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); | 194 | void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); |
185 | void aoecmd_ata_rsp(struct sk_buff *); | 195 | struct sk_buff *aoecmd_ata_rsp(struct sk_buff *); |
186 | void aoecmd_cfg_rsp(struct sk_buff *); | 196 | void aoecmd_cfg_rsp(struct sk_buff *); |
187 | void aoecmd_sleepwork(struct work_struct *); | 197 | void aoecmd_sleepwork(struct work_struct *); |
188 | void aoecmd_cleanslate(struct aoedev *); | 198 | void aoecmd_cleanslate(struct aoedev *); |
199 | void aoecmd_exit(void); | ||
200 | int aoecmd_init(void); | ||
189 | struct sk_buff *aoecmd_ata_id(struct aoedev *); | 201 | struct sk_buff *aoecmd_ata_id(struct aoedev *); |
202 | void aoe_freetframe(struct frame *); | ||
203 | void aoe_flush_iocq(void); | ||
204 | void aoe_end_request(struct aoedev *, struct request *, int); | ||
205 | int aoe_ktstart(struct ktstate *k); | ||
206 | void aoe_ktstop(struct ktstate *k); | ||
190 | 207 | ||
191 | int aoedev_init(void); | 208 | int aoedev_init(void); |
192 | void aoedev_exit(void); | 209 | void aoedev_exit(void); |
193 | struct aoedev *aoedev_by_aoeaddr(int maj, int min); | 210 | struct aoedev *aoedev_by_aoeaddr(ulong maj, int min, int do_alloc); |
194 | struct aoedev *aoedev_by_sysminor_m(ulong sysminor); | ||
195 | void aoedev_downdev(struct aoedev *d); | 211 | void aoedev_downdev(struct aoedev *d); |
196 | int aoedev_flush(const char __user *str, size_t size); | 212 | int aoedev_flush(const char __user *str, size_t size); |
213 | void aoe_failbuf(struct aoedev *, struct buf *); | ||
214 | void aoedev_put(struct aoedev *); | ||
197 | 215 | ||
198 | int aoenet_init(void); | 216 | int aoenet_init(void); |
199 | void aoenet_exit(void); | 217 | void aoenet_exit(void); |
200 | void aoenet_xmit(struct sk_buff_head *); | 218 | void aoenet_xmit(struct sk_buff_head *); |
201 | int is_aoe_netif(struct net_device *ifp); | 219 | int is_aoe_netif(struct net_device *ifp); |
202 | int set_aoe_iflist(const char __user *str, size_t size); | 220 | int set_aoe_iflist(const char __user *str, size_t size); |
203 | |||
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 321de7b6c442..00dfc5008ad4 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoeblk.c | 3 | * aoeblk.c |
4 | * block device routines | 4 | * block device routines |
@@ -161,68 +161,22 @@ aoeblk_release(struct gendisk *disk, fmode_t mode) | |||
161 | } | 161 | } |
162 | 162 | ||
163 | static void | 163 | static void |
164 | aoeblk_make_request(struct request_queue *q, struct bio *bio) | 164 | aoeblk_request(struct request_queue *q) |
165 | { | 165 | { |
166 | struct sk_buff_head queue; | ||
167 | struct aoedev *d; | 166 | struct aoedev *d; |
168 | struct buf *buf; | 167 | struct request *rq; |
169 | ulong flags; | ||
170 | |||
171 | blk_queue_bounce(q, &bio); | ||
172 | |||
173 | if (bio == NULL) { | ||
174 | printk(KERN_ERR "aoe: bio is NULL\n"); | ||
175 | BUG(); | ||
176 | return; | ||
177 | } | ||
178 | d = bio->bi_bdev->bd_disk->private_data; | ||
179 | if (d == NULL) { | ||
180 | printk(KERN_ERR "aoe: bd_disk->private_data is NULL\n"); | ||
181 | BUG(); | ||
182 | bio_endio(bio, -ENXIO); | ||
183 | return; | ||
184 | } else if (bio->bi_io_vec == NULL) { | ||
185 | printk(KERN_ERR "aoe: bi_io_vec is NULL\n"); | ||
186 | BUG(); | ||
187 | bio_endio(bio, -ENXIO); | ||
188 | return; | ||
189 | } | ||
190 | buf = mempool_alloc(d->bufpool, GFP_NOIO); | ||
191 | if (buf == NULL) { | ||
192 | printk(KERN_INFO "aoe: buf allocation failure\n"); | ||
193 | bio_endio(bio, -ENOMEM); | ||
194 | return; | ||
195 | } | ||
196 | memset(buf, 0, sizeof(*buf)); | ||
197 | INIT_LIST_HEAD(&buf->bufs); | ||
198 | buf->stime = jiffies; | ||
199 | buf->bio = bio; | ||
200 | buf->resid = bio->bi_size; | ||
201 | buf->sector = bio->bi_sector; | ||
202 | buf->bv = &bio->bi_io_vec[bio->bi_idx]; | ||
203 | buf->bv_resid = buf->bv->bv_len; | ||
204 | WARN_ON(buf->bv_resid == 0); | ||
205 | buf->bv_off = buf->bv->bv_offset; | ||
206 | |||
207 | spin_lock_irqsave(&d->lock, flags); | ||
208 | 168 | ||
169 | d = q->queuedata; | ||
209 | if ((d->flags & DEVFL_UP) == 0) { | 170 | if ((d->flags & DEVFL_UP) == 0) { |
210 | pr_info_ratelimited("aoe: device %ld.%d is not up\n", | 171 | pr_info_ratelimited("aoe: device %ld.%d is not up\n", |
211 | d->aoemajor, d->aoeminor); | 172 | d->aoemajor, d->aoeminor); |
212 | spin_unlock_irqrestore(&d->lock, flags); | 173 | while ((rq = blk_peek_request(q))) { |
213 | mempool_free(buf, d->bufpool); | 174 | blk_start_request(rq); |
214 | bio_endio(bio, -ENXIO); | 175 | aoe_end_request(d, rq, 1); |
176 | } | ||
215 | return; | 177 | return; |
216 | } | 178 | } |
217 | |||
218 | list_add_tail(&buf->bufs, &d->bufq); | ||
219 | |||
220 | aoecmd_work(d); | 179 | aoecmd_work(d); |
221 | __skb_queue_head_init(&queue); | ||
222 | skb_queue_splice_init(&d->sendq, &queue); | ||
223 | |||
224 | spin_unlock_irqrestore(&d->lock, flags); | ||
225 | aoenet_xmit(&queue); | ||
226 | } | 180 | } |
227 | 181 | ||
228 | static int | 182 | static int |
@@ -254,41 +208,54 @@ aoeblk_gdalloc(void *vp) | |||
254 | { | 208 | { |
255 | struct aoedev *d = vp; | 209 | struct aoedev *d = vp; |
256 | struct gendisk *gd; | 210 | struct gendisk *gd; |
211 | mempool_t *mp; | ||
212 | struct request_queue *q; | ||
213 | enum { KB = 1024, MB = KB * KB, READ_AHEAD = 2 * MB, }; | ||
257 | ulong flags; | 214 | ulong flags; |
258 | 215 | ||
259 | gd = alloc_disk(AOE_PARTITIONS); | 216 | gd = alloc_disk(AOE_PARTITIONS); |
260 | if (gd == NULL) { | 217 | if (gd == NULL) { |
261 | printk(KERN_ERR | 218 | pr_err("aoe: cannot allocate disk structure for %ld.%d\n", |
262 | "aoe: cannot allocate disk structure for %ld.%d\n", | ||
263 | d->aoemajor, d->aoeminor); | 219 | d->aoemajor, d->aoeminor); |
264 | goto err; | 220 | goto err; |
265 | } | 221 | } |
266 | 222 | ||
267 | d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); | 223 | mp = mempool_create(MIN_BUFS, mempool_alloc_slab, mempool_free_slab, |
268 | if (d->bufpool == NULL) { | 224 | buf_pool_cache); |
225 | if (mp == NULL) { | ||
269 | printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n", | 226 | printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%d\n", |
270 | d->aoemajor, d->aoeminor); | 227 | d->aoemajor, d->aoeminor); |
271 | goto err_disk; | 228 | goto err_disk; |
272 | } | 229 | } |
230 | q = blk_init_queue(aoeblk_request, &d->lock); | ||
231 | if (q == NULL) { | ||
232 | pr_err("aoe: cannot allocate block queue for %ld.%d\n", | ||
233 | d->aoemajor, d->aoeminor); | ||
234 | mempool_destroy(mp); | ||
235 | goto err_disk; | ||
236 | } | ||
273 | 237 | ||
274 | d->blkq = blk_alloc_queue(GFP_KERNEL); | 238 | d->blkq = blk_alloc_queue(GFP_KERNEL); |
275 | if (!d->blkq) | 239 | if (!d->blkq) |
276 | goto err_mempool; | 240 | goto err_mempool; |
277 | blk_queue_make_request(d->blkq, aoeblk_make_request); | ||
278 | d->blkq->backing_dev_info.name = "aoe"; | 241 | d->blkq->backing_dev_info.name = "aoe"; |
279 | if (bdi_init(&d->blkq->backing_dev_info)) | 242 | if (bdi_init(&d->blkq->backing_dev_info)) |
280 | goto err_blkq; | 243 | goto err_blkq; |
281 | spin_lock_irqsave(&d->lock, flags); | 244 | spin_lock_irqsave(&d->lock, flags); |
245 | blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS); | ||
246 | q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE; | ||
247 | d->bufpool = mp; | ||
248 | d->blkq = gd->queue = q; | ||
249 | q->queuedata = d; | ||
250 | d->gd = gd; | ||
282 | gd->major = AOE_MAJOR; | 251 | gd->major = AOE_MAJOR; |
283 | gd->first_minor = d->sysminor * AOE_PARTITIONS; | 252 | gd->first_minor = d->sysminor; |
284 | gd->fops = &aoe_bdops; | 253 | gd->fops = &aoe_bdops; |
285 | gd->private_data = d; | 254 | gd->private_data = d; |
286 | set_capacity(gd, d->ssize); | 255 | set_capacity(gd, d->ssize); |
287 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", | 256 | snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", |
288 | d->aoemajor, d->aoeminor); | 257 | d->aoemajor, d->aoeminor); |
289 | 258 | ||
290 | gd->queue = d->blkq; | ||
291 | d->gd = gd; | ||
292 | d->flags &= ~DEVFL_GDALLOC; | 259 | d->flags &= ~DEVFL_GDALLOC; |
293 | d->flags |= DEVFL_UP; | 260 | d->flags |= DEVFL_UP; |
294 | 261 | ||
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index e86d2062a164..ed57a890c643 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoechr.c | 3 | * aoechr.c |
4 | * AoE character device driver | 4 | * AoE character device driver |
@@ -86,34 +86,34 @@ revalidate(const char __user *str, size_t size) | |||
86 | if (copy_from_user(buf, str, size)) | 86 | if (copy_from_user(buf, str, size)) |
87 | return -EFAULT; | 87 | return -EFAULT; |
88 | 88 | ||
89 | /* should be e%d.%d format */ | ||
90 | n = sscanf(buf, "e%d.%d", &major, &minor); | 89 | n = sscanf(buf, "e%d.%d", &major, &minor); |
91 | if (n != 2) { | 90 | if (n != 2) { |
92 | printk(KERN_ERR "aoe: invalid device specification\n"); | 91 | pr_err("aoe: invalid device specification %s\n", buf); |
93 | return -EINVAL; | 92 | return -EINVAL; |
94 | } | 93 | } |
95 | d = aoedev_by_aoeaddr(major, minor); | 94 | d = aoedev_by_aoeaddr(major, minor, 0); |
96 | if (!d) | 95 | if (!d) |
97 | return -EINVAL; | 96 | return -EINVAL; |
98 | spin_lock_irqsave(&d->lock, flags); | 97 | spin_lock_irqsave(&d->lock, flags); |
99 | aoecmd_cleanslate(d); | 98 | aoecmd_cleanslate(d); |
99 | aoecmd_cfg(major, minor); | ||
100 | loop: | 100 | loop: |
101 | skb = aoecmd_ata_id(d); | 101 | skb = aoecmd_ata_id(d); |
102 | spin_unlock_irqrestore(&d->lock, flags); | 102 | spin_unlock_irqrestore(&d->lock, flags); |
103 | /* try again if we are able to sleep a bit, | 103 | /* try again if we are able to sleep a bit, |
104 | * otherwise give up this revalidation | 104 | * otherwise give up this revalidation |
105 | */ | 105 | */ |
106 | if (!skb && !msleep_interruptible(200)) { | 106 | if (!skb && !msleep_interruptible(250)) { |
107 | spin_lock_irqsave(&d->lock, flags); | 107 | spin_lock_irqsave(&d->lock, flags); |
108 | goto loop; | 108 | goto loop; |
109 | } | 109 | } |
110 | aoedev_put(d); | ||
110 | if (skb) { | 111 | if (skb) { |
111 | struct sk_buff_head queue; | 112 | struct sk_buff_head queue; |
112 | __skb_queue_head_init(&queue); | 113 | __skb_queue_head_init(&queue); |
113 | __skb_queue_tail(&queue, skb); | 114 | __skb_queue_tail(&queue, skb); |
114 | aoenet_xmit(&queue); | 115 | aoenet_xmit(&queue); |
115 | } | 116 | } |
116 | aoecmd_cfg(major, minor); | ||
117 | return 0; | 117 | return 0; |
118 | } | 118 | } |
119 | 119 | ||
@@ -174,6 +174,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp | |||
174 | break; | 174 | break; |
175 | case MINOR_FLUSH: | 175 | case MINOR_FLUSH: |
176 | ret = aoedev_flush(buf, cnt); | 176 | ret = aoedev_flush(buf, cnt); |
177 | break; | ||
177 | } | 178 | } |
178 | if (ret == 0) | 179 | if (ret == 0) |
179 | ret = cnt; | 180 | ret = cnt; |
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 887f68f6d79a..3804a0af3ef1 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoecmd.c | 3 | * aoecmd.c |
4 | * Filesystem request handling methods | 4 | * Filesystem request handling methods |
@@ -12,10 +12,19 @@ | |||
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <linux/genhd.h> | 13 | #include <linux/genhd.h> |
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/kthread.h> | ||
15 | #include <net/net_namespace.h> | 17 | #include <net/net_namespace.h> |
16 | #include <asm/unaligned.h> | 18 | #include <asm/unaligned.h> |
19 | #include <linux/uio.h> | ||
17 | #include "aoe.h" | 20 | #include "aoe.h" |
18 | 21 | ||
22 | #define MAXIOC (8192) /* default meant to avoid most soft lockups */ | ||
23 | |||
24 | static void ktcomplete(struct frame *, struct sk_buff *); | ||
25 | |||
26 | static struct buf *nextbuf(struct aoedev *); | ||
27 | |||
19 | static int aoe_deadsecs = 60 * 3; | 28 | static int aoe_deadsecs = 60 * 3; |
20 | module_param(aoe_deadsecs, int, 0644); | 29 | module_param(aoe_deadsecs, int, 0644); |
21 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); | 30 | MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); |
@@ -25,6 +34,15 @@ module_param(aoe_maxout, int, 0644); | |||
25 | MODULE_PARM_DESC(aoe_maxout, | 34 | MODULE_PARM_DESC(aoe_maxout, |
26 | "Only aoe_maxout outstanding packets for every MAC on eX.Y."); | 35 | "Only aoe_maxout outstanding packets for every MAC on eX.Y."); |
27 | 36 | ||
37 | static wait_queue_head_t ktiowq; | ||
38 | static struct ktstate kts; | ||
39 | |||
40 | /* io completion queue */ | ||
41 | static struct { | ||
42 | struct list_head head; | ||
43 | spinlock_t lock; | ||
44 | } iocq; | ||
45 | |||
28 | static struct sk_buff * | 46 | static struct sk_buff * |
29 | new_skb(ulong len) | 47 | new_skb(ulong len) |
30 | { | 48 | { |
@@ -41,15 +59,21 @@ new_skb(ulong len) | |||
41 | } | 59 | } |
42 | 60 | ||
43 | static struct frame * | 61 | static struct frame * |
44 | getframe(struct aoetgt *t, int tag) | 62 | getframe(struct aoedev *d, u32 tag) |
45 | { | 63 | { |
46 | struct frame *f, *e; | 64 | struct frame *f; |
65 | struct list_head *head, *pos, *nx; | ||
66 | u32 n; | ||
47 | 67 | ||
48 | f = t->frames; | 68 | n = tag % NFACTIVE; |
49 | e = f + t->nframes; | 69 | head = &d->factive[n]; |
50 | for (; f<e; f++) | 70 | list_for_each_safe(pos, nx, head) { |
51 | if (f->tag == tag) | 71 | f = list_entry(pos, struct frame, head); |
72 | if (f->tag == tag) { | ||
73 | list_del(pos); | ||
52 | return f; | 74 | return f; |
75 | } | ||
76 | } | ||
53 | return NULL; | 77 | return NULL; |
54 | } | 78 | } |
55 | 79 | ||
@@ -59,18 +83,18 @@ getframe(struct aoetgt *t, int tag) | |||
59 | * This driver reserves tag -1 to mean "unused frame." | 83 | * This driver reserves tag -1 to mean "unused frame." |
60 | */ | 84 | */ |
61 | static int | 85 | static int |
62 | newtag(struct aoetgt *t) | 86 | newtag(struct aoedev *d) |
63 | { | 87 | { |
64 | register ulong n; | 88 | register ulong n; |
65 | 89 | ||
66 | n = jiffies & 0xffff; | 90 | n = jiffies & 0xffff; |
67 | return n |= (++t->lasttag & 0x7fff) << 16; | 91 | return n |= (++d->lasttag & 0x7fff) << 16; |
68 | } | 92 | } |
69 | 93 | ||
70 | static int | 94 | static u32 |
71 | aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) | 95 | aoehdr_atainit(struct aoedev *d, struct aoetgt *t, struct aoe_hdr *h) |
72 | { | 96 | { |
73 | u32 host_tag = newtag(t); | 97 | u32 host_tag = newtag(d); |
74 | 98 | ||
75 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); | 99 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
76 | memcpy(h->dst, t->addr, sizeof h->dst); | 100 | memcpy(h->dst, t->addr, sizeof h->dst); |
@@ -95,16 +119,18 @@ put_lba(struct aoe_atahdr *ah, sector_t lba) | |||
95 | ah->lba5 = lba >>= 8; | 119 | ah->lba5 = lba >>= 8; |
96 | } | 120 | } |
97 | 121 | ||
98 | static void | 122 | static struct aoeif * |
99 | ifrotate(struct aoetgt *t) | 123 | ifrotate(struct aoetgt *t) |
100 | { | 124 | { |
101 | t->ifp++; | 125 | struct aoeif *ifp; |
102 | if (t->ifp >= &t->ifs[NAOEIFS] || t->ifp->nd == NULL) | 126 | |
103 | t->ifp = t->ifs; | 127 | ifp = t->ifp; |
104 | if (t->ifp->nd == NULL) { | 128 | ifp++; |
105 | printk(KERN_INFO "aoe: no interface to rotate to\n"); | 129 | if (ifp >= &t->ifs[NAOEIFS] || ifp->nd == NULL) |
106 | BUG(); | 130 | ifp = t->ifs; |
107 | } | 131 | if (ifp->nd == NULL) |
132 | return NULL; | ||
133 | return t->ifp = ifp; | ||
108 | } | 134 | } |
109 | 135 | ||
110 | static void | 136 | static void |
@@ -129,78 +155,128 @@ skb_pool_get(struct aoedev *d) | |||
129 | return NULL; | 155 | return NULL; |
130 | } | 156 | } |
131 | 157 | ||
132 | /* freeframe is where we do our load balancing so it's a little hairy. */ | 158 | void |
159 | aoe_freetframe(struct frame *f) | ||
160 | { | ||
161 | struct aoetgt *t; | ||
162 | |||
163 | t = f->t; | ||
164 | f->buf = NULL; | ||
165 | f->bv = NULL; | ||
166 | f->r_skb = NULL; | ||
167 | list_add(&f->head, &t->ffree); | ||
168 | } | ||
169 | |||
133 | static struct frame * | 170 | static struct frame * |
134 | freeframe(struct aoedev *d) | 171 | newtframe(struct aoedev *d, struct aoetgt *t) |
135 | { | 172 | { |
136 | struct frame *f, *e, *rf; | 173 | struct frame *f; |
137 | struct aoetgt **t; | ||
138 | struct sk_buff *skb; | 174 | struct sk_buff *skb; |
175 | struct list_head *pos; | ||
176 | |||
177 | if (list_empty(&t->ffree)) { | ||
178 | if (t->falloc >= NSKBPOOLMAX*2) | ||
179 | return NULL; | ||
180 | f = kcalloc(1, sizeof(*f), GFP_ATOMIC); | ||
181 | if (f == NULL) | ||
182 | return NULL; | ||
183 | t->falloc++; | ||
184 | f->t = t; | ||
185 | } else { | ||
186 | pos = t->ffree.next; | ||
187 | list_del(pos); | ||
188 | f = list_entry(pos, struct frame, head); | ||
189 | } | ||
190 | |||
191 | skb = f->skb; | ||
192 | if (skb == NULL) { | ||
193 | f->skb = skb = new_skb(ETH_ZLEN); | ||
194 | if (!skb) { | ||
195 | bail: aoe_freetframe(f); | ||
196 | return NULL; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | if (atomic_read(&skb_shinfo(skb)->dataref) != 1) { | ||
201 | skb = skb_pool_get(d); | ||
202 | if (skb == NULL) | ||
203 | goto bail; | ||
204 | skb_pool_put(d, f->skb); | ||
205 | f->skb = skb; | ||
206 | } | ||
207 | |||
208 | skb->truesize -= skb->data_len; | ||
209 | skb_shinfo(skb)->nr_frags = skb->data_len = 0; | ||
210 | skb_trim(skb, 0); | ||
211 | return f; | ||
212 | } | ||
213 | |||
214 | static struct frame * | ||
215 | newframe(struct aoedev *d) | ||
216 | { | ||
217 | struct frame *f; | ||
218 | struct aoetgt *t, **tt; | ||
219 | int totout = 0; | ||
139 | 220 | ||
140 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ | 221 | if (d->targets[0] == NULL) { /* shouldn't happen, but I'm paranoid */ |
141 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); | 222 | printk(KERN_ERR "aoe: NULL TARGETS!\n"); |
142 | return NULL; | 223 | return NULL; |
143 | } | 224 | } |
144 | t = d->tgt; | 225 | tt = d->tgt; /* last used target */ |
145 | t++; | ||
146 | if (t >= &d->targets[NTARGETS] || !*t) | ||
147 | t = d->targets; | ||
148 | for (;;) { | 226 | for (;;) { |
149 | if ((*t)->nout < (*t)->maxout | 227 | tt++; |
228 | if (tt >= &d->targets[NTARGETS] || !*tt) | ||
229 | tt = d->targets; | ||
230 | t = *tt; | ||
231 | totout += t->nout; | ||
232 | if (t->nout < t->maxout | ||
150 | && t != d->htgt | 233 | && t != d->htgt |
151 | && (*t)->ifp->nd) { | 234 | && t->ifp->nd) { |
152 | rf = NULL; | 235 | f = newtframe(d, t); |
153 | f = (*t)->frames; | 236 | if (f) { |
154 | e = f + (*t)->nframes; | 237 | ifrotate(t); |
155 | for (; f < e; f++) { | 238 | d->tgt = tt; |
156 | if (f->tag != FREETAG) | ||
157 | continue; | ||
158 | skb = f->skb; | ||
159 | if (!skb | ||
160 | && !(f->skb = skb = new_skb(ETH_ZLEN))) | ||
161 | continue; | ||
162 | if (atomic_read(&skb_shinfo(skb)->dataref) | ||
163 | != 1) { | ||
164 | if (!rf) | ||
165 | rf = f; | ||
166 | continue; | ||
167 | } | ||
168 | gotone: skb_shinfo(skb)->nr_frags = skb->data_len = 0; | ||
169 | skb_trim(skb, 0); | ||
170 | d->tgt = t; | ||
171 | ifrotate(*t); | ||
172 | return f; | 239 | return f; |
173 | } | 240 | } |
174 | /* Work can be done, but the network layer is | ||
175 | holding our precious packets. Try to grab | ||
176 | one from the pool. */ | ||
177 | f = rf; | ||
178 | if (f == NULL) { /* more paranoia */ | ||
179 | printk(KERN_ERR | ||
180 | "aoe: freeframe: %s.\n", | ||
181 | "unexpected null rf"); | ||
182 | d->flags |= DEVFL_KICKME; | ||
183 | return NULL; | ||
184 | } | ||
185 | skb = skb_pool_get(d); | ||
186 | if (skb) { | ||
187 | skb_pool_put(d, f->skb); | ||
188 | f->skb = skb; | ||
189 | goto gotone; | ||
190 | } | ||
191 | (*t)->dataref++; | ||
192 | if ((*t)->nout == 0) | ||
193 | d->flags |= DEVFL_KICKME; | ||
194 | } | 241 | } |
195 | if (t == d->tgt) /* we've looped and found nada */ | 242 | if (tt == d->tgt) /* we've looped and found nada */ |
196 | break; | 243 | break; |
197 | t++; | 244 | } |
198 | if (t >= &d->targets[NTARGETS] || !*t) | 245 | if (totout == 0) { |
199 | t = d->targets; | 246 | d->kicked++; |
247 | d->flags |= DEVFL_KICKME; | ||
200 | } | 248 | } |
201 | return NULL; | 249 | return NULL; |
202 | } | 250 | } |
203 | 251 | ||
252 | static void | ||
253 | skb_fillup(struct sk_buff *skb, struct bio_vec *bv, ulong off, ulong cnt) | ||
254 | { | ||
255 | int frag = 0; | ||
256 | ulong fcnt; | ||
257 | loop: | ||
258 | fcnt = bv->bv_len - (off - bv->bv_offset); | ||
259 | if (fcnt > cnt) | ||
260 | fcnt = cnt; | ||
261 | skb_fill_page_desc(skb, frag++, bv->bv_page, off, fcnt); | ||
262 | cnt -= fcnt; | ||
263 | if (cnt <= 0) | ||
264 | return; | ||
265 | bv++; | ||
266 | off = bv->bv_offset; | ||
267 | goto loop; | ||
268 | } | ||
269 | |||
270 | static void | ||
271 | fhash(struct frame *f) | ||
272 | { | ||
273 | struct aoedev *d = f->t->d; | ||
274 | u32 n; | ||
275 | |||
276 | n = f->tag % NFACTIVE; | ||
277 | list_add_tail(&f->head, &d->factive[n]); | ||
278 | } | ||
279 | |||
204 | static int | 280 | static int |
205 | aoecmd_ata_rw(struct aoedev *d) | 281 | aoecmd_ata_rw(struct aoedev *d) |
206 | { | 282 | { |
@@ -208,26 +284,47 @@ aoecmd_ata_rw(struct aoedev *d) | |||
208 | struct aoe_hdr *h; | 284 | struct aoe_hdr *h; |
209 | struct aoe_atahdr *ah; | 285 | struct aoe_atahdr *ah; |
210 | struct buf *buf; | 286 | struct buf *buf; |
211 | struct bio_vec *bv; | ||
212 | struct aoetgt *t; | 287 | struct aoetgt *t; |
213 | struct sk_buff *skb; | 288 | struct sk_buff *skb; |
214 | ulong bcnt; | 289 | struct sk_buff_head queue; |
290 | ulong bcnt, fbcnt; | ||
215 | char writebit, extbit; | 291 | char writebit, extbit; |
216 | 292 | ||
217 | writebit = 0x10; | 293 | writebit = 0x10; |
218 | extbit = 0x4; | 294 | extbit = 0x4; |
219 | 295 | ||
220 | f = freeframe(d); | 296 | buf = nextbuf(d); |
297 | if (buf == NULL) | ||
298 | return 0; | ||
299 | f = newframe(d); | ||
221 | if (f == NULL) | 300 | if (f == NULL) |
222 | return 0; | 301 | return 0; |
223 | t = *d->tgt; | 302 | t = *d->tgt; |
224 | buf = d->inprocess; | 303 | bcnt = d->maxbcnt; |
225 | bv = buf->bv; | ||
226 | bcnt = t->ifp->maxbcnt; | ||
227 | if (bcnt == 0) | 304 | if (bcnt == 0) |
228 | bcnt = DEFAULTBCNT; | 305 | bcnt = DEFAULTBCNT; |
229 | if (bcnt > buf->bv_resid) | 306 | if (bcnt > buf->resid) |
230 | bcnt = buf->bv_resid; | 307 | bcnt = buf->resid; |
308 | fbcnt = bcnt; | ||
309 | f->bv = buf->bv; | ||
310 | f->bv_off = f->bv->bv_offset + (f->bv->bv_len - buf->bv_resid); | ||
311 | do { | ||
312 | if (fbcnt < buf->bv_resid) { | ||
313 | buf->bv_resid -= fbcnt; | ||
314 | buf->resid -= fbcnt; | ||
315 | break; | ||
316 | } | ||
317 | fbcnt -= buf->bv_resid; | ||
318 | buf->resid -= buf->bv_resid; | ||
319 | if (buf->resid == 0) { | ||
320 | d->ip.buf = NULL; | ||
321 | break; | ||
322 | } | ||
323 | buf->bv++; | ||
324 | buf->bv_resid = buf->bv->bv_len; | ||
325 | WARN_ON(buf->bv_resid == 0); | ||
326 | } while (fbcnt); | ||
327 | |||
231 | /* initialize the headers & frame */ | 328 | /* initialize the headers & frame */ |
232 | skb = f->skb; | 329 | skb = f->skb; |
233 | h = (struct aoe_hdr *) skb_mac_header(skb); | 330 | h = (struct aoe_hdr *) skb_mac_header(skb); |
@@ -235,10 +332,10 @@ aoecmd_ata_rw(struct aoedev *d) | |||
235 | skb_put(skb, sizeof *h + sizeof *ah); | 332 | skb_put(skb, sizeof *h + sizeof *ah); |
236 | memset(h, 0, skb->len); | 333 | memset(h, 0, skb->len); |
237 | f->tag = aoehdr_atainit(d, t, h); | 334 | f->tag = aoehdr_atainit(d, t, h); |
335 | fhash(f); | ||
238 | t->nout++; | 336 | t->nout++; |
239 | f->waited = 0; | 337 | f->waited = 0; |
240 | f->buf = buf; | 338 | f->buf = buf; |
241 | f->bufaddr = page_address(bv->bv_page) + buf->bv_off; | ||
242 | f->bcnt = bcnt; | 339 | f->bcnt = bcnt; |
243 | f->lba = buf->sector; | 340 | f->lba = buf->sector; |
244 | 341 | ||
@@ -253,10 +350,11 @@ aoecmd_ata_rw(struct aoedev *d) | |||
253 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ | 350 | ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */ |
254 | } | 351 | } |
255 | if (bio_data_dir(buf->bio) == WRITE) { | 352 | if (bio_data_dir(buf->bio) == WRITE) { |
256 | skb_fill_page_desc(skb, 0, bv->bv_page, buf->bv_off, bcnt); | 353 | skb_fillup(skb, f->bv, f->bv_off, bcnt); |
257 | ah->aflags |= AOEAFL_WRITE; | 354 | ah->aflags |= AOEAFL_WRITE; |
258 | skb->len += bcnt; | 355 | skb->len += bcnt; |
259 | skb->data_len = bcnt; | 356 | skb->data_len = bcnt; |
357 | skb->truesize += bcnt; | ||
260 | t->wpkts++; | 358 | t->wpkts++; |
261 | } else { | 359 | } else { |
262 | t->rpkts++; | 360 | t->rpkts++; |
@@ -267,23 +365,15 @@ aoecmd_ata_rw(struct aoedev *d) | |||
267 | 365 | ||
268 | /* mark all tracking fields and load out */ | 366 | /* mark all tracking fields and load out */ |
269 | buf->nframesout += 1; | 367 | buf->nframesout += 1; |
270 | buf->bv_off += bcnt; | ||
271 | buf->bv_resid -= bcnt; | ||
272 | buf->resid -= bcnt; | ||
273 | buf->sector += bcnt >> 9; | 368 | buf->sector += bcnt >> 9; |
274 | if (buf->resid == 0) { | ||
275 | d->inprocess = NULL; | ||
276 | } else if (buf->bv_resid == 0) { | ||
277 | buf->bv = ++bv; | ||
278 | buf->bv_resid = bv->bv_len; | ||
279 | WARN_ON(buf->bv_resid == 0); | ||
280 | buf->bv_off = bv->bv_offset; | ||
281 | } | ||
282 | 369 | ||
283 | skb->dev = t->ifp->nd; | 370 | skb->dev = t->ifp->nd; |
284 | skb = skb_clone(skb, GFP_ATOMIC); | 371 | skb = skb_clone(skb, GFP_ATOMIC); |
285 | if (skb) | 372 | if (skb) { |
286 | __skb_queue_tail(&d->sendq, skb); | 373 | __skb_queue_head_init(&queue); |
374 | __skb_queue_tail(&queue, skb); | ||
375 | aoenet_xmit(&queue); | ||
376 | } | ||
287 | return 1; | 377 | return 1; |
288 | } | 378 | } |
289 | 379 | ||
@@ -330,17 +420,25 @@ cont: | |||
330 | } | 420 | } |
331 | 421 | ||
332 | static void | 422 | static void |
333 | resend(struct aoedev *d, struct aoetgt *t, struct frame *f) | 423 | resend(struct aoedev *d, struct frame *f) |
334 | { | 424 | { |
335 | struct sk_buff *skb; | 425 | struct sk_buff *skb; |
426 | struct sk_buff_head queue; | ||
336 | struct aoe_hdr *h; | 427 | struct aoe_hdr *h; |
337 | struct aoe_atahdr *ah; | 428 | struct aoe_atahdr *ah; |
429 | struct aoetgt *t; | ||
338 | char buf[128]; | 430 | char buf[128]; |
339 | u32 n; | 431 | u32 n; |
340 | 432 | ||
341 | ifrotate(t); | 433 | t = f->t; |
342 | n = newtag(t); | 434 | n = newtag(d); |
343 | skb = f->skb; | 435 | skb = f->skb; |
436 | if (ifrotate(t) == NULL) { | ||
437 | /* probably can't happen, but set it up to fail anyway */ | ||
438 | pr_info("aoe: resend: no interfaces to rotate to.\n"); | ||
439 | ktcomplete(f, NULL); | ||
440 | return; | ||
441 | } | ||
344 | h = (struct aoe_hdr *) skb_mac_header(skb); | 442 | h = (struct aoe_hdr *) skb_mac_header(skb); |
345 | ah = (struct aoe_atahdr *) (h+1); | 443 | ah = (struct aoe_atahdr *) (h+1); |
346 | 444 | ||
@@ -351,39 +449,22 @@ resend(struct aoedev *d, struct aoetgt *t, struct frame *f) | |||
351 | aoechr_error(buf); | 449 | aoechr_error(buf); |
352 | 450 | ||
353 | f->tag = n; | 451 | f->tag = n; |
452 | fhash(f); | ||
354 | h->tag = cpu_to_be32(n); | 453 | h->tag = cpu_to_be32(n); |
355 | memcpy(h->dst, t->addr, sizeof h->dst); | 454 | memcpy(h->dst, t->addr, sizeof h->dst); |
356 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); | 455 | memcpy(h->src, t->ifp->nd->dev_addr, sizeof h->src); |
357 | 456 | ||
358 | switch (ah->cmdstat) { | ||
359 | default: | ||
360 | break; | ||
361 | case ATA_CMD_PIO_READ: | ||
362 | case ATA_CMD_PIO_READ_EXT: | ||
363 | case ATA_CMD_PIO_WRITE: | ||
364 | case ATA_CMD_PIO_WRITE_EXT: | ||
365 | put_lba(ah, f->lba); | ||
366 | |||
367 | n = f->bcnt; | ||
368 | if (n > DEFAULTBCNT) | ||
369 | n = DEFAULTBCNT; | ||
370 | ah->scnt = n >> 9; | ||
371 | if (ah->aflags & AOEAFL_WRITE) { | ||
372 | skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), | ||
373 | offset_in_page(f->bufaddr), n); | ||
374 | skb->len = sizeof *h + sizeof *ah + n; | ||
375 | skb->data_len = n; | ||
376 | } | ||
377 | } | ||
378 | skb->dev = t->ifp->nd; | 457 | skb->dev = t->ifp->nd; |
379 | skb = skb_clone(skb, GFP_ATOMIC); | 458 | skb = skb_clone(skb, GFP_ATOMIC); |
380 | if (skb == NULL) | 459 | if (skb == NULL) |
381 | return; | 460 | return; |
382 | __skb_queue_tail(&d->sendq, skb); | 461 | __skb_queue_head_init(&queue); |
462 | __skb_queue_tail(&queue, skb); | ||
463 | aoenet_xmit(&queue); | ||
383 | } | 464 | } |
384 | 465 | ||
385 | static int | 466 | static int |
386 | tsince(int tag) | 467 | tsince(u32 tag) |
387 | { | 468 | { |
388 | int n; | 469 | int n; |
389 | 470 | ||
@@ -407,58 +488,65 @@ getif(struct aoetgt *t, struct net_device *nd) | |||
407 | return NULL; | 488 | return NULL; |
408 | } | 489 | } |
409 | 490 | ||
410 | static struct aoeif * | ||
411 | addif(struct aoetgt *t, struct net_device *nd) | ||
412 | { | ||
413 | struct aoeif *p; | ||
414 | |||
415 | p = getif(t, NULL); | ||
416 | if (!p) | ||
417 | return NULL; | ||
418 | p->nd = nd; | ||
419 | p->maxbcnt = DEFAULTBCNT; | ||
420 | p->lost = 0; | ||
421 | p->lostjumbo = 0; | ||
422 | return p; | ||
423 | } | ||
424 | |||
425 | static void | 491 | static void |
426 | ejectif(struct aoetgt *t, struct aoeif *ifp) | 492 | ejectif(struct aoetgt *t, struct aoeif *ifp) |
427 | { | 493 | { |
428 | struct aoeif *e; | 494 | struct aoeif *e; |
495 | struct net_device *nd; | ||
429 | ulong n; | 496 | ulong n; |
430 | 497 | ||
498 | nd = ifp->nd; | ||
431 | e = t->ifs + NAOEIFS - 1; | 499 | e = t->ifs + NAOEIFS - 1; |
432 | n = (e - ifp) * sizeof *ifp; | 500 | n = (e - ifp) * sizeof *ifp; |
433 | memmove(ifp, ifp+1, n); | 501 | memmove(ifp, ifp+1, n); |
434 | e->nd = NULL; | 502 | e->nd = NULL; |
503 | dev_put(nd); | ||
435 | } | 504 | } |
436 | 505 | ||
437 | static int | 506 | static int |
438 | sthtith(struct aoedev *d) | 507 | sthtith(struct aoedev *d) |
439 | { | 508 | { |
440 | struct frame *f, *e, *nf; | 509 | struct frame *f, *nf; |
510 | struct list_head *nx, *pos, *head; | ||
441 | struct sk_buff *skb; | 511 | struct sk_buff *skb; |
442 | struct aoetgt *ht = *d->htgt; | 512 | struct aoetgt *ht = d->htgt; |
443 | 513 | int i; | |
444 | f = ht->frames; | 514 | |
445 | e = f + ht->nframes; | 515 | for (i = 0; i < NFACTIVE; i++) { |
446 | for (; f < e; f++) { | 516 | head = &d->factive[i]; |
447 | if (f->tag == FREETAG) | 517 | list_for_each_safe(pos, nx, head) { |
448 | continue; | 518 | f = list_entry(pos, struct frame, head); |
449 | nf = freeframe(d); | 519 | if (f->t != ht) |
450 | if (!nf) | 520 | continue; |
451 | return 0; | 521 | |
452 | skb = nf->skb; | 522 | nf = newframe(d); |
453 | *nf = *f; | 523 | if (!nf) |
454 | f->skb = skb; | 524 | return 0; |
455 | f->tag = FREETAG; | 525 | |
456 | nf->waited = 0; | 526 | /* remove frame from active list */ |
457 | ht->nout--; | 527 | list_del(pos); |
458 | (*d->tgt)->nout++; | 528 | |
459 | resend(d, *d->tgt, nf); | 529 | /* reassign all pertinent bits to new outbound frame */ |
530 | skb = nf->skb; | ||
531 | nf->skb = f->skb; | ||
532 | nf->buf = f->buf; | ||
533 | nf->bcnt = f->bcnt; | ||
534 | nf->lba = f->lba; | ||
535 | nf->bv = f->bv; | ||
536 | nf->bv_off = f->bv_off; | ||
537 | nf->waited = 0; | ||
538 | f->skb = skb; | ||
539 | aoe_freetframe(f); | ||
540 | ht->nout--; | ||
541 | nf->t->nout++; | ||
542 | resend(d, nf); | ||
543 | } | ||
460 | } | 544 | } |
461 | /* he's clean, he's useless. take away his interfaces */ | 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 | */ | ||
462 | memset(ht->ifs, 0, sizeof ht->ifs); | 550 | memset(ht->ifs, 0, sizeof ht->ifs); |
463 | d->htgt = NULL; | 551 | d->htgt = NULL; |
464 | return 1; | 552 | return 1; |
@@ -477,13 +565,15 @@ ata_scnt(unsigned char *packet) { | |||
477 | static void | 565 | static void |
478 | rexmit_timer(ulong vp) | 566 | rexmit_timer(ulong vp) |
479 | { | 567 | { |
480 | struct sk_buff_head queue; | ||
481 | struct aoedev *d; | 568 | struct aoedev *d; |
482 | struct aoetgt *t, **tt, **te; | 569 | struct aoetgt *t, **tt, **te; |
483 | struct aoeif *ifp; | 570 | struct aoeif *ifp; |
484 | struct frame *f, *e; | 571 | struct frame *f; |
572 | struct list_head *head, *pos, *nx; | ||
573 | LIST_HEAD(flist); | ||
485 | register long timeout; | 574 | register long timeout; |
486 | ulong flags, n; | 575 | ulong flags, n; |
576 | int i; | ||
487 | 577 | ||
488 | d = (struct aoedev *) vp; | 578 | d = (struct aoedev *) vp; |
489 | 579 | ||
@@ -497,58 +587,22 @@ rexmit_timer(ulong vp) | |||
497 | spin_unlock_irqrestore(&d->lock, flags); | 587 | spin_unlock_irqrestore(&d->lock, flags); |
498 | return; | 588 | return; |
499 | } | 589 | } |
500 | tt = d->targets; | ||
501 | te = tt + NTARGETS; | ||
502 | for (; tt < te && *tt; tt++) { | ||
503 | t = *tt; | ||
504 | f = t->frames; | ||
505 | e = f + t->nframes; | ||
506 | for (; f < e; f++) { | ||
507 | if (f->tag == FREETAG | ||
508 | || tsince(f->tag) < timeout) | ||
509 | continue; | ||
510 | n = f->waited += timeout; | ||
511 | n /= HZ; | ||
512 | if (n > aoe_deadsecs) { | ||
513 | /* waited too long. device failure. */ | ||
514 | aoedev_downdev(d); | ||
515 | break; | ||
516 | } | ||
517 | |||
518 | if (n > HELPWAIT /* see if another target can help */ | ||
519 | && (tt != d->targets || d->targets[1])) | ||
520 | d->htgt = tt; | ||
521 | |||
522 | if (t->nout == t->maxout) { | ||
523 | if (t->maxout > 1) | ||
524 | t->maxout--; | ||
525 | t->lastwadj = jiffies; | ||
526 | } | ||
527 | |||
528 | ifp = getif(t, f->skb->dev); | ||
529 | if (ifp && ++ifp->lost > (t->nframes << 1) | ||
530 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
531 | ejectif(t, ifp); | ||
532 | ifp = NULL; | ||
533 | } | ||
534 | 590 | ||
535 | if (ata_scnt(skb_mac_header(f->skb)) > DEFAULTBCNT / 512 | 591 | /* collect all frames to rexmit into flist */ |
536 | && ifp && ++ifp->lostjumbo > (t->nframes << 1) | 592 | for (i = 0; i < NFACTIVE; i++) { |
537 | && ifp->maxbcnt != DEFAULTBCNT) { | 593 | head = &d->factive[i]; |
538 | printk(KERN_INFO | 594 | list_for_each_safe(pos, nx, head) { |
539 | "aoe: e%ld.%d: " | 595 | f = list_entry(pos, struct frame, head); |
540 | "too many lost jumbo on " | 596 | if (tsince(f->tag) < timeout) |
541 | "%s:%pm - " | 597 | break; /* end of expired frames */ |
542 | "falling back to %d frames.\n", | 598 | /* move to flist for later processing */ |
543 | d->aoemajor, d->aoeminor, | 599 | list_move_tail(pos, &flist); |
544 | ifp->nd->name, t->addr, | ||
545 | DEFAULTBCNT); | ||
546 | ifp->maxbcnt = 0; | ||
547 | } | ||
548 | resend(d, t, f); | ||
549 | } | 600 | } |
550 | 601 | } | |
551 | /* window check */ | 602 | /* window check */ |
603 | tt = d->targets; | ||
604 | te = tt + d->ntargets; | ||
605 | for (; tt < te && (t = *tt); tt++) { | ||
552 | if (t->nout == t->maxout | 606 | if (t->nout == t->maxout |
553 | && t->maxout < t->nframes | 607 | && t->maxout < t->nframes |
554 | && (jiffies - t->lastwadj)/HZ > 10) { | 608 | && (jiffies - t->lastwadj)/HZ > 10) { |
@@ -557,45 +611,173 @@ rexmit_timer(ulong vp) | |||
557 | } | 611 | } |
558 | } | 612 | } |
559 | 613 | ||
560 | if (!skb_queue_empty(&d->sendq)) { | 614 | if (!list_empty(&flist)) { /* retransmissions necessary */ |
561 | n = d->rttavg <<= 1; | 615 | n = d->rttavg <<= 1; |
562 | if (n > MAXTIMER) | 616 | if (n > MAXTIMER) |
563 | d->rttavg = MAXTIMER; | 617 | d->rttavg = MAXTIMER; |
564 | } | 618 | } |
565 | 619 | ||
566 | if (d->flags & DEVFL_KICKME || d->htgt) { | 620 | /* process expired frames */ |
567 | d->flags &= ~DEVFL_KICKME; | 621 | while (!list_empty(&flist)) { |
568 | aoecmd_work(d); | 622 | pos = flist.next; |
623 | f = list_entry(pos, struct frame, head); | ||
624 | n = f->waited += timeout; | ||
625 | n /= HZ; | ||
626 | if (n > aoe_deadsecs) { | ||
627 | /* Waited too long. Device failure. | ||
628 | * Hang all frames on first hash bucket for downdev | ||
629 | * to clean up. | ||
630 | */ | ||
631 | list_splice(&flist, &d->factive[0]); | ||
632 | aoedev_downdev(d); | ||
633 | break; | ||
634 | } | ||
635 | list_del(pos); | ||
636 | |||
637 | t = f->t; | ||
638 | if (n > aoe_deadsecs/2) | ||
639 | d->htgt = t; /* see if another target can help */ | ||
640 | |||
641 | if (t->nout == t->maxout) { | ||
642 | if (t->maxout > 1) | ||
643 | t->maxout--; | ||
644 | t->lastwadj = jiffies; | ||
645 | } | ||
646 | |||
647 | ifp = getif(t, f->skb->dev); | ||
648 | if (ifp && ++ifp->lost > (t->nframes << 1) | ||
649 | && (ifp != t->ifs || t->ifs[1].nd)) { | ||
650 | ejectif(t, ifp); | ||
651 | ifp = NULL; | ||
652 | } | ||
653 | resend(d, f); | ||
569 | } | 654 | } |
570 | 655 | ||
571 | __skb_queue_head_init(&queue); | 656 | if ((d->flags & DEVFL_KICKME || d->htgt) && d->blkq) { |
572 | skb_queue_splice_init(&d->sendq, &queue); | 657 | d->flags &= ~DEVFL_KICKME; |
658 | d->blkq->request_fn(d->blkq); | ||
659 | } | ||
573 | 660 | ||
574 | d->timer.expires = jiffies + TIMERTICK; | 661 | d->timer.expires = jiffies + TIMERTICK; |
575 | add_timer(&d->timer); | 662 | add_timer(&d->timer); |
576 | 663 | ||
577 | spin_unlock_irqrestore(&d->lock, flags); | 664 | spin_unlock_irqrestore(&d->lock, flags); |
665 | } | ||
578 | 666 | ||
579 | aoenet_xmit(&queue); | 667 | static unsigned long |
668 | rqbiocnt(struct request *r) | ||
669 | { | ||
670 | struct bio *bio; | ||
671 | unsigned long n = 0; | ||
672 | |||
673 | __rq_for_each_bio(bio, r) | ||
674 | n++; | ||
675 | return n; | ||
676 | } | ||
677 | |||
678 | /* This can be removed if we are certain that no users of the block | ||
679 | * layer will ever use zero-count pages in bios. Otherwise we have to | ||
680 | * protect against the put_page sometimes done by the network layer. | ||
681 | * | ||
682 | * See http://oss.sgi.com/archives/xfs/2007-01/msg00594.html for | ||
683 | * discussion. | ||
684 | * | ||
685 | * We cannot use get_page in the workaround, because it insists on a | ||
686 | * positive page count as a precondition. So we use _count directly. | ||
687 | */ | ||
688 | static void | ||
689 | bio_pageinc(struct bio *bio) | ||
690 | { | ||
691 | struct bio_vec *bv; | ||
692 | struct page *page; | ||
693 | int i; | ||
694 | |||
695 | bio_for_each_segment(bv, bio, i) { | ||
696 | page = bv->bv_page; | ||
697 | /* Non-zero page count for non-head members of | ||
698 | * compound pages is no longer allowed by the kernel, | ||
699 | * but this has never been seen here. | ||
700 | */ | ||
701 | if (unlikely(PageCompound(page))) | ||
702 | if (compound_trans_head(page) != page) { | ||
703 | pr_crit("page tail used for block I/O\n"); | ||
704 | BUG(); | ||
705 | } | ||
706 | atomic_inc(&page->_count); | ||
707 | } | ||
708 | } | ||
709 | |||
710 | static void | ||
711 | bio_pagedec(struct bio *bio) | ||
712 | { | ||
713 | struct bio_vec *bv; | ||
714 | int i; | ||
715 | |||
716 | bio_for_each_segment(bv, bio, i) | ||
717 | atomic_dec(&bv->bv_page->_count); | ||
718 | } | ||
719 | |||
720 | static void | ||
721 | bufinit(struct buf *buf, struct request *rq, struct bio *bio) | ||
722 | { | ||
723 | struct bio_vec *bv; | ||
724 | |||
725 | memset(buf, 0, sizeof(*buf)); | ||
726 | buf->rq = rq; | ||
727 | buf->bio = bio; | ||
728 | buf->resid = bio->bi_size; | ||
729 | buf->sector = bio->bi_sector; | ||
730 | bio_pageinc(bio); | ||
731 | buf->bv = bv = &bio->bi_io_vec[bio->bi_idx]; | ||
732 | buf->bv_resid = bv->bv_len; | ||
733 | WARN_ON(buf->bv_resid == 0); | ||
734 | } | ||
735 | |||
736 | static struct buf * | ||
737 | nextbuf(struct aoedev *d) | ||
738 | { | ||
739 | struct request *rq; | ||
740 | struct request_queue *q; | ||
741 | struct buf *buf; | ||
742 | struct bio *bio; | ||
743 | |||
744 | q = d->blkq; | ||
745 | if (q == NULL) | ||
746 | return NULL; /* initializing */ | ||
747 | if (d->ip.buf) | ||
748 | return d->ip.buf; | ||
749 | rq = d->ip.rq; | ||
750 | if (rq == NULL) { | ||
751 | rq = blk_peek_request(q); | ||
752 | if (rq == NULL) | ||
753 | return NULL; | ||
754 | blk_start_request(rq); | ||
755 | d->ip.rq = rq; | ||
756 | d->ip.nxbio = rq->bio; | ||
757 | rq->special = (void *) rqbiocnt(rq); | ||
758 | } | ||
759 | buf = mempool_alloc(d->bufpool, GFP_ATOMIC); | ||
760 | if (buf == NULL) { | ||
761 | pr_err("aoe: nextbuf: unable to mempool_alloc!\n"); | ||
762 | return NULL; | ||
763 | } | ||
764 | bio = d->ip.nxbio; | ||
765 | bufinit(buf, rq, bio); | ||
766 | bio = bio->bi_next; | ||
767 | d->ip.nxbio = bio; | ||
768 | if (bio == NULL) | ||
769 | d->ip.rq = NULL; | ||
770 | return d->ip.buf = buf; | ||
580 | } | 771 | } |
581 | 772 | ||
582 | /* enters with d->lock held */ | 773 | /* enters with d->lock held */ |
583 | void | 774 | void |
584 | aoecmd_work(struct aoedev *d) | 775 | aoecmd_work(struct aoedev *d) |
585 | { | 776 | { |
586 | struct buf *buf; | ||
587 | loop: | ||
588 | if (d->htgt && !sthtith(d)) | 777 | if (d->htgt && !sthtith(d)) |
589 | return; | 778 | return; |
590 | if (d->inprocess == NULL) { | 779 | while (aoecmd_ata_rw(d)) |
591 | if (list_empty(&d->bufq)) | 780 | ; |
592 | return; | ||
593 | buf = container_of(d->bufq.next, struct buf, bufs); | ||
594 | list_del(d->bufq.next); | ||
595 | d->inprocess = buf; | ||
596 | } | ||
597 | if (aoecmd_ata_rw(d)) | ||
598 | goto loop; | ||
599 | } | 781 | } |
600 | 782 | ||
601 | /* this function performs work that has been deferred until sleeping is OK | 783 | /* this function performs work that has been deferred until sleeping is OK |
@@ -604,28 +786,25 @@ void | |||
604 | aoecmd_sleepwork(struct work_struct *work) | 786 | aoecmd_sleepwork(struct work_struct *work) |
605 | { | 787 | { |
606 | struct aoedev *d = container_of(work, struct aoedev, work); | 788 | struct aoedev *d = container_of(work, struct aoedev, work); |
789 | struct block_device *bd; | ||
790 | u64 ssize; | ||
607 | 791 | ||
608 | if (d->flags & DEVFL_GDALLOC) | 792 | if (d->flags & DEVFL_GDALLOC) |
609 | aoeblk_gdalloc(d); | 793 | aoeblk_gdalloc(d); |
610 | 794 | ||
611 | if (d->flags & DEVFL_NEWSIZE) { | 795 | if (d->flags & DEVFL_NEWSIZE) { |
612 | struct block_device *bd; | ||
613 | unsigned long flags; | ||
614 | u64 ssize; | ||
615 | |||
616 | ssize = get_capacity(d->gd); | 796 | ssize = get_capacity(d->gd); |
617 | bd = bdget_disk(d->gd, 0); | 797 | bd = bdget_disk(d->gd, 0); |
618 | |||
619 | if (bd) { | 798 | if (bd) { |
620 | mutex_lock(&bd->bd_inode->i_mutex); | 799 | mutex_lock(&bd->bd_inode->i_mutex); |
621 | i_size_write(bd->bd_inode, (loff_t)ssize<<9); | 800 | i_size_write(bd->bd_inode, (loff_t)ssize<<9); |
622 | mutex_unlock(&bd->bd_inode->i_mutex); | 801 | mutex_unlock(&bd->bd_inode->i_mutex); |
623 | bdput(bd); | 802 | bdput(bd); |
624 | } | 803 | } |
625 | spin_lock_irqsave(&d->lock, flags); | 804 | spin_lock_irq(&d->lock); |
626 | d->flags |= DEVFL_UP; | 805 | d->flags |= DEVFL_UP; |
627 | d->flags &= ~DEVFL_NEWSIZE; | 806 | d->flags &= ~DEVFL_NEWSIZE; |
628 | spin_unlock_irqrestore(&d->lock, flags); | 807 | spin_unlock_irq(&d->lock); |
629 | } | 808 | } |
630 | } | 809 | } |
631 | 810 | ||
@@ -718,163 +897,299 @@ gettgt(struct aoedev *d, char *addr) | |||
718 | return NULL; | 897 | return NULL; |
719 | } | 898 | } |
720 | 899 | ||
721 | static inline void | 900 | static void |
722 | diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector) | 901 | bvcpy(struct bio_vec *bv, ulong off, struct sk_buff *skb, long cnt) |
902 | { | ||
903 | ulong fcnt; | ||
904 | char *p; | ||
905 | int soff = 0; | ||
906 | loop: | ||
907 | fcnt = bv->bv_len - (off - bv->bv_offset); | ||
908 | if (fcnt > cnt) | ||
909 | fcnt = cnt; | ||
910 | p = page_address(bv->bv_page) + off; | ||
911 | skb_copy_bits(skb, soff, p, fcnt); | ||
912 | soff += fcnt; | ||
913 | cnt -= fcnt; | ||
914 | if (cnt <= 0) | ||
915 | return; | ||
916 | bv++; | ||
917 | off = bv->bv_offset; | ||
918 | goto loop; | ||
919 | } | ||
920 | |||
921 | void | ||
922 | aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) | ||
923 | { | ||
924 | struct bio *bio; | ||
925 | int bok; | ||
926 | struct request_queue *q; | ||
927 | |||
928 | q = d->blkq; | ||
929 | if (rq == d->ip.rq) | ||
930 | d->ip.rq = NULL; | ||
931 | do { | ||
932 | bio = rq->bio; | ||
933 | bok = !fastfail && test_bit(BIO_UPTODATE, &bio->bi_flags); | ||
934 | } while (__blk_end_request(rq, bok ? 0 : -EIO, bio->bi_size)); | ||
935 | |||
936 | /* cf. http://lkml.org/lkml/2006/10/31/28 */ | ||
937 | if (!fastfail) | ||
938 | q->request_fn(q); | ||
939 | } | ||
940 | |||
941 | static void | ||
942 | aoe_end_buf(struct aoedev *d, struct buf *buf) | ||
943 | { | ||
944 | struct request *rq; | ||
945 | unsigned long n; | ||
946 | |||
947 | if (buf == d->ip.buf) | ||
948 | d->ip.buf = NULL; | ||
949 | rq = buf->rq; | ||
950 | bio_pagedec(buf->bio); | ||
951 | mempool_free(buf, d->bufpool); | ||
952 | n = (unsigned long) rq->special; | ||
953 | rq->special = (void *) --n; | ||
954 | if (n == 0) | ||
955 | aoe_end_request(d, rq, 0); | ||
956 | } | ||
957 | |||
958 | static void | ||
959 | ktiocomplete(struct frame *f) | ||
723 | { | 960 | { |
724 | unsigned long n_sect = bio->bi_size >> 9; | 961 | struct aoe_hdr *hin, *hout; |
725 | const int rw = bio_data_dir(bio); | 962 | struct aoe_atahdr *ahin, *ahout; |
726 | struct hd_struct *part; | 963 | struct buf *buf; |
727 | int cpu; | 964 | struct sk_buff *skb; |
965 | struct aoetgt *t; | ||
966 | struct aoeif *ifp; | ||
967 | struct aoedev *d; | ||
968 | long n; | ||
969 | |||
970 | if (f == NULL) | ||
971 | return; | ||
972 | |||
973 | t = f->t; | ||
974 | d = t->d; | ||
975 | |||
976 | hout = (struct aoe_hdr *) skb_mac_header(f->skb); | ||
977 | 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 | |||
983 | hin = (struct aoe_hdr *) skb->data; | ||
984 | skb_pull(skb, sizeof(*hin)); | ||
985 | ahin = (struct aoe_atahdr *) skb->data; | ||
986 | skb_pull(skb, sizeof(*ahin)); | ||
987 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | ||
988 | pr_err("aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", | ||
989 | ahout->cmdstat, ahin->cmdstat, | ||
990 | d->aoemajor, d->aoeminor); | ||
991 | noskb: if (buf) | ||
992 | clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); | ||
993 | goto badrsp; | ||
994 | } | ||
728 | 995 | ||
729 | cpu = part_stat_lock(); | 996 | n = ahout->scnt << 9; |
730 | part = disk_map_sector_rcu(disk, sector); | 997 | switch (ahout->cmdstat) { |
998 | case ATA_CMD_PIO_READ: | ||
999 | case ATA_CMD_PIO_READ_EXT: | ||
1000 | if (skb->len < n) { | ||
1001 | pr_err("aoe: runt data size in read. skb->len=%d need=%ld\n", | ||
1002 | skb->len, n); | ||
1003 | clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); | ||
1004 | break; | ||
1005 | } | ||
1006 | bvcpy(f->bv, f->bv_off, skb, n); | ||
1007 | case ATA_CMD_PIO_WRITE: | ||
1008 | case ATA_CMD_PIO_WRITE_EXT: | ||
1009 | spin_lock_irq(&d->lock); | ||
1010 | ifp = getif(t, skb->dev); | ||
1011 | if (ifp) | ||
1012 | ifp->lost = 0; | ||
1013 | if (d->htgt == t) /* I'll help myself, thank you. */ | ||
1014 | d->htgt = NULL; | ||
1015 | spin_unlock_irq(&d->lock); | ||
1016 | break; | ||
1017 | case ATA_CMD_ID_ATA: | ||
1018 | if (skb->len < 512) { | ||
1019 | pr_info("aoe: runt data size in ataid. skb->len=%d\n", | ||
1020 | skb->len); | ||
1021 | break; | ||
1022 | } | ||
1023 | if (skb_linearize(skb)) | ||
1024 | break; | ||
1025 | spin_lock_irq(&d->lock); | ||
1026 | ataid_complete(d, t, skb->data); | ||
1027 | spin_unlock_irq(&d->lock); | ||
1028 | break; | ||
1029 | default: | ||
1030 | pr_info("aoe: unrecognized ata command %2.2Xh for %d.%d\n", | ||
1031 | ahout->cmdstat, | ||
1032 | be16_to_cpu(get_unaligned(&hin->major)), | ||
1033 | hin->minor); | ||
1034 | } | ||
1035 | badrsp: | ||
1036 | spin_lock_irq(&d->lock); | ||
1037 | |||
1038 | aoe_freetframe(f); | ||
1039 | |||
1040 | if (buf && --buf->nframesout == 0 && buf->resid == 0) | ||
1041 | aoe_end_buf(d, buf); | ||
1042 | |||
1043 | aoecmd_work(d); | ||
1044 | |||
1045 | spin_unlock_irq(&d->lock); | ||
1046 | aoedev_put(d); | ||
1047 | dev_kfree_skb(skb); | ||
1048 | } | ||
1049 | |||
1050 | /* Enters with iocq.lock held. | ||
1051 | * Returns true iff responses needing processing remain. | ||
1052 | */ | ||
1053 | static int | ||
1054 | ktio(void) | ||
1055 | { | ||
1056 | struct frame *f; | ||
1057 | struct list_head *pos; | ||
1058 | int i; | ||
731 | 1059 | ||
732 | part_stat_inc(cpu, part, ios[rw]); | 1060 | for (i = 0; ; ++i) { |
733 | part_stat_add(cpu, part, ticks[rw], duration); | 1061 | if (i == MAXIOC) |
734 | part_stat_add(cpu, part, sectors[rw], n_sect); | 1062 | return 1; |
735 | part_stat_add(cpu, part, io_ticks, duration); | 1063 | if (list_empty(&iocq.head)) |
1064 | return 0; | ||
1065 | pos = iocq.head.next; | ||
1066 | list_del(pos); | ||
1067 | spin_unlock_irq(&iocq.lock); | ||
1068 | f = list_entry(pos, struct frame, head); | ||
1069 | ktiocomplete(f); | ||
1070 | spin_lock_irq(&iocq.lock); | ||
1071 | } | ||
1072 | } | ||
736 | 1073 | ||
737 | part_stat_unlock(); | 1074 | static int |
1075 | kthread(void *vp) | ||
1076 | { | ||
1077 | struct ktstate *k; | ||
1078 | DECLARE_WAITQUEUE(wait, current); | ||
1079 | int more; | ||
1080 | |||
1081 | k = vp; | ||
1082 | current->flags |= PF_NOFREEZE; | ||
1083 | set_user_nice(current, -10); | ||
1084 | complete(&k->rendez); /* tell spawner we're running */ | ||
1085 | do { | ||
1086 | spin_lock_irq(k->lock); | ||
1087 | more = k->fn(); | ||
1088 | if (!more) { | ||
1089 | add_wait_queue(k->waitq, &wait); | ||
1090 | __set_current_state(TASK_INTERRUPTIBLE); | ||
1091 | } | ||
1092 | spin_unlock_irq(k->lock); | ||
1093 | if (!more) { | ||
1094 | schedule(); | ||
1095 | remove_wait_queue(k->waitq, &wait); | ||
1096 | } else | ||
1097 | cond_resched(); | ||
1098 | } while (!kthread_should_stop()); | ||
1099 | complete(&k->rendez); /* tell spawner we're stopping */ | ||
1100 | return 0; | ||
738 | } | 1101 | } |
739 | 1102 | ||
740 | void | 1103 | void |
1104 | aoe_ktstop(struct ktstate *k) | ||
1105 | { | ||
1106 | kthread_stop(k->task); | ||
1107 | wait_for_completion(&k->rendez); | ||
1108 | } | ||
1109 | |||
1110 | int | ||
1111 | aoe_ktstart(struct ktstate *k) | ||
1112 | { | ||
1113 | struct task_struct *task; | ||
1114 | |||
1115 | init_completion(&k->rendez); | ||
1116 | task = kthread_run(kthread, k, k->name); | ||
1117 | if (task == NULL || IS_ERR(task)) | ||
1118 | return -ENOMEM; | ||
1119 | k->task = task; | ||
1120 | wait_for_completion(&k->rendez); /* allow kthread to start */ | ||
1121 | init_completion(&k->rendez); /* for waiting for exit later */ | ||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | /* pass it off to kthreads for processing */ | ||
1126 | static void | ||
1127 | ktcomplete(struct frame *f, struct sk_buff *skb) | ||
1128 | { | ||
1129 | ulong flags; | ||
1130 | |||
1131 | f->r_skb = skb; | ||
1132 | spin_lock_irqsave(&iocq.lock, flags); | ||
1133 | list_add_tail(&f->head, &iocq.head); | ||
1134 | spin_unlock_irqrestore(&iocq.lock, flags); | ||
1135 | wake_up(&ktiowq); | ||
1136 | } | ||
1137 | |||
1138 | struct sk_buff * | ||
741 | aoecmd_ata_rsp(struct sk_buff *skb) | 1139 | aoecmd_ata_rsp(struct sk_buff *skb) |
742 | { | 1140 | { |
743 | struct sk_buff_head queue; | ||
744 | struct aoedev *d; | 1141 | struct aoedev *d; |
745 | struct aoe_hdr *hin, *hout; | 1142 | struct aoe_hdr *h; |
746 | struct aoe_atahdr *ahin, *ahout; | ||
747 | struct frame *f; | 1143 | struct frame *f; |
748 | struct buf *buf; | ||
749 | struct aoetgt *t; | 1144 | struct aoetgt *t; |
750 | struct aoeif *ifp; | 1145 | u32 n; |
751 | register long n; | ||
752 | ulong flags; | 1146 | ulong flags; |
753 | char ebuf[128]; | 1147 | char ebuf[128]; |
754 | u16 aoemajor; | 1148 | u16 aoemajor; |
755 | 1149 | ||
756 | hin = (struct aoe_hdr *) skb_mac_header(skb); | 1150 | h = (struct aoe_hdr *) skb->data; |
757 | aoemajor = get_unaligned_be16(&hin->major); | 1151 | aoemajor = be16_to_cpu(get_unaligned(&h->major)); |
758 | d = aoedev_by_aoeaddr(aoemajor, hin->minor); | 1152 | d = aoedev_by_aoeaddr(aoemajor, h->minor, 0); |
759 | if (d == NULL) { | 1153 | if (d == NULL) { |
760 | snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response " | 1154 | snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response " |
761 | "for unknown device %d.%d\n", | 1155 | "for unknown device %d.%d\n", |
762 | aoemajor, hin->minor); | 1156 | aoemajor, h->minor); |
763 | aoechr_error(ebuf); | 1157 | aoechr_error(ebuf); |
764 | return; | 1158 | return skb; |
765 | } | 1159 | } |
766 | 1160 | ||
767 | spin_lock_irqsave(&d->lock, flags); | 1161 | spin_lock_irqsave(&d->lock, flags); |
768 | 1162 | ||
769 | n = get_unaligned_be32(&hin->tag); | 1163 | n = be32_to_cpu(get_unaligned(&h->tag)); |
770 | t = gettgt(d, hin->src); | 1164 | f = getframe(d, n); |
771 | if (t == NULL) { | ||
772 | printk(KERN_INFO "aoe: can't find target e%ld.%d:%pm\n", | ||
773 | d->aoemajor, d->aoeminor, hin->src); | ||
774 | spin_unlock_irqrestore(&d->lock, flags); | ||
775 | return; | ||
776 | } | ||
777 | f = getframe(t, n); | ||
778 | if (f == NULL) { | 1165 | if (f == NULL) { |
779 | calc_rttavg(d, -tsince(n)); | 1166 | calc_rttavg(d, -tsince(n)); |
780 | spin_unlock_irqrestore(&d->lock, flags); | 1167 | spin_unlock_irqrestore(&d->lock, flags); |
1168 | aoedev_put(d); | ||
781 | snprintf(ebuf, sizeof ebuf, | 1169 | snprintf(ebuf, sizeof ebuf, |
782 | "%15s e%d.%d tag=%08x@%08lx\n", | 1170 | "%15s e%d.%d tag=%08x@%08lx\n", |
783 | "unexpected rsp", | 1171 | "unexpected rsp", |
784 | get_unaligned_be16(&hin->major), | 1172 | get_unaligned_be16(&h->major), |
785 | hin->minor, | 1173 | h->minor, |
786 | get_unaligned_be32(&hin->tag), | 1174 | get_unaligned_be32(&h->tag), |
787 | jiffies); | 1175 | jiffies); |
788 | aoechr_error(ebuf); | 1176 | aoechr_error(ebuf); |
789 | return; | 1177 | return skb; |
790 | } | 1178 | } |
791 | 1179 | t = f->t; | |
792 | calc_rttavg(d, tsince(f->tag)); | 1180 | calc_rttavg(d, tsince(f->tag)); |
793 | |||
794 | ahin = (struct aoe_atahdr *) (hin+1); | ||
795 | hout = (struct aoe_hdr *) skb_mac_header(f->skb); | ||
796 | ahout = (struct aoe_atahdr *) (hout+1); | ||
797 | buf = f->buf; | ||
798 | |||
799 | if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ | ||
800 | printk(KERN_ERR | ||
801 | "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%d\n", | ||
802 | ahout->cmdstat, ahin->cmdstat, | ||
803 | d->aoemajor, d->aoeminor); | ||
804 | if (buf) | ||
805 | buf->flags |= BUFFL_FAIL; | ||
806 | } else { | ||
807 | if (d->htgt && t == *d->htgt) /* I'll help myself, thank you. */ | ||
808 | d->htgt = NULL; | ||
809 | n = ahout->scnt << 9; | ||
810 | switch (ahout->cmdstat) { | ||
811 | case ATA_CMD_PIO_READ: | ||
812 | case ATA_CMD_PIO_READ_EXT: | ||
813 | if (skb->len - sizeof *hin - sizeof *ahin < n) { | ||
814 | printk(KERN_ERR | ||
815 | "aoe: %s. skb->len=%d need=%ld\n", | ||
816 | "runt data size in read", skb->len, n); | ||
817 | /* fail frame f? just returning will rexmit. */ | ||
818 | spin_unlock_irqrestore(&d->lock, flags); | ||
819 | return; | ||
820 | } | ||
821 | memcpy(f->bufaddr, ahin+1, n); | ||
822 | case ATA_CMD_PIO_WRITE: | ||
823 | case ATA_CMD_PIO_WRITE_EXT: | ||
824 | ifp = getif(t, skb->dev); | ||
825 | if (ifp) { | ||
826 | ifp->lost = 0; | ||
827 | if (n > DEFAULTBCNT) | ||
828 | ifp->lostjumbo = 0; | ||
829 | } | ||
830 | if (f->bcnt -= n) { | ||
831 | f->lba += n >> 9; | ||
832 | f->bufaddr += n; | ||
833 | resend(d, t, f); | ||
834 | goto xmit; | ||
835 | } | ||
836 | break; | ||
837 | case ATA_CMD_ID_ATA: | ||
838 | if (skb->len - sizeof *hin - sizeof *ahin < 512) { | ||
839 | printk(KERN_INFO | ||
840 | "aoe: runt data size in ataid. skb->len=%d\n", | ||
841 | skb->len); | ||
842 | spin_unlock_irqrestore(&d->lock, flags); | ||
843 | return; | ||
844 | } | ||
845 | ataid_complete(d, t, (char *) (ahin+1)); | ||
846 | break; | ||
847 | default: | ||
848 | printk(KERN_INFO | ||
849 | "aoe: unrecognized ata command %2.2Xh for %d.%d\n", | ||
850 | ahout->cmdstat, | ||
851 | get_unaligned_be16(&hin->major), | ||
852 | hin->minor); | ||
853 | } | ||
854 | } | ||
855 | |||
856 | if (buf && --buf->nframesout == 0 && buf->resid == 0) { | ||
857 | diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector); | ||
858 | if (buf->flags & BUFFL_FAIL) | ||
859 | bio_endio(buf->bio, -EIO); | ||
860 | else { | ||
861 | bio_flush_dcache_pages(buf->bio); | ||
862 | bio_endio(buf->bio, 0); | ||
863 | } | ||
864 | mempool_free(buf, d->bufpool); | ||
865 | } | ||
866 | |||
867 | f->buf = NULL; | ||
868 | f->tag = FREETAG; | ||
869 | t->nout--; | 1181 | t->nout--; |
870 | |||
871 | aoecmd_work(d); | 1182 | aoecmd_work(d); |
872 | xmit: | ||
873 | __skb_queue_head_init(&queue); | ||
874 | skb_queue_splice_init(&d->sendq, &queue); | ||
875 | 1183 | ||
876 | spin_unlock_irqrestore(&d->lock, flags); | 1184 | spin_unlock_irqrestore(&d->lock, flags); |
877 | aoenet_xmit(&queue); | 1185 | |
1186 | ktcomplete(f, skb); | ||
1187 | |||
1188 | /* | ||
1189 | * Note here that we do not perform an aoedev_put, as we are | ||
1190 | * leaving this reference for the ktio to release. | ||
1191 | */ | ||
1192 | return NULL; | ||
878 | } | 1193 | } |
879 | 1194 | ||
880 | void | 1195 | void |
@@ -896,7 +1211,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
896 | struct sk_buff *skb; | 1211 | struct sk_buff *skb; |
897 | struct aoetgt *t; | 1212 | struct aoetgt *t; |
898 | 1213 | ||
899 | f = freeframe(d); | 1214 | f = newframe(d); |
900 | if (f == NULL) | 1215 | if (f == NULL) |
901 | return NULL; | 1216 | return NULL; |
902 | 1217 | ||
@@ -909,6 +1224,7 @@ aoecmd_ata_id(struct aoedev *d) | |||
909 | skb_put(skb, sizeof *h + sizeof *ah); | 1224 | skb_put(skb, sizeof *h + sizeof *ah); |
910 | memset(h, 0, skb->len); | 1225 | memset(h, 0, skb->len); |
911 | f->tag = aoehdr_atainit(d, t, h); | 1226 | f->tag = aoehdr_atainit(d, t, h); |
1227 | fhash(f); | ||
912 | t->nout++; | 1228 | t->nout++; |
913 | f->waited = 0; | 1229 | f->waited = 0; |
914 | 1230 | ||
@@ -929,7 +1245,6 @@ static struct aoetgt * | |||
929 | addtgt(struct aoedev *d, char *addr, ulong nframes) | 1245 | addtgt(struct aoedev *d, char *addr, ulong nframes) |
930 | { | 1246 | { |
931 | struct aoetgt *t, **tt, **te; | 1247 | struct aoetgt *t, **tt, **te; |
932 | struct frame *f, *e; | ||
933 | 1248 | ||
934 | tt = d->targets; | 1249 | tt = d->targets; |
935 | te = tt + NTARGETS; | 1250 | te = tt + NTARGETS; |
@@ -941,26 +1256,73 @@ addtgt(struct aoedev *d, char *addr, ulong nframes) | |||
941 | "aoe: device addtgt failure; too many targets\n"); | 1256 | "aoe: device addtgt failure; too many targets\n"); |
942 | return NULL; | 1257 | return NULL; |
943 | } | 1258 | } |
944 | t = kcalloc(1, sizeof *t, GFP_ATOMIC); | 1259 | t = kzalloc(sizeof(*t), GFP_ATOMIC); |
945 | f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); | 1260 | if (!t) { |
946 | if (!t || !f) { | ||
947 | kfree(f); | ||
948 | kfree(t); | ||
949 | printk(KERN_INFO "aoe: cannot allocate memory to add target\n"); | 1261 | printk(KERN_INFO "aoe: cannot allocate memory to add target\n"); |
950 | return NULL; | 1262 | return NULL; |
951 | } | 1263 | } |
952 | 1264 | ||
1265 | d->ntargets++; | ||
953 | t->nframes = nframes; | 1266 | t->nframes = nframes; |
954 | t->frames = f; | 1267 | t->d = d; |
955 | e = f + nframes; | ||
956 | for (; f < e; f++) | ||
957 | f->tag = FREETAG; | ||
958 | memcpy(t->addr, addr, sizeof t->addr); | 1268 | memcpy(t->addr, addr, sizeof t->addr); |
959 | t->ifp = t->ifs; | 1269 | t->ifp = t->ifs; |
960 | t->maxout = t->nframes; | 1270 | t->maxout = t->nframes; |
1271 | INIT_LIST_HEAD(&t->ffree); | ||
961 | return *tt = t; | 1272 | return *tt = t; |
962 | } | 1273 | } |
963 | 1274 | ||
1275 | static void | ||
1276 | setdbcnt(struct aoedev *d) | ||
1277 | { | ||
1278 | struct aoetgt **t, **e; | ||
1279 | int bcnt = 0; | ||
1280 | |||
1281 | t = d->targets; | ||
1282 | e = t + NTARGETS; | ||
1283 | for (; t < e && *t; t++) | ||
1284 | if (bcnt == 0 || bcnt > (*t)->minbcnt) | ||
1285 | bcnt = (*t)->minbcnt; | ||
1286 | if (bcnt != d->maxbcnt) { | ||
1287 | d->maxbcnt = bcnt; | ||
1288 | pr_info("aoe: e%ld.%d: setting %d byte data frames\n", | ||
1289 | d->aoemajor, d->aoeminor, bcnt); | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1293 | static void | ||
1294 | setifbcnt(struct aoetgt *t, struct net_device *nd, int bcnt) | ||
1295 | { | ||
1296 | struct aoedev *d; | ||
1297 | struct aoeif *p, *e; | ||
1298 | int minbcnt; | ||
1299 | |||
1300 | d = t->d; | ||
1301 | minbcnt = bcnt; | ||
1302 | p = t->ifs; | ||
1303 | e = p + NAOEIFS; | ||
1304 | for (; p < e; p++) { | ||
1305 | if (p->nd == NULL) | ||
1306 | break; /* end of the valid interfaces */ | ||
1307 | if (p->nd == nd) { | ||
1308 | p->bcnt = bcnt; /* we're updating */ | ||
1309 | nd = NULL; | ||
1310 | } else if (minbcnt > p->bcnt) | ||
1311 | minbcnt = p->bcnt; /* find the min interface */ | ||
1312 | } | ||
1313 | if (nd) { | ||
1314 | if (p == e) { | ||
1315 | pr_err("aoe: device setifbcnt failure; too many interfaces.\n"); | ||
1316 | return; | ||
1317 | } | ||
1318 | dev_hold(nd); | ||
1319 | p->nd = nd; | ||
1320 | p->bcnt = bcnt; | ||
1321 | } | ||
1322 | t->minbcnt = minbcnt; | ||
1323 | setdbcnt(d); | ||
1324 | } | ||
1325 | |||
964 | void | 1326 | void |
965 | aoecmd_cfg_rsp(struct sk_buff *skb) | 1327 | aoecmd_cfg_rsp(struct sk_buff *skb) |
966 | { | 1328 | { |
@@ -968,11 +1330,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
968 | struct aoe_hdr *h; | 1330 | struct aoe_hdr *h; |
969 | struct aoe_cfghdr *ch; | 1331 | struct aoe_cfghdr *ch; |
970 | struct aoetgt *t; | 1332 | struct aoetgt *t; |
971 | struct aoeif *ifp; | 1333 | ulong flags, aoemajor; |
972 | ulong flags, sysminor, aoemajor; | ||
973 | struct sk_buff *sl; | 1334 | struct sk_buff *sl; |
1335 | struct sk_buff_head queue; | ||
974 | u16 n; | 1336 | u16 n; |
975 | 1337 | ||
1338 | sl = NULL; | ||
976 | h = (struct aoe_hdr *) skb_mac_header(skb); | 1339 | h = (struct aoe_hdr *) skb_mac_header(skb); |
977 | ch = (struct aoe_cfghdr *) (h+1); | 1340 | ch = (struct aoe_cfghdr *) (h+1); |
978 | 1341 | ||
@@ -986,10 +1349,13 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
986 | "Check shelf dip switches.\n"); | 1349 | "Check shelf dip switches.\n"); |
987 | return; | 1350 | return; |
988 | } | 1351 | } |
989 | 1352 | if (aoemajor == 0xffff) { | |
990 | sysminor = SYSMINOR(aoemajor, h->minor); | 1353 | pr_info("aoe: e%ld.%d: broadcast shelf number invalid\n", |
991 | if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { | 1354 | aoemajor, (int) h->minor); |
992 | printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n", | 1355 | return; |
1356 | } | ||
1357 | if (h->minor == 0xff) { | ||
1358 | pr_info("aoe: e%ld.%d: broadcast slot number invalid\n", | ||
993 | aoemajor, (int) h->minor); | 1359 | aoemajor, (int) h->minor); |
994 | return; | 1360 | return; |
995 | } | 1361 | } |
@@ -998,9 +1364,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
998 | if (n > aoe_maxout) /* keep it reasonable */ | 1364 | if (n > aoe_maxout) /* keep it reasonable */ |
999 | n = aoe_maxout; | 1365 | n = aoe_maxout; |
1000 | 1366 | ||
1001 | d = aoedev_by_sysminor_m(sysminor); | 1367 | d = aoedev_by_aoeaddr(aoemajor, h->minor, 1); |
1002 | if (d == NULL) { | 1368 | if (d == NULL) { |
1003 | printk(KERN_INFO "aoe: device sysminor_m failure\n"); | 1369 | pr_info("aoe: device allocation failure\n"); |
1004 | return; | 1370 | return; |
1005 | } | 1371 | } |
1006 | 1372 | ||
@@ -1009,52 +1375,26 @@ aoecmd_cfg_rsp(struct sk_buff *skb) | |||
1009 | t = gettgt(d, h->src); | 1375 | t = gettgt(d, h->src); |
1010 | if (!t) { | 1376 | if (!t) { |
1011 | t = addtgt(d, h->src, n); | 1377 | t = addtgt(d, h->src, n); |
1012 | if (!t) { | 1378 | if (!t) |
1013 | spin_unlock_irqrestore(&d->lock, flags); | 1379 | goto bail; |
1014 | return; | ||
1015 | } | ||
1016 | } | ||
1017 | ifp = getif(t, skb->dev); | ||
1018 | if (!ifp) { | ||
1019 | ifp = addif(t, skb->dev); | ||
1020 | if (!ifp) { | ||
1021 | printk(KERN_INFO | ||
1022 | "aoe: device addif failure; " | ||
1023 | "too many interfaces?\n"); | ||
1024 | spin_unlock_irqrestore(&d->lock, flags); | ||
1025 | return; | ||
1026 | } | ||
1027 | } | ||
1028 | if (ifp->maxbcnt) { | ||
1029 | n = ifp->nd->mtu; | ||
1030 | n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); | ||
1031 | n /= 512; | ||
1032 | if (n > ch->scnt) | ||
1033 | n = ch->scnt; | ||
1034 | n = n ? n * 512 : DEFAULTBCNT; | ||
1035 | if (n != ifp->maxbcnt) { | ||
1036 | printk(KERN_INFO | ||
1037 | "aoe: e%ld.%d: setting %d%s%s:%pm\n", | ||
1038 | d->aoemajor, d->aoeminor, n, | ||
1039 | " byte data frames on ", ifp->nd->name, | ||
1040 | t->addr); | ||
1041 | ifp->maxbcnt = n; | ||
1042 | } | ||
1043 | } | 1380 | } |
1381 | n = skb->dev->mtu; | ||
1382 | n -= sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr); | ||
1383 | n /= 512; | ||
1384 | if (n > ch->scnt) | ||
1385 | n = ch->scnt; | ||
1386 | n = n ? n * 512 : DEFAULTBCNT; | ||
1387 | setifbcnt(t, skb->dev, n); | ||
1044 | 1388 | ||
1045 | /* don't change users' perspective */ | 1389 | /* don't change users' perspective */ |
1046 | if (d->nopen) { | 1390 | if (d->nopen == 0) { |
1047 | spin_unlock_irqrestore(&d->lock, flags); | 1391 | d->fw_ver = be16_to_cpu(ch->fwver); |
1048 | return; | 1392 | sl = aoecmd_ata_id(d); |
1049 | } | 1393 | } |
1050 | d->fw_ver = be16_to_cpu(ch->fwver); | 1394 | bail: |
1051 | |||
1052 | sl = aoecmd_ata_id(d); | ||
1053 | |||
1054 | spin_unlock_irqrestore(&d->lock, flags); | 1395 | spin_unlock_irqrestore(&d->lock, flags); |
1055 | 1396 | aoedev_put(d); | |
1056 | if (sl) { | 1397 | if (sl) { |
1057 | struct sk_buff_head queue; | ||
1058 | __skb_queue_head_init(&queue); | 1398 | __skb_queue_head_init(&queue); |
1059 | __skb_queue_tail(&queue, sl); | 1399 | __skb_queue_tail(&queue, sl); |
1060 | aoenet_xmit(&queue); | 1400 | aoenet_xmit(&queue); |
@@ -1065,20 +1405,74 @@ void | |||
1065 | aoecmd_cleanslate(struct aoedev *d) | 1405 | aoecmd_cleanslate(struct aoedev *d) |
1066 | { | 1406 | { |
1067 | struct aoetgt **t, **te; | 1407 | struct aoetgt **t, **te; |
1068 | struct aoeif *p, *e; | ||
1069 | 1408 | ||
1070 | d->mintimer = MINTIMER; | 1409 | d->mintimer = MINTIMER; |
1410 | d->maxbcnt = 0; | ||
1071 | 1411 | ||
1072 | t = d->targets; | 1412 | t = d->targets; |
1073 | te = t + NTARGETS; | 1413 | te = t + NTARGETS; |
1074 | for (; t < te && *t; t++) { | 1414 | for (; t < te && *t; t++) |
1075 | (*t)->maxout = (*t)->nframes; | 1415 | (*t)->maxout = (*t)->nframes; |
1076 | p = (*t)->ifs; | 1416 | } |
1077 | e = p + NAOEIFS; | 1417 | |
1078 | for (; p < e; p++) { | 1418 | void |
1079 | p->lostjumbo = 0; | 1419 | aoe_failbuf(struct aoedev *d, struct buf *buf) |
1080 | p->lost = 0; | 1420 | { |
1081 | p->maxbcnt = DEFAULTBCNT; | 1421 | if (buf == NULL) |
1422 | return; | ||
1423 | buf->resid = 0; | ||
1424 | clear_bit(BIO_UPTODATE, &buf->bio->bi_flags); | ||
1425 | if (buf->nframesout == 0) | ||
1426 | aoe_end_buf(d, buf); | ||
1427 | } | ||
1428 | |||
1429 | void | ||
1430 | aoe_flush_iocq(void) | ||
1431 | { | ||
1432 | struct frame *f; | ||
1433 | struct aoedev *d; | ||
1434 | LIST_HEAD(flist); | ||
1435 | struct list_head *pos; | ||
1436 | struct sk_buff *skb; | ||
1437 | ulong flags; | ||
1438 | |||
1439 | spin_lock_irqsave(&iocq.lock, flags); | ||
1440 | list_splice_init(&iocq.head, &flist); | ||
1441 | spin_unlock_irqrestore(&iocq.lock, flags); | ||
1442 | while (!list_empty(&flist)) { | ||
1443 | pos = flist.next; | ||
1444 | list_del(pos); | ||
1445 | f = list_entry(pos, struct frame, head); | ||
1446 | d = f->t->d; | ||
1447 | skb = f->r_skb; | ||
1448 | spin_lock_irqsave(&d->lock, flags); | ||
1449 | if (f->buf) { | ||
1450 | f->buf->nframesout--; | ||
1451 | aoe_failbuf(d, f->buf); | ||
1082 | } | 1452 | } |
1453 | aoe_freetframe(f); | ||
1454 | spin_unlock_irqrestore(&d->lock, flags); | ||
1455 | dev_kfree_skb(skb); | ||
1456 | aoedev_put(d); | ||
1083 | } | 1457 | } |
1084 | } | 1458 | } |
1459 | |||
1460 | int __init | ||
1461 | aoecmd_init(void) | ||
1462 | { | ||
1463 | INIT_LIST_HEAD(&iocq.head); | ||
1464 | spin_lock_init(&iocq.lock); | ||
1465 | init_waitqueue_head(&ktiowq); | ||
1466 | kts.name = "aoe_ktio"; | ||
1467 | kts.fn = ktio; | ||
1468 | kts.waitq = &ktiowq; | ||
1469 | kts.lock = &iocq.lock; | ||
1470 | return aoe_ktstart(&kts); | ||
1471 | } | ||
1472 | |||
1473 | void | ||
1474 | aoecmd_exit(void) | ||
1475 | { | ||
1476 | aoe_ktstop(&kts); | ||
1477 | aoe_flush_iocq(); | ||
1478 | } | ||
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 6b5110a47458..90e5b537f94b 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoedev.c | 3 | * aoedev.c |
4 | * AoE device utility functions; maintains device list. | 4 | * AoE device utility functions; maintains device list. |
@@ -9,6 +9,9 @@ | |||
9 | #include <linux/netdevice.h> | 9 | #include <linux/netdevice.h> |
10 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/bitmap.h> | ||
13 | #include <linux/kdev_t.h> | ||
14 | #include <linux/moduleparam.h> | ||
12 | #include "aoe.h" | 15 | #include "aoe.h" |
13 | 16 | ||
14 | static void dummy_timer(ulong); | 17 | static void dummy_timer(ulong); |
@@ -16,23 +19,121 @@ static void aoedev_freedev(struct aoedev *); | |||
16 | static void freetgt(struct aoedev *d, struct aoetgt *t); | 19 | static void freetgt(struct aoedev *d, struct aoetgt *t); |
17 | static void skbpoolfree(struct aoedev *d); | 20 | static void skbpoolfree(struct aoedev *d); |
18 | 21 | ||
22 | static int aoe_dyndevs = 1; | ||
23 | module_param(aoe_dyndevs, int, 0644); | ||
24 | MODULE_PARM_DESC(aoe_dyndevs, "Use dynamic minor numbers for devices."); | ||
25 | |||
19 | static struct aoedev *devlist; | 26 | static struct aoedev *devlist; |
20 | static DEFINE_SPINLOCK(devlist_lock); | 27 | static DEFINE_SPINLOCK(devlist_lock); |
21 | 28 | ||
22 | struct aoedev * | 29 | /* Because some systems will have one, many, or no |
23 | aoedev_by_aoeaddr(int maj, int min) | 30 | * - partitions, |
31 | * - slots per shelf, | ||
32 | * - or shelves, | ||
33 | * we need some flexibility in the way the minor numbers | ||
34 | * are allocated. So they are dynamic. | ||
35 | */ | ||
36 | #define N_DEVS ((1U<<MINORBITS)/AOE_PARTITIONS) | ||
37 | |||
38 | static DEFINE_SPINLOCK(used_minors_lock); | ||
39 | static DECLARE_BITMAP(used_minors, N_DEVS); | ||
40 | |||
41 | static int | ||
42 | minor_get_dyn(ulong *sysminor) | ||
24 | { | 43 | { |
25 | struct aoedev *d; | ||
26 | ulong flags; | 44 | ulong flags; |
45 | ulong n; | ||
46 | int error = 0; | ||
47 | |||
48 | spin_lock_irqsave(&used_minors_lock, flags); | ||
49 | n = find_first_zero_bit(used_minors, N_DEVS); | ||
50 | if (n < N_DEVS) | ||
51 | set_bit(n, used_minors); | ||
52 | else | ||
53 | error = -1; | ||
54 | spin_unlock_irqrestore(&used_minors_lock, flags); | ||
55 | |||
56 | *sysminor = n * AOE_PARTITIONS; | ||
57 | return error; | ||
58 | } | ||
27 | 59 | ||
28 | spin_lock_irqsave(&devlist_lock, flags); | 60 | static int |
61 | minor_get_static(ulong *sysminor, ulong aoemaj, int aoemin) | ||
62 | { | ||
63 | ulong flags; | ||
64 | ulong n; | ||
65 | int error = 0; | ||
66 | enum { | ||
67 | /* for backwards compatibility when !aoe_dyndevs, | ||
68 | * a static number of supported slots per shelf */ | ||
69 | NPERSHELF = 16, | ||
70 | }; | ||
71 | |||
72 | n = aoemaj * NPERSHELF + aoemin; | ||
73 | if (aoemin >= NPERSHELF || n >= N_DEVS) { | ||
74 | pr_err("aoe: %s with e%ld.%d\n", | ||
75 | "cannot use static minor device numbers", | ||
76 | aoemaj, aoemin); | ||
77 | error = -1; | ||
78 | } else { | ||
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 | } | ||
29 | 89 | ||
30 | for (d=devlist; d; d=d->next) | 90 | *sysminor = n; |
31 | if (d->aoemajor == maj && d->aoeminor == min) | 91 | return error; |
32 | break; | 92 | } |
93 | |||
94 | static int | ||
95 | minor_get(ulong *sysminor, ulong aoemaj, int aoemin) | ||
96 | { | ||
97 | if (aoe_dyndevs) | ||
98 | return minor_get_dyn(sysminor); | ||
99 | else | ||
100 | return minor_get_static(sysminor, aoemaj, aoemin); | ||
101 | } | ||
102 | |||
103 | static void | ||
104 | minor_free(ulong minor) | ||
105 | { | ||
106 | ulong flags; | ||
107 | |||
108 | minor /= AOE_PARTITIONS; | ||
109 | BUG_ON(minor >= N_DEVS); | ||
110 | |||
111 | spin_lock_irqsave(&used_minors_lock, flags); | ||
112 | BUG_ON(!test_bit(minor, used_minors)); | ||
113 | clear_bit(minor, used_minors); | ||
114 | spin_unlock_irqrestore(&used_minors_lock, flags); | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * Users who grab a pointer to the device with aoedev_by_aoeaddr | ||
119 | * automatically get a reference count and must be responsible | ||
120 | * for performing a aoedev_put. With the addition of async | ||
121 | * kthread processing I'm no longer confident that we can | ||
122 | * guarantee consistency in the face of device flushes. | ||
123 | * | ||
124 | * For the time being, we only bother to add extra references for | ||
125 | * frames sitting on the iocq. When the kthreads finish processing | ||
126 | * these frames, they will aoedev_put the device. | ||
127 | */ | ||
128 | |||
129 | void | ||
130 | aoedev_put(struct aoedev *d) | ||
131 | { | ||
132 | ulong flags; | ||
33 | 133 | ||
134 | spin_lock_irqsave(&devlist_lock, flags); | ||
135 | d->ref--; | ||
34 | spin_unlock_irqrestore(&devlist_lock, flags); | 136 | spin_unlock_irqrestore(&devlist_lock, flags); |
35 | return d; | ||
36 | } | 137 | } |
37 | 138 | ||
38 | static void | 139 | static void |
@@ -47,54 +148,74 @@ dummy_timer(ulong vp) | |||
47 | add_timer(&d->timer); | 148 | add_timer(&d->timer); |
48 | } | 149 | } |
49 | 150 | ||
151 | static void | ||
152 | aoe_failip(struct aoedev *d) | ||
153 | { | ||
154 | struct request *rq; | ||
155 | struct bio *bio; | ||
156 | unsigned long n; | ||
157 | |||
158 | aoe_failbuf(d, d->ip.buf); | ||
159 | |||
160 | rq = d->ip.rq; | ||
161 | if (rq == NULL) | ||
162 | return; | ||
163 | while ((bio = d->ip.nxbio)) { | ||
164 | clear_bit(BIO_UPTODATE, &bio->bi_flags); | ||
165 | d->ip.nxbio = bio->bi_next; | ||
166 | n = (unsigned long) rq->special; | ||
167 | rq->special = (void *) --n; | ||
168 | } | ||
169 | if ((unsigned long) rq->special == 0) | ||
170 | aoe_end_request(d, rq, 0); | ||
171 | } | ||
172 | |||
50 | void | 173 | void |
51 | aoedev_downdev(struct aoedev *d) | 174 | aoedev_downdev(struct aoedev *d) |
52 | { | 175 | { |
53 | struct aoetgt **t, **te; | 176 | struct aoetgt *t, **tt, **te; |
54 | struct frame *f, *e; | 177 | struct frame *f; |
55 | struct buf *buf; | 178 | struct list_head *head, *pos, *nx; |
56 | struct bio *bio; | 179 | struct request *rq; |
180 | int i; | ||
57 | 181 | ||
58 | t = d->targets; | 182 | d->flags &= ~DEVFL_UP; |
59 | te = t + NTARGETS; | 183 | |
60 | for (; t < te && *t; t++) { | 184 | /* clean out active buffers */ |
61 | f = (*t)->frames; | 185 | for (i = 0; i < NFACTIVE; i++) { |
62 | e = f + (*t)->nframes; | 186 | head = &d->factive[i]; |
63 | for (; f < e; f->tag = FREETAG, f->buf = NULL, f++) { | 187 | list_for_each_safe(pos, nx, head) { |
64 | if (f->tag == FREETAG || f->buf == NULL) | 188 | f = list_entry(pos, struct frame, head); |
65 | continue; | 189 | list_del(pos); |
66 | buf = f->buf; | 190 | if (f->buf) { |
67 | bio = buf->bio; | 191 | f->buf->nframesout--; |
68 | if (--buf->nframesout == 0 | 192 | aoe_failbuf(d, f->buf); |
69 | && buf != d->inprocess) { | ||
70 | mempool_free(buf, d->bufpool); | ||
71 | bio_endio(bio, -EIO); | ||
72 | } | 193 | } |
194 | aoe_freetframe(f); | ||
73 | } | 195 | } |
74 | (*t)->maxout = (*t)->nframes; | ||
75 | (*t)->nout = 0; | ||
76 | } | 196 | } |
77 | buf = d->inprocess; | 197 | /* reset window dressings */ |
78 | if (buf) { | 198 | tt = d->targets; |
79 | bio = buf->bio; | 199 | te = tt + NTARGETS; |
80 | mempool_free(buf, d->bufpool); | 200 | for (; tt < te && (t = *tt); tt++) { |
81 | bio_endio(bio, -EIO); | 201 | t->maxout = t->nframes; |
202 | t->nout = 0; | ||
82 | } | 203 | } |
83 | d->inprocess = NULL; | 204 | |
205 | /* clean out the in-process request (if any) */ | ||
206 | aoe_failip(d); | ||
84 | d->htgt = NULL; | 207 | d->htgt = NULL; |
85 | 208 | ||
86 | while (!list_empty(&d->bufq)) { | 209 | /* fast fail all pending I/O */ |
87 | buf = container_of(d->bufq.next, struct buf, bufs); | 210 | if (d->blkq) { |
88 | list_del(d->bufq.next); | 211 | while ((rq = blk_peek_request(d->blkq))) { |
89 | bio = buf->bio; | 212 | blk_start_request(rq); |
90 | mempool_free(buf, d->bufpool); | 213 | aoe_end_request(d, rq, 1); |
91 | bio_endio(bio, -EIO); | 214 | } |
92 | } | 215 | } |
93 | 216 | ||
94 | if (d->gd) | 217 | if (d->gd) |
95 | set_capacity(d->gd, 0); | 218 | set_capacity(d->gd, 0); |
96 | |||
97 | d->flags &= ~DEVFL_UP; | ||
98 | } | 219 | } |
99 | 220 | ||
100 | static void | 221 | static void |
@@ -107,6 +228,7 @@ aoedev_freedev(struct aoedev *d) | |||
107 | aoedisk_rm_sysfs(d); | 228 | aoedisk_rm_sysfs(d); |
108 | del_gendisk(d->gd); | 229 | del_gendisk(d->gd); |
109 | put_disk(d->gd); | 230 | put_disk(d->gd); |
231 | blk_cleanup_queue(d->blkq); | ||
110 | } | 232 | } |
111 | t = d->targets; | 233 | t = d->targets; |
112 | e = t + NTARGETS; | 234 | e = t + NTARGETS; |
@@ -115,7 +237,7 @@ aoedev_freedev(struct aoedev *d) | |||
115 | if (d->bufpool) | 237 | if (d->bufpool) |
116 | mempool_destroy(d->bufpool); | 238 | mempool_destroy(d->bufpool); |
117 | skbpoolfree(d); | 239 | skbpoolfree(d); |
118 | blk_cleanup_queue(d->blkq); | 240 | minor_free(d->sysminor); |
119 | kfree(d); | 241 | kfree(d); |
120 | } | 242 | } |
121 | 243 | ||
@@ -142,7 +264,8 @@ aoedev_flush(const char __user *str, size_t cnt) | |||
142 | spin_lock(&d->lock); | 264 | spin_lock(&d->lock); |
143 | if ((!all && (d->flags & DEVFL_UP)) | 265 | if ((!all && (d->flags & DEVFL_UP)) |
144 | || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) | 266 | || (d->flags & (DEVFL_GDALLOC|DEVFL_NEWSIZE)) |
145 | || d->nopen) { | 267 | || d->nopen |
268 | || d->ref) { | ||
146 | spin_unlock(&d->lock); | 269 | spin_unlock(&d->lock); |
147 | dd = &d->next; | 270 | dd = &d->next; |
148 | continue; | 271 | continue; |
@@ -163,12 +286,15 @@ aoedev_flush(const char __user *str, size_t cnt) | |||
163 | return 0; | 286 | return 0; |
164 | } | 287 | } |
165 | 288 | ||
166 | /* I'm not really sure that this is a realistic problem, but if the | 289 | /* This has been confirmed to occur once with Tms=3*1000 due to the |
167 | network driver goes gonzo let's just leak memory after complaining. */ | 290 | * driver changing link and not processing its transmit ring. The |
291 | * problem is hard enough to solve by returning an error that I'm | ||
292 | * still punting on "solving" this. | ||
293 | */ | ||
168 | static void | 294 | static void |
169 | skbfree(struct sk_buff *skb) | 295 | skbfree(struct sk_buff *skb) |
170 | { | 296 | { |
171 | enum { Sms = 100, Tms = 3*1000}; | 297 | enum { Sms = 250, Tms = 30 * 1000}; |
172 | int i = Tms / Sms; | 298 | int i = Tms / Sms; |
173 | 299 | ||
174 | if (skb == NULL) | 300 | if (skb == NULL) |
@@ -182,6 +308,7 @@ skbfree(struct sk_buff *skb) | |||
182 | "cannot free skb -- memory leaked."); | 308 | "cannot free skb -- memory leaked."); |
183 | return; | 309 | return; |
184 | } | 310 | } |
311 | skb->truesize -= skb->data_len; | ||
185 | skb_shinfo(skb)->nr_frags = skb->data_len = 0; | 312 | skb_shinfo(skb)->nr_frags = skb->data_len = 0; |
186 | skb_trim(skb, 0); | 313 | skb_trim(skb, 0); |
187 | dev_kfree_skb(skb); | 314 | dev_kfree_skb(skb); |
@@ -198,26 +325,29 @@ skbpoolfree(struct aoedev *d) | |||
198 | __skb_queue_head_init(&d->skbpool); | 325 | __skb_queue_head_init(&d->skbpool); |
199 | } | 326 | } |
200 | 327 | ||
201 | /* find it or malloc it */ | 328 | /* find it or allocate it */ |
202 | struct aoedev * | 329 | struct aoedev * |
203 | aoedev_by_sysminor_m(ulong sysminor) | 330 | aoedev_by_aoeaddr(ulong maj, int min, int do_alloc) |
204 | { | 331 | { |
205 | struct aoedev *d; | 332 | struct aoedev *d; |
333 | int i; | ||
206 | ulong flags; | 334 | ulong flags; |
335 | ulong sysminor; | ||
207 | 336 | ||
208 | spin_lock_irqsave(&devlist_lock, flags); | 337 | spin_lock_irqsave(&devlist_lock, flags); |
209 | 338 | ||
210 | for (d=devlist; d; d=d->next) | 339 | for (d=devlist; d; d=d->next) |
211 | if (d->sysminor == sysminor) | 340 | if (d->aoemajor == maj && d->aoeminor == min) { |
341 | d->ref++; | ||
212 | break; | 342 | break; |
213 | if (d) | 343 | } |
344 | if (d || !do_alloc || minor_get(&sysminor, maj, min) < 0) | ||
214 | goto out; | 345 | goto out; |
215 | d = kcalloc(1, sizeof *d, GFP_ATOMIC); | 346 | d = kcalloc(1, sizeof *d, GFP_ATOMIC); |
216 | if (!d) | 347 | if (!d) |
217 | goto out; | 348 | goto out; |
218 | INIT_WORK(&d->work, aoecmd_sleepwork); | 349 | INIT_WORK(&d->work, aoecmd_sleepwork); |
219 | spin_lock_init(&d->lock); | 350 | spin_lock_init(&d->lock); |
220 | skb_queue_head_init(&d->sendq); | ||
221 | skb_queue_head_init(&d->skbpool); | 351 | skb_queue_head_init(&d->skbpool); |
222 | init_timer(&d->timer); | 352 | init_timer(&d->timer); |
223 | d->timer.data = (ulong) d; | 353 | d->timer.data = (ulong) d; |
@@ -226,10 +356,12 @@ aoedev_by_sysminor_m(ulong sysminor) | |||
226 | add_timer(&d->timer); | 356 | add_timer(&d->timer); |
227 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ | 357 | d->bufpool = NULL; /* defer to aoeblk_gdalloc */ |
228 | d->tgt = d->targets; | 358 | d->tgt = d->targets; |
229 | INIT_LIST_HEAD(&d->bufq); | 359 | d->ref = 1; |
360 | for (i = 0; i < NFACTIVE; i++) | ||
361 | INIT_LIST_HEAD(&d->factive[i]); | ||
230 | d->sysminor = sysminor; | 362 | d->sysminor = sysminor; |
231 | d->aoemajor = AOEMAJOR(sysminor); | 363 | d->aoemajor = maj; |
232 | d->aoeminor = AOEMINOR(sysminor); | 364 | d->aoeminor = min; |
233 | d->mintimer = MINTIMER; | 365 | d->mintimer = MINTIMER; |
234 | d->next = devlist; | 366 | d->next = devlist; |
235 | devlist = d; | 367 | devlist = d; |
@@ -241,13 +373,23 @@ aoedev_by_sysminor_m(ulong sysminor) | |||
241 | static void | 373 | static void |
242 | freetgt(struct aoedev *d, struct aoetgt *t) | 374 | freetgt(struct aoedev *d, struct aoetgt *t) |
243 | { | 375 | { |
244 | struct frame *f, *e; | 376 | struct frame *f; |
377 | struct list_head *pos, *nx, *head; | ||
378 | struct aoeif *ifp; | ||
245 | 379 | ||
246 | f = t->frames; | 380 | for (ifp = t->ifs; ifp < &t->ifs[NAOEIFS]; ++ifp) { |
247 | e = f + t->nframes; | 381 | if (!ifp->nd) |
248 | for (; f < e; f++) | 382 | break; |
383 | dev_put(ifp->nd); | ||
384 | } | ||
385 | |||
386 | head = &t->ffree; | ||
387 | list_for_each_safe(pos, nx, head) { | ||
388 | list_del(pos); | ||
389 | f = list_entry(pos, struct frame, head); | ||
249 | skbfree(f->skb); | 390 | skbfree(f->skb); |
250 | kfree(t->frames); | 391 | kfree(f); |
392 | } | ||
251 | kfree(t); | 393 | kfree(t); |
252 | } | 394 | } |
253 | 395 | ||
@@ -257,6 +399,7 @@ aoedev_exit(void) | |||
257 | struct aoedev *d; | 399 | struct aoedev *d; |
258 | ulong flags; | 400 | ulong flags; |
259 | 401 | ||
402 | aoe_flush_iocq(); | ||
260 | while ((d = devlist)) { | 403 | while ((d = devlist)) { |
261 | devlist = d->next; | 404 | devlist = d->next; |
262 | 405 | ||
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 7f83ad90e76f..04793c2c701b 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoemain.c | 3 | * aoemain.c |
4 | * Module initialization routines, discover timer | 4 | * Module initialization routines, discover timer |
@@ -61,6 +61,7 @@ aoe_exit(void) | |||
61 | 61 | ||
62 | aoenet_exit(); | 62 | aoenet_exit(); |
63 | unregister_blkdev(AOE_MAJOR, DEVICE_NAME); | 63 | unregister_blkdev(AOE_MAJOR, DEVICE_NAME); |
64 | aoecmd_exit(); | ||
64 | aoechr_exit(); | 65 | aoechr_exit(); |
65 | aoedev_exit(); | 66 | aoedev_exit(); |
66 | aoeblk_exit(); /* free cache after de-allocating bufs */ | 67 | aoeblk_exit(); /* free cache after de-allocating bufs */ |
@@ -83,17 +84,20 @@ aoe_init(void) | |||
83 | ret = aoenet_init(); | 84 | ret = aoenet_init(); |
84 | if (ret) | 85 | if (ret) |
85 | goto net_fail; | 86 | goto net_fail; |
87 | ret = aoecmd_init(); | ||
88 | if (ret) | ||
89 | goto cmd_fail; | ||
86 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); | 90 | ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); |
87 | if (ret < 0) { | 91 | if (ret < 0) { |
88 | printk(KERN_ERR "aoe: can't register major\n"); | 92 | printk(KERN_ERR "aoe: can't register major\n"); |
89 | goto blkreg_fail; | 93 | goto blkreg_fail; |
90 | } | 94 | } |
91 | |||
92 | printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION); | 95 | printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION); |
93 | discover_timer(TINIT); | 96 | discover_timer(TINIT); |
94 | return 0; | 97 | return 0; |
95 | |||
96 | blkreg_fail: | 98 | blkreg_fail: |
99 | aoecmd_exit(); | ||
100 | cmd_fail: | ||
97 | aoenet_exit(); | 101 | aoenet_exit(); |
98 | net_fail: | 102 | net_fail: |
99 | aoeblk_exit(); | 103 | aoeblk_exit(); |
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 4d3bc0d49df5..162c6471275c 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ | 1 | /* Copyright (c) 2012 Coraid, Inc. See COPYING for GPL terms. */ |
2 | /* | 2 | /* |
3 | * aoenet.c | 3 | * aoenet.c |
4 | * Ethernet portion of AoE driver | 4 | * Ethernet portion of AoE driver |
@@ -33,6 +33,9 @@ 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; | ||
37 | static struct ktstate kts; | ||
38 | |||
36 | #ifndef MODULE | 39 | #ifndef MODULE |
37 | static int __init aoe_iflist_setup(char *str) | 40 | static int __init aoe_iflist_setup(char *str) |
38 | { | 41 | { |
@@ -44,6 +47,23 @@ static int __init aoe_iflist_setup(char *str) | |||
44 | __setup("aoe_iflist=", aoe_iflist_setup); | 47 | __setup("aoe_iflist=", aoe_iflist_setup); |
45 | #endif | 48 | #endif |
46 | 49 | ||
50 | static spinlock_t txlock; | ||
51 | static struct sk_buff_head skbtxq; | ||
52 | |||
53 | /* enters with txlock held */ | ||
54 | static int | ||
55 | tx(void) | ||
56 | { | ||
57 | struct sk_buff *skb; | ||
58 | |||
59 | while ((skb = skb_dequeue(&skbtxq))) { | ||
60 | spin_unlock_irq(&txlock); | ||
61 | dev_queue_xmit(skb); | ||
62 | spin_lock_irq(&txlock); | ||
63 | } | ||
64 | return 0; | ||
65 | } | ||
66 | |||
47 | int | 67 | int |
48 | is_aoe_netif(struct net_device *ifp) | 68 | is_aoe_netif(struct net_device *ifp) |
49 | { | 69 | { |
@@ -88,10 +108,14 @@ void | |||
88 | aoenet_xmit(struct sk_buff_head *queue) | 108 | aoenet_xmit(struct sk_buff_head *queue) |
89 | { | 109 | { |
90 | struct sk_buff *skb, *tmp; | 110 | struct sk_buff *skb, *tmp; |
111 | ulong flags; | ||
91 | 112 | ||
92 | skb_queue_walk_safe(queue, skb, tmp) { | 113 | skb_queue_walk_safe(queue, skb, tmp) { |
93 | __skb_unlink(skb, queue); | 114 | __skb_unlink(skb, queue); |
94 | dev_queue_xmit(skb); | 115 | spin_lock_irqsave(&txlock, flags); |
116 | skb_queue_tail(&skbtxq, skb); | ||
117 | spin_unlock_irqrestore(&txlock, flags); | ||
118 | wake_up(&txwq); | ||
95 | } | 119 | } |
96 | } | 120 | } |
97 | 121 | ||
@@ -102,7 +126,9 @@ static int | |||
102 | aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) | 126 | aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, struct net_device *orig_dev) |
103 | { | 127 | { |
104 | struct aoe_hdr *h; | 128 | struct aoe_hdr *h; |
129 | struct aoe_atahdr *ah; | ||
105 | u32 n; | 130 | u32 n; |
131 | int sn; | ||
106 | 132 | ||
107 | if (dev_net(ifp) != &init_net) | 133 | if (dev_net(ifp) != &init_net) |
108 | goto exit; | 134 | goto exit; |
@@ -110,13 +136,16 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
110 | skb = skb_share_check(skb, GFP_ATOMIC); | 136 | skb = skb_share_check(skb, GFP_ATOMIC); |
111 | if (skb == NULL) | 137 | if (skb == NULL) |
112 | return 0; | 138 | return 0; |
113 | if (skb_linearize(skb)) | ||
114 | goto exit; | ||
115 | if (!is_aoe_netif(ifp)) | 139 | if (!is_aoe_netif(ifp)) |
116 | goto exit; | 140 | goto exit; |
117 | skb_push(skb, ETH_HLEN); /* (1) */ | 141 | skb_push(skb, ETH_HLEN); /* (1) */ |
118 | 142 | sn = sizeof(*h) + sizeof(*ah); | |
119 | h = (struct aoe_hdr *) skb_mac_header(skb); | 143 | if (skb->len >= sn) { |
144 | sn -= skb_headlen(skb); | ||
145 | if (sn > 0 && !__pskb_pull_tail(skb, sn)) | ||
146 | goto exit; | ||
147 | } | ||
148 | h = (struct aoe_hdr *) skb->data; | ||
120 | n = get_unaligned_be32(&h->tag); | 149 | n = get_unaligned_be32(&h->tag); |
121 | if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31)) | 150 | if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31)) |
122 | goto exit; | 151 | goto exit; |
@@ -137,7 +166,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
137 | 166 | ||
138 | switch (h->cmd) { | 167 | switch (h->cmd) { |
139 | case AOECMD_ATA: | 168 | case AOECMD_ATA: |
140 | aoecmd_ata_rsp(skb); | 169 | /* ata_rsp may keep skb for later processing or give it back */ |
170 | skb = aoecmd_ata_rsp(skb); | ||
141 | break; | 171 | break; |
142 | case AOECMD_CFG: | 172 | case AOECMD_CFG: |
143 | aoecmd_cfg_rsp(skb); | 173 | aoecmd_cfg_rsp(skb); |
@@ -145,8 +175,12 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, | |||
145 | default: | 175 | default: |
146 | if (h->cmd >= AOECMD_VEND_MIN) | 176 | if (h->cmd >= AOECMD_VEND_MIN) |
147 | break; /* don't complain about vendor commands */ | 177 | break; /* don't complain about vendor commands */ |
148 | printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd); | 178 | pr_info("aoe: unknown AoE command type 0x%02x\n", h->cmd); |
179 | break; | ||
149 | } | 180 | } |
181 | |||
182 | if (!skb) | ||
183 | return 0; | ||
150 | exit: | 184 | exit: |
151 | dev_kfree_skb(skb); | 185 | dev_kfree_skb(skb); |
152 | return 0; | 186 | return 0; |
@@ -160,6 +194,15 @@ static struct packet_type aoe_pt __read_mostly = { | |||
160 | int __init | 194 | int __init |
161 | aoenet_init(void) | 195 | aoenet_init(void) |
162 | { | 196 | { |
197 | skb_queue_head_init(&skbtxq); | ||
198 | init_waitqueue_head(&txwq); | ||
199 | spin_lock_init(&txlock); | ||
200 | kts.lock = &txlock; | ||
201 | kts.fn = tx; | ||
202 | kts.waitq = &txwq; | ||
203 | kts.name = "aoe_tx"; | ||
204 | if (aoe_ktstart(&kts)) | ||
205 | return -EAGAIN; | ||
163 | dev_add_pack(&aoe_pt); | 206 | dev_add_pack(&aoe_pt); |
164 | return 0; | 207 | return 0; |
165 | } | 208 | } |
@@ -167,6 +210,8 @@ aoenet_init(void) | |||
167 | void | 210 | void |
168 | aoenet_exit(void) | 211 | aoenet_exit(void) |
169 | { | 212 | { |
213 | aoe_ktstop(&kts); | ||
214 | skb_queue_purge(&skbtxq); | ||
170 | dev_remove_pack(&aoe_pt); | 215 | dev_remove_pack(&aoe_pt); |
171 | } | 216 | } |
172 | 217 | ||
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 0c03411c59eb..043ddcca4abf 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -78,6 +78,8 @@ static const char *ioctl_cmd_to_ascii(int cmd) | |||
78 | case NBD_SET_SOCK: return "set-sock"; | 78 | case NBD_SET_SOCK: return "set-sock"; |
79 | case NBD_SET_BLKSIZE: return "set-blksize"; | 79 | case NBD_SET_BLKSIZE: return "set-blksize"; |
80 | case NBD_SET_SIZE: return "set-size"; | 80 | case NBD_SET_SIZE: return "set-size"; |
81 | case NBD_SET_TIMEOUT: return "set-timeout"; | ||
82 | case NBD_SET_FLAGS: return "set-flags"; | ||
81 | case NBD_DO_IT: return "do-it"; | 83 | case NBD_DO_IT: return "do-it"; |
82 | case NBD_CLEAR_SOCK: return "clear-sock"; | 84 | case NBD_CLEAR_SOCK: return "clear-sock"; |
83 | case NBD_CLEAR_QUE: return "clear-que"; | 85 | case NBD_CLEAR_QUE: return "clear-que"; |
@@ -96,6 +98,7 @@ static const char *nbdcmd_to_ascii(int cmd) | |||
96 | case NBD_CMD_READ: return "read"; | 98 | case NBD_CMD_READ: return "read"; |
97 | case NBD_CMD_WRITE: return "write"; | 99 | case NBD_CMD_WRITE: return "write"; |
98 | case NBD_CMD_DISC: return "disconnect"; | 100 | case NBD_CMD_DISC: return "disconnect"; |
101 | case NBD_CMD_TRIM: return "trim/discard"; | ||
99 | } | 102 | } |
100 | return "invalid"; | 103 | return "invalid"; |
101 | } | 104 | } |
@@ -467,8 +470,12 @@ static void nbd_handle_req(struct nbd_device *nbd, struct request *req) | |||
467 | 470 | ||
468 | nbd_cmd(req) = NBD_CMD_READ; | 471 | nbd_cmd(req) = NBD_CMD_READ; |
469 | if (rq_data_dir(req) == WRITE) { | 472 | if (rq_data_dir(req) == WRITE) { |
470 | nbd_cmd(req) = NBD_CMD_WRITE; | 473 | if ((req->cmd_flags & REQ_DISCARD)) { |
471 | if (nbd->flags & NBD_READ_ONLY) { | 474 | WARN_ON(!(nbd->flags & NBD_FLAG_SEND_TRIM)); |
475 | nbd_cmd(req) = NBD_CMD_TRIM; | ||
476 | } else | ||
477 | nbd_cmd(req) = NBD_CMD_WRITE; | ||
478 | if (nbd->flags & NBD_FLAG_READ_ONLY) { | ||
472 | dev_err(disk_to_dev(nbd->disk), | 479 | dev_err(disk_to_dev(nbd->disk), |
473 | "Write on read-only\n"); | 480 | "Write on read-only\n"); |
474 | goto error_out; | 481 | goto error_out; |
@@ -651,6 +658,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, | |||
651 | nbd->xmit_timeout = arg * HZ; | 658 | nbd->xmit_timeout = arg * HZ; |
652 | return 0; | 659 | return 0; |
653 | 660 | ||
661 | case NBD_SET_FLAGS: | ||
662 | nbd->flags = arg; | ||
663 | return 0; | ||
664 | |||
654 | case NBD_SET_SIZE_BLOCKS: | 665 | case NBD_SET_SIZE_BLOCKS: |
655 | nbd->bytesize = ((u64) arg) * nbd->blksize; | 666 | nbd->bytesize = ((u64) arg) * nbd->blksize; |
656 | bdev->bd_inode->i_size = nbd->bytesize; | 667 | bdev->bd_inode->i_size = nbd->bytesize; |
@@ -670,6 +681,10 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, | |||
670 | 681 | ||
671 | mutex_unlock(&nbd->tx_lock); | 682 | mutex_unlock(&nbd->tx_lock); |
672 | 683 | ||
684 | if (nbd->flags & NBD_FLAG_SEND_TRIM) | ||
685 | queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, | ||
686 | nbd->disk->queue); | ||
687 | |||
673 | thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name); | 688 | thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name); |
674 | if (IS_ERR(thread)) { | 689 | if (IS_ERR(thread)) { |
675 | mutex_lock(&nbd->tx_lock); | 690 | mutex_lock(&nbd->tx_lock); |
@@ -687,6 +702,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, | |||
687 | nbd->file = NULL; | 702 | nbd->file = NULL; |
688 | nbd_clear_que(nbd); | 703 | nbd_clear_que(nbd); |
689 | dev_warn(disk_to_dev(nbd->disk), "queue cleared\n"); | 704 | dev_warn(disk_to_dev(nbd->disk), "queue cleared\n"); |
705 | queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, nbd->disk->queue); | ||
690 | if (file) | 706 | if (file) |
691 | fput(file); | 707 | fput(file); |
692 | nbd->bytesize = 0; | 708 | nbd->bytesize = 0; |
@@ -805,6 +821,9 @@ static int __init nbd_init(void) | |||
805 | * Tell the block layer that we are not a rotational device | 821 | * Tell the block layer that we are not a rotational device |
806 | */ | 822 | */ |
807 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue); | 823 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, disk->queue); |
824 | disk->queue->limits.discard_granularity = 512; | ||
825 | disk->queue->limits.max_discard_sectors = UINT_MAX; | ||
826 | disk->queue->limits.discard_zeroes_data = 0; | ||
808 | } | 827 | } |
809 | 828 | ||
810 | if (register_blkdev(NBD_MAJOR, "nbd")) { | 829 | if (register_blkdev(NBD_MAJOR, "nbd")) { |
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 47ff7e470d87..0c7d340b9ab9 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c | |||
@@ -799,7 +799,7 @@ static int mbcs_remove(struct cx_dev *dev) | |||
799 | return 0; | 799 | return 0; |
800 | } | 800 | } |
801 | 801 | ||
802 | static const struct cx_device_id __devinitdata mbcs_id_table[] = { | 802 | static const struct cx_device_id __devinitconst mbcs_id_table[] = { |
803 | { | 803 | { |
804 | .part_num = MBCS_PART_NUM, | 804 | .part_num = MBCS_PART_NUM, |
805 | .mfg_num = MBCS_MFG_NUM, | 805 | .mfg_num = MBCS_MFG_NUM, |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 3491654cdf7b..a815d44c70a4 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -582,7 +582,7 @@ void dmaengine_get(void) | |||
582 | list_del_rcu(&device->global_node); | 582 | list_del_rcu(&device->global_node); |
583 | break; | 583 | break; |
584 | } else if (err) | 584 | } else if (err) |
585 | pr_err("%s: failed to get %s: (%d)\n", | 585 | pr_debug("%s: failed to get %s: (%d)\n", |
586 | __func__, dma_chan_name(chan), err); | 586 | __func__, dma_chan_name(chan), err); |
587 | } | 587 | } |
588 | } | 588 | } |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 2091ae8f539a..2421d95130d4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -982,7 +982,7 @@ int i2c_add_numbered_adapter(struct i2c_adapter *adap) | |||
982 | 982 | ||
983 | if (adap->nr == -1) /* -1 means dynamically assign bus id */ | 983 | if (adap->nr == -1) /* -1 means dynamically assign bus id */ |
984 | return i2c_add_adapter(adap); | 984 | return i2c_add_adapter(adap); |
985 | if (adap->nr & ~MAX_ID_MASK) | 985 | if (adap->nr & ~MAX_IDR_MASK) |
986 | return -EINVAL; | 986 | return -EINVAL; |
987 | 987 | ||
988 | retry: | 988 | retry: |
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index 57d00caefc86..01451940393b 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c | |||
@@ -181,7 +181,7 @@ static const struct ide_port_ops atp86x_port_ops = { | |||
181 | .cable_detect = atp86x_cable_detect, | 181 | .cable_detect = atp86x_cable_detect, |
182 | }; | 182 | }; |
183 | 183 | ||
184 | static const struct ide_port_info aec62xx_chipsets[] __devinitdata = { | 184 | static const struct ide_port_info aec62xx_chipsets[] __devinitconst = { |
185 | { /* 0: AEC6210 */ | 185 | { /* 0: AEC6210 */ |
186 | .name = DRV_NAME, | 186 | .name = DRV_NAME, |
187 | .init_chipset = init_chipset_aec62xx, | 187 | .init_chipset = init_chipset_aec62xx, |
diff --git a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c index d3be99fb4154..8f3570ee64c3 100644 --- a/drivers/ide/ali14xx.c +++ b/drivers/ide/ali14xx.c | |||
@@ -52,13 +52,13 @@ | |||
52 | 52 | ||
53 | /* port addresses for auto-detection */ | 53 | /* port addresses for auto-detection */ |
54 | #define ALI_NUM_PORTS 4 | 54 | #define ALI_NUM_PORTS 4 |
55 | static const int ports[ALI_NUM_PORTS] __initdata = | 55 | static const int ports[ALI_NUM_PORTS] __initconst = |
56 | { 0x074, 0x0f4, 0x034, 0x0e4 }; | 56 | { 0x074, 0x0f4, 0x034, 0x0e4 }; |
57 | 57 | ||
58 | /* register initialization data */ | 58 | /* register initialization data */ |
59 | typedef struct { u8 reg, data; } RegInitializer; | 59 | typedef struct { u8 reg, data; } RegInitializer; |
60 | 60 | ||
61 | static const RegInitializer initData[] __initdata = { | 61 | static const RegInitializer initData[] __initconst = { |
62 | {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, | 62 | {0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00}, |
63 | {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, | 63 | {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x2b}, {0x0a, 0x0f}, |
64 | {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, | 64 | {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00}, {0x28, 0x00}, |
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 2c8016ad0e26..911a27ca356b 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c | |||
@@ -512,7 +512,7 @@ static const struct ide_dma_ops ali_dma_ops = { | |||
512 | .dma_sff_read_status = ide_dma_sff_read_status, | 512 | .dma_sff_read_status = ide_dma_sff_read_status, |
513 | }; | 513 | }; |
514 | 514 | ||
515 | static const struct ide_port_info ali15x3_chipset __devinitdata = { | 515 | static const struct ide_port_info ali15x3_chipset __devinitconst = { |
516 | .name = DRV_NAME, | 516 | .name = DRV_NAME, |
517 | .init_chipset = init_chipset_ali15x3, | 517 | .init_chipset = init_chipset_ali15x3, |
518 | .init_hwif = init_hwif_ali15x3, | 518 | .init_hwif = init_hwif_ali15x3, |
diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 3747b2561f09..56fc99557ba2 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c | |||
@@ -223,7 +223,7 @@ static const struct ide_port_ops amd_port_ops = { | |||
223 | .udma_mask = udma, \ | 223 | .udma_mask = udma, \ |
224 | } | 224 | } |
225 | 225 | ||
226 | static const struct ide_port_info amd74xx_chipsets[] __devinitdata = { | 226 | static const struct ide_port_info amd74xx_chipsets[] __devinitconst = { |
227 | /* 0: AMD7401 */ DECLARE_AMD_DEV(0x00, ATA_UDMA2), | 227 | /* 0: AMD7401 */ DECLARE_AMD_DEV(0x00, ATA_UDMA2), |
228 | /* 1: AMD7409 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4), | 228 | /* 1: AMD7409 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA4), |
229 | /* 2: AMD7411/7441 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5), | 229 | /* 2: AMD7411/7441 */ DECLARE_AMD_DEV(ATA_SWDMA2, ATA_UDMA5), |
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c index 15f0ead89f5c..cb43480b1bd5 100644 --- a/drivers/ide/atiixp.c +++ b/drivers/ide/atiixp.c | |||
@@ -139,7 +139,7 @@ static const struct ide_port_ops atiixp_port_ops = { | |||
139 | .cable_detect = atiixp_cable_detect, | 139 | .cable_detect = atiixp_cable_detect, |
140 | }; | 140 | }; |
141 | 141 | ||
142 | static const struct ide_port_info atiixp_pci_info[] __devinitdata = { | 142 | static const struct ide_port_info atiixp_pci_info[] __devinitconst = { |
143 | { /* 0: IXP200/300/400/700 */ | 143 | { /* 0: IXP200/300/400/700 */ |
144 | .name = DRV_NAME, | 144 | .name = DRV_NAME, |
145 | .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, | 145 | .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, |
diff --git a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c index 14717304b388..70f0a2754c13 100644 --- a/drivers/ide/cmd640.c +++ b/drivers/ide/cmd640.c | |||
@@ -685,7 +685,7 @@ static int pci_conf2(void) | |||
685 | return 0; | 685 | return 0; |
686 | } | 686 | } |
687 | 687 | ||
688 | static const struct ide_port_info cmd640_port_info __initdata = { | 688 | static const struct ide_port_info cmd640_port_info __initconst = { |
689 | .chipset = ide_cmd640, | 689 | .chipset = ide_cmd640, |
690 | .host_flags = IDE_HFLAG_SERIALIZE | | 690 | .host_flags = IDE_HFLAG_SERIALIZE | |
691 | IDE_HFLAG_NO_DMA | | 691 | IDE_HFLAG_NO_DMA | |
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 5f80312e636b..d1fc43802f5d 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c | |||
@@ -327,7 +327,7 @@ static const struct ide_dma_ops cmd646_rev1_dma_ops = { | |||
327 | .dma_sff_read_status = ide_dma_sff_read_status, | 327 | .dma_sff_read_status = ide_dma_sff_read_status, |
328 | }; | 328 | }; |
329 | 329 | ||
330 | static const struct ide_port_info cmd64x_chipsets[] __devinitdata = { | 330 | static const struct ide_port_info cmd64x_chipsets[] __devinitconst = { |
331 | { /* 0: CMD643 */ | 331 | { /* 0: CMD643 */ |
332 | .name = DRV_NAME, | 332 | .name = DRV_NAME, |
333 | .init_chipset = init_chipset_cmd64x, | 333 | .init_chipset = init_chipset_cmd64x, |
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index 2c1e5f7cd261..14447621e60b 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c | |||
@@ -94,7 +94,7 @@ static const struct ide_port_ops cs5520_port_ops = { | |||
94 | .set_dma_mode = cs5520_set_dma_mode, | 94 | .set_dma_mode = cs5520_set_dma_mode, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | static const struct ide_port_info cyrix_chipset __devinitdata = { | 97 | static const struct ide_port_info cyrix_chipset __devinitconst = { |
98 | .name = DRV_NAME, | 98 | .name = DRV_NAME, |
99 | .enablebits = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } }, | 99 | .enablebits = { { 0x60, 0x01, 0x01 }, { 0x60, 0x02, 0x02 } }, |
100 | .port_ops = &cs5520_port_ops, | 100 | .port_ops = &cs5520_port_ops, |
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index 4dc4eb92b076..49b40ad59d1a 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c | |||
@@ -245,7 +245,7 @@ static const struct ide_port_ops cs5530_port_ops = { | |||
245 | .udma_filter = cs5530_udma_filter, | 245 | .udma_filter = cs5530_udma_filter, |
246 | }; | 246 | }; |
247 | 247 | ||
248 | static const struct ide_port_info cs5530_chipset __devinitdata = { | 248 | static const struct ide_port_info cs5530_chipset __devinitconst = { |
249 | .name = DRV_NAME, | 249 | .name = DRV_NAME, |
250 | .init_chipset = init_chipset_cs5530, | 250 | .init_chipset = init_chipset_cs5530, |
251 | .init_hwif = init_hwif_cs5530, | 251 | .init_hwif = init_hwif_cs5530, |
diff --git a/drivers/ide/cs5535.c b/drivers/ide/cs5535.c index 5059fafadf29..18d4c852602b 100644 --- a/drivers/ide/cs5535.c +++ b/drivers/ide/cs5535.c | |||
@@ -170,7 +170,7 @@ static const struct ide_port_ops cs5535_port_ops = { | |||
170 | .cable_detect = cs5535_cable_detect, | 170 | .cable_detect = cs5535_cable_detect, |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static const struct ide_port_info cs5535_chipset __devinitdata = { | 173 | static const struct ide_port_info cs5535_chipset __devinitconst = { |
174 | .name = DRV_NAME, | 174 | .name = DRV_NAME, |
175 | .port_ops = &cs5535_port_ops, | 175 | .port_ops = &cs5535_port_ops, |
176 | .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE, | 176 | .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE, |
diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 847553fd8b96..3ffb49dab574 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c | |||
@@ -163,7 +163,7 @@ static const struct ide_port_ops cy82c693_port_ops = { | |||
163 | .set_dma_mode = cy82c693_set_dma_mode, | 163 | .set_dma_mode = cy82c693_set_dma_mode, |
164 | }; | 164 | }; |
165 | 165 | ||
166 | static const struct ide_port_info cy82c693_chipset __devinitdata = { | 166 | static const struct ide_port_info cy82c693_chipset __devinitconst = { |
167 | .name = DRV_NAME, | 167 | .name = DRV_NAME, |
168 | .init_iops = init_iops_cy82c693, | 168 | .init_iops = init_iops_cy82c693, |
169 | .port_ops = &cy82c693_port_ops, | 169 | .port_ops = &cy82c693_port_ops, |
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c index 46af4743b3e6..8722df329cbe 100644 --- a/drivers/ide/dtc2278.c +++ b/drivers/ide/dtc2278.c | |||
@@ -91,7 +91,7 @@ static const struct ide_port_ops dtc2278_port_ops = { | |||
91 | .set_pio_mode = dtc2278_set_pio_mode, | 91 | .set_pio_mode = dtc2278_set_pio_mode, |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static const struct ide_port_info dtc2278_port_info __initdata = { | 94 | static const struct ide_port_info dtc2278_port_info __initconst = { |
95 | .name = DRV_NAME, | 95 | .name = DRV_NAME, |
96 | .chipset = ide_dtc2278, | 96 | .chipset = ide_dtc2278, |
97 | .port_ops = &dtc2278_port_ops, | 97 | .port_ops = &dtc2278_port_ops, |
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 58c51cddc100..4aec3b87ff91 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c | |||
@@ -443,7 +443,7 @@ static struct hpt_timings hpt37x_timings = { | |||
443 | } | 443 | } |
444 | }; | 444 | }; |
445 | 445 | ||
446 | static const struct hpt_info hpt36x __devinitdata = { | 446 | static const struct hpt_info hpt36x __devinitconst = { |
447 | .chip_name = "HPT36x", | 447 | .chip_name = "HPT36x", |
448 | .chip_type = HPT36x, | 448 | .chip_type = HPT36x, |
449 | .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2, | 449 | .udma_mask = HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2, |
@@ -451,7 +451,7 @@ static const struct hpt_info hpt36x __devinitdata = { | |||
451 | .timings = &hpt36x_timings | 451 | .timings = &hpt36x_timings |
452 | }; | 452 | }; |
453 | 453 | ||
454 | static const struct hpt_info hpt370 __devinitdata = { | 454 | static const struct hpt_info hpt370 __devinitconst = { |
455 | .chip_name = "HPT370", | 455 | .chip_name = "HPT370", |
456 | .chip_type = HPT370, | 456 | .chip_type = HPT370, |
457 | .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, | 457 | .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, |
@@ -459,7 +459,7 @@ static const struct hpt_info hpt370 __devinitdata = { | |||
459 | .timings = &hpt37x_timings | 459 | .timings = &hpt37x_timings |
460 | }; | 460 | }; |
461 | 461 | ||
462 | static const struct hpt_info hpt370a __devinitdata = { | 462 | static const struct hpt_info hpt370a __devinitconst = { |
463 | .chip_name = "HPT370A", | 463 | .chip_name = "HPT370A", |
464 | .chip_type = HPT370A, | 464 | .chip_type = HPT370A, |
465 | .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, | 465 | .udma_mask = HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4, |
@@ -467,7 +467,7 @@ static const struct hpt_info hpt370a __devinitdata = { | |||
467 | .timings = &hpt37x_timings | 467 | .timings = &hpt37x_timings |
468 | }; | 468 | }; |
469 | 469 | ||
470 | static const struct hpt_info hpt374 __devinitdata = { | 470 | static const struct hpt_info hpt374 __devinitconst = { |
471 | .chip_name = "HPT374", | 471 | .chip_name = "HPT374", |
472 | .chip_type = HPT374, | 472 | .chip_type = HPT374, |
473 | .udma_mask = ATA_UDMA5, | 473 | .udma_mask = ATA_UDMA5, |
@@ -475,7 +475,7 @@ static const struct hpt_info hpt374 __devinitdata = { | |||
475 | .timings = &hpt37x_timings | 475 | .timings = &hpt37x_timings |
476 | }; | 476 | }; |
477 | 477 | ||
478 | static const struct hpt_info hpt372 __devinitdata = { | 478 | static const struct hpt_info hpt372 __devinitconst = { |
479 | .chip_name = "HPT372", | 479 | .chip_name = "HPT372", |
480 | .chip_type = HPT372, | 480 | .chip_type = HPT372, |
481 | .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, | 481 | .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, |
@@ -483,7 +483,7 @@ static const struct hpt_info hpt372 __devinitdata = { | |||
483 | .timings = &hpt37x_timings | 483 | .timings = &hpt37x_timings |
484 | }; | 484 | }; |
485 | 485 | ||
486 | static const struct hpt_info hpt372a __devinitdata = { | 486 | static const struct hpt_info hpt372a __devinitconst = { |
487 | .chip_name = "HPT372A", | 487 | .chip_name = "HPT372A", |
488 | .chip_type = HPT372A, | 488 | .chip_type = HPT372A, |
489 | .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, | 489 | .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, |
@@ -491,7 +491,7 @@ static const struct hpt_info hpt372a __devinitdata = { | |||
491 | .timings = &hpt37x_timings | 491 | .timings = &hpt37x_timings |
492 | }; | 492 | }; |
493 | 493 | ||
494 | static const struct hpt_info hpt302 __devinitdata = { | 494 | static const struct hpt_info hpt302 __devinitconst = { |
495 | .chip_name = "HPT302", | 495 | .chip_name = "HPT302", |
496 | .chip_type = HPT302, | 496 | .chip_type = HPT302, |
497 | .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, | 497 | .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, |
@@ -499,7 +499,7 @@ static const struct hpt_info hpt302 __devinitdata = { | |||
499 | .timings = &hpt37x_timings | 499 | .timings = &hpt37x_timings |
500 | }; | 500 | }; |
501 | 501 | ||
502 | static const struct hpt_info hpt371 __devinitdata = { | 502 | static const struct hpt_info hpt371 __devinitconst = { |
503 | .chip_name = "HPT371", | 503 | .chip_name = "HPT371", |
504 | .chip_type = HPT371, | 504 | .chip_type = HPT371, |
505 | .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, | 505 | .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, |
@@ -507,7 +507,7 @@ static const struct hpt_info hpt371 __devinitdata = { | |||
507 | .timings = &hpt37x_timings | 507 | .timings = &hpt37x_timings |
508 | }; | 508 | }; |
509 | 509 | ||
510 | static const struct hpt_info hpt372n __devinitdata = { | 510 | static const struct hpt_info hpt372n __devinitconst = { |
511 | .chip_name = "HPT372N", | 511 | .chip_name = "HPT372N", |
512 | .chip_type = HPT372N, | 512 | .chip_type = HPT372N, |
513 | .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, | 513 | .udma_mask = HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, |
@@ -515,7 +515,7 @@ static const struct hpt_info hpt372n __devinitdata = { | |||
515 | .timings = &hpt37x_timings | 515 | .timings = &hpt37x_timings |
516 | }; | 516 | }; |
517 | 517 | ||
518 | static const struct hpt_info hpt302n __devinitdata = { | 518 | static const struct hpt_info hpt302n __devinitconst = { |
519 | .chip_name = "HPT302N", | 519 | .chip_name = "HPT302N", |
520 | .chip_type = HPT302N, | 520 | .chip_type = HPT302N, |
521 | .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, | 521 | .udma_mask = HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, |
@@ -523,7 +523,7 @@ static const struct hpt_info hpt302n __devinitdata = { | |||
523 | .timings = &hpt37x_timings | 523 | .timings = &hpt37x_timings |
524 | }; | 524 | }; |
525 | 525 | ||
526 | static const struct hpt_info hpt371n __devinitdata = { | 526 | static const struct hpt_info hpt371n __devinitconst = { |
527 | .chip_name = "HPT371N", | 527 | .chip_name = "HPT371N", |
528 | .chip_type = HPT371N, | 528 | .chip_type = HPT371N, |
529 | .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, | 529 | .udma_mask = HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5, |
@@ -1361,7 +1361,7 @@ static const struct ide_dma_ops hpt36x_dma_ops = { | |||
1361 | .dma_sff_read_status = ide_dma_sff_read_status, | 1361 | .dma_sff_read_status = ide_dma_sff_read_status, |
1362 | }; | 1362 | }; |
1363 | 1363 | ||
1364 | static const struct ide_port_info hpt366_chipsets[] __devinitdata = { | 1364 | static const struct ide_port_info hpt366_chipsets[] __devinitconst = { |
1365 | { /* 0: HPT36x */ | 1365 | { /* 0: HPT36x */ |
1366 | .name = DRV_NAME, | 1366 | .name = DRV_NAME, |
1367 | .init_chipset = init_chipset_hpt366, | 1367 | .init_chipset = init_chipset_hpt366, |
diff --git a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c index 986f2513eab4..1e0fd3aa962d 100644 --- a/drivers/ide/ht6560b.c +++ b/drivers/ide/ht6560b.c | |||
@@ -341,7 +341,7 @@ static const struct ide_port_ops ht6560b_port_ops = { | |||
341 | .set_pio_mode = ht6560b_set_pio_mode, | 341 | .set_pio_mode = ht6560b_set_pio_mode, |
342 | }; | 342 | }; |
343 | 343 | ||
344 | static const struct ide_port_info ht6560b_port_info __initdata = { | 344 | static const struct ide_port_info ht6560b_port_info __initconst = { |
345 | .name = DRV_NAME, | 345 | .name = DRV_NAME, |
346 | .chipset = ide_ht6560b, | 346 | .chipset = ide_ht6560b, |
347 | .tp_ops = &ht6560b_tp_ops, | 347 | .tp_ops = &ht6560b_tp_ops, |
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index bcb507b0cfd4..e640d0ac3af6 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c | |||
@@ -451,7 +451,7 @@ err_free: | |||
451 | return ret; | 451 | return ret; |
452 | } | 452 | } |
453 | 453 | ||
454 | static const struct ide_port_info icside_v6_port_info __initdata = { | 454 | static const struct ide_port_info icside_v6_port_info __initconst = { |
455 | .init_dma = icside_dma_off_init, | 455 | .init_dma = icside_dma_off_init, |
456 | .port_ops = &icside_v6_no_dma_port_ops, | 456 | .port_ops = &icside_v6_no_dma_port_ops, |
457 | .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, | 457 | .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, |
diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c index 7f56b738d762..dab5b670bfbf 100644 --- a/drivers/ide/ide-pci-generic.c +++ b/drivers/ide/ide-pci-generic.c | |||
@@ -53,7 +53,7 @@ static const struct ide_port_ops netcell_port_ops = { | |||
53 | .udma_mask = ATA_UDMA6, \ | 53 | .udma_mask = ATA_UDMA6, \ |
54 | } | 54 | } |
55 | 55 | ||
56 | static const struct ide_port_info generic_chipsets[] __devinitdata = { | 56 | static const struct ide_port_info generic_chipsets[] __devinitconst = { |
57 | /* 0: Unknown */ | 57 | /* 0: Unknown */ |
58 | DECLARE_GENERIC_PCI_DEV(0), | 58 | DECLARE_GENERIC_PCI_DEV(0), |
59 | 59 | ||
diff --git a/drivers/ide/it8172.c b/drivers/ide/it8172.c index 560e66d07659..d5dd180c4b85 100644 --- a/drivers/ide/it8172.c +++ b/drivers/ide/it8172.c | |||
@@ -115,7 +115,7 @@ static const struct ide_port_ops it8172_port_ops = { | |||
115 | .set_dma_mode = it8172_set_dma_mode, | 115 | .set_dma_mode = it8172_set_dma_mode, |
116 | }; | 116 | }; |
117 | 117 | ||
118 | static const struct ide_port_info it8172_port_info __devinitdata = { | 118 | static const struct ide_port_info it8172_port_info __devinitconst = { |
119 | .name = DRV_NAME, | 119 | .name = DRV_NAME, |
120 | .port_ops = &it8172_port_ops, | 120 | .port_ops = &it8172_port_ops, |
121 | .enablebits = { {0x41, 0x80, 0x80}, {0x00, 0x00, 0x00} }, | 121 | .enablebits = { {0x41, 0x80, 0x80}, {0x00, 0x00, 0x00} }, |
diff --git a/drivers/ide/it8213.c b/drivers/ide/it8213.c index 46816ba26416..1847aeb5450a 100644 --- a/drivers/ide/it8213.c +++ b/drivers/ide/it8213.c | |||
@@ -156,7 +156,7 @@ static const struct ide_port_ops it8213_port_ops = { | |||
156 | .cable_detect = it8213_cable_detect, | 156 | .cable_detect = it8213_cable_detect, |
157 | }; | 157 | }; |
158 | 158 | ||
159 | static const struct ide_port_info it8213_chipset __devinitdata = { | 159 | static const struct ide_port_info it8213_chipset __devinitconst = { |
160 | .name = DRV_NAME, | 160 | .name = DRV_NAME, |
161 | .enablebits = { {0x41, 0x80, 0x80} }, | 161 | .enablebits = { {0x41, 0x80, 0x80} }, |
162 | .port_ops = &it8213_port_ops, | 162 | .port_ops = &it8213_port_ops, |
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index 2e3169f2acda..c5611dbca342 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c | |||
@@ -630,7 +630,7 @@ static const struct ide_port_ops it821x_port_ops = { | |||
630 | .cable_detect = it821x_cable_detect, | 630 | .cable_detect = it821x_cable_detect, |
631 | }; | 631 | }; |
632 | 632 | ||
633 | static const struct ide_port_info it821x_chipset __devinitdata = { | 633 | static const struct ide_port_info it821x_chipset __devinitconst = { |
634 | .name = DRV_NAME, | 634 | .name = DRV_NAME, |
635 | .init_chipset = init_chipset_it821x, | 635 | .init_chipset = init_chipset_it821x, |
636 | .init_hwif = init_hwif_it821x, | 636 | .init_hwif = init_hwif_it821x, |
diff --git a/drivers/ide/jmicron.c b/drivers/ide/jmicron.c index 74c2c4a6d909..efddd7d9f92d 100644 --- a/drivers/ide/jmicron.c +++ b/drivers/ide/jmicron.c | |||
@@ -102,7 +102,7 @@ static const struct ide_port_ops jmicron_port_ops = { | |||
102 | .cable_detect = jmicron_cable_detect, | 102 | .cable_detect = jmicron_cable_detect, |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static const struct ide_port_info jmicron_chipset __devinitdata = { | 105 | static const struct ide_port_info jmicron_chipset __devinitconst = { |
106 | .name = DRV_NAME, | 106 | .name = DRV_NAME, |
107 | .enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } }, | 107 | .enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } }, |
108 | .port_ops = &jmicron_port_ops, | 108 | .port_ops = &jmicron_port_ops, |
diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 95327a2c2422..73f78d872d55 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c | |||
@@ -293,7 +293,7 @@ static const struct ide_dma_ops ns87415_dma_ops = { | |||
293 | .dma_sff_read_status = superio_dma_sff_read_status, | 293 | .dma_sff_read_status = superio_dma_sff_read_status, |
294 | }; | 294 | }; |
295 | 295 | ||
296 | static const struct ide_port_info ns87415_chipset __devinitdata = { | 296 | static const struct ide_port_info ns87415_chipset __devinitconst = { |
297 | .name = DRV_NAME, | 297 | .name = DRV_NAME, |
298 | .init_hwif = init_hwif_ns87415, | 298 | .init_hwif = init_hwif_ns87415, |
299 | .tp_ops = &ns87415_tp_ops, | 299 | .tp_ops = &ns87415_tp_ops, |
diff --git a/drivers/ide/opti621.c b/drivers/ide/opti621.c index 1a53a4c375ed..39edc66cb96c 100644 --- a/drivers/ide/opti621.c +++ b/drivers/ide/opti621.c | |||
@@ -131,7 +131,7 @@ static const struct ide_port_ops opti621_port_ops = { | |||
131 | .set_pio_mode = opti621_set_pio_mode, | 131 | .set_pio_mode = opti621_set_pio_mode, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static const struct ide_port_info opti621_chipset __devinitdata = { | 134 | static const struct ide_port_info opti621_chipset __devinitconst = { |
135 | .name = DRV_NAME, | 135 | .name = DRV_NAME, |
136 | .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, | 136 | .enablebits = { {0x45, 0x80, 0x00}, {0x40, 0x08, 0x00} }, |
137 | .port_ops = &opti621_port_ops, | 137 | .port_ops = &opti621_port_ops, |
diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c index 9546fe2a93f7..2e5ceb62fb3b 100644 --- a/drivers/ide/pdc202xx_new.c +++ b/drivers/ide/pdc202xx_new.c | |||
@@ -465,7 +465,7 @@ static const struct ide_port_ops pdcnew_port_ops = { | |||
465 | .udma_mask = udma, \ | 465 | .udma_mask = udma, \ |
466 | } | 466 | } |
467 | 467 | ||
468 | static const struct ide_port_info pdcnew_chipsets[] __devinitdata = { | 468 | static const struct ide_port_info pdcnew_chipsets[] __devinitconst = { |
469 | /* 0: PDC202{68,70} */ DECLARE_PDCNEW_DEV(ATA_UDMA5), | 469 | /* 0: PDC202{68,70} */ DECLARE_PDCNEW_DEV(ATA_UDMA5), |
470 | /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6), | 470 | /* 1: PDC202{69,71,75,76,77} */ DECLARE_PDCNEW_DEV(ATA_UDMA6), |
471 | }; | 471 | }; |
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index 3a35ec6193d2..563451096812 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c | |||
@@ -270,7 +270,7 @@ static const struct ide_dma_ops pdc2026x_dma_ops = { | |||
270 | .max_sectors = sectors, \ | 270 | .max_sectors = sectors, \ |
271 | } | 271 | } |
272 | 272 | ||
273 | static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = { | 273 | static const struct ide_port_info pdc202xx_chipsets[] __devinitconst = { |
274 | { /* 0: PDC20246 */ | 274 | { /* 0: PDC20246 */ |
275 | .name = DRV_NAME, | 275 | .name = DRV_NAME, |
276 | .init_chipset = init_chipset_pdc202xx, | 276 | .init_chipset = init_chipset_pdc202xx, |
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index 1892e81fb00f..fe0fd60cfc09 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c | |||
@@ -344,7 +344,7 @@ static const struct ide_port_ops ich_port_ops = { | |||
344 | .udma_mask = udma, \ | 344 | .udma_mask = udma, \ |
345 | } | 345 | } |
346 | 346 | ||
347 | static const struct ide_port_info piix_pci_info[] __devinitdata = { | 347 | static const struct ide_port_info piix_pci_info[] __devinitconst = { |
348 | /* 0: MPIIX */ | 348 | /* 0: MPIIX */ |
349 | { /* | 349 | { /* |
350 | * MPIIX actually has only a single IDE channel mapped to | 350 | * MPIIX actually has only a single IDE channel mapped to |
diff --git a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c index e03f4f19c1d6..a6fb6a894c7b 100644 --- a/drivers/ide/qd65xx.c +++ b/drivers/ide/qd65xx.c | |||
@@ -335,7 +335,7 @@ static const struct ide_port_ops qd6580_port_ops = { | |||
335 | .set_pio_mode = qd6580_set_pio_mode, | 335 | .set_pio_mode = qd6580_set_pio_mode, |
336 | }; | 336 | }; |
337 | 337 | ||
338 | static const struct ide_port_info qd65xx_port_info __initdata = { | 338 | static const struct ide_port_info qd65xx_port_info __initconst = { |
339 | .name = DRV_NAME, | 339 | .name = DRV_NAME, |
340 | .tp_ops = &qd65xx_tp_ops, | 340 | .tp_ops = &qd65xx_tp_ops, |
341 | .chipset = ide_qd65xx, | 341 | .chipset = ide_qd65xx, |
diff --git a/drivers/ide/rz1000.c b/drivers/ide/rz1000.c index a6414a884eb1..c04173e9fc38 100644 --- a/drivers/ide/rz1000.c +++ b/drivers/ide/rz1000.c | |||
@@ -38,7 +38,7 @@ static int __devinit rz1000_disable_readahead(struct pci_dev *dev) | |||
38 | } | 38 | } |
39 | } | 39 | } |
40 | 40 | ||
41 | static const struct ide_port_info rz1000_chipset __devinitdata = { | 41 | static const struct ide_port_info rz1000_chipset __devinitconst = { |
42 | .name = DRV_NAME, | 42 | .name = DRV_NAME, |
43 | .host_flags = IDE_HFLAG_NO_DMA, | 43 | .host_flags = IDE_HFLAG_NO_DMA, |
44 | }; | 44 | }; |
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c index 356b9b504ffd..d4758ebe77da 100644 --- a/drivers/ide/sc1200.c +++ b/drivers/ide/sc1200.c | |||
@@ -291,7 +291,7 @@ static const struct ide_dma_ops sc1200_dma_ops = { | |||
291 | .dma_sff_read_status = ide_dma_sff_read_status, | 291 | .dma_sff_read_status = ide_dma_sff_read_status, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static const struct ide_port_info sc1200_chipset __devinitdata = { | 294 | static const struct ide_port_info sc1200_chipset __devinitconst = { |
295 | .name = DRV_NAME, | 295 | .name = DRV_NAME, |
296 | .port_ops = &sc1200_port_ops, | 296 | .port_ops = &sc1200_port_ops, |
297 | .dma_ops = &sc1200_dma_ops, | 297 | .dma_ops = &sc1200_dma_ops, |
diff --git a/drivers/ide/scc_pata.c b/drivers/ide/scc_pata.c index b7f5b0c4310c..970103810021 100644 --- a/drivers/ide/scc_pata.c +++ b/drivers/ide/scc_pata.c | |||
@@ -811,7 +811,7 @@ static const struct ide_dma_ops scc_dma_ops = { | |||
811 | .dma_sff_read_status = scc_dma_sff_read_status, | 811 | .dma_sff_read_status = scc_dma_sff_read_status, |
812 | }; | 812 | }; |
813 | 813 | ||
814 | static const struct ide_port_info scc_chipset __devinitdata = { | 814 | static const struct ide_port_info scc_chipset __devinitconst = { |
815 | .name = "sccIDE", | 815 | .name = "sccIDE", |
816 | .init_iops = init_iops_scc, | 816 | .init_iops = init_iops_scc, |
817 | .init_dma = scc_init_dma, | 817 | .init_dma = scc_init_dma, |
diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index 35fb8dabb55d..24d72ef23df7 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c | |||
@@ -337,7 +337,7 @@ static const struct ide_port_ops svwks_port_ops = { | |||
337 | .cable_detect = svwks_cable_detect, | 337 | .cable_detect = svwks_cable_detect, |
338 | }; | 338 | }; |
339 | 339 | ||
340 | static const struct ide_port_info serverworks_chipsets[] __devinitdata = { | 340 | static const struct ide_port_info serverworks_chipsets[] __devinitconst = { |
341 | { /* 0: OSB4 */ | 341 | { /* 0: OSB4 */ |
342 | .name = DRV_NAME, | 342 | .name = DRV_NAME, |
343 | .init_chipset = init_chipset_svwks, | 343 | .init_chipset = init_chipset_svwks, |
diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c index ddeda444a27a..46f7e30d3790 100644 --- a/drivers/ide/siimage.c +++ b/drivers/ide/siimage.c | |||
@@ -719,7 +719,7 @@ static const struct ide_dma_ops sil_dma_ops = { | |||
719 | .udma_mask = ATA_UDMA6, \ | 719 | .udma_mask = ATA_UDMA6, \ |
720 | } | 720 | } |
721 | 721 | ||
722 | static const struct ide_port_info siimage_chipsets[] __devinitdata = { | 722 | static const struct ide_port_info siimage_chipsets[] __devinitconst = { |
723 | /* 0: SiI680 */ DECLARE_SII_DEV(&sil_pata_port_ops), | 723 | /* 0: SiI680 */ DECLARE_SII_DEV(&sil_pata_port_ops), |
724 | /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops) | 724 | /* 1: SiI3112 */ DECLARE_SII_DEV(&sil_sata_port_ops) |
725 | }; | 725 | }; |
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index 4a0022567758..09e61b4c5e94 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c | |||
@@ -563,7 +563,7 @@ static const struct ide_port_ops sis_ata133_port_ops = { | |||
563 | .cable_detect = sis_cable_detect, | 563 | .cable_detect = sis_cable_detect, |
564 | }; | 564 | }; |
565 | 565 | ||
566 | static const struct ide_port_info sis5513_chipset __devinitdata = { | 566 | static const struct ide_port_info sis5513_chipset __devinitconst = { |
567 | .name = DRV_NAME, | 567 | .name = DRV_NAME, |
568 | .init_chipset = init_chipset_sis5513, | 568 | .init_chipset = init_chipset_sis5513, |
569 | .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, | 569 | .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, |
diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index f21dc2ad7682..d051cd224bdb 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c | |||
@@ -299,7 +299,7 @@ static const struct ide_dma_ops sl82c105_dma_ops = { | |||
299 | .dma_sff_read_status = ide_dma_sff_read_status, | 299 | .dma_sff_read_status = ide_dma_sff_read_status, |
300 | }; | 300 | }; |
301 | 301 | ||
302 | static const struct ide_port_info sl82c105_chipset __devinitdata = { | 302 | static const struct ide_port_info sl82c105_chipset __devinitconst = { |
303 | .name = DRV_NAME, | 303 | .name = DRV_NAME, |
304 | .init_chipset = init_chipset_sl82c105, | 304 | .init_chipset = init_chipset_sl82c105, |
305 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, | 305 | .enablebits = {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, |
diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c index 864ffe0e26d9..863a5e9283ca 100644 --- a/drivers/ide/slc90e66.c +++ b/drivers/ide/slc90e66.c | |||
@@ -132,7 +132,7 @@ static const struct ide_port_ops slc90e66_port_ops = { | |||
132 | .cable_detect = slc90e66_cable_detect, | 132 | .cable_detect = slc90e66_cable_detect, |
133 | }; | 133 | }; |
134 | 134 | ||
135 | static const struct ide_port_info slc90e66_chipset __devinitdata = { | 135 | static const struct ide_port_info slc90e66_chipset __devinitconst = { |
136 | .name = DRV_NAME, | 136 | .name = DRV_NAME, |
137 | .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} }, | 137 | .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} }, |
138 | .port_ops = &slc90e66_port_ops, | 138 | .port_ops = &slc90e66_port_ops, |
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c index 4799d5c384e7..17946785ebf6 100644 --- a/drivers/ide/tc86c001.c +++ b/drivers/ide/tc86c001.c | |||
@@ -192,7 +192,7 @@ static const struct ide_dma_ops tc86c001_dma_ops = { | |||
192 | .dma_sff_read_status = ide_dma_sff_read_status, | 192 | .dma_sff_read_status = ide_dma_sff_read_status, |
193 | }; | 193 | }; |
194 | 194 | ||
195 | static const struct ide_port_info tc86c001_chipset __devinitdata = { | 195 | static const struct ide_port_info tc86c001_chipset __devinitconst = { |
196 | .name = DRV_NAME, | 196 | .name = DRV_NAME, |
197 | .init_hwif = init_hwif_tc86c001, | 197 | .init_hwif = init_hwif_tc86c001, |
198 | .port_ops = &tc86c001_port_ops, | 198 | .port_ops = &tc86c001_port_ops, |
diff --git a/drivers/ide/triflex.c b/drivers/ide/triflex.c index 281c91426345..55ce1b80efcb 100644 --- a/drivers/ide/triflex.c +++ b/drivers/ide/triflex.c | |||
@@ -92,7 +92,7 @@ static const struct ide_port_ops triflex_port_ops = { | |||
92 | .set_dma_mode = triflex_set_mode, | 92 | .set_dma_mode = triflex_set_mode, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | static const struct ide_port_info triflex_device __devinitdata = { | 95 | static const struct ide_port_info triflex_device __devinitconst = { |
96 | .name = DRV_NAME, | 96 | .name = DRV_NAME, |
97 | .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, | 97 | .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, |
98 | .port_ops = &triflex_port_ops, | 98 | .port_ops = &triflex_port_ops, |
diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index 4b42ca091534..e494a98a43a9 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c | |||
@@ -324,7 +324,7 @@ static struct ide_dma_ops trm290_dma_ops = { | |||
324 | .dma_check = trm290_dma_check, | 324 | .dma_check = trm290_dma_check, |
325 | }; | 325 | }; |
326 | 326 | ||
327 | static const struct ide_port_info trm290_chipset __devinitdata = { | 327 | static const struct ide_port_info trm290_chipset __devinitconst = { |
328 | .name = DRV_NAME, | 328 | .name = DRV_NAME, |
329 | .init_hwif = init_hwif_trm290, | 329 | .init_hwif = init_hwif_trm290, |
330 | .tp_ops = &trm290_tp_ops, | 330 | .tp_ops = &trm290_tp_ops, |
diff --git a/drivers/ide/tx4938ide.c b/drivers/ide/tx4938ide.c index 7002765b593c..91d49dd957ef 100644 --- a/drivers/ide/tx4938ide.c +++ b/drivers/ide/tx4938ide.c | |||
@@ -117,7 +117,7 @@ static const struct ide_port_ops tx4938ide_port_ops = { | |||
117 | .set_pio_mode = tx4938ide_set_pio_mode, | 117 | .set_pio_mode = tx4938ide_set_pio_mode, |
118 | }; | 118 | }; |
119 | 119 | ||
120 | static const struct ide_port_info tx4938ide_port_info __initdata = { | 120 | static const struct ide_port_info tx4938ide_port_info __initconst = { |
121 | .port_ops = &tx4938ide_port_ops, | 121 | .port_ops = &tx4938ide_port_ops, |
122 | #ifdef __BIG_ENDIAN | 122 | #ifdef __BIG_ENDIAN |
123 | .tp_ops = &tx4938ide_tp_ops, | 123 | .tp_ops = &tx4938ide_tp_ops, |
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 71c231954972..c0ab800b7bb3 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
@@ -522,7 +522,7 @@ static const struct ide_dma_ops tx4939ide_dma_ops = { | |||
522 | .dma_sff_read_status = tx4939ide_dma_sff_read_status, | 522 | .dma_sff_read_status = tx4939ide_dma_sff_read_status, |
523 | }; | 523 | }; |
524 | 524 | ||
525 | static const struct ide_port_info tx4939ide_port_info __initdata = { | 525 | static const struct ide_port_info tx4939ide_port_info __initconst = { |
526 | .init_hwif = tx4939ide_init_hwif, | 526 | .init_hwif = tx4939ide_init_hwif, |
527 | .init_dma = tx4939ide_init_dma, | 527 | .init_dma = tx4939ide_init_dma, |
528 | .port_ops = &tx4939ide_port_ops, | 528 | .port_ops = &tx4939ide_port_ops, |
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c index 5cfb78120669..3aa0fea0f3d9 100644 --- a/drivers/ide/umc8672.c +++ b/drivers/ide/umc8672.c | |||
@@ -128,7 +128,7 @@ static const struct ide_port_ops umc8672_port_ops = { | |||
128 | .set_pio_mode = umc_set_pio_mode, | 128 | .set_pio_mode = umc_set_pio_mode, |
129 | }; | 129 | }; |
130 | 130 | ||
131 | static const struct ide_port_info umc8672_port_info __initdata = { | 131 | static const struct ide_port_info umc8672_port_info __initconst = { |
132 | .name = DRV_NAME, | 132 | .name = DRV_NAME, |
133 | .chipset = ide_umc8672, | 133 | .chipset = ide_umc8672, |
134 | .port_ops = &umc8672_port_ops, | 134 | .port_ops = &umc8672_port_ops, |
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index f46f49cfcc28..eb7767864d10 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c | |||
@@ -403,7 +403,7 @@ static const struct ide_port_ops via_port_ops = { | |||
403 | .cable_detect = via82cxxx_cable_detect, | 403 | .cable_detect = via82cxxx_cable_detect, |
404 | }; | 404 | }; |
405 | 405 | ||
406 | static const struct ide_port_info via82cxxx_chipset __devinitdata = { | 406 | static const struct ide_port_info via82cxxx_chipset __devinitconst = { |
407 | .name = DRV_NAME, | 407 | .name = DRV_NAME, |
408 | .init_chipset = init_chipset_via82cxxx, | 408 | .init_chipset = init_chipset_via82cxxx, |
409 | .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, | 409 | .enablebits = { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } }, |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index d67999f6e34a..394fea2ba1bc 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -390,7 +390,7 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv) | |||
390 | ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, | 390 | ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, |
391 | next_id, &id); | 391 | next_id, &id); |
392 | if (!ret) | 392 | if (!ret) |
393 | next_id = ((unsigned) id + 1) & MAX_ID_MASK; | 393 | next_id = ((unsigned) id + 1) & MAX_IDR_MASK; |
394 | spin_unlock_irqrestore(&cm.lock, flags); | 394 | spin_unlock_irqrestore(&cm.lock, flags); |
395 | } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); | 395 | } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); |
396 | 396 | ||
diff --git a/drivers/infiniband/hw/mlx4/cm.c b/drivers/infiniband/hw/mlx4/cm.c index e25e4dafb8a8..80079e5a2e30 100644 --- a/drivers/infiniband/hw/mlx4/cm.c +++ b/drivers/infiniband/hw/mlx4/cm.c | |||
@@ -225,7 +225,7 @@ id_map_alloc(struct ib_device *ibdev, int slave_id, u32 sl_cm_id) | |||
225 | ret = idr_get_new_above(&sriov->pv_id_table, ent, | 225 | ret = idr_get_new_above(&sriov->pv_id_table, ent, |
226 | next_id, &id); | 226 | next_id, &id); |
227 | if (!ret) { | 227 | if (!ret) { |
228 | next_id = ((unsigned) id + 1) & MAX_ID_MASK; | 228 | next_id = ((unsigned) id + 1) & MAX_IDR_MASK; |
229 | ent->pv_cm_id = (u32)id; | 229 | ent->pv_cm_id = (u32)id; |
230 | sl_id_map_add(ibdev, ent); | 230 | sl_id_map_add(ibdev, ent); |
231 | } | 231 | } |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 20e5c2cda430..ef87310b7662 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -748,7 +748,7 @@ static void __devexit macio_pci_remove(struct pci_dev* pdev) | |||
748 | * MacIO is matched against any Apple ID, it's probe() function | 748 | * MacIO is matched against any Apple ID, it's probe() function |
749 | * will then decide wether it applies or not | 749 | * will then decide wether it applies or not |
750 | */ | 750 | */ |
751 | static const struct pci_device_id __devinitdata pci_ids [] = { { | 751 | static const struct pci_device_id __devinitconst pci_ids[] = { { |
752 | .vendor = PCI_VENDOR_ID_APPLE, | 752 | .vendor = PCI_VENDOR_ID_APPLE, |
753 | .device = PCI_ANY_ID, | 753 | .device = PCI_ANY_ID, |
754 | .subvendor = PCI_ANY_ID, | 754 | .subvendor = PCI_ANY_ID, |
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 3d6d9beb18d4..8fefc961ec06 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c | |||
@@ -374,21 +374,21 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo) | |||
374 | } | 374 | } |
375 | #endif | 375 | #endif |
376 | 376 | ||
377 | static const __devinitdata struct reg_default wm8994_revc_patch[] = { | 377 | static const __devinitconst struct reg_default wm8994_revc_patch[] = { |
378 | { 0x102, 0x3 }, | 378 | { 0x102, 0x3 }, |
379 | { 0x56, 0x3 }, | 379 | { 0x56, 0x3 }, |
380 | { 0x817, 0x0 }, | 380 | { 0x817, 0x0 }, |
381 | { 0x102, 0x0 }, | 381 | { 0x102, 0x0 }, |
382 | }; | 382 | }; |
383 | 383 | ||
384 | static const __devinitdata struct reg_default wm8958_reva_patch[] = { | 384 | static const __devinitconst struct reg_default wm8958_reva_patch[] = { |
385 | { 0x102, 0x3 }, | 385 | { 0x102, 0x3 }, |
386 | { 0xcb, 0x81 }, | 386 | { 0xcb, 0x81 }, |
387 | { 0x817, 0x0 }, | 387 | { 0x817, 0x0 }, |
388 | { 0x102, 0x0 }, | 388 | { 0x102, 0x0 }, |
389 | }; | 389 | }; |
390 | 390 | ||
391 | static const __devinitdata struct reg_default wm1811_reva_patch[] = { | 391 | static const __devinitconst struct reg_default wm1811_reva_patch[] = { |
392 | { 0x102, 0x3 }, | 392 | { 0x102, 0x3 }, |
393 | { 0x56, 0xc07 }, | 393 | { 0x56, 0xc07 }, |
394 | { 0x5d, 0x7e }, | 394 | { 0x5d, 0x7e }, |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 504da715a41a..9722d43d6140 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -653,7 +653,7 @@ static const struct sdhci_pci_fixes sdhci_via = { | |||
653 | .probe = via_probe, | 653 | .probe = via_probe, |
654 | }; | 654 | }; |
655 | 655 | ||
656 | static const struct pci_device_id pci_ids[] __devinitdata = { | 656 | static const struct pci_device_id pci_ids[] __devinitconst = { |
657 | { | 657 | { |
658 | .vendor = PCI_VENDOR_ID_RICOH, | 658 | .vendor = PCI_VENDOR_ID_RICOH, |
659 | .device = PCI_DEVICE_ID_RICOH_R5C822, | 659 | .device = PCI_DEVICE_ID_RICOH_R5C822, |
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 034c16b60e96..adc3708d8829 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #include <linux/kernel.h> | 56 | #include <linux/kernel.h> |
57 | #include <linux/can.h> | 57 | #include <linux/can.h> |
58 | 58 | ||
59 | static __initdata const char banner[] = | 59 | static __initconst const char banner[] = |
60 | KERN_INFO "slcan: serial line CAN interface driver\n"; | 60 | KERN_INFO "slcan: serial line CAN interface driver\n"; |
61 | 61 | ||
62 | MODULE_ALIAS_LDISC(N_SLCAN); | 62 | MODULE_ALIAS_LDISC(N_SLCAN); |
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 4f93c0be0053..0a2a5ee79a17 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c | |||
@@ -49,7 +49,7 @@ | |||
49 | #include <linux/slab.h> | 49 | #include <linux/slab.h> |
50 | #include <net/rtnetlink.h> | 50 | #include <net/rtnetlink.h> |
51 | 51 | ||
52 | static __initdata const char banner[] = | 52 | static __initconst const char banner[] = |
53 | KERN_INFO "vcan: Virtual CAN interface driver\n"; | 53 | KERN_INFO "vcan: Virtual CAN interface driver\n"; |
54 | 54 | ||
55 | MODULE_DESCRIPTION("virtual CAN interface"); | 55 | MODULE_DESCRIPTION("virtual CAN interface"); |
diff --git a/drivers/net/ethernet/8390/ne3210.c b/drivers/net/ethernet/8390/ne3210.c index a2f8b2b8e27c..e3f57427d5c5 100644 --- a/drivers/net/ethernet/8390/ne3210.c +++ b/drivers/net/ethernet/8390/ne3210.c | |||
@@ -81,7 +81,7 @@ static void ne3210_block_output(struct net_device *dev, int count, const unsigne | |||
81 | 81 | ||
82 | static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3}; | 82 | static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3}; |
83 | static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0}; | 83 | static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0}; |
84 | static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"}; | 84 | static const char * const ifmap[] __initconst = {"UTP", "?", "BNC", "AUI"}; |
85 | static int ifmap_val[] __initdata = { | 85 | static int ifmap_val[] __initdata = { |
86 | IF_PORT_10BASET, | 86 | IF_PORT_10BASET, |
87 | IF_PORT_UNKNOWN, | 87 | IF_PORT_UNKNOWN, |
diff --git a/drivers/net/ethernet/adaptec/starfire.c b/drivers/net/ethernet/adaptec/starfire.c index d920a529ba22..5b65992c2a0a 100644 --- a/drivers/net/ethernet/adaptec/starfire.c +++ b/drivers/net/ethernet/adaptec/starfire.c | |||
@@ -295,7 +295,7 @@ MODULE_DEVICE_TABLE(pci, starfire_pci_tbl); | |||
295 | static const struct chip_info { | 295 | static const struct chip_info { |
296 | const char *name; | 296 | const char *name; |
297 | int drv_flags; | 297 | int drv_flags; |
298 | } netdrv_tbl[] __devinitdata = { | 298 | } netdrv_tbl[] __devinitconst = { |
299 | { "Adaptec Starfire 6915", CanHaveMII }, | 299 | { "Adaptec Starfire 6915", CanHaveMII }, |
300 | }; | 300 | }; |
301 | 301 | ||
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 55a2e3795055..d19f82f7597a 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c | |||
@@ -702,7 +702,7 @@ struct atl1c_platform_patch { | |||
702 | u32 patch_flag; | 702 | u32 patch_flag; |
703 | #define ATL1C_LINK_PATCH 0x1 | 703 | #define ATL1C_LINK_PATCH 0x1 |
704 | }; | 704 | }; |
705 | static const struct atl1c_platform_patch plats[] __devinitdata = { | 705 | static const struct atl1c_platform_patch plats[] __devinitconst = { |
706 | {0x2060, 0xC1, 0x1019, 0x8152, 0x1}, | 706 | {0x2060, 0xC1, 0x1019, 0x8152, 0x1}, |
707 | {0x2060, 0xC1, 0x1019, 0x2060, 0x1}, | 707 | {0x2060, 0xC1, 0x1019, 0x2060, 0x1}, |
708 | {0x2060, 0xC1, 0x1019, 0xE000, 0x1}, | 708 | {0x2060, 0xC1, 0x1019, 0xE000, 0x1}, |
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 57d64b80fd72..623dd8635c46 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c | |||
@@ -2845,7 +2845,7 @@ static void atl2_force_ps(struct atl2_hw *hw) | |||
2845 | */ | 2845 | */ |
2846 | 2846 | ||
2847 | #define ATL2_PARAM(X, desc) \ | 2847 | #define ATL2_PARAM(X, desc) \ |
2848 | static const int __devinitdata X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \ | 2848 | static const int __devinitconst X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \ |
2849 | MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \ | 2849 | MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \ |
2850 | MODULE_PARM_DESC(X, desc); | 2850 | MODULE_PARM_DESC(X, desc); |
2851 | #else | 2851 | #else |
diff --git a/drivers/net/ethernet/dec/tulip/de2104x.c b/drivers/net/ethernet/dec/tulip/de2104x.c index 61cc09342865..77335853ac36 100644 --- a/drivers/net/ethernet/dec/tulip/de2104x.c +++ b/drivers/net/ethernet/dec/tulip/de2104x.c | |||
@@ -661,9 +661,6 @@ static netdev_tx_t de_start_xmit (struct sk_buff *skb, | |||
661 | new frame, not around filling de->setup_frame. This is non-deterministic | 661 | new frame, not around filling de->setup_frame. This is non-deterministic |
662 | when re-entered but still correct. */ | 662 | when re-entered but still correct. */ |
663 | 663 | ||
664 | #undef set_bit_le | ||
665 | #define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) | ||
666 | |||
667 | static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) | 664 | static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) |
668 | { | 665 | { |
669 | struct de_private *de = netdev_priv(dev); | 666 | struct de_private *de = netdev_priv(dev); |
@@ -673,12 +670,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) | |||
673 | u16 *eaddrs; | 670 | u16 *eaddrs; |
674 | 671 | ||
675 | memset(hash_table, 0, sizeof(hash_table)); | 672 | memset(hash_table, 0, sizeof(hash_table)); |
676 | set_bit_le(255, hash_table); /* Broadcast entry */ | 673 | __set_bit_le(255, hash_table); /* Broadcast entry */ |
677 | /* This should work on big-endian machines as well. */ | 674 | /* This should work on big-endian machines as well. */ |
678 | netdev_for_each_mc_addr(ha, dev) { | 675 | netdev_for_each_mc_addr(ha, dev) { |
679 | int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; | 676 | int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; |
680 | 677 | ||
681 | set_bit_le(index, hash_table); | 678 | __set_bit_le(index, hash_table); |
682 | } | 679 | } |
683 | 680 | ||
684 | for (i = 0; i < 32; i++) { | 681 | for (i = 0; i < 32; i++) { |
diff --git a/drivers/net/ethernet/dec/tulip/eeprom.c b/drivers/net/ethernet/dec/tulip/eeprom.c index ed7d1dcd9566..44f7e8e82d85 100644 --- a/drivers/net/ethernet/dec/tulip/eeprom.c +++ b/drivers/net/ethernet/dec/tulip/eeprom.c | |||
@@ -79,7 +79,7 @@ static struct eeprom_fixup eeprom_fixups[] __devinitdata = { | |||
79 | {NULL}}; | 79 | {NULL}}; |
80 | 80 | ||
81 | 81 | ||
82 | static const char *block_name[] __devinitdata = { | 82 | static const char *const block_name[] __devinitconst = { |
83 | "21140 non-MII", | 83 | "21140 non-MII", |
84 | "21140 MII PHY", | 84 | "21140 MII PHY", |
85 | "21142 Serial PHY", | 85 | "21142 Serial PHY", |
diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index c4f37aca2269..885700a19978 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c | |||
@@ -1010,9 +1010,6 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) | |||
1010 | new frame, not around filling tp->setup_frame. This is non-deterministic | 1010 | new frame, not around filling tp->setup_frame. This is non-deterministic |
1011 | when re-entered but still correct. */ | 1011 | when re-entered but still correct. */ |
1012 | 1012 | ||
1013 | #undef set_bit_le | ||
1014 | #define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) | ||
1015 | |||
1016 | static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) | 1013 | static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) |
1017 | { | 1014 | { |
1018 | struct tulip_private *tp = netdev_priv(dev); | 1015 | struct tulip_private *tp = netdev_priv(dev); |
@@ -1022,12 +1019,12 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) | |||
1022 | u16 *eaddrs; | 1019 | u16 *eaddrs; |
1023 | 1020 | ||
1024 | memset(hash_table, 0, sizeof(hash_table)); | 1021 | memset(hash_table, 0, sizeof(hash_table)); |
1025 | set_bit_le(255, hash_table); /* Broadcast entry */ | 1022 | __set_bit_le(255, hash_table); /* Broadcast entry */ |
1026 | /* This should work on big-endian machines as well. */ | 1023 | /* This should work on big-endian machines as well. */ |
1027 | netdev_for_each_mc_addr(ha, dev) { | 1024 | netdev_for_each_mc_addr(ha, dev) { |
1028 | int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; | 1025 | int index = ether_crc_le(ETH_ALEN, ha->addr) & 0x1ff; |
1029 | 1026 | ||
1030 | set_bit_le(index, hash_table); | 1027 | __set_bit_le(index, hash_table); |
1031 | } | 1028 | } |
1032 | for (i = 0; i < 32; i++) { | 1029 | for (i = 0; i < 32; i++) { |
1033 | *setup_frm++ = hash_table[i]; | 1030 | *setup_frm++ = hash_table[i]; |
diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c index 4d1ffca83c82..7c1ec4d7920b 100644 --- a/drivers/net/ethernet/dec/tulip/winbond-840.c +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c | |||
@@ -236,7 +236,7 @@ struct pci_id_info { | |||
236 | int drv_flags; /* Driver use, intended as capability flags. */ | 236 | int drv_flags; /* Driver use, intended as capability flags. */ |
237 | }; | 237 | }; |
238 | 238 | ||
239 | static const struct pci_id_info pci_id_tbl[] __devinitdata = { | 239 | static const struct pci_id_info pci_id_tbl[] __devinitconst = { |
240 | { /* Sometime a Level-One switch card. */ | 240 | { /* Sometime a Level-One switch card. */ |
241 | "Winbond W89c840", CanHaveMII | HasBrokenTx | FDXOnNoMII}, | 241 | "Winbond W89c840", CanHaveMII | HasBrokenTx | FDXOnNoMII}, |
242 | { "Winbond W89c840", CanHaveMII | HasBrokenTx}, | 242 | { "Winbond W89c840", CanHaveMII | HasBrokenTx}, |
diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index d7bb52a7bda1..3b83588e51f6 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c | |||
@@ -218,7 +218,7 @@ enum { | |||
218 | struct pci_id_info { | 218 | struct pci_id_info { |
219 | const char *name; | 219 | const char *name; |
220 | }; | 220 | }; |
221 | static const struct pci_id_info pci_id_tbl[] __devinitdata = { | 221 | static const struct pci_id_info pci_id_tbl[] __devinitconst = { |
222 | {"D-Link DFE-550TX FAST Ethernet Adapter"}, | 222 | {"D-Link DFE-550TX FAST Ethernet Adapter"}, |
223 | {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, | 223 | {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, |
224 | {"D-Link DFE-580TX 4 port Server Adapter"}, | 224 | {"D-Link DFE-580TX 4 port Server Adapter"}, |
diff --git a/drivers/net/ethernet/fealnx.c b/drivers/net/ethernet/fealnx.c index 9d71c9cc300b..0e4a0ac86aa8 100644 --- a/drivers/net/ethernet/fealnx.c +++ b/drivers/net/ethernet/fealnx.c | |||
@@ -150,7 +150,7 @@ struct chip_info { | |||
150 | int flags; | 150 | int flags; |
151 | }; | 151 | }; |
152 | 152 | ||
153 | static const struct chip_info skel_netdrv_tbl[] __devinitdata = { | 153 | static const struct chip_info skel_netdrv_tbl[] __devinitconst = { |
154 | { "100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, | 154 | { "100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, |
155 | { "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR }, | 155 | { "100/10M Ethernet PCI Adapter", HAS_CHIP_XCVR }, |
156 | { "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, | 156 | { "1000/100/10M Ethernet PCI Adapter", HAS_MII_XCVR }, |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index b528e52a8ee1..2a0c9dc48eb3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -38,7 +38,7 @@ static inline void writeq(u64 val, void __iomem *addr) | |||
38 | } | 38 | } |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | static const struct crb_128M_2M_block_map | 41 | static struct crb_128M_2M_block_map |
42 | crb_128M_2M_map[64] __cacheline_aligned_in_smp = { | 42 | crb_128M_2M_map[64] __cacheline_aligned_in_smp = { |
43 | {{{0, 0, 0, 0} } }, /* 0: PCI */ | 43 | {{{0, 0, 0, 0} } }, /* 0: PCI */ |
44 | {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ | 44 | {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ |
diff --git a/drivers/net/ethernet/realtek/8139too.c b/drivers/net/ethernet/realtek/8139too.c index 1d83565cc6af..3ed7add23c12 100644 --- a/drivers/net/ethernet/realtek/8139too.c +++ b/drivers/net/ethernet/realtek/8139too.c | |||
@@ -228,7 +228,7 @@ typedef enum { | |||
228 | static const struct { | 228 | static const struct { |
229 | const char *name; | 229 | const char *name; |
230 | u32 hw_flags; | 230 | u32 hw_flags; |
231 | } board_info[] __devinitdata = { | 231 | } board_info[] __devinitconst = { |
232 | { "RealTek RTL8139", RTL8139_CAPS }, | 232 | { "RealTek RTL8139", RTL8139_CAPS }, |
233 | { "RealTek RTL8129", RTL8129_CAPS }, | 233 | { "RealTek RTL8129", RTL8129_CAPS }, |
234 | }; | 234 | }; |
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 96bd980e828d..4f86d0cd516a 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -2019,14 +2019,14 @@ static void efx_set_rx_mode(struct net_device *net_dev) | |||
2019 | netdev_for_each_mc_addr(ha, net_dev) { | 2019 | netdev_for_each_mc_addr(ha, net_dev) { |
2020 | crc = ether_crc_le(ETH_ALEN, ha->addr); | 2020 | crc = ether_crc_le(ETH_ALEN, ha->addr); |
2021 | bit = crc & (EFX_MCAST_HASH_ENTRIES - 1); | 2021 | bit = crc & (EFX_MCAST_HASH_ENTRIES - 1); |
2022 | set_bit_le(bit, mc_hash->byte); | 2022 | __set_bit_le(bit, mc_hash); |
2023 | } | 2023 | } |
2024 | 2024 | ||
2025 | /* Broadcast packets go through the multicast hash filter. | 2025 | /* Broadcast packets go through the multicast hash filter. |
2026 | * ether_crc_le() of the broadcast address is 0xbe2612ff | 2026 | * ether_crc_le() of the broadcast address is 0xbe2612ff |
2027 | * so we always add bit 0xff to the mask. | 2027 | * so we always add bit 0xff to the mask. |
2028 | */ | 2028 | */ |
2029 | set_bit_le(0xff, mc_hash->byte); | 2029 | __set_bit_le(0xff, mc_hash); |
2030 | } | 2030 | } |
2031 | 2031 | ||
2032 | if (efx->port_enabled) | 2032 | if (efx->port_enabled) |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index c1a010cda89b..576a31091165 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
@@ -1101,18 +1101,6 @@ static inline struct efx_rx_buffer *efx_rx_buffer(struct efx_rx_queue *rx_queue, | |||
1101 | return &rx_queue->buffer[index]; | 1101 | return &rx_queue->buffer[index]; |
1102 | } | 1102 | } |
1103 | 1103 | ||
1104 | /* Set bit in a little-endian bitfield */ | ||
1105 | static inline void set_bit_le(unsigned nr, unsigned char *addr) | ||
1106 | { | ||
1107 | addr[nr / 8] |= (1 << (nr % 8)); | ||
1108 | } | ||
1109 | |||
1110 | /* Clear bit in a little-endian bitfield */ | ||
1111 | static inline void clear_bit_le(unsigned nr, unsigned char *addr) | ||
1112 | { | ||
1113 | addr[nr / 8] &= ~(1 << (nr % 8)); | ||
1114 | } | ||
1115 | |||
1116 | 1104 | ||
1117 | /** | 1105 | /** |
1118 | * EFX_MAX_FRAME_LEN - calculate maximum frame length | 1106 | * EFX_MAX_FRAME_LEN - calculate maximum frame length |
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index cdff40b65729..aab7cacb2e34 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c | |||
@@ -472,9 +472,9 @@ void efx_nic_init_tx(struct efx_tx_queue *tx_queue) | |||
472 | 472 | ||
473 | efx_reado(efx, ®, FR_AA_TX_CHKSM_CFG); | 473 | efx_reado(efx, ®, FR_AA_TX_CHKSM_CFG); |
474 | if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD) | 474 | if (tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD) |
475 | clear_bit_le(tx_queue->queue, (void *)®); | 475 | __clear_bit_le(tx_queue->queue, ®); |
476 | else | 476 | else |
477 | set_bit_le(tx_queue->queue, (void *)®); | 477 | __set_bit_le(tx_queue->queue, ®); |
478 | efx_writeo(efx, ®, FR_AA_TX_CHKSM_CFG); | 478 | efx_writeo(efx, ®, FR_AA_TX_CHKSM_CFG); |
479 | } | 479 | } |
480 | 480 | ||
diff --git a/drivers/net/ethernet/sis/sis190.c b/drivers/net/ethernet/sis/sis190.c index 4613591b43e7..d8166012b7d4 100644 --- a/drivers/net/ethernet/sis/sis190.c +++ b/drivers/net/ethernet/sis/sis190.c | |||
@@ -1618,7 +1618,7 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, | |||
1618 | static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, | 1618 | static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, |
1619 | struct net_device *dev) | 1619 | struct net_device *dev) |
1620 | { | 1620 | { |
1621 | static const u16 __devinitdata ids[] = { 0x0965, 0x0966, 0x0968 }; | 1621 | static const u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 }; |
1622 | struct sis190_private *tp = netdev_priv(dev); | 1622 | struct sis190_private *tp = netdev_priv(dev); |
1623 | struct pci_dev *isa_bridge; | 1623 | struct pci_dev *isa_bridge; |
1624 | u8 reg, tmp8; | 1624 | u8 reg, tmp8; |
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 64783a0d545a..1450e33fc250 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c | |||
@@ -811,9 +811,9 @@ static struct tty_ldisc_ops sp_ldisc = { | |||
811 | 811 | ||
812 | /* Initialize 6pack control device -- register 6pack line discipline */ | 812 | /* Initialize 6pack control device -- register 6pack line discipline */ |
813 | 813 | ||
814 | static const char msg_banner[] __initdata = KERN_INFO \ | 814 | static const char msg_banner[] __initconst = KERN_INFO \ |
815 | "AX.25: 6pack driver, " SIXPACK_VERSION "\n"; | 815 | "AX.25: 6pack driver, " SIXPACK_VERSION "\n"; |
816 | static const char msg_regfail[] __initdata = KERN_ERR \ | 816 | static const char msg_regfail[] __initconst = KERN_ERR \ |
817 | "6pack: can't register line discipline (err = %d)\n"; | 817 | "6pack: can't register line discipline (err = %d)\n"; |
818 | 818 | ||
819 | static int __init sixpack_init_driver(void) | 819 | static int __init sixpack_init_driver(void) |
@@ -829,7 +829,7 @@ static int __init sixpack_init_driver(void) | |||
829 | return status; | 829 | return status; |
830 | } | 830 | } |
831 | 831 | ||
832 | static const char msg_unregfail[] __exitdata = KERN_ERR \ | 832 | static const char msg_unregfail[] = KERN_ERR \ |
833 | "6pack: can't unregister line discipline (err = %d)\n"; | 833 | "6pack: can't unregister line discipline (err = %d)\n"; |
834 | 834 | ||
835 | static void __exit sixpack_exit_driver(void) | 835 | static void __exit sixpack_exit_driver(void) |
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index 76d54774ba82..c2e5497397d5 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c | |||
@@ -87,7 +87,7 @@ | |||
87 | 87 | ||
88 | #include <linux/bpqether.h> | 88 | #include <linux/bpqether.h> |
89 | 89 | ||
90 | static const char banner[] __initdata = KERN_INFO \ | 90 | static const char banner[] __initconst = KERN_INFO \ |
91 | "AX.25: bpqether driver version 004\n"; | 91 | "AX.25: bpqether driver version 004\n"; |
92 | 92 | ||
93 | static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; | 93 | static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; |
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 2c0894a92abd..8e01c457015b 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c | |||
@@ -997,9 +997,9 @@ static struct tty_ldisc_ops ax_ldisc = { | |||
997 | .write_wakeup = mkiss_write_wakeup | 997 | .write_wakeup = mkiss_write_wakeup |
998 | }; | 998 | }; |
999 | 999 | ||
1000 | static const char banner[] __initdata = KERN_INFO \ | 1000 | static const char banner[] __initconst = KERN_INFO \ |
1001 | "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n"; | 1001 | "mkiss: AX.25 Multikiss, Hans Albas PE1AYX\n"; |
1002 | static const char msg_regfail[] __initdata = KERN_ERR \ | 1002 | static const char msg_regfail[] __initconst = KERN_ERR \ |
1003 | "mkiss: can't register line discipline (err = %d)\n"; | 1003 | "mkiss: can't register line discipline (err = %d)\n"; |
1004 | 1004 | ||
1005 | static int __init mkiss_init_driver(void) | 1005 | static int __init mkiss_init_driver(void) |
@@ -1015,7 +1015,7 @@ static int __init mkiss_init_driver(void) | |||
1015 | return status; | 1015 | return status; |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static const char msg_unregfail[] __exitdata = KERN_ERR \ | 1018 | static const char msg_unregfail[] = KERN_ERR \ |
1019 | "mkiss: can't unregister line discipline (err = %d)\n"; | 1019 | "mkiss: can't unregister line discipline (err = %d)\n"; |
1020 | 1020 | ||
1021 | static void __exit mkiss_exit_driver(void) | 1021 | static void __exit mkiss_exit_driver(void) |
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index efc6c97163a7..1b4a47bd32b7 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c | |||
@@ -182,7 +182,7 @@ | |||
182 | 182 | ||
183 | #include "z8530.h" | 183 | #include "z8530.h" |
184 | 184 | ||
185 | static const char banner[] __initdata = KERN_INFO \ | 185 | static const char banner[] __initconst = KERN_INFO \ |
186 | "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n"; | 186 | "AX.25: Z8530 SCC driver version "VERSION".dl1bke\n"; |
187 | 187 | ||
188 | static void t_dwait(unsigned long); | 188 | static void t_dwait(unsigned long); |
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 5a6412ecce73..c6645f1017af 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c | |||
@@ -76,7 +76,7 @@ | |||
76 | /* --------------------------------------------------------------------- */ | 76 | /* --------------------------------------------------------------------- */ |
77 | 77 | ||
78 | static const char yam_drvname[] = "yam"; | 78 | static const char yam_drvname[] = "yam"; |
79 | static const char yam_drvinfo[] __initdata = KERN_INFO \ | 79 | static const char yam_drvinfo[] __initconst = KERN_INFO \ |
80 | "YAM driver version 0.8 by F1OAT/F6FBB\n"; | 80 | "YAM driver version 0.8 by F1OAT/F6FBB\n"; |
81 | 81 | ||
82 | /* --------------------------------------------------------------------- */ | 82 | /* --------------------------------------------------------------------- */ |
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 91d25888a1b9..d8b9b1e8ee02 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c | |||
@@ -26,7 +26,7 @@ | |||
26 | #include <linux/ethtool.h> | 26 | #include <linux/ethtool.h> |
27 | 27 | ||
28 | #define DRV_NAME "rionet" | 28 | #define DRV_NAME "rionet" |
29 | #define DRV_VERSION "0.2" | 29 | #define DRV_VERSION "0.3" |
30 | #define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>" | 30 | #define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>" |
31 | #define DRV_DESC "Ethernet over RapidIO" | 31 | #define DRV_DESC "Ethernet over RapidIO" |
32 | 32 | ||
@@ -47,8 +47,7 @@ MODULE_LICENSE("GPL"); | |||
47 | 47 | ||
48 | #define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE | 48 | #define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE |
49 | #define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE | 49 | #define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE |
50 | 50 | #define RIONET_MAX_NETS 8 | |
51 | static LIST_HEAD(rionet_peers); | ||
52 | 51 | ||
53 | struct rionet_private { | 52 | struct rionet_private { |
54 | struct rio_mport *mport; | 53 | struct rio_mport *mport; |
@@ -69,16 +68,14 @@ struct rionet_peer { | |||
69 | struct resource *res; | 68 | struct resource *res; |
70 | }; | 69 | }; |
71 | 70 | ||
72 | static int rionet_check = 0; | 71 | struct rionet_net { |
73 | static int rionet_capable = 1; | 72 | struct net_device *ndev; |
73 | struct list_head peers; | ||
74 | struct rio_dev **active; | ||
75 | int nact; /* number of active peers */ | ||
76 | }; | ||
74 | 77 | ||
75 | /* | 78 | static struct rionet_net nets[RIONET_MAX_NETS]; |
76 | * This is a fast lookup table for translating TX | ||
77 | * Ethernet packets into a destination RIO device. It | ||
78 | * could be made into a hash table to save memory depending | ||
79 | * on system trade-offs. | ||
80 | */ | ||
81 | static struct rio_dev **rionet_active; | ||
82 | 79 | ||
83 | #define is_rionet_capable(src_ops, dst_ops) \ | 80 | #define is_rionet_capable(src_ops, dst_ops) \ |
84 | ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ | 81 | ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ |
@@ -175,6 +172,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
175 | struct ethhdr *eth = (struct ethhdr *)skb->data; | 172 | struct ethhdr *eth = (struct ethhdr *)skb->data; |
176 | u16 destid; | 173 | u16 destid; |
177 | unsigned long flags; | 174 | unsigned long flags; |
175 | int add_num = 1; | ||
178 | 176 | ||
179 | local_irq_save(flags); | 177 | local_irq_save(flags); |
180 | if (!spin_trylock(&rnet->tx_lock)) { | 178 | if (!spin_trylock(&rnet->tx_lock)) { |
@@ -182,7 +180,10 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
182 | return NETDEV_TX_LOCKED; | 180 | return NETDEV_TX_LOCKED; |
183 | } | 181 | } |
184 | 182 | ||
185 | if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) { | 183 | if (is_multicast_ether_addr(eth->h_dest)) |
184 | add_num = nets[rnet->mport->id].nact; | ||
185 | |||
186 | if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { | ||
186 | netif_stop_queue(ndev); | 187 | netif_stop_queue(ndev); |
187 | spin_unlock_irqrestore(&rnet->tx_lock, flags); | 188 | spin_unlock_irqrestore(&rnet->tx_lock, flags); |
188 | printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", | 189 | printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", |
@@ -191,15 +192,22 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
191 | } | 192 | } |
192 | 193 | ||
193 | if (is_multicast_ether_addr(eth->h_dest)) { | 194 | if (is_multicast_ether_addr(eth->h_dest)) { |
195 | int count = 0; | ||
196 | |||
194 | for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); | 197 | for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); |
195 | i++) | 198 | i++) |
196 | if (rionet_active[i]) | 199 | if (nets[rnet->mport->id].active[i]) { |
197 | rionet_queue_tx_msg(skb, ndev, | 200 | rionet_queue_tx_msg(skb, ndev, |
198 | rionet_active[i]); | 201 | nets[rnet->mport->id].active[i]); |
202 | if (count) | ||
203 | atomic_inc(&skb->users); | ||
204 | count++; | ||
205 | } | ||
199 | } else if (RIONET_MAC_MATCH(eth->h_dest)) { | 206 | } else if (RIONET_MAC_MATCH(eth->h_dest)) { |
200 | destid = RIONET_GET_DESTID(eth->h_dest); | 207 | destid = RIONET_GET_DESTID(eth->h_dest); |
201 | if (rionet_active[destid]) | 208 | if (nets[rnet->mport->id].active[destid]) |
202 | rionet_queue_tx_msg(skb, ndev, rionet_active[destid]); | 209 | rionet_queue_tx_msg(skb, ndev, |
210 | nets[rnet->mport->id].active[destid]); | ||
203 | } | 211 | } |
204 | 212 | ||
205 | spin_unlock_irqrestore(&rnet->tx_lock, flags); | 213 | spin_unlock_irqrestore(&rnet->tx_lock, flags); |
@@ -218,16 +226,21 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u | |||
218 | printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x", | 226 | printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x", |
219 | DRV_NAME, sid, tid, info); | 227 | DRV_NAME, sid, tid, info); |
220 | if (info == RIONET_DOORBELL_JOIN) { | 228 | if (info == RIONET_DOORBELL_JOIN) { |
221 | if (!rionet_active[sid]) { | 229 | if (!nets[rnet->mport->id].active[sid]) { |
222 | list_for_each_entry(peer, &rionet_peers, node) { | 230 | list_for_each_entry(peer, |
223 | if (peer->rdev->destid == sid) | 231 | &nets[rnet->mport->id].peers, node) { |
224 | rionet_active[sid] = peer->rdev; | 232 | if (peer->rdev->destid == sid) { |
233 | nets[rnet->mport->id].active[sid] = | ||
234 | peer->rdev; | ||
235 | nets[rnet->mport->id].nact++; | ||
236 | } | ||
225 | } | 237 | } |
226 | rio_mport_send_doorbell(mport, sid, | 238 | rio_mport_send_doorbell(mport, sid, |
227 | RIONET_DOORBELL_JOIN); | 239 | RIONET_DOORBELL_JOIN); |
228 | } | 240 | } |
229 | } else if (info == RIONET_DOORBELL_LEAVE) { | 241 | } else if (info == RIONET_DOORBELL_LEAVE) { |
230 | rionet_active[sid] = NULL; | 242 | nets[rnet->mport->id].active[sid] = NULL; |
243 | nets[rnet->mport->id].nact--; | ||
231 | } else { | 244 | } else { |
232 | if (netif_msg_intr(rnet)) | 245 | if (netif_msg_intr(rnet)) |
233 | printk(KERN_WARNING "%s: unhandled doorbell\n", | 246 | printk(KERN_WARNING "%s: unhandled doorbell\n", |
@@ -321,7 +334,8 @@ static int rionet_open(struct net_device *ndev) | |||
321 | netif_carrier_on(ndev); | 334 | netif_carrier_on(ndev); |
322 | netif_start_queue(ndev); | 335 | netif_start_queue(ndev); |
323 | 336 | ||
324 | list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { | 337 | list_for_each_entry_safe(peer, tmp, |
338 | &nets[rnet->mport->id].peers, node) { | ||
325 | if (!(peer->res = rio_request_outb_dbell(peer->rdev, | 339 | if (!(peer->res = rio_request_outb_dbell(peer->rdev, |
326 | RIONET_DOORBELL_JOIN, | 340 | RIONET_DOORBELL_JOIN, |
327 | RIONET_DOORBELL_LEAVE))) | 341 | RIONET_DOORBELL_LEAVE))) |
@@ -346,7 +360,7 @@ static int rionet_close(struct net_device *ndev) | |||
346 | int i; | 360 | int i; |
347 | 361 | ||
348 | if (netif_msg_ifup(rnet)) | 362 | if (netif_msg_ifup(rnet)) |
349 | printk(KERN_INFO "%s: close\n", DRV_NAME); | 363 | printk(KERN_INFO "%s: close %s\n", DRV_NAME, ndev->name); |
350 | 364 | ||
351 | netif_stop_queue(ndev); | 365 | netif_stop_queue(ndev); |
352 | netif_carrier_off(ndev); | 366 | netif_carrier_off(ndev); |
@@ -354,10 +368,11 @@ static int rionet_close(struct net_device *ndev) | |||
354 | for (i = 0; i < RIONET_RX_RING_SIZE; i++) | 368 | for (i = 0; i < RIONET_RX_RING_SIZE; i++) |
355 | kfree_skb(rnet->rx_skb[i]); | 369 | kfree_skb(rnet->rx_skb[i]); |
356 | 370 | ||
357 | list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { | 371 | list_for_each_entry_safe(peer, tmp, |
358 | if (rionet_active[peer->rdev->destid]) { | 372 | &nets[rnet->mport->id].peers, node) { |
373 | if (nets[rnet->mport->id].active[peer->rdev->destid]) { | ||
359 | rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE); | 374 | rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE); |
360 | rionet_active[peer->rdev->destid] = NULL; | 375 | nets[rnet->mport->id].active[peer->rdev->destid] = NULL; |
361 | } | 376 | } |
362 | rio_release_outb_dbell(peer->rdev, peer->res); | 377 | rio_release_outb_dbell(peer->rdev, peer->res); |
363 | } | 378 | } |
@@ -373,17 +388,21 @@ static int rionet_close(struct net_device *ndev) | |||
373 | static void rionet_remove(struct rio_dev *rdev) | 388 | static void rionet_remove(struct rio_dev *rdev) |
374 | { | 389 | { |
375 | struct net_device *ndev = rio_get_drvdata(rdev); | 390 | struct net_device *ndev = rio_get_drvdata(rdev); |
391 | unsigned char netid = rdev->net->hport->id; | ||
376 | struct rionet_peer *peer, *tmp; | 392 | struct rionet_peer *peer, *tmp; |
377 | 393 | ||
378 | free_pages((unsigned long)rionet_active, get_order(sizeof(void *) * | ||
379 | RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size))); | ||
380 | unregister_netdev(ndev); | 394 | unregister_netdev(ndev); |
381 | free_netdev(ndev); | ||
382 | 395 | ||
383 | list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { | 396 | free_pages((unsigned long)nets[netid].active, get_order(sizeof(void *) * |
397 | RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size))); | ||
398 | nets[netid].active = NULL; | ||
399 | |||
400 | list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { | ||
384 | list_del(&peer->node); | 401 | list_del(&peer->node); |
385 | kfree(peer); | 402 | kfree(peer); |
386 | } | 403 | } |
404 | |||
405 | free_netdev(ndev); | ||
387 | } | 406 | } |
388 | 407 | ||
389 | static void rionet_get_drvinfo(struct net_device *ndev, | 408 | static void rionet_get_drvinfo(struct net_device *ndev, |
@@ -435,13 +454,13 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) | |||
435 | const size_t rionet_active_bytes = sizeof(void *) * | 454 | const size_t rionet_active_bytes = sizeof(void *) * |
436 | RIO_MAX_ROUTE_ENTRIES(mport->sys_size); | 455 | RIO_MAX_ROUTE_ENTRIES(mport->sys_size); |
437 | 456 | ||
438 | rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, | 457 | nets[mport->id].active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, |
439 | get_order(rionet_active_bytes)); | 458 | get_order(rionet_active_bytes)); |
440 | if (!rionet_active) { | 459 | if (!nets[mport->id].active) { |
441 | rc = -ENOMEM; | 460 | rc = -ENOMEM; |
442 | goto out; | 461 | goto out; |
443 | } | 462 | } |
444 | memset((void *)rionet_active, 0, rionet_active_bytes); | 463 | memset((void *)nets[mport->id].active, 0, rionet_active_bytes); |
445 | 464 | ||
446 | /* Set up private area */ | 465 | /* Set up private area */ |
447 | rnet = netdev_priv(ndev); | 466 | rnet = netdev_priv(ndev); |
@@ -470,60 +489,62 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) | |||
470 | if (rc != 0) | 489 | if (rc != 0) |
471 | goto out; | 490 | goto out; |
472 | 491 | ||
473 | printk("%s: %s %s Version %s, MAC %pM\n", | 492 | printk(KERN_INFO "%s: %s %s Version %s, MAC %pM, %s\n", |
474 | ndev->name, | 493 | ndev->name, |
475 | DRV_NAME, | 494 | DRV_NAME, |
476 | DRV_DESC, | 495 | DRV_DESC, |
477 | DRV_VERSION, | 496 | DRV_VERSION, |
478 | ndev->dev_addr); | 497 | ndev->dev_addr, |
498 | mport->name); | ||
479 | 499 | ||
480 | out: | 500 | out: |
481 | return rc; | 501 | return rc; |
482 | } | 502 | } |
483 | 503 | ||
484 | /* | 504 | static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1]; |
485 | * XXX Make multi-net safe | 505 | |
486 | */ | ||
487 | static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | 506 | static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) |
488 | { | 507 | { |
489 | int rc = -ENODEV; | 508 | int rc = -ENODEV; |
490 | u32 lsrc_ops, ldst_ops; | 509 | u32 lsrc_ops, ldst_ops; |
491 | struct rionet_peer *peer; | 510 | struct rionet_peer *peer; |
492 | struct net_device *ndev = NULL; | 511 | struct net_device *ndev = NULL; |
512 | unsigned char netid = rdev->net->hport->id; | ||
513 | int oldnet; | ||
493 | 514 | ||
494 | /* If local device is not rionet capable, give up quickly */ | 515 | if (netid >= RIONET_MAX_NETS) |
495 | if (!rionet_capable) | 516 | return rc; |
496 | goto out; | ||
497 | 517 | ||
498 | /* Allocate our net_device structure */ | 518 | oldnet = test_and_set_bit(netid, net_table); |
499 | ndev = alloc_etherdev(sizeof(struct rionet_private)); | ||
500 | if (ndev == NULL) { | ||
501 | rc = -ENOMEM; | ||
502 | goto out; | ||
503 | } | ||
504 | 519 | ||
505 | /* | 520 | /* |
506 | * First time through, make sure local device is rionet | 521 | * First time through, make sure local device is rionet |
507 | * capable, setup netdev, and set flags so this is skipped | 522 | * capable, setup netdev (will be skipped on later probes) |
508 | * on later probes | ||
509 | */ | 523 | */ |
510 | if (!rionet_check) { | 524 | if (!oldnet) { |
511 | rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, | 525 | rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, |
512 | &lsrc_ops); | 526 | &lsrc_ops); |
513 | rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR, | 527 | rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR, |
514 | &ldst_ops); | 528 | &ldst_ops); |
515 | if (!is_rionet_capable(lsrc_ops, ldst_ops)) { | 529 | if (!is_rionet_capable(lsrc_ops, ldst_ops)) { |
516 | printk(KERN_ERR | 530 | printk(KERN_ERR |
517 | "%s: local device is not network capable\n", | 531 | "%s: local device %s is not network capable\n", |
518 | DRV_NAME); | 532 | DRV_NAME, rdev->net->hport->name); |
519 | rionet_check = 1; | ||
520 | rionet_capable = 0; | ||
521 | goto out; | 533 | goto out; |
522 | } | 534 | } |
523 | 535 | ||
536 | /* Allocate our net_device structure */ | ||
537 | ndev = alloc_etherdev(sizeof(struct rionet_private)); | ||
538 | if (ndev == NULL) { | ||
539 | rc = -ENOMEM; | ||
540 | goto out; | ||
541 | } | ||
542 | nets[netid].ndev = ndev; | ||
524 | rc = rionet_setup_netdev(rdev->net->hport, ndev); | 543 | rc = rionet_setup_netdev(rdev->net->hport, ndev); |
525 | rionet_check = 1; | 544 | INIT_LIST_HEAD(&nets[netid].peers); |
526 | } | 545 | nets[netid].nact = 0; |
546 | } else if (nets[netid].ndev == NULL) | ||
547 | goto out; | ||
527 | 548 | ||
528 | /* | 549 | /* |
529 | * If the remote device has mailbox/doorbell capabilities, | 550 | * If the remote device has mailbox/doorbell capabilities, |
@@ -535,10 +556,10 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | |||
535 | goto out; | 556 | goto out; |
536 | } | 557 | } |
537 | peer->rdev = rdev; | 558 | peer->rdev = rdev; |
538 | list_add_tail(&peer->node, &rionet_peers); | 559 | list_add_tail(&peer->node, &nets[netid].peers); |
539 | } | 560 | } |
540 | 561 | ||
541 | rio_set_drvdata(rdev, ndev); | 562 | rio_set_drvdata(rdev, nets[netid].ndev); |
542 | 563 | ||
543 | out: | 564 | out: |
544 | return rc; | 565 | return rc; |
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c index 0e5769061702..feacc3b994b7 100644 --- a/drivers/net/wan/z85230.c +++ b/drivers/net/wan/z85230.c | |||
@@ -1775,7 +1775,7 @@ EXPORT_SYMBOL(z8530_queue_xmit); | |||
1775 | /* | 1775 | /* |
1776 | * Module support | 1776 | * Module support |
1777 | */ | 1777 | */ |
1778 | static const char banner[] __initdata = | 1778 | static const char banner[] __initconst = |
1779 | KERN_INFO "Generic Z85C30/Z85230 interface driver v0.02\n"; | 1779 | KERN_INFO "Generic Z85C30/Z85230 interface driver v0.02\n"; |
1780 | 1780 | ||
1781 | static int __init z85230_init_driver(void) | 1781 | static int __init z85230_init_driver(void) |
diff --git a/drivers/platform/x86/amilo-rfkill.c b/drivers/platform/x86/amilo-rfkill.c index a514bf66fdd7..1deca7f6c4ea 100644 --- a/drivers/platform/x86/amilo-rfkill.c +++ b/drivers/platform/x86/amilo-rfkill.c | |||
@@ -74,7 +74,7 @@ static const struct rfkill_ops amilo_m7440_rfkill_ops = { | |||
74 | .set_block = amilo_m7440_rfkill_set_block | 74 | .set_block = amilo_m7440_rfkill_set_block |
75 | }; | 75 | }; |
76 | 76 | ||
77 | static const struct dmi_system_id __devinitdata amilo_rfkill_id_table[] = { | 77 | static const struct dmi_system_id __devinitconst amilo_rfkill_id_table[] = { |
78 | { | 78 | { |
79 | .matches = { | 79 | .matches = { |
80 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 80 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
diff --git a/drivers/platform/x86/fujitsu-tablet.c b/drivers/platform/x86/fujitsu-tablet.c index 7acae3f85f3b..f77484528b1b 100644 --- a/drivers/platform/x86/fujitsu-tablet.c +++ b/drivers/platform/x86/fujitsu-tablet.c | |||
@@ -52,7 +52,7 @@ struct fujitsu_config { | |||
52 | unsigned int quirks; | 52 | unsigned int quirks; |
53 | }; | 53 | }; |
54 | 54 | ||
55 | static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initconst = { | 55 | static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initdata = { |
56 | KEY_RESERVED, | 56 | KEY_RESERVED, |
57 | KEY_RESERVED, | 57 | KEY_RESERVED, |
58 | KEY_RESERVED, | 58 | KEY_RESERVED, |
@@ -71,7 +71,7 @@ static unsigned short keymap_Lifebook_Tseries[KEYMAP_LEN] __initconst = { | |||
71 | KEY_LEFTALT | 71 | KEY_LEFTALT |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initconst = { | 74 | static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initdata = { |
75 | KEY_RESERVED, | 75 | KEY_RESERVED, |
76 | KEY_RESERVED, | 76 | KEY_RESERVED, |
77 | KEY_RESERVED, | 77 | KEY_RESERVED, |
@@ -90,7 +90,7 @@ static unsigned short keymap_Lifebook_U810[KEYMAP_LEN] __initconst = { | |||
90 | KEY_LEFTALT | 90 | KEY_LEFTALT |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initconst = { | 93 | static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initdata = { |
94 | KEY_RESERVED, | 94 | KEY_RESERVED, |
95 | KEY_RESERVED, | 95 | KEY_RESERVED, |
96 | KEY_RESERVED, | 96 | KEY_RESERVED, |
@@ -109,7 +109,7 @@ static unsigned short keymap_Stylistic_Tseries[KEYMAP_LEN] __initconst = { | |||
109 | KEY_LEFTALT | 109 | KEY_LEFTALT |
110 | }; | 110 | }; |
111 | 111 | ||
112 | static unsigned short keymap_Stylistic_ST5xxx[KEYMAP_LEN] __initconst = { | 112 | static unsigned short keymap_Stylistic_ST5xxx[KEYMAP_LEN] __initdata = { |
113 | KEY_RESERVED, | 113 | KEY_RESERVED, |
114 | KEY_RESERVED, | 114 | KEY_RESERVED, |
115 | KEY_RESERVED, | 115 | KEY_RESERVED, |
@@ -299,7 +299,7 @@ static int __devinit fujitsu_dmi_stylistic(const struct dmi_system_id *dmi) | |||
299 | return 1; | 299 | return 1; |
300 | } | 300 | } |
301 | 301 | ||
302 | static struct dmi_system_id dmi_ids[] __initconst = { | 302 | static const struct dmi_system_id dmi_ids[] __initconst = { |
303 | { | 303 | { |
304 | .callback = fujitsu_dmi_lifebook, | 304 | .callback = fujitsu_dmi_lifebook, |
305 | .ident = "Fujitsu Siemens P/T Series", | 305 | .ident = "Fujitsu Siemens P/T Series", |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 9da5fe715e6a..75dd651664ae 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -522,7 +522,7 @@ static acpi_handle ec_handle; | |||
522 | 522 | ||
523 | #define TPACPI_HANDLE(object, parent, paths...) \ | 523 | #define TPACPI_HANDLE(object, parent, paths...) \ |
524 | static acpi_handle object##_handle; \ | 524 | static acpi_handle object##_handle; \ |
525 | static const acpi_handle *object##_parent __initdata = \ | 525 | static const acpi_handle * const object##_parent __initconst = \ |
526 | &parent##_handle; \ | 526 | &parent##_handle; \ |
527 | static char *object##_paths[] __initdata = { paths } | 527 | static char *object##_paths[] __initdata = { paths } |
528 | 528 | ||
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c index e771487132f7..2420d5af0583 100644 --- a/drivers/pps/pps.c +++ b/drivers/pps/pps.c | |||
@@ -306,7 +306,7 @@ int pps_register_cdev(struct pps_device *pps) | |||
306 | if (err < 0) | 306 | if (err < 0) |
307 | return err; | 307 | return err; |
308 | 308 | ||
309 | pps->id &= MAX_ID_MASK; | 309 | pps->id &= MAX_IDR_MASK; |
310 | if (pps->id >= PPS_MAX_SOURCES) { | 310 | if (pps->id >= PPS_MAX_SOURCES) { |
311 | pr_err("%s: too many PPS sources in the system\n", | 311 | pr_err("%s: too many PPS sources in the system\n", |
312 | pps->info.name); | 312 | pps->info.name); |
diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index d5e1625bbac2..38ecd8f4d60e 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c | |||
@@ -862,6 +862,90 @@ static void tsi721_init_pc2sr_mapping(struct tsi721_device *priv) | |||
862 | } | 862 | } |
863 | 863 | ||
864 | /** | 864 | /** |
865 | * tsi721_rio_map_inb_mem -- Mapping inbound memory region. | ||
866 | * @mport: RapidIO master port | ||
867 | * @lstart: Local memory space start address. | ||
868 | * @rstart: RapidIO space start address. | ||
869 | * @size: The mapping region size. | ||
870 | * @flags: Flags for mapping. 0 for using default flags. | ||
871 | * | ||
872 | * Return: 0 -- Success. | ||
873 | * | ||
874 | * This function will create the inbound mapping | ||
875 | * from rstart to lstart. | ||
876 | */ | ||
877 | static int tsi721_rio_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart, | ||
878 | u64 rstart, u32 size, u32 flags) | ||
879 | { | ||
880 | struct tsi721_device *priv = mport->priv; | ||
881 | int i; | ||
882 | u32 regval; | ||
883 | |||
884 | if (!is_power_of_2(size) || size < 0x1000 || | ||
885 | ((u64)lstart & (size - 1)) || (rstart & (size - 1))) | ||
886 | return -EINVAL; | ||
887 | |||
888 | /* Search for free inbound translation window */ | ||
889 | for (i = 0; i < TSI721_IBWIN_NUM; i++) { | ||
890 | regval = ioread32(priv->regs + TSI721_IBWIN_LB(i)); | ||
891 | if (!(regval & TSI721_IBWIN_LB_WEN)) | ||
892 | break; | ||
893 | } | ||
894 | |||
895 | if (i >= TSI721_IBWIN_NUM) { | ||
896 | dev_err(&priv->pdev->dev, | ||
897 | "Unable to find free inbound window\n"); | ||
898 | return -EBUSY; | ||
899 | } | ||
900 | |||
901 | iowrite32(TSI721_IBWIN_SIZE(size) << 8, | ||
902 | priv->regs + TSI721_IBWIN_SZ(i)); | ||
903 | |||
904 | iowrite32(((u64)lstart >> 32), priv->regs + TSI721_IBWIN_TUA(i)); | ||
905 | iowrite32(((u64)lstart & TSI721_IBWIN_TLA_ADD), | ||
906 | priv->regs + TSI721_IBWIN_TLA(i)); | ||
907 | |||
908 | iowrite32(rstart >> 32, priv->regs + TSI721_IBWIN_UB(i)); | ||
909 | iowrite32((rstart & TSI721_IBWIN_LB_BA) | TSI721_IBWIN_LB_WEN, | ||
910 | priv->regs + TSI721_IBWIN_LB(i)); | ||
911 | dev_dbg(&priv->pdev->dev, | ||
912 | "Configured IBWIN%d mapping (RIO_0x%llx -> PCIe_0x%llx)\n", | ||
913 | i, rstart, (unsigned long long)lstart); | ||
914 | |||
915 | return 0; | ||
916 | } | ||
917 | |||
918 | /** | ||
919 | * fsl_rio_unmap_inb_mem -- Unmapping inbound memory region. | ||
920 | * @mport: RapidIO master port | ||
921 | * @lstart: Local memory space start address. | ||
922 | */ | ||
923 | static void tsi721_rio_unmap_inb_mem(struct rio_mport *mport, | ||
924 | dma_addr_t lstart) | ||
925 | { | ||
926 | struct tsi721_device *priv = mport->priv; | ||
927 | int i; | ||
928 | u64 addr; | ||
929 | u32 regval; | ||
930 | |||
931 | /* Search for matching active inbound translation window */ | ||
932 | for (i = 0; i < TSI721_IBWIN_NUM; i++) { | ||
933 | regval = ioread32(priv->regs + TSI721_IBWIN_LB(i)); | ||
934 | if (regval & TSI721_IBWIN_LB_WEN) { | ||
935 | regval = ioread32(priv->regs + TSI721_IBWIN_TUA(i)); | ||
936 | addr = (u64)regval << 32; | ||
937 | regval = ioread32(priv->regs + TSI721_IBWIN_TLA(i)); | ||
938 | addr |= regval & TSI721_IBWIN_TLA_ADD; | ||
939 | |||
940 | if (addr == (u64)lstart) { | ||
941 | iowrite32(0, priv->regs + TSI721_IBWIN_LB(i)); | ||
942 | break; | ||
943 | } | ||
944 | } | ||
945 | } | ||
946 | } | ||
947 | |||
948 | /** | ||
865 | * tsi721_init_sr2pc_mapping - initializes inbound (SRIO->PCIe) | 949 | * tsi721_init_sr2pc_mapping - initializes inbound (SRIO->PCIe) |
866 | * translation regions. | 950 | * translation regions. |
867 | * @priv: pointer to tsi721 private data | 951 | * @priv: pointer to tsi721 private data |
@@ -874,7 +958,7 @@ static void tsi721_init_sr2pc_mapping(struct tsi721_device *priv) | |||
874 | 958 | ||
875 | /* Disable all SR2PC inbound windows */ | 959 | /* Disable all SR2PC inbound windows */ |
876 | for (i = 0; i < TSI721_IBWIN_NUM; i++) | 960 | for (i = 0; i < TSI721_IBWIN_NUM; i++) |
877 | iowrite32(0, priv->regs + TSI721_IBWINLB(i)); | 961 | iowrite32(0, priv->regs + TSI721_IBWIN_LB(i)); |
878 | } | 962 | } |
879 | 963 | ||
880 | /** | 964 | /** |
@@ -2144,6 +2228,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) | |||
2144 | ops->add_outb_message = tsi721_add_outb_message; | 2228 | ops->add_outb_message = tsi721_add_outb_message; |
2145 | ops->add_inb_buffer = tsi721_add_inb_buffer; | 2229 | ops->add_inb_buffer = tsi721_add_inb_buffer; |
2146 | ops->get_inb_message = tsi721_get_inb_message; | 2230 | ops->get_inb_message = tsi721_get_inb_message; |
2231 | ops->map_inb = tsi721_rio_map_inb_mem; | ||
2232 | ops->unmap_inb = tsi721_rio_unmap_inb_mem; | ||
2147 | 2233 | ||
2148 | mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); | 2234 | mport = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); |
2149 | if (!mport) { | 2235 | if (!mport) { |
@@ -2165,7 +2251,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv) | |||
2165 | rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); | 2251 | rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); |
2166 | rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3); | 2252 | rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3); |
2167 | rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3); | 2253 | rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3); |
2168 | strcpy(mport->name, "Tsi721 mport"); | 2254 | snprintf(mport->name, RIO_MAX_MPORT_NAME, "%s(%s)", |
2255 | dev_driver_string(&pdev->dev), dev_name(&pdev->dev)); | ||
2169 | 2256 | ||
2170 | /* Hook up interrupt handler */ | 2257 | /* Hook up interrupt handler */ |
2171 | 2258 | ||
@@ -2315,7 +2402,8 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, | |||
2315 | 2402 | ||
2316 | /* Configure DMA attributes. */ | 2403 | /* Configure DMA attributes. */ |
2317 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { | 2404 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { |
2318 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { | 2405 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); |
2406 | if (err) { | ||
2319 | dev_info(&pdev->dev, "Unable to set DMA mask\n"); | 2407 | dev_info(&pdev->dev, "Unable to set DMA mask\n"); |
2320 | goto err_unmap_bars; | 2408 | goto err_unmap_bars; |
2321 | } | 2409 | } |
diff --git a/drivers/rapidio/devices/tsi721.h b/drivers/rapidio/devices/tsi721.h index 59de9d7be346..7d5b13ba8d4f 100644 --- a/drivers/rapidio/devices/tsi721.h +++ b/drivers/rapidio/devices/tsi721.h | |||
@@ -156,9 +156,18 @@ | |||
156 | 156 | ||
157 | #define TSI721_IBWIN_NUM 8 | 157 | #define TSI721_IBWIN_NUM 8 |
158 | 158 | ||
159 | #define TSI721_IBWINLB(x) (0x29000 + (x) * 0x20) | 159 | #define TSI721_IBWIN_LB(x) (0x29000 + (x) * 0x20) |
160 | #define TSI721_IBWINLB_BA 0xfffff000 | 160 | #define TSI721_IBWIN_LB_BA 0xfffff000 |
161 | #define TSI721_IBWINLB_WEN 0x00000001 | 161 | #define TSI721_IBWIN_LB_WEN 0x00000001 |
162 | |||
163 | #define TSI721_IBWIN_UB(x) (0x29004 + (x) * 0x20) | ||
164 | #define TSI721_IBWIN_SZ(x) (0x29008 + (x) * 0x20) | ||
165 | #define TSI721_IBWIN_SZ_SIZE 0x00001f00 | ||
166 | #define TSI721_IBWIN_SIZE(size) (__fls(size) - 12) | ||
167 | |||
168 | #define TSI721_IBWIN_TLA(x) (0x2900c + (x) * 0x20) | ||
169 | #define TSI721_IBWIN_TLA_ADD 0xfffff000 | ||
170 | #define TSI721_IBWIN_TUA(x) (0x29010 + (x) * 0x20) | ||
162 | 171 | ||
163 | #define TSI721_SR2PC_GEN_INTE 0x29800 | 172 | #define TSI721_SR2PC_GEN_INTE 0x29800 |
164 | #define TSI721_SR2PC_PWE 0x29804 | 173 | #define TSI721_SR2PC_PWE 0x29804 |
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 2bebd791a092..48e9041dd1e2 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -31,27 +31,21 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
34 | #include <linux/sched.h> | ||
34 | #include <linux/jiffies.h> | 35 | #include <linux/jiffies.h> |
35 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
36 | 37 | ||
37 | #include "rio.h" | 38 | #include "rio.h" |
38 | 39 | ||
39 | LIST_HEAD(rio_devices); | 40 | LIST_HEAD(rio_devices); |
40 | static LIST_HEAD(rio_switches); | ||
41 | |||
42 | static void rio_enum_timeout(unsigned long); | ||
43 | 41 | ||
44 | static void rio_init_em(struct rio_dev *rdev); | 42 | static void rio_init_em(struct rio_dev *rdev); |
45 | 43 | ||
46 | DEFINE_SPINLOCK(rio_global_list_lock); | 44 | DEFINE_SPINLOCK(rio_global_list_lock); |
47 | 45 | ||
48 | static int next_destid = 0; | 46 | static int next_destid = 0; |
49 | static int next_net = 0; | ||
50 | static int next_comptag = 1; | 47 | static int next_comptag = 1; |
51 | 48 | ||
52 | static struct timer_list rio_enum_timer = | ||
53 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); | ||
54 | |||
55 | static int rio_mport_phys_table[] = { | 49 | static int rio_mport_phys_table[] = { |
56 | RIO_EFB_PAR_EP_ID, | 50 | RIO_EFB_PAR_EP_ID, |
57 | RIO_EFB_PAR_EP_REC_ID, | 51 | RIO_EFB_PAR_EP_REC_ID, |
@@ -60,6 +54,114 @@ static int rio_mport_phys_table[] = { | |||
60 | -1, | 54 | -1, |
61 | }; | 55 | }; |
62 | 56 | ||
57 | |||
58 | /* | ||
59 | * rio_destid_alloc - Allocate next available destID for given network | ||
60 | * net: RIO network | ||
61 | * | ||
62 | * Returns next available device destination ID for the specified RIO network. | ||
63 | * Marks allocated ID as one in use. | ||
64 | * Returns RIO_INVALID_DESTID if new destID is not available. | ||
65 | */ | ||
66 | static u16 rio_destid_alloc(struct rio_net *net) | ||
67 | { | ||
68 | int destid; | ||
69 | struct rio_id_table *idtab = &net->destid_table; | ||
70 | |||
71 | spin_lock(&idtab->lock); | ||
72 | destid = find_next_zero_bit(idtab->table, idtab->max, idtab->next); | ||
73 | if (destid >= idtab->max) | ||
74 | destid = find_first_zero_bit(idtab->table, idtab->max); | ||
75 | |||
76 | if (destid < idtab->max) { | ||
77 | idtab->next = destid + 1; | ||
78 | if (idtab->next >= idtab->max) | ||
79 | idtab->next = 0; | ||
80 | set_bit(destid, idtab->table); | ||
81 | destid += idtab->start; | ||
82 | } else | ||
83 | destid = RIO_INVALID_DESTID; | ||
84 | |||
85 | spin_unlock(&idtab->lock); | ||
86 | return (u16)destid; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * rio_destid_reserve - Reserve the specivied destID | ||
91 | * net: RIO network | ||
92 | * destid: destID to reserve | ||
93 | * | ||
94 | * Tries to reserve the specified destID. | ||
95 | * Returns 0 if successfull. | ||
96 | */ | ||
97 | static int rio_destid_reserve(struct rio_net *net, u16 destid) | ||
98 | { | ||
99 | int oldbit; | ||
100 | struct rio_id_table *idtab = &net->destid_table; | ||
101 | |||
102 | destid -= idtab->start; | ||
103 | spin_lock(&idtab->lock); | ||
104 | oldbit = test_and_set_bit(destid, idtab->table); | ||
105 | spin_unlock(&idtab->lock); | ||
106 | return oldbit; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * rio_destid_free - free a previously allocated destID | ||
111 | * net: RIO network | ||
112 | * destid: destID to free | ||
113 | * | ||
114 | * Makes the specified destID available for use. | ||
115 | */ | ||
116 | static void rio_destid_free(struct rio_net *net, u16 destid) | ||
117 | { | ||
118 | struct rio_id_table *idtab = &net->destid_table; | ||
119 | |||
120 | destid -= idtab->start; | ||
121 | spin_lock(&idtab->lock); | ||
122 | clear_bit(destid, idtab->table); | ||
123 | spin_unlock(&idtab->lock); | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * rio_destid_first - return first destID in use | ||
128 | * net: RIO network | ||
129 | */ | ||
130 | static u16 rio_destid_first(struct rio_net *net) | ||
131 | { | ||
132 | int destid; | ||
133 | struct rio_id_table *idtab = &net->destid_table; | ||
134 | |||
135 | spin_lock(&idtab->lock); | ||
136 | destid = find_first_bit(idtab->table, idtab->max); | ||
137 | if (destid >= idtab->max) | ||
138 | destid = RIO_INVALID_DESTID; | ||
139 | else | ||
140 | destid += idtab->start; | ||
141 | spin_unlock(&idtab->lock); | ||
142 | return (u16)destid; | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * rio_destid_next - return next destID in use | ||
147 | * net: RIO network | ||
148 | * from: destination ID from which search shall continue | ||
149 | */ | ||
150 | static u16 rio_destid_next(struct rio_net *net, u16 from) | ||
151 | { | ||
152 | int destid; | ||
153 | struct rio_id_table *idtab = &net->destid_table; | ||
154 | |||
155 | spin_lock(&idtab->lock); | ||
156 | destid = find_next_bit(idtab->table, idtab->max, from); | ||
157 | if (destid >= idtab->max) | ||
158 | destid = RIO_INVALID_DESTID; | ||
159 | else | ||
160 | destid += idtab->start; | ||
161 | spin_unlock(&idtab->lock); | ||
162 | return (u16)destid; | ||
163 | } | ||
164 | |||
63 | /** | 165 | /** |
64 | * rio_get_device_id - Get the base/extended device id for a device | 166 | * rio_get_device_id - Get the base/extended device id for a device |
65 | * @port: RIO master port | 167 | * @port: RIO master port |
@@ -108,14 +210,15 @@ static void rio_local_set_device_id(struct rio_mport *port, u16 did) | |||
108 | 210 | ||
109 | /** | 211 | /** |
110 | * rio_clear_locks- Release all host locks and signal enumeration complete | 212 | * rio_clear_locks- Release all host locks and signal enumeration complete |
111 | * @port: Master port to issue transaction | 213 | * @net: RIO network to run on |
112 | * | 214 | * |
113 | * Marks the component tag CSR on each device with the enumeration | 215 | * Marks the component tag CSR on each device with the enumeration |
114 | * complete flag. When complete, it then release the host locks on | 216 | * complete flag. When complete, it then release the host locks on |
115 | * each device. Returns 0 on success or %-EINVAL on failure. | 217 | * each device. Returns 0 on success or %-EINVAL on failure. |
116 | */ | 218 | */ |
117 | static int rio_clear_locks(struct rio_mport *port) | 219 | static int rio_clear_locks(struct rio_net *net) |
118 | { | 220 | { |
221 | struct rio_mport *port = net->hport; | ||
119 | struct rio_dev *rdev; | 222 | struct rio_dev *rdev; |
120 | u32 result; | 223 | u32 result; |
121 | int ret = 0; | 224 | int ret = 0; |
@@ -130,7 +233,7 @@ static int rio_clear_locks(struct rio_mport *port) | |||
130 | result); | 233 | result); |
131 | ret = -EINVAL; | 234 | ret = -EINVAL; |
132 | } | 235 | } |
133 | list_for_each_entry(rdev, &rio_devices, global_list) { | 236 | list_for_each_entry(rdev, &net->devices, net_list) { |
134 | rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR, | 237 | rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR, |
135 | port->host_deviceid); | 238 | port->host_deviceid); |
136 | rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result); | 239 | rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result); |
@@ -176,10 +279,6 @@ static int rio_enum_host(struct rio_mport *port) | |||
176 | 279 | ||
177 | /* Set master port destid and init destid ctr */ | 280 | /* Set master port destid and init destid ctr */ |
178 | rio_local_set_device_id(port, port->host_deviceid); | 281 | rio_local_set_device_id(port, port->host_deviceid); |
179 | |||
180 | if (next_destid == port->host_deviceid) | ||
181 | next_destid++; | ||
182 | |||
183 | return 0; | 282 | return 0; |
184 | } | 283 | } |
185 | 284 | ||
@@ -446,9 +545,8 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
446 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { | 545 | if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) { |
447 | if (do_enum) { | 546 | if (do_enum) { |
448 | rio_set_device_id(port, destid, hopcount, next_destid); | 547 | rio_set_device_id(port, destid, hopcount, next_destid); |
449 | rdev->destid = next_destid++; | 548 | rdev->destid = next_destid; |
450 | if (next_destid == port->host_deviceid) | 549 | next_destid = rio_destid_alloc(net); |
451 | next_destid++; | ||
452 | } else | 550 | } else |
453 | rdev->destid = rio_get_device_id(port, destid, hopcount); | 551 | rdev->destid = rio_get_device_id(port, destid, hopcount); |
454 | 552 | ||
@@ -483,7 +581,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
483 | rswitch->clr_table(port, destid, hopcount, | 581 | rswitch->clr_table(port, destid, hopcount, |
484 | RIO_GLOBAL_TABLE); | 582 | RIO_GLOBAL_TABLE); |
485 | 583 | ||
486 | list_add_tail(&rswitch->node, &rio_switches); | 584 | list_add_tail(&rswitch->node, &net->switches); |
487 | 585 | ||
488 | } else { | 586 | } else { |
489 | if (do_enum) | 587 | if (do_enum) |
@@ -747,12 +845,7 @@ static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount) | |||
747 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | 845 | static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, |
748 | u8 hopcount, struct rio_dev *prev, int prev_port) | 846 | u8 hopcount, struct rio_dev *prev, int prev_port) |
749 | { | 847 | { |
750 | int port_num; | ||
751 | int cur_destid; | ||
752 | int sw_destid; | ||
753 | int sw_inport; | ||
754 | struct rio_dev *rdev; | 848 | struct rio_dev *rdev; |
755 | u16 destid; | ||
756 | u32 regval; | 849 | u32 regval; |
757 | int tmp; | 850 | int tmp; |
758 | 851 | ||
@@ -818,19 +911,26 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
818 | return -1; | 911 | return -1; |
819 | 912 | ||
820 | if (rio_is_switch(rdev)) { | 913 | if (rio_is_switch(rdev)) { |
914 | int sw_destid; | ||
915 | int cur_destid; | ||
916 | int sw_inport; | ||
917 | u16 destid; | ||
918 | int port_num; | ||
919 | |||
821 | sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); | 920 | sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo); |
822 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, | 921 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
823 | port->host_deviceid, sw_inport, 0); | 922 | port->host_deviceid, sw_inport, 0); |
824 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; | 923 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; |
825 | 924 | ||
826 | for (destid = 0; destid < next_destid; destid++) { | 925 | destid = rio_destid_first(net); |
827 | if (destid == port->host_deviceid) | 926 | while (destid != RIO_INVALID_DESTID && destid < next_destid) { |
828 | continue; | 927 | if (destid != port->host_deviceid) { |
829 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, | 928 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
830 | destid, sw_inport, 0); | 929 | destid, sw_inport, 0); |
831 | rdev->rswitch->route_table[destid] = sw_inport; | 930 | rdev->rswitch->route_table[destid] = sw_inport; |
931 | } | ||
932 | destid = rio_destid_next(net, destid + 1); | ||
832 | } | 933 | } |
833 | |||
834 | pr_debug( | 934 | pr_debug( |
835 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", | 935 | "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n", |
836 | rio_name(rdev), rdev->vid, rdev->did, | 936 | rio_name(rdev), rdev->vid, rdev->did, |
@@ -839,12 +939,10 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
839 | for (port_num = 0; | 939 | for (port_num = 0; |
840 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); | 940 | port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo); |
841 | port_num++) { | 941 | port_num++) { |
842 | /*Enable Input Output Port (transmitter reviever)*/ | 942 | if (sw_inport == port_num) { |
843 | rio_enable_rx_tx_port(port, 0, | 943 | rio_enable_rx_tx_port(port, 0, |
844 | RIO_ANY_DESTID(port->sys_size), | 944 | RIO_ANY_DESTID(port->sys_size), |
845 | hopcount, port_num); | 945 | hopcount, port_num); |
846 | |||
847 | if (sw_inport == port_num) { | ||
848 | rdev->rswitch->port_ok |= (1 << port_num); | 946 | rdev->rswitch->port_ok |= (1 << port_num); |
849 | continue; | 947 | continue; |
850 | } | 948 | } |
@@ -857,6 +955,9 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
857 | pr_debug( | 955 | pr_debug( |
858 | "RIO: scanning device on port %d\n", | 956 | "RIO: scanning device on port %d\n", |
859 | port_num); | 957 | port_num); |
958 | rio_enable_rx_tx_port(port, 0, | ||
959 | RIO_ANY_DESTID(port->sys_size), | ||
960 | hopcount, port_num); | ||
860 | rdev->rswitch->port_ok |= (1 << port_num); | 961 | rdev->rswitch->port_ok |= (1 << port_num); |
861 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, | 962 | rio_route_add_entry(rdev, RIO_GLOBAL_TABLE, |
862 | RIO_ANY_DESTID(port->sys_size), | 963 | RIO_ANY_DESTID(port->sys_size), |
@@ -867,19 +968,22 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
867 | return -1; | 968 | return -1; |
868 | 969 | ||
869 | /* Update routing tables */ | 970 | /* Update routing tables */ |
870 | if (next_destid > cur_destid) { | 971 | destid = rio_destid_next(net, cur_destid + 1); |
972 | if (destid != RIO_INVALID_DESTID) { | ||
871 | for (destid = cur_destid; | 973 | for (destid = cur_destid; |
872 | destid < next_destid; destid++) { | 974 | destid < next_destid;) { |
873 | if (destid == port->host_deviceid) | 975 | if (destid != port->host_deviceid) { |
874 | continue; | 976 | rio_route_add_entry(rdev, |
875 | rio_route_add_entry(rdev, | ||
876 | RIO_GLOBAL_TABLE, | 977 | RIO_GLOBAL_TABLE, |
877 | destid, | 978 | destid, |
878 | port_num, | 979 | port_num, |
879 | 0); | 980 | 0); |
880 | rdev->rswitch-> | 981 | rdev->rswitch-> |
881 | route_table[destid] = | 982 | route_table[destid] = |
882 | port_num; | 983 | port_num; |
984 | } | ||
985 | destid = rio_destid_next(net, | ||
986 | destid + 1); | ||
883 | } | 987 | } |
884 | } | 988 | } |
885 | } else { | 989 | } else { |
@@ -905,11 +1009,8 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
905 | rio_init_em(rdev); | 1009 | rio_init_em(rdev); |
906 | 1010 | ||
907 | /* Check for empty switch */ | 1011 | /* Check for empty switch */ |
908 | if (next_destid == sw_destid) { | 1012 | if (next_destid == sw_destid) |
909 | next_destid++; | 1013 | next_destid = rio_destid_alloc(net); |
910 | if (next_destid == port->host_deviceid) | ||
911 | next_destid++; | ||
912 | } | ||
913 | 1014 | ||
914 | rdev->destid = sw_destid; | 1015 | rdev->destid = sw_destid; |
915 | } else | 1016 | } else |
@@ -1047,48 +1148,71 @@ static int rio_mport_is_active(struct rio_mport *port) | |||
1047 | /** | 1148 | /** |
1048 | * rio_alloc_net- Allocate and configure a new RIO network | 1149 | * rio_alloc_net- Allocate and configure a new RIO network |
1049 | * @port: Master port associated with the RIO network | 1150 | * @port: Master port associated with the RIO network |
1151 | * @do_enum: Enumeration/Discovery mode flag | ||
1152 | * @start: logical minimal start id for new net | ||
1050 | * | 1153 | * |
1051 | * Allocates a RIO network structure, initializes per-network | 1154 | * Allocates a RIO network structure, initializes per-network |
1052 | * list heads, and adds the associated master port to the | 1155 | * list heads, and adds the associated master port to the |
1053 | * network list of associated master ports. Returns a | 1156 | * network list of associated master ports. Returns a |
1054 | * RIO network pointer on success or %NULL on failure. | 1157 | * RIO network pointer on success or %NULL on failure. |
1055 | */ | 1158 | */ |
1056 | static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port) | 1159 | static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port, |
1160 | int do_enum, u16 start) | ||
1057 | { | 1161 | { |
1058 | struct rio_net *net; | 1162 | struct rio_net *net; |
1059 | 1163 | ||
1060 | net = kzalloc(sizeof(struct rio_net), GFP_KERNEL); | 1164 | net = kzalloc(sizeof(struct rio_net), GFP_KERNEL); |
1165 | if (net && do_enum) { | ||
1166 | net->destid_table.table = kzalloc( | ||
1167 | BITS_TO_LONGS(RIO_MAX_ROUTE_ENTRIES(port->sys_size)) * | ||
1168 | sizeof(long), | ||
1169 | GFP_KERNEL); | ||
1170 | |||
1171 | if (net->destid_table.table == NULL) { | ||
1172 | pr_err("RIO: failed to allocate destID table\n"); | ||
1173 | kfree(net); | ||
1174 | net = NULL; | ||
1175 | } else { | ||
1176 | net->destid_table.start = start; | ||
1177 | net->destid_table.next = 0; | ||
1178 | net->destid_table.max = | ||
1179 | RIO_MAX_ROUTE_ENTRIES(port->sys_size); | ||
1180 | spin_lock_init(&net->destid_table.lock); | ||
1181 | } | ||
1182 | } | ||
1183 | |||
1061 | if (net) { | 1184 | if (net) { |
1062 | INIT_LIST_HEAD(&net->node); | 1185 | INIT_LIST_HEAD(&net->node); |
1063 | INIT_LIST_HEAD(&net->devices); | 1186 | INIT_LIST_HEAD(&net->devices); |
1187 | INIT_LIST_HEAD(&net->switches); | ||
1064 | INIT_LIST_HEAD(&net->mports); | 1188 | INIT_LIST_HEAD(&net->mports); |
1065 | list_add_tail(&port->nnode, &net->mports); | 1189 | list_add_tail(&port->nnode, &net->mports); |
1066 | net->hport = port; | 1190 | net->hport = port; |
1067 | net->id = next_net++; | 1191 | net->id = port->id; |
1068 | } | 1192 | } |
1069 | return net; | 1193 | return net; |
1070 | } | 1194 | } |
1071 | 1195 | ||
1072 | /** | 1196 | /** |
1073 | * rio_update_route_tables- Updates route tables in switches | 1197 | * rio_update_route_tables- Updates route tables in switches |
1074 | * @port: Master port associated with the RIO network | 1198 | * @net: RIO network to run update on |
1075 | * | 1199 | * |
1076 | * For each enumerated device, ensure that each switch in a system | 1200 | * For each enumerated device, ensure that each switch in a system |
1077 | * has correct routing entries. Add routes for devices that where | 1201 | * has correct routing entries. Add routes for devices that where |
1078 | * unknown dirung the first enumeration pass through the switch. | 1202 | * unknown dirung the first enumeration pass through the switch. |
1079 | */ | 1203 | */ |
1080 | static void rio_update_route_tables(struct rio_mport *port) | 1204 | static void rio_update_route_tables(struct rio_net *net) |
1081 | { | 1205 | { |
1082 | struct rio_dev *rdev, *swrdev; | 1206 | struct rio_dev *rdev, *swrdev; |
1083 | struct rio_switch *rswitch; | 1207 | struct rio_switch *rswitch; |
1084 | u8 sport; | 1208 | u8 sport; |
1085 | u16 destid; | 1209 | u16 destid; |
1086 | 1210 | ||
1087 | list_for_each_entry(rdev, &rio_devices, global_list) { | 1211 | list_for_each_entry(rdev, &net->devices, net_list) { |
1088 | 1212 | ||
1089 | destid = rdev->destid; | 1213 | destid = rdev->destid; |
1090 | 1214 | ||
1091 | list_for_each_entry(rswitch, &rio_switches, node) { | 1215 | list_for_each_entry(rswitch, &net->switches, node) { |
1092 | 1216 | ||
1093 | if (rio_is_switch(rdev) && (rdev->rswitch == rswitch)) | 1217 | if (rio_is_switch(rdev) && (rdev->rswitch == rswitch)) |
1094 | continue; | 1218 | continue; |
@@ -1166,12 +1290,16 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
1166 | 1290 | ||
1167 | /* If master port has an active link, allocate net and enum peers */ | 1291 | /* If master port has an active link, allocate net and enum peers */ |
1168 | if (rio_mport_is_active(mport)) { | 1292 | if (rio_mport_is_active(mport)) { |
1169 | if (!(net = rio_alloc_net(mport))) { | 1293 | net = rio_alloc_net(mport, 1, 0); |
1294 | if (!net) { | ||
1170 | printk(KERN_ERR "RIO: failed to allocate new net\n"); | 1295 | printk(KERN_ERR "RIO: failed to allocate new net\n"); |
1171 | rc = -ENOMEM; | 1296 | rc = -ENOMEM; |
1172 | goto out; | 1297 | goto out; |
1173 | } | 1298 | } |
1174 | 1299 | ||
1300 | /* reserve mport destID in new net */ | ||
1301 | rio_destid_reserve(net, mport->host_deviceid); | ||
1302 | |||
1175 | /* Enable Input Output Port (transmitter reviever) */ | 1303 | /* Enable Input Output Port (transmitter reviever) */ |
1176 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); | 1304 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); |
1177 | 1305 | ||
@@ -1179,17 +1307,21 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
1179 | rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, | 1307 | rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR, |
1180 | next_comptag++); | 1308 | next_comptag++); |
1181 | 1309 | ||
1310 | next_destid = rio_destid_alloc(net); | ||
1311 | |||
1182 | if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { | 1312 | if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) { |
1183 | /* A higher priority host won enumeration, bail. */ | 1313 | /* A higher priority host won enumeration, bail. */ |
1184 | printk(KERN_INFO | 1314 | printk(KERN_INFO |
1185 | "RIO: master port %d device has lost enumeration to a remote host\n", | 1315 | "RIO: master port %d device has lost enumeration to a remote host\n", |
1186 | mport->id); | 1316 | mport->id); |
1187 | rio_clear_locks(mport); | 1317 | rio_clear_locks(net); |
1188 | rc = -EBUSY; | 1318 | rc = -EBUSY; |
1189 | goto out; | 1319 | goto out; |
1190 | } | 1320 | } |
1191 | rio_update_route_tables(mport); | 1321 | /* free the last allocated destID (unused) */ |
1192 | rio_clear_locks(mport); | 1322 | rio_destid_free(net, next_destid); |
1323 | rio_update_route_tables(net); | ||
1324 | rio_clear_locks(net); | ||
1193 | rio_pw_enable(mport, 1); | 1325 | rio_pw_enable(mport, 1); |
1194 | } else { | 1326 | } else { |
1195 | printk(KERN_INFO "RIO: master port %d link inactive\n", | 1327 | printk(KERN_INFO "RIO: master port %d link inactive\n", |
@@ -1203,47 +1335,34 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
1203 | 1335 | ||
1204 | /** | 1336 | /** |
1205 | * rio_build_route_tables- Generate route tables from switch route entries | 1337 | * rio_build_route_tables- Generate route tables from switch route entries |
1338 | * @net: RIO network to run route tables scan on | ||
1206 | * | 1339 | * |
1207 | * For each switch device, generate a route table by copying existing | 1340 | * For each switch device, generate a route table by copying existing |
1208 | * route entries from the switch. | 1341 | * route entries from the switch. |
1209 | */ | 1342 | */ |
1210 | static void rio_build_route_tables(void) | 1343 | static void rio_build_route_tables(struct rio_net *net) |
1211 | { | 1344 | { |
1345 | struct rio_switch *rswitch; | ||
1212 | struct rio_dev *rdev; | 1346 | struct rio_dev *rdev; |
1213 | int i; | 1347 | int i; |
1214 | u8 sport; | 1348 | u8 sport; |
1215 | 1349 | ||
1216 | list_for_each_entry(rdev, &rio_devices, global_list) | 1350 | list_for_each_entry(rswitch, &net->switches, node) { |
1217 | if (rio_is_switch(rdev)) { | 1351 | rdev = sw_to_rio_dev(rswitch); |
1218 | rio_lock_device(rdev->net->hport, rdev->destid, | ||
1219 | rdev->hopcount, 1000); | ||
1220 | for (i = 0; | ||
1221 | i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); | ||
1222 | i++) { | ||
1223 | if (rio_route_get_entry(rdev, | ||
1224 | RIO_GLOBAL_TABLE, i, &sport, 0) < 0) | ||
1225 | continue; | ||
1226 | rdev->rswitch->route_table[i] = sport; | ||
1227 | } | ||
1228 | 1352 | ||
1229 | rio_unlock_device(rdev->net->hport, | 1353 | rio_lock_device(net->hport, rdev->destid, |
1230 | rdev->destid, | 1354 | rdev->hopcount, 1000); |
1231 | rdev->hopcount); | 1355 | for (i = 0; |
1356 | i < RIO_MAX_ROUTE_ENTRIES(net->hport->sys_size); | ||
1357 | i++) { | ||
1358 | if (rio_route_get_entry(rdev, RIO_GLOBAL_TABLE, | ||
1359 | i, &sport, 0) < 0) | ||
1360 | continue; | ||
1361 | rswitch->route_table[i] = sport; | ||
1232 | } | 1362 | } |
1233 | } | ||
1234 | 1363 | ||
1235 | /** | 1364 | rio_unlock_device(net->hport, rdev->destid, rdev->hopcount); |
1236 | * rio_enum_timeout- Signal that enumeration timed out | 1365 | } |
1237 | * @data: Address of timeout flag. | ||
1238 | * | ||
1239 | * When the enumeration complete timer expires, set a flag that | ||
1240 | * signals to the discovery process that enumeration did not | ||
1241 | * complete in a sane amount of time. | ||
1242 | */ | ||
1243 | static void rio_enum_timeout(unsigned long data) | ||
1244 | { | ||
1245 | /* Enumeration timed out, set flag */ | ||
1246 | *(int *)data = 1; | ||
1247 | } | 1366 | } |
1248 | 1367 | ||
1249 | /** | 1368 | /** |
@@ -1259,34 +1378,33 @@ static void rio_enum_timeout(unsigned long data) | |||
1259 | int __devinit rio_disc_mport(struct rio_mport *mport) | 1378 | int __devinit rio_disc_mport(struct rio_mport *mport) |
1260 | { | 1379 | { |
1261 | struct rio_net *net = NULL; | 1380 | struct rio_net *net = NULL; |
1262 | int enum_timeout_flag = 0; | 1381 | unsigned long to_end; |
1263 | 1382 | ||
1264 | printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id, | 1383 | printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id, |
1265 | mport->name); | 1384 | mport->name); |
1266 | 1385 | ||
1267 | /* If master port has an active link, allocate net and discover peers */ | 1386 | /* If master port has an active link, allocate net and discover peers */ |
1268 | if (rio_mport_is_active(mport)) { | 1387 | if (rio_mport_is_active(mport)) { |
1269 | if (!(net = rio_alloc_net(mport))) { | 1388 | pr_debug("RIO: wait for enumeration to complete...\n"); |
1270 | printk(KERN_ERR "RIO: Failed to allocate new net\n"); | ||
1271 | goto bail; | ||
1272 | } | ||
1273 | 1389 | ||
1274 | pr_debug("RIO: wait for enumeration complete..."); | 1390 | to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; |
1275 | 1391 | while (time_before(jiffies, to_end)) { | |
1276 | rio_enum_timer.expires = | 1392 | if (rio_enum_complete(mport)) |
1277 | jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; | 1393 | goto enum_done; |
1278 | rio_enum_timer.data = (unsigned long)&enum_timeout_flag; | 1394 | schedule_timeout_uninterruptible(msecs_to_jiffies(10)); |
1279 | add_timer(&rio_enum_timer); | ||
1280 | while (!rio_enum_complete(mport)) { | ||
1281 | mdelay(1); | ||
1282 | if (enum_timeout_flag) { | ||
1283 | del_timer_sync(&rio_enum_timer); | ||
1284 | goto timeout; | ||
1285 | } | ||
1286 | } | 1395 | } |
1287 | del_timer_sync(&rio_enum_timer); | ||
1288 | 1396 | ||
1289 | pr_debug("done\n"); | 1397 | pr_debug("RIO: discovery timeout on mport %d %s\n", |
1398 | mport->id, mport->name); | ||
1399 | goto bail; | ||
1400 | enum_done: | ||
1401 | pr_debug("RIO: ... enumeration done\n"); | ||
1402 | |||
1403 | net = rio_alloc_net(mport, 0, 0); | ||
1404 | if (!net) { | ||
1405 | printk(KERN_ERR "RIO: Failed to allocate new net\n"); | ||
1406 | goto bail; | ||
1407 | } | ||
1290 | 1408 | ||
1291 | /* Read DestID assigned by enumerator */ | 1409 | /* Read DestID assigned by enumerator */ |
1292 | rio_local_read_config_32(mport, RIO_DID_CSR, | 1410 | rio_local_read_config_32(mport, RIO_DID_CSR, |
@@ -1302,13 +1420,10 @@ int __devinit rio_disc_mport(struct rio_mport *mport) | |||
1302 | goto bail; | 1420 | goto bail; |
1303 | } | 1421 | } |
1304 | 1422 | ||
1305 | rio_build_route_tables(); | 1423 | rio_build_route_tables(net); |
1306 | } | 1424 | } |
1307 | 1425 | ||
1308 | return 0; | 1426 | return 0; |
1309 | 1427 | bail: | |
1310 | timeout: | ||
1311 | pr_debug("timeout\n"); | ||
1312 | bail: | ||
1313 | return -EBUSY; | 1428 | return -EBUSY; |
1314 | } | 1429 | } |
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index c40665a4fa33..d4bd69013c50 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -33,6 +33,7 @@ | |||
33 | 33 | ||
34 | static LIST_HEAD(rio_mports); | 34 | static LIST_HEAD(rio_mports); |
35 | static unsigned char next_portid; | 35 | static unsigned char next_portid; |
36 | static DEFINE_SPINLOCK(rio_mmap_lock); | ||
36 | 37 | ||
37 | /** | 38 | /** |
38 | * rio_local_get_device_id - Get the base/extended device id for a port | 39 | * rio_local_get_device_id - Get the base/extended device id for a port |
@@ -398,6 +399,49 @@ int rio_release_inb_pwrite(struct rio_dev *rdev) | |||
398 | EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); | 399 | EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); |
399 | 400 | ||
400 | /** | 401 | /** |
402 | * rio_map_inb_region -- Map inbound memory region. | ||
403 | * @mport: Master port. | ||
404 | * @lstart: physical address of memory region to be mapped | ||
405 | * @rbase: RIO base address assigned to this window | ||
406 | * @size: Size of the memory region | ||
407 | * @rflags: Flags for mapping. | ||
408 | * | ||
409 | * Return: 0 -- Success. | ||
410 | * | ||
411 | * This function will create the mapping from RIO space to local memory. | ||
412 | */ | ||
413 | int rio_map_inb_region(struct rio_mport *mport, dma_addr_t local, | ||
414 | u64 rbase, u32 size, u32 rflags) | ||
415 | { | ||
416 | int rc = 0; | ||
417 | unsigned long flags; | ||
418 | |||
419 | if (!mport->ops->map_inb) | ||
420 | return -1; | ||
421 | spin_lock_irqsave(&rio_mmap_lock, flags); | ||
422 | rc = mport->ops->map_inb(mport, local, rbase, size, rflags); | ||
423 | spin_unlock_irqrestore(&rio_mmap_lock, flags); | ||
424 | return rc; | ||
425 | } | ||
426 | EXPORT_SYMBOL_GPL(rio_map_inb_region); | ||
427 | |||
428 | /** | ||
429 | * rio_unmap_inb_region -- Unmap the inbound memory region | ||
430 | * @mport: Master port | ||
431 | * @lstart: physical address of memory region to be unmapped | ||
432 | */ | ||
433 | void rio_unmap_inb_region(struct rio_mport *mport, dma_addr_t lstart) | ||
434 | { | ||
435 | unsigned long flags; | ||
436 | if (!mport->ops->unmap_inb) | ||
437 | return; | ||
438 | spin_lock_irqsave(&rio_mmap_lock, flags); | ||
439 | mport->ops->unmap_inb(mport, lstart); | ||
440 | spin_unlock_irqrestore(&rio_mmap_lock, flags); | ||
441 | } | ||
442 | EXPORT_SYMBOL_GPL(rio_unmap_inb_region); | ||
443 | |||
444 | /** | ||
401 | * rio_mport_get_physefb - Helper function that returns register offset | 445 | * rio_mport_get_physefb - Helper function that returns register offset |
402 | * for Physical Layer Extended Features Block. | 446 | * for Physical Layer Extended Features Block. |
403 | * @port: Master port to issue transaction | 447 | * @port: Master port to issue transaction |
@@ -1216,15 +1260,62 @@ static int __devinit rio_init(void) | |||
1216 | return 0; | 1260 | return 0; |
1217 | } | 1261 | } |
1218 | 1262 | ||
1263 | static struct workqueue_struct *rio_wq; | ||
1264 | |||
1265 | struct rio_disc_work { | ||
1266 | struct work_struct work; | ||
1267 | struct rio_mport *mport; | ||
1268 | }; | ||
1269 | |||
1270 | static void __devinit disc_work_handler(struct work_struct *_work) | ||
1271 | { | ||
1272 | struct rio_disc_work *work; | ||
1273 | |||
1274 | work = container_of(_work, struct rio_disc_work, work); | ||
1275 | pr_debug("RIO: discovery work for mport %d %s\n", | ||
1276 | work->mport->id, work->mport->name); | ||
1277 | rio_disc_mport(work->mport); | ||
1278 | |||
1279 | kfree(work); | ||
1280 | } | ||
1281 | |||
1219 | int __devinit rio_init_mports(void) | 1282 | int __devinit rio_init_mports(void) |
1220 | { | 1283 | { |
1221 | struct rio_mport *port; | 1284 | struct rio_mport *port; |
1285 | struct rio_disc_work *work; | ||
1286 | int no_disc = 0; | ||
1222 | 1287 | ||
1223 | list_for_each_entry(port, &rio_mports, node) { | 1288 | list_for_each_entry(port, &rio_mports, node) { |
1224 | if (port->host_deviceid >= 0) | 1289 | if (port->host_deviceid >= 0) |
1225 | rio_enum_mport(port); | 1290 | rio_enum_mport(port); |
1226 | else | 1291 | else if (!no_disc) { |
1227 | rio_disc_mport(port); | 1292 | if (!rio_wq) { |
1293 | rio_wq = alloc_workqueue("riodisc", 0, 0); | ||
1294 | if (!rio_wq) { | ||
1295 | pr_err("RIO: unable allocate rio_wq\n"); | ||
1296 | no_disc = 1; | ||
1297 | continue; | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1301 | work = kzalloc(sizeof *work, GFP_KERNEL); | ||
1302 | if (!work) { | ||
1303 | pr_err("RIO: no memory for work struct\n"); | ||
1304 | no_disc = 1; | ||
1305 | continue; | ||
1306 | } | ||
1307 | |||
1308 | work->mport = port; | ||
1309 | INIT_WORK(&work->work, disc_work_handler); | ||
1310 | queue_work(rio_wq, &work->work); | ||
1311 | } | ||
1312 | } | ||
1313 | |||
1314 | if (rio_wq) { | ||
1315 | pr_debug("RIO: flush discovery workqueue\n"); | ||
1316 | flush_workqueue(rio_wq); | ||
1317 | pr_debug("RIO: flush discovery workqueue finished\n"); | ||
1318 | destroy_workqueue(rio_wq); | ||
1228 | } | 1319 | } |
1229 | 1320 | ||
1230 | rio_init(); | 1321 | rio_init(); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index fabc99a75c65..e069f176a82d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -19,7 +19,6 @@ if RTC_CLASS | |||
19 | 19 | ||
20 | config RTC_HCTOSYS | 20 | config RTC_HCTOSYS |
21 | bool "Set system time from RTC on startup and resume" | 21 | bool "Set system time from RTC on startup and resume" |
22 | depends on RTC_CLASS = y | ||
23 | default y | 22 | default y |
24 | help | 23 | help |
25 | If you say yes here, the system time (wall clock) will be set using | 24 | If you say yes here, the system time (wall clock) will be set using |
@@ -51,7 +50,6 @@ config RTC_HCTOSYS_DEVICE | |||
51 | 50 | ||
52 | config RTC_DEBUG | 51 | config RTC_DEBUG |
53 | bool "RTC debug support" | 52 | bool "RTC debug support" |
54 | depends on RTC_CLASS = y | ||
55 | help | 53 | help |
56 | Say yes here to enable debugging support in the RTC framework | 54 | Say yes here to enable debugging support in the RTC framework |
57 | and individual RTC drivers. | 55 | and individual RTC drivers. |
@@ -61,7 +59,6 @@ comment "RTC interfaces" | |||
61 | config RTC_INTF_SYSFS | 59 | config RTC_INTF_SYSFS |
62 | boolean "/sys/class/rtc/rtcN (sysfs)" | 60 | boolean "/sys/class/rtc/rtcN (sysfs)" |
63 | depends on SYSFS | 61 | depends on SYSFS |
64 | default RTC_CLASS | ||
65 | help | 62 | help |
66 | Say yes here if you want to use your RTCs using sysfs interfaces, | 63 | Say yes here if you want to use your RTCs using sysfs interfaces, |
67 | /sys/class/rtc/rtc0 through /sys/.../rtcN. | 64 | /sys/class/rtc/rtc0 through /sys/.../rtcN. |
@@ -69,19 +66,19 @@ config RTC_INTF_SYSFS | |||
69 | If unsure, say Y. | 66 | If unsure, say Y. |
70 | 67 | ||
71 | config RTC_INTF_PROC | 68 | config RTC_INTF_PROC |
72 | boolean "/proc/driver/rtc (procfs for rtc0)" | 69 | boolean "/proc/driver/rtc (procfs for rtcN)" |
73 | depends on PROC_FS | 70 | depends on PROC_FS |
74 | default RTC_CLASS | ||
75 | help | 71 | help |
76 | Say yes here if you want to use your first RTC through the proc | 72 | Say yes here if you want to use your system clock RTC through |
77 | interface, /proc/driver/rtc. Other RTCs will not be available | 73 | the proc interface, /proc/driver/rtc. |
78 | through that API. | 74 | Other RTCs will not be available through that API. |
75 | If there is no RTC for the system clock, then the first RTC(rtc0) | ||
76 | is used by default. | ||
79 | 77 | ||
80 | If unsure, say Y. | 78 | If unsure, say Y. |
81 | 79 | ||
82 | config RTC_INTF_DEV | 80 | config RTC_INTF_DEV |
83 | boolean "/dev/rtcN (character devices)" | 81 | boolean "/dev/rtcN (character devices)" |
84 | default RTC_CLASS | ||
85 | help | 82 | help |
86 | Say yes here if you want to use your RTCs using the /dev | 83 | Say yes here if you want to use your RTCs using the /dev |
87 | interfaces, which "udev" sets up as /dev/rtc0 through | 84 | interfaces, which "udev" sets up as /dev/rtc0 through |
@@ -127,7 +124,7 @@ if I2C | |||
127 | 124 | ||
128 | config RTC_DRV_88PM860X | 125 | config RTC_DRV_88PM860X |
129 | tristate "Marvell 88PM860x" | 126 | tristate "Marvell 88PM860x" |
130 | depends on RTC_CLASS && I2C && MFD_88PM860X | 127 | depends on I2C && MFD_88PM860X |
131 | help | 128 | help |
132 | If you say yes here you get support for RTC function in Marvell | 129 | If you say yes here you get support for RTC function in Marvell |
133 | 88PM860x chips. | 130 | 88PM860x chips. |
@@ -137,7 +134,7 @@ config RTC_DRV_88PM860X | |||
137 | 134 | ||
138 | config RTC_DRV_88PM80X | 135 | config RTC_DRV_88PM80X |
139 | tristate "Marvell 88PM80x" | 136 | tristate "Marvell 88PM80x" |
140 | depends on RTC_CLASS && I2C && MFD_88PM800 | 137 | depends on I2C && MFD_88PM800 |
141 | help | 138 | help |
142 | If you say yes here you get support for RTC function in Marvell | 139 | If you say yes here you get support for RTC function in Marvell |
143 | 88PM80x chips. | 140 | 88PM80x chips. |
@@ -165,7 +162,7 @@ config RTC_DRV_DS1307 | |||
165 | 162 | ||
166 | config RTC_DRV_DS1374 | 163 | config RTC_DRV_DS1374 |
167 | tristate "Dallas/Maxim DS1374" | 164 | tristate "Dallas/Maxim DS1374" |
168 | depends on RTC_CLASS && I2C | 165 | depends on I2C |
169 | help | 166 | help |
170 | If you say yes here you get support for Dallas Semiconductor | 167 | If you say yes here you get support for Dallas Semiconductor |
171 | DS1374 real-time clock chips. If an interrupt is associated | 168 | DS1374 real-time clock chips. If an interrupt is associated |
@@ -185,7 +182,7 @@ config RTC_DRV_DS1672 | |||
185 | 182 | ||
186 | config RTC_DRV_DS3232 | 183 | config RTC_DRV_DS3232 |
187 | tristate "Dallas/Maxim DS3232" | 184 | tristate "Dallas/Maxim DS3232" |
188 | depends on RTC_CLASS && I2C | 185 | depends on I2C |
189 | help | 186 | help |
190 | If you say yes here you get support for Dallas Semiconductor | 187 | If you say yes here you get support for Dallas Semiconductor |
191 | DS3232 real-time clock chips. If an interrupt is associated | 188 | DS3232 real-time clock chips. If an interrupt is associated |
@@ -203,6 +200,16 @@ config RTC_DRV_MAX6900 | |||
203 | This driver can also be built as a module. If so, the module | 200 | This driver can also be built as a module. If so, the module |
204 | will be called rtc-max6900. | 201 | will be called rtc-max6900. |
205 | 202 | ||
203 | config RTC_DRV_MAX8907 | ||
204 | tristate "Maxim MAX8907" | ||
205 | depends on MFD_MAX8907 | ||
206 | help | ||
207 | If you say yes here you will get support for the | ||
208 | RTC of Maxim MAX8907 PMIC. | ||
209 | |||
210 | This driver can also be built as a module. If so, the module | ||
211 | will be called rtc-max8907. | ||
212 | |||
206 | config RTC_DRV_MAX8925 | 213 | config RTC_DRV_MAX8925 |
207 | tristate "Maxim MAX8925" | 214 | tristate "Maxim MAX8925" |
208 | depends on MFD_MAX8925 | 215 | depends on MFD_MAX8925 |
@@ -325,7 +332,7 @@ config RTC_DRV_TWL92330 | |||
325 | 332 | ||
326 | config RTC_DRV_TWL4030 | 333 | config RTC_DRV_TWL4030 |
327 | tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" | 334 | tristate "TI TWL4030/TWL5030/TWL6030/TPS659x0" |
328 | depends on RTC_CLASS && TWL4030_CORE | 335 | depends on TWL4030_CORE |
329 | help | 336 | help |
330 | If you say yes here you get support for the RTC on the | 337 | If you say yes here you get support for the RTC on the |
331 | TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms. | 338 | TWL4030/TWL5030/TWL6030 family chips, used mostly with OMAP3 platforms. |
@@ -333,6 +340,26 @@ config RTC_DRV_TWL4030 | |||
333 | This driver can also be built as a module. If so, the module | 340 | This driver can also be built as a module. If so, the module |
334 | will be called rtc-twl. | 341 | will be called rtc-twl. |
335 | 342 | ||
343 | config RTC_DRV_TPS65910 | ||
344 | tristate "TI TPS65910 RTC driver" | ||
345 | depends on RTC_CLASS && MFD_TPS65910 | ||
346 | help | ||
347 | If you say yes here you get support for the RTC on the | ||
348 | TPS65910 chips. | ||
349 | |||
350 | This driver can also be built as a module. If so, the module | ||
351 | will be called rtc-tps65910. | ||
352 | |||
353 | config RTC_DRV_RC5T583 | ||
354 | tristate "RICOH 5T583 RTC driver" | ||
355 | depends on MFD_RC5T583 | ||
356 | help | ||
357 | If you say yes here you get support for the RTC on the | ||
358 | RICOH 5T583 chips. | ||
359 | |||
360 | This driver can also be built as a module. If so, the module | ||
361 | will be called rtc-rc5t583. | ||
362 | |||
336 | config RTC_DRV_S35390A | 363 | config RTC_DRV_S35390A |
337 | tristate "Seiko Instruments S-35390A" | 364 | tristate "Seiko Instruments S-35390A" |
338 | select BITREVERSE | 365 | select BITREVERSE |
@@ -538,7 +565,6 @@ config RTC_DRV_DS1302 | |||
538 | 565 | ||
539 | config RTC_DRV_DS1511 | 566 | config RTC_DRV_DS1511 |
540 | tristate "Dallas DS1511" | 567 | tristate "Dallas DS1511" |
541 | depends on RTC_CLASS | ||
542 | help | 568 | help |
543 | If you say yes here you get support for the | 569 | If you say yes here you get support for the |
544 | Dallas DS1511 timekeeping/watchdog chip. | 570 | Dallas DS1511 timekeeping/watchdog chip. |
@@ -583,7 +609,6 @@ config RTC_DRV_EFI | |||
583 | 609 | ||
584 | config RTC_DRV_STK17TA8 | 610 | config RTC_DRV_STK17TA8 |
585 | tristate "Simtek STK17TA8" | 611 | tristate "Simtek STK17TA8" |
586 | depends on RTC_CLASS | ||
587 | help | 612 | help |
588 | If you say yes here you get support for the | 613 | If you say yes here you get support for the |
589 | Simtek STK17TA8 timekeeping chip. | 614 | Simtek STK17TA8 timekeeping chip. |
@@ -658,6 +683,15 @@ config RTC_DRV_V3020 | |||
658 | This driver can also be built as a module. If so, the module | 683 | This driver can also be built as a module. If so, the module |
659 | will be called rtc-v3020. | 684 | will be called rtc-v3020. |
660 | 685 | ||
686 | config RTC_DRV_DS2404 | ||
687 | tristate "Dallas DS2404" | ||
688 | help | ||
689 | If you say yes here you get support for the | ||
690 | Dallas DS2404 RTC chip. | ||
691 | |||
692 | This driver can also be built as a module. If so, the module | ||
693 | will be called rtc-ds2404. | ||
694 | |||
661 | config RTC_DRV_WM831X | 695 | config RTC_DRV_WM831X |
662 | tristate "Wolfson Microelectronics WM831x RTC" | 696 | tristate "Wolfson Microelectronics WM831x RTC" |
663 | depends on MFD_WM831X | 697 | depends on MFD_WM831X |
@@ -704,6 +738,7 @@ config RTC_DRV_AB3100 | |||
704 | config RTC_DRV_AB8500 | 738 | config RTC_DRV_AB8500 |
705 | tristate "ST-Ericsson AB8500 RTC" | 739 | tristate "ST-Ericsson AB8500 RTC" |
706 | depends on AB8500_CORE | 740 | depends on AB8500_CORE |
741 | select RTC_INTF_DEV | ||
707 | select RTC_INTF_DEV_UIE_EMUL | 742 | select RTC_INTF_DEV_UIE_EMUL |
708 | help | 743 | help |
709 | Select this to enable the ST-Ericsson AB8500 power management IC RTC | 744 | Select this to enable the ST-Ericsson AB8500 power management IC RTC |
@@ -711,7 +746,7 @@ config RTC_DRV_AB8500 | |||
711 | 746 | ||
712 | config RTC_DRV_NUC900 | 747 | config RTC_DRV_NUC900 |
713 | tristate "NUC910/NUC920 RTC driver" | 748 | tristate "NUC910/NUC920 RTC driver" |
714 | depends on RTC_CLASS && ARCH_W90X900 | 749 | depends on ARCH_W90X900 |
715 | help | 750 | help |
716 | If you say yes here you get support for the RTC subsystem of the | 751 | If you say yes here you get support for the RTC subsystem of the |
717 | NUC910/NUC920 used in embedded systems. | 752 | NUC910/NUC920 used in embedded systems. |
@@ -731,7 +766,6 @@ config RTC_DRV_DAVINCI | |||
731 | config RTC_DRV_IMXDI | 766 | config RTC_DRV_IMXDI |
732 | tristate "Freescale IMX DryIce Real Time Clock" | 767 | tristate "Freescale IMX DryIce Real Time Clock" |
733 | depends on SOC_IMX25 | 768 | depends on SOC_IMX25 |
734 | depends on RTC_CLASS | ||
735 | help | 769 | help |
736 | Support for Freescale IMX DryIce RTC | 770 | Support for Freescale IMX DryIce RTC |
737 | 771 | ||
@@ -791,7 +825,7 @@ config RTC_DRV_SA1100 | |||
791 | 825 | ||
792 | config RTC_DRV_SH | 826 | config RTC_DRV_SH |
793 | tristate "SuperH On-Chip RTC" | 827 | tristate "SuperH On-Chip RTC" |
794 | depends on RTC_CLASS && SUPERH && HAVE_CLK | 828 | depends on SUPERH && HAVE_CLK |
795 | help | 829 | help |
796 | Say Y here to enable support for the on-chip RTC found in | 830 | Say Y here to enable support for the on-chip RTC found in |
797 | most SuperH processors. | 831 | most SuperH processors. |
@@ -1023,7 +1057,6 @@ config RTC_DRV_MPC5121 | |||
1023 | 1057 | ||
1024 | config RTC_DRV_JZ4740 | 1058 | config RTC_DRV_JZ4740 |
1025 | tristate "Ingenic JZ4740 SoC" | 1059 | tristate "Ingenic JZ4740 SoC" |
1026 | depends on RTC_CLASS | ||
1027 | depends on MACH_JZ4740 | 1060 | depends on MACH_JZ4740 |
1028 | help | 1061 | help |
1029 | If you say yes here you get support for the Ingenic JZ4740 SoC RTC | 1062 | If you say yes here you get support for the Ingenic JZ4740 SoC RTC |
@@ -1053,7 +1086,7 @@ config RTC_DRV_PM8XXX | |||
1053 | 1086 | ||
1054 | config RTC_DRV_TEGRA | 1087 | config RTC_DRV_TEGRA |
1055 | tristate "NVIDIA Tegra Internal RTC driver" | 1088 | tristate "NVIDIA Tegra Internal RTC driver" |
1056 | depends on RTC_CLASS && ARCH_TEGRA | 1089 | depends on ARCH_TEGRA |
1057 | help | 1090 | help |
1058 | If you say yes here you get support for the | 1091 | If you say yes here you get support for the |
1059 | Tegra 200 series internal RTC module. | 1092 | Tegra 200 series internal RTC module. |
@@ -1090,7 +1123,6 @@ config RTC_DRV_LOONGSON1 | |||
1090 | config RTC_DRV_MXC | 1123 | config RTC_DRV_MXC |
1091 | tristate "Freescale MXC Real Time Clock" | 1124 | tristate "Freescale MXC Real Time Clock" |
1092 | depends on ARCH_MXC | 1125 | depends on ARCH_MXC |
1093 | depends on RTC_CLASS | ||
1094 | help | 1126 | help |
1095 | If you say yes here you get support for the Freescale MXC | 1127 | If you say yes here you get support for the Freescale MXC |
1096 | RTC module. | 1128 | RTC module. |
@@ -1098,4 +1130,15 @@ config RTC_DRV_MXC | |||
1098 | This driver can also be built as a module, if so, the module | 1130 | This driver can also be built as a module, if so, the module |
1099 | will be called "rtc-mxc". | 1131 | will be called "rtc-mxc". |
1100 | 1132 | ||
1133 | config RTC_DRV_SNVS | ||
1134 | tristate "Freescale SNVS RTC support" | ||
1135 | depends on HAS_IOMEM | ||
1136 | depends on OF | ||
1137 | help | ||
1138 | If you say yes here you get support for the Freescale SNVS | ||
1139 | Low Power (LP) RTC module. | ||
1140 | |||
1141 | This driver can also be built as a module, if so, the module | ||
1142 | will be called "rtc-snvs". | ||
1143 | |||
1101 | endif # RTC_CLASS | 1144 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 0d5b2b66f90d..56297f0fd388 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -43,6 +43,7 @@ obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | |||
43 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 43 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
44 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 44 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
45 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 45 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
46 | obj-$(CONFIG_RTC_DRV_DS2404) += rtc-ds2404.o | ||
46 | obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o | 47 | obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o |
47 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o | 48 | obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o |
48 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o | 49 | obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o |
@@ -64,6 +65,7 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | |||
64 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 65 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
65 | obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o | 66 | obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o |
66 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 67 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
68 | obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o | ||
67 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o | 69 | obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o |
68 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o | 70 | obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o |
69 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 71 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
@@ -85,6 +87,7 @@ obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o | |||
85 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o | 87 | obj-$(CONFIG_RTC_DRV_PUV3) += rtc-puv3.o |
86 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o | 88 | obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o |
87 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | 89 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o |
90 | obj-$(CONFIG_RTC_DRV_RC5T583) += rtc-rc5t583.o | ||
88 | obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o | 91 | obj-$(CONFIG_RTC_DRV_RP5C01) += rtc-rp5c01.o |
89 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 92 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
90 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 93 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
@@ -96,6 +99,7 @@ obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o | |||
96 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o | 99 | obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o |
97 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o | 100 | obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o |
98 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o | 101 | obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o |
102 | obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o | ||
99 | obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o | 103 | obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o |
100 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | 104 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o |
101 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o | 105 | obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o |
@@ -105,6 +109,7 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o | |||
105 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o | 109 | obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o |
106 | obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o | 110 | obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o |
107 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o | 111 | obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o |
112 | obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o | ||
108 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o | 113 | obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o |
109 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | 114 | obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o |
110 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 115 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index dc4c2748bbc3..f8a0aab218cb 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -31,8 +31,12 @@ static void rtc_device_release(struct device *dev) | |||
31 | kfree(rtc); | 31 | kfree(rtc); |
32 | } | 32 | } |
33 | 33 | ||
34 | #if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE) | 34 | #ifdef CONFIG_RTC_HCTOSYS_DEVICE |
35 | /* Result of the last RTC to system clock attempt. */ | ||
36 | int rtc_hctosys_ret = -ENODEV; | ||
37 | #endif | ||
35 | 38 | ||
39 | #if defined(CONFIG_PM) && defined(CONFIG_RTC_HCTOSYS_DEVICE) | ||
36 | /* | 40 | /* |
37 | * On suspend(), measure the delta between one RTC and the | 41 | * On suspend(), measure the delta between one RTC and the |
38 | * system's wall clock; restore it on resume(). | 42 | * system's wall clock; restore it on resume(). |
@@ -84,6 +88,7 @@ static int rtc_resume(struct device *dev) | |||
84 | struct timespec new_system, new_rtc; | 88 | struct timespec new_system, new_rtc; |
85 | struct timespec sleep_time; | 89 | struct timespec sleep_time; |
86 | 90 | ||
91 | rtc_hctosys_ret = -ENODEV; | ||
87 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 92 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
88 | return 0; | 93 | return 0; |
89 | 94 | ||
@@ -117,6 +122,7 @@ static int rtc_resume(struct device *dev) | |||
117 | 122 | ||
118 | if (sleep_time.tv_sec >= 0) | 123 | if (sleep_time.tv_sec >= 0) |
119 | timekeeping_inject_sleeptime(&sleep_time); | 124 | timekeeping_inject_sleeptime(&sleep_time); |
125 | rtc_hctosys_ret = 0; | ||
120 | return 0; | 126 | return 0; |
121 | } | 127 | } |
122 | 128 | ||
@@ -238,6 +244,7 @@ void rtc_device_unregister(struct rtc_device *rtc) | |||
238 | rtc_proc_del_device(rtc); | 244 | rtc_proc_del_device(rtc); |
239 | device_unregister(&rtc->dev); | 245 | device_unregister(&rtc->dev); |
240 | rtc->ops = NULL; | 246 | rtc->ops = NULL; |
247 | ida_simple_remove(&rtc_ida, rtc->id); | ||
241 | mutex_unlock(&rtc->ops_lock); | 248 | mutex_unlock(&rtc->ops_lock); |
242 | put_device(&rtc->dev); | 249 | put_device(&rtc->dev); |
243 | } | 250 | } |
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index bc90b091f195..4aa60d74004e 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c | |||
@@ -22,8 +22,6 @@ | |||
22 | * the best guess is to add 0.5s. | 22 | * the best guess is to add 0.5s. |
23 | */ | 23 | */ |
24 | 24 | ||
25 | int rtc_hctosys_ret = -ENODEV; | ||
26 | |||
27 | static int __init rtc_hctosys(void) | 25 | static int __init rtc_hctosys(void) |
28 | { | 26 | { |
29 | int err = -ENODEV; | 27 | int err = -ENODEV; |
@@ -56,7 +54,7 @@ static int __init rtc_hctosys(void) | |||
56 | 54 | ||
57 | rtc_tm_to_time(&tm, &tv.tv_sec); | 55 | rtc_tm_to_time(&tm, &tv.tv_sec); |
58 | 56 | ||
59 | do_settimeofday(&tv); | 57 | err = do_settimeofday(&tv); |
60 | 58 | ||
61 | dev_info(rtc->dev.parent, | 59 | dev_info(rtc->dev.parent, |
62 | "setting system clock to " | 60 | "setting system clock to " |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 1dd61f402b04..2dfe7a2fb998 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -473,18 +473,7 @@ static struct platform_driver at91_rtc_driver = { | |||
473 | }, | 473 | }, |
474 | }; | 474 | }; |
475 | 475 | ||
476 | static int __init at91_rtc_init(void) | 476 | module_platform_driver(at91_rtc_driver); |
477 | { | ||
478 | return platform_driver_register(&at91_rtc_driver); | ||
479 | } | ||
480 | module_init(at91_rtc_init); | ||
481 | |||
482 | static void __exit at91_rtc_exit(void) | ||
483 | { | ||
484 | platform_driver_unregister(&at91_rtc_driver); | ||
485 | } | ||
486 | module_exit(at91_rtc_exit); | ||
487 | |||
488 | 477 | ||
489 | MODULE_AUTHOR("Michel Benoit"); | 478 | MODULE_AUTHOR("Michel Benoit"); |
490 | MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x"); | 479 | MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x"); |
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c index 76b2156d3c62..c8115b83e5ab 100644 --- a/drivers/rtc/rtc-coh901331.c +++ b/drivers/rtc/rtc-coh901331.c | |||
@@ -276,8 +276,7 @@ static void coh901331_shutdown(struct platform_device *pdev) | |||
276 | 276 | ||
277 | clk_enable(rtap->clk); | 277 | clk_enable(rtap->clk); |
278 | writel(0, rtap->virtbase + COH901331_IRQ_MASK); | 278 | writel(0, rtap->virtbase + COH901331_IRQ_MASK); |
279 | clk_disable(rtap->clk); | 279 | clk_disable_unprepare(rtap->clk); |
280 | clk_unprepare(rtap->clk); | ||
281 | } | 280 | } |
282 | 281 | ||
283 | static struct platform_driver coh901331_driver = { | 282 | static struct platform_driver coh901331_driver = { |
diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 7fa67d0df172..45d65c0b3a85 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c | |||
@@ -37,8 +37,17 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
37 | unsigned char buf[4]; | 37 | unsigned char buf[4]; |
38 | 38 | ||
39 | struct i2c_msg msgs[] = { | 39 | struct i2c_msg msgs[] = { |
40 | {client->addr, 0, 1, &addr}, /* setup read ptr */ | 40 | {/* setup read ptr */ |
41 | {client->addr, I2C_M_RD, 4, buf}, /* read date */ | 41 | .addr = client->addr, |
42 | .len = 1, | ||
43 | .buf = &addr | ||
44 | }, | ||
45 | {/* read date */ | ||
46 | .addr = client->addr, | ||
47 | .flags = I2C_M_RD, | ||
48 | .len = 4, | ||
49 | .buf = buf | ||
50 | }, | ||
42 | }; | 51 | }; |
43 | 52 | ||
44 | /* read date registers */ | 53 | /* read date registers */ |
@@ -99,8 +108,17 @@ static int ds1672_get_control(struct i2c_client *client, u8 *status) | |||
99 | unsigned char addr = DS1672_REG_CONTROL; | 108 | unsigned char addr = DS1672_REG_CONTROL; |
100 | 109 | ||
101 | struct i2c_msg msgs[] = { | 110 | struct i2c_msg msgs[] = { |
102 | {client->addr, 0, 1, &addr}, /* setup read ptr */ | 111 | {/* setup read ptr */ |
103 | {client->addr, I2C_M_RD, 1, status}, /* read control */ | 112 | .addr = client->addr, |
113 | .len = 1, | ||
114 | .buf = &addr | ||
115 | }, | ||
116 | {/* read control */ | ||
117 | .addr = client->addr, | ||
118 | .flags = I2C_M_RD, | ||
119 | .len = 1, | ||
120 | .buf = status | ||
121 | }, | ||
104 | }; | 122 | }; |
105 | 123 | ||
106 | /* read control register */ | 124 | /* read control register */ |
diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c new file mode 100644 index 000000000000..5ea9df7c8c31 --- /dev/null +++ b/drivers/rtc/rtc-ds2404.c | |||
@@ -0,0 +1,303 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Sven Schnelle <svens@stackframe.org> | ||
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 | |||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/rtc.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/bcd.h> | ||
16 | #include <linux/rtc-ds2404.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/slab.h> | ||
20 | |||
21 | #include <linux/io.h> | ||
22 | |||
23 | #define DS2404_STATUS_REG 0x200 | ||
24 | #define DS2404_CONTROL_REG 0x201 | ||
25 | #define DS2404_RTC_REG 0x202 | ||
26 | |||
27 | #define DS2404_WRITE_SCRATCHPAD_CMD 0x0f | ||
28 | #define DS2404_READ_SCRATCHPAD_CMD 0xaa | ||
29 | #define DS2404_COPY_SCRATCHPAD_CMD 0x55 | ||
30 | #define DS2404_READ_MEMORY_CMD 0xf0 | ||
31 | |||
32 | struct ds2404; | ||
33 | |||
34 | struct ds2404_chip_ops { | ||
35 | int (*map_io)(struct ds2404 *chip, struct platform_device *pdev, | ||
36 | struct ds2404_platform_data *pdata); | ||
37 | void (*unmap_io)(struct ds2404 *chip); | ||
38 | }; | ||
39 | |||
40 | #define DS2404_RST 0 | ||
41 | #define DS2404_CLK 1 | ||
42 | #define DS2404_DQ 2 | ||
43 | |||
44 | struct ds2404_gpio { | ||
45 | const char *name; | ||
46 | unsigned int gpio; | ||
47 | }; | ||
48 | |||
49 | struct ds2404 { | ||
50 | struct ds2404_gpio *gpio; | ||
51 | struct ds2404_chip_ops *ops; | ||
52 | struct rtc_device *rtc; | ||
53 | }; | ||
54 | |||
55 | static struct ds2404_gpio ds2404_gpio[] = { | ||
56 | { "RTC RST", 0 }, | ||
57 | { "RTC CLK", 0 }, | ||
58 | { "RTC DQ", 0 }, | ||
59 | }; | ||
60 | |||
61 | static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev, | ||
62 | struct ds2404_platform_data *pdata) | ||
63 | { | ||
64 | int i, err; | ||
65 | |||
66 | ds2404_gpio[DS2404_RST].gpio = pdata->gpio_rst; | ||
67 | ds2404_gpio[DS2404_CLK].gpio = pdata->gpio_clk; | ||
68 | ds2404_gpio[DS2404_DQ].gpio = pdata->gpio_dq; | ||
69 | |||
70 | for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) { | ||
71 | err = gpio_request(ds2404_gpio[i].gpio, ds2404_gpio[i].name); | ||
72 | if (err) { | ||
73 | printk(KERN_ERR "error mapping gpio %s: %d\n", | ||
74 | ds2404_gpio[i].name, err); | ||
75 | goto err_request; | ||
76 | } | ||
77 | if (i != DS2404_DQ) | ||
78 | gpio_direction_output(ds2404_gpio[i].gpio, 1); | ||
79 | } | ||
80 | |||
81 | chip->gpio = ds2404_gpio; | ||
82 | return 0; | ||
83 | |||
84 | err_request: | ||
85 | while (--i >= 0) | ||
86 | gpio_free(ds2404_gpio[i].gpio); | ||
87 | return err; | ||
88 | } | ||
89 | |||
90 | static void ds2404_gpio_unmap(struct ds2404 *chip) | ||
91 | { | ||
92 | int i; | ||
93 | |||
94 | for (i = 0; i < ARRAY_SIZE(ds2404_gpio); i++) | ||
95 | gpio_free(ds2404_gpio[i].gpio); | ||
96 | } | ||
97 | |||
98 | static struct ds2404_chip_ops ds2404_gpio_ops = { | ||
99 | .map_io = ds2404_gpio_map, | ||
100 | .unmap_io = ds2404_gpio_unmap, | ||
101 | }; | ||
102 | |||
103 | static void ds2404_reset(struct device *dev) | ||
104 | { | ||
105 | gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 0); | ||
106 | udelay(1000); | ||
107 | gpio_set_value(ds2404_gpio[DS2404_RST].gpio, 1); | ||
108 | gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0); | ||
109 | gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 0); | ||
110 | udelay(10); | ||
111 | } | ||
112 | |||
113 | static void ds2404_write_byte(struct device *dev, u8 byte) | ||
114 | { | ||
115 | int i; | ||
116 | |||
117 | gpio_direction_output(ds2404_gpio[DS2404_DQ].gpio, 1); | ||
118 | for (i = 0; i < 8; i++) { | ||
119 | gpio_set_value(ds2404_gpio[DS2404_DQ].gpio, byte & (1 << i)); | ||
120 | udelay(10); | ||
121 | gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1); | ||
122 | udelay(10); | ||
123 | gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0); | ||
124 | udelay(10); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | static u8 ds2404_read_byte(struct device *dev) | ||
129 | { | ||
130 | int i; | ||
131 | u8 ret = 0; | ||
132 | |||
133 | gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio); | ||
134 | |||
135 | for (i = 0; i < 8; i++) { | ||
136 | gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 0); | ||
137 | udelay(10); | ||
138 | if (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio)) | ||
139 | ret |= 1 << i; | ||
140 | gpio_set_value(ds2404_gpio[DS2404_CLK].gpio, 1); | ||
141 | udelay(10); | ||
142 | } | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static void ds2404_read_memory(struct device *dev, u16 offset, | ||
147 | int length, u8 *out) | ||
148 | { | ||
149 | ds2404_reset(dev); | ||
150 | ds2404_write_byte(dev, DS2404_READ_MEMORY_CMD); | ||
151 | ds2404_write_byte(dev, offset & 0xff); | ||
152 | ds2404_write_byte(dev, (offset >> 8) & 0xff); | ||
153 | while (length--) | ||
154 | *out++ = ds2404_read_byte(dev); | ||
155 | } | ||
156 | |||
157 | static void ds2404_write_memory(struct device *dev, u16 offset, | ||
158 | int length, u8 *out) | ||
159 | { | ||
160 | int i; | ||
161 | u8 ta01, ta02, es; | ||
162 | |||
163 | ds2404_reset(dev); | ||
164 | ds2404_write_byte(dev, DS2404_WRITE_SCRATCHPAD_CMD); | ||
165 | ds2404_write_byte(dev, offset & 0xff); | ||
166 | ds2404_write_byte(dev, (offset >> 8) & 0xff); | ||
167 | |||
168 | for (i = 0; i < length; i++) | ||
169 | ds2404_write_byte(dev, out[i]); | ||
170 | |||
171 | ds2404_reset(dev); | ||
172 | ds2404_write_byte(dev, DS2404_READ_SCRATCHPAD_CMD); | ||
173 | |||
174 | ta01 = ds2404_read_byte(dev); | ||
175 | ta02 = ds2404_read_byte(dev); | ||
176 | es = ds2404_read_byte(dev); | ||
177 | |||
178 | for (i = 0; i < length; i++) { | ||
179 | if (out[i] != ds2404_read_byte(dev)) { | ||
180 | printk(KERN_ERR "read invalid data\n"); | ||
181 | return; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | ds2404_reset(dev); | ||
186 | ds2404_write_byte(dev, DS2404_COPY_SCRATCHPAD_CMD); | ||
187 | ds2404_write_byte(dev, ta01); | ||
188 | ds2404_write_byte(dev, ta02); | ||
189 | ds2404_write_byte(dev, es); | ||
190 | |||
191 | gpio_direction_input(ds2404_gpio[DS2404_DQ].gpio); | ||
192 | while (gpio_get_value(ds2404_gpio[DS2404_DQ].gpio)) | ||
193 | ; | ||
194 | } | ||
195 | |||
196 | static void ds2404_enable_osc(struct device *dev) | ||
197 | { | ||
198 | u8 in[1] = { 0x10 }; /* enable oscillator */ | ||
199 | ds2404_write_memory(dev, 0x201, 1, in); | ||
200 | } | ||
201 | |||
202 | static int ds2404_read_time(struct device *dev, struct rtc_time *dt) | ||
203 | { | ||
204 | unsigned long time = 0; | ||
205 | |||
206 | ds2404_read_memory(dev, 0x203, 4, (u8 *)&time); | ||
207 | time = le32_to_cpu(time); | ||
208 | |||
209 | rtc_time_to_tm(time, dt); | ||
210 | return rtc_valid_tm(dt); | ||
211 | } | ||
212 | |||
213 | static int ds2404_set_mmss(struct device *dev, unsigned long secs) | ||
214 | { | ||
215 | u32 time = cpu_to_le32(secs); | ||
216 | ds2404_write_memory(dev, 0x203, 4, (u8 *)&time); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static const struct rtc_class_ops ds2404_rtc_ops = { | ||
221 | .read_time = ds2404_read_time, | ||
222 | .set_mmss = ds2404_set_mmss, | ||
223 | }; | ||
224 | |||
225 | static int rtc_probe(struct platform_device *pdev) | ||
226 | { | ||
227 | struct ds2404_platform_data *pdata = pdev->dev.platform_data; | ||
228 | struct ds2404 *chip; | ||
229 | int retval = -EBUSY; | ||
230 | |||
231 | chip = kzalloc(sizeof(struct ds2404), GFP_KERNEL); | ||
232 | if (!chip) | ||
233 | return -ENOMEM; | ||
234 | |||
235 | chip->ops = &ds2404_gpio_ops; | ||
236 | |||
237 | retval = chip->ops->map_io(chip, pdev, pdata); | ||
238 | if (retval) | ||
239 | goto err_chip; | ||
240 | |||
241 | dev_info(&pdev->dev, "using GPIOs RST:%d, CLK:%d, DQ:%d\n", | ||
242 | chip->gpio[DS2404_RST].gpio, chip->gpio[DS2404_CLK].gpio, | ||
243 | chip->gpio[DS2404_DQ].gpio); | ||
244 | |||
245 | platform_set_drvdata(pdev, chip); | ||
246 | |||
247 | chip->rtc = rtc_device_register("ds2404", | ||
248 | &pdev->dev, &ds2404_rtc_ops, THIS_MODULE); | ||
249 | if (IS_ERR(chip->rtc)) { | ||
250 | retval = PTR_ERR(chip->rtc); | ||
251 | goto err_io; | ||
252 | } | ||
253 | |||
254 | ds2404_enable_osc(&pdev->dev); | ||
255 | return 0; | ||
256 | |||
257 | err_io: | ||
258 | chip->ops->unmap_io(chip); | ||
259 | err_chip: | ||
260 | kfree(chip); | ||
261 | return retval; | ||
262 | } | ||
263 | |||
264 | static int rtc_remove(struct platform_device *dev) | ||
265 | { | ||
266 | struct ds2404 *chip = platform_get_drvdata(dev); | ||
267 | struct rtc_device *rtc = chip->rtc; | ||
268 | |||
269 | if (rtc) | ||
270 | rtc_device_unregister(rtc); | ||
271 | |||
272 | chip->ops->unmap_io(chip); | ||
273 | kfree(chip); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static struct platform_driver rtc_device_driver = { | ||
279 | .probe = rtc_probe, | ||
280 | .remove = rtc_remove, | ||
281 | .driver = { | ||
282 | .name = "ds2404", | ||
283 | .owner = THIS_MODULE, | ||
284 | }, | ||
285 | }; | ||
286 | |||
287 | static __init int ds2404_init(void) | ||
288 | { | ||
289 | return platform_driver_register(&rtc_device_driver); | ||
290 | } | ||
291 | |||
292 | static __exit void ds2404_exit(void) | ||
293 | { | ||
294 | platform_driver_unregister(&rtc_device_driver); | ||
295 | } | ||
296 | |||
297 | module_init(ds2404_init); | ||
298 | module_exit(ds2404_exit); | ||
299 | |||
300 | MODULE_DESCRIPTION("DS2404 RTC"); | ||
301 | MODULE_AUTHOR("Sven Schnelle"); | ||
302 | MODULE_LICENSE("GPL"); | ||
303 | MODULE_ALIAS("platform:ds2404"); | ||
diff --git a/drivers/rtc/rtc-em3027.c b/drivers/rtc/rtc-em3027.c index 0104ea7ebe50..f6c24ce35d36 100644 --- a/drivers/rtc/rtc-em3027.c +++ b/drivers/rtc/rtc-em3027.c | |||
@@ -49,8 +49,17 @@ static int em3027_get_time(struct device *dev, struct rtc_time *tm) | |||
49 | unsigned char buf[7]; | 49 | unsigned char buf[7]; |
50 | 50 | ||
51 | struct i2c_msg msgs[] = { | 51 | struct i2c_msg msgs[] = { |
52 | {client->addr, 0, 1, &addr}, /* setup read addr */ | 52 | {/* setup read addr */ |
53 | {client->addr, I2C_M_RD, 7, buf}, /* read time/date */ | 53 | .addr = client->addr, |
54 | .len = 1, | ||
55 | .buf = &addr | ||
56 | }, | ||
57 | {/* read time/date */ | ||
58 | .addr = client->addr, | ||
59 | .flags = I2C_M_RD, | ||
60 | .len = 7, | ||
61 | .buf = buf | ||
62 | }, | ||
54 | }; | 63 | }; |
55 | 64 | ||
56 | /* read time/date registers */ | 65 | /* read time/date registers */ |
@@ -76,7 +85,9 @@ static int em3027_set_time(struct device *dev, struct rtc_time *tm) | |||
76 | unsigned char buf[8]; | 85 | unsigned char buf[8]; |
77 | 86 | ||
78 | struct i2c_msg msg = { | 87 | struct i2c_msg msg = { |
79 | client->addr, 0, 8, buf, /* write time/date */ | 88 | .addr = client->addr, |
89 | .len = 8, | ||
90 | .buf = buf, /* write time/date */ | ||
80 | }; | 91 | }; |
81 | 92 | ||
82 | buf[0] = EM3027_REG_WATCH_SEC; | 93 | buf[0] = EM3027_REG_WATCH_SEC; |
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index dd2aeee6c66a..26c81f233606 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c | |||
@@ -68,9 +68,17 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], | |||
68 | { | 68 | { |
69 | u8 reg_addr[1] = { reg }; | 69 | u8 reg_addr[1] = { reg }; |
70 | struct i2c_msg msgs[2] = { | 70 | struct i2c_msg msgs[2] = { |
71 | {client->addr, 0, sizeof(reg_addr), reg_addr} | 71 | { |
72 | , | 72 | .addr = client->addr, |
73 | {client->addr, I2C_M_RD, len, buf} | 73 | .len = sizeof(reg_addr), |
74 | .buf = reg_addr | ||
75 | }, | ||
76 | { | ||
77 | .addr = client->addr, | ||
78 | .flags = I2C_M_RD, | ||
79 | .len = len, | ||
80 | .buf = buf | ||
81 | } | ||
74 | }; | 82 | }; |
75 | int ret; | 83 | int ret; |
76 | 84 | ||
@@ -90,7 +98,11 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], | |||
90 | { | 98 | { |
91 | u8 i2c_buf[ISL1208_REG_USR2 + 2]; | 99 | u8 i2c_buf[ISL1208_REG_USR2 + 2]; |
92 | struct i2c_msg msgs[1] = { | 100 | struct i2c_msg msgs[1] = { |
93 | {client->addr, 0, len + 1, i2c_buf} | 101 | { |
102 | .addr = client->addr, | ||
103 | .len = len + 1, | ||
104 | .buf = i2c_buf | ||
105 | } | ||
94 | }; | 106 | }; |
95 | int ret; | 107 | int ret; |
96 | 108 | ||
@@ -697,6 +709,7 @@ isl1208_remove(struct i2c_client *client) | |||
697 | 709 | ||
698 | static const struct i2c_device_id isl1208_id[] = { | 710 | static const struct i2c_device_id isl1208_id[] = { |
699 | { "isl1208", 0 }, | 711 | { "isl1208", 0 }, |
712 | { "isl1218", 0 }, | ||
700 | { } | 713 | { } |
701 | }; | 714 | }; |
702 | MODULE_DEVICE_TABLE(i2c, isl1208_id); | 715 | MODULE_DEVICE_TABLE(i2c, isl1208_id); |
diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 05ab227eeff7..1224182d3eab 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c | |||
@@ -42,7 +42,7 @@ struct jz4740_rtc { | |||
42 | 42 | ||
43 | struct rtc_device *rtc; | 43 | struct rtc_device *rtc; |
44 | 44 | ||
45 | unsigned int irq; | 45 | int irq; |
46 | 46 | ||
47 | spinlock_t lock; | 47 | spinlock_t lock; |
48 | }; | 48 | }; |
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 4e0f84af99a7..b885bcd08908 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -213,163 +213,14 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
213 | return m41t80_set_datetime(to_i2c_client(dev), tm); | 213 | return m41t80_set_datetime(to_i2c_client(dev), tm); |
214 | } | 214 | } |
215 | 215 | ||
216 | static int m41t80_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | 216 | /* |
217 | { | 217 | * XXX - m41t80 alarm functionality is reported broken. |
218 | struct i2c_client *client = to_i2c_client(dev); | 218 | * until it is fixed, don't register alarm functions. |
219 | int rc; | 219 | */ |
220 | |||
221 | rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); | ||
222 | if (rc < 0) | ||
223 | goto err; | ||
224 | |||
225 | if (enabled) | ||
226 | rc |= M41T80_ALMON_AFE; | ||
227 | else | ||
228 | rc &= ~M41T80_ALMON_AFE; | ||
229 | |||
230 | if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0) | ||
231 | goto err; | ||
232 | |||
233 | return 0; | ||
234 | err: | ||
235 | return -EIO; | ||
236 | } | ||
237 | |||
238 | static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
239 | { | ||
240 | struct i2c_client *client = to_i2c_client(dev); | ||
241 | u8 wbuf[1 + M41T80_ALARM_REG_SIZE]; | ||
242 | u8 *buf = &wbuf[1]; | ||
243 | u8 *reg = buf - M41T80_REG_ALARM_MON; | ||
244 | u8 dt_addr[1] = { M41T80_REG_ALARM_MON }; | ||
245 | struct i2c_msg msgs_in[] = { | ||
246 | { | ||
247 | .addr = client->addr, | ||
248 | .flags = 0, | ||
249 | .len = 1, | ||
250 | .buf = dt_addr, | ||
251 | }, | ||
252 | { | ||
253 | .addr = client->addr, | ||
254 | .flags = I2C_M_RD, | ||
255 | .len = M41T80_ALARM_REG_SIZE, | ||
256 | .buf = buf, | ||
257 | }, | ||
258 | }; | ||
259 | struct i2c_msg msgs[] = { | ||
260 | { | ||
261 | .addr = client->addr, | ||
262 | .flags = 0, | ||
263 | .len = 1 + M41T80_ALARM_REG_SIZE, | ||
264 | .buf = wbuf, | ||
265 | }, | ||
266 | }; | ||
267 | |||
268 | if (i2c_transfer(client->adapter, msgs_in, 2) < 0) { | ||
269 | dev_err(&client->dev, "read error\n"); | ||
270 | return -EIO; | ||
271 | } | ||
272 | reg[M41T80_REG_ALARM_MON] &= ~(0x1f | M41T80_ALMON_AFE); | ||
273 | reg[M41T80_REG_ALARM_DAY] = 0; | ||
274 | reg[M41T80_REG_ALARM_HOUR] &= ~(0x3f | 0x80); | ||
275 | reg[M41T80_REG_ALARM_MIN] = 0; | ||
276 | reg[M41T80_REG_ALARM_SEC] = 0; | ||
277 | |||
278 | wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */ | ||
279 | reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ? | ||
280 | bin2bcd(t->time.tm_sec) : 0x80; | ||
281 | reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ? | ||
282 | bin2bcd(t->time.tm_min) : 0x80; | ||
283 | reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ? | ||
284 | bin2bcd(t->time.tm_hour) : 0x80; | ||
285 | reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ? | ||
286 | bin2bcd(t->time.tm_mday) : 0x80; | ||
287 | if (t->time.tm_mon >= 0) | ||
288 | reg[M41T80_REG_ALARM_MON] |= bin2bcd(t->time.tm_mon + 1); | ||
289 | else | ||
290 | reg[M41T80_REG_ALARM_DAY] |= 0x40; | ||
291 | |||
292 | if (i2c_transfer(client->adapter, msgs, 1) != 1) { | ||
293 | dev_err(&client->dev, "write error\n"); | ||
294 | return -EIO; | ||
295 | } | ||
296 | |||
297 | if (t->enabled) { | ||
298 | reg[M41T80_REG_ALARM_MON] |= M41T80_ALMON_AFE; | ||
299 | if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, | ||
300 | reg[M41T80_REG_ALARM_MON]) < 0) { | ||
301 | dev_err(&client->dev, "write error\n"); | ||
302 | return -EIO; | ||
303 | } | ||
304 | } | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t) | ||
309 | { | ||
310 | struct i2c_client *client = to_i2c_client(dev); | ||
311 | u8 buf[M41T80_ALARM_REG_SIZE + 1]; /* all alarm regs and flags */ | ||
312 | u8 dt_addr[1] = { M41T80_REG_ALARM_MON }; | ||
313 | u8 *reg = buf - M41T80_REG_ALARM_MON; | ||
314 | struct i2c_msg msgs[] = { | ||
315 | { | ||
316 | .addr = client->addr, | ||
317 | .flags = 0, | ||
318 | .len = 1, | ||
319 | .buf = dt_addr, | ||
320 | }, | ||
321 | { | ||
322 | .addr = client->addr, | ||
323 | .flags = I2C_M_RD, | ||
324 | .len = M41T80_ALARM_REG_SIZE + 1, | ||
325 | .buf = buf, | ||
326 | }, | ||
327 | }; | ||
328 | |||
329 | if (i2c_transfer(client->adapter, msgs, 2) < 0) { | ||
330 | dev_err(&client->dev, "read error\n"); | ||
331 | return -EIO; | ||
332 | } | ||
333 | t->time.tm_sec = -1; | ||
334 | t->time.tm_min = -1; | ||
335 | t->time.tm_hour = -1; | ||
336 | t->time.tm_mday = -1; | ||
337 | t->time.tm_mon = -1; | ||
338 | if (!(reg[M41T80_REG_ALARM_SEC] & 0x80)) | ||
339 | t->time.tm_sec = bcd2bin(reg[M41T80_REG_ALARM_SEC] & 0x7f); | ||
340 | if (!(reg[M41T80_REG_ALARM_MIN] & 0x80)) | ||
341 | t->time.tm_min = bcd2bin(reg[M41T80_REG_ALARM_MIN] & 0x7f); | ||
342 | if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80)) | ||
343 | t->time.tm_hour = bcd2bin(reg[M41T80_REG_ALARM_HOUR] & 0x3f); | ||
344 | if (!(reg[M41T80_REG_ALARM_DAY] & 0x80)) | ||
345 | t->time.tm_mday = bcd2bin(reg[M41T80_REG_ALARM_DAY] & 0x3f); | ||
346 | if (!(reg[M41T80_REG_ALARM_DAY] & 0x40)) | ||
347 | t->time.tm_mon = bcd2bin(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1; | ||
348 | t->time.tm_year = -1; | ||
349 | t->time.tm_wday = -1; | ||
350 | t->time.tm_yday = -1; | ||
351 | t->time.tm_isdst = -1; | ||
352 | t->enabled = !!(reg[M41T80_REG_ALARM_MON] & M41T80_ALMON_AFE); | ||
353 | t->pending = !!(reg[M41T80_REG_FLAGS] & M41T80_FLAGS_AF); | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static struct rtc_class_ops m41t80_rtc_ops = { | 220 | static struct rtc_class_ops m41t80_rtc_ops = { |
358 | .read_time = m41t80_rtc_read_time, | 221 | .read_time = m41t80_rtc_read_time, |
359 | .set_time = m41t80_rtc_set_time, | 222 | .set_time = m41t80_rtc_set_time, |
360 | /* | ||
361 | * XXX - m41t80 alarm functionality is reported broken. | ||
362 | * until it is fixed, don't register alarm functions. | ||
363 | * | ||
364 | .read_alarm = m41t80_rtc_read_alarm, | ||
365 | .set_alarm = m41t80_rtc_set_alarm, | ||
366 | */ | ||
367 | .proc = m41t80_rtc_proc, | 223 | .proc = m41t80_rtc_proc, |
368 | /* | ||
369 | * See above comment on broken alarm | ||
370 | * | ||
371 | .alarm_irq_enable = m41t80_rtc_alarm_irq_enable, | ||
372 | */ | ||
373 | }; | 224 | }; |
374 | 225 | ||
375 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) | 226 | #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) |
diff --git a/drivers/rtc/rtc-max8907.c b/drivers/rtc/rtc-max8907.c new file mode 100644 index 000000000000..e094ffa434f8 --- /dev/null +++ b/drivers/rtc/rtc-max8907.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * RTC driver for Maxim MAX8907 | ||
3 | * | ||
4 | * Copyright (c) 2011-2012, NVIDIA Corporation. | ||
5 | * | ||
6 | * Based on drivers/rtc/rtc-max8925.c, | ||
7 | * Copyright (C) 2009-2010 Marvell International Ltd. | ||
8 | * | ||
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 | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/bcd.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/mfd/max8907.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/rtc.h> | ||
21 | #include <linux/slab.h> | ||
22 | |||
23 | enum { | ||
24 | RTC_SEC = 0, | ||
25 | RTC_MIN, | ||
26 | RTC_HOUR, | ||
27 | RTC_WEEKDAY, | ||
28 | RTC_DATE, | ||
29 | RTC_MONTH, | ||
30 | RTC_YEAR1, | ||
31 | RTC_YEAR2, | ||
32 | }; | ||
33 | |||
34 | #define TIME_NUM 8 | ||
35 | #define ALARM_1SEC (1 << 7) | ||
36 | #define HOUR_12 (1 << 7) | ||
37 | #define HOUR_AM_PM (1 << 5) | ||
38 | #define ALARM0_IRQ (1 << 3) | ||
39 | #define ALARM1_IRQ (1 << 2) | ||
40 | #define ALARM0_STATUS (1 << 2) | ||
41 | #define ALARM1_STATUS (1 << 1) | ||
42 | |||
43 | struct max8907_rtc { | ||
44 | struct max8907 *max8907; | ||
45 | struct regmap *regmap; | ||
46 | struct rtc_device *rtc_dev; | ||
47 | int irq; | ||
48 | }; | ||
49 | |||
50 | static irqreturn_t max8907_irq_handler(int irq, void *data) | ||
51 | { | ||
52 | struct max8907_rtc *rtc = data; | ||
53 | |||
54 | regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); | ||
55 | |||
56 | rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); | ||
57 | |||
58 | return IRQ_HANDLED; | ||
59 | } | ||
60 | |||
61 | static void regs_to_tm(u8 *regs, struct rtc_time *tm) | ||
62 | { | ||
63 | tm->tm_year = bcd2bin(regs[RTC_YEAR2]) * 100 + | ||
64 | bcd2bin(regs[RTC_YEAR1]) - 1900; | ||
65 | tm->tm_mon = bcd2bin(regs[RTC_MONTH] & 0x1f) - 1; | ||
66 | tm->tm_mday = bcd2bin(regs[RTC_DATE] & 0x3f); | ||
67 | tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07) - 1; | ||
68 | if (regs[RTC_HOUR] & HOUR_12) { | ||
69 | tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x01f); | ||
70 | if (tm->tm_hour == 12) | ||
71 | tm->tm_hour = 0; | ||
72 | if (regs[RTC_HOUR] & HOUR_AM_PM) | ||
73 | tm->tm_hour += 12; | ||
74 | } else { | ||
75 | tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x03f); | ||
76 | } | ||
77 | tm->tm_min = bcd2bin(regs[RTC_MIN] & 0x7f); | ||
78 | tm->tm_sec = bcd2bin(regs[RTC_SEC] & 0x7f); | ||
79 | } | ||
80 | |||
81 | static void tm_to_regs(struct rtc_time *tm, u8 *regs) | ||
82 | { | ||
83 | u8 high, low; | ||
84 | |||
85 | high = (tm->tm_year + 1900) / 100; | ||
86 | low = tm->tm_year % 100; | ||
87 | regs[RTC_YEAR2] = bin2bcd(high); | ||
88 | regs[RTC_YEAR1] = bin2bcd(low); | ||
89 | regs[RTC_MONTH] = bin2bcd(tm->tm_mon + 1); | ||
90 | regs[RTC_DATE] = bin2bcd(tm->tm_mday); | ||
91 | regs[RTC_WEEKDAY] = tm->tm_wday + 1; | ||
92 | regs[RTC_HOUR] = bin2bcd(tm->tm_hour); | ||
93 | regs[RTC_MIN] = bin2bcd(tm->tm_min); | ||
94 | regs[RTC_SEC] = bin2bcd(tm->tm_sec); | ||
95 | } | ||
96 | |||
97 | static int max8907_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
98 | { | ||
99 | struct max8907_rtc *rtc = dev_get_drvdata(dev); | ||
100 | u8 regs[TIME_NUM]; | ||
101 | int ret; | ||
102 | |||
103 | ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_RTC_SEC, regs, | ||
104 | TIME_NUM); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | |||
108 | regs_to_tm(regs, tm); | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int max8907_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
114 | { | ||
115 | struct max8907_rtc *rtc = dev_get_drvdata(dev); | ||
116 | u8 regs[TIME_NUM]; | ||
117 | |||
118 | tm_to_regs(tm, regs); | ||
119 | |||
120 | return regmap_bulk_write(rtc->regmap, MAX8907_REG_RTC_SEC, regs, | ||
121 | TIME_NUM); | ||
122 | } | ||
123 | |||
124 | static int max8907_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
125 | { | ||
126 | struct max8907_rtc *rtc = dev_get_drvdata(dev); | ||
127 | u8 regs[TIME_NUM]; | ||
128 | unsigned int val; | ||
129 | int ret; | ||
130 | |||
131 | ret = regmap_bulk_read(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs, | ||
132 | TIME_NUM); | ||
133 | if (ret < 0) | ||
134 | return ret; | ||
135 | |||
136 | regs_to_tm(regs, &alrm->time); | ||
137 | |||
138 | ret = regmap_read(rtc->regmap, MAX8907_REG_ALARM0_CNTL, &val); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | |||
142 | alrm->enabled = !!(val & 0x7f); | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int max8907_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
148 | { | ||
149 | struct max8907_rtc *rtc = dev_get_drvdata(dev); | ||
150 | u8 regs[TIME_NUM]; | ||
151 | int ret; | ||
152 | |||
153 | tm_to_regs(&alrm->time, regs); | ||
154 | |||
155 | /* Disable alarm while we update the target time */ | ||
156 | ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); | ||
157 | if (ret < 0) | ||
158 | return ret; | ||
159 | |||
160 | ret = regmap_bulk_write(rtc->regmap, MAX8907_REG_ALARM0_SEC, regs, | ||
161 | TIME_NUM); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | if (alrm->enabled) | ||
166 | ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, | ||
167 | 0x7f, 0x7f); | ||
168 | |||
169 | return ret; | ||
170 | } | ||
171 | |||
172 | static const struct rtc_class_ops max8907_rtc_ops = { | ||
173 | .read_time = max8907_rtc_read_time, | ||
174 | .set_time = max8907_rtc_set_time, | ||
175 | .read_alarm = max8907_rtc_read_alarm, | ||
176 | .set_alarm = max8907_rtc_set_alarm, | ||
177 | }; | ||
178 | |||
179 | static int __devinit max8907_rtc_probe(struct platform_device *pdev) | ||
180 | { | ||
181 | struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent); | ||
182 | struct max8907_rtc *rtc; | ||
183 | int ret; | ||
184 | |||
185 | rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); | ||
186 | if (!rtc) | ||
187 | return -ENOMEM; | ||
188 | platform_set_drvdata(pdev, rtc); | ||
189 | |||
190 | rtc->max8907 = max8907; | ||
191 | rtc->regmap = max8907->regmap_rtc; | ||
192 | |||
193 | rtc->rtc_dev = rtc_device_register("max8907-rtc", &pdev->dev, | ||
194 | &max8907_rtc_ops, THIS_MODULE); | ||
195 | if (IS_ERR(rtc->rtc_dev)) { | ||
196 | ret = PTR_ERR(rtc->rtc_dev); | ||
197 | dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); | ||
198 | return ret; | ||
199 | } | ||
200 | |||
201 | rtc->irq = regmap_irq_get_virq(max8907->irqc_rtc, | ||
202 | MAX8907_IRQ_RTC_ALARM0); | ||
203 | if (rtc->irq < 0) { | ||
204 | ret = rtc->irq; | ||
205 | goto err_unregister; | ||
206 | } | ||
207 | |||
208 | ret = request_threaded_irq(rtc->irq, NULL, max8907_irq_handler, | ||
209 | IRQF_ONESHOT, "max8907-alarm0", rtc); | ||
210 | if (ret < 0) { | ||
211 | dev_err(&pdev->dev, "Failed to request IRQ%d: %d\n", | ||
212 | rtc->irq, ret); | ||
213 | goto err_unregister; | ||
214 | } | ||
215 | |||
216 | return 0; | ||
217 | |||
218 | err_unregister: | ||
219 | rtc_device_unregister(rtc->rtc_dev); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static int __devexit max8907_rtc_remove(struct platform_device *pdev) | ||
224 | { | ||
225 | struct max8907_rtc *rtc = platform_get_drvdata(pdev); | ||
226 | |||
227 | free_irq(rtc->irq, rtc); | ||
228 | rtc_device_unregister(rtc->rtc_dev); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static struct platform_driver max8907_rtc_driver = { | ||
234 | .driver = { | ||
235 | .name = "max8907-rtc", | ||
236 | .owner = THIS_MODULE, | ||
237 | }, | ||
238 | .probe = max8907_rtc_probe, | ||
239 | .remove = __devexit_p(max8907_rtc_remove), | ||
240 | }; | ||
241 | module_platform_driver(max8907_rtc_driver); | ||
242 | |||
243 | MODULE_DESCRIPTION("Maxim MAX8907 RTC driver"); | ||
244 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index e3e50d69baf8..cd0106293a49 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c | |||
@@ -343,7 +343,7 @@ static struct rtc_class_ops mxc_rtc_ops = { | |||
343 | .alarm_irq_enable = mxc_rtc_alarm_irq_enable, | 343 | .alarm_irq_enable = mxc_rtc_alarm_irq_enable, |
344 | }; | 344 | }; |
345 | 345 | ||
346 | static int __init mxc_rtc_probe(struct platform_device *pdev) | 346 | static int __devinit mxc_rtc_probe(struct platform_device *pdev) |
347 | { | 347 | { |
348 | struct resource *res; | 348 | struct resource *res; |
349 | struct rtc_device *rtc; | 349 | struct rtc_device *rtc; |
@@ -367,14 +367,14 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
367 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, | 367 | pdata->ioaddr = devm_ioremap(&pdev->dev, res->start, |
368 | resource_size(res)); | 368 | resource_size(res)); |
369 | 369 | ||
370 | pdata->clk = clk_get(&pdev->dev, "rtc"); | 370 | pdata->clk = devm_clk_get(&pdev->dev, NULL); |
371 | if (IS_ERR(pdata->clk)) { | 371 | if (IS_ERR(pdata->clk)) { |
372 | dev_err(&pdev->dev, "unable to get clock!\n"); | 372 | dev_err(&pdev->dev, "unable to get clock!\n"); |
373 | ret = PTR_ERR(pdata->clk); | 373 | ret = PTR_ERR(pdata->clk); |
374 | goto exit_free_pdata; | 374 | goto exit_free_pdata; |
375 | } | 375 | } |
376 | 376 | ||
377 | clk_enable(pdata->clk); | 377 | clk_prepare_enable(pdata->clk); |
378 | rate = clk_get_rate(pdata->clk); | 378 | rate = clk_get_rate(pdata->clk); |
379 | 379 | ||
380 | if (rate == 32768) | 380 | if (rate == 32768) |
@@ -426,22 +426,20 @@ static int __init mxc_rtc_probe(struct platform_device *pdev) | |||
426 | exit_clr_drvdata: | 426 | exit_clr_drvdata: |
427 | platform_set_drvdata(pdev, NULL); | 427 | platform_set_drvdata(pdev, NULL); |
428 | exit_put_clk: | 428 | exit_put_clk: |
429 | clk_disable(pdata->clk); | 429 | clk_disable_unprepare(pdata->clk); |
430 | clk_put(pdata->clk); | ||
431 | 430 | ||
432 | exit_free_pdata: | 431 | exit_free_pdata: |
433 | 432 | ||
434 | return ret; | 433 | return ret; |
435 | } | 434 | } |
436 | 435 | ||
437 | static int __exit mxc_rtc_remove(struct platform_device *pdev) | 436 | static int __devexit mxc_rtc_remove(struct platform_device *pdev) |
438 | { | 437 | { |
439 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | 438 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); |
440 | 439 | ||
441 | rtc_device_unregister(pdata->rtc); | 440 | rtc_device_unregister(pdata->rtc); |
442 | 441 | ||
443 | clk_disable(pdata->clk); | 442 | clk_disable_unprepare(pdata->clk); |
444 | clk_put(pdata->clk); | ||
445 | platform_set_drvdata(pdev, NULL); | 443 | platform_set_drvdata(pdev, NULL); |
446 | 444 | ||
447 | return 0; | 445 | return 0; |
@@ -482,21 +480,11 @@ static struct platform_driver mxc_rtc_driver = { | |||
482 | #endif | 480 | #endif |
483 | .owner = THIS_MODULE, | 481 | .owner = THIS_MODULE, |
484 | }, | 482 | }, |
485 | .remove = __exit_p(mxc_rtc_remove), | 483 | .probe = mxc_rtc_probe, |
484 | .remove = __devexit_p(mxc_rtc_remove), | ||
486 | }; | 485 | }; |
487 | 486 | ||
488 | static int __init mxc_rtc_init(void) | 487 | module_platform_driver(mxc_rtc_driver) |
489 | { | ||
490 | return platform_driver_probe(&mxc_rtc_driver, mxc_rtc_probe); | ||
491 | } | ||
492 | |||
493 | static void __exit mxc_rtc_exit(void) | ||
494 | { | ||
495 | platform_driver_unregister(&mxc_rtc_driver); | ||
496 | } | ||
497 | |||
498 | module_init(mxc_rtc_init); | ||
499 | module_exit(mxc_rtc_exit); | ||
500 | 488 | ||
501 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 489 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
502 | MODULE_DESCRIPTION("RTC driver for Freescale MXC"); | 490 | MODULE_DESCRIPTION("RTC driver for Freescale MXC"); |
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index c2fe426a6ef2..98e3a2b681e6 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c | |||
@@ -78,8 +78,17 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
78 | unsigned char buf[13] = { PCF8563_REG_ST1 }; | 78 | unsigned char buf[13] = { PCF8563_REG_ST1 }; |
79 | 79 | ||
80 | struct i2c_msg msgs[] = { | 80 | struct i2c_msg msgs[] = { |
81 | { client->addr, 0, 1, buf }, /* setup read ptr */ | 81 | {/* setup read ptr */ |
82 | { client->addr, I2C_M_RD, 13, buf }, /* read status + date */ | 82 | .addr = client->addr, |
83 | .len = 1, | ||
84 | .buf = buf | ||
85 | }, | ||
86 | {/* read status + date */ | ||
87 | .addr = client->addr, | ||
88 | .flags = I2C_M_RD, | ||
89 | .len = 13, | ||
90 | .buf = buf | ||
91 | }, | ||
83 | }; | 92 | }; |
84 | 93 | ||
85 | /* read registers */ | 94 | /* read registers */ |
diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c index 0a59fda5c09d..e96236ac2e78 100644 --- a/drivers/rtc/rtc-proc.c +++ b/drivers/rtc/rtc-proc.c | |||
@@ -18,6 +18,26 @@ | |||
18 | 18 | ||
19 | #include "rtc-core.h" | 19 | #include "rtc-core.h" |
20 | 20 | ||
21 | #define NAME_SIZE 10 | ||
22 | |||
23 | #if defined(CONFIG_RTC_HCTOSYS_DEVICE) | ||
24 | static bool is_rtc_hctosys(struct rtc_device *rtc) | ||
25 | { | ||
26 | int size; | ||
27 | char name[NAME_SIZE]; | ||
28 | |||
29 | size = scnprintf(name, NAME_SIZE, "rtc%d", rtc->id); | ||
30 | if (size > NAME_SIZE) | ||
31 | return false; | ||
32 | |||
33 | return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE); | ||
34 | } | ||
35 | #else | ||
36 | static bool is_rtc_hctosys(struct rtc_device *rtc) | ||
37 | { | ||
38 | return (rtc->id == 0); | ||
39 | } | ||
40 | #endif | ||
21 | 41 | ||
22 | static int rtc_proc_show(struct seq_file *seq, void *offset) | 42 | static int rtc_proc_show(struct seq_file *seq, void *offset) |
23 | { | 43 | { |
@@ -117,12 +137,12 @@ static const struct file_operations rtc_proc_fops = { | |||
117 | 137 | ||
118 | void rtc_proc_add_device(struct rtc_device *rtc) | 138 | void rtc_proc_add_device(struct rtc_device *rtc) |
119 | { | 139 | { |
120 | if (rtc->id == 0) | 140 | if (is_rtc_hctosys(rtc)) |
121 | proc_create_data("driver/rtc", 0, NULL, &rtc_proc_fops, rtc); | 141 | proc_create_data("driver/rtc", 0, NULL, &rtc_proc_fops, rtc); |
122 | } | 142 | } |
123 | 143 | ||
124 | void rtc_proc_del_device(struct rtc_device *rtc) | 144 | void rtc_proc_del_device(struct rtc_device *rtc) |
125 | { | 145 | { |
126 | if (rtc->id == 0) | 146 | if (is_rtc_hctosys(rtc)) |
127 | remove_proc_entry("driver/rtc", NULL); | 147 | remove_proc_entry("driver/rtc", NULL); |
128 | } | 148 | } |
diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c new file mode 100644 index 000000000000..cdb140c29c56 --- /dev/null +++ b/drivers/rtc/rtc-rc5t583.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /* | ||
2 | * rtc-rc5t583.c -- RICOH RC5T583 Real Time Clock | ||
3 | * | ||
4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
5 | * Author: Venu Byravarasu <vbyravarasu@nvidia.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
18 | |||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/rtc.h> | ||
25 | #include <linux/bcd.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/interrupt.h> | ||
28 | #include <linux/mfd/rc5t583.h> | ||
29 | |||
30 | struct rc5t583_rtc { | ||
31 | struct rtc_device *rtc; | ||
32 | /* To store the list of enabled interrupts, during system suspend */ | ||
33 | u32 irqen; | ||
34 | }; | ||
35 | |||
36 | /* Total number of RTC registers needed to set time*/ | ||
37 | #define NUM_TIME_REGS (RC5T583_RTC_YEAR - RC5T583_RTC_SEC + 1) | ||
38 | |||
39 | /* Total number of RTC registers needed to set Y-Alarm*/ | ||
40 | #define NUM_YAL_REGS (RC5T583_RTC_AY_YEAR - RC5T583_RTC_AY_MIN + 1) | ||
41 | |||
42 | /* Set Y-Alarm interrupt */ | ||
43 | #define SET_YAL BIT(5) | ||
44 | |||
45 | /* Get Y-Alarm interrupt status*/ | ||
46 | #define GET_YAL_STATUS BIT(3) | ||
47 | |||
48 | static int rc5t583_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | ||
49 | { | ||
50 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
51 | u8 val; | ||
52 | |||
53 | /* Set Y-Alarm, based on 'enabled' */ | ||
54 | val = enabled ? SET_YAL : 0; | ||
55 | |||
56 | return regmap_update_bits(rc5t583->regmap, RC5T583_RTC_CTL1, SET_YAL, | ||
57 | val); | ||
58 | } | ||
59 | |||
60 | /* | ||
61 | * Gets current rc5t583 RTC time and date parameters. | ||
62 | * | ||
63 | * The RTC's time/alarm representation is not what gmtime(3) requires | ||
64 | * Linux to use: | ||
65 | * | ||
66 | * - Months are 1..12 vs Linux 0-11 | ||
67 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) | ||
68 | */ | ||
69 | static int rc5t583_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
70 | { | ||
71 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
72 | u8 rtc_data[NUM_TIME_REGS]; | ||
73 | int ret; | ||
74 | |||
75 | ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data, | ||
76 | NUM_TIME_REGS); | ||
77 | if (ret < 0) { | ||
78 | dev_err(dev, "RTC read time failed with err:%d\n", ret); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | tm->tm_sec = bcd2bin(rtc_data[0]); | ||
83 | tm->tm_min = bcd2bin(rtc_data[1]); | ||
84 | tm->tm_hour = bcd2bin(rtc_data[2]); | ||
85 | tm->tm_wday = bcd2bin(rtc_data[3]); | ||
86 | tm->tm_mday = bcd2bin(rtc_data[4]); | ||
87 | tm->tm_mon = bcd2bin(rtc_data[5]) - 1; | ||
88 | tm->tm_year = bcd2bin(rtc_data[6]) + 100; | ||
89 | |||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | static int rc5t583_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
94 | { | ||
95 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
96 | unsigned char rtc_data[NUM_TIME_REGS]; | ||
97 | int ret; | ||
98 | |||
99 | rtc_data[0] = bin2bcd(tm->tm_sec); | ||
100 | rtc_data[1] = bin2bcd(tm->tm_min); | ||
101 | rtc_data[2] = bin2bcd(tm->tm_hour); | ||
102 | rtc_data[3] = bin2bcd(tm->tm_wday); | ||
103 | rtc_data[4] = bin2bcd(tm->tm_mday); | ||
104 | rtc_data[5] = bin2bcd(tm->tm_mon + 1); | ||
105 | rtc_data[6] = bin2bcd(tm->tm_year - 100); | ||
106 | |||
107 | ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_SEC, rtc_data, | ||
108 | NUM_TIME_REGS); | ||
109 | if (ret < 0) { | ||
110 | dev_err(dev, "RTC set time failed with error %d\n", ret); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | static int rc5t583_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
118 | { | ||
119 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
120 | unsigned char alarm_data[NUM_YAL_REGS]; | ||
121 | u32 interrupt_enable; | ||
122 | int ret; | ||
123 | |||
124 | ret = regmap_bulk_read(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data, | ||
125 | NUM_YAL_REGS); | ||
126 | if (ret < 0) { | ||
127 | dev_err(dev, "rtc_read_alarm error %d\n", ret); | ||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | alm->time.tm_min = bcd2bin(alarm_data[0]); | ||
132 | alm->time.tm_hour = bcd2bin(alarm_data[1]); | ||
133 | alm->time.tm_mday = bcd2bin(alarm_data[2]); | ||
134 | alm->time.tm_mon = bcd2bin(alarm_data[3]) - 1; | ||
135 | alm->time.tm_year = bcd2bin(alarm_data[4]) + 100; | ||
136 | |||
137 | ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, &interrupt_enable); | ||
138 | if (ret < 0) | ||
139 | return ret; | ||
140 | |||
141 | /* check if YALE is set */ | ||
142 | if (interrupt_enable & SET_YAL) | ||
143 | alm->enabled = 1; | ||
144 | |||
145 | return ret; | ||
146 | } | ||
147 | |||
148 | static int rc5t583_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
149 | { | ||
150 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
151 | unsigned char alarm_data[NUM_YAL_REGS]; | ||
152 | int ret; | ||
153 | |||
154 | ret = rc5t583_rtc_alarm_irq_enable(dev, 0); | ||
155 | if (ret) | ||
156 | return ret; | ||
157 | |||
158 | alarm_data[0] = bin2bcd(alm->time.tm_min); | ||
159 | alarm_data[1] = bin2bcd(alm->time.tm_hour); | ||
160 | alarm_data[2] = bin2bcd(alm->time.tm_mday); | ||
161 | alarm_data[3] = bin2bcd(alm->time.tm_mon + 1); | ||
162 | alarm_data[4] = bin2bcd(alm->time.tm_year - 100); | ||
163 | |||
164 | ret = regmap_bulk_write(rc5t583->regmap, RC5T583_RTC_AY_MIN, alarm_data, | ||
165 | NUM_YAL_REGS); | ||
166 | if (ret) { | ||
167 | dev_err(dev, "rtc_set_alarm error %d\n", ret); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | if (alm->enabled) | ||
172 | ret = rc5t583_rtc_alarm_irq_enable(dev, 1); | ||
173 | |||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | static irqreturn_t rc5t583_rtc_interrupt(int irq, void *rtc) | ||
178 | { | ||
179 | struct device *dev = rtc; | ||
180 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
181 | struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); | ||
182 | unsigned long events = 0; | ||
183 | int ret; | ||
184 | u32 rtc_reg; | ||
185 | |||
186 | ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL2, &rtc_reg); | ||
187 | if (ret < 0) | ||
188 | return IRQ_NONE; | ||
189 | |||
190 | if (rtc_reg & GET_YAL_STATUS) { | ||
191 | events = RTC_IRQF | RTC_AF; | ||
192 | /* clear pending Y-alarm interrupt bit */ | ||
193 | rtc_reg &= ~GET_YAL_STATUS; | ||
194 | } | ||
195 | |||
196 | ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, rtc_reg); | ||
197 | if (ret) | ||
198 | return IRQ_NONE; | ||
199 | |||
200 | /* Notify RTC core on event */ | ||
201 | rtc_update_irq(rc5t583_rtc->rtc, 1, events); | ||
202 | |||
203 | return IRQ_HANDLED; | ||
204 | } | ||
205 | |||
206 | static const struct rtc_class_ops rc5t583_rtc_ops = { | ||
207 | .read_time = rc5t583_rtc_read_time, | ||
208 | .set_time = rc5t583_rtc_set_time, | ||
209 | .read_alarm = rc5t583_rtc_read_alarm, | ||
210 | .set_alarm = rc5t583_rtc_set_alarm, | ||
211 | .alarm_irq_enable = rc5t583_rtc_alarm_irq_enable, | ||
212 | }; | ||
213 | |||
214 | static int __devinit rc5t583_rtc_probe(struct platform_device *pdev) | ||
215 | { | ||
216 | struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); | ||
217 | struct rc5t583_rtc *ricoh_rtc; | ||
218 | struct rc5t583_platform_data *pmic_plat_data; | ||
219 | int ret; | ||
220 | int irq; | ||
221 | |||
222 | ricoh_rtc = devm_kzalloc(&pdev->dev, sizeof(struct rc5t583_rtc), | ||
223 | GFP_KERNEL); | ||
224 | if (!ricoh_rtc) | ||
225 | return -ENOMEM; | ||
226 | |||
227 | platform_set_drvdata(pdev, ricoh_rtc); | ||
228 | |||
229 | /* Clear pending interrupts */ | ||
230 | ret = regmap_write(rc5t583->regmap, RC5T583_RTC_CTL2, 0); | ||
231 | if (ret < 0) | ||
232 | return ret; | ||
233 | |||
234 | /* clear RTC Adjust register */ | ||
235 | ret = regmap_write(rc5t583->regmap, RC5T583_RTC_ADJ, 0); | ||
236 | if (ret < 0) { | ||
237 | dev_err(&pdev->dev, "unable to program rtc_adjust reg\n"); | ||
238 | return -EBUSY; | ||
239 | } | ||
240 | |||
241 | pmic_plat_data = dev_get_platdata(rc5t583->dev); | ||
242 | irq = pmic_plat_data->irq_base; | ||
243 | if (irq <= 0) { | ||
244 | dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", | ||
245 | irq); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | irq += RC5T583_IRQ_YALE; | ||
250 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | ||
251 | rc5t583_rtc_interrupt, IRQF_TRIGGER_LOW, | ||
252 | "rtc-rc5t583", &pdev->dev); | ||
253 | if (ret < 0) { | ||
254 | dev_err(&pdev->dev, "IRQ is not free.\n"); | ||
255 | return ret; | ||
256 | } | ||
257 | device_init_wakeup(&pdev->dev, 1); | ||
258 | |||
259 | ricoh_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
260 | &rc5t583_rtc_ops, THIS_MODULE); | ||
261 | if (IS_ERR(ricoh_rtc->rtc)) { | ||
262 | ret = PTR_ERR(ricoh_rtc->rtc); | ||
263 | dev_err(&pdev->dev, "RTC device register: err %d\n", ret); | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * Disable rc5t583 RTC interrupts. | ||
272 | * Sets status flag to free. | ||
273 | */ | ||
274 | static int __devexit rc5t583_rtc_remove(struct platform_device *pdev) | ||
275 | { | ||
276 | struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(&pdev->dev); | ||
277 | |||
278 | rc5t583_rtc_alarm_irq_enable(&rc5t583_rtc->rtc->dev, 0); | ||
279 | |||
280 | rtc_device_unregister(rc5t583_rtc->rtc); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | #ifdef CONFIG_PM_SLEEP | ||
285 | |||
286 | static int rc5t583_rtc_suspend(struct device *dev) | ||
287 | { | ||
288 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
289 | struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); | ||
290 | int ret; | ||
291 | |||
292 | /* Store current list of enabled interrupts*/ | ||
293 | ret = regmap_read(rc5t583->regmap, RC5T583_RTC_CTL1, | ||
294 | &rc5t583_rtc->irqen); | ||
295 | return ret; | ||
296 | } | ||
297 | |||
298 | static int rc5t583_rtc_resume(struct device *dev) | ||
299 | { | ||
300 | struct rc5t583 *rc5t583 = dev_get_drvdata(dev->parent); | ||
301 | struct rc5t583_rtc *rc5t583_rtc = dev_get_drvdata(dev); | ||
302 | |||
303 | /* Restore list of enabled interrupts before suspend */ | ||
304 | return regmap_write(rc5t583->regmap, RC5T583_RTC_CTL1, | ||
305 | rc5t583_rtc->irqen); | ||
306 | } | ||
307 | |||
308 | static const struct dev_pm_ops rc5t583_rtc_pm_ops = { | ||
309 | .suspend = rc5t583_rtc_suspend, | ||
310 | .resume = rc5t583_rtc_resume, | ||
311 | }; | ||
312 | |||
313 | #define DEV_PM_OPS (&rc5t583_rtc_pm_ops) | ||
314 | #else | ||
315 | #define DEV_PM_OPS NULL | ||
316 | #endif | ||
317 | |||
318 | static struct platform_driver rc5t583_rtc_driver = { | ||
319 | .probe = rc5t583_rtc_probe, | ||
320 | .remove = __devexit_p(rc5t583_rtc_remove), | ||
321 | .driver = { | ||
322 | .owner = THIS_MODULE, | ||
323 | .name = "rtc-rc5t583", | ||
324 | .pm = DEV_PM_OPS, | ||
325 | }, | ||
326 | }; | ||
327 | |||
328 | module_platform_driver(rc5t583_rtc_driver); | ||
329 | MODULE_ALIAS("platform:rtc-rc5t583"); | ||
330 | MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); | ||
331 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index fb4842c3544e..76f565ae384d 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c | |||
@@ -104,7 +104,12 @@ static int rs5c_get_regs(struct rs5c372 *rs5c) | |||
104 | { | 104 | { |
105 | struct i2c_client *client = rs5c->client; | 105 | struct i2c_client *client = rs5c->client; |
106 | struct i2c_msg msgs[] = { | 106 | struct i2c_msg msgs[] = { |
107 | { client->addr, I2C_M_RD, sizeof rs5c->buf, rs5c->buf }, | 107 | { |
108 | .addr = client->addr, | ||
109 | .flags = I2C_M_RD, | ||
110 | .len = sizeof(rs5c->buf), | ||
111 | .buf = rs5c->buf | ||
112 | }, | ||
108 | }; | 113 | }; |
109 | 114 | ||
110 | /* This implements the third reading method from the datasheet, using | 115 | /* This implements the third reading method from the datasheet, using |
diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index c9562ceedef3..8a092325188d 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #define S35390A_CMD_STATUS1 0 | 19 | #define S35390A_CMD_STATUS1 0 |
20 | #define S35390A_CMD_STATUS2 1 | 20 | #define S35390A_CMD_STATUS2 1 |
21 | #define S35390A_CMD_TIME1 2 | 21 | #define S35390A_CMD_TIME1 2 |
22 | #define S35390A_CMD_TIME2 3 | ||
23 | #define S35390A_CMD_INT2_REG1 5 | ||
22 | 24 | ||
23 | #define S35390A_BYTE_YEAR 0 | 25 | #define S35390A_BYTE_YEAR 0 |
24 | #define S35390A_BYTE_MONTH 1 | 26 | #define S35390A_BYTE_MONTH 1 |
@@ -28,12 +30,23 @@ | |||
28 | #define S35390A_BYTE_MINS 5 | 30 | #define S35390A_BYTE_MINS 5 |
29 | #define S35390A_BYTE_SECS 6 | 31 | #define S35390A_BYTE_SECS 6 |
30 | 32 | ||
33 | #define S35390A_ALRM_BYTE_WDAY 0 | ||
34 | #define S35390A_ALRM_BYTE_HOURS 1 | ||
35 | #define S35390A_ALRM_BYTE_MINS 2 | ||
36 | |||
31 | #define S35390A_FLAG_POC 0x01 | 37 | #define S35390A_FLAG_POC 0x01 |
32 | #define S35390A_FLAG_BLD 0x02 | 38 | #define S35390A_FLAG_BLD 0x02 |
33 | #define S35390A_FLAG_24H 0x40 | 39 | #define S35390A_FLAG_24H 0x40 |
34 | #define S35390A_FLAG_RESET 0x80 | 40 | #define S35390A_FLAG_RESET 0x80 |
35 | #define S35390A_FLAG_TEST 0x01 | 41 | #define S35390A_FLAG_TEST 0x01 |
36 | 42 | ||
43 | #define S35390A_INT2_MODE_MASK 0xF0 | ||
44 | |||
45 | #define S35390A_INT2_MODE_NOINTR 0x00 | ||
46 | #define S35390A_INT2_MODE_FREQ 0x10 | ||
47 | #define S35390A_INT2_MODE_ALARM 0x40 | ||
48 | #define S35390A_INT2_MODE_PMIN_EDG 0x20 | ||
49 | |||
37 | static const struct i2c_device_id s35390a_id[] = { | 50 | static const struct i2c_device_id s35390a_id[] = { |
38 | { "s35390a", 0 }, | 51 | { "s35390a", 0 }, |
39 | { } | 52 | { } |
@@ -50,7 +63,11 @@ static int s35390a_set_reg(struct s35390a *s35390a, int reg, char *buf, int len) | |||
50 | { | 63 | { |
51 | struct i2c_client *client = s35390a->client[reg]; | 64 | struct i2c_client *client = s35390a->client[reg]; |
52 | struct i2c_msg msg[] = { | 65 | struct i2c_msg msg[] = { |
53 | { client->addr, 0, len, buf }, | 66 | { |
67 | .addr = client->addr, | ||
68 | .len = len, | ||
69 | .buf = buf | ||
70 | }, | ||
54 | }; | 71 | }; |
55 | 72 | ||
56 | if ((i2c_transfer(client->adapter, msg, 1)) != 1) | 73 | if ((i2c_transfer(client->adapter, msg, 1)) != 1) |
@@ -63,7 +80,12 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, char *buf, int len) | |||
63 | { | 80 | { |
64 | struct i2c_client *client = s35390a->client[reg]; | 81 | struct i2c_client *client = s35390a->client[reg]; |
65 | struct i2c_msg msg[] = { | 82 | struct i2c_msg msg[] = { |
66 | { client->addr, I2C_M_RD, len, buf }, | 83 | { |
84 | .addr = client->addr, | ||
85 | .flags = I2C_M_RD, | ||
86 | .len = len, | ||
87 | .buf = buf | ||
88 | }, | ||
67 | }; | 89 | }; |
68 | 90 | ||
69 | if ((i2c_transfer(client->adapter, msg, 1)) != 1) | 91 | if ((i2c_transfer(client->adapter, msg, 1)) != 1) |
@@ -184,6 +206,104 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm) | |||
184 | return rtc_valid_tm(tm); | 206 | return rtc_valid_tm(tm); |
185 | } | 207 | } |
186 | 208 | ||
209 | static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) | ||
210 | { | ||
211 | struct s35390a *s35390a = i2c_get_clientdata(client); | ||
212 | char buf[3], sts = 0; | ||
213 | int err, i; | ||
214 | |||
215 | dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\ | ||
216 | "mon=%d, year=%d, wday=%d\n", __func__, alm->time.tm_sec, | ||
217 | alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, | ||
218 | alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); | ||
219 | |||
220 | /* disable interrupt */ | ||
221 | err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); | ||
222 | if (err < 0) | ||
223 | return err; | ||
224 | |||
225 | /* clear pending interrupt, if any */ | ||
226 | err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); | ||
227 | if (err < 0) | ||
228 | return err; | ||
229 | |||
230 | if (alm->enabled) | ||
231 | sts = S35390A_INT2_MODE_ALARM; | ||
232 | else | ||
233 | sts = S35390A_INT2_MODE_NOINTR; | ||
234 | |||
235 | /* This chip expects the bits of each byte to be in reverse order */ | ||
236 | sts = bitrev8(sts); | ||
237 | |||
238 | /* set interupt mode*/ | ||
239 | err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); | ||
240 | if (err < 0) | ||
241 | return err; | ||
242 | |||
243 | if (alm->time.tm_wday != -1) | ||
244 | buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80; | ||
245 | |||
246 | buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, | ||
247 | alm->time.tm_hour) | 0x80; | ||
248 | buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80; | ||
249 | |||
250 | if (alm->time.tm_hour >= 12) | ||
251 | buf[S35390A_ALRM_BYTE_HOURS] |= 0x40; | ||
252 | |||
253 | for (i = 0; i < 3; ++i) | ||
254 | buf[i] = bitrev8(buf[i]); | ||
255 | |||
256 | err = s35390a_set_reg(s35390a, S35390A_CMD_INT2_REG1, buf, | ||
257 | sizeof(buf)); | ||
258 | |||
259 | return err; | ||
260 | } | ||
261 | |||
262 | static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm) | ||
263 | { | ||
264 | struct s35390a *s35390a = i2c_get_clientdata(client); | ||
265 | char buf[3], sts; | ||
266 | int i, err; | ||
267 | |||
268 | err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); | ||
269 | if (err < 0) | ||
270 | return err; | ||
271 | |||
272 | if (bitrev8(sts) != S35390A_INT2_MODE_ALARM) | ||
273 | return -EINVAL; | ||
274 | |||
275 | err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf)); | ||
276 | if (err < 0) | ||
277 | return err; | ||
278 | |||
279 | /* This chip returns the bits of each byte in reverse order */ | ||
280 | for (i = 0; i < 3; ++i) { | ||
281 | buf[i] = bitrev8(buf[i]); | ||
282 | buf[i] &= ~0x80; | ||
283 | } | ||
284 | |||
285 | alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]); | ||
286 | alm->time.tm_hour = s35390a_reg2hr(s35390a, | ||
287 | buf[S35390A_ALRM_BYTE_HOURS]); | ||
288 | alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]); | ||
289 | |||
290 | dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n", | ||
291 | __func__, alm->time.tm_min, alm->time.tm_hour, | ||
292 | alm->time.tm_wday); | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
298 | { | ||
299 | return s35390a_read_alarm(to_i2c_client(dev), alm); | ||
300 | } | ||
301 | |||
302 | static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
303 | { | ||
304 | return s35390a_set_alarm(to_i2c_client(dev), alm); | ||
305 | } | ||
306 | |||
187 | static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) | 307 | static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) |
188 | { | 308 | { |
189 | return s35390a_get_datetime(to_i2c_client(dev), tm); | 309 | return s35390a_get_datetime(to_i2c_client(dev), tm); |
@@ -197,6 +317,9 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
197 | static const struct rtc_class_ops s35390a_rtc_ops = { | 317 | static const struct rtc_class_ops s35390a_rtc_ops = { |
198 | .read_time = s35390a_rtc_read_time, | 318 | .read_time = s35390a_rtc_read_time, |
199 | .set_time = s35390a_rtc_set_time, | 319 | .set_time = s35390a_rtc_set_time, |
320 | .set_alarm = s35390a_rtc_set_alarm, | ||
321 | .read_alarm = s35390a_rtc_read_alarm, | ||
322 | |||
200 | }; | 323 | }; |
201 | 324 | ||
202 | static struct i2c_driver s35390a_driver; | 325 | static struct i2c_driver s35390a_driver; |
@@ -261,6 +384,8 @@ static int s35390a_probe(struct i2c_client *client, | |||
261 | if (s35390a_get_datetime(client, &tm) < 0) | 384 | if (s35390a_get_datetime(client, &tm) < 0) |
262 | dev_warn(&client->dev, "clock needs to be set\n"); | 385 | dev_warn(&client->dev, "clock needs to be set\n"); |
263 | 386 | ||
387 | device_set_wakeup_capable(&client->dev, 1); | ||
388 | |||
264 | s35390a->rtc = rtc_device_register(s35390a_driver.driver.name, | 389 | s35390a->rtc = rtc_device_register(s35390a_driver.driver.name, |
265 | &client->dev, &s35390a_rtc_ops, THIS_MODULE); | 390 | &client->dev, &s35390a_rtc_ops, THIS_MODULE); |
266 | 391 | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index bfbd92c8d1c9..77823d21d314 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -476,13 +476,13 @@ static int __devinit s3c_rtc_probe(struct platform_device *pdev) | |||
476 | s3c_rtc_tickno = platform_get_irq(pdev, 1); | 476 | s3c_rtc_tickno = platform_get_irq(pdev, 1); |
477 | if (s3c_rtc_tickno < 0) { | 477 | if (s3c_rtc_tickno < 0) { |
478 | dev_err(&pdev->dev, "no irq for rtc tick\n"); | 478 | dev_err(&pdev->dev, "no irq for rtc tick\n"); |
479 | return -ENOENT; | 479 | return s3c_rtc_tickno; |
480 | } | 480 | } |
481 | 481 | ||
482 | s3c_rtc_alarmno = platform_get_irq(pdev, 0); | 482 | s3c_rtc_alarmno = platform_get_irq(pdev, 0); |
483 | if (s3c_rtc_alarmno < 0) { | 483 | if (s3c_rtc_alarmno < 0) { |
484 | dev_err(&pdev->dev, "no irq for alarm\n"); | 484 | dev_err(&pdev->dev, "no irq for alarm\n"); |
485 | return -ENOENT; | 485 | return s3c_rtc_alarmno; |
486 | } | 486 | } |
487 | 487 | ||
488 | pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n", | 488 | pr_debug("s3c2410_rtc: tick irq %d, alarm irq %d\n", |
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c new file mode 100644 index 000000000000..3c0da333f465 --- /dev/null +++ b/drivers/rtc/rtc-snvs.c | |||
@@ -0,0 +1,350 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/of_device.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/rtc.h> | ||
20 | |||
21 | /* These register offsets are relative to LP (Low Power) range */ | ||
22 | #define SNVS_LPCR 0x04 | ||
23 | #define SNVS_LPSR 0x18 | ||
24 | #define SNVS_LPSRTCMR 0x1c | ||
25 | #define SNVS_LPSRTCLR 0x20 | ||
26 | #define SNVS_LPTAR 0x24 | ||
27 | #define SNVS_LPPGDR 0x30 | ||
28 | |||
29 | #define SNVS_LPCR_SRTC_ENV (1 << 0) | ||
30 | #define SNVS_LPCR_LPTA_EN (1 << 1) | ||
31 | #define SNVS_LPCR_LPWUI_EN (1 << 3) | ||
32 | #define SNVS_LPSR_LPTA (1 << 0) | ||
33 | |||
34 | #define SNVS_LPPGDR_INIT 0x41736166 | ||
35 | #define CNTR_TO_SECS_SH 15 | ||
36 | |||
37 | struct snvs_rtc_data { | ||
38 | struct rtc_device *rtc; | ||
39 | void __iomem *ioaddr; | ||
40 | int irq; | ||
41 | spinlock_t lock; | ||
42 | }; | ||
43 | |||
44 | static u32 rtc_read_lp_counter(void __iomem *ioaddr) | ||
45 | { | ||
46 | u64 read1, read2; | ||
47 | |||
48 | do { | ||
49 | read1 = readl(ioaddr + SNVS_LPSRTCMR); | ||
50 | read1 <<= 32; | ||
51 | read1 |= readl(ioaddr + SNVS_LPSRTCLR); | ||
52 | |||
53 | read2 = readl(ioaddr + SNVS_LPSRTCMR); | ||
54 | read2 <<= 32; | ||
55 | read2 |= readl(ioaddr + SNVS_LPSRTCLR); | ||
56 | } while (read1 != read2); | ||
57 | |||
58 | /* Convert 47-bit counter to 32-bit raw second count */ | ||
59 | return (u32) (read1 >> CNTR_TO_SECS_SH); | ||
60 | } | ||
61 | |||
62 | static void rtc_write_sync_lp(void __iomem *ioaddr) | ||
63 | { | ||
64 | u32 count1, count2, count3; | ||
65 | int i; | ||
66 | |||
67 | /* Wait for 3 CKIL cycles */ | ||
68 | for (i = 0; i < 3; i++) { | ||
69 | do { | ||
70 | count1 = readl(ioaddr + SNVS_LPSRTCLR); | ||
71 | count2 = readl(ioaddr + SNVS_LPSRTCLR); | ||
72 | } while (count1 != count2); | ||
73 | |||
74 | /* Now wait until counter value changes */ | ||
75 | do { | ||
76 | do { | ||
77 | count2 = readl(ioaddr + SNVS_LPSRTCLR); | ||
78 | count3 = readl(ioaddr + SNVS_LPSRTCLR); | ||
79 | } while (count2 != count3); | ||
80 | } while (count3 == count1); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable) | ||
85 | { | ||
86 | unsigned long flags; | ||
87 | int timeout = 1000; | ||
88 | u32 lpcr; | ||
89 | |||
90 | spin_lock_irqsave(&data->lock, flags); | ||
91 | |||
92 | lpcr = readl(data->ioaddr + SNVS_LPCR); | ||
93 | if (enable) | ||
94 | lpcr |= SNVS_LPCR_SRTC_ENV; | ||
95 | else | ||
96 | lpcr &= ~SNVS_LPCR_SRTC_ENV; | ||
97 | writel(lpcr, data->ioaddr + SNVS_LPCR); | ||
98 | |||
99 | spin_unlock_irqrestore(&data->lock, flags); | ||
100 | |||
101 | while (--timeout) { | ||
102 | lpcr = readl(data->ioaddr + SNVS_LPCR); | ||
103 | |||
104 | if (enable) { | ||
105 | if (lpcr & SNVS_LPCR_SRTC_ENV) | ||
106 | break; | ||
107 | } else { | ||
108 | if (!(lpcr & SNVS_LPCR_SRTC_ENV)) | ||
109 | break; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | if (!timeout) | ||
114 | return -ETIMEDOUT; | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
120 | { | ||
121 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
122 | unsigned long time = rtc_read_lp_counter(data->ioaddr); | ||
123 | |||
124 | rtc_time_to_tm(time, tm); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
130 | { | ||
131 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
132 | unsigned long time; | ||
133 | |||
134 | rtc_tm_to_time(tm, &time); | ||
135 | |||
136 | /* Disable RTC first */ | ||
137 | snvs_rtc_enable(data, false); | ||
138 | |||
139 | /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */ | ||
140 | writel(time << CNTR_TO_SECS_SH, data->ioaddr + SNVS_LPSRTCLR); | ||
141 | writel(time >> (32 - CNTR_TO_SECS_SH), data->ioaddr + SNVS_LPSRTCMR); | ||
142 | |||
143 | /* Enable RTC again */ | ||
144 | snvs_rtc_enable(data, true); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
150 | { | ||
151 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
152 | u32 lptar, lpsr; | ||
153 | |||
154 | lptar = readl(data->ioaddr + SNVS_LPTAR); | ||
155 | rtc_time_to_tm(lptar, &alrm->time); | ||
156 | |||
157 | lpsr = readl(data->ioaddr + SNVS_LPSR); | ||
158 | alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0; | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) | ||
164 | { | ||
165 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
166 | u32 lpcr; | ||
167 | unsigned long flags; | ||
168 | |||
169 | spin_lock_irqsave(&data->lock, flags); | ||
170 | |||
171 | lpcr = readl(data->ioaddr + SNVS_LPCR); | ||
172 | if (enable) | ||
173 | lpcr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN); | ||
174 | else | ||
175 | lpcr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN); | ||
176 | writel(lpcr, data->ioaddr + SNVS_LPCR); | ||
177 | |||
178 | spin_unlock_irqrestore(&data->lock, flags); | ||
179 | |||
180 | rtc_write_sync_lp(data->ioaddr); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
186 | { | ||
187 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
188 | struct rtc_time *alrm_tm = &alrm->time; | ||
189 | unsigned long time; | ||
190 | unsigned long flags; | ||
191 | u32 lpcr; | ||
192 | |||
193 | rtc_tm_to_time(alrm_tm, &time); | ||
194 | |||
195 | spin_lock_irqsave(&data->lock, flags); | ||
196 | |||
197 | /* Have to clear LPTA_EN before programming new alarm time in LPTAR */ | ||
198 | lpcr = readl(data->ioaddr + SNVS_LPCR); | ||
199 | lpcr &= ~SNVS_LPCR_LPTA_EN; | ||
200 | writel(lpcr, data->ioaddr + SNVS_LPCR); | ||
201 | |||
202 | spin_unlock_irqrestore(&data->lock, flags); | ||
203 | |||
204 | writel(time, data->ioaddr + SNVS_LPTAR); | ||
205 | |||
206 | /* Clear alarm interrupt status bit */ | ||
207 | writel(SNVS_LPSR_LPTA, data->ioaddr + SNVS_LPSR); | ||
208 | |||
209 | return snvs_rtc_alarm_irq_enable(dev, alrm->enabled); | ||
210 | } | ||
211 | |||
212 | static const struct rtc_class_ops snvs_rtc_ops = { | ||
213 | .read_time = snvs_rtc_read_time, | ||
214 | .set_time = snvs_rtc_set_time, | ||
215 | .read_alarm = snvs_rtc_read_alarm, | ||
216 | .set_alarm = snvs_rtc_set_alarm, | ||
217 | .alarm_irq_enable = snvs_rtc_alarm_irq_enable, | ||
218 | }; | ||
219 | |||
220 | static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id) | ||
221 | { | ||
222 | struct device *dev = dev_id; | ||
223 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
224 | u32 lpsr; | ||
225 | u32 events = 0; | ||
226 | |||
227 | lpsr = readl(data->ioaddr + SNVS_LPSR); | ||
228 | |||
229 | if (lpsr & SNVS_LPSR_LPTA) { | ||
230 | events |= (RTC_AF | RTC_IRQF); | ||
231 | |||
232 | /* RTC alarm should be one-shot */ | ||
233 | snvs_rtc_alarm_irq_enable(dev, 0); | ||
234 | |||
235 | rtc_update_irq(data->rtc, 1, events); | ||
236 | } | ||
237 | |||
238 | /* clear interrupt status */ | ||
239 | writel(lpsr, data->ioaddr + SNVS_LPSR); | ||
240 | |||
241 | return events ? IRQ_HANDLED : IRQ_NONE; | ||
242 | } | ||
243 | |||
244 | static int __devinit snvs_rtc_probe(struct platform_device *pdev) | ||
245 | { | ||
246 | struct snvs_rtc_data *data; | ||
247 | struct resource *res; | ||
248 | int ret; | ||
249 | |||
250 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
251 | if (!data) | ||
252 | return -ENOMEM; | ||
253 | |||
254 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
255 | data->ioaddr = devm_request_and_ioremap(&pdev->dev, res); | ||
256 | if (!data->ioaddr) | ||
257 | return -EADDRNOTAVAIL; | ||
258 | |||
259 | data->irq = platform_get_irq(pdev, 0); | ||
260 | if (data->irq < 0) | ||
261 | return data->irq; | ||
262 | |||
263 | platform_set_drvdata(pdev, data); | ||
264 | |||
265 | spin_lock_init(&data->lock); | ||
266 | |||
267 | /* Initialize glitch detect */ | ||
268 | writel(SNVS_LPPGDR_INIT, data->ioaddr + SNVS_LPPGDR); | ||
269 | |||
270 | /* Clear interrupt status */ | ||
271 | writel(0xffffffff, data->ioaddr + SNVS_LPSR); | ||
272 | |||
273 | /* Enable RTC */ | ||
274 | snvs_rtc_enable(data, true); | ||
275 | |||
276 | device_init_wakeup(&pdev->dev, true); | ||
277 | |||
278 | ret = devm_request_irq(&pdev->dev, data->irq, snvs_rtc_irq_handler, | ||
279 | IRQF_SHARED, "rtc alarm", &pdev->dev); | ||
280 | if (ret) { | ||
281 | dev_err(&pdev->dev, "failed to request irq %d: %d\n", | ||
282 | data->irq, ret); | ||
283 | return ret; | ||
284 | } | ||
285 | |||
286 | data->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
287 | &snvs_rtc_ops, THIS_MODULE); | ||
288 | if (IS_ERR(data->rtc)) { | ||
289 | ret = PTR_ERR(data->rtc); | ||
290 | dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); | ||
291 | return ret; | ||
292 | } | ||
293 | |||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | static int __devexit snvs_rtc_remove(struct platform_device *pdev) | ||
298 | { | ||
299 | struct snvs_rtc_data *data = platform_get_drvdata(pdev); | ||
300 | |||
301 | rtc_device_unregister(data->rtc); | ||
302 | |||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | #ifdef CONFIG_PM_SLEEP | ||
307 | static int snvs_rtc_suspend(struct device *dev) | ||
308 | { | ||
309 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
310 | |||
311 | if (device_may_wakeup(dev)) | ||
312 | enable_irq_wake(data->irq); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int snvs_rtc_resume(struct device *dev) | ||
318 | { | ||
319 | struct snvs_rtc_data *data = dev_get_drvdata(dev); | ||
320 | |||
321 | if (device_may_wakeup(dev)) | ||
322 | disable_irq_wake(data->irq); | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | #endif | ||
327 | |||
328 | static SIMPLE_DEV_PM_OPS(snvs_rtc_pm_ops, snvs_rtc_suspend, snvs_rtc_resume); | ||
329 | |||
330 | static const struct of_device_id __devinitconst snvs_dt_ids[] = { | ||
331 | { .compatible = "fsl,sec-v4.0-mon-rtc-lp", }, | ||
332 | { /* sentinel */ } | ||
333 | }; | ||
334 | MODULE_DEVICE_TABLE(of, snvs_dt_ids); | ||
335 | |||
336 | static struct platform_driver snvs_rtc_driver = { | ||
337 | .driver = { | ||
338 | .name = "snvs_rtc", | ||
339 | .owner = THIS_MODULE, | ||
340 | .pm = &snvs_rtc_pm_ops, | ||
341 | .of_match_table = snvs_dt_ids, | ||
342 | }, | ||
343 | .probe = snvs_rtc_probe, | ||
344 | .remove = __devexit_p(snvs_rtc_remove), | ||
345 | }; | ||
346 | module_platform_driver(snvs_rtc_driver); | ||
347 | |||
348 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
349 | MODULE_DESCRIPTION("Freescale SNVS RTC Driver"); | ||
350 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index e2785479113c..bb507d23f6ce 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c | |||
@@ -235,7 +235,7 @@ static int spear_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
235 | static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) | 235 | static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) |
236 | { | 236 | { |
237 | struct spear_rtc_config *config = dev_get_drvdata(dev); | 237 | struct spear_rtc_config *config = dev_get_drvdata(dev); |
238 | unsigned int time, date, err = 0; | 238 | unsigned int time, date; |
239 | 239 | ||
240 | if (tm2bcd(tm) < 0) | 240 | if (tm2bcd(tm) < 0) |
241 | return -EINVAL; | 241 | return -EINVAL; |
@@ -247,11 +247,8 @@ static int spear_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
247 | (tm->tm_year << YEAR_SHIFT); | 247 | (tm->tm_year << YEAR_SHIFT); |
248 | writel(time, config->ioaddr + TIME_REG); | 248 | writel(time, config->ioaddr + TIME_REG); |
249 | writel(date, config->ioaddr + DATE_REG); | 249 | writel(date, config->ioaddr + DATE_REG); |
250 | err = is_write_complete(config); | ||
251 | if (err < 0) | ||
252 | return err; | ||
253 | 250 | ||
254 | return 0; | 251 | return is_write_complete(config); |
255 | } | 252 | } |
256 | 253 | ||
257 | /* | 254 | /* |
@@ -295,7 +292,8 @@ static int spear_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | |||
295 | static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | 292 | static int spear_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) |
296 | { | 293 | { |
297 | struct spear_rtc_config *config = dev_get_drvdata(dev); | 294 | struct spear_rtc_config *config = dev_get_drvdata(dev); |
298 | unsigned int time, date, err = 0; | 295 | unsigned int time, date; |
296 | int err; | ||
299 | 297 | ||
300 | if (tm2bcd(&alm->time) < 0) | 298 | if (tm2bcd(&alm->time) < 0) |
301 | return -EINVAL; | 299 | return -EINVAL; |
@@ -357,7 +355,7 @@ static int __devinit spear_rtc_probe(struct platform_device *pdev) | |||
357 | { | 355 | { |
358 | struct resource *res; | 356 | struct resource *res; |
359 | struct spear_rtc_config *config; | 357 | struct spear_rtc_config *config; |
360 | unsigned int status = 0; | 358 | int status = 0; |
361 | int irq; | 359 | int irq; |
362 | 360 | ||
363 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 361 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 380083ca572f..b70e2bb63645 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
@@ -102,6 +102,12 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, | |||
102 | return n; | 102 | return n; |
103 | } | 103 | } |
104 | 104 | ||
105 | /** | ||
106 | * rtc_sysfs_show_hctosys - indicate if the given RTC set the system time | ||
107 | * | ||
108 | * Returns 1 if the system clock was set by this RTC at the last | ||
109 | * boot or resume event. | ||
110 | */ | ||
105 | static ssize_t | 111 | static ssize_t |
106 | rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, | 112 | rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, |
107 | char *buf) | 113 | char *buf) |
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c new file mode 100644 index 000000000000..7a82337e4dee --- /dev/null +++ b/drivers/rtc/rtc-tps65910.c | |||
@@ -0,0 +1,349 @@ | |||
1 | /* | ||
2 | * rtc-tps65910.c -- TPS65910 Real Time Clock interface | ||
3 | * | ||
4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
5 | * Author: Venu Byravarasu <vbyravarasu@nvidia.com> | ||
6 | * | ||
7 | * Based on original TI driver rtc-twl.c | ||
8 | * Copyright (C) 2007 MontaVista Software, Inc | ||
9 | * Author: Alexandre Rusev <source@mvista.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/bcd.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/mfd/tps65910.h> | ||
27 | |||
28 | struct tps65910_rtc { | ||
29 | struct rtc_device *rtc; | ||
30 | /* To store the list of enabled interrupts */ | ||
31 | u32 irqstat; | ||
32 | }; | ||
33 | |||
34 | /* Total number of RTC registers needed to set time*/ | ||
35 | #define NUM_TIME_REGS (TPS65910_YEARS - TPS65910_SECONDS + 1) | ||
36 | |||
37 | static int tps65910_rtc_alarm_irq_enable(struct device *dev, unsigned enabled) | ||
38 | { | ||
39 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
40 | u8 val = 0; | ||
41 | |||
42 | if (enabled) | ||
43 | val = TPS65910_RTC_INTERRUPTS_IT_ALARM; | ||
44 | |||
45 | return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, val); | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Gets current tps65910 RTC time and date parameters. | ||
50 | * | ||
51 | * The RTC's time/alarm representation is not what gmtime(3) requires | ||
52 | * Linux to use: | ||
53 | * | ||
54 | * - Months are 1..12 vs Linux 0-11 | ||
55 | * - Years are 0..99 vs Linux 1900..N (we assume 21st century) | ||
56 | */ | ||
57 | static int tps65910_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
58 | { | ||
59 | unsigned char rtc_data[NUM_TIME_REGS]; | ||
60 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
61 | int ret; | ||
62 | |||
63 | /* Copy RTC counting registers to static registers or latches */ | ||
64 | ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, | ||
65 | TPS65910_RTC_CTRL_GET_TIME, TPS65910_RTC_CTRL_GET_TIME); | ||
66 | if (ret < 0) { | ||
67 | dev_err(dev, "RTC CTRL reg update failed with err:%d\n", ret); | ||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, rtc_data, | ||
72 | NUM_TIME_REGS); | ||
73 | if (ret < 0) { | ||
74 | dev_err(dev, "reading from RTC failed with err:%d\n", ret); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | tm->tm_sec = bcd2bin(rtc_data[0]); | ||
79 | tm->tm_min = bcd2bin(rtc_data[1]); | ||
80 | tm->tm_hour = bcd2bin(rtc_data[2]); | ||
81 | tm->tm_mday = bcd2bin(rtc_data[3]); | ||
82 | tm->tm_mon = bcd2bin(rtc_data[4]) - 1; | ||
83 | tm->tm_year = bcd2bin(rtc_data[5]) + 100; | ||
84 | |||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | static int tps65910_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
89 | { | ||
90 | unsigned char rtc_data[NUM_TIME_REGS]; | ||
91 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
92 | int ret; | ||
93 | |||
94 | rtc_data[0] = bin2bcd(tm->tm_sec); | ||
95 | rtc_data[1] = bin2bcd(tm->tm_min); | ||
96 | rtc_data[2] = bin2bcd(tm->tm_hour); | ||
97 | rtc_data[3] = bin2bcd(tm->tm_mday); | ||
98 | rtc_data[4] = bin2bcd(tm->tm_mon + 1); | ||
99 | rtc_data[5] = bin2bcd(tm->tm_year - 100); | ||
100 | |||
101 | /* Stop RTC while updating the RTC time registers */ | ||
102 | ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, | ||
103 | TPS65910_RTC_CTRL_STOP_RTC, 0); | ||
104 | if (ret < 0) { | ||
105 | dev_err(dev, "RTC stop failed with err:%d\n", ret); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | /* update all the time registers in one shot */ | ||
110 | ret = regmap_bulk_write(tps->regmap, TPS65910_SECONDS, rtc_data, | ||
111 | NUM_TIME_REGS); | ||
112 | if (ret < 0) { | ||
113 | dev_err(dev, "rtc_set_time error %d\n", ret); | ||
114 | return ret; | ||
115 | } | ||
116 | |||
117 | /* Start back RTC */ | ||
118 | ret = regmap_update_bits(tps->regmap, TPS65910_RTC_CTRL, | ||
119 | TPS65910_RTC_CTRL_STOP_RTC, 1); | ||
120 | if (ret < 0) | ||
121 | dev_err(dev, "RTC start failed with err:%d\n", ret); | ||
122 | |||
123 | return ret; | ||
124 | } | ||
125 | |||
126 | /* | ||
127 | * Gets current tps65910 RTC alarm time. | ||
128 | */ | ||
129 | static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
130 | { | ||
131 | unsigned char alarm_data[NUM_TIME_REGS]; | ||
132 | u32 int_val; | ||
133 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
134 | int ret; | ||
135 | |||
136 | ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data, | ||
137 | NUM_TIME_REGS); | ||
138 | if (ret < 0) { | ||
139 | dev_err(dev, "rtc_read_alarm error %d\n", ret); | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | alm->time.tm_sec = bcd2bin(alarm_data[0]); | ||
144 | alm->time.tm_min = bcd2bin(alarm_data[1]); | ||
145 | alm->time.tm_hour = bcd2bin(alarm_data[2]); | ||
146 | alm->time.tm_mday = bcd2bin(alarm_data[3]); | ||
147 | alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1; | ||
148 | alm->time.tm_year = bcd2bin(alarm_data[5]) + 100; | ||
149 | |||
150 | ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, &int_val); | ||
151 | if (ret < 0) | ||
152 | return ret; | ||
153 | |||
154 | if (int_val & TPS65910_RTC_INTERRUPTS_IT_ALARM) | ||
155 | alm->enabled = 1; | ||
156 | |||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | static int tps65910_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) | ||
161 | { | ||
162 | unsigned char alarm_data[NUM_TIME_REGS]; | ||
163 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
164 | int ret; | ||
165 | |||
166 | ret = tps65910_rtc_alarm_irq_enable(dev, 0); | ||
167 | if (ret) | ||
168 | return ret; | ||
169 | |||
170 | alarm_data[0] = bin2bcd(alm->time.tm_sec); | ||
171 | alarm_data[1] = bin2bcd(alm->time.tm_min); | ||
172 | alarm_data[2] = bin2bcd(alm->time.tm_hour); | ||
173 | alarm_data[3] = bin2bcd(alm->time.tm_mday); | ||
174 | alarm_data[4] = bin2bcd(alm->time.tm_mon + 1); | ||
175 | alarm_data[5] = bin2bcd(alm->time.tm_year - 100); | ||
176 | |||
177 | /* update all the alarm registers in one shot */ | ||
178 | ret = regmap_bulk_write(tps->regmap, TPS65910_ALARM_SECONDS, | ||
179 | alarm_data, NUM_TIME_REGS); | ||
180 | if (ret) { | ||
181 | dev_err(dev, "rtc_set_alarm error %d\n", ret); | ||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | if (alm->enabled) | ||
186 | ret = tps65910_rtc_alarm_irq_enable(dev, 1); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static irqreturn_t tps65910_rtc_interrupt(int irq, void *rtc) | ||
192 | { | ||
193 | struct device *dev = rtc; | ||
194 | unsigned long events = 0; | ||
195 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
196 | struct tps65910_rtc *tps_rtc = dev_get_drvdata(dev); | ||
197 | int ret; | ||
198 | u32 rtc_reg; | ||
199 | |||
200 | ret = regmap_read(tps->regmap, TPS65910_RTC_STATUS, &rtc_reg); | ||
201 | if (ret) | ||
202 | return IRQ_NONE; | ||
203 | |||
204 | if (rtc_reg & TPS65910_RTC_STATUS_ALARM) | ||
205 | events = RTC_IRQF | RTC_AF; | ||
206 | |||
207 | ret = regmap_write(tps->regmap, TPS65910_RTC_STATUS, rtc_reg); | ||
208 | if (ret) | ||
209 | return IRQ_NONE; | ||
210 | |||
211 | /* Notify RTC core on event */ | ||
212 | rtc_update_irq(tps_rtc->rtc, 1, events); | ||
213 | |||
214 | return IRQ_HANDLED; | ||
215 | } | ||
216 | |||
217 | static const struct rtc_class_ops tps65910_rtc_ops = { | ||
218 | .read_time = tps65910_rtc_read_time, | ||
219 | .set_time = tps65910_rtc_set_time, | ||
220 | .read_alarm = tps65910_rtc_read_alarm, | ||
221 | .set_alarm = tps65910_rtc_set_alarm, | ||
222 | .alarm_irq_enable = tps65910_rtc_alarm_irq_enable, | ||
223 | }; | ||
224 | |||
225 | static int __devinit tps65910_rtc_probe(struct platform_device *pdev) | ||
226 | { | ||
227 | struct tps65910 *tps65910 = NULL; | ||
228 | struct tps65910_rtc *tps_rtc = NULL; | ||
229 | int ret; | ||
230 | int irq; | ||
231 | u32 rtc_reg; | ||
232 | |||
233 | tps65910 = dev_get_drvdata(pdev->dev.parent); | ||
234 | |||
235 | tps_rtc = devm_kzalloc(&pdev->dev, sizeof(struct tps65910_rtc), | ||
236 | GFP_KERNEL); | ||
237 | if (!tps_rtc) | ||
238 | return -ENOMEM; | ||
239 | |||
240 | /* Clear pending interrupts */ | ||
241 | ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg); | ||
242 | if (ret < 0) | ||
243 | return ret; | ||
244 | |||
245 | ret = regmap_write(tps65910->regmap, TPS65910_RTC_STATUS, rtc_reg); | ||
246 | if (ret < 0) | ||
247 | return ret; | ||
248 | |||
249 | dev_dbg(&pdev->dev, "Enabling rtc-tps65910.\n"); | ||
250 | rtc_reg = TPS65910_RTC_CTRL_STOP_RTC; | ||
251 | ret = regmap_write(tps65910->regmap, TPS65910_RTC_CTRL, rtc_reg); | ||
252 | if (ret < 0) | ||
253 | return ret; | ||
254 | |||
255 | irq = platform_get_irq(pdev, 0); | ||
256 | if (irq <= 0) { | ||
257 | dev_warn(&pdev->dev, "Wake up is not possible as irq = %d\n", | ||
258 | irq); | ||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, | ||
263 | tps65910_rtc_interrupt, IRQF_TRIGGER_LOW, | ||
264 | "rtc-tps65910", &pdev->dev); | ||
265 | if (ret < 0) { | ||
266 | dev_err(&pdev->dev, "IRQ is not free.\n"); | ||
267 | return ret; | ||
268 | } | ||
269 | device_init_wakeup(&pdev->dev, 1); | ||
270 | |||
271 | tps_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev, | ||
272 | &tps65910_rtc_ops, THIS_MODULE); | ||
273 | if (IS_ERR(tps_rtc->rtc)) { | ||
274 | ret = PTR_ERR(tps_rtc->rtc); | ||
275 | dev_err(&pdev->dev, "RTC device register: err %d\n", ret); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | platform_set_drvdata(pdev, tps_rtc); | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* | ||
285 | * Disable tps65910 RTC interrupts. | ||
286 | * Sets status flag to free. | ||
287 | */ | ||
288 | static int __devexit tps65910_rtc_remove(struct platform_device *pdev) | ||
289 | { | ||
290 | /* leave rtc running, but disable irqs */ | ||
291 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
292 | |||
293 | tps65910_rtc_alarm_irq_enable(&rtc->dev, 0); | ||
294 | |||
295 | rtc_device_unregister(rtc); | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | #ifdef CONFIG_PM_SLEEP | ||
300 | |||
301 | static int tps65910_rtc_suspend(struct device *dev) | ||
302 | { | ||
303 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
304 | u8 alarm = TPS65910_RTC_INTERRUPTS_IT_ALARM; | ||
305 | int ret; | ||
306 | |||
307 | /* Store current list of enabled interrupts*/ | ||
308 | ret = regmap_read(tps->regmap, TPS65910_RTC_INTERRUPTS, | ||
309 | &tps->rtc->irqstat); | ||
310 | if (ret < 0) | ||
311 | return ret; | ||
312 | |||
313 | /* Enable RTC ALARM interrupt only */ | ||
314 | return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, alarm); | ||
315 | } | ||
316 | |||
317 | static int tps65910_rtc_resume(struct device *dev) | ||
318 | { | ||
319 | struct tps65910 *tps = dev_get_drvdata(dev->parent); | ||
320 | |||
321 | /* Restore list of enabled interrupts before suspend */ | ||
322 | return regmap_write(tps->regmap, TPS65910_RTC_INTERRUPTS, | ||
323 | tps->rtc->irqstat); | ||
324 | } | ||
325 | |||
326 | static const struct dev_pm_ops tps65910_rtc_pm_ops = { | ||
327 | .suspend = tps65910_rtc_suspend, | ||
328 | .resume = tps65910_rtc_resume, | ||
329 | }; | ||
330 | |||
331 | #define DEV_PM_OPS (&tps65910_rtc_pm_ops) | ||
332 | #else | ||
333 | #define DEV_PM_OPS NULL | ||
334 | #endif | ||
335 | |||
336 | static struct platform_driver tps65910_rtc_driver = { | ||
337 | .probe = tps65910_rtc_probe, | ||
338 | .remove = __devexit_p(tps65910_rtc_remove), | ||
339 | .driver = { | ||
340 | .owner = THIS_MODULE, | ||
341 | .name = "tps65910-rtc", | ||
342 | .pm = DEV_PM_OPS, | ||
343 | }, | ||
344 | }; | ||
345 | |||
346 | module_platform_driver(tps65910_rtc_driver); | ||
347 | MODULE_ALIAS("platform:rtc-tps65910"); | ||
348 | MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>"); | ||
349 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 403b3d41d101..f36e59c6bc01 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c | |||
@@ -97,8 +97,17 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm, | |||
97 | int i; | 97 | int i; |
98 | 98 | ||
99 | struct i2c_msg msgs[] = { | 99 | struct i2c_msg msgs[] = { |
100 | { client->addr, 0, 2, dt_addr }, /* setup read ptr */ | 100 | {/* setup read ptr */ |
101 | { client->addr, I2C_M_RD, 8, buf }, /* read date */ | 101 | .addr = client->addr, |
102 | .len = 2, | ||
103 | .buf = dt_addr | ||
104 | }, | ||
105 | {/* read date */ | ||
106 | .addr = client->addr, | ||
107 | .flags = I2C_M_RD, | ||
108 | .len = 8, | ||
109 | .buf = buf | ||
110 | }, | ||
102 | }; | 111 | }; |
103 | 112 | ||
104 | /* read date registers */ | 113 | /* read date registers */ |
@@ -142,8 +151,17 @@ static int x1205_get_status(struct i2c_client *client, unsigned char *sr) | |||
142 | static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; | 151 | static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; |
143 | 152 | ||
144 | struct i2c_msg msgs[] = { | 153 | struct i2c_msg msgs[] = { |
145 | { client->addr, 0, 2, sr_addr }, /* setup read ptr */ | 154 | { /* setup read ptr */ |
146 | { client->addr, I2C_M_RD, 1, sr }, /* read status */ | 155 | .addr = client->addr, |
156 | .len = 2, | ||
157 | .buf = sr_addr | ||
158 | }, | ||
159 | { /* read status */ | ||
160 | .addr = client->addr, | ||
161 | .flags = I2C_M_RD, | ||
162 | .len = 1, | ||
163 | .buf = sr | ||
164 | }, | ||
147 | }; | 165 | }; |
148 | 166 | ||
149 | /* read status register */ | 167 | /* read status register */ |
@@ -279,8 +297,17 @@ static int x1205_get_dtrim(struct i2c_client *client, int *trim) | |||
279 | static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR }; | 297 | static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR }; |
280 | 298 | ||
281 | struct i2c_msg msgs[] = { | 299 | struct i2c_msg msgs[] = { |
282 | { client->addr, 0, 2, dtr_addr }, /* setup read ptr */ | 300 | { /* setup read ptr */ |
283 | { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */ | 301 | .addr = client->addr, |
302 | .len = 2, | ||
303 | .buf = dtr_addr | ||
304 | }, | ||
305 | { /* read dtr */ | ||
306 | .addr = client->addr, | ||
307 | .flags = I2C_M_RD, | ||
308 | .len = 1, | ||
309 | .buf = &dtr | ||
310 | }, | ||
284 | }; | 311 | }; |
285 | 312 | ||
286 | /* read dtr register */ | 313 | /* read dtr register */ |
@@ -311,8 +338,17 @@ static int x1205_get_atrim(struct i2c_client *client, int *trim) | |||
311 | static unsigned char atr_addr[2] = { 0, X1205_REG_ATR }; | 338 | static unsigned char atr_addr[2] = { 0, X1205_REG_ATR }; |
312 | 339 | ||
313 | struct i2c_msg msgs[] = { | 340 | struct i2c_msg msgs[] = { |
314 | { client->addr, 0, 2, atr_addr }, /* setup read ptr */ | 341 | {/* setup read ptr */ |
315 | { client->addr, I2C_M_RD, 1, &atr }, /* read atr */ | 342 | .addr = client->addr, |
343 | .len = 2, | ||
344 | .buf = atr_addr | ||
345 | }, | ||
346 | {/* read atr */ | ||
347 | .addr = client->addr, | ||
348 | .flags = I2C_M_RD, | ||
349 | .len = 1, | ||
350 | .buf = &atr | ||
351 | }, | ||
316 | }; | 352 | }; |
317 | 353 | ||
318 | /* read atr register */ | 354 | /* read atr register */ |
@@ -381,8 +417,17 @@ static int x1205_validate_client(struct i2c_client *client) | |||
381 | unsigned char addr[2] = { 0, probe_zero_pattern[i] }; | 417 | unsigned char addr[2] = { 0, probe_zero_pattern[i] }; |
382 | 418 | ||
383 | struct i2c_msg msgs[2] = { | 419 | struct i2c_msg msgs[2] = { |
384 | { client->addr, 0, 2, addr }, | 420 | { |
385 | { client->addr, I2C_M_RD, 1, &buf }, | 421 | .addr = client->addr, |
422 | .len = 2, | ||
423 | .buf = addr | ||
424 | }, | ||
425 | { | ||
426 | .addr = client->addr, | ||
427 | .flags = I2C_M_RD, | ||
428 | .len = 1, | ||
429 | .buf = &buf | ||
430 | }, | ||
386 | }; | 431 | }; |
387 | 432 | ||
388 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { | 433 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { |
@@ -409,8 +454,17 @@ static int x1205_validate_client(struct i2c_client *client) | |||
409 | unsigned char addr[2] = { 0, probe_limits_pattern[i].reg }; | 454 | unsigned char addr[2] = { 0, probe_limits_pattern[i].reg }; |
410 | 455 | ||
411 | struct i2c_msg msgs[2] = { | 456 | struct i2c_msg msgs[2] = { |
412 | { client->addr, 0, 2, addr }, | 457 | { |
413 | { client->addr, I2C_M_RD, 1, ® }, | 458 | .addr = client->addr, |
459 | .len = 2, | ||
460 | .buf = addr | ||
461 | }, | ||
462 | { | ||
463 | .addr = client->addr, | ||
464 | .flags = I2C_M_RD, | ||
465 | .len = 1, | ||
466 | .buf = ® | ||
467 | }, | ||
414 | }; | 468 | }; |
415 | 469 | ||
416 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { | 470 | if ((xfer = i2c_transfer(client->adapter, msgs, 2)) != 2) { |
@@ -444,8 +498,18 @@ static int x1205_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
444 | static unsigned char int_addr[2] = { 0, X1205_REG_INT }; | 498 | static unsigned char int_addr[2] = { 0, X1205_REG_INT }; |
445 | struct i2c_client *client = to_i2c_client(dev); | 499 | struct i2c_client *client = to_i2c_client(dev); |
446 | struct i2c_msg msgs[] = { | 500 | struct i2c_msg msgs[] = { |
447 | { client->addr, 0, 2, int_addr }, /* setup read ptr */ | 501 | { /* setup read ptr */ |
448 | { client->addr, I2C_M_RD, 1, &intreg }, /* read INT register */ | 502 | .addr = client->addr, |
503 | .len = 2, | ||
504 | .buf = int_addr | ||
505 | }, | ||
506 | {/* read INT register */ | ||
507 | |||
508 | .addr = client->addr, | ||
509 | .flags = I2C_M_RD, | ||
510 | .len = 1, | ||
511 | .buf = &intreg | ||
512 | }, | ||
449 | }; | 513 | }; |
450 | 514 | ||
451 | /* read interrupt register and status register */ | 515 | /* read interrupt register and status register */ |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 7199534cd07d..cb7f1582a6d1 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -93,7 +93,7 @@ static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = { | |||
93 | #elif defined(__devinitconst) | 93 | #elif defined(__devinitconst) |
94 | static const struct pci_device_id aac_pci_tbl[] __devinitconst = { | 94 | static const struct pci_device_id aac_pci_tbl[] __devinitconst = { |
95 | #else | 95 | #else |
96 | static const struct pci_device_id aac_pci_tbl[] __devinitdata = { | 96 | static const struct pci_device_id aac_pci_tbl[] __devinitconst = { |
97 | #endif | 97 | #endif |
98 | { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */ | 98 | { 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */ |
99 | { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */ | 99 | { 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */ |
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index ff80552ead84..1c4120c3db41 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c | |||
@@ -1012,7 +1012,7 @@ static struct sas_domain_function_template aic94xx_transport_functions = { | |||
1012 | .lldd_ata_set_dmamode = asd_set_dmamode, | 1012 | .lldd_ata_set_dmamode = asd_set_dmamode, |
1013 | }; | 1013 | }; |
1014 | 1014 | ||
1015 | static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { | 1015 | static const struct pci_device_id aic94xx_pci_table[] __devinitconst = { |
1016 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1}, | 1016 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1}, |
1017 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1}, | 1017 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1}, |
1018 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1}, | 1018 | {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1}, |
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 68ce08552f69..a540162ac59c 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c | |||
@@ -1173,7 +1173,16 @@ wait_io1: | |||
1173 | outw(val, tmport); | 1173 | outw(val, tmport); |
1174 | outb(2, 0x80); | 1174 | outb(2, 0x80); |
1175 | TCM_SYNC: | 1175 | TCM_SYNC: |
1176 | udelay(0x800); | 1176 | /* |
1177 | * The funny division into multiple delays is to accomodate | ||
1178 | * arches like ARM where udelay() multiplies its argument by | ||
1179 | * a large number to initialize a loop counter. To avoid | ||
1180 | * overflow, the maximum supported udelay is 2000 microseconds. | ||
1181 | * | ||
1182 | * XXX it would be more polite to find a way to use msleep() | ||
1183 | */ | ||
1184 | mdelay(2); | ||
1185 | udelay(48); | ||
1177 | if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ | 1186 | if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ |
1178 | outw(0, tmport--); | 1187 | outw(0, tmport--); |
1179 | outb(0, tmport); | 1188 | outb(0, tmport); |
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 67789b8345d2..efd81bb25e01 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -78,7 +78,7 @@ again: | |||
78 | else if (unlikely(err)) | 78 | else if (unlikely(err)) |
79 | return err; | 79 | return err; |
80 | 80 | ||
81 | *id = *id & MAX_ID_MASK; | 81 | *id = *id & MAX_IDR_MASK; |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 747442d2c0f6..0fefa84ed9ae 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
@@ -149,7 +149,7 @@ enum { | |||
149 | }; | 149 | }; |
150 | 150 | ||
151 | /* Must match above enum */ | 151 | /* Must match above enum */ |
152 | static const char *r128_family[] __devinitdata = { | 152 | static char * const r128_family[] __devinitconst = { |
153 | "AGP", | 153 | "AGP", |
154 | "PCI", | 154 | "PCI", |
155 | "PRO AGP", | 155 | "PRO AGP", |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 63cee2e9d622..c101697a4ba7 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -229,13 +229,6 @@ config BACKLIGHT_HP700 | |||
229 | If you have an HP Jornada 700 series, | 229 | If you have an HP Jornada 700 series, |
230 | say Y to include backlight control driver. | 230 | say Y to include backlight control driver. |
231 | 231 | ||
232 | config BACKLIGHT_PROGEAR | ||
233 | tristate "Frontpath ProGear Backlight Driver" | ||
234 | depends on PCI && X86 | ||
235 | help | ||
236 | If you have a Frontpath ProGear say Y to enable the | ||
237 | backlight driver. | ||
238 | |||
239 | config BACKLIGHT_CARILLO_RANCH | 232 | config BACKLIGHT_CARILLO_RANCH |
240 | tristate "Intel Carillo Ranch Backlight Driver" | 233 | tristate "Intel Carillo Ranch Backlight Driver" |
241 | depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 | 234 | depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 |
@@ -352,6 +345,22 @@ config BACKLIGHT_AAT2870 | |||
352 | If you have a AnalogicTech AAT2870 say Y to enable the | 345 | If you have a AnalogicTech AAT2870 say Y to enable the |
353 | backlight driver. | 346 | backlight driver. |
354 | 347 | ||
348 | config BACKLIGHT_LM3630 | ||
349 | tristate "Backlight Driver for LM3630" | ||
350 | depends on BACKLIGHT_CLASS_DEVICE && I2C | ||
351 | select REGMAP_I2C | ||
352 | help | ||
353 | This supports TI LM3630 Backlight Driver | ||
354 | |||
355 | config BACKLIGHT_LM3639 | ||
356 | tristate "Backlight Driver for LM3639" | ||
357 | depends on BACKLIGHT_CLASS_DEVICE && I2C | ||
358 | select REGMAP_I2C | ||
359 | select NEW_LEDS | ||
360 | select LEDS_CLASS | ||
361 | help | ||
362 | This supports TI LM3639 Backlight + 1.5A Flash LED Driver | ||
363 | |||
355 | config BACKLIGHT_LP855X | 364 | config BACKLIGHT_LP855X |
356 | tristate "Backlight driver for TI LP855X" | 365 | tristate "Backlight driver for TI LP855X" |
357 | depends on BACKLIGHT_CLASS_DEVICE && I2C | 366 | depends on BACKLIGHT_CLASS_DEVICE && I2C |
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 00223a62ec12..e7ce7291635d 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -23,10 +23,11 @@ obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o | |||
23 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o | 23 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o |
24 | obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o | 24 | obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o |
25 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o | 25 | obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o |
26 | obj-$(CONFIG_BACKLIGHT_LM3630) += lm3630_bl.o | ||
27 | obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o | ||
26 | obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o | 28 | obj-$(CONFIG_BACKLIGHT_LP855X) += lp855x_bl.o |
27 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o | 29 | obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o |
28 | obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o | 30 | obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o |
29 | obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o | ||
30 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o | 31 | obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o |
31 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o | 32 | obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o |
32 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o | 33 | obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o |
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c index b628d68f5162..ac196181fe45 100644 --- a/drivers/video/backlight/da9052_bl.c +++ b/drivers/video/backlight/da9052_bl.c | |||
@@ -72,7 +72,7 @@ static int da9052_adjust_wled_brightness(struct da9052_bl *wleds) | |||
72 | if (ret < 0) | 72 | if (ret < 0) |
73 | return ret; | 73 | return ret; |
74 | 74 | ||
75 | msleep(10); | 75 | usleep_range(10000, 11000); |
76 | 76 | ||
77 | if (wleds->brightness) { | 77 | if (wleds->brightness) { |
78 | ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], | 78 | ret = da9052_reg_write(wleds->da9052, wled_bank[wleds->led_reg], |
@@ -129,7 +129,6 @@ static int da9052_backlight_probe(struct platform_device *pdev) | |||
129 | &da9052_backlight_ops, &props); | 129 | &da9052_backlight_ops, &props); |
130 | if (IS_ERR(bl)) { | 130 | if (IS_ERR(bl)) { |
131 | dev_err(&pdev->dev, "Failed to register backlight\n"); | 131 | dev_err(&pdev->dev, "Failed to register backlight\n"); |
132 | devm_kfree(&pdev->dev, wleds); | ||
133 | return PTR_ERR(bl); | 132 | return PTR_ERR(bl); |
134 | } | 133 | } |
135 | 134 | ||
@@ -149,7 +148,6 @@ static int da9052_backlight_remove(struct platform_device *pdev) | |||
149 | wleds->state = DA9052_WLEDS_OFF; | 148 | wleds->state = DA9052_WLEDS_OFF; |
150 | da9052_adjust_wled_brightness(wleds); | 149 | da9052_adjust_wled_brightness(wleds); |
151 | backlight_device_unregister(bl); | 150 | backlight_device_unregister(bl); |
152 | devm_kfree(&pdev->dev, wleds); | ||
153 | 151 | ||
154 | return 0; | 152 | return 0; |
155 | } | 153 | } |
diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index 72dd5556a35b..6c5ed6b242cc 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c | |||
@@ -34,9 +34,9 @@ static void kb3886_bl_set_intensity(int intensity) | |||
34 | mutex_lock(&bl_mutex); | 34 | mutex_lock(&bl_mutex); |
35 | intensity = intensity&0xff; | 35 | intensity = intensity&0xff; |
36 | outb(KB3886_ADC_DAC_PWM, KB3886_PARENT); | 36 | outb(KB3886_ADC_DAC_PWM, KB3886_PARENT); |
37 | msleep(10); | 37 | usleep_range(10000, 11000); |
38 | outb(KB3886_PWM0_WRITE, KB3886_IO); | 38 | outb(KB3886_PWM0_WRITE, KB3886_IO); |
39 | msleep(10); | 39 | usleep_range(10000, 11000); |
40 | outb(intensity, KB3886_IO); | 40 | outb(intensity, KB3886_IO); |
41 | mutex_unlock(&bl_mutex); | 41 | mutex_unlock(&bl_mutex); |
42 | } | 42 | } |
diff --git a/drivers/video/backlight/lm3630_bl.c b/drivers/video/backlight/lm3630_bl.c new file mode 100644 index 000000000000..dc191441796f --- /dev/null +++ b/drivers/video/backlight/lm3630_bl.c | |||
@@ -0,0 +1,475 @@ | |||
1 | /* | ||
2 | * Simple driver for Texas Instruments LM3630 Backlight driver chip | ||
3 | * Copyright (C) 2012 Texas Instruments | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/backlight.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/uaccess.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/regmap.h> | ||
19 | #include <linux/platform_data/lm3630_bl.h> | ||
20 | |||
21 | #define REG_CTRL 0x00 | ||
22 | #define REG_CONFIG 0x01 | ||
23 | #define REG_BRT_A 0x03 | ||
24 | #define REG_BRT_B 0x04 | ||
25 | #define REG_INT_STATUS 0x09 | ||
26 | #define REG_INT_EN 0x0A | ||
27 | #define REG_FAULT 0x0B | ||
28 | #define REG_PWM_OUTLOW 0x12 | ||
29 | #define REG_PWM_OUTHIGH 0x13 | ||
30 | #define REG_MAX 0x1F | ||
31 | |||
32 | #define INT_DEBOUNCE_MSEC 10 | ||
33 | |||
34 | enum lm3630_leds { | ||
35 | BLED_ALL = 0, | ||
36 | BLED_1, | ||
37 | BLED_2 | ||
38 | }; | ||
39 | |||
40 | static const char *bled_name[] = { | ||
41 | [BLED_ALL] = "lm3630_bled", /*Bank1 controls all string */ | ||
42 | [BLED_1] = "lm3630_bled1", /*Bank1 controls bled1 */ | ||
43 | [BLED_2] = "lm3630_bled2", /*Bank1 or 2 controls bled2 */ | ||
44 | }; | ||
45 | |||
46 | struct lm3630_chip_data { | ||
47 | struct device *dev; | ||
48 | struct delayed_work work; | ||
49 | int irq; | ||
50 | struct workqueue_struct *irqthread; | ||
51 | struct lm3630_platform_data *pdata; | ||
52 | struct backlight_device *bled1; | ||
53 | struct backlight_device *bled2; | ||
54 | struct regmap *regmap; | ||
55 | }; | ||
56 | |||
57 | /* initialize chip */ | ||
58 | static int __devinit lm3630_chip_init(struct lm3630_chip_data *pchip) | ||
59 | { | ||
60 | int ret; | ||
61 | unsigned int reg_val; | ||
62 | struct lm3630_platform_data *pdata = pchip->pdata; | ||
63 | |||
64 | /*pwm control */ | ||
65 | reg_val = ((pdata->pwm_active & 0x01) << 2) | (pdata->pwm_ctrl & 0x03); | ||
66 | ret = regmap_update_bits(pchip->regmap, REG_CONFIG, 0x07, reg_val); | ||
67 | if (ret < 0) | ||
68 | goto out; | ||
69 | |||
70 | /* bank control */ | ||
71 | reg_val = ((pdata->bank_b_ctrl & 0x01) << 1) | | ||
72 | (pdata->bank_a_ctrl & 0x07); | ||
73 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x07, reg_val); | ||
74 | if (ret < 0) | ||
75 | goto out; | ||
76 | |||
77 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
78 | if (ret < 0) | ||
79 | goto out; | ||
80 | |||
81 | /* set initial brightness */ | ||
82 | if (pdata->bank_a_ctrl != BANK_A_CTRL_DISABLE) { | ||
83 | ret = regmap_write(pchip->regmap, | ||
84 | REG_BRT_A, pdata->init_brt_led1); | ||
85 | if (ret < 0) | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | if (pdata->bank_b_ctrl != BANK_B_CTRL_DISABLE) { | ||
90 | ret = regmap_write(pchip->regmap, | ||
91 | REG_BRT_B, pdata->init_brt_led2); | ||
92 | if (ret < 0) | ||
93 | goto out; | ||
94 | } | ||
95 | return ret; | ||
96 | |||
97 | out: | ||
98 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | /* interrupt handling */ | ||
103 | static void lm3630_delayed_func(struct work_struct *work) | ||
104 | { | ||
105 | int ret; | ||
106 | unsigned int reg_val; | ||
107 | struct lm3630_chip_data *pchip; | ||
108 | |||
109 | pchip = container_of(work, struct lm3630_chip_data, work.work); | ||
110 | |||
111 | ret = regmap_read(pchip->regmap, REG_INT_STATUS, ®_val); | ||
112 | if (ret < 0) { | ||
113 | dev_err(pchip->dev, | ||
114 | "i2c failed to access REG_INT_STATUS Register\n"); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | dev_info(pchip->dev, "REG_INT_STATUS Register is 0x%x\n", reg_val); | ||
119 | } | ||
120 | |||
121 | static irqreturn_t lm3630_isr_func(int irq, void *chip) | ||
122 | { | ||
123 | int ret; | ||
124 | struct lm3630_chip_data *pchip = chip; | ||
125 | unsigned long delay = msecs_to_jiffies(INT_DEBOUNCE_MSEC); | ||
126 | |||
127 | queue_delayed_work(pchip->irqthread, &pchip->work, delay); | ||
128 | |||
129 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
130 | if (ret < 0) | ||
131 | goto out; | ||
132 | |||
133 | return IRQ_HANDLED; | ||
134 | out: | ||
135 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
136 | return IRQ_HANDLED; | ||
137 | } | ||
138 | |||
139 | static int lm3630_intr_config(struct lm3630_chip_data *pchip) | ||
140 | { | ||
141 | INIT_DELAYED_WORK(&pchip->work, lm3630_delayed_func); | ||
142 | pchip->irqthread = create_singlethread_workqueue("lm3630-irqthd"); | ||
143 | if (!pchip->irqthread) { | ||
144 | dev_err(pchip->dev, "create irq thread fail...\n"); | ||
145 | return -1; | ||
146 | } | ||
147 | if (request_threaded_irq | ||
148 | (pchip->irq, NULL, lm3630_isr_func, | ||
149 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "lm3630_irq", pchip)) { | ||
150 | dev_err(pchip->dev, "request threaded irq fail..\n"); | ||
151 | return -1; | ||
152 | } | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static bool | ||
157 | set_intensity(struct backlight_device *bl, struct lm3630_chip_data *pchip) | ||
158 | { | ||
159 | if (!pchip->pdata->pwm_set_intensity) | ||
160 | return false; | ||
161 | pchip->pdata->pwm_set_intensity(bl->props.brightness - 1, | ||
162 | pchip->pdata->pwm_period); | ||
163 | return true; | ||
164 | } | ||
165 | |||
166 | /* update and get brightness */ | ||
167 | static int lm3630_bank_a_update_status(struct backlight_device *bl) | ||
168 | { | ||
169 | int ret; | ||
170 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
171 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
172 | |||
173 | /* brightness 0 means disable */ | ||
174 | if (!bl->props.brightness) { | ||
175 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x04, 0x00); | ||
176 | if (ret < 0) | ||
177 | goto out; | ||
178 | return bl->props.brightness; | ||
179 | } | ||
180 | |||
181 | /* pwm control */ | ||
182 | if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
183 | if (!set_intensity(bl, pchip)) | ||
184 | dev_err(pchip->dev, "No pwm control func. in plat-data\n"); | ||
185 | } else { | ||
186 | |||
187 | /* i2c control */ | ||
188 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
189 | if (ret < 0) | ||
190 | goto out; | ||
191 | mdelay(1); | ||
192 | ret = regmap_write(pchip->regmap, | ||
193 | REG_BRT_A, bl->props.brightness - 1); | ||
194 | if (ret < 0) | ||
195 | goto out; | ||
196 | } | ||
197 | return bl->props.brightness; | ||
198 | out: | ||
199 | dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); | ||
200 | return bl->props.brightness; | ||
201 | } | ||
202 | |||
203 | static int lm3630_bank_a_get_brightness(struct backlight_device *bl) | ||
204 | { | ||
205 | unsigned int reg_val; | ||
206 | int brightness, ret; | ||
207 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
208 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
209 | |||
210 | if (pwm_ctrl == PWM_CTRL_BANK_A || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
211 | ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, ®_val); | ||
212 | if (ret < 0) | ||
213 | goto out; | ||
214 | brightness = reg_val & 0x01; | ||
215 | ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, ®_val); | ||
216 | if (ret < 0) | ||
217 | goto out; | ||
218 | brightness = ((brightness << 8) | reg_val) + 1; | ||
219 | } else { | ||
220 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
221 | if (ret < 0) | ||
222 | goto out; | ||
223 | mdelay(1); | ||
224 | ret = regmap_read(pchip->regmap, REG_BRT_A, ®_val); | ||
225 | if (ret < 0) | ||
226 | goto out; | ||
227 | brightness = reg_val + 1; | ||
228 | } | ||
229 | bl->props.brightness = brightness; | ||
230 | return bl->props.brightness; | ||
231 | out: | ||
232 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static const struct backlight_ops lm3630_bank_a_ops = { | ||
237 | .options = BL_CORE_SUSPENDRESUME, | ||
238 | .update_status = lm3630_bank_a_update_status, | ||
239 | .get_brightness = lm3630_bank_a_get_brightness, | ||
240 | }; | ||
241 | |||
242 | static int lm3630_bank_b_update_status(struct backlight_device *bl) | ||
243 | { | ||
244 | int ret; | ||
245 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
246 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
247 | |||
248 | if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
249 | if (!set_intensity(bl, pchip)) | ||
250 | dev_err(pchip->dev, | ||
251 | "no pwm control func. in plat-data\n"); | ||
252 | } else { | ||
253 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
254 | if (ret < 0) | ||
255 | goto out; | ||
256 | mdelay(1); | ||
257 | ret = regmap_write(pchip->regmap, | ||
258 | REG_BRT_B, bl->props.brightness - 1); | ||
259 | } | ||
260 | return bl->props.brightness; | ||
261 | out: | ||
262 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
263 | return bl->props.brightness; | ||
264 | } | ||
265 | |||
266 | static int lm3630_bank_b_get_brightness(struct backlight_device *bl) | ||
267 | { | ||
268 | unsigned int reg_val; | ||
269 | int brightness, ret; | ||
270 | struct lm3630_chip_data *pchip = bl_get_data(bl); | ||
271 | enum lm3630_pwm_ctrl pwm_ctrl = pchip->pdata->pwm_ctrl; | ||
272 | |||
273 | if (pwm_ctrl == PWM_CTRL_BANK_B || pwm_ctrl == PWM_CTRL_BANK_ALL) { | ||
274 | ret = regmap_read(pchip->regmap, REG_PWM_OUTHIGH, ®_val); | ||
275 | if (ret < 0) | ||
276 | goto out; | ||
277 | brightness = reg_val & 0x01; | ||
278 | ret = regmap_read(pchip->regmap, REG_PWM_OUTLOW, ®_val); | ||
279 | if (ret < 0) | ||
280 | goto out; | ||
281 | brightness = ((brightness << 8) | reg_val) + 1; | ||
282 | } else { | ||
283 | ret = regmap_update_bits(pchip->regmap, REG_CTRL, 0x80, 0x00); | ||
284 | if (ret < 0) | ||
285 | goto out; | ||
286 | mdelay(1); | ||
287 | ret = regmap_read(pchip->regmap, REG_BRT_B, ®_val); | ||
288 | if (ret < 0) | ||
289 | goto out; | ||
290 | brightness = reg_val + 1; | ||
291 | } | ||
292 | bl->props.brightness = brightness; | ||
293 | |||
294 | return bl->props.brightness; | ||
295 | out: | ||
296 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
297 | return bl->props.brightness; | ||
298 | } | ||
299 | |||
300 | static const struct backlight_ops lm3630_bank_b_ops = { | ||
301 | .options = BL_CORE_SUSPENDRESUME, | ||
302 | .update_status = lm3630_bank_b_update_status, | ||
303 | .get_brightness = lm3630_bank_b_get_brightness, | ||
304 | }; | ||
305 | |||
306 | static int lm3630_backlight_register(struct lm3630_chip_data *pchip, | ||
307 | enum lm3630_leds ledno) | ||
308 | { | ||
309 | const char *name = bled_name[ledno]; | ||
310 | struct backlight_properties props; | ||
311 | struct lm3630_platform_data *pdata = pchip->pdata; | ||
312 | |||
313 | props.type = BACKLIGHT_RAW; | ||
314 | switch (ledno) { | ||
315 | case BLED_1: | ||
316 | case BLED_ALL: | ||
317 | props.brightness = pdata->init_brt_led1; | ||
318 | props.max_brightness = pdata->max_brt_led1; | ||
319 | pchip->bled1 = | ||
320 | backlight_device_register(name, pchip->dev, pchip, | ||
321 | &lm3630_bank_a_ops, &props); | ||
322 | if (IS_ERR(pchip->bled1)) | ||
323 | return -EIO; | ||
324 | break; | ||
325 | case BLED_2: | ||
326 | props.brightness = pdata->init_brt_led2; | ||
327 | props.max_brightness = pdata->max_brt_led2; | ||
328 | pchip->bled2 = | ||
329 | backlight_device_register(name, pchip->dev, pchip, | ||
330 | &lm3630_bank_b_ops, &props); | ||
331 | if (IS_ERR(pchip->bled2)) | ||
332 | return -EIO; | ||
333 | break; | ||
334 | } | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static void lm3630_backlight_unregister(struct lm3630_chip_data *pchip) | ||
339 | { | ||
340 | if (pchip->bled1) | ||
341 | backlight_device_unregister(pchip->bled1); | ||
342 | if (pchip->bled2) | ||
343 | backlight_device_unregister(pchip->bled2); | ||
344 | } | ||
345 | |||
346 | static const struct regmap_config lm3630_regmap = { | ||
347 | .reg_bits = 8, | ||
348 | .val_bits = 8, | ||
349 | .max_register = REG_MAX, | ||
350 | }; | ||
351 | |||
352 | static int __devinit lm3630_probe(struct i2c_client *client, | ||
353 | const struct i2c_device_id *id) | ||
354 | { | ||
355 | struct lm3630_platform_data *pdata = client->dev.platform_data; | ||
356 | struct lm3630_chip_data *pchip; | ||
357 | int ret; | ||
358 | |||
359 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
360 | dev_err(&client->dev, "fail : i2c functionality check...\n"); | ||
361 | return -EOPNOTSUPP; | ||
362 | } | ||
363 | |||
364 | if (pdata == NULL) { | ||
365 | dev_err(&client->dev, "fail : no platform data.\n"); | ||
366 | return -ENODATA; | ||
367 | } | ||
368 | |||
369 | pchip = devm_kzalloc(&client->dev, sizeof(struct lm3630_chip_data), | ||
370 | GFP_KERNEL); | ||
371 | if (!pchip) | ||
372 | return -ENOMEM; | ||
373 | pchip->pdata = pdata; | ||
374 | pchip->dev = &client->dev; | ||
375 | |||
376 | pchip->regmap = devm_regmap_init_i2c(client, &lm3630_regmap); | ||
377 | if (IS_ERR(pchip->regmap)) { | ||
378 | ret = PTR_ERR(pchip->regmap); | ||
379 | dev_err(&client->dev, "fail : allocate register map: %d\n", | ||
380 | ret); | ||
381 | return ret; | ||
382 | } | ||
383 | i2c_set_clientdata(client, pchip); | ||
384 | |||
385 | /* chip initialize */ | ||
386 | ret = lm3630_chip_init(pchip); | ||
387 | if (ret < 0) { | ||
388 | dev_err(&client->dev, "fail : init chip\n"); | ||
389 | goto err_chip_init; | ||
390 | } | ||
391 | |||
392 | switch (pdata->bank_a_ctrl) { | ||
393 | case BANK_A_CTRL_ALL: | ||
394 | ret = lm3630_backlight_register(pchip, BLED_ALL); | ||
395 | pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE; | ||
396 | break; | ||
397 | case BANK_A_CTRL_LED1: | ||
398 | ret = lm3630_backlight_register(pchip, BLED_1); | ||
399 | break; | ||
400 | case BANK_A_CTRL_LED2: | ||
401 | ret = lm3630_backlight_register(pchip, BLED_2); | ||
402 | pdata->bank_b_ctrl = BANK_B_CTRL_DISABLE; | ||
403 | break; | ||
404 | default: | ||
405 | break; | ||
406 | } | ||
407 | |||
408 | if (ret < 0) | ||
409 | goto err_bl_reg; | ||
410 | |||
411 | if (pdata->bank_b_ctrl && pchip->bled2 == NULL) { | ||
412 | ret = lm3630_backlight_register(pchip, BLED_2); | ||
413 | if (ret < 0) | ||
414 | goto err_bl_reg; | ||
415 | } | ||
416 | |||
417 | /* interrupt enable : irq 0 is not allowed for lm3630 */ | ||
418 | pchip->irq = client->irq; | ||
419 | if (pchip->irq) | ||
420 | lm3630_intr_config(pchip); | ||
421 | |||
422 | dev_info(&client->dev, "LM3630 backlight register OK.\n"); | ||
423 | return 0; | ||
424 | |||
425 | err_bl_reg: | ||
426 | dev_err(&client->dev, "fail : backlight register.\n"); | ||
427 | lm3630_backlight_unregister(pchip); | ||
428 | err_chip_init: | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static int __devexit lm3630_remove(struct i2c_client *client) | ||
433 | { | ||
434 | int ret; | ||
435 | struct lm3630_chip_data *pchip = i2c_get_clientdata(client); | ||
436 | |||
437 | ret = regmap_write(pchip->regmap, REG_BRT_A, 0); | ||
438 | if (ret < 0) | ||
439 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
440 | |||
441 | ret = regmap_write(pchip->regmap, REG_BRT_B, 0); | ||
442 | if (ret < 0) | ||
443 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
444 | |||
445 | lm3630_backlight_unregister(pchip); | ||
446 | if (pchip->irq) { | ||
447 | free_irq(pchip->irq, pchip); | ||
448 | flush_workqueue(pchip->irqthread); | ||
449 | destroy_workqueue(pchip->irqthread); | ||
450 | } | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static const struct i2c_device_id lm3630_id[] = { | ||
455 | {LM3630_NAME, 0}, | ||
456 | {} | ||
457 | }; | ||
458 | |||
459 | MODULE_DEVICE_TABLE(i2c, lm3630_id); | ||
460 | |||
461 | static struct i2c_driver lm3630_i2c_driver = { | ||
462 | .driver = { | ||
463 | .name = LM3630_NAME, | ||
464 | }, | ||
465 | .probe = lm3630_probe, | ||
466 | .remove = __devexit_p(lm3630_remove), | ||
467 | .id_table = lm3630_id, | ||
468 | }; | ||
469 | |||
470 | module_i2c_driver(lm3630_i2c_driver); | ||
471 | |||
472 | MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3630"); | ||
473 | MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); | ||
474 | MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); | ||
475 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c new file mode 100644 index 000000000000..c6915c6c3cd1 --- /dev/null +++ b/drivers/video/backlight/lm3639_bl.c | |||
@@ -0,0 +1,437 @@ | |||
1 | /* | ||
2 | * Simple driver for Texas Instruments LM3639 Backlight + Flash LED driver chip | ||
3 | * Copyright (C) 2012 Texas Instruments | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/slab.h> | ||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/leds.h> | ||
14 | #include <linux/backlight.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/regmap.h> | ||
20 | #include <linux/platform_data/lm3639_bl.h> | ||
21 | |||
22 | #define REG_DEV_ID 0x00 | ||
23 | #define REG_CHECKSUM 0x01 | ||
24 | #define REG_BL_CONF_1 0x02 | ||
25 | #define REG_BL_CONF_2 0x03 | ||
26 | #define REG_BL_CONF_3 0x04 | ||
27 | #define REG_BL_CONF_4 0x05 | ||
28 | #define REG_FL_CONF_1 0x06 | ||
29 | #define REG_FL_CONF_2 0x07 | ||
30 | #define REG_FL_CONF_3 0x08 | ||
31 | #define REG_IO_CTRL 0x09 | ||
32 | #define REG_ENABLE 0x0A | ||
33 | #define REG_FLAG 0x0B | ||
34 | #define REG_MAX REG_FLAG | ||
35 | |||
36 | struct lm3639_chip_data { | ||
37 | struct device *dev; | ||
38 | struct lm3639_platform_data *pdata; | ||
39 | |||
40 | struct backlight_device *bled; | ||
41 | struct led_classdev cdev_flash; | ||
42 | struct led_classdev cdev_torch; | ||
43 | struct regmap *regmap; | ||
44 | |||
45 | unsigned int bled_mode; | ||
46 | unsigned int bled_map; | ||
47 | unsigned int last_flag; | ||
48 | }; | ||
49 | |||
50 | /* initialize chip */ | ||
51 | static int __devinit lm3639_chip_init(struct lm3639_chip_data *pchip) | ||
52 | { | ||
53 | int ret; | ||
54 | unsigned int reg_val; | ||
55 | struct lm3639_platform_data *pdata = pchip->pdata; | ||
56 | |||
57 | /* input pins config. */ | ||
58 | ret = | ||
59 | regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x08, | ||
60 | pdata->pin_pwm); | ||
61 | if (ret < 0) | ||
62 | goto out; | ||
63 | |||
64 | reg_val = (pdata->pin_pwm & 0x40) | pdata->pin_strobe | pdata->pin_tx; | ||
65 | ret = regmap_update_bits(pchip->regmap, REG_IO_CTRL, 0x7C, reg_val); | ||
66 | if (ret < 0) | ||
67 | goto out; | ||
68 | |||
69 | /* init brightness */ | ||
70 | ret = regmap_write(pchip->regmap, REG_BL_CONF_4, pdata->init_brt_led); | ||
71 | if (ret < 0) | ||
72 | goto out; | ||
73 | |||
74 | ret = regmap_write(pchip->regmap, REG_BL_CONF_3, pdata->init_brt_led); | ||
75 | if (ret < 0) | ||
76 | goto out; | ||
77 | |||
78 | /* output pins config. */ | ||
79 | if (!pdata->init_brt_led) | ||
80 | reg_val = pdata->fled_pins | pdata->bled_pins; | ||
81 | else | ||
82 | reg_val = pdata->fled_pins | pdata->bled_pins | 0x01; | ||
83 | |||
84 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x79, reg_val); | ||
85 | if (ret < 0) | ||
86 | goto out; | ||
87 | |||
88 | return ret; | ||
89 | out: | ||
90 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
91 | return ret; | ||
92 | } | ||
93 | |||
94 | /* update and get brightness */ | ||
95 | static int lm3639_bled_update_status(struct backlight_device *bl) | ||
96 | { | ||
97 | int ret; | ||
98 | unsigned int reg_val; | ||
99 | struct lm3639_chip_data *pchip = bl_get_data(bl); | ||
100 | struct lm3639_platform_data *pdata = pchip->pdata; | ||
101 | |||
102 | ret = regmap_read(pchip->regmap, REG_FLAG, ®_val); | ||
103 | if (ret < 0) | ||
104 | goto out; | ||
105 | |||
106 | if (reg_val != 0) | ||
107 | dev_info(pchip->dev, "last flag is 0x%x\n", reg_val); | ||
108 | |||
109 | /* pwm control */ | ||
110 | if (pdata->pin_pwm) { | ||
111 | if (pdata->pwm_set_intensity) | ||
112 | pdata->pwm_set_intensity(bl->props.brightness, | ||
113 | pdata->max_brt_led); | ||
114 | else | ||
115 | dev_err(pchip->dev, | ||
116 | "No pwm control func. in plat-data\n"); | ||
117 | return bl->props.brightness; | ||
118 | } | ||
119 | |||
120 | /* i2c control and set brigtness */ | ||
121 | ret = regmap_write(pchip->regmap, REG_BL_CONF_4, bl->props.brightness); | ||
122 | if (ret < 0) | ||
123 | goto out; | ||
124 | ret = regmap_write(pchip->regmap, REG_BL_CONF_3, bl->props.brightness); | ||
125 | if (ret < 0) | ||
126 | goto out; | ||
127 | |||
128 | if (!bl->props.brightness) | ||
129 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x00); | ||
130 | else | ||
131 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x01); | ||
132 | if (ret < 0) | ||
133 | goto out; | ||
134 | |||
135 | return bl->props.brightness; | ||
136 | out: | ||
137 | dev_err(pchip->dev, "i2c failed to access registers\n"); | ||
138 | return bl->props.brightness; | ||
139 | } | ||
140 | |||
141 | static int lm3639_bled_get_brightness(struct backlight_device *bl) | ||
142 | { | ||
143 | int ret; | ||
144 | unsigned int reg_val; | ||
145 | struct lm3639_chip_data *pchip = bl_get_data(bl); | ||
146 | struct lm3639_platform_data *pdata = pchip->pdata; | ||
147 | |||
148 | if (pdata->pin_pwm) { | ||
149 | if (pdata->pwm_get_intensity) | ||
150 | bl->props.brightness = pdata->pwm_get_intensity(); | ||
151 | else | ||
152 | dev_err(pchip->dev, | ||
153 | "No pwm control func. in plat-data\n"); | ||
154 | return bl->props.brightness; | ||
155 | } | ||
156 | |||
157 | ret = regmap_read(pchip->regmap, REG_BL_CONF_1, ®_val); | ||
158 | if (ret < 0) | ||
159 | goto out; | ||
160 | if (reg_val & 0x10) | ||
161 | ret = regmap_read(pchip->regmap, REG_BL_CONF_4, ®_val); | ||
162 | else | ||
163 | ret = regmap_read(pchip->regmap, REG_BL_CONF_3, ®_val); | ||
164 | if (ret < 0) | ||
165 | goto out; | ||
166 | bl->props.brightness = reg_val; | ||
167 | |||
168 | return bl->props.brightness; | ||
169 | out: | ||
170 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
171 | return bl->props.brightness; | ||
172 | } | ||
173 | |||
174 | static const struct backlight_ops lm3639_bled_ops = { | ||
175 | .options = BL_CORE_SUSPENDRESUME, | ||
176 | .update_status = lm3639_bled_update_status, | ||
177 | .get_brightness = lm3639_bled_get_brightness, | ||
178 | }; | ||
179 | |||
180 | /* backlight mapping mode */ | ||
181 | static ssize_t lm3639_bled_mode_store(struct device *dev, | ||
182 | struct device_attribute *devAttr, | ||
183 | const char *buf, size_t size) | ||
184 | { | ||
185 | ssize_t ret; | ||
186 | struct lm3639_chip_data *pchip = dev_get_drvdata(dev); | ||
187 | unsigned int state; | ||
188 | |||
189 | ret = kstrtouint(buf, 10, &state); | ||
190 | if (ret) | ||
191 | goto out_input; | ||
192 | |||
193 | if (!state) | ||
194 | ret = | ||
195 | regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10, | ||
196 | 0x00); | ||
197 | else | ||
198 | ret = | ||
199 | regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10, | ||
200 | 0x10); | ||
201 | |||
202 | if (ret < 0) | ||
203 | goto out; | ||
204 | |||
205 | return size; | ||
206 | |||
207 | out: | ||
208 | dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__); | ||
209 | return size; | ||
210 | |||
211 | out_input: | ||
212 | dev_err(pchip->dev, "%s:input conversion fail\n", __func__); | ||
213 | return size; | ||
214 | |||
215 | } | ||
216 | |||
217 | static DEVICE_ATTR(bled_mode, 0666, NULL, lm3639_bled_mode_store); | ||
218 | |||
219 | /* torch */ | ||
220 | static void lm3639_torch_brightness_set(struct led_classdev *cdev, | ||
221 | enum led_brightness brightness) | ||
222 | { | ||
223 | int ret; | ||
224 | unsigned int reg_val; | ||
225 | struct lm3639_chip_data *pchip; | ||
226 | |||
227 | pchip = container_of(cdev, struct lm3639_chip_data, cdev_torch); | ||
228 | |||
229 | ret = regmap_read(pchip->regmap, REG_FLAG, ®_val); | ||
230 | if (ret < 0) | ||
231 | goto out; | ||
232 | if (reg_val != 0) | ||
233 | dev_info(pchip->dev, "last flag is 0x%x\n", reg_val); | ||
234 | |||
235 | /* brightness 0 means off state */ | ||
236 | if (!brightness) { | ||
237 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00); | ||
238 | if (ret < 0) | ||
239 | goto out; | ||
240 | return; | ||
241 | } | ||
242 | |||
243 | ret = regmap_update_bits(pchip->regmap, | ||
244 | REG_FL_CONF_1, 0x70, (brightness - 1) << 4); | ||
245 | if (ret < 0) | ||
246 | goto out; | ||
247 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x02); | ||
248 | if (ret < 0) | ||
249 | goto out; | ||
250 | |||
251 | return; | ||
252 | out: | ||
253 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
254 | return; | ||
255 | } | ||
256 | |||
257 | /* flash */ | ||
258 | static void lm3639_flash_brightness_set(struct led_classdev *cdev, | ||
259 | enum led_brightness brightness) | ||
260 | { | ||
261 | int ret; | ||
262 | unsigned int reg_val; | ||
263 | struct lm3639_chip_data *pchip; | ||
264 | |||
265 | pchip = container_of(cdev, struct lm3639_chip_data, cdev_flash); | ||
266 | |||
267 | ret = regmap_read(pchip->regmap, REG_FLAG, ®_val); | ||
268 | if (ret < 0) | ||
269 | goto out; | ||
270 | if (reg_val != 0) | ||
271 | dev_info(pchip->dev, "last flag is 0x%x\n", reg_val); | ||
272 | |||
273 | /* torch off before flash control */ | ||
274 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00); | ||
275 | if (ret < 0) | ||
276 | goto out; | ||
277 | |||
278 | /* brightness 0 means off state */ | ||
279 | if (!brightness) | ||
280 | return; | ||
281 | |||
282 | ret = regmap_update_bits(pchip->regmap, | ||
283 | REG_FL_CONF_1, 0x0F, brightness - 1); | ||
284 | if (ret < 0) | ||
285 | goto out; | ||
286 | ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x06); | ||
287 | if (ret < 0) | ||
288 | goto out; | ||
289 | |||
290 | return; | ||
291 | out: | ||
292 | dev_err(pchip->dev, "i2c failed to access register\n"); | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | static const struct regmap_config lm3639_regmap = { | ||
297 | .reg_bits = 8, | ||
298 | .val_bits = 8, | ||
299 | .max_register = REG_MAX, | ||
300 | }; | ||
301 | |||
302 | static int __devinit lm3639_probe(struct i2c_client *client, | ||
303 | const struct i2c_device_id *id) | ||
304 | { | ||
305 | int ret; | ||
306 | struct lm3639_chip_data *pchip; | ||
307 | struct lm3639_platform_data *pdata = client->dev.platform_data; | ||
308 | struct backlight_properties props; | ||
309 | |||
310 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
311 | dev_err(&client->dev, "i2c functionality check fail.\n"); | ||
312 | return -EOPNOTSUPP; | ||
313 | } | ||
314 | |||
315 | if (pdata == NULL) { | ||
316 | dev_err(&client->dev, "Needs Platform Data.\n"); | ||
317 | return -ENODATA; | ||
318 | } | ||
319 | |||
320 | pchip = devm_kzalloc(&client->dev, | ||
321 | sizeof(struct lm3639_chip_data), GFP_KERNEL); | ||
322 | if (!pchip) | ||
323 | return -ENOMEM; | ||
324 | |||
325 | pchip->pdata = pdata; | ||
326 | pchip->dev = &client->dev; | ||
327 | |||
328 | pchip->regmap = devm_regmap_init_i2c(client, &lm3639_regmap); | ||
329 | if (IS_ERR(pchip->regmap)) { | ||
330 | ret = PTR_ERR(pchip->regmap); | ||
331 | dev_err(&client->dev, "fail : allocate register map: %d\n", | ||
332 | ret); | ||
333 | return ret; | ||
334 | } | ||
335 | i2c_set_clientdata(client, pchip); | ||
336 | |||
337 | /* chip initialize */ | ||
338 | ret = lm3639_chip_init(pchip); | ||
339 | if (ret < 0) { | ||
340 | dev_err(&client->dev, "fail : chip init\n"); | ||
341 | goto err_out; | ||
342 | } | ||
343 | |||
344 | /* backlight */ | ||
345 | props.type = BACKLIGHT_RAW; | ||
346 | props.brightness = pdata->init_brt_led; | ||
347 | props.max_brightness = pdata->max_brt_led; | ||
348 | pchip->bled = | ||
349 | backlight_device_register("lm3639_bled", pchip->dev, pchip, | ||
350 | &lm3639_bled_ops, &props); | ||
351 | if (IS_ERR(pchip->bled)) { | ||
352 | dev_err(&client->dev, "fail : backlight register\n"); | ||
353 | ret = -EIO; | ||
354 | goto err_out; | ||
355 | } | ||
356 | |||
357 | ret = device_create_file(&(pchip->bled->dev), &dev_attr_bled_mode); | ||
358 | if (ret < 0) { | ||
359 | dev_err(&client->dev, "failed : add sysfs entries\n"); | ||
360 | ret = -EIO; | ||
361 | goto err_bled_mode; | ||
362 | } | ||
363 | |||
364 | /* flash */ | ||
365 | pchip->cdev_flash.name = "lm3639_flash"; | ||
366 | pchip->cdev_flash.max_brightness = 16; | ||
367 | pchip->cdev_flash.brightness_set = lm3639_flash_brightness_set; | ||
368 | ret = led_classdev_register((struct device *) | ||
369 | &client->dev, &pchip->cdev_flash); | ||
370 | if (ret < 0) { | ||
371 | dev_err(&client->dev, "fail : flash register\n"); | ||
372 | ret = -EIO; | ||
373 | goto err_flash; | ||
374 | } | ||
375 | |||
376 | /* torch */ | ||
377 | pchip->cdev_torch.name = "lm3639_torch"; | ||
378 | pchip->cdev_torch.max_brightness = 8; | ||
379 | pchip->cdev_torch.brightness_set = lm3639_torch_brightness_set; | ||
380 | ret = led_classdev_register((struct device *) | ||
381 | &client->dev, &pchip->cdev_torch); | ||
382 | if (ret < 0) { | ||
383 | dev_err(&client->dev, "fail : torch register\n"); | ||
384 | ret = -EIO; | ||
385 | goto err_torch; | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | |||
390 | err_torch: | ||
391 | led_classdev_unregister(&pchip->cdev_flash); | ||
392 | err_flash: | ||
393 | device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode); | ||
394 | err_bled_mode: | ||
395 | backlight_device_unregister(pchip->bled); | ||
396 | err_out: | ||
397 | return ret; | ||
398 | } | ||
399 | |||
400 | static int __devexit lm3639_remove(struct i2c_client *client) | ||
401 | { | ||
402 | struct lm3639_chip_data *pchip = i2c_get_clientdata(client); | ||
403 | |||
404 | regmap_write(pchip->regmap, REG_ENABLE, 0x00); | ||
405 | |||
406 | if (&pchip->cdev_torch) | ||
407 | led_classdev_unregister(&pchip->cdev_torch); | ||
408 | if (&pchip->cdev_flash) | ||
409 | led_classdev_unregister(&pchip->cdev_flash); | ||
410 | if (pchip->bled) { | ||
411 | device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode); | ||
412 | backlight_device_unregister(pchip->bled); | ||
413 | } | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static const struct i2c_device_id lm3639_id[] = { | ||
418 | {LM3639_NAME, 0}, | ||
419 | {} | ||
420 | }; | ||
421 | |||
422 | MODULE_DEVICE_TABLE(i2c, lm3639_id); | ||
423 | static struct i2c_driver lm3639_i2c_driver = { | ||
424 | .driver = { | ||
425 | .name = LM3639_NAME, | ||
426 | }, | ||
427 | .probe = lm3639_probe, | ||
428 | .remove = __devexit_p(lm3639_remove), | ||
429 | .id_table = lm3639_id, | ||
430 | }; | ||
431 | |||
432 | module_i2c_driver(lm3639_i2c_driver); | ||
433 | |||
434 | MODULE_DESCRIPTION("Texas Instruments Backlight+Flash LED driver for LM3639"); | ||
435 | MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); | ||
436 | MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); | ||
437 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index 6c0f1ac0d32a..4066a5bbd826 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c | |||
@@ -75,7 +75,7 @@ static int ltv350qv_power_on(struct ltv350qv *lcd) | |||
75 | /* Power On Reset Display off State */ | 75 | /* Power On Reset Display off State */ |
76 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, 0x0000)) | 76 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, 0x0000)) |
77 | goto err; | 77 | goto err; |
78 | msleep(15); | 78 | usleep_range(15000, 16000); |
79 | 79 | ||
80 | /* Power Setting Function 1 */ | 80 | /* Power Setting Function 1 */ |
81 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE)) | 81 | if (ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE)) |
@@ -153,7 +153,7 @@ err_settings: | |||
153 | err_power2: | 153 | err_power2: |
154 | err_power1: | 154 | err_power1: |
155 | ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); | 155 | ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); |
156 | msleep(1); | 156 | usleep_range(1000, 1100); |
157 | err: | 157 | err: |
158 | ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); | 158 | ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); |
159 | return -EIO; | 159 | return -EIO; |
@@ -175,7 +175,7 @@ static int ltv350qv_power_off(struct ltv350qv *lcd) | |||
175 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); | 175 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL2, 0x0000); |
176 | 176 | ||
177 | /* Wait at least 1 ms */ | 177 | /* Wait at least 1 ms */ |
178 | msleep(1); | 178 | usleep_range(1000, 1100); |
179 | 179 | ||
180 | /* Power down setting 2 */ | 180 | /* Power down setting 2 */ |
181 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); | 181 | ret |= ltv350qv_write_reg(lcd, LTV_PWRCTL1, LTV_VCOM_DISABLE); |
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index b6672340d6c7..ca4f5d70fe10 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
17 | #include <linux/backlight.h> | 17 | #include <linux/backlight.h> |
18 | #include <linux/lcd.h> | 18 | #include <linux/lcd.h> |
19 | #include <linux/of.h> | ||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | 21 | ||
21 | #include <video/platform_lcd.h> | 22 | #include <video/platform_lcd.h> |
@@ -145,6 +146,14 @@ static SIMPLE_DEV_PM_OPS(platform_lcd_pm_ops, platform_lcd_suspend, | |||
145 | platform_lcd_resume); | 146 | platform_lcd_resume); |
146 | #endif | 147 | #endif |
147 | 148 | ||
149 | #ifdef CONFIG_OF | ||
150 | static const struct of_device_id platform_lcd_of_match[] = { | ||
151 | { .compatible = "platform-lcd" }, | ||
152 | {}, | ||
153 | }; | ||
154 | MODULE_DEVICE_TABLE(of, platform_lcd_of_match); | ||
155 | #endif | ||
156 | |||
148 | static struct platform_driver platform_lcd_driver = { | 157 | static struct platform_driver platform_lcd_driver = { |
149 | .driver = { | 158 | .driver = { |
150 | .name = "platform-lcd", | 159 | .name = "platform-lcd", |
@@ -152,6 +161,7 @@ static struct platform_driver platform_lcd_driver = { | |||
152 | #ifdef CONFIG_PM | 161 | #ifdef CONFIG_PM |
153 | .pm = &platform_lcd_pm_ops, | 162 | .pm = &platform_lcd_pm_ops, |
154 | #endif | 163 | #endif |
164 | .of_match_table = of_match_ptr(platform_lcd_of_match), | ||
155 | }, | 165 | }, |
156 | .probe = platform_lcd_probe, | 166 | .probe = platform_lcd_probe, |
157 | .remove = __devexit_p(platform_lcd_remove), | 167 | .remove = __devexit_p(platform_lcd_remove), |
diff --git a/drivers/video/backlight/progear_bl.c b/drivers/video/backlight/progear_bl.c deleted file mode 100644 index 69b35f02929e..000000000000 --- a/drivers/video/backlight/progear_bl.c +++ /dev/null | |||
@@ -1,162 +0,0 @@ | |||
1 | /* | ||
2 | * Backlight Driver for Frontpath ProGear HX1050+ | ||
3 | * | ||
4 | * Copyright (c) 2006 Marcin Juszkiewicz | ||
5 | * | ||
6 | * Based on Progear LCD driver by M Schacht | ||
7 | * <mschacht at alumni dot washington dot edu> | ||
8 | * | ||
9 | * Based on Sharp's Corgi Backlight Driver | ||
10 | * Based on Backlight Driver for HP Jornada 680 | ||
11 | * | ||
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 | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/mutex.h> | ||
25 | #include <linux/fb.h> | ||
26 | #include <linux/backlight.h> | ||
27 | #include <linux/pci.h> | ||
28 | |||
29 | #define PMU_LPCR 0xB0 | ||
30 | #define SB_MPS1 0x61 | ||
31 | #define HW_LEVEL_MAX 0x77 | ||
32 | #define HW_LEVEL_MIN 0x4f | ||
33 | |||
34 | static struct pci_dev *pmu_dev = NULL; | ||
35 | static struct pci_dev *sb_dev = NULL; | ||
36 | |||
37 | static int progearbl_set_intensity(struct backlight_device *bd) | ||
38 | { | ||
39 | int intensity = bd->props.brightness; | ||
40 | |||
41 | if (bd->props.power != FB_BLANK_UNBLANK) | ||
42 | intensity = 0; | ||
43 | if (bd->props.fb_blank != FB_BLANK_UNBLANK) | ||
44 | intensity = 0; | ||
45 | |||
46 | pci_write_config_byte(pmu_dev, PMU_LPCR, intensity + HW_LEVEL_MIN); | ||
47 | |||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int progearbl_get_intensity(struct backlight_device *bd) | ||
52 | { | ||
53 | u8 intensity; | ||
54 | pci_read_config_byte(pmu_dev, PMU_LPCR, &intensity); | ||
55 | |||
56 | return intensity - HW_LEVEL_MIN; | ||
57 | } | ||
58 | |||
59 | static const struct backlight_ops progearbl_ops = { | ||
60 | .get_brightness = progearbl_get_intensity, | ||
61 | .update_status = progearbl_set_intensity, | ||
62 | }; | ||
63 | |||
64 | static int progearbl_probe(struct platform_device *pdev) | ||
65 | { | ||
66 | struct backlight_properties props; | ||
67 | u8 temp; | ||
68 | struct backlight_device *progear_backlight_device; | ||
69 | int ret; | ||
70 | |||
71 | pmu_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); | ||
72 | if (!pmu_dev) { | ||
73 | pr_err("ALI M7101 PMU not found.\n"); | ||
74 | return -ENODEV; | ||
75 | } | ||
76 | |||
77 | sb_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); | ||
78 | if (!sb_dev) { | ||
79 | pr_err("ALI 1533 SB not found.\n"); | ||
80 | ret = -ENODEV; | ||
81 | goto put_pmu; | ||
82 | } | ||
83 | |||
84 | /* Set SB_MPS1 to enable brightness control. */ | ||
85 | pci_read_config_byte(sb_dev, SB_MPS1, &temp); | ||
86 | pci_write_config_byte(sb_dev, SB_MPS1, temp | 0x20); | ||
87 | |||
88 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
89 | props.type = BACKLIGHT_RAW; | ||
90 | props.max_brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; | ||
91 | progear_backlight_device = backlight_device_register("progear-bl", | ||
92 | &pdev->dev, NULL, | ||
93 | &progearbl_ops, | ||
94 | &props); | ||
95 | if (IS_ERR(progear_backlight_device)) { | ||
96 | ret = PTR_ERR(progear_backlight_device); | ||
97 | goto put_sb; | ||
98 | } | ||
99 | |||
100 | platform_set_drvdata(pdev, progear_backlight_device); | ||
101 | |||
102 | progear_backlight_device->props.power = FB_BLANK_UNBLANK; | ||
103 | progear_backlight_device->props.brightness = HW_LEVEL_MAX - HW_LEVEL_MIN; | ||
104 | progearbl_set_intensity(progear_backlight_device); | ||
105 | |||
106 | return 0; | ||
107 | put_sb: | ||
108 | pci_dev_put(sb_dev); | ||
109 | put_pmu: | ||
110 | pci_dev_put(pmu_dev); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | static int progearbl_remove(struct platform_device *pdev) | ||
115 | { | ||
116 | struct backlight_device *bd = platform_get_drvdata(pdev); | ||
117 | backlight_device_unregister(bd); | ||
118 | |||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static struct platform_driver progearbl_driver = { | ||
123 | .probe = progearbl_probe, | ||
124 | .remove = progearbl_remove, | ||
125 | .driver = { | ||
126 | .name = "progear-bl", | ||
127 | }, | ||
128 | }; | ||
129 | |||
130 | static struct platform_device *progearbl_device; | ||
131 | |||
132 | static int __init progearbl_init(void) | ||
133 | { | ||
134 | int ret = platform_driver_register(&progearbl_driver); | ||
135 | |||
136 | if (ret) | ||
137 | return ret; | ||
138 | progearbl_device = platform_device_register_simple("progear-bl", -1, | ||
139 | NULL, 0); | ||
140 | if (IS_ERR(progearbl_device)) { | ||
141 | platform_driver_unregister(&progearbl_driver); | ||
142 | return PTR_ERR(progearbl_device); | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void __exit progearbl_exit(void) | ||
149 | { | ||
150 | pci_dev_put(pmu_dev); | ||
151 | pci_dev_put(sb_dev); | ||
152 | |||
153 | platform_device_unregister(progearbl_device); | ||
154 | platform_driver_unregister(&progearbl_driver); | ||
155 | } | ||
156 | |||
157 | module_init(progearbl_init); | ||
158 | module_exit(progearbl_exit); | ||
159 | |||
160 | MODULE_AUTHOR("Marcin Juszkiewicz <linux@hrw.one.pl>"); | ||
161 | MODULE_DESCRIPTION("ProGear Backlight Driver"); | ||
162 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index 5a5d0928df33..265c5ed59ade 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c | |||
@@ -29,7 +29,7 @@ static int crt_option = 1; | |||
29 | static char panel_option[32] = ""; | 29 | static char panel_option[32] = ""; |
30 | 30 | ||
31 | /* Modes relevant to the GX1 (taken from modedb.c) */ | 31 | /* Modes relevant to the GX1 (taken from modedb.c) */ |
32 | static const struct fb_videomode __devinitdata gx1_modedb[] = { | 32 | static const struct fb_videomode __devinitconst gx1_modedb[] = { |
33 | /* 640x480-60 VESA */ | 33 | /* 640x480-60 VESA */ |
34 | { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, | 34 | { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2, |
35 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, | 35 | 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA }, |
diff --git a/drivers/video/gxt4500.c b/drivers/video/gxt4500.c index 0fad23f810a3..0e9afa41d163 100644 --- a/drivers/video/gxt4500.c +++ b/drivers/video/gxt4500.c | |||
@@ -156,7 +156,7 @@ struct gxt4500_par { | |||
156 | static char *mode_option; | 156 | static char *mode_option; |
157 | 157 | ||
158 | /* default mode: 1280x1024 @ 60 Hz, 8 bpp */ | 158 | /* default mode: 1280x1024 @ 60 Hz, 8 bpp */ |
159 | static const struct fb_videomode defaultmode __devinitdata = { | 159 | static const struct fb_videomode defaultmode __devinitconst = { |
160 | .refresh = 60, | 160 | .refresh = 60, |
161 | .xres = 1280, | 161 | .xres = 1280, |
162 | .yres = 1024, | 162 | .yres = 1024, |
@@ -581,7 +581,7 @@ static int gxt4500_blank(int blank, struct fb_info *info) | |||
581 | return 0; | 581 | return 0; |
582 | } | 582 | } |
583 | 583 | ||
584 | static const struct fb_fix_screeninfo gxt4500_fix __devinitdata = { | 584 | static const struct fb_fix_screeninfo gxt4500_fix __devinitconst = { |
585 | .id = "IBM GXT4500P", | 585 | .id = "IBM GXT4500P", |
586 | .type = FB_TYPE_PACKED_PIXELS, | 586 | .type = FB_TYPE_PACKED_PIXELS, |
587 | .visual = FB_VISUAL_PSEUDOCOLOR, | 587 | .visual = FB_VISUAL_PSEUDOCOLOR, |
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index b83f36190cae..5c067816a81d 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -97,7 +97,7 @@ static int i810fb_blank (int blank_mode, struct fb_info *info); | |||
97 | static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par); | 97 | static void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par); |
98 | 98 | ||
99 | /* PCI */ | 99 | /* PCI */ |
100 | static const char *i810_pci_list[] __devinitdata = { | 100 | static const char * const i810_pci_list[] __devinitconst = { |
101 | "Intel(R) 810 Framebuffer Device" , | 101 | "Intel(R) 810 Framebuffer Device" , |
102 | "Intel(R) 810-DC100 Framebuffer Device" , | 102 | "Intel(R) 810-DC100 Framebuffer Device" , |
103 | "Intel(R) 810E Framebuffer Device" , | 103 | "Intel(R) 810E Framebuffer Device" , |
diff --git a/drivers/video/jz4740_fb.c b/drivers/video/jz4740_fb.c index de366937c933..3c63fc24bb1f 100644 --- a/drivers/video/jz4740_fb.c +++ b/drivers/video/jz4740_fb.c | |||
@@ -136,7 +136,7 @@ struct jzfb { | |||
136 | uint32_t pseudo_palette[16]; | 136 | uint32_t pseudo_palette[16]; |
137 | }; | 137 | }; |
138 | 138 | ||
139 | static const struct fb_fix_screeninfo jzfb_fix __devinitdata = { | 139 | static const struct fb_fix_screeninfo jzfb_fix __devinitconst = { |
140 | .id = "JZ4740 FB", | 140 | .id = "JZ4740 FB", |
141 | .type = FB_TYPE_PACKED_PIXELS, | 141 | .type = FB_TYPE_PACKED_PIXELS, |
142 | .visual = FB_VISUAL_TRUECOLOR, | 142 | .visual = FB_VISUAL_TRUECOLOR, |