diff options
Diffstat (limited to 'drivers')
200 files changed, 6764 insertions, 2948 deletions
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index c5885f5ce0ac..499b003f9278 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -110,7 +110,7 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); | |||
110 | * | 110 | * |
111 | * Initialize and register the CPU device. | 111 | * Initialize and register the CPU device. |
112 | */ | 112 | */ |
113 | int __devinit register_cpu(struct cpu *cpu, int num) | 113 | int __cpuinit register_cpu(struct cpu *cpu, int num) |
114 | { | 114 | { |
115 | int error; | 115 | int error; |
116 | cpu->node_id = cpu_to_node(num); | 116 | cpu->node_id = cpu_to_node(num); |
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 94268c75d04f..424995073c6b 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
@@ -90,7 +90,7 @@ static struct atari_disk_type { | |||
90 | unsigned blocks; /* total number of blocks */ | 90 | unsigned blocks; /* total number of blocks */ |
91 | unsigned fdc_speed; /* fdc_speed setting */ | 91 | unsigned fdc_speed; /* fdc_speed setting */ |
92 | unsigned stretch; /* track doubling ? */ | 92 | unsigned stretch; /* track doubling ? */ |
93 | } disk_type[] = { | 93 | } atari_disk_type[] = { |
94 | { "d360", 9, 720, 0, 0}, /* 0: 360kB diskette */ | 94 | { "d360", 9, 720, 0, 0}, /* 0: 360kB diskette */ |
95 | { "D360", 9, 720, 0, 1}, /* 1: 360kb in 720k or 1.2MB drive */ | 95 | { "D360", 9, 720, 0, 1}, /* 1: 360kb in 720k or 1.2MB drive */ |
96 | { "D720", 9,1440, 0, 0}, /* 2: 720kb in 720k or 1.2MB drive */ | 96 | { "D720", 9,1440, 0, 0}, /* 2: 720kb in 720k or 1.2MB drive */ |
@@ -658,7 +658,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) | |||
658 | return -EINVAL; | 658 | return -EINVAL; |
659 | } | 659 | } |
660 | type = minor2disktype[type].index; | 660 | type = minor2disktype[type].index; |
661 | UDT = &disk_type[type]; | 661 | UDT = &atari_disk_type[type]; |
662 | } | 662 | } |
663 | 663 | ||
664 | if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { | 664 | if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { |
@@ -1064,7 +1064,7 @@ static void fd_rwsec_done1(int status) | |||
1064 | searched for a non-existent sector! */ | 1064 | searched for a non-existent sector! */ |
1065 | !(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) { | 1065 | !(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) { |
1066 | if (Probing) { | 1066 | if (Probing) { |
1067 | if (SUDT > disk_type) { | 1067 | if (SUDT > atari_disk_type) { |
1068 | if (SUDT[-1].blocks > ReqBlock) { | 1068 | if (SUDT[-1].blocks > ReqBlock) { |
1069 | /* try another disk type */ | 1069 | /* try another disk type */ |
1070 | SUDT--; | 1070 | SUDT--; |
@@ -1082,7 +1082,7 @@ static void fd_rwsec_done1(int status) | |||
1082 | } else { | 1082 | } else { |
1083 | /* record not found, but not probing. Maybe stretch wrong ? Restart probing */ | 1083 | /* record not found, but not probing. Maybe stretch wrong ? Restart probing */ |
1084 | if (SUD.autoprobe) { | 1084 | if (SUD.autoprobe) { |
1085 | SUDT = disk_type + StartDiskType[DriveType]; | 1085 | SUDT = atari_disk_type + StartDiskType[DriveType]; |
1086 | set_capacity(unit[SelectedDrive].disk, | 1086 | set_capacity(unit[SelectedDrive].disk, |
1087 | SUDT->blocks); | 1087 | SUDT->blocks); |
1088 | Probing = 1; | 1088 | Probing = 1; |
@@ -1421,7 +1421,7 @@ repeat: | |||
1421 | if (type == 0) { | 1421 | if (type == 0) { |
1422 | if (!UDT) { | 1422 | if (!UDT) { |
1423 | Probing = 1; | 1423 | Probing = 1; |
1424 | UDT = disk_type + StartDiskType[DriveType]; | 1424 | UDT = atari_disk_type + StartDiskType[DriveType]; |
1425 | set_capacity(floppy->disk, UDT->blocks); | 1425 | set_capacity(floppy->disk, UDT->blocks); |
1426 | UD.autoprobe = 1; | 1426 | UD.autoprobe = 1; |
1427 | } | 1427 | } |
@@ -1439,7 +1439,7 @@ repeat: | |||
1439 | goto repeat; | 1439 | goto repeat; |
1440 | } | 1440 | } |
1441 | type = minor2disktype[type].index; | 1441 | type = minor2disktype[type].index; |
1442 | UDT = &disk_type[type]; | 1442 | UDT = &atari_disk_type[type]; |
1443 | set_capacity(floppy->disk, UDT->blocks); | 1443 | set_capacity(floppy->disk, UDT->blocks); |
1444 | UD.autoprobe = 0; | 1444 | UD.autoprobe = 0; |
1445 | } | 1445 | } |
@@ -1505,7 +1505,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1505 | if (minor2disktype[type].drive_types > DriveType) | 1505 | if (minor2disktype[type].drive_types > DriveType) |
1506 | return -ENODEV; | 1506 | return -ENODEV; |
1507 | type = minor2disktype[type].index; | 1507 | type = minor2disktype[type].index; |
1508 | dtp = &disk_type[type]; | 1508 | dtp = &atari_disk_type[type]; |
1509 | if (UD.flags & FTD_MSG) | 1509 | if (UD.flags & FTD_MSG) |
1510 | printk (KERN_ERR "floppy%d: found dtp %p name %s!\n", | 1510 | printk (KERN_ERR "floppy%d: found dtp %p name %s!\n", |
1511 | drive, dtp, dtp->name); | 1511 | drive, dtp, dtp->name); |
@@ -1576,7 +1576,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1576 | continue; | 1576 | continue; |
1577 | } | 1577 | } |
1578 | setidx = minor2disktype[settype].index; | 1578 | setidx = minor2disktype[settype].index; |
1579 | dtp = &disk_type[setidx]; | 1579 | dtp = &atari_disk_type[setidx]; |
1580 | 1580 | ||
1581 | /* found matching entry ?? */ | 1581 | /* found matching entry ?? */ |
1582 | if ( dtp->blocks == setprm.size | 1582 | if ( dtp->blocks == setprm.size |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 855ce8e5efba..9715be3f2487 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -2630,12 +2630,14 @@ static void do_cciss_request(struct request_queue *q) | |||
2630 | c->Request.CDB[8] = creq->nr_sectors & 0xff; | 2630 | c->Request.CDB[8] = creq->nr_sectors & 0xff; |
2631 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; | 2631 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; |
2632 | } else { | 2632 | } else { |
2633 | u32 upper32 = upper_32_bits(start_blk); | ||
2634 | |||
2633 | c->Request.CDBLen = 16; | 2635 | c->Request.CDBLen = 16; |
2634 | c->Request.CDB[1]= 0; | 2636 | c->Request.CDB[1]= 0; |
2635 | c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB | 2637 | c->Request.CDB[2]= (upper32 >> 24) & 0xff; //MSB |
2636 | c->Request.CDB[3]= (start_blk >> 48) & 0xff; | 2638 | c->Request.CDB[3]= (upper32 >> 16) & 0xff; |
2637 | c->Request.CDB[4]= (start_blk >> 40) & 0xff; | 2639 | c->Request.CDB[4]= (upper32 >> 8) & 0xff; |
2638 | c->Request.CDB[5]= (start_blk >> 32) & 0xff; | 2640 | c->Request.CDB[5]= upper32 & 0xff; |
2639 | c->Request.CDB[6]= (start_blk >> 24) & 0xff; | 2641 | c->Request.CDB[6]= (start_blk >> 24) & 0xff; |
2640 | c->Request.CDB[7]= (start_blk >> 16) & 0xff; | 2642 | c->Request.CDB[7]= (start_blk >> 16) & 0xff; |
2641 | c->Request.CDB[8]= (start_blk >> 8) & 0xff; | 2643 | c->Request.CDB[8]= (start_blk >> 8) & 0xff; |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index b8af22e610df..91ebb007416c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -973,6 +973,10 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) | |||
973 | lo->transfer = xfer->transfer; | 973 | lo->transfer = xfer->transfer; |
974 | lo->ioctl = xfer->ioctl; | 974 | lo->ioctl = xfer->ioctl; |
975 | 975 | ||
976 | if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) != | ||
977 | (info->lo_flags & LO_FLAGS_AUTOCLEAR)) | ||
978 | lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; | ||
979 | |||
976 | lo->lo_encrypt_key_size = info->lo_encrypt_key_size; | 980 | lo->lo_encrypt_key_size = info->lo_encrypt_key_size; |
977 | lo->lo_init[0] = info->lo_init[0]; | 981 | lo->lo_init[0] = info->lo_init[0]; |
978 | lo->lo_init[1] = info->lo_init[1]; | 982 | lo->lo_init[1] = info->lo_init[1]; |
@@ -1331,6 +1335,10 @@ static int lo_release(struct inode *inode, struct file *file) | |||
1331 | 1335 | ||
1332 | mutex_lock(&lo->lo_ctl_mutex); | 1336 | mutex_lock(&lo->lo_ctl_mutex); |
1333 | --lo->lo_refcnt; | 1337 | --lo->lo_refcnt; |
1338 | |||
1339 | if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt) | ||
1340 | loop_clr_fd(lo, inode->i_bdev); | ||
1341 | |||
1334 | mutex_unlock(&lo->lo_ctl_mutex); | 1342 | mutex_unlock(&lo->lo_ctl_mutex); |
1335 | 1343 | ||
1336 | return 0; | 1344 | return 0; |
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 76096cad798f..8b9549ab4a4e 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c | |||
@@ -660,7 +660,7 @@ static int pt_open(struct inode *inode, struct file *file) | |||
660 | pt_identify(tape); | 660 | pt_identify(tape); |
661 | 661 | ||
662 | err = -ENODEV; | 662 | err = -ENODEV; |
663 | if (!tape->flags & PT_MEDIA) | 663 | if (!(tape->flags & PT_MEDIA)) |
664 | goto out; | 664 | goto out; |
665 | 665 | ||
666 | err = -EROFS; | 666 | err = -EROFS; |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index e9de1712e5a0..674cd66dcaba 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -2212,11 +2212,11 @@ static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed) | |||
2212 | return ret; | 2212 | return ret; |
2213 | } | 2213 | } |
2214 | 2214 | ||
2215 | if (!buf[6] & 0x40) { | 2215 | if (!(buf[6] & 0x40)) { |
2216 | printk(DRIVER_NAME": Disc type is not CD-RW\n"); | 2216 | printk(DRIVER_NAME": Disc type is not CD-RW\n"); |
2217 | return 1; | 2217 | return 1; |
2218 | } | 2218 | } |
2219 | if (!buf[6] & 0x4) { | 2219 | if (!(buf[6] & 0x4)) { |
2220 | printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n"); | 2220 | printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n"); |
2221 | return 1; | 2221 | return 1; |
2222 | } | 2222 | } |
diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 82f4eecc8699..06e23be70904 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/backing-dev.h> | 56 | #include <linux/backing-dev.h> |
57 | #include <linux/blkpg.h> | 57 | #include <linux/blkpg.h> |
58 | #include <linux/writeback.h> | 58 | #include <linux/writeback.h> |
59 | #include <linux/log2.h> | ||
59 | 60 | ||
60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
61 | 62 | ||
@@ -450,7 +451,7 @@ static int __init rd_init(void) | |||
450 | err = -ENOMEM; | 451 | err = -ENOMEM; |
451 | 452 | ||
452 | if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || | 453 | if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || |
453 | (rd_blocksize & (rd_blocksize-1))) { | 454 | !is_power_of_2(rd_blocksize)) { |
454 | printk("RAMDISK: wrong blocksize %d, reverting to defaults\n", | 455 | printk("RAMDISK: wrong blocksize %d, reverting to defaults\n", |
455 | rd_blocksize); | 456 | rd_blocksize); |
456 | rd_blocksize = BLOCK_SIZE; | 457 | rd_blocksize = BLOCK_SIZE; |
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 47e5b40510cb..db259e60289b 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
@@ -1206,25 +1206,26 @@ int check_for_audio_disc(struct cdrom_device_info * cdi, | |||
1206 | return 0; | 1206 | return 0; |
1207 | } | 1207 | } |
1208 | 1208 | ||
1209 | /* Admittedly, the logic below could be performed in a nicer way. */ | ||
1210 | int cdrom_release(struct cdrom_device_info *cdi, struct file *fp) | 1209 | int cdrom_release(struct cdrom_device_info *cdi, struct file *fp) |
1211 | { | 1210 | { |
1212 | struct cdrom_device_ops *cdo = cdi->ops; | 1211 | struct cdrom_device_ops *cdo = cdi->ops; |
1213 | int opened_for_data; | 1212 | int opened_for_data; |
1214 | 1213 | ||
1215 | cdinfo(CD_CLOSE, "entering cdrom_release\n"); | 1214 | cdinfo(CD_CLOSE, "entering cdrom_release\n"); |
1216 | 1215 | ||
1217 | if (cdi->use_count > 0) | 1216 | if (cdi->use_count > 0) |
1218 | cdi->use_count--; | 1217 | cdi->use_count--; |
1219 | if (cdi->use_count == 0) | 1218 | |
1219 | if (cdi->use_count == 0) { | ||
1220 | cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); | 1220 | cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); |
1221 | if (cdi->use_count == 0) | ||
1222 | cdrom_dvd_rw_close_write(cdi); | 1221 | cdrom_dvd_rw_close_write(cdi); |
1223 | if (cdi->use_count == 0 && | 1222 | |
1224 | (cdo->capability & CDC_LOCK) && !keeplocked) { | 1223 | if ((cdo->capability & CDC_LOCK) && !keeplocked) { |
1225 | cdinfo(CD_CLOSE, "Unlocking door!\n"); | 1224 | cdinfo(CD_CLOSE, "Unlocking door!\n"); |
1226 | cdo->lock_door(cdi, 0); | 1225 | cdo->lock_door(cdi, 0); |
1226 | } | ||
1227 | } | 1227 | } |
1228 | |||
1228 | opened_for_data = !(cdi->options & CDO_USE_FFLAGS) || | 1229 | opened_for_data = !(cdi->options & CDO_USE_FFLAGS) || |
1229 | !(fp && fp->f_flags & O_NONBLOCK); | 1230 | !(fp && fp->f_flags & O_NONBLOCK); |
1230 | 1231 | ||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 466629594776..85bf9b2aa74a 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -276,7 +276,7 @@ config N_HDLC | |||
276 | 276 | ||
277 | config RISCOM8 | 277 | config RISCOM8 |
278 | tristate "SDL RISCom/8 card support" | 278 | tristate "SDL RISCom/8 card support" |
279 | depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP | 279 | depends on SERIAL_NONSTANDARD |
280 | help | 280 | help |
281 | This is a driver for the SDL Communications RISCom/8 multiport card, | 281 | This is a driver for the SDL Communications RISCom/8 multiport card, |
282 | which gives you many serial ports. You would need something like | 282 | which gives you many serial ports. You would need something like |
@@ -765,7 +765,7 @@ config JS_RTC | |||
765 | 765 | ||
766 | config SGI_DS1286 | 766 | config SGI_DS1286 |
767 | tristate "SGI DS1286 RTC support" | 767 | tristate "SGI DS1286 RTC support" |
768 | depends on SGI_IP22 | 768 | depends on SGI_HAS_DS1286 |
769 | help | 769 | help |
770 | If you say Y here and create a character special file /dev/rtc with | 770 | If you say Y here and create a character special file /dev/rtc with |
771 | major number 10 and minor number 135 using mknod ("man mknod"), you | 771 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 480fae29c9b2..44160d5ebca0 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -93,7 +93,7 @@ struct hvc_struct { | |||
93 | }; | 93 | }; |
94 | 94 | ||
95 | /* dynamic list of hvc_struct instances */ | 95 | /* dynamic list of hvc_struct instances */ |
96 | static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs); | 96 | static LIST_HEAD(hvc_structs); |
97 | 97 | ||
98 | /* | 98 | /* |
99 | * Protect the list of hvc_struct instances from inserts and removals during | 99 | * Protect the list of hvc_struct instances from inserts and removals during |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 3402def22007..786d518e9477 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -306,7 +306,7 @@ struct hvcs_struct { | |||
306 | /* Required to back map a kref to its containing object */ | 306 | /* Required to back map a kref to its containing object */ |
307 | #define from_kref(k) container_of(k, struct hvcs_struct, kref) | 307 | #define from_kref(k) container_of(k, struct hvcs_struct, kref) |
308 | 308 | ||
309 | static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs); | 309 | static LIST_HEAD(hvcs_structs); |
310 | static DEFINE_SPINLOCK(hvcs_structs_lock); | 310 | static DEFINE_SPINLOCK(hvcs_structs_lock); |
311 | 311 | ||
312 | static void hvcs_unthrottle(struct tty_struct *tty); | 312 | static void hvcs_unthrottle(struct tty_struct *tty); |
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 868e39fd42e4..f7feae4ebb5e 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c | |||
@@ -42,6 +42,8 @@ enum { | |||
42 | VIA_STRFILT_ENABLE = (1 << 14), | 42 | VIA_STRFILT_ENABLE = (1 << 14), |
43 | VIA_RAWBITS_ENABLE = (1 << 13), | 43 | VIA_RAWBITS_ENABLE = (1 << 13), |
44 | VIA_RNG_ENABLE = (1 << 6), | 44 | VIA_RNG_ENABLE = (1 << 6), |
45 | VIA_NOISESRC1 = (1 << 8), | ||
46 | VIA_NOISESRC2 = (1 << 9), | ||
45 | VIA_XSTORE_CNT_MASK = 0x0F, | 47 | VIA_XSTORE_CNT_MASK = 0x0F, |
46 | 48 | ||
47 | VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ | 49 | VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ |
@@ -119,6 +121,7 @@ static int via_rng_data_read(struct hwrng *rng, u32 *data) | |||
119 | 121 | ||
120 | static int via_rng_init(struct hwrng *rng) | 122 | static int via_rng_init(struct hwrng *rng) |
121 | { | 123 | { |
124 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
122 | u32 lo, hi, old_lo; | 125 | u32 lo, hi, old_lo; |
123 | 126 | ||
124 | /* Control the RNG via MSR. Tread lightly and pay very close | 127 | /* Control the RNG via MSR. Tread lightly and pay very close |
@@ -134,6 +137,17 @@ static int via_rng_init(struct hwrng *rng) | |||
134 | lo &= ~VIA_XSTORE_CNT_MASK; | 137 | lo &= ~VIA_XSTORE_CNT_MASK; |
135 | lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); | 138 | lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); |
136 | lo |= VIA_RNG_ENABLE; | 139 | lo |= VIA_RNG_ENABLE; |
140 | lo |= VIA_NOISESRC1; | ||
141 | |||
142 | /* Enable secondary noise source on CPUs where it is present. */ | ||
143 | |||
144 | /* Nehemiah stepping 8 and higher */ | ||
145 | if ((c->x86_model == 9) && (c->x86_mask > 7)) | ||
146 | lo |= VIA_NOISESRC2; | ||
147 | |||
148 | /* Esther */ | ||
149 | if (c->x86_model >= 10) | ||
150 | lo |= VIA_NOISESRC2; | ||
137 | 151 | ||
138 | if (lo != old_lo) | 152 | if (lo != old_lo) |
139 | wrmsr(MSR_VIA_RNG, lo, hi); | 153 | wrmsr(MSR_VIA_RNG, lo, hi); |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 30e564516422..179223a17414 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -439,6 +439,13 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = { | |||
439 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), | 439 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), |
440 | }, | 440 | }, |
441 | }, | 441 | }, |
442 | { /* UK Inspiron 6400 */ | ||
443 | .ident = "Dell Inspiron 3", | ||
444 | .matches = { | ||
445 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
446 | DMI_MATCH(DMI_PRODUCT_NAME, "MM061"), | ||
447 | }, | ||
448 | }, | ||
442 | { } | 449 | { } |
443 | }; | 450 | }; |
444 | 451 | ||
diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c index 932264a657d0..86e6538a77b0 100644 --- a/drivers/char/ip27-rtc.c +++ b/drivers/char/ip27-rtc.c | |||
@@ -46,8 +46,8 @@ | |||
46 | #include <asm/sn/sn0/hub.h> | 46 | #include <asm/sn/sn0/hub.h> |
47 | #include <asm/sn/sn_private.h> | 47 | #include <asm/sn/sn_private.h> |
48 | 48 | ||
49 | static int rtc_ioctl(struct inode *inode, struct file *file, | 49 | static long rtc_ioctl(struct file *filp, unsigned int cmd, |
50 | unsigned int cmd, unsigned long arg); | 50 | unsigned long arg); |
51 | 51 | ||
52 | static int rtc_read_proc(char *page, char **start, off_t off, | 52 | static int rtc_read_proc(char *page, char **start, off_t off, |
53 | int count, int *eof, void *data); | 53 | int count, int *eof, void *data); |
@@ -75,8 +75,7 @@ static unsigned long epoch = 1970; /* year corresponding to 0x00 */ | |||
75 | static const unsigned char days_in_mo[] = | 75 | static const unsigned char days_in_mo[] = |
76 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | 76 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
77 | 77 | ||
78 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 78 | static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
79 | unsigned long arg) | ||
80 | { | 79 | { |
81 | 80 | ||
82 | struct rtc_time wtime; | 81 | struct rtc_time wtime; |
@@ -197,7 +196,7 @@ static int rtc_release(struct inode *inode, struct file *file) | |||
197 | 196 | ||
198 | static const struct file_operations rtc_fops = { | 197 | static const struct file_operations rtc_fops = { |
199 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
200 | .ioctl = rtc_ioctl, | 199 | .unlocked_ioctl = rtc_ioctl, |
201 | .open = rtc_open, | 200 | .open = rtc_open, |
202 | .release = rtc_release, | 201 | .release = rtc_release, |
203 | }; | 202 | }; |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 5dc1265ce1d5..32b2b22996dc 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -365,12 +365,12 @@ static struct device_driver ipmidriver = { | |||
365 | }; | 365 | }; |
366 | static DEFINE_MUTEX(ipmidriver_mutex); | 366 | static DEFINE_MUTEX(ipmidriver_mutex); |
367 | 367 | ||
368 | static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces); | 368 | static LIST_HEAD(ipmi_interfaces); |
369 | static DEFINE_MUTEX(ipmi_interfaces_mutex); | 369 | static DEFINE_MUTEX(ipmi_interfaces_mutex); |
370 | 370 | ||
371 | /* List of watchers that want to know when smi's are added and | 371 | /* List of watchers that want to know when smi's are added and |
372 | deleted. */ | 372 | deleted. */ |
373 | static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); | 373 | static LIST_HEAD(smi_watchers); |
374 | static DEFINE_MUTEX(smi_watchers_mutex); | 374 | static DEFINE_MUTEX(smi_watchers_mutex); |
375 | 375 | ||
376 | 376 | ||
@@ -441,7 +441,7 @@ struct watcher_entry { | |||
441 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | 441 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) |
442 | { | 442 | { |
443 | ipmi_smi_t intf; | 443 | ipmi_smi_t intf; |
444 | struct list_head to_deliver = LIST_HEAD_INIT(to_deliver); | 444 | LIST_HEAD(to_deliver); |
445 | struct watcher_entry *e, *e2; | 445 | struct watcher_entry *e, *e2; |
446 | 446 | ||
447 | mutex_lock(&smi_watchers_mutex); | 447 | mutex_lock(&smi_watchers_mutex); |
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 81674d7c56c7..60ac642752be 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -312,7 +312,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf, | |||
312 | if (copy_size > LP_BUFFER_SIZE) | 312 | if (copy_size > LP_BUFFER_SIZE) |
313 | copy_size = LP_BUFFER_SIZE; | 313 | copy_size = LP_BUFFER_SIZE; |
314 | 314 | ||
315 | if (down_interruptible (&lp_table[minor].port_mutex)) | 315 | if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) |
316 | return -EINTR; | 316 | return -EINTR; |
317 | 317 | ||
318 | if (copy_from_user (kbuf, buf, copy_size)) { | 318 | if (copy_from_user (kbuf, buf, copy_size)) { |
@@ -399,7 +399,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf, | |||
399 | lp_release_parport (&lp_table[minor]); | 399 | lp_release_parport (&lp_table[minor]); |
400 | } | 400 | } |
401 | out_unlock: | 401 | out_unlock: |
402 | up (&lp_table[minor].port_mutex); | 402 | mutex_unlock(&lp_table[minor].port_mutex); |
403 | 403 | ||
404 | return retv; | 404 | return retv; |
405 | } | 405 | } |
@@ -421,7 +421,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, | |||
421 | if (count > LP_BUFFER_SIZE) | 421 | if (count > LP_BUFFER_SIZE) |
422 | count = LP_BUFFER_SIZE; | 422 | count = LP_BUFFER_SIZE; |
423 | 423 | ||
424 | if (down_interruptible (&lp_table[minor].port_mutex)) | 424 | if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) |
425 | return -EINTR; | 425 | return -EINTR; |
426 | 426 | ||
427 | lp_claim_parport_or_block (&lp_table[minor]); | 427 | lp_claim_parport_or_block (&lp_table[minor]); |
@@ -479,7 +479,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, | |||
479 | if (retval > 0 && copy_to_user (buf, kbuf, retval)) | 479 | if (retval > 0 && copy_to_user (buf, kbuf, retval)) |
480 | retval = -EFAULT; | 480 | retval = -EFAULT; |
481 | 481 | ||
482 | up (&lp_table[minor].port_mutex); | 482 | mutex_unlock(&lp_table[minor].port_mutex); |
483 | 483 | ||
484 | return retval; | 484 | return retval; |
485 | } | 485 | } |
@@ -888,7 +888,7 @@ static int __init lp_init (void) | |||
888 | lp_table[i].last_error = 0; | 888 | lp_table[i].last_error = 0; |
889 | init_waitqueue_head (&lp_table[i].waitq); | 889 | init_waitqueue_head (&lp_table[i].waitq); |
890 | init_waitqueue_head (&lp_table[i].dataq); | 890 | init_waitqueue_head (&lp_table[i].dataq); |
891 | init_MUTEX (&lp_table[i].port_mutex); | 891 | mutex_init(&lp_table[i].port_mutex); |
892 | lp_table[i].timeout = 10 * HZ; | 892 | lp_table[i].timeout = 10 * HZ; |
893 | } | 893 | } |
894 | 894 | ||
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index fd0abef7ee08..47420787a017 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -37,7 +37,6 @@ | |||
37 | 37 | ||
38 | 38 | ||
39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
40 | #include <linux/autoconf.h> | ||
41 | #include <linux/errno.h> | 40 | #include <linux/errno.h> |
42 | #include <linux/signal.h> | 41 | #include <linux/signal.h> |
43 | #include <linux/sched.h> | 42 | #include <linux/sched.h> |
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index 081c84c7b548..bf1bee4e1f5e 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c | |||
@@ -20,7 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/autoconf.h> | ||
24 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
25 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
26 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 596c7173997b..90c3969012a3 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -695,17 +695,16 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
695 | return; | 695 | return; |
696 | } | 696 | } |
697 | 697 | ||
698 | if (tty->stopped && !tty->flow_stopped && | ||
699 | I_IXON(tty) && I_IXANY(tty)) { | ||
700 | start_tty(tty); | ||
701 | return; | ||
702 | } | ||
703 | |||
704 | if (I_ISTRIP(tty)) | 698 | if (I_ISTRIP(tty)) |
705 | c &= 0x7f; | 699 | c &= 0x7f; |
706 | if (I_IUCLC(tty) && L_IEXTEN(tty)) | 700 | if (I_IUCLC(tty) && L_IEXTEN(tty)) |
707 | c=tolower(c); | 701 | c=tolower(c); |
708 | 702 | ||
703 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && | ||
704 | ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) || | ||
705 | c == INTR_CHAR(tty) || c == QUIT_CHAR(tty))) | ||
706 | start_tty(tty); | ||
707 | |||
709 | if (tty->closing) { | 708 | if (tty->closing) { |
710 | if (I_IXON(tty)) { | 709 | if (I_IXON(tty)) { |
711 | if (c == START_CHAR(tty)) | 710 | if (c == START_CHAR(tty)) |
@@ -769,7 +768,21 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
769 | signal = SIGTSTP; | 768 | signal = SIGTSTP; |
770 | if (c == SUSP_CHAR(tty)) { | 769 | if (c == SUSP_CHAR(tty)) { |
771 | send_signal: | 770 | send_signal: |
772 | isig(signal, tty, 0); | 771 | /* |
772 | * Echo character, and then send the signal. | ||
773 | * Note that we do not use isig() here because we want | ||
774 | * the order to be: | ||
775 | * 1) flush, 2) echo, 3) signal | ||
776 | */ | ||
777 | if (!L_NOFLSH(tty)) { | ||
778 | n_tty_flush_buffer(tty); | ||
779 | if (tty->driver->flush_buffer) | ||
780 | tty->driver->flush_buffer(tty); | ||
781 | } | ||
782 | if (L_ECHO(tty)) | ||
783 | echo_char(c, tty); | ||
784 | if (tty->pgrp) | ||
785 | kill_pgrp(tty->pgrp, signal, 1); | ||
773 | return; | 786 | return; |
774 | } | 787 | } |
775 | } | 788 | } |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 8caff0ca80ff..279ff5005cec 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/init.h> | 57 | #include <linux/init.h> |
58 | #include <linux/delay.h> | 58 | #include <linux/delay.h> |
59 | #include <linux/ioctl.h> | 59 | #include <linux/ioctl.h> |
60 | #include <linux/synclink.h> | ||
60 | 61 | ||
61 | #include <asm/system.h> | 62 | #include <asm/system.h> |
62 | #include <asm/io.h> | 63 | #include <asm/io.h> |
@@ -87,8 +88,6 @@ | |||
87 | 88 | ||
88 | #include <asm/uaccess.h> | 89 | #include <asm/uaccess.h> |
89 | 90 | ||
90 | #include "linux/synclink.h" | ||
91 | |||
92 | static MGSL_PARAMS default_params = { | 91 | static MGSL_PARAMS default_params = { |
93 | MGSL_MODE_HDLC, /* unsigned long mode */ | 92 | MGSL_MODE_HDLC, /* unsigned long mode */ |
94 | 0, /* unsigned char loopback; */ | 93 | 0, /* unsigned char loopback; */ |
diff --git a/drivers/char/random.c b/drivers/char/random.c index c511a831f0c0..f43c89f7c449 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1039,6 +1039,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count) | |||
1039 | p += bytes; | 1039 | p += bytes; |
1040 | 1040 | ||
1041 | add_entropy_words(r, buf, (bytes + 3) / 4); | 1041 | add_entropy_words(r, buf, (bytes + 3) / 4); |
1042 | cond_resched(); | ||
1042 | } | 1043 | } |
1043 | 1044 | ||
1044 | return 0; | 1045 | return 0; |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 102ece4c4e0e..d130b87d8ed7 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
50 | #include <linux/spinlock.h> | ||
50 | 51 | ||
51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
52 | 53 | ||
@@ -81,6 +82,8 @@ | |||
81 | 82 | ||
82 | static struct tty_driver *riscom_driver; | 83 | static struct tty_driver *riscom_driver; |
83 | 84 | ||
85 | static DEFINE_SPINLOCK(riscom_lock); | ||
86 | |||
84 | static struct riscom_board rc_board[RC_NBOARD] = { | 87 | static struct riscom_board rc_board[RC_NBOARD] = { |
85 | { | 88 | { |
86 | .base = RC_IOBASE1, | 89 | .base = RC_IOBASE1, |
@@ -217,13 +220,14 @@ static void __init rc_init_CD180(struct riscom_board const * bp) | |||
217 | { | 220 | { |
218 | unsigned long flags; | 221 | unsigned long flags; |
219 | 222 | ||
220 | save_flags(flags); cli(); | 223 | spin_lock_irqsave(&riscom_lock, flags); |
224 | |||
221 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ | 225 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ |
222 | rc_wait_CCR(bp); /* Wait for CCR ready */ | 226 | rc_wait_CCR(bp); /* Wait for CCR ready */ |
223 | rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ | 227 | rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ |
224 | sti(); | 228 | spin_unlock_irqrestore(&riscom_lock, flags); |
225 | msleep(50); /* Delay 0.05 sec */ | 229 | msleep(50); /* Delay 0.05 sec */ |
226 | cli(); | 230 | spin_lock_irqsave(&riscom_lock, flags); |
227 | rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ | 231 | rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ |
228 | rc_out(bp, CD180_GICR, 0); /* Clear all bits */ | 232 | rc_out(bp, CD180_GICR, 0); /* Clear all bits */ |
229 | rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ | 233 | rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ |
@@ -234,7 +238,7 @@ static void __init rc_init_CD180(struct riscom_board const * bp) | |||
234 | rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); | 238 | rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); |
235 | rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); | 239 | rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); |
236 | 240 | ||
237 | restore_flags(flags); | 241 | spin_unlock_irqrestore(&riscom_lock, flags); |
238 | } | 242 | } |
239 | 243 | ||
240 | /* Main probing routine, also sets irq. */ | 244 | /* Main probing routine, also sets irq. */ |
@@ -812,9 +816,9 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port) | |||
812 | } | 816 | } |
813 | port->xmit_buf = (unsigned char *) tmp; | 817 | port->xmit_buf = (unsigned char *) tmp; |
814 | } | 818 | } |
815 | 819 | ||
816 | save_flags(flags); cli(); | 820 | spin_lock_irqsave(&riscom_lock, flags); |
817 | 821 | ||
818 | if (port->tty) | 822 | if (port->tty) |
819 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 823 | clear_bit(TTY_IO_ERROR, &port->tty->flags); |
820 | 824 | ||
@@ -825,7 +829,7 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port) | |||
825 | rc_change_speed(bp, port); | 829 | rc_change_speed(bp, port); |
826 | port->flags |= ASYNC_INITIALIZED; | 830 | port->flags |= ASYNC_INITIALIZED; |
827 | 831 | ||
828 | restore_flags(flags); | 832 | spin_unlock_irqrestore(&riscom_lock, flags); |
829 | return 0; | 833 | return 0; |
830 | } | 834 | } |
831 | 835 | ||
@@ -901,6 +905,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
901 | int retval; | 905 | int retval; |
902 | int do_clocal = 0; | 906 | int do_clocal = 0; |
903 | int CD; | 907 | int CD; |
908 | unsigned long flags; | ||
904 | 909 | ||
905 | /* | 910 | /* |
906 | * If the device is in the middle of being closed, then block | 911 | * If the device is in the middle of being closed, then block |
@@ -936,19 +941,26 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
936 | */ | 941 | */ |
937 | retval = 0; | 942 | retval = 0; |
938 | add_wait_queue(&port->open_wait, &wait); | 943 | add_wait_queue(&port->open_wait, &wait); |
939 | cli(); | 944 | |
945 | spin_lock_irqsave(&riscom_lock, flags); | ||
946 | |||
940 | if (!tty_hung_up_p(filp)) | 947 | if (!tty_hung_up_p(filp)) |
941 | port->count--; | 948 | port->count--; |
942 | sti(); | 949 | |
950 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
951 | |||
943 | port->blocked_open++; | 952 | port->blocked_open++; |
944 | while (1) { | 953 | while (1) { |
945 | cli(); | 954 | spin_lock_irqsave(&riscom_lock, flags); |
955 | |||
946 | rc_out(bp, CD180_CAR, port_No(port)); | 956 | rc_out(bp, CD180_CAR, port_No(port)); |
947 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; | 957 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; |
948 | rc_out(bp, CD180_MSVR, MSVR_RTS); | 958 | rc_out(bp, CD180_MSVR, MSVR_RTS); |
949 | bp->DTR &= ~(1u << port_No(port)); | 959 | bp->DTR &= ~(1u << port_No(port)); |
950 | rc_out(bp, RC_DTR, bp->DTR); | 960 | rc_out(bp, RC_DTR, bp->DTR); |
951 | sti(); | 961 | |
962 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
963 | |||
952 | set_current_state(TASK_INTERRUPTIBLE); | 964 | set_current_state(TASK_INTERRUPTIBLE); |
953 | if (tty_hung_up_p(filp) || | 965 | if (tty_hung_up_p(filp) || |
954 | !(port->flags & ASYNC_INITIALIZED)) { | 966 | !(port->flags & ASYNC_INITIALIZED)) { |
@@ -1020,8 +1032,9 @@ static void rc_close(struct tty_struct * tty, struct file * filp) | |||
1020 | 1032 | ||
1021 | if (!port || rc_paranoia_check(port, tty->name, "close")) | 1033 | if (!port || rc_paranoia_check(port, tty->name, "close")) |
1022 | return; | 1034 | return; |
1023 | 1035 | ||
1024 | save_flags(flags); cli(); | 1036 | spin_lock_irqsave(&riscom_lock, flags); |
1037 | |||
1025 | if (tty_hung_up_p(filp)) | 1038 | if (tty_hung_up_p(filp)) |
1026 | goto out; | 1039 | goto out; |
1027 | 1040 | ||
@@ -1088,7 +1101,9 @@ static void rc_close(struct tty_struct * tty, struct file * filp) | |||
1088 | } | 1101 | } |
1089 | port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 1102 | port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
1090 | wake_up_interruptible(&port->close_wait); | 1103 | wake_up_interruptible(&port->close_wait); |
1091 | out: restore_flags(flags); | 1104 | |
1105 | out: | ||
1106 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1092 | } | 1107 | } |
1093 | 1108 | ||
1094 | static int rc_write(struct tty_struct * tty, | 1109 | static int rc_write(struct tty_struct * tty, |
@@ -1107,34 +1122,33 @@ static int rc_write(struct tty_struct * tty, | |||
1107 | if (!tty || !port->xmit_buf) | 1122 | if (!tty || !port->xmit_buf) |
1108 | return 0; | 1123 | return 0; |
1109 | 1124 | ||
1110 | save_flags(flags); | ||
1111 | while (1) { | 1125 | while (1) { |
1112 | cli(); | 1126 | spin_lock_irqsave(&riscom_lock, flags); |
1127 | |||
1113 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, | 1128 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, |
1114 | SERIAL_XMIT_SIZE - port->xmit_head)); | 1129 | SERIAL_XMIT_SIZE - port->xmit_head)); |
1115 | if (c <= 0) { | 1130 | if (c <= 0) |
1116 | restore_flags(flags); | 1131 | break; /* lock continues to be held */ |
1117 | break; | ||
1118 | } | ||
1119 | 1132 | ||
1120 | memcpy(port->xmit_buf + port->xmit_head, buf, c); | 1133 | memcpy(port->xmit_buf + port->xmit_head, buf, c); |
1121 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | 1134 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); |
1122 | port->xmit_cnt += c; | 1135 | port->xmit_cnt += c; |
1123 | restore_flags(flags); | 1136 | |
1137 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1124 | 1138 | ||
1125 | buf += c; | 1139 | buf += c; |
1126 | count -= c; | 1140 | count -= c; |
1127 | total += c; | 1141 | total += c; |
1128 | } | 1142 | } |
1129 | 1143 | ||
1130 | cli(); | ||
1131 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && | 1144 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && |
1132 | !(port->IER & IER_TXRDY)) { | 1145 | !(port->IER & IER_TXRDY)) { |
1133 | port->IER |= IER_TXRDY; | 1146 | port->IER |= IER_TXRDY; |
1134 | rc_out(bp, CD180_CAR, port_No(port)); | 1147 | rc_out(bp, CD180_CAR, port_No(port)); |
1135 | rc_out(bp, CD180_IER, port->IER); | 1148 | rc_out(bp, CD180_IER, port->IER); |
1136 | } | 1149 | } |
1137 | restore_flags(flags); | 1150 | |
1151 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1138 | 1152 | ||
1139 | return total; | 1153 | return total; |
1140 | } | 1154 | } |
@@ -1150,7 +1164,7 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch) | |||
1150 | if (!tty || !port->xmit_buf) | 1164 | if (!tty || !port->xmit_buf) |
1151 | return; | 1165 | return; |
1152 | 1166 | ||
1153 | save_flags(flags); cli(); | 1167 | spin_lock_irqsave(&riscom_lock, flags); |
1154 | 1168 | ||
1155 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) | 1169 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) |
1156 | goto out; | 1170 | goto out; |
@@ -1158,7 +1172,9 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch) | |||
1158 | port->xmit_buf[port->xmit_head++] = ch; | 1172 | port->xmit_buf[port->xmit_head++] = ch; |
1159 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | 1173 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; |
1160 | port->xmit_cnt++; | 1174 | port->xmit_cnt++; |
1161 | out: restore_flags(flags); | 1175 | |
1176 | out: | ||
1177 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1162 | } | 1178 | } |
1163 | 1179 | ||
1164 | static void rc_flush_chars(struct tty_struct * tty) | 1180 | static void rc_flush_chars(struct tty_struct * tty) |
@@ -1173,11 +1189,13 @@ static void rc_flush_chars(struct tty_struct * tty) | |||
1173 | !port->xmit_buf) | 1189 | !port->xmit_buf) |
1174 | return; | 1190 | return; |
1175 | 1191 | ||
1176 | save_flags(flags); cli(); | 1192 | spin_lock_irqsave(&riscom_lock, flags); |
1193 | |||
1177 | port->IER |= IER_TXRDY; | 1194 | port->IER |= IER_TXRDY; |
1178 | rc_out(port_Board(port), CD180_CAR, port_No(port)); | 1195 | rc_out(port_Board(port), CD180_CAR, port_No(port)); |
1179 | rc_out(port_Board(port), CD180_IER, port->IER); | 1196 | rc_out(port_Board(port), CD180_IER, port->IER); |
1180 | restore_flags(flags); | 1197 | |
1198 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1181 | } | 1199 | } |
1182 | 1200 | ||
1183 | static int rc_write_room(struct tty_struct * tty) | 1201 | static int rc_write_room(struct tty_struct * tty) |
@@ -1212,9 +1230,11 @@ static void rc_flush_buffer(struct tty_struct *tty) | |||
1212 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) | 1230 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) |
1213 | return; | 1231 | return; |
1214 | 1232 | ||
1215 | save_flags(flags); cli(); | 1233 | spin_lock_irqsave(&riscom_lock, flags); |
1234 | |||
1216 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 1235 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
1217 | restore_flags(flags); | 1236 | |
1237 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1218 | 1238 | ||
1219 | tty_wakeup(tty); | 1239 | tty_wakeup(tty); |
1220 | } | 1240 | } |
@@ -1231,11 +1251,15 @@ static int rc_tiocmget(struct tty_struct *tty, struct file *file) | |||
1231 | return -ENODEV; | 1251 | return -ENODEV; |
1232 | 1252 | ||
1233 | bp = port_Board(port); | 1253 | bp = port_Board(port); |
1234 | save_flags(flags); cli(); | 1254 | |
1255 | spin_lock_irqsave(&riscom_lock, flags); | ||
1256 | |||
1235 | rc_out(bp, CD180_CAR, port_No(port)); | 1257 | rc_out(bp, CD180_CAR, port_No(port)); |
1236 | status = rc_in(bp, CD180_MSVR); | 1258 | status = rc_in(bp, CD180_MSVR); |
1237 | result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; | 1259 | result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; |
1238 | restore_flags(flags); | 1260 | |
1261 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1262 | |||
1239 | result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) | 1263 | result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) |
1240 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | 1264 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) |
1241 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1265 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
@@ -1256,7 +1280,8 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1256 | 1280 | ||
1257 | bp = port_Board(port); | 1281 | bp = port_Board(port); |
1258 | 1282 | ||
1259 | save_flags(flags); cli(); | 1283 | spin_lock_irqsave(&riscom_lock, flags); |
1284 | |||
1260 | if (set & TIOCM_RTS) | 1285 | if (set & TIOCM_RTS) |
1261 | port->MSVR |= MSVR_RTS; | 1286 | port->MSVR |= MSVR_RTS; |
1262 | if (set & TIOCM_DTR) | 1287 | if (set & TIOCM_DTR) |
@@ -1270,7 +1295,9 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1270 | rc_out(bp, CD180_CAR, port_No(port)); | 1295 | rc_out(bp, CD180_CAR, port_No(port)); |
1271 | rc_out(bp, CD180_MSVR, port->MSVR); | 1296 | rc_out(bp, CD180_MSVR, port->MSVR); |
1272 | rc_out(bp, RC_DTR, bp->DTR); | 1297 | rc_out(bp, RC_DTR, bp->DTR); |
1273 | restore_flags(flags); | 1298 | |
1299 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1300 | |||
1274 | return 0; | 1301 | return 0; |
1275 | } | 1302 | } |
1276 | 1303 | ||
@@ -1279,7 +1306,8 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length | |||
1279 | struct riscom_board *bp = port_Board(port); | 1306 | struct riscom_board *bp = port_Board(port); |
1280 | unsigned long flags; | 1307 | unsigned long flags; |
1281 | 1308 | ||
1282 | save_flags(flags); cli(); | 1309 | spin_lock_irqsave(&riscom_lock, flags); |
1310 | |||
1283 | port->break_length = RISCOM_TPS / HZ * length; | 1311 | port->break_length = RISCOM_TPS / HZ * length; |
1284 | port->COR2 |= COR2_ETC; | 1312 | port->COR2 |= COR2_ETC; |
1285 | port->IER |= IER_TXRDY; | 1313 | port->IER |= IER_TXRDY; |
@@ -1289,7 +1317,8 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length | |||
1289 | rc_wait_CCR(bp); | 1317 | rc_wait_CCR(bp); |
1290 | rc_out(bp, CD180_CCR, CCR_CORCHG2); | 1318 | rc_out(bp, CD180_CCR, CCR_CORCHG2); |
1291 | rc_wait_CCR(bp); | 1319 | rc_wait_CCR(bp); |
1292 | restore_flags(flags); | 1320 | |
1321 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1293 | } | 1322 | } |
1294 | 1323 | ||
1295 | static inline int rc_set_serial_info(struct riscom_port * port, | 1324 | static inline int rc_set_serial_info(struct riscom_port * port, |
@@ -1298,7 +1327,6 @@ static inline int rc_set_serial_info(struct riscom_port * port, | |||
1298 | struct serial_struct tmp; | 1327 | struct serial_struct tmp; |
1299 | struct riscom_board *bp = port_Board(port); | 1328 | struct riscom_board *bp = port_Board(port); |
1300 | int change_speed; | 1329 | int change_speed; |
1301 | unsigned long flags; | ||
1302 | 1330 | ||
1303 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) | 1331 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) |
1304 | return -EFAULT; | 1332 | return -EFAULT; |
@@ -1332,9 +1360,11 @@ static inline int rc_set_serial_info(struct riscom_port * port, | |||
1332 | port->closing_wait = tmp.closing_wait; | 1360 | port->closing_wait = tmp.closing_wait; |
1333 | } | 1361 | } |
1334 | if (change_speed) { | 1362 | if (change_speed) { |
1335 | save_flags(flags); cli(); | 1363 | unsigned long flags; |
1364 | |||
1365 | spin_lock_irqsave(&riscom_lock, flags); | ||
1336 | rc_change_speed(bp, port); | 1366 | rc_change_speed(bp, port); |
1337 | restore_flags(flags); | 1367 | spin_unlock_irqrestore(&riscom_lock, flags); |
1338 | } | 1368 | } |
1339 | return 0; | 1369 | return 0; |
1340 | } | 1370 | } |
@@ -1414,17 +1444,19 @@ static void rc_throttle(struct tty_struct * tty) | |||
1414 | return; | 1444 | return; |
1415 | 1445 | ||
1416 | bp = port_Board(port); | 1446 | bp = port_Board(port); |
1417 | 1447 | ||
1418 | save_flags(flags); cli(); | 1448 | spin_lock_irqsave(&riscom_lock, flags); |
1449 | |||
1419 | port->MSVR &= ~MSVR_RTS; | 1450 | port->MSVR &= ~MSVR_RTS; |
1420 | rc_out(bp, CD180_CAR, port_No(port)); | 1451 | rc_out(bp, CD180_CAR, port_No(port)); |
1421 | if (I_IXOFF(tty)) { | 1452 | if (I_IXOFF(tty)) { |
1422 | rc_wait_CCR(bp); | 1453 | rc_wait_CCR(bp); |
1423 | rc_out(bp, CD180_CCR, CCR_SSCH2); | 1454 | rc_out(bp, CD180_CCR, CCR_SSCH2); |
1424 | rc_wait_CCR(bp); | 1455 | rc_wait_CCR(bp); |
1425 | } | 1456 | } |
1426 | rc_out(bp, CD180_MSVR, port->MSVR); | 1457 | rc_out(bp, CD180_MSVR, port->MSVR); |
1427 | restore_flags(flags); | 1458 | |
1459 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1428 | } | 1460 | } |
1429 | 1461 | ||
1430 | static void rc_unthrottle(struct tty_struct * tty) | 1462 | static void rc_unthrottle(struct tty_struct * tty) |
@@ -1438,7 +1470,8 @@ static void rc_unthrottle(struct tty_struct * tty) | |||
1438 | 1470 | ||
1439 | bp = port_Board(port); | 1471 | bp = port_Board(port); |
1440 | 1472 | ||
1441 | save_flags(flags); cli(); | 1473 | spin_lock_irqsave(&riscom_lock, flags); |
1474 | |||
1442 | port->MSVR |= MSVR_RTS; | 1475 | port->MSVR |= MSVR_RTS; |
1443 | rc_out(bp, CD180_CAR, port_No(port)); | 1476 | rc_out(bp, CD180_CAR, port_No(port)); |
1444 | if (I_IXOFF(tty)) { | 1477 | if (I_IXOFF(tty)) { |
@@ -1447,7 +1480,8 @@ static void rc_unthrottle(struct tty_struct * tty) | |||
1447 | rc_wait_CCR(bp); | 1480 | rc_wait_CCR(bp); |
1448 | } | 1481 | } |
1449 | rc_out(bp, CD180_MSVR, port->MSVR); | 1482 | rc_out(bp, CD180_MSVR, port->MSVR); |
1450 | restore_flags(flags); | 1483 | |
1484 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1451 | } | 1485 | } |
1452 | 1486 | ||
1453 | static void rc_stop(struct tty_struct * tty) | 1487 | static void rc_stop(struct tty_struct * tty) |
@@ -1461,11 +1495,13 @@ static void rc_stop(struct tty_struct * tty) | |||
1461 | 1495 | ||
1462 | bp = port_Board(port); | 1496 | bp = port_Board(port); |
1463 | 1497 | ||
1464 | save_flags(flags); cli(); | 1498 | spin_lock_irqsave(&riscom_lock, flags); |
1499 | |||
1465 | port->IER &= ~IER_TXRDY; | 1500 | port->IER &= ~IER_TXRDY; |
1466 | rc_out(bp, CD180_CAR, port_No(port)); | 1501 | rc_out(bp, CD180_CAR, port_No(port)); |
1467 | rc_out(bp, CD180_IER, port->IER); | 1502 | rc_out(bp, CD180_IER, port->IER); |
1468 | restore_flags(flags); | 1503 | |
1504 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1469 | } | 1505 | } |
1470 | 1506 | ||
1471 | static void rc_start(struct tty_struct * tty) | 1507 | static void rc_start(struct tty_struct * tty) |
@@ -1479,13 +1515,15 @@ static void rc_start(struct tty_struct * tty) | |||
1479 | 1515 | ||
1480 | bp = port_Board(port); | 1516 | bp = port_Board(port); |
1481 | 1517 | ||
1482 | save_flags(flags); cli(); | 1518 | spin_lock_irqsave(&riscom_lock, flags); |
1519 | |||
1483 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { | 1520 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { |
1484 | port->IER |= IER_TXRDY; | 1521 | port->IER |= IER_TXRDY; |
1485 | rc_out(bp, CD180_CAR, port_No(port)); | 1522 | rc_out(bp, CD180_CAR, port_No(port)); |
1486 | rc_out(bp, CD180_IER, port->IER); | 1523 | rc_out(bp, CD180_IER, port->IER); |
1487 | } | 1524 | } |
1488 | restore_flags(flags); | 1525 | |
1526 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1489 | } | 1527 | } |
1490 | 1528 | ||
1491 | /* | 1529 | /* |
@@ -1537,9 +1575,9 @@ static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termio | |||
1537 | tty->termios->c_iflag == old_termios->c_iflag) | 1575 | tty->termios->c_iflag == old_termios->c_iflag) |
1538 | return; | 1576 | return; |
1539 | 1577 | ||
1540 | save_flags(flags); cli(); | 1578 | spin_lock_irqsave(&riscom_lock, flags); |
1541 | rc_change_speed(port_Board(port), port); | 1579 | rc_change_speed(port_Board(port), port); |
1542 | restore_flags(flags); | 1580 | spin_unlock_irqrestore(&riscom_lock, flags); |
1543 | 1581 | ||
1544 | if ((old_termios->c_cflag & CRTSCTS) && | 1582 | if ((old_termios->c_cflag & CRTSCTS) && |
1545 | !(tty->termios->c_cflag & CRTSCTS)) { | 1583 | !(tty->termios->c_cflag & CRTSCTS)) { |
@@ -1627,11 +1665,12 @@ static void rc_release_drivers(void) | |||
1627 | { | 1665 | { |
1628 | unsigned long flags; | 1666 | unsigned long flags; |
1629 | 1667 | ||
1630 | save_flags(flags); | 1668 | spin_lock_irqsave(&riscom_lock, flags); |
1631 | cli(); | 1669 | |
1632 | tty_unregister_driver(riscom_driver); | 1670 | tty_unregister_driver(riscom_driver); |
1633 | put_tty_driver(riscom_driver); | 1671 | put_tty_driver(riscom_driver); |
1634 | restore_flags(flags); | 1672 | |
1673 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1635 | } | 1674 | } |
1636 | 1675 | ||
1637 | #ifndef MODULE | 1676 | #ifndef MODULE |
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 3c869145bfdc..4ba3aec9e1cd 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c | |||
@@ -653,7 +653,7 @@ static void a2232_init_portstructs(void) | |||
653 | port->gs.closing_wait = 30 * HZ; | 653 | port->gs.closing_wait = 30 * HZ; |
654 | port->gs.rd = &a2232_real_driver; | 654 | port->gs.rd = &a2232_real_driver; |
655 | #ifdef NEW_WRITE_LOCKING | 655 | #ifdef NEW_WRITE_LOCKING |
656 | init_MUTEX(&(port->gs.port_write_mutex)); | 656 | mutex_init(&(port->gs.port_write_mutex)); |
657 | #endif | 657 | #endif |
658 | init_waitqueue_head(&port->gs.open_wait); | 658 | init_waitqueue_head(&port->gs.open_wait); |
659 | init_waitqueue_head(&port->gs.close_wait); | 659 | init_waitqueue_head(&port->gs.close_wait); |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index d010ed95ed3b..ddc74d1f4f1b 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -85,6 +85,7 @@ | |||
85 | #include <linux/vmalloc.h> | 85 | #include <linux/vmalloc.h> |
86 | #include <linux/init.h> | 86 | #include <linux/init.h> |
87 | #include <linux/ioctl.h> | 87 | #include <linux/ioctl.h> |
88 | #include <linux/synclink.h> | ||
88 | 89 | ||
89 | #include <asm/system.h> | 90 | #include <asm/system.h> |
90 | #include <asm/io.h> | 91 | #include <asm/io.h> |
@@ -110,8 +111,6 @@ | |||
110 | 111 | ||
111 | #include <asm/uaccess.h> | 112 | #include <asm/uaccess.h> |
112 | 113 | ||
113 | #include "linux/synclink.h" | ||
114 | |||
115 | #define RCLRVALUE 0xffff | 114 | #define RCLRVALUE 0xffff |
116 | 115 | ||
117 | static MGSL_PARAMS default_params = { | 116 | static MGSL_PARAMS default_params = { |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 64e835f62438..1f954acf2bac 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -73,6 +73,7 @@ | |||
73 | #include <linux/bitops.h> | 73 | #include <linux/bitops.h> |
74 | #include <linux/workqueue.h> | 74 | #include <linux/workqueue.h> |
75 | #include <linux/hdlc.h> | 75 | #include <linux/hdlc.h> |
76 | #include <linux/synclink.h> | ||
76 | 77 | ||
77 | #include <asm/system.h> | 78 | #include <asm/system.h> |
78 | #include <asm/io.h> | 79 | #include <asm/io.h> |
@@ -81,8 +82,6 @@ | |||
81 | #include <asm/types.h> | 82 | #include <asm/types.h> |
82 | #include <asm/uaccess.h> | 83 | #include <asm/uaccess.h> |
83 | 84 | ||
84 | #include "linux/synclink.h" | ||
85 | |||
86 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) | 85 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) |
87 | #define SYNCLINK_GENERIC_HDLC 1 | 86 | #define SYNCLINK_GENERIC_HDLC 1 |
88 | #else | 87 | #else |
@@ -2040,37 +2039,41 @@ static void bh_transmit(struct slgt_info *info) | |||
2040 | tty_wakeup(tty); | 2039 | tty_wakeup(tty); |
2041 | } | 2040 | } |
2042 | 2041 | ||
2043 | static void dsr_change(struct slgt_info *info) | 2042 | static void dsr_change(struct slgt_info *info, unsigned short status) |
2044 | { | 2043 | { |
2045 | get_signals(info); | 2044 | if (status & BIT3) { |
2045 | info->signals |= SerialSignal_DSR; | ||
2046 | info->input_signal_events.dsr_up++; | ||
2047 | } else { | ||
2048 | info->signals &= ~SerialSignal_DSR; | ||
2049 | info->input_signal_events.dsr_down++; | ||
2050 | } | ||
2046 | DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); | 2051 | DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); |
2047 | if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2052 | if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2048 | slgt_irq_off(info, IRQ_DSR); | 2053 | slgt_irq_off(info, IRQ_DSR); |
2049 | return; | 2054 | return; |
2050 | } | 2055 | } |
2051 | info->icount.dsr++; | 2056 | info->icount.dsr++; |
2052 | if (info->signals & SerialSignal_DSR) | ||
2053 | info->input_signal_events.dsr_up++; | ||
2054 | else | ||
2055 | info->input_signal_events.dsr_down++; | ||
2056 | wake_up_interruptible(&info->status_event_wait_q); | 2057 | wake_up_interruptible(&info->status_event_wait_q); |
2057 | wake_up_interruptible(&info->event_wait_q); | 2058 | wake_up_interruptible(&info->event_wait_q); |
2058 | info->pending_bh |= BH_STATUS; | 2059 | info->pending_bh |= BH_STATUS; |
2059 | } | 2060 | } |
2060 | 2061 | ||
2061 | static void cts_change(struct slgt_info *info) | 2062 | static void cts_change(struct slgt_info *info, unsigned short status) |
2062 | { | 2063 | { |
2063 | get_signals(info); | 2064 | if (status & BIT2) { |
2065 | info->signals |= SerialSignal_CTS; | ||
2066 | info->input_signal_events.cts_up++; | ||
2067 | } else { | ||
2068 | info->signals &= ~SerialSignal_CTS; | ||
2069 | info->input_signal_events.cts_down++; | ||
2070 | } | ||
2064 | DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); | 2071 | DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); |
2065 | if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2072 | if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2066 | slgt_irq_off(info, IRQ_CTS); | 2073 | slgt_irq_off(info, IRQ_CTS); |
2067 | return; | 2074 | return; |
2068 | } | 2075 | } |
2069 | info->icount.cts++; | 2076 | info->icount.cts++; |
2070 | if (info->signals & SerialSignal_CTS) | ||
2071 | info->input_signal_events.cts_up++; | ||
2072 | else | ||
2073 | info->input_signal_events.cts_down++; | ||
2074 | wake_up_interruptible(&info->status_event_wait_q); | 2077 | wake_up_interruptible(&info->status_event_wait_q); |
2075 | wake_up_interruptible(&info->event_wait_q); | 2078 | wake_up_interruptible(&info->event_wait_q); |
2076 | info->pending_bh |= BH_STATUS; | 2079 | info->pending_bh |= BH_STATUS; |
@@ -2091,20 +2094,21 @@ static void cts_change(struct slgt_info *info) | |||
2091 | } | 2094 | } |
2092 | } | 2095 | } |
2093 | 2096 | ||
2094 | static void dcd_change(struct slgt_info *info) | 2097 | static void dcd_change(struct slgt_info *info, unsigned short status) |
2095 | { | 2098 | { |
2096 | get_signals(info); | 2099 | if (status & BIT1) { |
2100 | info->signals |= SerialSignal_DCD; | ||
2101 | info->input_signal_events.dcd_up++; | ||
2102 | } else { | ||
2103 | info->signals &= ~SerialSignal_DCD; | ||
2104 | info->input_signal_events.dcd_down++; | ||
2105 | } | ||
2097 | DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); | 2106 | DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); |
2098 | if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2107 | if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2099 | slgt_irq_off(info, IRQ_DCD); | 2108 | slgt_irq_off(info, IRQ_DCD); |
2100 | return; | 2109 | return; |
2101 | } | 2110 | } |
2102 | info->icount.dcd++; | 2111 | info->icount.dcd++; |
2103 | if (info->signals & SerialSignal_DCD) { | ||
2104 | info->input_signal_events.dcd_up++; | ||
2105 | } else { | ||
2106 | info->input_signal_events.dcd_down++; | ||
2107 | } | ||
2108 | #if SYNCLINK_GENERIC_HDLC | 2112 | #if SYNCLINK_GENERIC_HDLC |
2109 | if (info->netcount) { | 2113 | if (info->netcount) { |
2110 | if (info->signals & SerialSignal_DCD) | 2114 | if (info->signals & SerialSignal_DCD) |
@@ -2127,20 +2131,21 @@ static void dcd_change(struct slgt_info *info) | |||
2127 | } | 2131 | } |
2128 | } | 2132 | } |
2129 | 2133 | ||
2130 | static void ri_change(struct slgt_info *info) | 2134 | static void ri_change(struct slgt_info *info, unsigned short status) |
2131 | { | 2135 | { |
2132 | get_signals(info); | 2136 | if (status & BIT0) { |
2137 | info->signals |= SerialSignal_RI; | ||
2138 | info->input_signal_events.ri_up++; | ||
2139 | } else { | ||
2140 | info->signals &= ~SerialSignal_RI; | ||
2141 | info->input_signal_events.ri_down++; | ||
2142 | } | ||
2133 | DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); | 2143 | DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); |
2134 | if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2144 | if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2135 | slgt_irq_off(info, IRQ_RI); | 2145 | slgt_irq_off(info, IRQ_RI); |
2136 | return; | 2146 | return; |
2137 | } | 2147 | } |
2138 | info->icount.dcd++; | 2148 | info->icount.rng++; |
2139 | if (info->signals & SerialSignal_RI) { | ||
2140 | info->input_signal_events.ri_up++; | ||
2141 | } else { | ||
2142 | info->input_signal_events.ri_down++; | ||
2143 | } | ||
2144 | wake_up_interruptible(&info->status_event_wait_q); | 2149 | wake_up_interruptible(&info->status_event_wait_q); |
2145 | wake_up_interruptible(&info->event_wait_q); | 2150 | wake_up_interruptible(&info->event_wait_q); |
2146 | info->pending_bh |= BH_STATUS; | 2151 | info->pending_bh |= BH_STATUS; |
@@ -2191,13 +2196,13 @@ static void isr_serial(struct slgt_info *info) | |||
2191 | } | 2196 | } |
2192 | 2197 | ||
2193 | if (status & IRQ_DSR) | 2198 | if (status & IRQ_DSR) |
2194 | dsr_change(info); | 2199 | dsr_change(info, status); |
2195 | if (status & IRQ_CTS) | 2200 | if (status & IRQ_CTS) |
2196 | cts_change(info); | 2201 | cts_change(info, status); |
2197 | if (status & IRQ_DCD) | 2202 | if (status & IRQ_DCD) |
2198 | dcd_change(info); | 2203 | dcd_change(info, status); |
2199 | if (status & IRQ_RI) | 2204 | if (status & IRQ_RI) |
2200 | ri_change(info); | 2205 | ri_change(info, status); |
2201 | } | 2206 | } |
2202 | 2207 | ||
2203 | static void isr_rdma(struct slgt_info *info) | 2208 | static void isr_rdma(struct slgt_info *info) |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index c63013b2fc36..f3e7807f78d9 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/termios.h> | 66 | #include <linux/termios.h> |
67 | #include <linux/workqueue.h> | 67 | #include <linux/workqueue.h> |
68 | #include <linux/hdlc.h> | 68 | #include <linux/hdlc.h> |
69 | #include <linux/synclink.h> | ||
69 | 70 | ||
70 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE)) | 71 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE)) |
71 | #define SYNCLINK_GENERIC_HDLC 1 | 72 | #define SYNCLINK_GENERIC_HDLC 1 |
@@ -80,8 +81,6 @@ | |||
80 | 81 | ||
81 | #include <asm/uaccess.h> | 82 | #include <asm/uaccess.h> |
82 | 83 | ||
83 | #include "linux/synclink.h" | ||
84 | |||
85 | static MGSL_PARAMS default_params = { | 84 | static MGSL_PARAMS default_params = { |
86 | MGSL_MODE_HDLC, /* unsigned long mode */ | 85 | MGSL_MODE_HDLC, /* unsigned long mode */ |
87 | 0, /* unsigned char loopback; */ | 86 | 0, /* unsigned char loopback; */ |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index c88424a0c89b..a5d8bcb40000 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1031,18 +1031,13 @@ void tpm_remove_hardware(struct device *dev) | |||
1031 | 1031 | ||
1032 | spin_unlock(&driver_lock); | 1032 | spin_unlock(&driver_lock); |
1033 | 1033 | ||
1034 | dev_set_drvdata(dev, NULL); | ||
1035 | misc_deregister(&chip->vendor.miscdev); | 1034 | misc_deregister(&chip->vendor.miscdev); |
1036 | kfree(chip->vendor.miscdev.name); | ||
1037 | 1035 | ||
1038 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); | 1036 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); |
1039 | tpm_bios_log_teardown(chip->bios_dir); | 1037 | tpm_bios_log_teardown(chip->bios_dir); |
1040 | 1038 | ||
1041 | clear_bit(chip->dev_num, dev_mask); | 1039 | /* write it this way to be explicit (chip->dev == dev) */ |
1042 | 1040 | put_device(chip->dev); | |
1043 | kfree(chip); | ||
1044 | |||
1045 | put_device(dev); | ||
1046 | } | 1041 | } |
1047 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); | 1042 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); |
1048 | 1043 | ||
@@ -1083,6 +1078,26 @@ int tpm_pm_resume(struct device *dev) | |||
1083 | EXPORT_SYMBOL_GPL(tpm_pm_resume); | 1078 | EXPORT_SYMBOL_GPL(tpm_pm_resume); |
1084 | 1079 | ||
1085 | /* | 1080 | /* |
1081 | * Once all references to platform device are down to 0, | ||
1082 | * release all allocated structures. | ||
1083 | * In case vendor provided release function, | ||
1084 | * call it too. | ||
1085 | */ | ||
1086 | static void tpm_dev_release(struct device *dev) | ||
1087 | { | ||
1088 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
1089 | |||
1090 | if (chip->vendor.release) | ||
1091 | chip->vendor.release(dev); | ||
1092 | |||
1093 | chip->release(dev); | ||
1094 | |||
1095 | clear_bit(chip->dev_num, dev_mask); | ||
1096 | kfree(chip->vendor.miscdev.name); | ||
1097 | kfree(chip); | ||
1098 | } | ||
1099 | |||
1100 | /* | ||
1086 | * Called from tpm_<specific>.c probe function only for devices | 1101 | * Called from tpm_<specific>.c probe function only for devices |
1087 | * the driver has determined it should claim. Prior to calling | 1102 | * the driver has determined it should claim. Prior to calling |
1088 | * this function the specific probe function has called pci_enable_device | 1103 | * this function the specific probe function has called pci_enable_device |
@@ -1136,23 +1151,21 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1136 | 1151 | ||
1137 | chip->vendor.miscdev.parent = dev; | 1152 | chip->vendor.miscdev.parent = dev; |
1138 | chip->dev = get_device(dev); | 1153 | chip->dev = get_device(dev); |
1154 | chip->release = dev->release; | ||
1155 | dev->release = tpm_dev_release; | ||
1156 | dev_set_drvdata(dev, chip); | ||
1139 | 1157 | ||
1140 | if (misc_register(&chip->vendor.miscdev)) { | 1158 | if (misc_register(&chip->vendor.miscdev)) { |
1141 | dev_err(chip->dev, | 1159 | dev_err(chip->dev, |
1142 | "unable to misc_register %s, minor %d\n", | 1160 | "unable to misc_register %s, minor %d\n", |
1143 | chip->vendor.miscdev.name, | 1161 | chip->vendor.miscdev.name, |
1144 | chip->vendor.miscdev.minor); | 1162 | chip->vendor.miscdev.minor); |
1145 | put_device(dev); | 1163 | put_device(chip->dev); |
1146 | clear_bit(chip->dev_num, dev_mask); | ||
1147 | kfree(chip); | ||
1148 | kfree(devname); | ||
1149 | return NULL; | 1164 | return NULL; |
1150 | } | 1165 | } |
1151 | 1166 | ||
1152 | spin_lock(&driver_lock); | 1167 | spin_lock(&driver_lock); |
1153 | 1168 | ||
1154 | dev_set_drvdata(dev, chip); | ||
1155 | |||
1156 | list_add(&chip->list, &tpm_chip_list); | 1169 | list_add(&chip->list, &tpm_chip_list); |
1157 | 1170 | ||
1158 | spin_unlock(&driver_lock); | 1171 | spin_unlock(&driver_lock); |
@@ -1160,10 +1173,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1160 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { | 1173 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { |
1161 | list_del(&chip->list); | 1174 | list_del(&chip->list); |
1162 | misc_deregister(&chip->vendor.miscdev); | 1175 | misc_deregister(&chip->vendor.miscdev); |
1163 | put_device(dev); | 1176 | put_device(chip->dev); |
1164 | clear_bit(chip->dev_num, dev_mask); | ||
1165 | kfree(chip); | ||
1166 | kfree(devname); | ||
1167 | return NULL; | 1177 | return NULL; |
1168 | } | 1178 | } |
1169 | 1179 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index d15ccddc92eb..e885148b4cfb 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -74,6 +74,7 @@ struct tpm_vendor_specific { | |||
74 | int (*send) (struct tpm_chip *, u8 *, size_t); | 74 | int (*send) (struct tpm_chip *, u8 *, size_t); |
75 | void (*cancel) (struct tpm_chip *); | 75 | void (*cancel) (struct tpm_chip *); |
76 | u8 (*status) (struct tpm_chip *); | 76 | u8 (*status) (struct tpm_chip *); |
77 | void (*release) (struct device *); | ||
77 | struct miscdevice miscdev; | 78 | struct miscdevice miscdev; |
78 | struct attribute_group *attr_group; | 79 | struct attribute_group *attr_group; |
79 | struct list_head list; | 80 | struct list_head list; |
@@ -106,6 +107,7 @@ struct tpm_chip { | |||
106 | struct dentry **bios_dir; | 107 | struct dentry **bios_dir; |
107 | 108 | ||
108 | struct list_head list; | 109 | struct list_head list; |
110 | void (*release) (struct device *); | ||
109 | }; | 111 | }; |
110 | 112 | ||
111 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) | 113 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) |
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 967002a5a1e5..726ee8a0277f 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -611,7 +611,7 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) | |||
611 | } | 611 | } |
612 | } | 612 | } |
613 | 613 | ||
614 | static struct pnp_driver tpm_inf_pnp = { | 614 | static struct pnp_driver tpm_inf_pnp_driver = { |
615 | .name = "tpm_inf_pnp", | 615 | .name = "tpm_inf_pnp", |
616 | .driver = { | 616 | .driver = { |
617 | .owner = THIS_MODULE, | 617 | .owner = THIS_MODULE, |
@@ -625,12 +625,12 @@ static struct pnp_driver tpm_inf_pnp = { | |||
625 | 625 | ||
626 | static int __init init_inf(void) | 626 | static int __init init_inf(void) |
627 | { | 627 | { |
628 | return pnp_register_driver(&tpm_inf_pnp); | 628 | return pnp_register_driver(&tpm_inf_pnp_driver); |
629 | } | 629 | } |
630 | 630 | ||
631 | static void __exit cleanup_inf(void) | 631 | static void __exit cleanup_inf(void) |
632 | { | 632 | { |
633 | pnp_unregister_driver(&tpm_inf_pnp); | 633 | pnp_unregister_driver(&tpm_inf_pnp_driver); |
634 | } | 634 | } |
635 | 635 | ||
636 | module_init(init_inf); | 636 | module_init(init_inf); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f36fecd3fd26..79c86c47947f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -138,7 +138,7 @@ EXPORT_SYMBOL(tty_mutex); | |||
138 | extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ | 138 | extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ |
139 | extern int pty_limit; /* Config limit on Unix98 ptys */ | 139 | extern int pty_limit; /* Config limit on Unix98 ptys */ |
140 | static DEFINE_IDR(allocated_ptys); | 140 | static DEFINE_IDR(allocated_ptys); |
141 | static DECLARE_MUTEX(allocated_ptys_lock); | 141 | static DEFINE_MUTEX(allocated_ptys_lock); |
142 | static int ptmx_open(struct inode *, struct file *); | 142 | static int ptmx_open(struct inode *, struct file *); |
143 | #endif | 143 | #endif |
144 | 144 | ||
@@ -2571,9 +2571,9 @@ static void release_dev(struct file * filp) | |||
2571 | #ifdef CONFIG_UNIX98_PTYS | 2571 | #ifdef CONFIG_UNIX98_PTYS |
2572 | /* Make this pty number available for reallocation */ | 2572 | /* Make this pty number available for reallocation */ |
2573 | if (devpts) { | 2573 | if (devpts) { |
2574 | down(&allocated_ptys_lock); | 2574 | mutex_lock(&allocated_ptys_lock); |
2575 | idr_remove(&allocated_ptys, idx); | 2575 | idr_remove(&allocated_ptys, idx); |
2576 | up(&allocated_ptys_lock); | 2576 | mutex_unlock(&allocated_ptys_lock); |
2577 | } | 2577 | } |
2578 | #endif | 2578 | #endif |
2579 | 2579 | ||
@@ -2737,24 +2737,24 @@ static int ptmx_open(struct inode * inode, struct file * filp) | |||
2737 | nonseekable_open(inode, filp); | 2737 | nonseekable_open(inode, filp); |
2738 | 2738 | ||
2739 | /* find a device that is not in use. */ | 2739 | /* find a device that is not in use. */ |
2740 | down(&allocated_ptys_lock); | 2740 | mutex_lock(&allocated_ptys_lock); |
2741 | if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { | 2741 | if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { |
2742 | up(&allocated_ptys_lock); | 2742 | mutex_unlock(&allocated_ptys_lock); |
2743 | return -ENOMEM; | 2743 | return -ENOMEM; |
2744 | } | 2744 | } |
2745 | idr_ret = idr_get_new(&allocated_ptys, NULL, &index); | 2745 | idr_ret = idr_get_new(&allocated_ptys, NULL, &index); |
2746 | if (idr_ret < 0) { | 2746 | if (idr_ret < 0) { |
2747 | up(&allocated_ptys_lock); | 2747 | mutex_unlock(&allocated_ptys_lock); |
2748 | if (idr_ret == -EAGAIN) | 2748 | if (idr_ret == -EAGAIN) |
2749 | return -ENOMEM; | 2749 | return -ENOMEM; |
2750 | return -EIO; | 2750 | return -EIO; |
2751 | } | 2751 | } |
2752 | if (index >= pty_limit) { | 2752 | if (index >= pty_limit) { |
2753 | idr_remove(&allocated_ptys, index); | 2753 | idr_remove(&allocated_ptys, index); |
2754 | up(&allocated_ptys_lock); | 2754 | mutex_unlock(&allocated_ptys_lock); |
2755 | return -EIO; | 2755 | return -EIO; |
2756 | } | 2756 | } |
2757 | up(&allocated_ptys_lock); | 2757 | mutex_unlock(&allocated_ptys_lock); |
2758 | 2758 | ||
2759 | mutex_lock(&tty_mutex); | 2759 | mutex_lock(&tty_mutex); |
2760 | retval = init_dev(ptm_driver, index, &tty); | 2760 | retval = init_dev(ptm_driver, index, &tty); |
@@ -2781,9 +2781,9 @@ out1: | |||
2781 | release_dev(filp); | 2781 | release_dev(filp); |
2782 | return retval; | 2782 | return retval; |
2783 | out: | 2783 | out: |
2784 | down(&allocated_ptys_lock); | 2784 | mutex_lock(&allocated_ptys_lock); |
2785 | idr_remove(&allocated_ptys, index); | 2785 | idr_remove(&allocated_ptys, index); |
2786 | up(&allocated_ptys_lock); | 2786 | mutex_unlock(&allocated_ptys_lock); |
2787 | return retval; | 2787 | return retval; |
2788 | } | 2788 | } |
2789 | #endif | 2789 | #endif |
@@ -3721,7 +3721,6 @@ static void initialize_tty_struct(struct tty_struct *tty) | |||
3721 | tty->buf.head = tty->buf.tail = NULL; | 3721 | tty->buf.head = tty->buf.tail = NULL; |
3722 | tty_buffer_init(tty); | 3722 | tty_buffer_init(tty); |
3723 | INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); | 3723 | INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); |
3724 | init_MUTEX(&tty->buf.pty_sem); | ||
3725 | mutex_init(&tty->termios_mutex); | 3724 | mutex_init(&tty->termios_mutex); |
3726 | init_waitqueue_head(&tty->write_wait); | 3725 | init_waitqueue_head(&tty->write_wait); |
3727 | init_waitqueue_head(&tty->read_wait); | 3726 | init_waitqueue_head(&tty->read_wait); |
@@ -4048,10 +4047,6 @@ void __init console_init(void) | |||
4048 | } | 4047 | } |
4049 | } | 4048 | } |
4050 | 4049 | ||
4051 | #ifdef CONFIG_VT | ||
4052 | extern int vty_init(void); | ||
4053 | #endif | ||
4054 | |||
4055 | static int __init tty_class_init(void) | 4050 | static int __init tty_class_init(void) |
4056 | { | 4051 | { |
4057 | tty_class = class_create(THIS_MODULE, "tty"); | 4052 | tty_class = class_create(THIS_MODULE, "tty"); |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7a5badfb7d84..367be9175061 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -2400,13 +2400,15 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
2400 | { | 2400 | { |
2401 | struct vc_data *vc = vc_cons[fg_console].d; | 2401 | struct vc_data *vc = vc_cons[fg_console].d; |
2402 | unsigned char c; | 2402 | unsigned char c; |
2403 | static unsigned long printing; | 2403 | static DEFINE_SPINLOCK(printing_lock); |
2404 | const ushort *start; | 2404 | const ushort *start; |
2405 | ushort cnt = 0; | 2405 | ushort cnt = 0; |
2406 | ushort myx; | 2406 | ushort myx; |
2407 | 2407 | ||
2408 | /* console busy or not yet initialized */ | 2408 | /* console busy or not yet initialized */ |
2409 | if (!printable || test_and_set_bit(0, &printing)) | 2409 | if (!printable) |
2410 | return; | ||
2411 | if (!spin_trylock(&printing_lock)) | ||
2410 | return; | 2412 | return; |
2411 | 2413 | ||
2412 | if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) | 2414 | if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) |
@@ -2481,7 +2483,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
2481 | notify_update(vc); | 2483 | notify_update(vc); |
2482 | 2484 | ||
2483 | quit: | 2485 | quit: |
2484 | clear_bit(0, &printing); | 2486 | spin_unlock(&printing_lock); |
2485 | } | 2487 | } |
2486 | 2488 | ||
2487 | static struct tty_driver *vt_console_device(struct console *c, int *index) | 2489 | static struct tty_driver *vt_console_device(struct console *c, int *index) |
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 18cdcb3ae1ca..1636806ec55e 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c | |||
@@ -658,4 +658,5 @@ MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")"); | |||
658 | MODULE_VERSION(DRIVER_VERSION); | 658 | MODULE_VERSION(DRIVER_VERSION); |
659 | MODULE_AUTHOR("Dell Inc."); | 659 | MODULE_AUTHOR("Dell Inc."); |
660 | MODULE_LICENSE("GPL"); | 660 | MODULE_LICENSE("GPL"); |
661 | 661 | /* Any System or BIOS claiming to be by Dell */ | |
662 | MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*"); | ||
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 313c99cbdc62..e880d6c8d896 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/autoconf.h> | ||
15 | 14 | ||
16 | struct dmi_device_attribute{ | 15 | struct dmi_device_attribute{ |
17 | struct device_attribute dev_attr; | 16 | struct device_attribute dev_attr; |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 74fac0f5c348..bbd28342e771 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -27,15 +27,16 @@ config DEBUG_GPIO | |||
27 | 27 | ||
28 | comment "I2C GPIO expanders:" | 28 | comment "I2C GPIO expanders:" |
29 | 29 | ||
30 | config GPIO_PCA9539 | 30 | config GPIO_PCA953X |
31 | tristate "PCA9539 16-bit I/O port" | 31 | tristate "PCA953x I/O ports" |
32 | depends on I2C | 32 | depends on I2C |
33 | help | 33 | help |
34 | Say yes here to support the PCA9539 16-bit I/O port. These | 34 | Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit), |
35 | parts are made by NXP and TI. | 35 | PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539 |
36 | (16-bit) I/O ports. These parts are made by NXP and TI. | ||
36 | 37 | ||
37 | This driver can also be built as a module. If so, the module | 38 | This driver can also be built as a module. If so, the module |
38 | will be called pca9539. | 39 | will be called pca953x. |
39 | 40 | ||
40 | config GPIO_PCF857X | 41 | config GPIO_PCF857X |
41 | tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders" | 42 | tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders" |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 470ecd6aa778..fdde9923cf33 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -5,5 +5,5 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG | |||
5 | obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o | 5 | obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o |
6 | 6 | ||
7 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | 7 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o |
8 | obj-$(CONFIG_GPIO_PCA9539) += pca9539.o | 8 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
9 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 9 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca9539.c deleted file mode 100644 index 3e85c92a7d59..000000000000 --- a/drivers/gpio/pca9539.c +++ /dev/null | |||
@@ -1,271 +0,0 @@ | |||
1 | /* | ||
2 | * pca9539.c - 16-bit I/O port with interrupt and reset | ||
3 | * | ||
4 | * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> | ||
5 | * Copyright (C) 2007 Marvell International Ltd. | ||
6 | * | ||
7 | * Derived from drivers/i2c/chips/pca9539.c | ||
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 as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/i2c/pca9539.h> | ||
18 | |||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | |||
22 | #define NR_PCA9539_GPIOS 16 | ||
23 | |||
24 | #define PCA9539_INPUT 0 | ||
25 | #define PCA9539_OUTPUT 2 | ||
26 | #define PCA9539_INVERT 4 | ||
27 | #define PCA9539_DIRECTION 6 | ||
28 | |||
29 | struct pca9539_chip { | ||
30 | unsigned gpio_start; | ||
31 | uint16_t reg_output; | ||
32 | uint16_t reg_direction; | ||
33 | |||
34 | struct i2c_client *client; | ||
35 | struct gpio_chip gpio_chip; | ||
36 | }; | ||
37 | |||
38 | /* NOTE: we can't currently rely on fault codes to come from SMBus | ||
39 | * calls, so we map all errors to EIO here and return zero otherwise. | ||
40 | */ | ||
41 | static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val) | ||
42 | { | ||
43 | if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) | ||
44 | return -EIO; | ||
45 | else | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val) | ||
50 | { | ||
51 | int ret; | ||
52 | |||
53 | ret = i2c_smbus_read_word_data(chip->client, reg); | ||
54 | if (ret < 0) { | ||
55 | dev_err(&chip->client->dev, "failed reading register\n"); | ||
56 | return -EIO; | ||
57 | } | ||
58 | |||
59 | *val = (uint16_t)ret; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off) | ||
64 | { | ||
65 | struct pca9539_chip *chip; | ||
66 | uint16_t reg_val; | ||
67 | int ret; | ||
68 | |||
69 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
70 | |||
71 | reg_val = chip->reg_direction | (1u << off); | ||
72 | ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | |||
76 | chip->reg_direction = reg_val; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int pca9539_gpio_direction_output(struct gpio_chip *gc, | ||
81 | unsigned off, int val) | ||
82 | { | ||
83 | struct pca9539_chip *chip; | ||
84 | uint16_t reg_val; | ||
85 | int ret; | ||
86 | |||
87 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
88 | |||
89 | /* set output level */ | ||
90 | if (val) | ||
91 | reg_val = chip->reg_output | (1u << off); | ||
92 | else | ||
93 | reg_val = chip->reg_output & ~(1u << off); | ||
94 | |||
95 | ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); | ||
96 | if (ret) | ||
97 | return ret; | ||
98 | |||
99 | chip->reg_output = reg_val; | ||
100 | |||
101 | /* then direction */ | ||
102 | reg_val = chip->reg_direction & ~(1u << off); | ||
103 | ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); | ||
104 | if (ret) | ||
105 | return ret; | ||
106 | |||
107 | chip->reg_direction = reg_val; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off) | ||
112 | { | ||
113 | struct pca9539_chip *chip; | ||
114 | uint16_t reg_val; | ||
115 | int ret; | ||
116 | |||
117 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
118 | |||
119 | ret = pca9539_read_reg(chip, PCA9539_INPUT, ®_val); | ||
120 | if (ret < 0) { | ||
121 | /* NOTE: diagnostic already emitted; that's all we should | ||
122 | * do unless gpio_*_value_cansleep() calls become different | ||
123 | * from their nonsleeping siblings (and report faults). | ||
124 | */ | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | return (reg_val & (1u << off)) ? 1 : 0; | ||
129 | } | ||
130 | |||
131 | static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) | ||
132 | { | ||
133 | struct pca9539_chip *chip; | ||
134 | uint16_t reg_val; | ||
135 | int ret; | ||
136 | |||
137 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
138 | |||
139 | if (val) | ||
140 | reg_val = chip->reg_output | (1u << off); | ||
141 | else | ||
142 | reg_val = chip->reg_output & ~(1u << off); | ||
143 | |||
144 | ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); | ||
145 | if (ret) | ||
146 | return; | ||
147 | |||
148 | chip->reg_output = reg_val; | ||
149 | } | ||
150 | |||
151 | static int pca9539_init_gpio(struct pca9539_chip *chip) | ||
152 | { | ||
153 | struct gpio_chip *gc; | ||
154 | |||
155 | gc = &chip->gpio_chip; | ||
156 | |||
157 | gc->direction_input = pca9539_gpio_direction_input; | ||
158 | gc->direction_output = pca9539_gpio_direction_output; | ||
159 | gc->get = pca9539_gpio_get_value; | ||
160 | gc->set = pca9539_gpio_set_value; | ||
161 | |||
162 | gc->base = chip->gpio_start; | ||
163 | gc->ngpio = NR_PCA9539_GPIOS; | ||
164 | gc->label = "pca9539"; | ||
165 | |||
166 | return gpiochip_add(gc); | ||
167 | } | ||
168 | |||
169 | static int __devinit pca9539_probe(struct i2c_client *client) | ||
170 | { | ||
171 | struct pca9539_platform_data *pdata; | ||
172 | struct pca9539_chip *chip; | ||
173 | int ret; | ||
174 | |||
175 | pdata = client->dev.platform_data; | ||
176 | if (pdata == NULL) | ||
177 | return -ENODEV; | ||
178 | |||
179 | chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); | ||
180 | if (chip == NULL) | ||
181 | return -ENOMEM; | ||
182 | |||
183 | chip->client = client; | ||
184 | |||
185 | chip->gpio_start = pdata->gpio_base; | ||
186 | |||
187 | /* initialize cached registers from their original values. | ||
188 | * we can't share this chip with another i2c master. | ||
189 | */ | ||
190 | ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output); | ||
191 | if (ret) | ||
192 | goto out_failed; | ||
193 | |||
194 | ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction); | ||
195 | if (ret) | ||
196 | goto out_failed; | ||
197 | |||
198 | /* set platform specific polarity inversion */ | ||
199 | ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert); | ||
200 | if (ret) | ||
201 | goto out_failed; | ||
202 | |||
203 | ret = pca9539_init_gpio(chip); | ||
204 | if (ret) | ||
205 | goto out_failed; | ||
206 | |||
207 | if (pdata->setup) { | ||
208 | ret = pdata->setup(client, chip->gpio_chip.base, | ||
209 | chip->gpio_chip.ngpio, pdata->context); | ||
210 | if (ret < 0) | ||
211 | dev_warn(&client->dev, "setup failed, %d\n", ret); | ||
212 | } | ||
213 | |||
214 | i2c_set_clientdata(client, chip); | ||
215 | return 0; | ||
216 | |||
217 | out_failed: | ||
218 | kfree(chip); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static int pca9539_remove(struct i2c_client *client) | ||
223 | { | ||
224 | struct pca9539_platform_data *pdata = client->dev.platform_data; | ||
225 | struct pca9539_chip *chip = i2c_get_clientdata(client); | ||
226 | int ret = 0; | ||
227 | |||
228 | if (pdata->teardown) { | ||
229 | ret = pdata->teardown(client, chip->gpio_chip.base, | ||
230 | chip->gpio_chip.ngpio, pdata->context); | ||
231 | if (ret < 0) { | ||
232 | dev_err(&client->dev, "%s failed, %d\n", | ||
233 | "teardown", ret); | ||
234 | return ret; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | ret = gpiochip_remove(&chip->gpio_chip); | ||
239 | if (ret) { | ||
240 | dev_err(&client->dev, "%s failed, %d\n", | ||
241 | "gpiochip_remove()", ret); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | kfree(chip); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static struct i2c_driver pca9539_driver = { | ||
250 | .driver = { | ||
251 | .name = "pca9539", | ||
252 | }, | ||
253 | .probe = pca9539_probe, | ||
254 | .remove = pca9539_remove, | ||
255 | }; | ||
256 | |||
257 | static int __init pca9539_init(void) | ||
258 | { | ||
259 | return i2c_add_driver(&pca9539_driver); | ||
260 | } | ||
261 | module_init(pca9539_init); | ||
262 | |||
263 | static void __exit pca9539_exit(void) | ||
264 | { | ||
265 | i2c_del_driver(&pca9539_driver); | ||
266 | } | ||
267 | module_exit(pca9539_exit); | ||
268 | |||
269 | MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); | ||
270 | MODULE_DESCRIPTION("GPIO expander driver for PCA9539"); | ||
271 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c new file mode 100644 index 000000000000..92583cd4bffd --- /dev/null +++ b/drivers/gpio/pca953x.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * pca953x.c - 4/8/16 bit I/O ports | ||
3 | * | ||
4 | * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> | ||
5 | * Copyright (C) 2007 Marvell International Ltd. | ||
6 | * | ||
7 | * Derived from drivers/i2c/chips/pca9539.c | ||
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 as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/i2c/pca953x.h> | ||
18 | |||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | #define PCA953X_INPUT 0 | ||
22 | #define PCA953X_OUTPUT 1 | ||
23 | #define PCA953X_INVERT 2 | ||
24 | #define PCA953X_DIRECTION 3 | ||
25 | |||
26 | /* This is temporary - in 2.6.26 i2c_driver_data should replace it. */ | ||
27 | struct pca953x_desc { | ||
28 | char name[I2C_NAME_SIZE]; | ||
29 | unsigned long driver_data; | ||
30 | }; | ||
31 | |||
32 | static const struct pca953x_desc pca953x_descs[] = { | ||
33 | { "pca9534", 8, }, | ||
34 | { "pca9535", 16, }, | ||
35 | { "pca9536", 4, }, | ||
36 | { "pca9537", 4, }, | ||
37 | { "pca9538", 8, }, | ||
38 | { "pca9539", 16, }, | ||
39 | /* REVISIT several pca955x parts should work here too */ | ||
40 | }; | ||
41 | |||
42 | struct pca953x_chip { | ||
43 | unsigned gpio_start; | ||
44 | uint16_t reg_output; | ||
45 | uint16_t reg_direction; | ||
46 | |||
47 | struct i2c_client *client; | ||
48 | struct gpio_chip gpio_chip; | ||
49 | }; | ||
50 | |||
51 | /* NOTE: we can't currently rely on fault codes to come from SMBus | ||
52 | * calls, so we map all errors to EIO here and return zero otherwise. | ||
53 | */ | ||
54 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) | ||
55 | { | ||
56 | int ret; | ||
57 | |||
58 | if (chip->gpio_chip.ngpio <= 8) | ||
59 | ret = i2c_smbus_write_byte_data(chip->client, reg, val); | ||
60 | else | ||
61 | ret = i2c_smbus_write_word_data(chip->client, reg << 1, val); | ||
62 | |||
63 | if (ret < 0) { | ||
64 | dev_err(&chip->client->dev, "failed writing register\n"); | ||
65 | return -EIO; | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | if (chip->gpio_chip.ngpio <= 8) | ||
76 | ret = i2c_smbus_read_byte_data(chip->client, reg); | ||
77 | else | ||
78 | ret = i2c_smbus_read_word_data(chip->client, reg << 1); | ||
79 | |||
80 | if (ret < 0) { | ||
81 | dev_err(&chip->client->dev, "failed reading register\n"); | ||
82 | return -EIO; | ||
83 | } | ||
84 | |||
85 | *val = (uint16_t)ret; | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) | ||
90 | { | ||
91 | struct pca953x_chip *chip; | ||
92 | uint16_t reg_val; | ||
93 | int ret; | ||
94 | |||
95 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
96 | |||
97 | reg_val = chip->reg_direction | (1u << off); | ||
98 | ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); | ||
99 | if (ret) | ||
100 | return ret; | ||
101 | |||
102 | chip->reg_direction = reg_val; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int pca953x_gpio_direction_output(struct gpio_chip *gc, | ||
107 | unsigned off, int val) | ||
108 | { | ||
109 | struct pca953x_chip *chip; | ||
110 | uint16_t reg_val; | ||
111 | int ret; | ||
112 | |||
113 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
114 | |||
115 | /* set output level */ | ||
116 | if (val) | ||
117 | reg_val = chip->reg_output | (1u << off); | ||
118 | else | ||
119 | reg_val = chip->reg_output & ~(1u << off); | ||
120 | |||
121 | ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | chip->reg_output = reg_val; | ||
126 | |||
127 | /* then direction */ | ||
128 | reg_val = chip->reg_direction & ~(1u << off); | ||
129 | ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); | ||
130 | if (ret) | ||
131 | return ret; | ||
132 | |||
133 | chip->reg_direction = reg_val; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) | ||
138 | { | ||
139 | struct pca953x_chip *chip; | ||
140 | uint16_t reg_val; | ||
141 | int ret; | ||
142 | |||
143 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
144 | |||
145 | ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val); | ||
146 | if (ret < 0) { | ||
147 | /* NOTE: diagnostic already emitted; that's all we should | ||
148 | * do unless gpio_*_value_cansleep() calls become different | ||
149 | * from their nonsleeping siblings (and report faults). | ||
150 | */ | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | return (reg_val & (1u << off)) ? 1 : 0; | ||
155 | } | ||
156 | |||
157 | static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) | ||
158 | { | ||
159 | struct pca953x_chip *chip; | ||
160 | uint16_t reg_val; | ||
161 | int ret; | ||
162 | |||
163 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
164 | |||
165 | if (val) | ||
166 | reg_val = chip->reg_output | (1u << off); | ||
167 | else | ||
168 | reg_val = chip->reg_output & ~(1u << off); | ||
169 | |||
170 | ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); | ||
171 | if (ret) | ||
172 | return; | ||
173 | |||
174 | chip->reg_output = reg_val; | ||
175 | } | ||
176 | |||
177 | static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | ||
178 | { | ||
179 | struct gpio_chip *gc; | ||
180 | |||
181 | gc = &chip->gpio_chip; | ||
182 | |||
183 | gc->direction_input = pca953x_gpio_direction_input; | ||
184 | gc->direction_output = pca953x_gpio_direction_output; | ||
185 | gc->get = pca953x_gpio_get_value; | ||
186 | gc->set = pca953x_gpio_set_value; | ||
187 | |||
188 | gc->base = chip->gpio_start; | ||
189 | gc->ngpio = gpios; | ||
190 | gc->label = chip->client->name; | ||
191 | } | ||
192 | |||
193 | static int __devinit pca953x_probe(struct i2c_client *client) | ||
194 | { | ||
195 | struct pca953x_platform_data *pdata; | ||
196 | struct pca953x_chip *chip; | ||
197 | int ret, i; | ||
198 | const struct pca953x_desc *id = NULL; | ||
199 | |||
200 | pdata = client->dev.platform_data; | ||
201 | if (pdata == NULL) | ||
202 | return -ENODEV; | ||
203 | |||
204 | /* this loop vanishes when we get i2c_device_id */ | ||
205 | for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++) | ||
206 | if (!strcmp(pca953x_descs[i].name, client->name)) { | ||
207 | id = pca953x_descs + i; | ||
208 | break; | ||
209 | } | ||
210 | if (!id) | ||
211 | return -ENODEV; | ||
212 | |||
213 | chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); | ||
214 | if (chip == NULL) | ||
215 | return -ENOMEM; | ||
216 | |||
217 | chip->client = client; | ||
218 | |||
219 | chip->gpio_start = pdata->gpio_base; | ||
220 | |||
221 | /* initialize cached registers from their original values. | ||
222 | * we can't share this chip with another i2c master. | ||
223 | */ | ||
224 | pca953x_setup_gpio(chip, id->driver_data); | ||
225 | |||
226 | ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); | ||
227 | if (ret) | ||
228 | goto out_failed; | ||
229 | |||
230 | ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); | ||
231 | if (ret) | ||
232 | goto out_failed; | ||
233 | |||
234 | /* set platform specific polarity inversion */ | ||
235 | ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert); | ||
236 | if (ret) | ||
237 | goto out_failed; | ||
238 | |||
239 | |||
240 | ret = gpiochip_add(&chip->gpio_chip); | ||
241 | if (ret) | ||
242 | goto out_failed; | ||
243 | |||
244 | if (pdata->setup) { | ||
245 | ret = pdata->setup(client, chip->gpio_chip.base, | ||
246 | chip->gpio_chip.ngpio, pdata->context); | ||
247 | if (ret < 0) | ||
248 | dev_warn(&client->dev, "setup failed, %d\n", ret); | ||
249 | } | ||
250 | |||
251 | i2c_set_clientdata(client, chip); | ||
252 | return 0; | ||
253 | |||
254 | out_failed: | ||
255 | kfree(chip); | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | static int pca953x_remove(struct i2c_client *client) | ||
260 | { | ||
261 | struct pca953x_platform_data *pdata = client->dev.platform_data; | ||
262 | struct pca953x_chip *chip = i2c_get_clientdata(client); | ||
263 | int ret = 0; | ||
264 | |||
265 | if (pdata->teardown) { | ||
266 | ret = pdata->teardown(client, chip->gpio_chip.base, | ||
267 | chip->gpio_chip.ngpio, pdata->context); | ||
268 | if (ret < 0) { | ||
269 | dev_err(&client->dev, "%s failed, %d\n", | ||
270 | "teardown", ret); | ||
271 | return ret; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | ret = gpiochip_remove(&chip->gpio_chip); | ||
276 | if (ret) { | ||
277 | dev_err(&client->dev, "%s failed, %d\n", | ||
278 | "gpiochip_remove()", ret); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | kfree(chip); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static struct i2c_driver pca953x_driver = { | ||
287 | .driver = { | ||
288 | .name = "pca953x", | ||
289 | }, | ||
290 | .probe = pca953x_probe, | ||
291 | .remove = pca953x_remove, | ||
292 | }; | ||
293 | |||
294 | static int __init pca953x_init(void) | ||
295 | { | ||
296 | return i2c_add_driver(&pca953x_driver); | ||
297 | } | ||
298 | module_init(pca953x_init); | ||
299 | |||
300 | static void __exit pca953x_exit(void) | ||
301 | { | ||
302 | i2c_del_driver(&pca953x_driver); | ||
303 | } | ||
304 | module_exit(pca953x_exit); | ||
305 | |||
306 | MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); | ||
307 | MODULE_DESCRIPTION("GPIO expander driver for PCA953x"); | ||
308 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index fd0ef8268950..6daea896c5db 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -1049,7 +1049,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1049 | */ | 1049 | */ |
1050 | if (!match || match->irq != hwif->irq) { | 1050 | if (!match || match->irq != hwif->irq) { |
1051 | int sa = 0; | 1051 | int sa = 0; |
1052 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 1052 | #if defined(__mc68000__) |
1053 | sa = IRQF_SHARED; | 1053 | sa = IRQF_SHARED; |
1054 | #endif /* __mc68000__ || CONFIG_APUS */ | 1054 | #endif /* __mc68000__ || CONFIG_APUS */ |
1055 | 1055 | ||
@@ -1072,7 +1072,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1072 | hwif->rqsize = 65536; | 1072 | hwif->rqsize = 65536; |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | #if !defined(__mc68000__) && !defined(CONFIG_APUS) | 1075 | #if !defined(__mc68000__) |
1076 | printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, | 1076 | printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, |
1077 | hwif->io_ports[IDE_DATA_OFFSET], | 1077 | hwif->io_ports[IDE_DATA_OFFSET], |
1078 | hwif->io_ports[IDE_DATA_OFFSET]+7, | 1078 | hwif->io_ports[IDE_DATA_OFFSET]+7, |
@@ -1080,7 +1080,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1080 | #else | 1080 | #else |
1081 | printk("%s at 0x%08lx on irq %d", hwif->name, | 1081 | printk("%s at 0x%08lx on irq %d", hwif->name, |
1082 | hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); | 1082 | hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); |
1083 | #endif /* __mc68000__ && CONFIG_APUS */ | 1083 | #endif /* __mc68000__ */ |
1084 | if (match) | 1084 | if (match) |
1085 | printk(" (%sed with %s)", | 1085 | printk(" (%sed with %s)", |
1086 | hwif->sharing_irq ? "shar" : "serializ", match->name); | 1086 | hwif->sharing_irq ? "shar" : "serializ", match->name); |
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 2ae6c6016a86..28ae15ed12c5 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -109,7 +109,7 @@ struct h3600_dev { | |||
109 | static irqreturn_t action_button_handler(int irq, void *dev_id) | 109 | static irqreturn_t action_button_handler(int irq, void *dev_id) |
110 | { | 110 | { |
111 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; | 111 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; |
112 | struct input_dev *dev = (struct input_dev *) dev_id; | 112 | struct input_dev *dev = dev_id; |
113 | 113 | ||
114 | input_report_key(dev, KEY_ENTER, down); | 114 | input_report_key(dev, KEY_ENTER, down); |
115 | input_sync(dev); | 115 | input_sync(dev); |
@@ -120,7 +120,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id) | |||
120 | static irqreturn_t npower_button_handler(int irq, void *dev_id) | 120 | static irqreturn_t npower_button_handler(int irq, void *dev_id) |
121 | { | 121 | { |
122 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; | 122 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; |
123 | struct input_dev *dev = (struct input_dev *) dev_id; | 123 | struct input_dev *dev = dev_id; |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * This interrupt is only called when we release the key. So we have | 126 | * This interrupt is only called when we release the key. So we have |
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index ee2b0b9f8f46..8325022e2bed 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c | |||
@@ -310,7 +310,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
310 | } | 310 | } |
311 | break; | 311 | break; |
312 | case ISDN_CMD_DIAL: | 312 | case ISDN_CMD_DIAL: |
313 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 313 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
314 | return -ENODEV; | 314 | return -ENODEV; |
315 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 315 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
316 | break; | 316 | break; |
@@ -339,7 +339,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
339 | } | 339 | } |
340 | return ret; | 340 | return ret; |
341 | case ISDN_CMD_ACCEPTD: | 341 | case ISDN_CMD_ACCEPTD: |
342 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 342 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
343 | return -ENODEV; | 343 | return -ENODEV; |
344 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 344 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
345 | break; | 345 | break; |
@@ -347,11 +347,11 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
347 | actcapi_select_b2_protocol_req(card, chan); | 347 | actcapi_select_b2_protocol_req(card, chan); |
348 | return 0; | 348 | return 0; |
349 | case ISDN_CMD_ACCEPTB: | 349 | case ISDN_CMD_ACCEPTB: |
350 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 350 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
351 | return -ENODEV; | 351 | return -ENODEV; |
352 | return 0; | 352 | return 0; |
353 | case ISDN_CMD_HANGUP: | 353 | case ISDN_CMD_HANGUP: |
354 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 354 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
355 | return -ENODEV; | 355 | return -ENODEV; |
356 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 356 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
357 | break; | 357 | break; |
@@ -366,7 +366,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
366 | } | 366 | } |
367 | return 0; | 367 | return 0; |
368 | case ISDN_CMD_SETEAZ: | 368 | case ISDN_CMD_SETEAZ: |
369 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 369 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
370 | return -ENODEV; | 370 | return -ENODEV; |
371 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 371 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
372 | break; | 372 | break; |
@@ -386,7 +386,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
386 | actcapi_listen_req(card); | 386 | actcapi_listen_req(card); |
387 | return 0; | 387 | return 0; |
388 | case ISDN_CMD_CLREAZ: | 388 | case ISDN_CMD_CLREAZ: |
389 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 389 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
390 | return -ENODEV; | 390 | return -ENODEV; |
391 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 391 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
392 | break; | 392 | break; |
@@ -394,14 +394,14 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
394 | actcapi_listen_req(card); | 394 | actcapi_listen_req(card); |
395 | return 0; | 395 | return 0; |
396 | case ISDN_CMD_SETL2: | 396 | case ISDN_CMD_SETL2: |
397 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 397 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
398 | return -ENODEV; | 398 | return -ENODEV; |
399 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 399 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
400 | break; | 400 | break; |
401 | chan->l2prot = (c->arg >> 8); | 401 | chan->l2prot = (c->arg >> 8); |
402 | return 0; | 402 | return 0; |
403 | case ISDN_CMD_SETL3: | 403 | case ISDN_CMD_SETL3: |
404 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 404 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
405 | return -ENODEV; | 405 | return -ENODEV; |
406 | if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) { | 406 | if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) { |
407 | printk(KERN_WARNING "L3 protocol unknown\n"); | 407 | printk(KERN_WARNING "L3 protocol unknown\n"); |
@@ -524,7 +524,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) | |||
524 | act2000_card *card = act2000_findcard(id); | 524 | act2000_card *card = act2000_findcard(id); |
525 | 525 | ||
526 | if (card) { | 526 | if (card) { |
527 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 527 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
528 | return -ENODEV; | 528 | return -ENODEV; |
529 | return (len); | 529 | return (len); |
530 | } | 530 | } |
@@ -539,7 +539,7 @@ if_readstatus(u_char __user * buf, int len, int id, int channel) | |||
539 | act2000_card *card = act2000_findcard(id); | 539 | act2000_card *card = act2000_findcard(id); |
540 | 540 | ||
541 | if (card) { | 541 | if (card) { |
542 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 542 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
543 | return -ENODEV; | 543 | return -ENODEV; |
544 | return (act2000_readstatus(buf, len, card)); | 544 | return (act2000_readstatus(buf, len, card)); |
545 | } | 545 | } |
@@ -554,7 +554,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) | |||
554 | act2000_card *card = act2000_findcard(id); | 554 | act2000_card *card = act2000_findcard(id); |
555 | 555 | ||
556 | if (card) { | 556 | if (card) { |
557 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 557 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
558 | return -ENODEV; | 558 | return -ENODEV; |
559 | return (act2000_sendbuf(card, channel, ack, skb)); | 559 | return (act2000_sendbuf(card, channel, ack, skb)); |
560 | } | 560 | } |
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 00a3be5b862b..091deb9d1c47 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c | |||
@@ -350,8 +350,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) | |||
350 | unsigned char *src, c; | 350 | unsigned char *src, c; |
351 | int procbytes; | 351 | int procbytes; |
352 | 352 | ||
353 | head = atomic_read(&inbuf->head); | 353 | head = inbuf->head; |
354 | tail = atomic_read(&inbuf->tail); | 354 | tail = inbuf->tail; |
355 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | 355 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); |
356 | 356 | ||
357 | if (head != tail) { | 357 | if (head != tail) { |
@@ -361,7 +361,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) | |||
361 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | 361 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); |
362 | 362 | ||
363 | while (numbytes) { | 363 | while (numbytes) { |
364 | if (atomic_read(&cs->mstate) == MS_LOCKED) { | 364 | if (cs->mstate == MS_LOCKED) { |
365 | procbytes = lock_loop(src, numbytes, inbuf); | 365 | procbytes = lock_loop(src, numbytes, inbuf); |
366 | src += procbytes; | 366 | src += procbytes; |
367 | numbytes -= procbytes; | 367 | numbytes -= procbytes; |
@@ -436,7 +436,7 @@ nextbyte: | |||
436 | } | 436 | } |
437 | 437 | ||
438 | gig_dbg(DEBUG_INTR, "setting head to %u", head); | 438 | gig_dbg(DEBUG_INTR, "setting head to %u", head); |
439 | atomic_set(&inbuf->head, head); | 439 | inbuf->head = head; |
440 | } | 440 | } |
441 | } | 441 | } |
442 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); | 442 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); |
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index af7648274b38..5255b5e20e13 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -73,6 +73,14 @@ static int gigaset_probe(struct usb_interface *interface, | |||
73 | /* Function will be called if the device is unplugged */ | 73 | /* Function will be called if the device is unplugged */ |
74 | static void gigaset_disconnect(struct usb_interface *interface); | 74 | static void gigaset_disconnect(struct usb_interface *interface); |
75 | 75 | ||
76 | /* functions called before/after suspend */ | ||
77 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | ||
78 | static int gigaset_resume(struct usb_interface *intf); | ||
79 | |||
80 | /* functions called before/after device reset */ | ||
81 | static int gigaset_pre_reset(struct usb_interface *intf); | ||
82 | static int gigaset_post_reset(struct usb_interface *intf); | ||
83 | |||
76 | static int atread_submit(struct cardstate *, int); | 84 | static int atread_submit(struct cardstate *, int); |
77 | static void stopurbs(struct bas_bc_state *); | 85 | static void stopurbs(struct bas_bc_state *); |
78 | static int req_submit(struct bc_state *, int, int, int); | 86 | static int req_submit(struct bc_state *, int, int, int); |
@@ -105,8 +113,9 @@ struct bas_cardstate { | |||
105 | unsigned char int_in_buf[3]; | 113 | unsigned char int_in_buf[3]; |
106 | 114 | ||
107 | spinlock_t lock; /* locks all following */ | 115 | spinlock_t lock; /* locks all following */ |
108 | atomic_t basstate; /* bitmap (BS_*) */ | 116 | int basstate; /* bitmap (BS_*) */ |
109 | int pending; /* uncompleted base request */ | 117 | int pending; /* uncompleted base request */ |
118 | wait_queue_head_t waitqueue; | ||
110 | int rcvbuf_size; /* size of AT receive buffer */ | 119 | int rcvbuf_size; /* size of AT receive buffer */ |
111 | /* 0: no receive in progress */ | 120 | /* 0: no receive in progress */ |
112 | int retry_cmd_in; /* receive req retry count */ | 121 | int retry_cmd_in; /* receive req retry count */ |
@@ -121,10 +130,10 @@ struct bas_cardstate { | |||
121 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ | 130 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ |
122 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ | 131 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ |
123 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ | 132 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ |
133 | #define BS_SUSPEND 0x100 /* USB port suspended */ | ||
124 | 134 | ||
125 | 135 | ||
126 | static struct gigaset_driver *driver = NULL; | 136 | static struct gigaset_driver *driver = NULL; |
127 | static struct cardstate *cardstate = NULL; | ||
128 | 137 | ||
129 | /* usb specific object needed to register this driver with the usb subsystem */ | 138 | /* usb specific object needed to register this driver with the usb subsystem */ |
130 | static struct usb_driver gigaset_usb_driver = { | 139 | static struct usb_driver gigaset_usb_driver = { |
@@ -132,6 +141,11 @@ static struct usb_driver gigaset_usb_driver = { | |||
132 | .probe = gigaset_probe, | 141 | .probe = gigaset_probe, |
133 | .disconnect = gigaset_disconnect, | 142 | .disconnect = gigaset_disconnect, |
134 | .id_table = gigaset_table, | 143 | .id_table = gigaset_table, |
144 | .suspend = gigaset_suspend, | ||
145 | .resume = gigaset_resume, | ||
146 | .reset_resume = gigaset_post_reset, | ||
147 | .pre_reset = gigaset_pre_reset, | ||
148 | .post_reset = gigaset_post_reset, | ||
135 | }; | 149 | }; |
136 | 150 | ||
137 | /* get message text for usb_submit_urb return code | 151 | /* get message text for usb_submit_urb return code |
@@ -248,12 +262,12 @@ static inline void dump_urb(enum debuglevel level, const char *tag, | |||
248 | if (urb) { | 262 | if (urb) { |
249 | gig_dbg(level, | 263 | gig_dbg(level, |
250 | " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " | 264 | " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " |
251 | "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,", | 265 | "hcpriv=0x%08lx, transfer_flags=0x%x,", |
252 | (unsigned long) urb->dev, | 266 | (unsigned long) urb->dev, |
253 | usb_pipetype_str(urb->pipe), | 267 | usb_pipetype_str(urb->pipe), |
254 | usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), | 268 | usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), |
255 | usb_pipein(urb->pipe) ? "in" : "out", | 269 | usb_pipein(urb->pipe) ? "in" : "out", |
256 | urb->status, (unsigned long) urb->hcpriv, | 270 | (unsigned long) urb->hcpriv, |
257 | urb->transfer_flags); | 271 | urb->transfer_flags); |
258 | gig_dbg(level, | 272 | gig_dbg(level, |
259 | " transfer_buffer=0x%08lx[%d], actual_length=%d, " | 273 | " transfer_buffer=0x%08lx[%d], actual_length=%d, " |
@@ -355,27 +369,27 @@ static void check_pending(struct bas_cardstate *ucs) | |||
355 | case 0: | 369 | case 0: |
356 | break; | 370 | break; |
357 | case HD_OPEN_ATCHANNEL: | 371 | case HD_OPEN_ATCHANNEL: |
358 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) | 372 | if (ucs->basstate & BS_ATOPEN) |
359 | ucs->pending = 0; | 373 | ucs->pending = 0; |
360 | break; | 374 | break; |
361 | case HD_OPEN_B1CHANNEL: | 375 | case HD_OPEN_B1CHANNEL: |
362 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) | 376 | if (ucs->basstate & BS_B1OPEN) |
363 | ucs->pending = 0; | 377 | ucs->pending = 0; |
364 | break; | 378 | break; |
365 | case HD_OPEN_B2CHANNEL: | 379 | case HD_OPEN_B2CHANNEL: |
366 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) | 380 | if (ucs->basstate & BS_B2OPEN) |
367 | ucs->pending = 0; | 381 | ucs->pending = 0; |
368 | break; | 382 | break; |
369 | case HD_CLOSE_ATCHANNEL: | 383 | case HD_CLOSE_ATCHANNEL: |
370 | if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) | 384 | if (!(ucs->basstate & BS_ATOPEN)) |
371 | ucs->pending = 0; | 385 | ucs->pending = 0; |
372 | break; | 386 | break; |
373 | case HD_CLOSE_B1CHANNEL: | 387 | case HD_CLOSE_B1CHANNEL: |
374 | if (!(atomic_read(&ucs->basstate) & BS_B1OPEN)) | 388 | if (!(ucs->basstate & BS_B1OPEN)) |
375 | ucs->pending = 0; | 389 | ucs->pending = 0; |
376 | break; | 390 | break; |
377 | case HD_CLOSE_B2CHANNEL: | 391 | case HD_CLOSE_B2CHANNEL: |
378 | if (!(atomic_read(&ucs->basstate) & BS_B2OPEN)) | 392 | if (!(ucs->basstate & BS_B2OPEN)) |
379 | ucs->pending = 0; | 393 | ucs->pending = 0; |
380 | break; | 394 | break; |
381 | case HD_DEVICE_INIT_ACK: /* no reply expected */ | 395 | case HD_DEVICE_INIT_ACK: /* no reply expected */ |
@@ -441,8 +455,8 @@ inline static int update_basstate(struct bas_cardstate *ucs, | |||
441 | int state; | 455 | int state; |
442 | 456 | ||
443 | spin_lock_irqsave(&ucs->lock, flags); | 457 | spin_lock_irqsave(&ucs->lock, flags); |
444 | state = atomic_read(&ucs->basstate); | 458 | state = ucs->basstate; |
445 | atomic_set(&ucs->basstate, (state & ~clear) | set); | 459 | ucs->basstate = (state & ~clear) | set; |
446 | spin_unlock_irqrestore(&ucs->lock, flags); | 460 | spin_unlock_irqrestore(&ucs->lock, flags); |
447 | return state; | 461 | return state; |
448 | } | 462 | } |
@@ -459,11 +473,13 @@ static void read_ctrl_callback(struct urb *urb) | |||
459 | struct inbuf_t *inbuf = urb->context; | 473 | struct inbuf_t *inbuf = urb->context; |
460 | struct cardstate *cs = inbuf->cs; | 474 | struct cardstate *cs = inbuf->cs; |
461 | struct bas_cardstate *ucs = cs->hw.bas; | 475 | struct bas_cardstate *ucs = cs->hw.bas; |
476 | int status = urb->status; | ||
462 | int have_data = 0; | 477 | int have_data = 0; |
463 | unsigned numbytes; | 478 | unsigned numbytes; |
464 | int rc; | 479 | int rc; |
465 | 480 | ||
466 | update_basstate(ucs, 0, BS_ATRDPEND); | 481 | update_basstate(ucs, 0, BS_ATRDPEND); |
482 | wake_up(&ucs->waitqueue); | ||
467 | 483 | ||
468 | if (!ucs->rcvbuf_size) { | 484 | if (!ucs->rcvbuf_size) { |
469 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | 485 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); |
@@ -472,7 +488,7 @@ static void read_ctrl_callback(struct urb *urb) | |||
472 | 488 | ||
473 | del_timer(&ucs->timer_cmd_in); | 489 | del_timer(&ucs->timer_cmd_in); |
474 | 490 | ||
475 | switch (urb->status) { | 491 | switch (status) { |
476 | case 0: /* normal completion */ | 492 | case 0: /* normal completion */ |
477 | numbytes = urb->actual_length; | 493 | numbytes = urb->actual_length; |
478 | if (unlikely(numbytes != ucs->rcvbuf_size)) { | 494 | if (unlikely(numbytes != ucs->rcvbuf_size)) { |
@@ -506,12 +522,12 @@ static void read_ctrl_callback(struct urb *urb) | |||
506 | case -ESHUTDOWN: /* device shut down */ | 522 | case -ESHUTDOWN: /* device shut down */ |
507 | /* no action necessary */ | 523 | /* no action necessary */ |
508 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 524 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
509 | __func__, get_usb_statmsg(urb->status)); | 525 | __func__, get_usb_statmsg(status)); |
510 | break; | 526 | break; |
511 | 527 | ||
512 | default: /* severe trouble */ | 528 | default: /* severe trouble */ |
513 | dev_warn(cs->dev, "control read: %s\n", | 529 | dev_warn(cs->dev, "control read: %s\n", |
514 | get_usb_statmsg(urb->status)); | 530 | get_usb_statmsg(status)); |
515 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | 531 | if (ucs->retry_cmd_in++ < BAS_RETRY) { |
516 | dev_notice(cs->dev, "control read: retry %d\n", | 532 | dev_notice(cs->dev, "control read: retry %d\n", |
517 | ucs->retry_cmd_in); | 533 | ucs->retry_cmd_in); |
@@ -550,17 +566,28 @@ static void read_ctrl_callback(struct urb *urb) | |||
550 | static int atread_submit(struct cardstate *cs, int timeout) | 566 | static int atread_submit(struct cardstate *cs, int timeout) |
551 | { | 567 | { |
552 | struct bas_cardstate *ucs = cs->hw.bas; | 568 | struct bas_cardstate *ucs = cs->hw.bas; |
569 | int basstate; | ||
553 | int ret; | 570 | int ret; |
554 | 571 | ||
555 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", | 572 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", |
556 | ucs->rcvbuf_size); | 573 | ucs->rcvbuf_size); |
557 | 574 | ||
558 | if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) { | 575 | basstate = update_basstate(ucs, BS_ATRDPEND, 0); |
576 | if (basstate & BS_ATRDPEND) { | ||
559 | dev_err(cs->dev, | 577 | dev_err(cs->dev, |
560 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); | 578 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); |
561 | return -EBUSY; | 579 | return -EBUSY; |
562 | } | 580 | } |
563 | 581 | ||
582 | if (basstate & BS_SUSPEND) { | ||
583 | dev_notice(cs->dev, | ||
584 | "HD_READ_ATMESSAGE not submitted, " | ||
585 | "suspend in progress\n"); | ||
586 | update_basstate(ucs, 0, BS_ATRDPEND); | ||
587 | /* treat like disconnect */ | ||
588 | return -ENODEV; | ||
589 | } | ||
590 | |||
564 | ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; | 591 | ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; |
565 | ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; | 592 | ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; |
566 | ucs->dr_cmd_in.wValue = 0; | 593 | ucs->dr_cmd_in.wValue = 0; |
@@ -601,12 +628,13 @@ static void read_int_callback(struct urb *urb) | |||
601 | struct cardstate *cs = urb->context; | 628 | struct cardstate *cs = urb->context; |
602 | struct bas_cardstate *ucs = cs->hw.bas; | 629 | struct bas_cardstate *ucs = cs->hw.bas; |
603 | struct bc_state *bcs; | 630 | struct bc_state *bcs; |
631 | int status = urb->status; | ||
604 | unsigned long flags; | 632 | unsigned long flags; |
605 | int rc; | 633 | int rc; |
606 | unsigned l; | 634 | unsigned l; |
607 | int channel; | 635 | int channel; |
608 | 636 | ||
609 | switch (urb->status) { | 637 | switch (status) { |
610 | case 0: /* success */ | 638 | case 0: /* success */ |
611 | break; | 639 | break; |
612 | case -ENOENT: /* cancelled */ | 640 | case -ENOENT: /* cancelled */ |
@@ -614,7 +642,7 @@ static void read_int_callback(struct urb *urb) | |||
614 | case -EINPROGRESS: /* pending */ | 642 | case -EINPROGRESS: /* pending */ |
615 | /* ignore silently */ | 643 | /* ignore silently */ |
616 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 644 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
617 | __func__, get_usb_statmsg(urb->status)); | 645 | __func__, get_usb_statmsg(status)); |
618 | return; | 646 | return; |
619 | case -ENODEV: /* device removed */ | 647 | case -ENODEV: /* device removed */ |
620 | case -ESHUTDOWN: /* device shut down */ | 648 | case -ESHUTDOWN: /* device shut down */ |
@@ -623,7 +651,7 @@ static void read_int_callback(struct urb *urb) | |||
623 | return; | 651 | return; |
624 | default: /* severe trouble */ | 652 | default: /* severe trouble */ |
625 | dev_warn(cs->dev, "interrupt read: %s\n", | 653 | dev_warn(cs->dev, "interrupt read: %s\n", |
626 | get_usb_statmsg(urb->status)); | 654 | get_usb_statmsg(status)); |
627 | //FIXME corrective action? resubmission always ok? | 655 | //FIXME corrective action? resubmission always ok? |
628 | goto resubmit; | 656 | goto resubmit; |
629 | } | 657 | } |
@@ -745,6 +773,7 @@ static void read_int_callback(struct urb *urb) | |||
745 | } | 773 | } |
746 | 774 | ||
747 | check_pending(ucs); | 775 | check_pending(ucs); |
776 | wake_up(&ucs->waitqueue); | ||
748 | 777 | ||
749 | resubmit: | 778 | resubmit: |
750 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 779 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -766,17 +795,18 @@ static void read_iso_callback(struct urb *urb) | |||
766 | { | 795 | { |
767 | struct bc_state *bcs; | 796 | struct bc_state *bcs; |
768 | struct bas_bc_state *ubc; | 797 | struct bas_bc_state *ubc; |
798 | int status = urb->status; | ||
769 | unsigned long flags; | 799 | unsigned long flags; |
770 | int i, rc; | 800 | int i, rc; |
771 | 801 | ||
772 | /* status codes not worth bothering the tasklet with */ | 802 | /* status codes not worth bothering the tasklet with */ |
773 | if (unlikely(urb->status == -ENOENT || | 803 | if (unlikely(status == -ENOENT || |
774 | urb->status == -ECONNRESET || | 804 | status == -ECONNRESET || |
775 | urb->status == -EINPROGRESS || | 805 | status == -EINPROGRESS || |
776 | urb->status == -ENODEV || | 806 | status == -ENODEV || |
777 | urb->status == -ESHUTDOWN)) { | 807 | status == -ESHUTDOWN)) { |
778 | gig_dbg(DEBUG_ISO, "%s: %s", | 808 | gig_dbg(DEBUG_ISO, "%s: %s", |
779 | __func__, get_usb_statmsg(urb->status)); | 809 | __func__, get_usb_statmsg(status)); |
780 | return; | 810 | return; |
781 | } | 811 | } |
782 | 812 | ||
@@ -787,10 +817,11 @@ static void read_iso_callback(struct urb *urb) | |||
787 | if (likely(ubc->isoindone == NULL)) { | 817 | if (likely(ubc->isoindone == NULL)) { |
788 | /* pass URB to tasklet */ | 818 | /* pass URB to tasklet */ |
789 | ubc->isoindone = urb; | 819 | ubc->isoindone = urb; |
820 | ubc->isoinstatus = status; | ||
790 | tasklet_schedule(&ubc->rcvd_tasklet); | 821 | tasklet_schedule(&ubc->rcvd_tasklet); |
791 | } else { | 822 | } else { |
792 | /* tasklet still busy, drop data and resubmit URB */ | 823 | /* tasklet still busy, drop data and resubmit URB */ |
793 | ubc->loststatus = urb->status; | 824 | ubc->loststatus = status; |
794 | for (i = 0; i < BAS_NUMFRAMES; i++) { | 825 | for (i = 0; i < BAS_NUMFRAMES; i++) { |
795 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; | 826 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; |
796 | if (unlikely(urb->iso_frame_desc[i].status != 0 && | 827 | if (unlikely(urb->iso_frame_desc[i].status != 0 && |
@@ -800,7 +831,7 @@ static void read_iso_callback(struct urb *urb) | |||
800 | urb->iso_frame_desc[i].status = 0; | 831 | urb->iso_frame_desc[i].status = 0; |
801 | urb->iso_frame_desc[i].actual_length = 0; | 832 | urb->iso_frame_desc[i].actual_length = 0; |
802 | } | 833 | } |
803 | if (likely(atomic_read(&ubc->running))) { | 834 | if (likely(ubc->running)) { |
804 | /* urb->dev is clobbered by USB subsystem */ | 835 | /* urb->dev is clobbered by USB subsystem */ |
805 | urb->dev = bcs->cs->hw.bas->udev; | 836 | urb->dev = bcs->cs->hw.bas->udev; |
806 | urb->transfer_flags = URB_ISO_ASAP; | 837 | urb->transfer_flags = URB_ISO_ASAP; |
@@ -831,22 +862,24 @@ static void write_iso_callback(struct urb *urb) | |||
831 | { | 862 | { |
832 | struct isow_urbctx_t *ucx; | 863 | struct isow_urbctx_t *ucx; |
833 | struct bas_bc_state *ubc; | 864 | struct bas_bc_state *ubc; |
865 | int status = urb->status; | ||
834 | unsigned long flags; | 866 | unsigned long flags; |
835 | 867 | ||
836 | /* status codes not worth bothering the tasklet with */ | 868 | /* status codes not worth bothering the tasklet with */ |
837 | if (unlikely(urb->status == -ENOENT || | 869 | if (unlikely(status == -ENOENT || |
838 | urb->status == -ECONNRESET || | 870 | status == -ECONNRESET || |
839 | urb->status == -EINPROGRESS || | 871 | status == -EINPROGRESS || |
840 | urb->status == -ENODEV || | 872 | status == -ENODEV || |
841 | urb->status == -ESHUTDOWN)) { | 873 | status == -ESHUTDOWN)) { |
842 | gig_dbg(DEBUG_ISO, "%s: %s", | 874 | gig_dbg(DEBUG_ISO, "%s: %s", |
843 | __func__, get_usb_statmsg(urb->status)); | 875 | __func__, get_usb_statmsg(status)); |
844 | return; | 876 | return; |
845 | } | 877 | } |
846 | 878 | ||
847 | /* pass URB context to tasklet */ | 879 | /* pass URB context to tasklet */ |
848 | ucx = urb->context; | 880 | ucx = urb->context; |
849 | ubc = ucx->bcs->hw.bas; | 881 | ubc = ucx->bcs->hw.bas; |
882 | ucx->status = status; | ||
850 | 883 | ||
851 | spin_lock_irqsave(&ubc->isooutlock, flags); | 884 | spin_lock_irqsave(&ubc->isooutlock, flags); |
852 | ubc->isooutovfl = ubc->isooutdone; | 885 | ubc->isooutovfl = ubc->isooutdone; |
@@ -875,7 +908,7 @@ static int starturbs(struct bc_state *bcs) | |||
875 | bcs->inputstate |= INS_flag_hunt; | 908 | bcs->inputstate |= INS_flag_hunt; |
876 | 909 | ||
877 | /* submit all isochronous input URBs */ | 910 | /* submit all isochronous input URBs */ |
878 | atomic_set(&ubc->running, 1); | 911 | ubc->running = 1; |
879 | for (k = 0; k < BAS_INURBS; k++) { | 912 | for (k = 0; k < BAS_INURBS; k++) { |
880 | urb = ubc->isoinurbs[k]; | 913 | urb = ubc->isoinurbs[k]; |
881 | if (!urb) { | 914 | if (!urb) { |
@@ -932,15 +965,15 @@ static int starturbs(struct bc_state *bcs) | |||
932 | ubc->isoouturbs[k].limit = -1; | 965 | ubc->isoouturbs[k].limit = -1; |
933 | } | 966 | } |
934 | 967 | ||
935 | /* submit two URBs, keep third one */ | 968 | /* keep one URB free, submit the others */ |
936 | for (k = 0; k < 2; ++k) { | 969 | for (k = 0; k < BAS_OUTURBS-1; ++k) { |
937 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); | 970 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); |
938 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); | 971 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); |
939 | if (rc != 0) | 972 | if (rc != 0) |
940 | goto error; | 973 | goto error; |
941 | } | 974 | } |
942 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); | 975 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); |
943 | ubc->isooutfree = &ubc->isoouturbs[2]; | 976 | ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS-1]; |
944 | ubc->isooutdone = ubc->isooutovfl = NULL; | 977 | ubc->isooutdone = ubc->isooutovfl = NULL; |
945 | return 0; | 978 | return 0; |
946 | error: | 979 | error: |
@@ -958,7 +991,7 @@ static void stopurbs(struct bas_bc_state *ubc) | |||
958 | { | 991 | { |
959 | int k, rc; | 992 | int k, rc; |
960 | 993 | ||
961 | atomic_set(&ubc->running, 0); | 994 | ubc->running = 0; |
962 | 995 | ||
963 | for (k = 0; k < BAS_INURBS; ++k) { | 996 | for (k = 0; k < BAS_INURBS; ++k) { |
964 | rc = usb_unlink_urb(ubc->isoinurbs[k]); | 997 | rc = usb_unlink_urb(ubc->isoinurbs[k]); |
@@ -1034,7 +1067,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
1034 | } | 1067 | } |
1035 | break; | 1068 | break; |
1036 | } | 1069 | } |
1037 | ucx->limit = atomic_read(&ubc->isooutbuf->nextread); | 1070 | ucx->limit = ubc->isooutbuf->nextread; |
1038 | ifd->status = 0; | 1071 | ifd->status = 0; |
1039 | ifd->actual_length = 0; | 1072 | ifd->actual_length = 0; |
1040 | } | 1073 | } |
@@ -1070,6 +1103,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1070 | struct cardstate *cs = bcs->cs; | 1103 | struct cardstate *cs = bcs->cs; |
1071 | struct isow_urbctx_t *done, *next, *ovfl; | 1104 | struct isow_urbctx_t *done, *next, *ovfl; |
1072 | struct urb *urb; | 1105 | struct urb *urb; |
1106 | int status; | ||
1073 | struct usb_iso_packet_descriptor *ifd; | 1107 | struct usb_iso_packet_descriptor *ifd; |
1074 | int offset; | 1108 | int offset; |
1075 | unsigned long flags; | 1109 | unsigned long flags; |
@@ -1080,7 +1114,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1080 | 1114 | ||
1081 | /* loop while completed URBs arrive in time */ | 1115 | /* loop while completed URBs arrive in time */ |
1082 | for (;;) { | 1116 | for (;;) { |
1083 | if (unlikely(!(atomic_read(&ubc->running)))) { | 1117 | if (unlikely(!(ubc->running))) { |
1084 | gig_dbg(DEBUG_ISO, "%s: not running", __func__); | 1118 | gig_dbg(DEBUG_ISO, "%s: not running", __func__); |
1085 | return; | 1119 | return; |
1086 | } | 1120 | } |
@@ -1126,7 +1160,8 @@ static void write_iso_tasklet(unsigned long data) | |||
1126 | 1160 | ||
1127 | /* process completed URB */ | 1161 | /* process completed URB */ |
1128 | urb = done->urb; | 1162 | urb = done->urb; |
1129 | switch (urb->status) { | 1163 | status = done->status; |
1164 | switch (status) { | ||
1130 | case -EXDEV: /* partial completion */ | 1165 | case -EXDEV: /* partial completion */ |
1131 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", | 1166 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", |
1132 | __func__); | 1167 | __func__); |
@@ -1179,12 +1214,12 @@ static void write_iso_tasklet(unsigned long data) | |||
1179 | break; | 1214 | break; |
1180 | default: /* severe trouble */ | 1215 | default: /* severe trouble */ |
1181 | dev_warn(cs->dev, "isochronous write: %s\n", | 1216 | dev_warn(cs->dev, "isochronous write: %s\n", |
1182 | get_usb_statmsg(urb->status)); | 1217 | get_usb_statmsg(status)); |
1183 | } | 1218 | } |
1184 | 1219 | ||
1185 | /* mark the write buffer area covered by this URB as free */ | 1220 | /* mark the write buffer area covered by this URB as free */ |
1186 | if (done->limit >= 0) | 1221 | if (done->limit >= 0) |
1187 | atomic_set(&ubc->isooutbuf->read, done->limit); | 1222 | ubc->isooutbuf->read = done->limit; |
1188 | 1223 | ||
1189 | /* mark URB as free */ | 1224 | /* mark URB as free */ |
1190 | spin_lock_irqsave(&ubc->isooutlock, flags); | 1225 | spin_lock_irqsave(&ubc->isooutlock, flags); |
@@ -1233,6 +1268,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1233 | struct bas_bc_state *ubc = bcs->hw.bas; | 1268 | struct bas_bc_state *ubc = bcs->hw.bas; |
1234 | struct cardstate *cs = bcs->cs; | 1269 | struct cardstate *cs = bcs->cs; |
1235 | struct urb *urb; | 1270 | struct urb *urb; |
1271 | int status; | ||
1236 | char *rcvbuf; | 1272 | char *rcvbuf; |
1237 | unsigned long flags; | 1273 | unsigned long flags; |
1238 | int totleft, numbytes, offset, frame, rc; | 1274 | int totleft, numbytes, offset, frame, rc; |
@@ -1245,6 +1281,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1245 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1281 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1246 | return; | 1282 | return; |
1247 | } | 1283 | } |
1284 | status = ubc->isoinstatus; | ||
1248 | ubc->isoindone = NULL; | 1285 | ubc->isoindone = NULL; |
1249 | if (unlikely(ubc->loststatus != -EINPROGRESS)) { | 1286 | if (unlikely(ubc->loststatus != -EINPROGRESS)) { |
1250 | dev_warn(cs->dev, | 1287 | dev_warn(cs->dev, |
@@ -1256,15 +1293,15 @@ static void read_iso_tasklet(unsigned long data) | |||
1256 | } | 1293 | } |
1257 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1294 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1258 | 1295 | ||
1259 | if (unlikely(!(atomic_read(&ubc->running)))) { | 1296 | if (unlikely(!(ubc->running))) { |
1260 | gig_dbg(DEBUG_ISO, | 1297 | gig_dbg(DEBUG_ISO, |
1261 | "%s: channel not running, " | 1298 | "%s: channel not running, " |
1262 | "dropped URB with status: %s", | 1299 | "dropped URB with status: %s", |
1263 | __func__, get_usb_statmsg(urb->status)); | 1300 | __func__, get_usb_statmsg(status)); |
1264 | return; | 1301 | return; |
1265 | } | 1302 | } |
1266 | 1303 | ||
1267 | switch (urb->status) { | 1304 | switch (status) { |
1268 | case 0: /* normal completion */ | 1305 | case 0: /* normal completion */ |
1269 | break; | 1306 | break; |
1270 | case -EXDEV: /* inspect individual frames | 1307 | case -EXDEV: /* inspect individual frames |
@@ -1276,7 +1313,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1276 | case -ECONNRESET: | 1313 | case -ECONNRESET: |
1277 | case -EINPROGRESS: | 1314 | case -EINPROGRESS: |
1278 | gig_dbg(DEBUG_ISO, "%s: %s", | 1315 | gig_dbg(DEBUG_ISO, "%s: %s", |
1279 | __func__, get_usb_statmsg(urb->status)); | 1316 | __func__, get_usb_statmsg(status)); |
1280 | continue; /* -> skip */ | 1317 | continue; /* -> skip */ |
1281 | case -EPIPE: | 1318 | case -EPIPE: |
1282 | dev_err(cs->dev, "isochronous read stalled\n"); | 1319 | dev_err(cs->dev, "isochronous read stalled\n"); |
@@ -1284,7 +1321,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1284 | continue; /* -> skip */ | 1321 | continue; /* -> skip */ |
1285 | default: /* severe trouble */ | 1322 | default: /* severe trouble */ |
1286 | dev_warn(cs->dev, "isochronous read: %s\n", | 1323 | dev_warn(cs->dev, "isochronous read: %s\n", |
1287 | get_usb_statmsg(urb->status)); | 1324 | get_usb_statmsg(status)); |
1288 | goto error; | 1325 | goto error; |
1289 | } | 1326 | } |
1290 | 1327 | ||
@@ -1406,6 +1443,8 @@ static void req_timeout(unsigned long data) | |||
1406 | dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", | 1443 | dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", |
1407 | pending); | 1444 | pending); |
1408 | } | 1445 | } |
1446 | |||
1447 | wake_up(&ucs->waitqueue); | ||
1409 | } | 1448 | } |
1410 | 1449 | ||
1411 | /* write_ctrl_callback | 1450 | /* write_ctrl_callback |
@@ -1418,11 +1457,12 @@ static void req_timeout(unsigned long data) | |||
1418 | static void write_ctrl_callback(struct urb *urb) | 1457 | static void write_ctrl_callback(struct urb *urb) |
1419 | { | 1458 | { |
1420 | struct bas_cardstate *ucs = urb->context; | 1459 | struct bas_cardstate *ucs = urb->context; |
1460 | int status = urb->status; | ||
1421 | int rc; | 1461 | int rc; |
1422 | unsigned long flags; | 1462 | unsigned long flags; |
1423 | 1463 | ||
1424 | /* check status */ | 1464 | /* check status */ |
1425 | switch (urb->status) { | 1465 | switch (status) { |
1426 | case 0: /* normal completion */ | 1466 | case 0: /* normal completion */ |
1427 | spin_lock_irqsave(&ucs->lock, flags); | 1467 | spin_lock_irqsave(&ucs->lock, flags); |
1428 | switch (ucs->pending) { | 1468 | switch (ucs->pending) { |
@@ -1441,20 +1481,22 @@ static void write_ctrl_callback(struct urb *urb) | |||
1441 | case -ESHUTDOWN: /* device shut down */ | 1481 | case -ESHUTDOWN: /* device shut down */ |
1442 | /* ignore silently */ | 1482 | /* ignore silently */ |
1443 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1483 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1444 | __func__, get_usb_statmsg(urb->status)); | 1484 | __func__, get_usb_statmsg(status)); |
1445 | break; | 1485 | break; |
1446 | 1486 | ||
1447 | default: /* any failure */ | 1487 | default: /* any failure */ |
1448 | if (++ucs->retry_ctrl > BAS_RETRY) { | 1488 | /* don't retry if suspend requested */ |
1489 | if (++ucs->retry_ctrl > BAS_RETRY || | ||
1490 | (ucs->basstate & BS_SUSPEND)) { | ||
1449 | dev_err(&ucs->interface->dev, | 1491 | dev_err(&ucs->interface->dev, |
1450 | "control request 0x%02x failed: %s\n", | 1492 | "control request 0x%02x failed: %s\n", |
1451 | ucs->dr_ctrl.bRequest, | 1493 | ucs->dr_ctrl.bRequest, |
1452 | get_usb_statmsg(urb->status)); | 1494 | get_usb_statmsg(status)); |
1453 | break; /* give up */ | 1495 | break; /* give up */ |
1454 | } | 1496 | } |
1455 | dev_notice(&ucs->interface->dev, | 1497 | dev_notice(&ucs->interface->dev, |
1456 | "control request 0x%02x: %s, retry %d\n", | 1498 | "control request 0x%02x: %s, retry %d\n", |
1457 | ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status), | 1499 | ucs->dr_ctrl.bRequest, get_usb_statmsg(status), |
1458 | ucs->retry_ctrl); | 1500 | ucs->retry_ctrl); |
1459 | /* urb->dev is clobbered by USB subsystem */ | 1501 | /* urb->dev is clobbered by USB subsystem */ |
1460 | urb->dev = ucs->udev; | 1502 | urb->dev = ucs->udev; |
@@ -1474,6 +1516,7 @@ static void write_ctrl_callback(struct urb *urb) | |||
1474 | del_timer(&ucs->timer_ctrl); | 1516 | del_timer(&ucs->timer_ctrl); |
1475 | ucs->pending = 0; | 1517 | ucs->pending = 0; |
1476 | spin_unlock_irqrestore(&ucs->lock, flags); | 1518 | spin_unlock_irqrestore(&ucs->lock, flags); |
1519 | wake_up(&ucs->waitqueue); | ||
1477 | } | 1520 | } |
1478 | 1521 | ||
1479 | /* req_submit | 1522 | /* req_submit |
@@ -1548,37 +1591,46 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1548 | */ | 1591 | */ |
1549 | static int gigaset_init_bchannel(struct bc_state *bcs) | 1592 | static int gigaset_init_bchannel(struct bc_state *bcs) |
1550 | { | 1593 | { |
1594 | struct cardstate *cs = bcs->cs; | ||
1551 | int req, ret; | 1595 | int req, ret; |
1552 | unsigned long flags; | 1596 | unsigned long flags; |
1553 | 1597 | ||
1554 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1598 | spin_lock_irqsave(&cs->lock, flags); |
1555 | if (unlikely(!bcs->cs->connected)) { | 1599 | if (unlikely(!cs->connected)) { |
1556 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | 1600 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); |
1557 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1601 | spin_unlock_irqrestore(&cs->lock, flags); |
1558 | return -ENODEV; | 1602 | return -ENODEV; |
1559 | } | 1603 | } |
1560 | 1604 | ||
1605 | if (cs->hw.bas->basstate & BS_SUSPEND) { | ||
1606 | dev_notice(cs->dev, | ||
1607 | "not starting isochronous I/O, " | ||
1608 | "suspend in progress\n"); | ||
1609 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1610 | return -EHOSTUNREACH; | ||
1611 | } | ||
1612 | |||
1561 | if ((ret = starturbs(bcs)) < 0) { | 1613 | if ((ret = starturbs(bcs)) < 0) { |
1562 | dev_err(bcs->cs->dev, | 1614 | dev_err(cs->dev, |
1563 | "could not start isochronous I/O for channel B%d: %s\n", | 1615 | "could not start isochronous I/O for channel B%d: %s\n", |
1564 | bcs->channel + 1, | 1616 | bcs->channel + 1, |
1565 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); | 1617 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); |
1566 | if (ret != -ENODEV) | 1618 | if (ret != -ENODEV) |
1567 | error_hangup(bcs); | 1619 | error_hangup(bcs); |
1568 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1620 | spin_unlock_irqrestore(&cs->lock, flags); |
1569 | return ret; | 1621 | return ret; |
1570 | } | 1622 | } |
1571 | 1623 | ||
1572 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; | 1624 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; |
1573 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { | 1625 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { |
1574 | dev_err(bcs->cs->dev, "could not open channel B%d\n", | 1626 | dev_err(cs->dev, "could not open channel B%d\n", |
1575 | bcs->channel + 1); | 1627 | bcs->channel + 1); |
1576 | stopurbs(bcs->hw.bas); | 1628 | stopurbs(bcs->hw.bas); |
1577 | if (ret != -ENODEV) | 1629 | if (ret != -ENODEV) |
1578 | error_hangup(bcs); | 1630 | error_hangup(bcs); |
1579 | } | 1631 | } |
1580 | 1632 | ||
1581 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1633 | spin_unlock_irqrestore(&cs->lock, flags); |
1582 | return ret; | 1634 | return ret; |
1583 | } | 1635 | } |
1584 | 1636 | ||
@@ -1594,20 +1646,20 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1594 | */ | 1646 | */ |
1595 | static int gigaset_close_bchannel(struct bc_state *bcs) | 1647 | static int gigaset_close_bchannel(struct bc_state *bcs) |
1596 | { | 1648 | { |
1649 | struct cardstate *cs = bcs->cs; | ||
1597 | int req, ret; | 1650 | int req, ret; |
1598 | unsigned long flags; | 1651 | unsigned long flags; |
1599 | 1652 | ||
1600 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1653 | spin_lock_irqsave(&cs->lock, flags); |
1601 | if (unlikely(!bcs->cs->connected)) { | 1654 | if (unlikely(!cs->connected)) { |
1602 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1655 | spin_unlock_irqrestore(&cs->lock, flags); |
1603 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | 1656 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); |
1604 | return -ENODEV; | 1657 | return -ENODEV; |
1605 | } | 1658 | } |
1606 | 1659 | ||
1607 | if (!(atomic_read(&bcs->cs->hw.bas->basstate) & | 1660 | if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { |
1608 | (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { | ||
1609 | /* channel not running: just signal common.c */ | 1661 | /* channel not running: just signal common.c */ |
1610 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1662 | spin_unlock_irqrestore(&cs->lock, flags); |
1611 | gigaset_bchannel_down(bcs); | 1663 | gigaset_bchannel_down(bcs); |
1612 | return 0; | 1664 | return 0; |
1613 | } | 1665 | } |
@@ -1615,10 +1667,10 @@ static int gigaset_close_bchannel(struct bc_state *bcs) | |||
1615 | /* channel running: tell device to close it */ | 1667 | /* channel running: tell device to close it */ |
1616 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; | 1668 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; |
1617 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) | 1669 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) |
1618 | dev_err(bcs->cs->dev, "closing channel B%d failed\n", | 1670 | dev_err(cs->dev, "closing channel B%d failed\n", |
1619 | bcs->channel + 1); | 1671 | bcs->channel + 1); |
1620 | 1672 | ||
1621 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1673 | spin_unlock_irqrestore(&cs->lock, flags); |
1622 | return ret; | 1674 | return ret; |
1623 | } | 1675 | } |
1624 | 1676 | ||
@@ -1665,12 +1717,14 @@ static void write_command_callback(struct urb *urb) | |||
1665 | { | 1717 | { |
1666 | struct cardstate *cs = urb->context; | 1718 | struct cardstate *cs = urb->context; |
1667 | struct bas_cardstate *ucs = cs->hw.bas; | 1719 | struct bas_cardstate *ucs = cs->hw.bas; |
1720 | int status = urb->status; | ||
1668 | unsigned long flags; | 1721 | unsigned long flags; |
1669 | 1722 | ||
1670 | update_basstate(ucs, 0, BS_ATWRPEND); | 1723 | update_basstate(ucs, 0, BS_ATWRPEND); |
1724 | wake_up(&ucs->waitqueue); | ||
1671 | 1725 | ||
1672 | /* check status */ | 1726 | /* check status */ |
1673 | switch (urb->status) { | 1727 | switch (status) { |
1674 | case 0: /* normal completion */ | 1728 | case 0: /* normal completion */ |
1675 | break; | 1729 | break; |
1676 | case -ENOENT: /* cancelled */ | 1730 | case -ENOENT: /* cancelled */ |
@@ -1680,26 +1734,33 @@ static void write_command_callback(struct urb *urb) | |||
1680 | case -ESHUTDOWN: /* device shut down */ | 1734 | case -ESHUTDOWN: /* device shut down */ |
1681 | /* ignore silently */ | 1735 | /* ignore silently */ |
1682 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1736 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1683 | __func__, get_usb_statmsg(urb->status)); | 1737 | __func__, get_usb_statmsg(status)); |
1684 | return; | 1738 | return; |
1685 | default: /* any failure */ | 1739 | default: /* any failure */ |
1686 | if (++ucs->retry_cmd_out > BAS_RETRY) { | 1740 | if (++ucs->retry_cmd_out > BAS_RETRY) { |
1687 | dev_warn(cs->dev, | 1741 | dev_warn(cs->dev, |
1688 | "command write: %s, " | 1742 | "command write: %s, " |
1689 | "giving up after %d retries\n", | 1743 | "giving up after %d retries\n", |
1690 | get_usb_statmsg(urb->status), | 1744 | get_usb_statmsg(status), |
1691 | ucs->retry_cmd_out); | 1745 | ucs->retry_cmd_out); |
1692 | break; | 1746 | break; |
1693 | } | 1747 | } |
1748 | if (ucs->basstate & BS_SUSPEND) { | ||
1749 | dev_warn(cs->dev, | ||
1750 | "command write: %s, " | ||
1751 | "won't retry - suspend requested\n", | ||
1752 | get_usb_statmsg(status)); | ||
1753 | break; | ||
1754 | } | ||
1694 | if (cs->cmdbuf == NULL) { | 1755 | if (cs->cmdbuf == NULL) { |
1695 | dev_warn(cs->dev, | 1756 | dev_warn(cs->dev, |
1696 | "command write: %s, " | 1757 | "command write: %s, " |
1697 | "cannot retry - cmdbuf gone\n", | 1758 | "cannot retry - cmdbuf gone\n", |
1698 | get_usb_statmsg(urb->status)); | 1759 | get_usb_statmsg(status)); |
1699 | break; | 1760 | break; |
1700 | } | 1761 | } |
1701 | dev_notice(cs->dev, "command write: %s, retry %d\n", | 1762 | dev_notice(cs->dev, "command write: %s, retry %d\n", |
1702 | get_usb_statmsg(urb->status), ucs->retry_cmd_out); | 1763 | get_usb_statmsg(status), ucs->retry_cmd_out); |
1703 | if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) | 1764 | if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) |
1704 | /* resubmitted - bypass regular exit block */ | 1765 | /* resubmitted - bypass regular exit block */ |
1705 | return; | 1766 | return; |
@@ -1799,8 +1860,14 @@ static int start_cbsend(struct cardstate *cs) | |||
1799 | int rc; | 1860 | int rc; |
1800 | int retval = 0; | 1861 | int retval = 0; |
1801 | 1862 | ||
1863 | /* check if suspend requested */ | ||
1864 | if (ucs->basstate & BS_SUSPEND) { | ||
1865 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending"); | ||
1866 | return -EHOSTUNREACH; | ||
1867 | } | ||
1868 | |||
1802 | /* check if AT channel is open */ | 1869 | /* check if AT channel is open */ |
1803 | if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) { | 1870 | if (!(ucs->basstate & BS_ATOPEN)) { |
1804 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); | 1871 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); |
1805 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); | 1872 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); |
1806 | if (rc < 0) { | 1873 | if (rc < 0) { |
@@ -1816,8 +1883,7 @@ static int start_cbsend(struct cardstate *cs) | |||
1816 | /* try to send first command in queue */ | 1883 | /* try to send first command in queue */ |
1817 | spin_lock_irqsave(&cs->cmdlock, flags); | 1884 | spin_lock_irqsave(&cs->cmdlock, flags); |
1818 | 1885 | ||
1819 | while ((cb = cs->cmdbuf) != NULL && | 1886 | while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) { |
1820 | atomic_read(&ucs->basstate) & BS_ATREADY) { | ||
1821 | ucs->retry_cmd_out = 0; | 1887 | ucs->retry_cmd_out = 0; |
1822 | rc = atwrite_submit(cs, cb->buf, cb->len); | 1888 | rc = atwrite_submit(cs, cb->buf, cb->len); |
1823 | if (unlikely(rc)) { | 1889 | if (unlikely(rc)) { |
@@ -1855,7 +1921,7 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1855 | unsigned long flags; | 1921 | unsigned long flags; |
1856 | int rc; | 1922 | int rc; |
1857 | 1923 | ||
1858 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 1924 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
1859 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 1925 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
1860 | "CMD Transmit", len, buf); | 1926 | "CMD Transmit", len, buf); |
1861 | 1927 | ||
@@ -1970,7 +2036,7 @@ static int gigaset_freebcshw(struct bc_state *bcs) | |||
1970 | return 0; | 2036 | return 0; |
1971 | 2037 | ||
1972 | /* kill URBs and tasklets before freeing - better safe than sorry */ | 2038 | /* kill URBs and tasklets before freeing - better safe than sorry */ |
1973 | atomic_set(&ubc->running, 0); | 2039 | ubc->running = 0; |
1974 | gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); | 2040 | gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); |
1975 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2041 | for (i = 0; i < BAS_OUTURBS; ++i) { |
1976 | usb_kill_urb(ubc->isoouturbs[i].urb); | 2042 | usb_kill_urb(ubc->isoouturbs[i].urb); |
@@ -2005,7 +2071,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) | |||
2005 | return 0; | 2071 | return 0; |
2006 | } | 2072 | } |
2007 | 2073 | ||
2008 | atomic_set(&ubc->running, 0); | 2074 | ubc->running = 0; |
2009 | atomic_set(&ubc->corrbytes, 0); | 2075 | atomic_set(&ubc->corrbytes, 0); |
2010 | spin_lock_init(&ubc->isooutlock); | 2076 | spin_lock_init(&ubc->isooutlock); |
2011 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2077 | for (i = 0; i < BAS_OUTURBS; ++i) { |
@@ -2050,7 +2116,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) | |||
2050 | { | 2116 | { |
2051 | struct bas_bc_state *ubc = bcs->hw.bas; | 2117 | struct bas_bc_state *ubc = bcs->hw.bas; |
2052 | 2118 | ||
2053 | atomic_set(&bcs->hw.bas->running, 0); | 2119 | bcs->hw.bas->running = 0; |
2054 | atomic_set(&bcs->hw.bas->corrbytes, 0); | 2120 | atomic_set(&bcs->hw.bas->corrbytes, 0); |
2055 | bcs->hw.bas->numsub = 0; | 2121 | bcs->hw.bas->numsub = 0; |
2056 | spin_lock_init(&ubc->isooutlock); | 2122 | spin_lock_init(&ubc->isooutlock); |
@@ -2081,10 +2147,11 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
2081 | spin_lock_init(&ucs->lock); | 2147 | spin_lock_init(&ucs->lock); |
2082 | ucs->pending = 0; | 2148 | ucs->pending = 0; |
2083 | 2149 | ||
2084 | atomic_set(&ucs->basstate, 0); | 2150 | ucs->basstate = 0; |
2085 | init_timer(&ucs->timer_ctrl); | 2151 | init_timer(&ucs->timer_ctrl); |
2086 | init_timer(&ucs->timer_atrdy); | 2152 | init_timer(&ucs->timer_atrdy); |
2087 | init_timer(&ucs->timer_cmd_in); | 2153 | init_timer(&ucs->timer_cmd_in); |
2154 | init_waitqueue_head(&ucs->waitqueue); | ||
2088 | 2155 | ||
2089 | return 1; | 2156 | return 1; |
2090 | } | 2157 | } |
@@ -2102,7 +2169,7 @@ static void freeurbs(struct cardstate *cs) | |||
2102 | int i, j; | 2169 | int i, j; |
2103 | 2170 | ||
2104 | gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); | 2171 | gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); |
2105 | for (j = 0; j < 2; ++j) { | 2172 | for (j = 0; j < BAS_CHANNELS; ++j) { |
2106 | ubc = cs->bcs[j].hw.bas; | 2173 | ubc = cs->bcs[j].hw.bas; |
2107 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2174 | for (i = 0; i < BAS_OUTURBS; ++i) { |
2108 | usb_kill_urb(ubc->isoouturbs[i].urb); | 2175 | usb_kill_urb(ubc->isoouturbs[i].urb); |
@@ -2179,11 +2246,11 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2179 | __func__, le16_to_cpu(udev->descriptor.idVendor), | 2246 | __func__, le16_to_cpu(udev->descriptor.idVendor), |
2180 | le16_to_cpu(udev->descriptor.idProduct)); | 2247 | le16_to_cpu(udev->descriptor.idProduct)); |
2181 | 2248 | ||
2182 | cs = gigaset_getunassignedcs(driver); | 2249 | /* allocate memory for our device state and intialize it */ |
2183 | if (!cs) { | 2250 | cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, |
2184 | dev_err(&udev->dev, "no free cardstate\n"); | 2251 | GIGASET_MODULENAME); |
2252 | if (!cs) | ||
2185 | return -ENODEV; | 2253 | return -ENODEV; |
2186 | } | ||
2187 | ucs = cs->hw.bas; | 2254 | ucs = cs->hw.bas; |
2188 | 2255 | ||
2189 | /* save off device structure ptrs for later use */ | 2256 | /* save off device structure ptrs for later use */ |
@@ -2203,7 +2270,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2203 | !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) | 2270 | !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) |
2204 | goto allocerr; | 2271 | goto allocerr; |
2205 | 2272 | ||
2206 | for (j = 0; j < 2; ++j) { | 2273 | for (j = 0; j < BAS_CHANNELS; ++j) { |
2207 | ubc = cs->bcs[j].hw.bas; | 2274 | ubc = cs->bcs[j].hw.bas; |
2208 | for (i = 0; i < BAS_OUTURBS; ++i) | 2275 | for (i = 0; i < BAS_OUTURBS; ++i) |
2209 | if (!(ubc->isoouturbs[i].urb = | 2276 | if (!(ubc->isoouturbs[i].urb = |
@@ -2237,7 +2304,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2237 | 2304 | ||
2238 | /* tell common part that the device is ready */ | 2305 | /* tell common part that the device is ready */ |
2239 | if (startmode == SM_LOCKED) | 2306 | if (startmode == SM_LOCKED) |
2240 | atomic_set(&cs->mstate, MS_LOCKED); | 2307 | cs->mstate = MS_LOCKED; |
2241 | 2308 | ||
2242 | /* save address of controller structure */ | 2309 | /* save address of controller structure */ |
2243 | usb_set_intfdata(interface, cs); | 2310 | usb_set_intfdata(interface, cs); |
@@ -2252,7 +2319,7 @@ allocerr: | |||
2252 | error: | 2319 | error: |
2253 | freeurbs(cs); | 2320 | freeurbs(cs); |
2254 | usb_set_intfdata(interface, NULL); | 2321 | usb_set_intfdata(interface, NULL); |
2255 | gigaset_unassign(cs); | 2322 | gigaset_freecs(cs); |
2256 | return -ENODEV; | 2323 | return -ENODEV; |
2257 | } | 2324 | } |
2258 | 2325 | ||
@@ -2272,11 +2339,10 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2272 | dev_info(cs->dev, "disconnecting Gigaset base\n"); | 2339 | dev_info(cs->dev, "disconnecting Gigaset base\n"); |
2273 | 2340 | ||
2274 | /* mark base as not ready, all channels disconnected */ | 2341 | /* mark base as not ready, all channels disconnected */ |
2275 | atomic_set(&ucs->basstate, 0); | 2342 | ucs->basstate = 0; |
2276 | 2343 | ||
2277 | /* tell LL all channels are down */ | 2344 | /* tell LL all channels are down */ |
2278 | //FIXME shouldn't gigaset_stop() do this? | 2345 | for (j = 0; j < BAS_CHANNELS; ++j) |
2279 | for (j = 0; j < 2; ++j) | ||
2280 | gigaset_bchannel_down(cs->bcs + j); | 2346 | gigaset_bchannel_down(cs->bcs + j); |
2281 | 2347 | ||
2282 | /* stop driver (common part) */ | 2348 | /* stop driver (common part) */ |
@@ -2295,9 +2361,113 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2295 | ucs->interface = NULL; | 2361 | ucs->interface = NULL; |
2296 | ucs->udev = NULL; | 2362 | ucs->udev = NULL; |
2297 | cs->dev = NULL; | 2363 | cs->dev = NULL; |
2298 | gigaset_unassign(cs); | 2364 | gigaset_freecs(cs); |
2299 | } | 2365 | } |
2300 | 2366 | ||
2367 | /* gigaset_suspend | ||
2368 | * This function is called before the USB connection is suspended. | ||
2369 | */ | ||
2370 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) | ||
2371 | { | ||
2372 | struct cardstate *cs = usb_get_intfdata(intf); | ||
2373 | struct bas_cardstate *ucs = cs->hw.bas; | ||
2374 | int rc; | ||
2375 | |||
2376 | /* set suspend flag; this stops AT command/response traffic */ | ||
2377 | if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) { | ||
2378 | gig_dbg(DEBUG_SUSPEND, "already suspended"); | ||
2379 | return 0; | ||
2380 | } | ||
2381 | |||
2382 | /* wait a bit for blocking conditions to go away */ | ||
2383 | rc = wait_event_timeout(ucs->waitqueue, | ||
2384 | !(ucs->basstate & | ||
2385 | (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)), | ||
2386 | BAS_TIMEOUT*HZ/10); | ||
2387 | gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc); | ||
2388 | |||
2389 | /* check for conditions preventing suspend */ | ||
2390 | if (ucs->basstate & (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)) { | ||
2391 | dev_warn(cs->dev, "cannot suspend:\n"); | ||
2392 | if (ucs->basstate & BS_B1OPEN) | ||
2393 | dev_warn(cs->dev, " B channel 1 open\n"); | ||
2394 | if (ucs->basstate & BS_B2OPEN) | ||
2395 | dev_warn(cs->dev, " B channel 2 open\n"); | ||
2396 | if (ucs->basstate & BS_ATRDPEND) | ||
2397 | dev_warn(cs->dev, " receiving AT reply\n"); | ||
2398 | if (ucs->basstate & BS_ATWRPEND) | ||
2399 | dev_warn(cs->dev, " sending AT command\n"); | ||
2400 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2401 | return -EBUSY; | ||
2402 | } | ||
2403 | |||
2404 | /* close AT channel if open */ | ||
2405 | if (ucs->basstate & BS_ATOPEN) { | ||
2406 | gig_dbg(DEBUG_SUSPEND, "closing AT channel"); | ||
2407 | rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0); | ||
2408 | if (rc) { | ||
2409 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2410 | return rc; | ||
2411 | } | ||
2412 | wait_event_timeout(ucs->waitqueue, !ucs->pending, | ||
2413 | BAS_TIMEOUT*HZ/10); | ||
2414 | /* in case of timeout, proceed anyway */ | ||
2415 | } | ||
2416 | |||
2417 | /* kill all URBs and timers that might still be pending */ | ||
2418 | usb_kill_urb(ucs->urb_ctrl); | ||
2419 | usb_kill_urb(ucs->urb_int_in); | ||
2420 | del_timer_sync(&ucs->timer_ctrl); | ||
2421 | |||
2422 | gig_dbg(DEBUG_SUSPEND, "suspend complete"); | ||
2423 | return 0; | ||
2424 | } | ||
2425 | |||
2426 | /* gigaset_resume | ||
2427 | * This function is called after the USB connection has been resumed. | ||
2428 | */ | ||
2429 | static int gigaset_resume(struct usb_interface *intf) | ||
2430 | { | ||
2431 | struct cardstate *cs = usb_get_intfdata(intf); | ||
2432 | struct bas_cardstate *ucs = cs->hw.bas; | ||
2433 | int rc; | ||
2434 | |||
2435 | /* resubmit interrupt URB for spontaneous messages from base */ | ||
2436 | rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); | ||
2437 | if (rc) { | ||
2438 | dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", | ||
2439 | get_usb_rcmsg(rc)); | ||
2440 | return rc; | ||
2441 | } | ||
2442 | |||
2443 | /* clear suspend flag to reallow activity */ | ||
2444 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2445 | |||
2446 | gig_dbg(DEBUG_SUSPEND, "resume complete"); | ||
2447 | return 0; | ||
2448 | } | ||
2449 | |||
2450 | /* gigaset_pre_reset | ||
2451 | * This function is called before the USB connection is reset. | ||
2452 | */ | ||
2453 | static int gigaset_pre_reset(struct usb_interface *intf) | ||
2454 | { | ||
2455 | /* handle just like suspend */ | ||
2456 | return gigaset_suspend(intf, PMSG_ON); | ||
2457 | } | ||
2458 | |||
2459 | /* gigaset_post_reset | ||
2460 | * This function is called after the USB connection has been reset. | ||
2461 | */ | ||
2462 | static int gigaset_post_reset(struct usb_interface *intf) | ||
2463 | { | ||
2464 | /* FIXME: send HD_DEVICE_INIT_ACK? */ | ||
2465 | |||
2466 | /* resume operations */ | ||
2467 | return gigaset_resume(intf); | ||
2468 | } | ||
2469 | |||
2470 | |||
2301 | static const struct gigaset_ops gigops = { | 2471 | static const struct gigaset_ops gigops = { |
2302 | gigaset_write_cmd, | 2472 | gigaset_write_cmd, |
2303 | gigaset_write_room, | 2473 | gigaset_write_room, |
@@ -2330,12 +2500,6 @@ static int __init bas_gigaset_init(void) | |||
2330 | &gigops, THIS_MODULE)) == NULL) | 2500 | &gigops, THIS_MODULE)) == NULL) |
2331 | goto error; | 2501 | goto error; |
2332 | 2502 | ||
2333 | /* allocate memory for our device state and intialize it */ | ||
2334 | cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, | ||
2335 | GIGASET_MODULENAME); | ||
2336 | if (!cardstate) | ||
2337 | goto error; | ||
2338 | |||
2339 | /* register this driver with the USB subsystem */ | 2503 | /* register this driver with the USB subsystem */ |
2340 | result = usb_register(&gigaset_usb_driver); | 2504 | result = usb_register(&gigaset_usb_driver); |
2341 | if (result < 0) { | 2505 | if (result < 0) { |
@@ -2347,9 +2511,7 @@ static int __init bas_gigaset_init(void) | |||
2347 | info(DRIVER_DESC); | 2511 | info(DRIVER_DESC); |
2348 | return 0; | 2512 | return 0; |
2349 | 2513 | ||
2350 | error: if (cardstate) | 2514 | error: |
2351 | gigaset_freecs(cardstate); | ||
2352 | cardstate = NULL; | ||
2353 | if (driver) | 2515 | if (driver) |
2354 | gigaset_freedriver(driver); | 2516 | gigaset_freedriver(driver); |
2355 | driver = NULL; | 2517 | driver = NULL; |
@@ -2361,43 +2523,50 @@ error: if (cardstate) | |||
2361 | */ | 2523 | */ |
2362 | static void __exit bas_gigaset_exit(void) | 2524 | static void __exit bas_gigaset_exit(void) |
2363 | { | 2525 | { |
2364 | struct bas_cardstate *ucs = cardstate->hw.bas; | 2526 | struct bas_cardstate *ucs; |
2527 | int i; | ||
2365 | 2528 | ||
2366 | gigaset_blockdriver(driver); /* => probe will fail | 2529 | gigaset_blockdriver(driver); /* => probe will fail |
2367 | * => no gigaset_start any more | 2530 | * => no gigaset_start any more |
2368 | */ | 2531 | */ |
2369 | 2532 | ||
2370 | gigaset_shutdown(cardstate); | 2533 | /* stop all connected devices */ |
2371 | /* from now on, no isdn callback should be possible */ | 2534 | for (i = 0; i < driver->minors; i++) { |
2372 | 2535 | if (gigaset_shutdown(driver->cs + i) < 0) | |
2373 | /* close all still open channels */ | 2536 | continue; /* no device */ |
2374 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) { | 2537 | /* from now on, no isdn callback should be possible */ |
2375 | gig_dbg(DEBUG_INIT, "closing B1 channel"); | 2538 | |
2376 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2539 | /* close all still open channels */ |
2377 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0, | 2540 | ucs = driver->cs[i].hw.bas; |
2378 | NULL, 0, BAS_TIMEOUT); | 2541 | if (ucs->basstate & BS_B1OPEN) { |
2379 | } | 2542 | gig_dbg(DEBUG_INIT, "closing B1 channel"); |
2380 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) { | 2543 | usb_control_msg(ucs->udev, |
2381 | gig_dbg(DEBUG_INIT, "closing B2 channel"); | 2544 | usb_sndctrlpipe(ucs->udev, 0), |
2382 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2545 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, |
2383 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0, | 2546 | 0, 0, NULL, 0, BAS_TIMEOUT); |
2384 | NULL, 0, BAS_TIMEOUT); | 2547 | } |
2385 | } | 2548 | if (ucs->basstate & BS_B2OPEN) { |
2386 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) { | 2549 | gig_dbg(DEBUG_INIT, "closing B2 channel"); |
2387 | gig_dbg(DEBUG_INIT, "closing AT channel"); | 2550 | usb_control_msg(ucs->udev, |
2388 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2551 | usb_sndctrlpipe(ucs->udev, 0), |
2389 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0, | 2552 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, |
2390 | NULL, 0, BAS_TIMEOUT); | 2553 | 0, 0, NULL, 0, BAS_TIMEOUT); |
2554 | } | ||
2555 | if (ucs->basstate & BS_ATOPEN) { | ||
2556 | gig_dbg(DEBUG_INIT, "closing AT channel"); | ||
2557 | usb_control_msg(ucs->udev, | ||
2558 | usb_sndctrlpipe(ucs->udev, 0), | ||
2559 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, | ||
2560 | 0, 0, NULL, 0, BAS_TIMEOUT); | ||
2561 | } | ||
2562 | ucs->basstate = 0; | ||
2391 | } | 2563 | } |
2392 | atomic_set(&ucs->basstate, 0); | ||
2393 | 2564 | ||
2394 | /* deregister this driver with the USB subsystem */ | 2565 | /* deregister this driver with the USB subsystem */ |
2395 | usb_deregister(&gigaset_usb_driver); | 2566 | usb_deregister(&gigaset_usb_driver); |
2396 | /* this will call the disconnect-callback */ | 2567 | /* this will call the disconnect-callback */ |
2397 | /* from now on, no disconnect/probe callback should be running */ | 2568 | /* from now on, no disconnect/probe callback should be running */ |
2398 | 2569 | ||
2399 | gigaset_freecs(cardstate); | ||
2400 | cardstate = NULL; | ||
2401 | gigaset_freedriver(driver); | 2570 | gigaset_freedriver(driver); |
2402 | driver = NULL; | 2571 | driver = NULL; |
2403 | } | 2572 | } |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index acd417197d03..aacedec4986f 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -31,7 +31,6 @@ MODULE_PARM_DESC(debug, "debug level"); | |||
31 | /* driver state flags */ | 31 | /* driver state flags */ |
32 | #define VALID_MINOR 0x01 | 32 | #define VALID_MINOR 0x01 |
33 | #define VALID_ID 0x02 | 33 | #define VALID_ID 0x02 |
34 | #define ASSIGNED 0x04 | ||
35 | 34 | ||
36 | void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | 35 | void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, |
37 | size_t len, const unsigned char *buf) | 36 | size_t len, const unsigned char *buf) |
@@ -178,7 +177,7 @@ int gigaset_get_channel(struct bc_state *bcs) | |||
178 | unsigned long flags; | 177 | unsigned long flags; |
179 | 178 | ||
180 | spin_lock_irqsave(&bcs->cs->lock, flags); | 179 | spin_lock_irqsave(&bcs->cs->lock, flags); |
181 | if (bcs->use_count) { | 180 | if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { |
182 | gig_dbg(DEBUG_ANY, "could not allocate channel %d", | 181 | gig_dbg(DEBUG_ANY, "could not allocate channel %d", |
183 | bcs->channel); | 182 | bcs->channel); |
184 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 183 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
@@ -203,6 +202,7 @@ void gigaset_free_channel(struct bc_state *bcs) | |||
203 | } | 202 | } |
204 | --bcs->use_count; | 203 | --bcs->use_count; |
205 | bcs->busy = 0; | 204 | bcs->busy = 0; |
205 | module_put(bcs->cs->driver->owner); | ||
206 | gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); | 206 | gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); |
207 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 207 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
208 | } | 208 | } |
@@ -356,31 +356,28 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv) | |||
356 | { | 356 | { |
357 | unsigned long flags; | 357 | unsigned long flags; |
358 | unsigned i; | 358 | unsigned i; |
359 | struct cardstate *cs; | ||
359 | struct cardstate *ret = NULL; | 360 | struct cardstate *ret = NULL; |
360 | 361 | ||
361 | spin_lock_irqsave(&drv->lock, flags); | 362 | spin_lock_irqsave(&drv->lock, flags); |
363 | if (drv->blocked) | ||
364 | goto exit; | ||
362 | for (i = 0; i < drv->minors; ++i) { | 365 | for (i = 0; i < drv->minors; ++i) { |
363 | if (!(drv->flags[i] & VALID_MINOR)) { | 366 | cs = drv->cs + i; |
364 | if (try_module_get(drv->owner)) { | 367 | if (!(cs->flags & VALID_MINOR)) { |
365 | drv->flags[i] = VALID_MINOR; | 368 | cs->flags = VALID_MINOR; |
366 | ret = drv->cs + i; | 369 | ret = cs; |
367 | } | ||
368 | break; | 370 | break; |
369 | } | 371 | } |
370 | } | 372 | } |
373 | exit: | ||
371 | spin_unlock_irqrestore(&drv->lock, flags); | 374 | spin_unlock_irqrestore(&drv->lock, flags); |
372 | return ret; | 375 | return ret; |
373 | } | 376 | } |
374 | 377 | ||
375 | static void free_cs(struct cardstate *cs) | 378 | static void free_cs(struct cardstate *cs) |
376 | { | 379 | { |
377 | unsigned long flags; | 380 | cs->flags = 0; |
378 | struct gigaset_driver *drv = cs->driver; | ||
379 | spin_lock_irqsave(&drv->lock, flags); | ||
380 | if (drv->flags[cs->minor_index] & VALID_MINOR) | ||
381 | module_put(drv->owner); | ||
382 | drv->flags[cs->minor_index] = 0; | ||
383 | spin_unlock_irqrestore(&drv->lock, flags); | ||
384 | } | 381 | } |
385 | 382 | ||
386 | static void make_valid(struct cardstate *cs, unsigned mask) | 383 | static void make_valid(struct cardstate *cs, unsigned mask) |
@@ -388,7 +385,7 @@ static void make_valid(struct cardstate *cs, unsigned mask) | |||
388 | unsigned long flags; | 385 | unsigned long flags; |
389 | struct gigaset_driver *drv = cs->driver; | 386 | struct gigaset_driver *drv = cs->driver; |
390 | spin_lock_irqsave(&drv->lock, flags); | 387 | spin_lock_irqsave(&drv->lock, flags); |
391 | drv->flags[cs->minor_index] |= mask; | 388 | cs->flags |= mask; |
392 | spin_unlock_irqrestore(&drv->lock, flags); | 389 | spin_unlock_irqrestore(&drv->lock, flags); |
393 | } | 390 | } |
394 | 391 | ||
@@ -397,7 +394,7 @@ static void make_invalid(struct cardstate *cs, unsigned mask) | |||
397 | unsigned long flags; | 394 | unsigned long flags; |
398 | struct gigaset_driver *drv = cs->driver; | 395 | struct gigaset_driver *drv = cs->driver; |
399 | spin_lock_irqsave(&drv->lock, flags); | 396 | spin_lock_irqsave(&drv->lock, flags); |
400 | drv->flags[cs->minor_index] &= ~mask; | 397 | cs->flags &= ~mask; |
401 | spin_unlock_irqrestore(&drv->lock, flags); | 398 | spin_unlock_irqrestore(&drv->lock, flags); |
402 | } | 399 | } |
403 | 400 | ||
@@ -501,11 +498,11 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, | |||
501 | struct cardstate *cs, int inputstate) | 498 | struct cardstate *cs, int inputstate) |
502 | /* inbuf->read must be allocated before! */ | 499 | /* inbuf->read must be allocated before! */ |
503 | { | 500 | { |
504 | atomic_set(&inbuf->head, 0); | 501 | inbuf->head = 0; |
505 | atomic_set(&inbuf->tail, 0); | 502 | inbuf->tail = 0; |
506 | inbuf->cs = cs; | 503 | inbuf->cs = cs; |
507 | inbuf->bcs = bcs; /*base driver: NULL*/ | 504 | inbuf->bcs = bcs; /*base driver: NULL*/ |
508 | inbuf->rcvbuf = NULL; //FIXME | 505 | inbuf->rcvbuf = NULL; |
509 | inbuf->inputstate = inputstate; | 506 | inbuf->inputstate = inputstate; |
510 | } | 507 | } |
511 | 508 | ||
@@ -521,8 +518,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | |||
521 | return 0; | 518 | return 0; |
522 | 519 | ||
523 | bytesleft = numbytes; | 520 | bytesleft = numbytes; |
524 | tail = atomic_read(&inbuf->tail); | 521 | tail = inbuf->tail; |
525 | head = atomic_read(&inbuf->head); | 522 | head = inbuf->head; |
526 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | 523 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); |
527 | 524 | ||
528 | while (bytesleft) { | 525 | while (bytesleft) { |
@@ -546,7 +543,7 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | |||
546 | src += n; | 543 | src += n; |
547 | } | 544 | } |
548 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); | 545 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); |
549 | atomic_set(&inbuf->tail, tail); | 546 | inbuf->tail = tail; |
550 | return numbytes != bytesleft; | 547 | return numbytes != bytesleft; |
551 | } | 548 | } |
552 | EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); | 549 | EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); |
@@ -668,7 +665,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
668 | 665 | ||
669 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, | 666 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, |
670 | (unsigned long) cs); | 667 | (unsigned long) cs); |
671 | atomic_set(&cs->commands_pending, 0); | 668 | cs->commands_pending = 0; |
672 | cs->cur_at_seq = 0; | 669 | cs->cur_at_seq = 0; |
673 | cs->gotfwver = -1; | 670 | cs->gotfwver = -1; |
674 | cs->open_count = 0; | 671 | cs->open_count = 0; |
@@ -688,8 +685,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
688 | init_waitqueue_head(&cs->waitqueue); | 685 | init_waitqueue_head(&cs->waitqueue); |
689 | cs->waiting = 0; | 686 | cs->waiting = 0; |
690 | 687 | ||
691 | atomic_set(&cs->mode, M_UNKNOWN); | 688 | cs->mode = M_UNKNOWN; |
692 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 689 | cs->mstate = MS_UNINITIALIZED; |
693 | 690 | ||
694 | for (i = 0; i < channels; ++i) { | 691 | for (i = 0; i < channels; ++i) { |
695 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); | 692 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); |
@@ -806,8 +803,8 @@ static void cleanup_cs(struct cardstate *cs) | |||
806 | 803 | ||
807 | spin_lock_irqsave(&cs->lock, flags); | 804 | spin_lock_irqsave(&cs->lock, flags); |
808 | 805 | ||
809 | atomic_set(&cs->mode, M_UNKNOWN); | 806 | cs->mode = M_UNKNOWN; |
810 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 807 | cs->mstate = MS_UNINITIALIZED; |
811 | 808 | ||
812 | clear_at_state(&cs->at_state); | 809 | clear_at_state(&cs->at_state); |
813 | dealloc_at_states(cs); | 810 | dealloc_at_states(cs); |
@@ -817,8 +814,8 @@ static void cleanup_cs(struct cardstate *cs) | |||
817 | kfree(cs->inbuf->rcvbuf); | 814 | kfree(cs->inbuf->rcvbuf); |
818 | cs->inbuf->rcvbuf = NULL; | 815 | cs->inbuf->rcvbuf = NULL; |
819 | cs->inbuf->inputstate = INS_command; | 816 | cs->inbuf->inputstate = INS_command; |
820 | atomic_set(&cs->inbuf->head, 0); | 817 | cs->inbuf->head = 0; |
821 | atomic_set(&cs->inbuf->tail, 0); | 818 | cs->inbuf->tail = 0; |
822 | 819 | ||
823 | cb = cs->cmdbuf; | 820 | cb = cs->cmdbuf; |
824 | while (cb) { | 821 | while (cb) { |
@@ -832,7 +829,7 @@ static void cleanup_cs(struct cardstate *cs) | |||
832 | cs->gotfwver = -1; | 829 | cs->gotfwver = -1; |
833 | cs->dle = 0; | 830 | cs->dle = 0; |
834 | cs->cur_at_seq = 0; | 831 | cs->cur_at_seq = 0; |
835 | atomic_set(&cs->commands_pending, 0); | 832 | cs->commands_pending = 0; |
836 | cs->cbytes = 0; | 833 | cs->cbytes = 0; |
837 | 834 | ||
838 | spin_unlock_irqrestore(&cs->lock, flags); | 835 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -862,7 +859,7 @@ int gigaset_start(struct cardstate *cs) | |||
862 | cs->connected = 1; | 859 | cs->connected = 1; |
863 | spin_unlock_irqrestore(&cs->lock, flags); | 860 | spin_unlock_irqrestore(&cs->lock, flags); |
864 | 861 | ||
865 | if (atomic_read(&cs->mstate) != MS_LOCKED) { | 862 | if (cs->mstate != MS_LOCKED) { |
866 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); | 863 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); |
867 | cs->ops->baud_rate(cs, B115200); | 864 | cs->ops->baud_rate(cs, B115200); |
868 | cs->ops->set_line_ctrl(cs, CS8); | 865 | cs->ops->set_line_ctrl(cs, CS8); |
@@ -893,10 +890,17 @@ error: | |||
893 | } | 890 | } |
894 | EXPORT_SYMBOL_GPL(gigaset_start); | 891 | EXPORT_SYMBOL_GPL(gigaset_start); |
895 | 892 | ||
896 | void gigaset_shutdown(struct cardstate *cs) | 893 | /* gigaset_shutdown |
894 | * check if a device is associated to the cardstate structure and stop it | ||
895 | * return value: 0 if ok, -1 if no device was associated | ||
896 | */ | ||
897 | int gigaset_shutdown(struct cardstate *cs) | ||
897 | { | 898 | { |
898 | mutex_lock(&cs->mutex); | 899 | mutex_lock(&cs->mutex); |
899 | 900 | ||
901 | if (!(cs->flags & VALID_MINOR)) | ||
902 | return -1; | ||
903 | |||
900 | cs->waiting = 1; | 904 | cs->waiting = 1; |
901 | 905 | ||
902 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { | 906 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { |
@@ -913,6 +917,7 @@ void gigaset_shutdown(struct cardstate *cs) | |||
913 | 917 | ||
914 | exit: | 918 | exit: |
915 | mutex_unlock(&cs->mutex); | 919 | mutex_unlock(&cs->mutex); |
920 | return 0; | ||
916 | } | 921 | } |
917 | EXPORT_SYMBOL_GPL(gigaset_shutdown); | 922 | EXPORT_SYMBOL_GPL(gigaset_shutdown); |
918 | 923 | ||
@@ -954,13 +959,11 @@ struct cardstate *gigaset_get_cs_by_id(int id) | |||
954 | list_for_each_entry(drv, &drivers, list) { | 959 | list_for_each_entry(drv, &drivers, list) { |
955 | spin_lock(&drv->lock); | 960 | spin_lock(&drv->lock); |
956 | for (i = 0; i < drv->minors; ++i) { | 961 | for (i = 0; i < drv->minors; ++i) { |
957 | if (drv->flags[i] & VALID_ID) { | 962 | cs = drv->cs + i; |
958 | cs = drv->cs + i; | 963 | if ((cs->flags & VALID_ID) && cs->myid == id) { |
959 | if (cs->myid == id) | 964 | ret = cs; |
960 | ret = cs; | ||
961 | } | ||
962 | if (ret) | ||
963 | break; | 965 | break; |
966 | } | ||
964 | } | 967 | } |
965 | spin_unlock(&drv->lock); | 968 | spin_unlock(&drv->lock); |
966 | if (ret) | 969 | if (ret) |
@@ -983,10 +986,9 @@ void gigaset_debugdrivers(void) | |||
983 | spin_lock(&drv->lock); | 986 | spin_lock(&drv->lock); |
984 | for (i = 0; i < drv->minors; ++i) { | 987 | for (i = 0; i < drv->minors; ++i) { |
985 | gig_dbg(DEBUG_DRIVER, " index %u", i); | 988 | gig_dbg(DEBUG_DRIVER, " index %u", i); |
986 | gig_dbg(DEBUG_DRIVER, " flags 0x%02x", | ||
987 | drv->flags[i]); | ||
988 | cs = drv->cs + i; | 989 | cs = drv->cs + i; |
989 | gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); | 990 | gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); |
991 | gig_dbg(DEBUG_DRIVER, " flags 0x%02x", cs->flags); | ||
990 | gig_dbg(DEBUG_DRIVER, " minor_index %u", | 992 | gig_dbg(DEBUG_DRIVER, " minor_index %u", |
991 | cs->minor_index); | 993 | cs->minor_index); |
992 | gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); | 994 | gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); |
@@ -1010,7 +1012,7 @@ static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) | |||
1010 | continue; | 1012 | continue; |
1011 | index = minor - drv->minor; | 1013 | index = minor - drv->minor; |
1012 | spin_lock(&drv->lock); | 1014 | spin_lock(&drv->lock); |
1013 | if (drv->flags[index] & VALID_MINOR) | 1015 | if (drv->cs[index].flags & VALID_MINOR) |
1014 | ret = drv->cs + index; | 1016 | ret = drv->cs + index; |
1015 | spin_unlock(&drv->lock); | 1017 | spin_unlock(&drv->lock); |
1016 | if (ret) | 1018 | if (ret) |
@@ -1038,7 +1040,6 @@ void gigaset_freedriver(struct gigaset_driver *drv) | |||
1038 | gigaset_if_freedriver(drv); | 1040 | gigaset_if_freedriver(drv); |
1039 | 1041 | ||
1040 | kfree(drv->cs); | 1042 | kfree(drv->cs); |
1041 | kfree(drv->flags); | ||
1042 | kfree(drv); | 1043 | kfree(drv); |
1043 | } | 1044 | } |
1044 | EXPORT_SYMBOL_GPL(gigaset_freedriver); | 1045 | EXPORT_SYMBOL_GPL(gigaset_freedriver); |
@@ -1080,12 +1081,8 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
1080 | if (!drv->cs) | 1081 | if (!drv->cs) |
1081 | goto error; | 1082 | goto error; |
1082 | 1083 | ||
1083 | drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); | ||
1084 | if (!drv->flags) | ||
1085 | goto error; | ||
1086 | |||
1087 | for (i = 0; i < minors; ++i) { | 1084 | for (i = 0; i < minors; ++i) { |
1088 | drv->flags[i] = 0; | 1085 | drv->cs[i].flags = 0; |
1089 | drv->cs[i].driver = drv; | 1086 | drv->cs[i].driver = drv; |
1090 | drv->cs[i].ops = drv->ops; | 1087 | drv->cs[i].ops = drv->ops; |
1091 | drv->cs[i].minor_index = i; | 1088 | drv->cs[i].minor_index = i; |
@@ -1106,53 +1103,9 @@ error: | |||
1106 | } | 1103 | } |
1107 | EXPORT_SYMBOL_GPL(gigaset_initdriver); | 1104 | EXPORT_SYMBOL_GPL(gigaset_initdriver); |
1108 | 1105 | ||
1109 | /* For drivers without fixed assignment device<->cardstate (usb) */ | ||
1110 | struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) | ||
1111 | { | ||
1112 | unsigned long flags; | ||
1113 | struct cardstate *cs = NULL; | ||
1114 | unsigned i; | ||
1115 | |||
1116 | spin_lock_irqsave(&drv->lock, flags); | ||
1117 | if (drv->blocked) | ||
1118 | goto exit; | ||
1119 | for (i = 0; i < drv->minors; ++i) { | ||
1120 | if ((drv->flags[i] & VALID_MINOR) && | ||
1121 | !(drv->flags[i] & ASSIGNED)) { | ||
1122 | drv->flags[i] |= ASSIGNED; | ||
1123 | cs = drv->cs + i; | ||
1124 | break; | ||
1125 | } | ||
1126 | } | ||
1127 | exit: | ||
1128 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1129 | return cs; | ||
1130 | } | ||
1131 | EXPORT_SYMBOL_GPL(gigaset_getunassignedcs); | ||
1132 | |||
1133 | void gigaset_unassign(struct cardstate *cs) | ||
1134 | { | ||
1135 | unsigned long flags; | ||
1136 | unsigned *minor_flags; | ||
1137 | struct gigaset_driver *drv; | ||
1138 | |||
1139 | if (!cs) | ||
1140 | return; | ||
1141 | drv = cs->driver; | ||
1142 | spin_lock_irqsave(&drv->lock, flags); | ||
1143 | minor_flags = drv->flags + cs->minor_index; | ||
1144 | if (*minor_flags & VALID_MINOR) | ||
1145 | *minor_flags &= ~ASSIGNED; | ||
1146 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1147 | } | ||
1148 | EXPORT_SYMBOL_GPL(gigaset_unassign); | ||
1149 | |||
1150 | void gigaset_blockdriver(struct gigaset_driver *drv) | 1106 | void gigaset_blockdriver(struct gigaset_driver *drv) |
1151 | { | 1107 | { |
1152 | unsigned long flags; | ||
1153 | spin_lock_irqsave(&drv->lock, flags); | ||
1154 | drv->blocked = 1; | 1108 | drv->blocked = 1; |
1155 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1156 | } | 1109 | } |
1157 | EXPORT_SYMBOL_GPL(gigaset_blockdriver); | 1110 | EXPORT_SYMBOL_GPL(gigaset_blockdriver); |
1158 | 1111 | ||
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cec1ef342fcc..5cbf64d850ee 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -735,7 +735,7 @@ static void disconnect(struct at_state_t **at_state_p) | |||
735 | /* revert to selected idle mode */ | 735 | /* revert to selected idle mode */ |
736 | if (!cs->cidmode) { | 736 | if (!cs->cidmode) { |
737 | cs->at_state.pending_commands |= PC_UMMODE; | 737 | cs->at_state.pending_commands |= PC_UMMODE; |
738 | atomic_set(&cs->commands_pending, 1); //FIXME | 738 | cs->commands_pending = 1; |
739 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | 739 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); |
740 | } | 740 | } |
741 | spin_unlock_irqrestore(&cs->lock, flags); | 741 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -793,15 +793,15 @@ static void init_failed(struct cardstate *cs, int mode) | |||
793 | struct at_state_t *at_state; | 793 | struct at_state_t *at_state; |
794 | 794 | ||
795 | cs->at_state.pending_commands &= ~PC_INIT; | 795 | cs->at_state.pending_commands &= ~PC_INIT; |
796 | atomic_set(&cs->mode, mode); | 796 | cs->mode = mode; |
797 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 797 | cs->mstate = MS_UNINITIALIZED; |
798 | gigaset_free_channels(cs); | 798 | gigaset_free_channels(cs); |
799 | for (i = 0; i < cs->channels; ++i) { | 799 | for (i = 0; i < cs->channels; ++i) { |
800 | at_state = &cs->bcs[i].at_state; | 800 | at_state = &cs->bcs[i].at_state; |
801 | if (at_state->pending_commands & PC_CID) { | 801 | if (at_state->pending_commands & PC_CID) { |
802 | at_state->pending_commands &= ~PC_CID; | 802 | at_state->pending_commands &= ~PC_CID; |
803 | at_state->pending_commands |= PC_NOCID; | 803 | at_state->pending_commands |= PC_NOCID; |
804 | atomic_set(&cs->commands_pending, 1); | 804 | cs->commands_pending = 1; |
805 | } | 805 | } |
806 | } | 806 | } |
807 | } | 807 | } |
@@ -812,11 +812,11 @@ static void schedule_init(struct cardstate *cs, int state) | |||
812 | gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); | 812 | gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); |
813 | return; | 813 | return; |
814 | } | 814 | } |
815 | atomic_set(&cs->mstate, state); | 815 | cs->mstate = state; |
816 | atomic_set(&cs->mode, M_UNKNOWN); | 816 | cs->mode = M_UNKNOWN; |
817 | gigaset_block_channels(cs); | 817 | gigaset_block_channels(cs); |
818 | cs->at_state.pending_commands |= PC_INIT; | 818 | cs->at_state.pending_commands |= PC_INIT; |
819 | atomic_set(&cs->commands_pending, 1); | 819 | cs->commands_pending = 1; |
820 | gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); | 820 | gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); |
821 | } | 821 | } |
822 | 822 | ||
@@ -953,13 +953,13 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind | |||
953 | 953 | ||
954 | at_state->pending_commands |= PC_CID; | 954 | at_state->pending_commands |= PC_CID; |
955 | gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); | 955 | gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); |
956 | atomic_set(&cs->commands_pending, 1); | 956 | cs->commands_pending = 1; |
957 | return; | 957 | return; |
958 | 958 | ||
959 | error: | 959 | error: |
960 | at_state->pending_commands |= PC_NOCID; | 960 | at_state->pending_commands |= PC_NOCID; |
961 | gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); | 961 | gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); |
962 | atomic_set(&cs->commands_pending, 1); | 962 | cs->commands_pending = 1; |
963 | return; | 963 | return; |
964 | } | 964 | } |
965 | 965 | ||
@@ -973,12 +973,12 @@ static void start_accept(struct at_state_t *at_state) | |||
973 | if (retval == 0) { | 973 | if (retval == 0) { |
974 | at_state->pending_commands |= PC_ACCEPT; | 974 | at_state->pending_commands |= PC_ACCEPT; |
975 | gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); | 975 | gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); |
976 | atomic_set(&cs->commands_pending, 1); | 976 | cs->commands_pending = 1; |
977 | } else { | 977 | } else { |
978 | //FIXME | 978 | /* error reset */ |
979 | at_state->pending_commands |= PC_HUP; | 979 | at_state->pending_commands |= PC_HUP; |
980 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 980 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); |
981 | atomic_set(&cs->commands_pending, 1); | 981 | cs->commands_pending = 1; |
982 | } | 982 | } |
983 | } | 983 | } |
984 | 984 | ||
@@ -986,7 +986,7 @@ static void do_start(struct cardstate *cs) | |||
986 | { | 986 | { |
987 | gigaset_free_channels(cs); | 987 | gigaset_free_channels(cs); |
988 | 988 | ||
989 | if (atomic_read(&cs->mstate) != MS_LOCKED) | 989 | if (cs->mstate != MS_LOCKED) |
990 | schedule_init(cs, MS_INIT); | 990 | schedule_init(cs, MS_INIT); |
991 | 991 | ||
992 | cs->isdn_up = 1; | 992 | cs->isdn_up = 1; |
@@ -1000,9 +1000,9 @@ static void do_start(struct cardstate *cs) | |||
1000 | 1000 | ||
1001 | static void finish_shutdown(struct cardstate *cs) | 1001 | static void finish_shutdown(struct cardstate *cs) |
1002 | { | 1002 | { |
1003 | if (atomic_read(&cs->mstate) != MS_LOCKED) { | 1003 | if (cs->mstate != MS_LOCKED) { |
1004 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 1004 | cs->mstate = MS_UNINITIALIZED; |
1005 | atomic_set(&cs->mode, M_UNKNOWN); | 1005 | cs->mode = M_UNKNOWN; |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | /* Tell the LL that the device is not available .. */ | 1008 | /* Tell the LL that the device is not available .. */ |
@@ -1022,10 +1022,10 @@ static void do_shutdown(struct cardstate *cs) | |||
1022 | { | 1022 | { |
1023 | gigaset_block_channels(cs); | 1023 | gigaset_block_channels(cs); |
1024 | 1024 | ||
1025 | if (atomic_read(&cs->mstate) == MS_READY) { | 1025 | if (cs->mstate == MS_READY) { |
1026 | atomic_set(&cs->mstate, MS_SHUTDOWN); | 1026 | cs->mstate = MS_SHUTDOWN; |
1027 | cs->at_state.pending_commands |= PC_SHUTDOWN; | 1027 | cs->at_state.pending_commands |= PC_SHUTDOWN; |
1028 | atomic_set(&cs->commands_pending, 1); | 1028 | cs->commands_pending = 1; |
1029 | gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); | 1029 | gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); |
1030 | } else | 1030 | } else |
1031 | finish_shutdown(cs); | 1031 | finish_shutdown(cs); |
@@ -1120,7 +1120,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs, | |||
1120 | * In fact it doesn't. | 1120 | * In fact it doesn't. |
1121 | */ | 1121 | */ |
1122 | at_state->pending_commands |= PC_HUP; | 1122 | at_state->pending_commands |= PC_HUP; |
1123 | atomic_set(&cs->commands_pending, 1); | 1123 | cs->commands_pending = 1; |
1124 | break; | 1124 | break; |
1125 | } | 1125 | } |
1126 | } | 1126 | } |
@@ -1130,7 +1130,7 @@ static int do_lock(struct cardstate *cs) | |||
1130 | int mode; | 1130 | int mode; |
1131 | int i; | 1131 | int i; |
1132 | 1132 | ||
1133 | switch (atomic_read(&cs->mstate)) { | 1133 | switch (cs->mstate) { |
1134 | case MS_UNINITIALIZED: | 1134 | case MS_UNINITIALIZED: |
1135 | case MS_READY: | 1135 | case MS_READY: |
1136 | if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || | 1136 | if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || |
@@ -1152,20 +1152,20 @@ static int do_lock(struct cardstate *cs) | |||
1152 | return -EBUSY; | 1152 | return -EBUSY; |
1153 | } | 1153 | } |
1154 | 1154 | ||
1155 | mode = atomic_read(&cs->mode); | 1155 | mode = cs->mode; |
1156 | atomic_set(&cs->mstate, MS_LOCKED); | 1156 | cs->mstate = MS_LOCKED; |
1157 | atomic_set(&cs->mode, M_UNKNOWN); | 1157 | cs->mode = M_UNKNOWN; |
1158 | 1158 | ||
1159 | return mode; | 1159 | return mode; |
1160 | } | 1160 | } |
1161 | 1161 | ||
1162 | static int do_unlock(struct cardstate *cs) | 1162 | static int do_unlock(struct cardstate *cs) |
1163 | { | 1163 | { |
1164 | if (atomic_read(&cs->mstate) != MS_LOCKED) | 1164 | if (cs->mstate != MS_LOCKED) |
1165 | return -EINVAL; | 1165 | return -EINVAL; |
1166 | 1166 | ||
1167 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 1167 | cs->mstate = MS_UNINITIALIZED; |
1168 | atomic_set(&cs->mode, M_UNKNOWN); | 1168 | cs->mode = M_UNKNOWN; |
1169 | gigaset_free_channels(cs); | 1169 | gigaset_free_channels(cs); |
1170 | if (cs->connected) | 1170 | if (cs->connected) |
1171 | schedule_init(cs, MS_INIT); | 1171 | schedule_init(cs, MS_INIT); |
@@ -1198,17 +1198,17 @@ static void do_action(int action, struct cardstate *cs, | |||
1198 | case ACT_INIT: | 1198 | case ACT_INIT: |
1199 | cs->at_state.pending_commands &= ~PC_INIT; | 1199 | cs->at_state.pending_commands &= ~PC_INIT; |
1200 | cs->cur_at_seq = SEQ_NONE; | 1200 | cs->cur_at_seq = SEQ_NONE; |
1201 | atomic_set(&cs->mode, M_UNIMODEM); | 1201 | cs->mode = M_UNIMODEM; |
1202 | spin_lock_irqsave(&cs->lock, flags); | 1202 | spin_lock_irqsave(&cs->lock, flags); |
1203 | if (!cs->cidmode) { | 1203 | if (!cs->cidmode) { |
1204 | spin_unlock_irqrestore(&cs->lock, flags); | 1204 | spin_unlock_irqrestore(&cs->lock, flags); |
1205 | gigaset_free_channels(cs); | 1205 | gigaset_free_channels(cs); |
1206 | atomic_set(&cs->mstate, MS_READY); | 1206 | cs->mstate = MS_READY; |
1207 | break; | 1207 | break; |
1208 | } | 1208 | } |
1209 | spin_unlock_irqrestore(&cs->lock, flags); | 1209 | spin_unlock_irqrestore(&cs->lock, flags); |
1210 | cs->at_state.pending_commands |= PC_CIDMODE; | 1210 | cs->at_state.pending_commands |= PC_CIDMODE; |
1211 | atomic_set(&cs->commands_pending, 1); | 1211 | cs->commands_pending = 1; |
1212 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 1212 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); |
1213 | break; | 1213 | break; |
1214 | case ACT_FAILINIT: | 1214 | case ACT_FAILINIT: |
@@ -1234,22 +1234,20 @@ static void do_action(int action, struct cardstate *cs, | |||
1234 | | INS_command; | 1234 | | INS_command; |
1235 | break; | 1235 | break; |
1236 | case ACT_CMODESET: | 1236 | case ACT_CMODESET: |
1237 | if (atomic_read(&cs->mstate) == MS_INIT || | 1237 | if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { |
1238 | atomic_read(&cs->mstate) == MS_RECOVER) { | ||
1239 | gigaset_free_channels(cs); | 1238 | gigaset_free_channels(cs); |
1240 | atomic_set(&cs->mstate, MS_READY); | 1239 | cs->mstate = MS_READY; |
1241 | } | 1240 | } |
1242 | atomic_set(&cs->mode, M_CID); | 1241 | cs->mode = M_CID; |
1243 | cs->cur_at_seq = SEQ_NONE; | 1242 | cs->cur_at_seq = SEQ_NONE; |
1244 | break; | 1243 | break; |
1245 | case ACT_UMODESET: | 1244 | case ACT_UMODESET: |
1246 | atomic_set(&cs->mode, M_UNIMODEM); | 1245 | cs->mode = M_UNIMODEM; |
1247 | cs->cur_at_seq = SEQ_NONE; | 1246 | cs->cur_at_seq = SEQ_NONE; |
1248 | break; | 1247 | break; |
1249 | case ACT_FAILCMODE: | 1248 | case ACT_FAILCMODE: |
1250 | cs->cur_at_seq = SEQ_NONE; | 1249 | cs->cur_at_seq = SEQ_NONE; |
1251 | if (atomic_read(&cs->mstate) == MS_INIT || | 1250 | if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { |
1252 | atomic_read(&cs->mstate) == MS_RECOVER) { | ||
1253 | init_failed(cs, M_UNKNOWN); | 1251 | init_failed(cs, M_UNKNOWN); |
1254 | break; | 1252 | break; |
1255 | } | 1253 | } |
@@ -1307,7 +1305,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1307 | case ACT_CONNECT: | 1305 | case ACT_CONNECT: |
1308 | if (cs->onechannel) { | 1306 | if (cs->onechannel) { |
1309 | at_state->pending_commands |= PC_DLE1; | 1307 | at_state->pending_commands |= PC_DLE1; |
1310 | atomic_set(&cs->commands_pending, 1); | 1308 | cs->commands_pending = 1; |
1311 | break; | 1309 | break; |
1312 | } | 1310 | } |
1313 | bcs->chstate |= CHS_D_UP; | 1311 | bcs->chstate |= CHS_D_UP; |
@@ -1333,7 +1331,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1333 | * DLE only used for M10x with one B channel. | 1331 | * DLE only used for M10x with one B channel. |
1334 | */ | 1332 | */ |
1335 | at_state->pending_commands |= PC_DLE0; | 1333 | at_state->pending_commands |= PC_DLE0; |
1336 | atomic_set(&cs->commands_pending, 1); | 1334 | cs->commands_pending = 1; |
1337 | } else | 1335 | } else |
1338 | disconnect(p_at_state); | 1336 | disconnect(p_at_state); |
1339 | break; | 1337 | break; |
@@ -1369,7 +1367,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1369 | "Could not enter DLE mode. Trying to hang up.\n"); | 1367 | "Could not enter DLE mode. Trying to hang up.\n"); |
1370 | channel = cs->curchannel; | 1368 | channel = cs->curchannel; |
1371 | cs->bcs[channel].at_state.pending_commands |= PC_HUP; | 1369 | cs->bcs[channel].at_state.pending_commands |= PC_HUP; |
1372 | atomic_set(&cs->commands_pending, 1); | 1370 | cs->commands_pending = 1; |
1373 | break; | 1371 | break; |
1374 | 1372 | ||
1375 | case ACT_CID: /* got cid; start dialing */ | 1373 | case ACT_CID: /* got cid; start dialing */ |
@@ -1379,7 +1377,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1379 | cs->bcs[channel].at_state.cid = ev->parameter; | 1377 | cs->bcs[channel].at_state.cid = ev->parameter; |
1380 | cs->bcs[channel].at_state.pending_commands |= | 1378 | cs->bcs[channel].at_state.pending_commands |= |
1381 | PC_DIAL; | 1379 | PC_DIAL; |
1382 | atomic_set(&cs->commands_pending, 1); | 1380 | cs->commands_pending = 1; |
1383 | break; | 1381 | break; |
1384 | } | 1382 | } |
1385 | /* fall through */ | 1383 | /* fall through */ |
@@ -1411,14 +1409,14 @@ static void do_action(int action, struct cardstate *cs, | |||
1411 | case ACT_ABORTDIAL: /* error/timeout during dial preparation */ | 1409 | case ACT_ABORTDIAL: /* error/timeout during dial preparation */ |
1412 | cs->cur_at_seq = SEQ_NONE; | 1410 | cs->cur_at_seq = SEQ_NONE; |
1413 | at_state->pending_commands |= PC_HUP; | 1411 | at_state->pending_commands |= PC_HUP; |
1414 | atomic_set(&cs->commands_pending, 1); | 1412 | cs->commands_pending = 1; |
1415 | break; | 1413 | break; |
1416 | 1414 | ||
1417 | case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ | 1415 | case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ |
1418 | case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ | 1416 | case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ |
1419 | case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ | 1417 | case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ |
1420 | at_state->pending_commands |= PC_HUP; | 1418 | at_state->pending_commands |= PC_HUP; |
1421 | atomic_set(&cs->commands_pending, 1); | 1419 | cs->commands_pending = 1; |
1422 | break; | 1420 | break; |
1423 | case ACT_GETSTRING: /* warning: RING, ZDLE, ... | 1421 | case ACT_GETSTRING: /* warning: RING, ZDLE, ... |
1424 | are not handled properly anymore */ | 1422 | are not handled properly anymore */ |
@@ -1515,7 +1513,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1515 | break; | 1513 | break; |
1516 | case ACT_HUP: | 1514 | case ACT_HUP: |
1517 | at_state->pending_commands |= PC_HUP; | 1515 | at_state->pending_commands |= PC_HUP; |
1518 | atomic_set(&cs->commands_pending, 1); | 1516 | cs->commands_pending = 1; |
1519 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 1517 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); |
1520 | break; | 1518 | break; |
1521 | 1519 | ||
@@ -1558,7 +1556,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1558 | cs->at_state.pending_commands |= PC_UMMODE; | 1556 | cs->at_state.pending_commands |= PC_UMMODE; |
1559 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | 1557 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); |
1560 | } | 1558 | } |
1561 | atomic_set(&cs->commands_pending, 1); | 1559 | cs->commands_pending = 1; |
1562 | } | 1560 | } |
1563 | spin_unlock_irqrestore(&cs->lock, flags); | 1561 | spin_unlock_irqrestore(&cs->lock, flags); |
1564 | cs->waiting = 0; | 1562 | cs->waiting = 0; |
@@ -1741,7 +1739,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1741 | int sequence; | 1739 | int sequence; |
1742 | unsigned long flags; | 1740 | unsigned long flags; |
1743 | 1741 | ||
1744 | atomic_set(&cs->commands_pending, 0); | 1742 | cs->commands_pending = 0; |
1745 | 1743 | ||
1746 | if (cs->cur_at_seq) { | 1744 | if (cs->cur_at_seq) { |
1747 | gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); | 1745 | gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); |
@@ -1779,7 +1777,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1779 | ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); | 1777 | ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); |
1780 | if (at_state->cid > 0) | 1778 | if (at_state->cid > 0) |
1781 | at_state->pending_commands |= PC_HUP; | 1779 | at_state->pending_commands |= PC_HUP; |
1782 | if (atomic_read(&cs->mstate) == MS_RECOVER) { | 1780 | if (cs->mstate == MS_RECOVER) { |
1783 | if (at_state->pending_commands & PC_CID) { | 1781 | if (at_state->pending_commands & PC_CID) { |
1784 | at_state->pending_commands |= PC_NOCID; | 1782 | at_state->pending_commands |= PC_NOCID; |
1785 | at_state->pending_commands &= ~PC_CID; | 1783 | at_state->pending_commands &= ~PC_CID; |
@@ -1793,7 +1791,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1793 | if (cs->at_state.pending_commands == PC_UMMODE | 1791 | if (cs->at_state.pending_commands == PC_UMMODE |
1794 | && !cs->cidmode | 1792 | && !cs->cidmode |
1795 | && list_empty(&cs->temp_at_states) | 1793 | && list_empty(&cs->temp_at_states) |
1796 | && atomic_read(&cs->mode) == M_CID) { | 1794 | && cs->mode == M_CID) { |
1797 | sequence = SEQ_UMMODE; | 1795 | sequence = SEQ_UMMODE; |
1798 | at_state = &cs->at_state; | 1796 | at_state = &cs->at_state; |
1799 | for (i = 0; i < cs->channels; ++i) { | 1797 | for (i = 0; i < cs->channels; ++i) { |
@@ -1860,7 +1858,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1860 | } | 1858 | } |
1861 | if (cs->at_state.pending_commands & PC_CIDMODE) { | 1859 | if (cs->at_state.pending_commands & PC_CIDMODE) { |
1862 | cs->at_state.pending_commands &= ~PC_CIDMODE; | 1860 | cs->at_state.pending_commands &= ~PC_CIDMODE; |
1863 | if (atomic_read(&cs->mode) == M_UNIMODEM) { | 1861 | if (cs->mode == M_UNIMODEM) { |
1864 | cs->retry_count = 1; | 1862 | cs->retry_count = 1; |
1865 | schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); | 1863 | schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); |
1866 | return; | 1864 | return; |
@@ -1886,11 +1884,11 @@ static void process_command_flags(struct cardstate *cs) | |||
1886 | return; | 1884 | return; |
1887 | } | 1885 | } |
1888 | if (bcs->at_state.pending_commands & PC_CID) { | 1886 | if (bcs->at_state.pending_commands & PC_CID) { |
1889 | switch (atomic_read(&cs->mode)) { | 1887 | switch (cs->mode) { |
1890 | case M_UNIMODEM: | 1888 | case M_UNIMODEM: |
1891 | cs->at_state.pending_commands |= PC_CIDMODE; | 1889 | cs->at_state.pending_commands |= PC_CIDMODE; |
1892 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 1890 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); |
1893 | atomic_set(&cs->commands_pending, 1); | 1891 | cs->commands_pending = 1; |
1894 | return; | 1892 | return; |
1895 | #ifdef GIG_MAYINITONDIAL | 1893 | #ifdef GIG_MAYINITONDIAL |
1896 | case M_UNKNOWN: | 1894 | case M_UNKNOWN: |
@@ -1926,7 +1924,7 @@ static void process_events(struct cardstate *cs) | |||
1926 | for (i = 0; i < 2 * MAX_EVENTS; ++i) { | 1924 | for (i = 0; i < 2 * MAX_EVENTS; ++i) { |
1927 | tail = cs->ev_tail; | 1925 | tail = cs->ev_tail; |
1928 | if (tail == head) { | 1926 | if (tail == head) { |
1929 | if (!check_flags && !atomic_read(&cs->commands_pending)) | 1927 | if (!check_flags && !cs->commands_pending) |
1930 | break; | 1928 | break; |
1931 | check_flags = 0; | 1929 | check_flags = 0; |
1932 | spin_unlock_irqrestore(&cs->ev_lock, flags); | 1930 | spin_unlock_irqrestore(&cs->ev_lock, flags); |
@@ -1934,7 +1932,7 @@ static void process_events(struct cardstate *cs) | |||
1934 | spin_lock_irqsave(&cs->ev_lock, flags); | 1932 | spin_lock_irqsave(&cs->ev_lock, flags); |
1935 | tail = cs->ev_tail; | 1933 | tail = cs->ev_tail; |
1936 | if (tail == head) { | 1934 | if (tail == head) { |
1937 | if (!atomic_read(&cs->commands_pending)) | 1935 | if (!cs->commands_pending) |
1938 | break; | 1936 | break; |
1939 | continue; | 1937 | continue; |
1940 | } | 1938 | } |
@@ -1971,7 +1969,7 @@ void gigaset_handle_event(unsigned long data) | |||
1971 | struct cardstate *cs = (struct cardstate *) data; | 1969 | struct cardstate *cs = (struct cardstate *) data; |
1972 | 1970 | ||
1973 | /* handle incoming data on control/common channel */ | 1971 | /* handle incoming data on control/common channel */ |
1974 | if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) { | 1972 | if (cs->inbuf->head != cs->inbuf->tail) { |
1975 | gig_dbg(DEBUG_INTR, "processing new data"); | 1973 | gig_dbg(DEBUG_INTR, "processing new data"); |
1976 | cs->ops->handle_input(cs->inbuf); | 1974 | cs->ops->handle_input(cs->inbuf); |
1977 | } | 1975 | } |
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 02bdaf22d7ea..f365993161fc 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -70,22 +70,13 @@ | |||
70 | 70 | ||
71 | extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ | 71 | extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ |
72 | 72 | ||
73 | /* any combination of these can be given with the 'debug=' parameter to insmod, | 73 | /* debug flags, combine by adding/bitwise OR */ |
74 | * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and | ||
75 | * DEBUG_INTR. | ||
76 | */ | ||
77 | enum debuglevel { | 74 | enum debuglevel { |
78 | DEBUG_REG = 0x0002, /* serial port I/O register operations */ | 75 | DEBUG_INTR = 0x00008, /* interrupt processing */ |
79 | DEBUG_OPEN = 0x0004, /* open/close serial port */ | ||
80 | DEBUG_INTR = 0x0008, /* interrupt processing */ | ||
81 | DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on | ||
82 | interrupt requests, not available as | ||
83 | run-time option */ | ||
84 | DEBUG_CMD = 0x00020, /* sent/received LL commands */ | 76 | DEBUG_CMD = 0x00020, /* sent/received LL commands */ |
85 | DEBUG_STREAM = 0x00040, /* application data stream I/O events */ | 77 | DEBUG_STREAM = 0x00040, /* application data stream I/O events */ |
86 | DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ | 78 | DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ |
87 | DEBUG_LLDATA = 0x00100, /* sent/received LL data */ | 79 | DEBUG_LLDATA = 0x00100, /* sent/received LL data */ |
88 | DEBUG_INTR_0 = 0x00200, /* serial port interrupt processing */ | ||
89 | DEBUG_DRIVER = 0x00400, /* driver structure */ | 80 | DEBUG_DRIVER = 0x00400, /* driver structure */ |
90 | DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ | 81 | DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ |
91 | DEBUG_WRITE = 0x01000, /* M105 data write */ | 82 | DEBUG_WRITE = 0x01000, /* M105 data write */ |
@@ -93,7 +84,7 @@ enum debuglevel { | |||
93 | DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ | 84 | DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ |
94 | DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data | 85 | DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data |
95 | structures */ | 86 | structures */ |
96 | DEBUG_LOCK = 0x10000, /* semaphore operations */ | 87 | DEBUG_SUSPEND = 0x10000, /* suspend/resume processing */ |
97 | DEBUG_OUTPUT = 0x20000, /* output to device */ | 88 | DEBUG_OUTPUT = 0x20000, /* output to device */ |
98 | DEBUG_ISO = 0x40000, /* isochronous transfers */ | 89 | DEBUG_ISO = 0x40000, /* isochronous transfers */ |
99 | DEBUG_IF = 0x80000, /* character device operations */ | 90 | DEBUG_IF = 0x80000, /* character device operations */ |
@@ -191,6 +182,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
191 | #define HD_OPEN_ATCHANNEL (0x28) // 3070 | 182 | #define HD_OPEN_ATCHANNEL (0x28) // 3070 |
192 | #define HD_CLOSE_ATCHANNEL (0x29) // 3070 | 183 | #define HD_CLOSE_ATCHANNEL (0x29) // 3070 |
193 | 184 | ||
185 | /* number of B channels supported by base driver */ | ||
186 | #define BAS_CHANNELS 2 | ||
187 | |||
194 | /* USB frames for isochronous transfer */ | 188 | /* USB frames for isochronous transfer */ |
195 | #define BAS_FRAMETIME 1 /* number of milliseconds between frames */ | 189 | #define BAS_FRAMETIME 1 /* number of milliseconds between frames */ |
196 | #define BAS_NUMFRAMES 8 /* number of frames per URB */ | 190 | #define BAS_NUMFRAMES 8 /* number of frames per URB */ |
@@ -313,7 +307,7 @@ struct inbuf_t { | |||
313 | struct bc_state *bcs; | 307 | struct bc_state *bcs; |
314 | struct cardstate *cs; | 308 | struct cardstate *cs; |
315 | int inputstate; | 309 | int inputstate; |
316 | atomic_t head, tail; | 310 | int head, tail; |
317 | unsigned char data[RBUFSIZE]; | 311 | unsigned char data[RBUFSIZE]; |
318 | }; | 312 | }; |
319 | 313 | ||
@@ -335,9 +329,9 @@ struct inbuf_t { | |||
335 | * are also filled with that value | 329 | * are also filled with that value |
336 | */ | 330 | */ |
337 | struct isowbuf_t { | 331 | struct isowbuf_t { |
338 | atomic_t read; | 332 | int read; |
339 | atomic_t nextread; | 333 | int nextread; |
340 | atomic_t write; | 334 | int write; |
341 | atomic_t writesem; | 335 | atomic_t writesem; |
342 | int wbits; | 336 | int wbits; |
343 | unsigned char data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD]; | 337 | unsigned char data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD]; |
@@ -350,11 +344,13 @@ struct isowbuf_t { | |||
350 | * - urb: pointer to the URB itself | 344 | * - urb: pointer to the URB itself |
351 | * - bcs: pointer to the B Channel control structure | 345 | * - bcs: pointer to the B Channel control structure |
352 | * - limit: end of write buffer area covered by this URB | 346 | * - limit: end of write buffer area covered by this URB |
347 | * - status: URB completion status | ||
353 | */ | 348 | */ |
354 | struct isow_urbctx_t { | 349 | struct isow_urbctx_t { |
355 | struct urb *urb; | 350 | struct urb *urb; |
356 | struct bc_state *bcs; | 351 | struct bc_state *bcs; |
357 | int limit; | 352 | int limit; |
353 | int status; | ||
358 | }; | 354 | }; |
359 | 355 | ||
360 | /* AT state structure | 356 | /* AT state structure |
@@ -439,14 +435,15 @@ struct cardstate { | |||
439 | unsigned minor_index; | 435 | unsigned minor_index; |
440 | struct device *dev; | 436 | struct device *dev; |
441 | struct device *tty_dev; | 437 | struct device *tty_dev; |
438 | unsigned flags; | ||
442 | 439 | ||
443 | const struct gigaset_ops *ops; | 440 | const struct gigaset_ops *ops; |
444 | 441 | ||
445 | /* Stuff to handle communication */ | 442 | /* Stuff to handle communication */ |
446 | wait_queue_head_t waitqueue; | 443 | wait_queue_head_t waitqueue; |
447 | int waiting; | 444 | int waiting; |
448 | atomic_t mode; /* see M_XXXX */ | 445 | int mode; /* see M_XXXX */ |
449 | atomic_t mstate; /* Modem state: see MS_XXXX */ | 446 | int mstate; /* Modem state: see MS_XXXX */ |
450 | /* only changed by the event layer */ | 447 | /* only changed by the event layer */ |
451 | int cmd_result; | 448 | int cmd_result; |
452 | 449 | ||
@@ -503,7 +500,7 @@ struct cardstate { | |||
503 | processed */ | 500 | processed */ |
504 | int curchannel; /* channel those commands are meant | 501 | int curchannel; /* channel those commands are meant |
505 | for */ | 502 | for */ |
506 | atomic_t commands_pending; /* flag(s) in xxx.commands_pending have | 503 | int commands_pending; /* flag(s) in xxx.commands_pending have |
507 | been set */ | 504 | been set */ |
508 | struct tasklet_struct event_tasklet; | 505 | struct tasklet_struct event_tasklet; |
509 | /* tasklet for serializing AT commands. | 506 | /* tasklet for serializing AT commands. |
@@ -543,7 +540,6 @@ struct gigaset_driver { | |||
543 | unsigned minor; | 540 | unsigned minor; |
544 | unsigned minors; | 541 | unsigned minors; |
545 | struct cardstate *cs; | 542 | struct cardstate *cs; |
546 | unsigned *flags; | ||
547 | int blocked; | 543 | int blocked; |
548 | 544 | ||
549 | const struct gigaset_ops *ops; | 545 | const struct gigaset_ops *ops; |
@@ -559,7 +555,7 @@ struct cmdbuf_t { | |||
559 | 555 | ||
560 | struct bas_bc_state { | 556 | struct bas_bc_state { |
561 | /* isochronous output state */ | 557 | /* isochronous output state */ |
562 | atomic_t running; | 558 | int running; |
563 | atomic_t corrbytes; | 559 | atomic_t corrbytes; |
564 | spinlock_t isooutlock; | 560 | spinlock_t isooutlock; |
565 | struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; | 561 | struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; |
@@ -574,6 +570,7 @@ struct bas_bc_state { | |||
574 | struct urb *isoinurbs[BAS_INURBS]; | 570 | struct urb *isoinurbs[BAS_INURBS]; |
575 | unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; | 571 | unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; |
576 | struct urb *isoindone; /* completed isoc read URB */ | 572 | struct urb *isoindone; /* completed isoc read URB */ |
573 | int isoinstatus; /* status of completed URB */ | ||
577 | int loststatus; /* status of dropped URB */ | 574 | int loststatus; /* status of dropped URB */ |
578 | unsigned isoinlost; /* number of bytes lost */ | 575 | unsigned isoinlost; /* number of bytes lost */ |
579 | /* state of bit unstuffing algorithm | 576 | /* state of bit unstuffing algorithm |
@@ -770,10 +767,6 @@ void gigaset_freedriver(struct gigaset_driver *drv); | |||
770 | void gigaset_debugdrivers(void); | 767 | void gigaset_debugdrivers(void); |
771 | struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); | 768 | struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); |
772 | struct cardstate *gigaset_get_cs_by_id(int id); | 769 | struct cardstate *gigaset_get_cs_by_id(int id); |
773 | |||
774 | /* For drivers without fixed assignment device<->cardstate (usb) */ | ||
775 | struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv); | ||
776 | void gigaset_unassign(struct cardstate *cs); | ||
777 | void gigaset_blockdriver(struct gigaset_driver *drv); | 770 | void gigaset_blockdriver(struct gigaset_driver *drv); |
778 | 771 | ||
779 | /* Allocate and initialize card state. Calls hardware dependent | 772 | /* Allocate and initialize card state. Calls hardware dependent |
@@ -792,7 +785,7 @@ int gigaset_start(struct cardstate *cs); | |||
792 | void gigaset_stop(struct cardstate *cs); | 785 | void gigaset_stop(struct cardstate *cs); |
793 | 786 | ||
794 | /* Tell common.c that the driver is being unloaded. */ | 787 | /* Tell common.c that the driver is being unloaded. */ |
795 | void gigaset_shutdown(struct cardstate *cs); | 788 | int gigaset_shutdown(struct cardstate *cs); |
796 | 789 | ||
797 | /* Tell common.c that an skb has been sent. */ | 790 | /* Tell common.c that an skb has been sent. */ |
798 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); | 791 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); |
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index eb50f3dab5f7..af195b07c191 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c | |||
@@ -28,12 +28,11 @@ static int if_lock(struct cardstate *cs, int *arg) | |||
28 | return -EINVAL; | 28 | return -EINVAL; |
29 | 29 | ||
30 | if (cmd < 0) { | 30 | if (cmd < 0) { |
31 | *arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove? | 31 | *arg = cs->mstate == MS_LOCKED; |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED | 35 | if (!cmd && cs->mstate == MS_LOCKED && cs->connected) { |
36 | && cs->connected) { | ||
37 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); | 36 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); |
38 | cs->ops->baud_rate(cs, B115200); | 37 | cs->ops->baud_rate(cs, B115200); |
39 | cs->ops->set_line_ctrl(cs, CS8); | 38 | cs->ops->set_line_ctrl(cs, CS8); |
@@ -104,7 +103,7 @@ static int if_config(struct cardstate *cs, int *arg) | |||
104 | if (*arg != 1) | 103 | if (*arg != 1) |
105 | return -EINVAL; | 104 | return -EINVAL; |
106 | 105 | ||
107 | if (atomic_read(&cs->mstate) != MS_LOCKED) | 106 | if (cs->mstate != MS_LOCKED) |
108 | return -EBUSY; | 107 | return -EBUSY; |
109 | 108 | ||
110 | if (!cs->connected) { | 109 | if (!cs->connected) { |
@@ -162,7 +161,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) | |||
162 | tty->driver_data = NULL; | 161 | tty->driver_data = NULL; |
163 | 162 | ||
164 | cs = gigaset_get_cs_by_tty(tty); | 163 | cs = gigaset_get_cs_by_tty(tty); |
165 | if (!cs) | 164 | if (!cs || !try_module_get(cs->driver->owner)) |
166 | return -ENODEV; | 165 | return -ENODEV; |
167 | 166 | ||
168 | if (mutex_lock_interruptible(&cs->mutex)) | 167 | if (mutex_lock_interruptible(&cs->mutex)) |
@@ -208,6 +207,8 @@ static void if_close(struct tty_struct *tty, struct file *filp) | |||
208 | } | 207 | } |
209 | 208 | ||
210 | mutex_unlock(&cs->mutex); | 209 | mutex_unlock(&cs->mutex); |
210 | |||
211 | module_put(cs->driver->owner); | ||
211 | } | 212 | } |
212 | 213 | ||
213 | static int if_ioctl(struct tty_struct *tty, struct file *file, | 214 | static int if_ioctl(struct tty_struct *tty, struct file *file, |
@@ -364,7 +365,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
364 | 365 | ||
365 | if (!cs->open_count) | 366 | if (!cs->open_count) |
366 | warn("%s: device not opened", __func__); | 367 | warn("%s: device not opened", __func__); |
367 | else if (atomic_read(&cs->mstate) != MS_LOCKED) { | 368 | else if (cs->mstate != MS_LOCKED) { |
368 | warn("can't write to unlocked device"); | 369 | warn("can't write to unlocked device"); |
369 | retval = -EBUSY; | 370 | retval = -EBUSY; |
370 | } else if (!cs->connected) { | 371 | } else if (!cs->connected) { |
@@ -398,9 +399,9 @@ static int if_write_room(struct tty_struct *tty) | |||
398 | 399 | ||
399 | if (!cs->open_count) | 400 | if (!cs->open_count) |
400 | warn("%s: device not opened", __func__); | 401 | warn("%s: device not opened", __func__); |
401 | else if (atomic_read(&cs->mstate) != MS_LOCKED) { | 402 | else if (cs->mstate != MS_LOCKED) { |
402 | warn("can't write to unlocked device"); | 403 | warn("can't write to unlocked device"); |
403 | retval = -EBUSY; //FIXME | 404 | retval = -EBUSY; |
404 | } else if (!cs->connected) { | 405 | } else if (!cs->connected) { |
405 | gig_dbg(DEBUG_ANY, "can't write to unplugged device"); | 406 | gig_dbg(DEBUG_ANY, "can't write to unplugged device"); |
406 | retval = -EBUSY; //FIXME | 407 | retval = -EBUSY; //FIXME |
@@ -430,7 +431,7 @@ static int if_chars_in_buffer(struct tty_struct *tty) | |||
430 | 431 | ||
431 | if (!cs->open_count) | 432 | if (!cs->open_count) |
432 | warn("%s: device not opened", __func__); | 433 | warn("%s: device not opened", __func__); |
433 | else if (atomic_read(&cs->mstate) != MS_LOCKED) { | 434 | else if (cs->mstate != MS_LOCKED) { |
434 | warn("can't write to unlocked device"); | 435 | warn("can't write to unlocked device"); |
435 | retval = -EBUSY; | 436 | retval = -EBUSY; |
436 | } else if (!cs->connected) { | 437 | } else if (!cs->connected) { |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index e0505f238807..e30a7773f93c 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
@@ -23,9 +23,9 @@ | |||
23 | */ | 23 | */ |
24 | void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) | 24 | void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) |
25 | { | 25 | { |
26 | atomic_set(&iwb->read, 0); | 26 | iwb->read = 0; |
27 | atomic_set(&iwb->nextread, 0); | 27 | iwb->nextread = 0; |
28 | atomic_set(&iwb->write, 0); | 28 | iwb->write = 0; |
29 | atomic_set(&iwb->writesem, 1); | 29 | atomic_set(&iwb->writesem, 1); |
30 | iwb->wbits = 0; | 30 | iwb->wbits = 0; |
31 | iwb->idle = idle; | 31 | iwb->idle = idle; |
@@ -39,8 +39,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) | |||
39 | { | 39 | { |
40 | int read, write, freebytes; | 40 | int read, write, freebytes; |
41 | 41 | ||
42 | read = atomic_read(&iwb->read); | 42 | read = iwb->read; |
43 | write = atomic_read(&iwb->write); | 43 | write = iwb->write; |
44 | if ((freebytes = read - write) > 0) { | 44 | if ((freebytes = read - write) > 0) { |
45 | /* no wraparound: need padding space within regular area */ | 45 | /* no wraparound: need padding space within regular area */ |
46 | return freebytes - BAS_OUTBUFPAD; | 46 | return freebytes - BAS_OUTBUFPAD; |
@@ -62,7 +62,7 @@ static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) | |||
62 | int read; | 62 | int read; |
63 | if (a == b) | 63 | if (a == b) |
64 | return 0; | 64 | return 0; |
65 | read = atomic_read(&iwb->read); | 65 | read = iwb->read; |
66 | if (a < b) { | 66 | if (a < b) { |
67 | if (a < read && read <= b) | 67 | if (a < read && read <= b) |
68 | return +1; | 68 | return +1; |
@@ -91,18 +91,18 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb) | |||
91 | #ifdef CONFIG_GIGASET_DEBUG | 91 | #ifdef CONFIG_GIGASET_DEBUG |
92 | gig_dbg(DEBUG_ISO, | 92 | gig_dbg(DEBUG_ISO, |
93 | "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", | 93 | "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", |
94 | __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); | 94 | __func__, iwb->data[iwb->write], iwb->wbits); |
95 | #endif | 95 | #endif |
96 | return 1; | 96 | return 1; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* finish writing | 99 | /* finish writing |
100 | * release the write semaphore and update the maximum buffer fill level | 100 | * release the write semaphore |
101 | * returns the current write position | 101 | * returns the current write position |
102 | */ | 102 | */ |
103 | static inline int isowbuf_donewrite(struct isowbuf_t *iwb) | 103 | static inline int isowbuf_donewrite(struct isowbuf_t *iwb) |
104 | { | 104 | { |
105 | int write = atomic_read(&iwb->write); | 105 | int write = iwb->write; |
106 | atomic_inc(&iwb->writesem); | 106 | atomic_inc(&iwb->writesem); |
107 | return write; | 107 | return write; |
108 | } | 108 | } |
@@ -116,7 +116,7 @@ static inline int isowbuf_donewrite(struct isowbuf_t *iwb) | |||
116 | */ | 116 | */ |
117 | static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) | 117 | static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) |
118 | { | 118 | { |
119 | int write = atomic_read(&iwb->write); | 119 | int write = iwb->write; |
120 | data <<= iwb->wbits; | 120 | data <<= iwb->wbits; |
121 | data |= iwb->data[write]; | 121 | data |= iwb->data[write]; |
122 | nbits += iwb->wbits; | 122 | nbits += iwb->wbits; |
@@ -128,7 +128,7 @@ static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) | |||
128 | } | 128 | } |
129 | iwb->wbits = nbits; | 129 | iwb->wbits = nbits; |
130 | iwb->data[write] = data & 0xff; | 130 | iwb->data[write] = data & 0xff; |
131 | atomic_set(&iwb->write, write); | 131 | iwb->write = write; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* put final flag on HDLC bitstream | 134 | /* put final flag on HDLC bitstream |
@@ -142,7 +142,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb) | |||
142 | /* add two flags, thus reliably covering one byte */ | 142 | /* add two flags, thus reliably covering one byte */ |
143 | isowbuf_putbits(iwb, 0x7e7e, 8); | 143 | isowbuf_putbits(iwb, 0x7e7e, 8); |
144 | /* recover the idle flag byte */ | 144 | /* recover the idle flag byte */ |
145 | write = atomic_read(&iwb->write); | 145 | write = iwb->write; |
146 | iwb->idle = iwb->data[write]; | 146 | iwb->idle = iwb->data[write]; |
147 | gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); | 147 | gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); |
148 | /* mask extraneous bits in buffer */ | 148 | /* mask extraneous bits in buffer */ |
@@ -160,8 +160,8 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
160 | int read, write, limit, src, dst; | 160 | int read, write, limit, src, dst; |
161 | unsigned char pbyte; | 161 | unsigned char pbyte; |
162 | 162 | ||
163 | read = atomic_read(&iwb->nextread); | 163 | read = iwb->nextread; |
164 | write = atomic_read(&iwb->write); | 164 | write = iwb->write; |
165 | if (likely(read == write)) { | 165 | if (likely(read == write)) { |
166 | /* return idle frame */ | 166 | /* return idle frame */ |
167 | return read < BAS_OUTBUFPAD ? | 167 | return read < BAS_OUTBUFPAD ? |
@@ -176,7 +176,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
176 | err("invalid size %d", size); | 176 | err("invalid size %d", size); |
177 | return -EINVAL; | 177 | return -EINVAL; |
178 | } | 178 | } |
179 | src = atomic_read(&iwb->read); | 179 | src = iwb->read; |
180 | if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD || | 180 | if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD || |
181 | (read < src && limit >= src))) { | 181 | (read < src && limit >= src))) { |
182 | err("isoc write buffer frame reservation violated"); | 182 | err("isoc write buffer frame reservation violated"); |
@@ -191,7 +191,8 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
191 | if (!isowbuf_startwrite(iwb)) | 191 | if (!isowbuf_startwrite(iwb)) |
192 | return -EBUSY; | 192 | return -EBUSY; |
193 | /* write position could have changed */ | 193 | /* write position could have changed */ |
194 | if (limit >= (write = atomic_read(&iwb->write))) { | 194 | write = iwb->write; |
195 | if (limit >= write) { | ||
195 | pbyte = iwb->data[write]; /* save | 196 | pbyte = iwb->data[write]; /* save |
196 | partial byte */ | 197 | partial byte */ |
197 | limit = write + BAS_OUTBUFPAD; | 198 | limit = write + BAS_OUTBUFPAD; |
@@ -213,7 +214,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
213 | __func__, pbyte, limit); | 214 | __func__, pbyte, limit); |
214 | iwb->data[limit] = pbyte; /* restore | 215 | iwb->data[limit] = pbyte; /* restore |
215 | partial byte */ | 216 | partial byte */ |
216 | atomic_set(&iwb->write, limit); | 217 | iwb->write = limit; |
217 | } | 218 | } |
218 | isowbuf_donewrite(iwb); | 219 | isowbuf_donewrite(iwb); |
219 | } | 220 | } |
@@ -233,7 +234,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
233 | limit = src; | 234 | limit = src; |
234 | } | 235 | } |
235 | } | 236 | } |
236 | atomic_set(&iwb->nextread, limit); | 237 | iwb->nextread = limit; |
237 | return read; | 238 | return read; |
238 | } | 239 | } |
239 | 240 | ||
@@ -477,7 +478,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, | |||
477 | unsigned char c; | 478 | unsigned char c; |
478 | 479 | ||
479 | if (unlikely(count <= 0)) | 480 | if (unlikely(count <= 0)) |
480 | return atomic_read(&iwb->write); /* better ideas? */ | 481 | return iwb->write; |
481 | 482 | ||
482 | if (isowbuf_freebytes(iwb) < count || | 483 | if (isowbuf_freebytes(iwb) < count || |
483 | !isowbuf_startwrite(iwb)) { | 484 | !isowbuf_startwrite(iwb)) { |
@@ -486,13 +487,13 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, | |||
486 | } | 487 | } |
487 | 488 | ||
488 | gig_dbg(DEBUG_STREAM, "put %d bytes", count); | 489 | gig_dbg(DEBUG_STREAM, "put %d bytes", count); |
489 | write = atomic_read(&iwb->write); | 490 | write = iwb->write; |
490 | do { | 491 | do { |
491 | c = bitrev8(*in++); | 492 | c = bitrev8(*in++); |
492 | iwb->data[write++] = c; | 493 | iwb->data[write++] = c; |
493 | write %= BAS_OUTBUFSIZE; | 494 | write %= BAS_OUTBUFSIZE; |
494 | } while (--count > 0); | 495 | } while (--count > 0); |
495 | atomic_set(&iwb->write, write); | 496 | iwb->write = write; |
496 | iwb->idle = c; | 497 | iwb->idle = c; |
497 | 498 | ||
498 | return isowbuf_donewrite(iwb); | 499 | return isowbuf_donewrite(iwb); |
@@ -947,8 +948,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
947 | unsigned tail, head, numbytes; | 948 | unsigned tail, head, numbytes; |
948 | unsigned char *src; | 949 | unsigned char *src; |
949 | 950 | ||
950 | head = atomic_read(&inbuf->head); | 951 | head = inbuf->head; |
951 | while (head != (tail = atomic_read(&inbuf->tail))) { | 952 | while (head != (tail = inbuf->tail)) { |
952 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | 953 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); |
953 | if (head > tail) | 954 | if (head > tail) |
954 | tail = RBUFSIZE; | 955 | tail = RBUFSIZE; |
@@ -956,7 +957,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
956 | numbytes = tail - head; | 957 | numbytes = tail - head; |
957 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | 958 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); |
958 | 959 | ||
959 | if (atomic_read(&cs->mstate) == MS_LOCKED) { | 960 | if (cs->mstate == MS_LOCKED) { |
960 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", | 961 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", |
961 | numbytes, src); | 962 | numbytes, src); |
962 | gigaset_if_receive(inbuf->cs, src, numbytes); | 963 | gigaset_if_receive(inbuf->cs, src, numbytes); |
@@ -970,7 +971,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
970 | if (head == RBUFSIZE) | 971 | if (head == RBUFSIZE) |
971 | head = 0; | 972 | head = 0; |
972 | gig_dbg(DEBUG_INTR, "setting head to %u", head); | 973 | gig_dbg(DEBUG_INTR, "setting head to %u", head); |
973 | atomic_set(&inbuf->head, head); | 974 | inbuf->head = head; |
974 | } | 975 | } |
975 | } | 976 | } |
976 | 977 | ||
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ea44302e6e7e..fceeb1d57682 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/tty.h> | 18 | #include <linux/tty.h> |
19 | #include <linux/poll.h> | 19 | #include <linux/poll.h> |
20 | #include <linux/completion.h> | ||
20 | 21 | ||
21 | /* Version Information */ | 22 | /* Version Information */ |
22 | #define DRIVER_AUTHOR "Tilman Schmidt" | 23 | #define DRIVER_AUTHOR "Tilman Schmidt" |
@@ -48,7 +49,7 @@ struct ser_cardstate { | |||
48 | struct platform_device dev; | 49 | struct platform_device dev; |
49 | struct tty_struct *tty; | 50 | struct tty_struct *tty; |
50 | atomic_t refcnt; | 51 | atomic_t refcnt; |
51 | struct mutex dead_mutex; | 52 | struct completion dead_cmp; |
52 | }; | 53 | }; |
53 | 54 | ||
54 | static struct platform_driver device_driver = { | 55 | static struct platform_driver device_driver = { |
@@ -240,7 +241,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
240 | struct cmdbuf_t *cb; | 241 | struct cmdbuf_t *cb; |
241 | unsigned long flags; | 242 | unsigned long flags; |
242 | 243 | ||
243 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 244 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
244 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 245 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
245 | "CMD Transmit", len, buf); | 246 | "CMD Transmit", len, buf); |
246 | 247 | ||
@@ -498,7 +499,7 @@ static struct cardstate *cs_get(struct tty_struct *tty) | |||
498 | static void cs_put(struct cardstate *cs) | 499 | static void cs_put(struct cardstate *cs) |
499 | { | 500 | { |
500 | if (atomic_dec_and_test(&cs->hw.ser->refcnt)) | 501 | if (atomic_dec_and_test(&cs->hw.ser->refcnt)) |
501 | mutex_unlock(&cs->hw.ser->dead_mutex); | 502 | complete(&cs->hw.ser->dead_cmp); |
502 | } | 503 | } |
503 | 504 | ||
504 | /* | 505 | /* |
@@ -527,8 +528,8 @@ gigaset_tty_open(struct tty_struct *tty) | |||
527 | 528 | ||
528 | cs->dev = &cs->hw.ser->dev.dev; | 529 | cs->dev = &cs->hw.ser->dev.dev; |
529 | cs->hw.ser->tty = tty; | 530 | cs->hw.ser->tty = tty; |
530 | mutex_init(&cs->hw.ser->dead_mutex); | ||
531 | atomic_set(&cs->hw.ser->refcnt, 1); | 531 | atomic_set(&cs->hw.ser->refcnt, 1); |
532 | init_completion(&cs->hw.ser->dead_cmp); | ||
532 | 533 | ||
533 | tty->disc_data = cs; | 534 | tty->disc_data = cs; |
534 | 535 | ||
@@ -536,14 +537,13 @@ gigaset_tty_open(struct tty_struct *tty) | |||
536 | * startup system and notify the LL that we are ready to run | 537 | * startup system and notify the LL that we are ready to run |
537 | */ | 538 | */ |
538 | if (startmode == SM_LOCKED) | 539 | if (startmode == SM_LOCKED) |
539 | atomic_set(&cs->mstate, MS_LOCKED); | 540 | cs->mstate = MS_LOCKED; |
540 | if (!gigaset_start(cs)) { | 541 | if (!gigaset_start(cs)) { |
541 | tasklet_kill(&cs->write_tasklet); | 542 | tasklet_kill(&cs->write_tasklet); |
542 | goto error; | 543 | goto error; |
543 | } | 544 | } |
544 | 545 | ||
545 | gig_dbg(DEBUG_INIT, "Startup of HLL done"); | 546 | gig_dbg(DEBUG_INIT, "Startup of HLL done"); |
546 | mutex_lock(&cs->hw.ser->dead_mutex); | ||
547 | return 0; | 547 | return 0; |
548 | 548 | ||
549 | error: | 549 | error: |
@@ -577,7 +577,7 @@ gigaset_tty_close(struct tty_struct *tty) | |||
577 | else { | 577 | else { |
578 | /* wait for running methods to finish */ | 578 | /* wait for running methods to finish */ |
579 | if (!atomic_dec_and_test(&cs->hw.ser->refcnt)) | 579 | if (!atomic_dec_and_test(&cs->hw.ser->refcnt)) |
580 | mutex_lock(&cs->hw.ser->dead_mutex); | 580 | wait_for_completion(&cs->hw.ser->dead_cmp); |
581 | } | 581 | } |
582 | 582 | ||
583 | /* stop operations */ | 583 | /* stop operations */ |
@@ -714,8 +714,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, | |||
714 | return; | 714 | return; |
715 | } | 715 | } |
716 | 716 | ||
717 | tail = atomic_read(&inbuf->tail); | 717 | tail = inbuf->tail; |
718 | head = atomic_read(&inbuf->head); | 718 | head = inbuf->head; |
719 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes", | 719 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes", |
720 | head, tail, count); | 720 | head, tail, count); |
721 | 721 | ||
@@ -742,7 +742,7 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, | |||
742 | } | 742 | } |
743 | 743 | ||
744 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); | 744 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); |
745 | atomic_set(&inbuf->tail, tail); | 745 | inbuf->tail = tail; |
746 | 746 | ||
747 | /* Everything was received .. Push data into handler */ | 747 | /* Everything was received .. Push data into handler */ |
748 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | 748 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); |
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index ca4bee173cfb..77d20ab0cd4d 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -104,12 +104,17 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); | |||
104 | * flags per packet. | 104 | * flags per packet. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | /* functions called if a device of this driver is connected/disconnected */ | ||
107 | static int gigaset_probe(struct usb_interface *interface, | 108 | static int gigaset_probe(struct usb_interface *interface, |
108 | const struct usb_device_id *id); | 109 | const struct usb_device_id *id); |
109 | static void gigaset_disconnect(struct usb_interface *interface); | 110 | static void gigaset_disconnect(struct usb_interface *interface); |
110 | 111 | ||
112 | /* functions called before/after suspend */ | ||
113 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | ||
114 | static int gigaset_resume(struct usb_interface *intf); | ||
115 | static int gigaset_pre_reset(struct usb_interface *intf); | ||
116 | |||
111 | static struct gigaset_driver *driver = NULL; | 117 | static struct gigaset_driver *driver = NULL; |
112 | static struct cardstate *cardstate = NULL; | ||
113 | 118 | ||
114 | /* usb specific object needed to register this driver with the usb subsystem */ | 119 | /* usb specific object needed to register this driver with the usb subsystem */ |
115 | static struct usb_driver gigaset_usb_driver = { | 120 | static struct usb_driver gigaset_usb_driver = { |
@@ -117,12 +122,17 @@ static struct usb_driver gigaset_usb_driver = { | |||
117 | .probe = gigaset_probe, | 122 | .probe = gigaset_probe, |
118 | .disconnect = gigaset_disconnect, | 123 | .disconnect = gigaset_disconnect, |
119 | .id_table = gigaset_table, | 124 | .id_table = gigaset_table, |
125 | .suspend = gigaset_suspend, | ||
126 | .resume = gigaset_resume, | ||
127 | .reset_resume = gigaset_resume, | ||
128 | .pre_reset = gigaset_pre_reset, | ||
129 | .post_reset = gigaset_resume, | ||
120 | }; | 130 | }; |
121 | 131 | ||
122 | struct usb_cardstate { | 132 | struct usb_cardstate { |
123 | struct usb_device *udev; /* usb device pointer */ | 133 | struct usb_device *udev; /* usb device pointer */ |
124 | struct usb_interface *interface; /* interface for this device */ | 134 | struct usb_interface *interface; /* interface for this device */ |
125 | atomic_t busy; /* bulk output in progress */ | 135 | int busy; /* bulk output in progress */ |
126 | 136 | ||
127 | /* Output buffer */ | 137 | /* Output buffer */ |
128 | unsigned char *bulk_out_buffer; | 138 | unsigned char *bulk_out_buffer; |
@@ -314,7 +324,7 @@ static void gigaset_modem_fill(unsigned long data) | |||
314 | 324 | ||
315 | gig_dbg(DEBUG_OUTPUT, "modem_fill"); | 325 | gig_dbg(DEBUG_OUTPUT, "modem_fill"); |
316 | 326 | ||
317 | if (atomic_read(&cs->hw.usb->busy)) { | 327 | if (cs->hw.usb->busy) { |
318 | gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); | 328 | gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); |
319 | return; | 329 | return; |
320 | } | 330 | } |
@@ -361,18 +371,13 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
361 | { | 371 | { |
362 | struct inbuf_t *inbuf = urb->context; | 372 | struct inbuf_t *inbuf = urb->context; |
363 | struct cardstate *cs = inbuf->cs; | 373 | struct cardstate *cs = inbuf->cs; |
364 | int resubmit = 0; | 374 | int status = urb->status; |
365 | int r; | 375 | int r; |
366 | unsigned numbytes; | 376 | unsigned numbytes; |
367 | unsigned char *src; | 377 | unsigned char *src; |
368 | unsigned long flags; | 378 | unsigned long flags; |
369 | 379 | ||
370 | if (!urb->status) { | 380 | if (!status) { |
371 | if (!cs->connected) { | ||
372 | err("%s: disconnected", __func__); /* should never happen */ | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | numbytes = urb->actual_length; | 381 | numbytes = urb->actual_length; |
377 | 382 | ||
378 | if (numbytes) { | 383 | if (numbytes) { |
@@ -389,28 +394,26 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
389 | } | 394 | } |
390 | } else | 395 | } else |
391 | gig_dbg(DEBUG_INTR, "Received zero block length"); | 396 | gig_dbg(DEBUG_INTR, "Received zero block length"); |
392 | resubmit = 1; | ||
393 | } else { | 397 | } else { |
394 | /* The urb might have been killed. */ | 398 | /* The urb might have been killed. */ |
395 | gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", | 399 | gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d", |
396 | __func__, urb->status); | 400 | __func__, status); |
397 | if (urb->status != -ENOENT) { /* not killed */ | 401 | if (status == -ENOENT || status == -ESHUTDOWN) |
398 | if (!cs->connected) { | 402 | /* killed or endpoint shutdown: don't resubmit */ |
399 | err("%s: disconnected", __func__); /* should never happen */ | 403 | return; |
400 | return; | ||
401 | } | ||
402 | resubmit = 1; | ||
403 | } | ||
404 | } | 404 | } |
405 | 405 | ||
406 | if (resubmit) { | 406 | /* resubmit URB */ |
407 | spin_lock_irqsave(&cs->lock, flags); | 407 | spin_lock_irqsave(&cs->lock, flags); |
408 | r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV; | 408 | if (!cs->connected) { |
409 | spin_unlock_irqrestore(&cs->lock, flags); | 409 | spin_unlock_irqrestore(&cs->lock, flags); |
410 | if (r) | 410 | err("%s: disconnected", __func__); |
411 | dev_err(cs->dev, "error %d when resubmitting urb.\n", | 411 | return; |
412 | -r); | ||
413 | } | 412 | } |
413 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
414 | spin_unlock_irqrestore(&cs->lock, flags); | ||
415 | if (r) | ||
416 | dev_err(cs->dev, "error %d resubmitting URB\n", -r); | ||
414 | } | 417 | } |
415 | 418 | ||
416 | 419 | ||
@@ -418,19 +421,28 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
418 | static void gigaset_write_bulk_callback(struct urb *urb) | 421 | static void gigaset_write_bulk_callback(struct urb *urb) |
419 | { | 422 | { |
420 | struct cardstate *cs = urb->context; | 423 | struct cardstate *cs = urb->context; |
424 | int status = urb->status; | ||
421 | unsigned long flags; | 425 | unsigned long flags; |
422 | 426 | ||
423 | if (urb->status) | 427 | switch (status) { |
428 | case 0: /* normal completion */ | ||
429 | break; | ||
430 | case -ENOENT: /* killed */ | ||
431 | gig_dbg(DEBUG_ANY, "%s: killed", __func__); | ||
432 | cs->hw.usb->busy = 0; | ||
433 | return; | ||
434 | default: | ||
424 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", | 435 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", |
425 | -urb->status); | 436 | -status); |
426 | /* That's all we can do. Communication problems | 437 | /* That's all we can do. Communication problems |
427 | are handled by timeouts or network protocols. */ | 438 | are handled by timeouts or network protocols. */ |
439 | } | ||
428 | 440 | ||
429 | spin_lock_irqsave(&cs->lock, flags); | 441 | spin_lock_irqsave(&cs->lock, flags); |
430 | if (!cs->connected) { | 442 | if (!cs->connected) { |
431 | err("%s: not connected", __func__); | 443 | err("%s: not connected", __func__); |
432 | } else { | 444 | } else { |
433 | atomic_set(&cs->hw.usb->busy, 0); | 445 | cs->hw.usb->busy = 0; |
434 | tasklet_schedule(&cs->write_tasklet); | 446 | tasklet_schedule(&cs->write_tasklet); |
435 | } | 447 | } |
436 | spin_unlock_irqrestore(&cs->lock, flags); | 448 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -478,14 +490,14 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
478 | 490 | ||
479 | cb->offset += count; | 491 | cb->offset += count; |
480 | cb->len -= count; | 492 | cb->len -= count; |
481 | atomic_set(&ucs->busy, 1); | 493 | ucs->busy = 1; |
482 | 494 | ||
483 | spin_lock_irqsave(&cs->lock, flags); | 495 | spin_lock_irqsave(&cs->lock, flags); |
484 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; | 496 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; |
485 | spin_unlock_irqrestore(&cs->lock, flags); | 497 | spin_unlock_irqrestore(&cs->lock, flags); |
486 | 498 | ||
487 | if (status) { | 499 | if (status) { |
488 | atomic_set(&ucs->busy, 0); | 500 | ucs->busy = 0; |
489 | err("could not submit urb (error %d)\n", | 501 | err("could not submit urb (error %d)\n", |
490 | -status); | 502 | -status); |
491 | cb->len = 0; /* skip urb => remove cb+wakeup | 503 | cb->len = 0; /* skip urb => remove cb+wakeup |
@@ -504,7 +516,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
504 | struct cmdbuf_t *cb; | 516 | struct cmdbuf_t *cb; |
505 | unsigned long flags; | 517 | unsigned long flags; |
506 | 518 | ||
507 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 519 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
508 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 520 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
509 | "CMD Transmit", len, buf); | 521 | "CMD Transmit", len, buf); |
510 | 522 | ||
@@ -641,7 +653,7 @@ static int write_modem(struct cardstate *cs) | |||
641 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); | 653 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); |
642 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); | 654 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); |
643 | skb_pull(bcs->tx_skb, count); | 655 | skb_pull(bcs->tx_skb, count); |
644 | atomic_set(&ucs->busy, 1); | 656 | ucs->busy = 1; |
645 | gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); | 657 | gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); |
646 | 658 | ||
647 | spin_lock_irqsave(&cs->lock, flags); | 659 | spin_lock_irqsave(&cs->lock, flags); |
@@ -659,7 +671,7 @@ static int write_modem(struct cardstate *cs) | |||
659 | 671 | ||
660 | if (ret) { | 672 | if (ret) { |
661 | err("could not submit urb (error %d)\n", -ret); | 673 | err("could not submit urb (error %d)\n", -ret); |
662 | atomic_set(&ucs->busy, 0); | 674 | ucs->busy = 0; |
663 | } | 675 | } |
664 | 676 | ||
665 | if (!bcs->tx_skb->len) { | 677 | if (!bcs->tx_skb->len) { |
@@ -680,53 +692,44 @@ static int gigaset_probe(struct usb_interface *interface, | |||
680 | { | 692 | { |
681 | int retval; | 693 | int retval; |
682 | struct usb_device *udev = interface_to_usbdev(interface); | 694 | struct usb_device *udev = interface_to_usbdev(interface); |
683 | unsigned int ifnum; | 695 | struct usb_host_interface *hostif = interface->cur_altsetting; |
684 | struct usb_host_interface *hostif; | ||
685 | struct cardstate *cs = NULL; | 696 | struct cardstate *cs = NULL; |
686 | struct usb_cardstate *ucs = NULL; | 697 | struct usb_cardstate *ucs = NULL; |
687 | struct usb_endpoint_descriptor *endpoint; | 698 | struct usb_endpoint_descriptor *endpoint; |
688 | int buffer_size; | 699 | int buffer_size; |
689 | int alt; | ||
690 | 700 | ||
691 | gig_dbg(DEBUG_ANY, | 701 | gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__); |
692 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", | ||
693 | __func__, le16_to_cpu(udev->descriptor.idVendor), | ||
694 | le16_to_cpu(udev->descriptor.idProduct)); | ||
695 | |||
696 | retval = -ENODEV; //FIXME | ||
697 | 702 | ||
698 | /* See if the device offered us matches what we can accept */ | 703 | /* See if the device offered us matches what we can accept */ |
699 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || | 704 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || |
700 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) | 705 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) { |
706 | gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip", | ||
707 | le16_to_cpu(udev->descriptor.idVendor), | ||
708 | le16_to_cpu(udev->descriptor.idProduct)); | ||
701 | return -ENODEV; | 709 | return -ENODEV; |
702 | 710 | } | |
703 | /* this starts to become ascii art... */ | 711 | if (hostif->desc.bInterfaceNumber != 0) { |
704 | hostif = interface->cur_altsetting; | 712 | gig_dbg(DEBUG_ANY, "interface %d not for me - skip", |
705 | alt = hostif->desc.bAlternateSetting; | 713 | hostif->desc.bInterfaceNumber); |
706 | ifnum = hostif->desc.bInterfaceNumber; // FIXME ? | 714 | return -ENODEV; |
707 | 715 | } | |
708 | if (alt != 0 || ifnum != 0) { | 716 | if (hostif->desc.bAlternateSetting != 0) { |
709 | dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); | 717 | dev_notice(&udev->dev, "unsupported altsetting %d - skip", |
718 | hostif->desc.bAlternateSetting); | ||
710 | return -ENODEV; | 719 | return -ENODEV; |
711 | } | 720 | } |
712 | |||
713 | /* Reject application specific intefaces | ||
714 | * | ||
715 | */ | ||
716 | if (hostif->desc.bInterfaceClass != 255) { | 721 | if (hostif->desc.bInterfaceClass != 255) { |
717 | dev_info(&udev->dev, | 722 | dev_notice(&udev->dev, "unsupported interface class %d - skip", |
718 | "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", | 723 | hostif->desc.bInterfaceClass); |
719 | __func__, ifnum, hostif->desc.bInterfaceClass); | ||
720 | return -ENODEV; | 724 | return -ENODEV; |
721 | } | 725 | } |
722 | 726 | ||
723 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); | 727 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); |
724 | 728 | ||
725 | cs = gigaset_getunassignedcs(driver); | 729 | /* allocate memory for our device state and intialize it */ |
726 | if (!cs) { | 730 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
727 | dev_warn(&udev->dev, "no free cardstate\n"); | 731 | if (!cs) |
728 | return -ENODEV; | 732 | return -ENODEV; |
729 | } | ||
730 | ucs = cs->hw.usb; | 733 | ucs = cs->hw.usb; |
731 | 734 | ||
732 | /* save off device structure ptrs for later use */ | 735 | /* save off device structure ptrs for later use */ |
@@ -759,7 +762,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
759 | 762 | ||
760 | endpoint = &hostif->endpoint[1].desc; | 763 | endpoint = &hostif->endpoint[1].desc; |
761 | 764 | ||
762 | atomic_set(&ucs->busy, 0); | 765 | ucs->busy = 0; |
763 | 766 | ||
764 | ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); | 767 | ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); |
765 | if (!ucs->read_urb) { | 768 | if (!ucs->read_urb) { |
@@ -792,7 +795,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
792 | 795 | ||
793 | /* tell common part that the device is ready */ | 796 | /* tell common part that the device is ready */ |
794 | if (startmode == SM_LOCKED) | 797 | if (startmode == SM_LOCKED) |
795 | atomic_set(&cs->mstate, MS_LOCKED); | 798 | cs->mstate = MS_LOCKED; |
796 | 799 | ||
797 | if (!gigaset_start(cs)) { | 800 | if (!gigaset_start(cs)) { |
798 | tasklet_kill(&cs->write_tasklet); | 801 | tasklet_kill(&cs->write_tasklet); |
@@ -813,7 +816,7 @@ error: | |||
813 | usb_put_dev(ucs->udev); | 816 | usb_put_dev(ucs->udev); |
814 | ucs->udev = NULL; | 817 | ucs->udev = NULL; |
815 | ucs->interface = NULL; | 818 | ucs->interface = NULL; |
816 | gigaset_unassign(cs); | 819 | gigaset_freecs(cs); |
817 | return retval; | 820 | return retval; |
818 | } | 821 | } |
819 | 822 | ||
@@ -824,6 +827,9 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
824 | 827 | ||
825 | cs = usb_get_intfdata(interface); | 828 | cs = usb_get_intfdata(interface); |
826 | ucs = cs->hw.usb; | 829 | ucs = cs->hw.usb; |
830 | |||
831 | dev_info(cs->dev, "disconnecting Gigaset USB adapter\n"); | ||
832 | |||
827 | usb_kill_urb(ucs->read_urb); | 833 | usb_kill_urb(ucs->read_urb); |
828 | 834 | ||
829 | gigaset_stop(cs); | 835 | gigaset_stop(cs); |
@@ -831,7 +837,7 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
831 | usb_set_intfdata(interface, NULL); | 837 | usb_set_intfdata(interface, NULL); |
832 | tasklet_kill(&cs->write_tasklet); | 838 | tasklet_kill(&cs->write_tasklet); |
833 | 839 | ||
834 | usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ | 840 | usb_kill_urb(ucs->bulk_out_urb); |
835 | 841 | ||
836 | kfree(ucs->bulk_out_buffer); | 842 | kfree(ucs->bulk_out_buffer); |
837 | usb_free_urb(ucs->bulk_out_urb); | 843 | usb_free_urb(ucs->bulk_out_urb); |
@@ -844,7 +850,53 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
844 | ucs->interface = NULL; | 850 | ucs->interface = NULL; |
845 | ucs->udev = NULL; | 851 | ucs->udev = NULL; |
846 | cs->dev = NULL; | 852 | cs->dev = NULL; |
847 | gigaset_unassign(cs); | 853 | gigaset_freecs(cs); |
854 | } | ||
855 | |||
856 | /* gigaset_suspend | ||
857 | * This function is called before the USB connection is suspended or reset. | ||
858 | */ | ||
859 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) | ||
860 | { | ||
861 | struct cardstate *cs = usb_get_intfdata(intf); | ||
862 | |||
863 | /* stop activity */ | ||
864 | cs->connected = 0; /* prevent rescheduling */ | ||
865 | usb_kill_urb(cs->hw.usb->read_urb); | ||
866 | tasklet_kill(&cs->write_tasklet); | ||
867 | usb_kill_urb(cs->hw.usb->bulk_out_urb); | ||
868 | |||
869 | gig_dbg(DEBUG_SUSPEND, "suspend complete"); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | /* gigaset_resume | ||
874 | * This function is called after the USB connection has been resumed or reset. | ||
875 | */ | ||
876 | static int gigaset_resume(struct usb_interface *intf) | ||
877 | { | ||
878 | struct cardstate *cs = usb_get_intfdata(intf); | ||
879 | int rc; | ||
880 | |||
881 | /* resubmit interrupt URB */ | ||
882 | cs->connected = 1; | ||
883 | rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL); | ||
884 | if (rc) { | ||
885 | dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc); | ||
886 | return rc; | ||
887 | } | ||
888 | |||
889 | gig_dbg(DEBUG_SUSPEND, "resume complete"); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | /* gigaset_pre_reset | ||
894 | * This function is called before the USB connection is reset. | ||
895 | */ | ||
896 | static int gigaset_pre_reset(struct usb_interface *intf) | ||
897 | { | ||
898 | /* same as suspend */ | ||
899 | return gigaset_suspend(intf, PMSG_ON); | ||
848 | } | 900 | } |
849 | 901 | ||
850 | static const struct gigaset_ops ops = { | 902 | static const struct gigaset_ops ops = { |
@@ -880,11 +932,6 @@ static int __init usb_gigaset_init(void) | |||
880 | &ops, THIS_MODULE)) == NULL) | 932 | &ops, THIS_MODULE)) == NULL) |
881 | goto error; | 933 | goto error; |
882 | 934 | ||
883 | /* allocate memory for our device state and intialize it */ | ||
884 | cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); | ||
885 | if (!cardstate) | ||
886 | goto error; | ||
887 | |||
888 | /* register this driver with the USB subsystem */ | 935 | /* register this driver with the USB subsystem */ |
889 | result = usb_register(&gigaset_usb_driver); | 936 | result = usb_register(&gigaset_usb_driver); |
890 | if (result < 0) { | 937 | if (result < 0) { |
@@ -897,9 +944,7 @@ static int __init usb_gigaset_init(void) | |||
897 | info(DRIVER_DESC); | 944 | info(DRIVER_DESC); |
898 | return 0; | 945 | return 0; |
899 | 946 | ||
900 | error: if (cardstate) | 947 | error: |
901 | gigaset_freecs(cardstate); | ||
902 | cardstate = NULL; | ||
903 | if (driver) | 948 | if (driver) |
904 | gigaset_freedriver(driver); | 949 | gigaset_freedriver(driver); |
905 | driver = NULL; | 950 | driver = NULL; |
@@ -913,11 +958,16 @@ error: if (cardstate) | |||
913 | */ | 958 | */ |
914 | static void __exit usb_gigaset_exit(void) | 959 | static void __exit usb_gigaset_exit(void) |
915 | { | 960 | { |
961 | int i; | ||
962 | |||
916 | gigaset_blockdriver(driver); /* => probe will fail | 963 | gigaset_blockdriver(driver); /* => probe will fail |
917 | * => no gigaset_start any more | 964 | * => no gigaset_start any more |
918 | */ | 965 | */ |
919 | 966 | ||
920 | gigaset_shutdown(cardstate); | 967 | /* stop all connected devices */ |
968 | for (i = 0; i < driver->minors; i++) | ||
969 | gigaset_shutdown(driver->cs + i); | ||
970 | |||
921 | /* from now on, no isdn callback should be possible */ | 971 | /* from now on, no isdn callback should be possible */ |
922 | 972 | ||
923 | /* deregister this driver with the USB subsystem */ | 973 | /* deregister this driver with the USB subsystem */ |
@@ -925,8 +975,6 @@ static void __exit usb_gigaset_exit(void) | |||
925 | /* this will call the disconnect-callback */ | 975 | /* this will call the disconnect-callback */ |
926 | /* from now on, no disconnect/probe callback should be running */ | 976 | /* from now on, no disconnect/probe callback should be running */ |
927 | 977 | ||
928 | gigaset_freecs(cardstate); | ||
929 | cardstate = NULL; | ||
930 | gigaset_freedriver(driver); | 978 | gigaset_freedriver(driver); |
931 | driver = NULL; | 979 | driver = NULL; |
932 | } | 980 | } |
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index 0db9cc661e28..84318ec8d13e 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c | |||
@@ -1188,7 +1188,7 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) { | |||
1188 | 1188 | ||
1189 | if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && | 1189 | if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && |
1190 | (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { | 1190 | (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { |
1191 | dword rx_dma_magic; | 1191 | dword uninitialized_var(rx_dma_magic); |
1192 | if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { | 1192 | if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { |
1193 | pC->xbuffer[0] = LLI; | 1193 | pC->xbuffer[0] = LLI; |
1194 | pC->xbuffer[1] = 8; | 1194 | pC->xbuffer[1] = 8; |
diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c index ffa2afa77c2f..1403a5458e68 100644 --- a/drivers/isdn/hardware/eicon/diva.c +++ b/drivers/isdn/hardware/eicon/diva.c | |||
@@ -515,12 +515,11 @@ diva_xdi_read(void *adapter, void *os_handle, void __user *dst, | |||
515 | 515 | ||
516 | irqreturn_t diva_os_irq_wrapper(int irq, void *context) | 516 | irqreturn_t diva_os_irq_wrapper(int irq, void *context) |
517 | { | 517 | { |
518 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context; | 518 | diva_os_xdi_adapter_t *a = context; |
519 | diva_xdi_clear_interrupts_proc_t clear_int_proc; | 519 | diva_xdi_clear_interrupts_proc_t clear_int_proc; |
520 | 520 | ||
521 | if (!a || !a->xdi_adapter.diva_isr_handler) { | 521 | if (!a || !a->xdi_adapter.diva_isr_handler) |
522 | return IRQ_NONE; | 522 | return IRQ_NONE; |
523 | } | ||
524 | 523 | ||
525 | if ((clear_int_proc = a->clear_interrupts_proc)) { | 524 | if ((clear_int_proc = a->clear_interrupts_proc)) { |
526 | (*clear_int_proc) (a); | 525 | (*clear_int_proc) (a); |
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index b9177ca4369a..1ff98e7eb794 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c | |||
@@ -9027,7 +9027,7 @@ static byte AddInfo(byte **add_i, | |||
9027 | /* facility is a nested structure */ | 9027 | /* facility is a nested structure */ |
9028 | /* FTY can be more than once */ | 9028 | /* FTY can be more than once */ |
9029 | 9029 | ||
9030 | if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f ) | 9030 | if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f)) |
9031 | { | 9031 | { |
9032 | add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */ | 9032 | add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */ |
9033 | } | 9033 | } |
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 035d158779df..0f1db1f669b2 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c | |||
@@ -263,11 +263,7 @@ hdlc_empty_fifo(struct BCState *bcs, int count) | |||
263 | outl(idx, cs->hw.avm.cfg_reg + 4); | 263 | outl(idx, cs->hw.avm.cfg_reg + 4); |
264 | while (cnt < count) { | 264 | while (cnt < count) { |
265 | #ifdef __powerpc__ | 265 | #ifdef __powerpc__ |
266 | #ifdef CONFIG_APUS | ||
267 | *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); | ||
268 | #else | ||
269 | *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); | 266 | *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); |
270 | #endif /* CONFIG_APUS */ | ||
271 | #else | 267 | #else |
272 | *ptr++ = inl(cs->hw.avm.isac); | 268 | *ptr++ = inl(cs->hw.avm.isac); |
273 | #endif /* __powerpc__ */ | 269 | #endif /* __powerpc__ */ |
@@ -328,11 +324,7 @@ hdlc_fill_fifo(struct BCState *bcs) | |||
328 | if (cs->subtyp == AVM_FRITZ_PCI) { | 324 | if (cs->subtyp == AVM_FRITZ_PCI) { |
329 | while (cnt<count) { | 325 | while (cnt<count) { |
330 | #ifdef __powerpc__ | 326 | #ifdef __powerpc__ |
331 | #ifdef CONFIG_APUS | ||
332 | out_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); | ||
333 | #else | ||
334 | out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); | 327 | out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); |
335 | #endif /* CONFIG_APUS */ | ||
336 | #else | 328 | #else |
337 | outl(*ptr++, cs->hw.avm.isac); | 329 | outl(*ptr++, cs->hw.avm.isac); |
338 | #endif /* __powerpc__ */ | 330 | #endif /* __powerpc__ */ |
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 9cb6e5021adb..133eb18e65cc 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c | |||
@@ -1917,7 +1917,6 @@ isdn_tty_modem_init(void) | |||
1917 | info->owner = THIS_MODULE; | 1917 | info->owner = THIS_MODULE; |
1918 | #endif | 1918 | #endif |
1919 | spin_lock_init(&info->readlock); | 1919 | spin_lock_init(&info->readlock); |
1920 | init_MUTEX(&info->write_sem); | ||
1921 | sprintf(info->last_cause, "0000"); | 1920 | sprintf(info->last_cause, "0000"); |
1922 | sprintf(info->last_num, "none"); | 1921 | sprintf(info->last_num, "none"); |
1923 | info->last_dir = 0; | 1922 | info->last_dir = 0; |
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c index a943d078bacc..f93de4a30355 100644 --- a/drivers/isdn/i4l/isdn_ttyfax.c +++ b/drivers/isdn/i4l/isdn_ttyfax.c | |||
@@ -834,7 +834,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) | |||
834 | char *rp = &f->resolution; | 834 | char *rp = &f->resolution; |
835 | 835 | ||
836 | p[0] += 2; | 836 | p[0] += 2; |
837 | if (!info->faxonline & 1) /* not outgoing connection */ | 837 | if (!(info->faxonline & 1)) /* not outgoing connection */ |
838 | PARSE_ERROR1; | 838 | PARSE_ERROR1; |
839 | 839 | ||
840 | for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) { | 840 | for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) { |
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 82d957bde299..bf7997abc4ac 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c | |||
@@ -1302,7 +1302,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1302 | } | 1302 | } |
1303 | break; | 1303 | break; |
1304 | case ISDN_CMD_DIAL: | 1304 | case ISDN_CMD_DIAL: |
1305 | if (!card->flags & ICN_FLAGS_RUNNING) | 1305 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1306 | return -ENODEV; | 1306 | return -ENODEV; |
1307 | if (card->leased) | 1307 | if (card->leased) |
1308 | break; | 1308 | break; |
@@ -1328,7 +1328,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1328 | } | 1328 | } |
1329 | break; | 1329 | break; |
1330 | case ISDN_CMD_ACCEPTD: | 1330 | case ISDN_CMD_ACCEPTD: |
1331 | if (!card->flags & ICN_FLAGS_RUNNING) | 1331 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1332 | return -ENODEV; | 1332 | return -ENODEV; |
1333 | if (c->arg < ICN_BCH) { | 1333 | if (c->arg < ICN_BCH) { |
1334 | a = c->arg + 1; | 1334 | a = c->arg + 1; |
@@ -1348,7 +1348,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1348 | } | 1348 | } |
1349 | break; | 1349 | break; |
1350 | case ISDN_CMD_ACCEPTB: | 1350 | case ISDN_CMD_ACCEPTB: |
1351 | if (!card->flags & ICN_FLAGS_RUNNING) | 1351 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1352 | return -ENODEV; | 1352 | return -ENODEV; |
1353 | if (c->arg < ICN_BCH) { | 1353 | if (c->arg < ICN_BCH) { |
1354 | a = c->arg + 1; | 1354 | a = c->arg + 1; |
@@ -1366,7 +1366,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1366 | } | 1366 | } |
1367 | break; | 1367 | break; |
1368 | case ISDN_CMD_HANGUP: | 1368 | case ISDN_CMD_HANGUP: |
1369 | if (!card->flags & ICN_FLAGS_RUNNING) | 1369 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1370 | return -ENODEV; | 1370 | return -ENODEV; |
1371 | if (c->arg < ICN_BCH) { | 1371 | if (c->arg < ICN_BCH) { |
1372 | a = c->arg + 1; | 1372 | a = c->arg + 1; |
@@ -1375,7 +1375,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1375 | } | 1375 | } |
1376 | break; | 1376 | break; |
1377 | case ISDN_CMD_SETEAZ: | 1377 | case ISDN_CMD_SETEAZ: |
1378 | if (!card->flags & ICN_FLAGS_RUNNING) | 1378 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1379 | return -ENODEV; | 1379 | return -ENODEV; |
1380 | if (card->leased) | 1380 | if (card->leased) |
1381 | break; | 1381 | break; |
@@ -1391,7 +1391,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1391 | } | 1391 | } |
1392 | break; | 1392 | break; |
1393 | case ISDN_CMD_CLREAZ: | 1393 | case ISDN_CMD_CLREAZ: |
1394 | if (!card->flags & ICN_FLAGS_RUNNING) | 1394 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1395 | return -ENODEV; | 1395 | return -ENODEV; |
1396 | if (card->leased) | 1396 | if (card->leased) |
1397 | break; | 1397 | break; |
@@ -1405,7 +1405,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1405 | } | 1405 | } |
1406 | break; | 1406 | break; |
1407 | case ISDN_CMD_SETL2: | 1407 | case ISDN_CMD_SETL2: |
1408 | if (!card->flags & ICN_FLAGS_RUNNING) | 1408 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1409 | return -ENODEV; | 1409 | return -ENODEV; |
1410 | if ((c->arg & 255) < ICN_BCH) { | 1410 | if ((c->arg & 255) < ICN_BCH) { |
1411 | a = c->arg; | 1411 | a = c->arg; |
@@ -1424,7 +1424,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1424 | } | 1424 | } |
1425 | break; | 1425 | break; |
1426 | case ISDN_CMD_SETL3: | 1426 | case ISDN_CMD_SETL3: |
1427 | if (!card->flags & ICN_FLAGS_RUNNING) | 1427 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1428 | return -ENODEV; | 1428 | return -ENODEV; |
1429 | return 0; | 1429 | return 0; |
1430 | default: | 1430 | default: |
@@ -1471,7 +1471,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) | |||
1471 | icn_card *card = icn_findcard(id); | 1471 | icn_card *card = icn_findcard(id); |
1472 | 1472 | ||
1473 | if (card) { | 1473 | if (card) { |
1474 | if (!card->flags & ICN_FLAGS_RUNNING) | 1474 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1475 | return -ENODEV; | 1475 | return -ENODEV; |
1476 | return (icn_writecmd(buf, len, 1, card)); | 1476 | return (icn_writecmd(buf, len, 1, card)); |
1477 | } | 1477 | } |
@@ -1486,7 +1486,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) | |||
1486 | icn_card *card = icn_findcard(id); | 1486 | icn_card *card = icn_findcard(id); |
1487 | 1487 | ||
1488 | if (card) { | 1488 | if (card) { |
1489 | if (!card->flags & ICN_FLAGS_RUNNING) | 1489 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1490 | return -ENODEV; | 1490 | return -ENODEV; |
1491 | return (icn_readstatus(buf, len, card)); | 1491 | return (icn_readstatus(buf, len, card)); |
1492 | } | 1492 | } |
@@ -1501,7 +1501,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) | |||
1501 | icn_card *card = icn_findcard(id); | 1501 | icn_card *card = icn_findcard(id); |
1502 | 1502 | ||
1503 | if (card) { | 1503 | if (card) { |
1504 | if (!card->flags & ICN_FLAGS_RUNNING) | 1504 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1505 | return -ENODEV; | 1505 | return -ENODEV; |
1506 | return (icn_sendbuf(channel, ack, skb, card)); | 1506 | return (icn_sendbuf(channel, ack, skb, card)); |
1507 | } | 1507 | } |
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index bb92e3cd9334..655ef9a3f4df 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c | |||
@@ -1184,7 +1184,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1184 | } | 1184 | } |
1185 | break; | 1185 | break; |
1186 | case ISDN_CMD_DIAL: | 1186 | case ISDN_CMD_DIAL: |
1187 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1187 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1188 | return -ENODEV; | 1188 | return -ENODEV; |
1189 | if (card->leased) | 1189 | if (card->leased) |
1190 | break; | 1190 | break; |
@@ -1210,7 +1210,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1210 | } | 1210 | } |
1211 | break; | 1211 | break; |
1212 | case ISDN_CMD_ACCEPTD: | 1212 | case ISDN_CMD_ACCEPTD: |
1213 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1213 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1214 | return -ENODEV; | 1214 | return -ENODEV; |
1215 | if (c->arg < ISDNLOOP_BCH) { | 1215 | if (c->arg < ISDNLOOP_BCH) { |
1216 | a = c->arg + 1; | 1216 | a = c->arg + 1; |
@@ -1238,7 +1238,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1238 | } | 1238 | } |
1239 | break; | 1239 | break; |
1240 | case ISDN_CMD_ACCEPTB: | 1240 | case ISDN_CMD_ACCEPTB: |
1241 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1241 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1242 | return -ENODEV; | 1242 | return -ENODEV; |
1243 | if (c->arg < ISDNLOOP_BCH) { | 1243 | if (c->arg < ISDNLOOP_BCH) { |
1244 | a = c->arg + 1; | 1244 | a = c->arg + 1; |
@@ -1264,7 +1264,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1264 | i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); | 1264 | i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); |
1265 | break; | 1265 | break; |
1266 | case ISDN_CMD_HANGUP: | 1266 | case ISDN_CMD_HANGUP: |
1267 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1267 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1268 | return -ENODEV; | 1268 | return -ENODEV; |
1269 | if (c->arg < ISDNLOOP_BCH) { | 1269 | if (c->arg < ISDNLOOP_BCH) { |
1270 | a = c->arg + 1; | 1270 | a = c->arg + 1; |
@@ -1273,7 +1273,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1273 | } | 1273 | } |
1274 | break; | 1274 | break; |
1275 | case ISDN_CMD_SETEAZ: | 1275 | case ISDN_CMD_SETEAZ: |
1276 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1276 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1277 | return -ENODEV; | 1277 | return -ENODEV; |
1278 | if (card->leased) | 1278 | if (card->leased) |
1279 | break; | 1279 | break; |
@@ -1303,7 +1303,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1303 | } | 1303 | } |
1304 | break; | 1304 | break; |
1305 | case ISDN_CMD_SETL2: | 1305 | case ISDN_CMD_SETL2: |
1306 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1306 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1307 | return -ENODEV; | 1307 | return -ENODEV; |
1308 | if ((c->arg & 255) < ISDNLOOP_BCH) { | 1308 | if ((c->arg & 255) < ISDNLOOP_BCH) { |
1309 | a = c->arg; | 1309 | a = c->arg; |
@@ -1395,7 +1395,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) | |||
1395 | isdnloop_card *card = isdnloop_findcard(id); | 1395 | isdnloop_card *card = isdnloop_findcard(id); |
1396 | 1396 | ||
1397 | if (card) { | 1397 | if (card) { |
1398 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1398 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1399 | return -ENODEV; | 1399 | return -ENODEV; |
1400 | return (isdnloop_readstatus(buf, len, card)); | 1400 | return (isdnloop_readstatus(buf, len, card)); |
1401 | } | 1401 | } |
@@ -1410,7 +1410,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) | |||
1410 | isdnloop_card *card = isdnloop_findcard(id); | 1410 | isdnloop_card *card = isdnloop_findcard(id); |
1411 | 1411 | ||
1412 | if (card) { | 1412 | if (card) { |
1413 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1413 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1414 | return -ENODEV; | 1414 | return -ENODEV; |
1415 | /* ack request stored in skb scratch area */ | 1415 | /* ack request stored in skb scratch area */ |
1416 | *(skb->head) = ack; | 1416 | *(skb->head) = ack; |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 1b1ef3130e6e..a0585fb6da94 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -237,7 +237,7 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde | |||
237 | if (!page) | 237 | if (!page) |
238 | return ERR_PTR(-ENOMEM); | 238 | return ERR_PTR(-ENOMEM); |
239 | 239 | ||
240 | ITERATE_RDEV(mddev, rdev, tmp) { | 240 | rdev_for_each(rdev, tmp, mddev) { |
241 | if (! test_bit(In_sync, &rdev->flags) | 241 | if (! test_bit(In_sync, &rdev->flags) |
242 | || test_bit(Faulty, &rdev->flags)) | 242 | || test_bit(Faulty, &rdev->flags)) |
243 | continue; | 243 | continue; |
@@ -261,7 +261,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) | |||
261 | struct list_head *tmp; | 261 | struct list_head *tmp; |
262 | mddev_t *mddev = bitmap->mddev; | 262 | mddev_t *mddev = bitmap->mddev; |
263 | 263 | ||
264 | ITERATE_RDEV(mddev, rdev, tmp) | 264 | rdev_for_each(rdev, tmp, mddev) |
265 | if (test_bit(In_sync, &rdev->flags) | 265 | if (test_bit(In_sync, &rdev->flags) |
266 | && !test_bit(Faulty, &rdev->flags)) { | 266 | && !test_bit(Faulty, &rdev->flags)) { |
267 | int size = PAGE_SIZE; | 267 | int size = PAGE_SIZE; |
@@ -1348,14 +1348,38 @@ void bitmap_close_sync(struct bitmap *bitmap) | |||
1348 | */ | 1348 | */ |
1349 | sector_t sector = 0; | 1349 | sector_t sector = 0; |
1350 | int blocks; | 1350 | int blocks; |
1351 | if (!bitmap) return; | 1351 | if (!bitmap) |
1352 | return; | ||
1352 | while (sector < bitmap->mddev->resync_max_sectors) { | 1353 | while (sector < bitmap->mddev->resync_max_sectors) { |
1353 | bitmap_end_sync(bitmap, sector, &blocks, 0); | 1354 | bitmap_end_sync(bitmap, sector, &blocks, 0); |
1354 | /* | 1355 | sector += blocks; |
1355 | if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n", | 1356 | } |
1356 | (unsigned long long)sector, blocks); | 1357 | } |
1357 | */ sector += blocks; | 1358 | |
1359 | void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector) | ||
1360 | { | ||
1361 | sector_t s = 0; | ||
1362 | int blocks; | ||
1363 | |||
1364 | if (!bitmap) | ||
1365 | return; | ||
1366 | if (sector == 0) { | ||
1367 | bitmap->last_end_sync = jiffies; | ||
1368 | return; | ||
1369 | } | ||
1370 | if (time_before(jiffies, (bitmap->last_end_sync | ||
1371 | + bitmap->daemon_sleep * HZ))) | ||
1372 | return; | ||
1373 | wait_event(bitmap->mddev->recovery_wait, | ||
1374 | atomic_read(&bitmap->mddev->recovery_active) == 0); | ||
1375 | |||
1376 | sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1); | ||
1377 | s = 0; | ||
1378 | while (s < sector && s < bitmap->mddev->resync_max_sectors) { | ||
1379 | bitmap_end_sync(bitmap, s, &blocks, 0); | ||
1380 | s += blocks; | ||
1358 | } | 1381 | } |
1382 | bitmap->last_end_sync = jiffies; | ||
1359 | } | 1383 | } |
1360 | 1384 | ||
1361 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) | 1385 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) |
@@ -1565,3 +1589,4 @@ EXPORT_SYMBOL(bitmap_start_sync); | |||
1565 | EXPORT_SYMBOL(bitmap_end_sync); | 1589 | EXPORT_SYMBOL(bitmap_end_sync); |
1566 | EXPORT_SYMBOL(bitmap_unplug); | 1590 | EXPORT_SYMBOL(bitmap_unplug); |
1567 | EXPORT_SYMBOL(bitmap_close_sync); | 1591 | EXPORT_SYMBOL(bitmap_close_sync); |
1592 | EXPORT_SYMBOL(bitmap_cond_end_sync); | ||
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index cf2ddce34118..d107ddceefcd 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c | |||
@@ -294,7 +294,7 @@ static int run(mddev_t *mddev) | |||
294 | } | 294 | } |
295 | conf->nfaults = 0; | 295 | conf->nfaults = 0; |
296 | 296 | ||
297 | ITERATE_RDEV(mddev, rdev, tmp) | 297 | rdev_for_each(rdev, tmp, mddev) |
298 | conf->rdev = rdev; | 298 | conf->rdev = rdev; |
299 | 299 | ||
300 | mddev->array_size = mddev->size; | 300 | mddev->array_size = mddev->size; |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 3dac1cfb8189..0b8511776b3e 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -122,7 +122,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
122 | cnt = 0; | 122 | cnt = 0; |
123 | conf->array_size = 0; | 123 | conf->array_size = 0; |
124 | 124 | ||
125 | ITERATE_RDEV(mddev,rdev,tmp) { | 125 | rdev_for_each(rdev, tmp, mddev) { |
126 | int j = rdev->raid_disk; | 126 | int j = rdev->raid_disk; |
127 | dev_info_t *disk = conf->disks + j; | 127 | dev_info_t *disk = conf->disks + j; |
128 | 128 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index c28a120b4161..5fc326d3970e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -195,7 +195,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); | |||
195 | * Any code which breaks out of this loop while own | 195 | * Any code which breaks out of this loop while own |
196 | * a reference to the current mddev and must mddev_put it. | 196 | * a reference to the current mddev and must mddev_put it. |
197 | */ | 197 | */ |
198 | #define ITERATE_MDDEV(mddev,tmp) \ | 198 | #define for_each_mddev(mddev,tmp) \ |
199 | \ | 199 | \ |
200 | for (({ spin_lock(&all_mddevs_lock); \ | 200 | for (({ spin_lock(&all_mddevs_lock); \ |
201 | tmp = all_mddevs.next; \ | 201 | tmp = all_mddevs.next; \ |
@@ -275,6 +275,7 @@ static mddev_t * mddev_find(dev_t unit) | |||
275 | spin_lock_init(&new->write_lock); | 275 | spin_lock_init(&new->write_lock); |
276 | init_waitqueue_head(&new->sb_wait); | 276 | init_waitqueue_head(&new->sb_wait); |
277 | new->reshape_position = MaxSector; | 277 | new->reshape_position = MaxSector; |
278 | new->resync_max = MaxSector; | ||
278 | 279 | ||
279 | new->queue = blk_alloc_queue(GFP_KERNEL); | 280 | new->queue = blk_alloc_queue(GFP_KERNEL); |
280 | if (!new->queue) { | 281 | if (!new->queue) { |
@@ -310,7 +311,7 @@ static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) | |||
310 | mdk_rdev_t * rdev; | 311 | mdk_rdev_t * rdev; |
311 | struct list_head *tmp; | 312 | struct list_head *tmp; |
312 | 313 | ||
313 | ITERATE_RDEV(mddev,rdev,tmp) { | 314 | rdev_for_each(rdev, tmp, mddev) { |
314 | if (rdev->desc_nr == nr) | 315 | if (rdev->desc_nr == nr) |
315 | return rdev; | 316 | return rdev; |
316 | } | 317 | } |
@@ -322,7 +323,7 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev) | |||
322 | struct list_head *tmp; | 323 | struct list_head *tmp; |
323 | mdk_rdev_t *rdev; | 324 | mdk_rdev_t *rdev; |
324 | 325 | ||
325 | ITERATE_RDEV(mddev,rdev,tmp) { | 326 | rdev_for_each(rdev, tmp, mddev) { |
326 | if (rdev->bdev->bd_dev == dev) | 327 | if (rdev->bdev->bd_dev == dev) |
327 | return rdev; | 328 | return rdev; |
328 | } | 329 | } |
@@ -773,12 +774,16 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
773 | __u64 ev1 = md_event(sb); | 774 | __u64 ev1 = md_event(sb); |
774 | 775 | ||
775 | rdev->raid_disk = -1; | 776 | rdev->raid_disk = -1; |
776 | rdev->flags = 0; | 777 | clear_bit(Faulty, &rdev->flags); |
778 | clear_bit(In_sync, &rdev->flags); | ||
779 | clear_bit(WriteMostly, &rdev->flags); | ||
780 | clear_bit(BarriersNotsupp, &rdev->flags); | ||
781 | |||
777 | if (mddev->raid_disks == 0) { | 782 | if (mddev->raid_disks == 0) { |
778 | mddev->major_version = 0; | 783 | mddev->major_version = 0; |
779 | mddev->minor_version = sb->minor_version; | 784 | mddev->minor_version = sb->minor_version; |
780 | mddev->patch_version = sb->patch_version; | 785 | mddev->patch_version = sb->patch_version; |
781 | mddev->persistent = ! sb->not_persistent; | 786 | mddev->external = 0; |
782 | mddev->chunk_size = sb->chunk_size; | 787 | mddev->chunk_size = sb->chunk_size; |
783 | mddev->ctime = sb->ctime; | 788 | mddev->ctime = sb->ctime; |
784 | mddev->utime = sb->utime; | 789 | mddev->utime = sb->utime; |
@@ -904,7 +909,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
904 | sb->size = mddev->size; | 909 | sb->size = mddev->size; |
905 | sb->raid_disks = mddev->raid_disks; | 910 | sb->raid_disks = mddev->raid_disks; |
906 | sb->md_minor = mddev->md_minor; | 911 | sb->md_minor = mddev->md_minor; |
907 | sb->not_persistent = !mddev->persistent; | 912 | sb->not_persistent = 0; |
908 | sb->utime = mddev->utime; | 913 | sb->utime = mddev->utime; |
909 | sb->state = 0; | 914 | sb->state = 0; |
910 | sb->events_hi = (mddev->events>>32); | 915 | sb->events_hi = (mddev->events>>32); |
@@ -938,7 +943,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
938 | sb->state |= (1<<MD_SB_BITMAP_PRESENT); | 943 | sb->state |= (1<<MD_SB_BITMAP_PRESENT); |
939 | 944 | ||
940 | sb->disks[0].state = (1<<MD_DISK_REMOVED); | 945 | sb->disks[0].state = (1<<MD_DISK_REMOVED); |
941 | ITERATE_RDEV(mddev,rdev2,tmp) { | 946 | rdev_for_each(rdev2, tmp, mddev) { |
942 | mdp_disk_t *d; | 947 | mdp_disk_t *d; |
943 | int desc_nr; | 948 | int desc_nr; |
944 | if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) | 949 | if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) |
@@ -1153,11 +1158,15 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1153 | __u64 ev1 = le64_to_cpu(sb->events); | 1158 | __u64 ev1 = le64_to_cpu(sb->events); |
1154 | 1159 | ||
1155 | rdev->raid_disk = -1; | 1160 | rdev->raid_disk = -1; |
1156 | rdev->flags = 0; | 1161 | clear_bit(Faulty, &rdev->flags); |
1162 | clear_bit(In_sync, &rdev->flags); | ||
1163 | clear_bit(WriteMostly, &rdev->flags); | ||
1164 | clear_bit(BarriersNotsupp, &rdev->flags); | ||
1165 | |||
1157 | if (mddev->raid_disks == 0) { | 1166 | if (mddev->raid_disks == 0) { |
1158 | mddev->major_version = 1; | 1167 | mddev->major_version = 1; |
1159 | mddev->patch_version = 0; | 1168 | mddev->patch_version = 0; |
1160 | mddev->persistent = 1; | 1169 | mddev->external = 0; |
1161 | mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9; | 1170 | mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9; |
1162 | mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); | 1171 | mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); |
1163 | mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); | 1172 | mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); |
@@ -1286,7 +1295,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1286 | } | 1295 | } |
1287 | 1296 | ||
1288 | max_dev = 0; | 1297 | max_dev = 0; |
1289 | ITERATE_RDEV(mddev,rdev2,tmp) | 1298 | rdev_for_each(rdev2, tmp, mddev) |
1290 | if (rdev2->desc_nr+1 > max_dev) | 1299 | if (rdev2->desc_nr+1 > max_dev) |
1291 | max_dev = rdev2->desc_nr+1; | 1300 | max_dev = rdev2->desc_nr+1; |
1292 | 1301 | ||
@@ -1295,7 +1304,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1295 | for (i=0; i<max_dev;i++) | 1304 | for (i=0; i<max_dev;i++) |
1296 | sb->dev_roles[i] = cpu_to_le16(0xfffe); | 1305 | sb->dev_roles[i] = cpu_to_le16(0xfffe); |
1297 | 1306 | ||
1298 | ITERATE_RDEV(mddev,rdev2,tmp) { | 1307 | rdev_for_each(rdev2, tmp, mddev) { |
1299 | i = rdev2->desc_nr; | 1308 | i = rdev2->desc_nr; |
1300 | if (test_bit(Faulty, &rdev2->flags)) | 1309 | if (test_bit(Faulty, &rdev2->flags)) |
1301 | sb->dev_roles[i] = cpu_to_le16(0xfffe); | 1310 | sb->dev_roles[i] = cpu_to_le16(0xfffe); |
@@ -1333,8 +1342,8 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) | |||
1333 | struct list_head *tmp, *tmp2; | 1342 | struct list_head *tmp, *tmp2; |
1334 | mdk_rdev_t *rdev, *rdev2; | 1343 | mdk_rdev_t *rdev, *rdev2; |
1335 | 1344 | ||
1336 | ITERATE_RDEV(mddev1,rdev,tmp) | 1345 | rdev_for_each(rdev, tmp, mddev1) |
1337 | ITERATE_RDEV(mddev2, rdev2, tmp2) | 1346 | rdev_for_each(rdev2, tmp2, mddev2) |
1338 | if (rdev->bdev->bd_contains == | 1347 | if (rdev->bdev->bd_contains == |
1339 | rdev2->bdev->bd_contains) | 1348 | rdev2->bdev->bd_contains) |
1340 | return 1; | 1349 | return 1; |
@@ -1401,7 +1410,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1401 | goto fail; | 1410 | goto fail; |
1402 | } | 1411 | } |
1403 | list_add(&rdev->same_set, &mddev->disks); | 1412 | list_add(&rdev->same_set, &mddev->disks); |
1404 | bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk); | 1413 | bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk); |
1405 | return 0; | 1414 | return 0; |
1406 | 1415 | ||
1407 | fail: | 1416 | fail: |
@@ -1410,10 +1419,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1410 | return err; | 1419 | return err; |
1411 | } | 1420 | } |
1412 | 1421 | ||
1413 | static void delayed_delete(struct work_struct *ws) | 1422 | static void md_delayed_delete(struct work_struct *ws) |
1414 | { | 1423 | { |
1415 | mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work); | 1424 | mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work); |
1416 | kobject_del(&rdev->kobj); | 1425 | kobject_del(&rdev->kobj); |
1426 | kobject_put(&rdev->kobj); | ||
1417 | } | 1427 | } |
1418 | 1428 | ||
1419 | static void unbind_rdev_from_array(mdk_rdev_t * rdev) | 1429 | static void unbind_rdev_from_array(mdk_rdev_t * rdev) |
@@ -1432,7 +1442,8 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) | |||
1432 | /* We need to delay this, otherwise we can deadlock when | 1442 | /* We need to delay this, otherwise we can deadlock when |
1433 | * writing to 'remove' to "dev/state" | 1443 | * writing to 'remove' to "dev/state" |
1434 | */ | 1444 | */ |
1435 | INIT_WORK(&rdev->del_work, delayed_delete); | 1445 | INIT_WORK(&rdev->del_work, md_delayed_delete); |
1446 | kobject_get(&rdev->kobj); | ||
1436 | schedule_work(&rdev->del_work); | 1447 | schedule_work(&rdev->del_work); |
1437 | } | 1448 | } |
1438 | 1449 | ||
@@ -1441,7 +1452,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) | |||
1441 | * otherwise reused by a RAID array (or any other kernel | 1452 | * otherwise reused by a RAID array (or any other kernel |
1442 | * subsystem), by bd_claiming the device. | 1453 | * subsystem), by bd_claiming the device. |
1443 | */ | 1454 | */ |
1444 | static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) | 1455 | static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared) |
1445 | { | 1456 | { |
1446 | int err = 0; | 1457 | int err = 0; |
1447 | struct block_device *bdev; | 1458 | struct block_device *bdev; |
@@ -1453,13 +1464,15 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) | |||
1453 | __bdevname(dev, b)); | 1464 | __bdevname(dev, b)); |
1454 | return PTR_ERR(bdev); | 1465 | return PTR_ERR(bdev); |
1455 | } | 1466 | } |
1456 | err = bd_claim(bdev, rdev); | 1467 | err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev); |
1457 | if (err) { | 1468 | if (err) { |
1458 | printk(KERN_ERR "md: could not bd_claim %s.\n", | 1469 | printk(KERN_ERR "md: could not bd_claim %s.\n", |
1459 | bdevname(bdev, b)); | 1470 | bdevname(bdev, b)); |
1460 | blkdev_put(bdev); | 1471 | blkdev_put(bdev); |
1461 | return err; | 1472 | return err; |
1462 | } | 1473 | } |
1474 | if (!shared) | ||
1475 | set_bit(AllReserved, &rdev->flags); | ||
1463 | rdev->bdev = bdev; | 1476 | rdev->bdev = bdev; |
1464 | return err; | 1477 | return err; |
1465 | } | 1478 | } |
@@ -1503,7 +1516,7 @@ static void export_array(mddev_t *mddev) | |||
1503 | struct list_head *tmp; | 1516 | struct list_head *tmp; |
1504 | mdk_rdev_t *rdev; | 1517 | mdk_rdev_t *rdev; |
1505 | 1518 | ||
1506 | ITERATE_RDEV(mddev,rdev,tmp) { | 1519 | rdev_for_each(rdev, tmp, mddev) { |
1507 | if (!rdev->mddev) { | 1520 | if (!rdev->mddev) { |
1508 | MD_BUG(); | 1521 | MD_BUG(); |
1509 | continue; | 1522 | continue; |
@@ -1581,17 +1594,17 @@ static void md_print_devices(void) | |||
1581 | printk("md: **********************************\n"); | 1594 | printk("md: **********************************\n"); |
1582 | printk("md: * <COMPLETE RAID STATE PRINTOUT> *\n"); | 1595 | printk("md: * <COMPLETE RAID STATE PRINTOUT> *\n"); |
1583 | printk("md: **********************************\n"); | 1596 | printk("md: **********************************\n"); |
1584 | ITERATE_MDDEV(mddev,tmp) { | 1597 | for_each_mddev(mddev, tmp) { |
1585 | 1598 | ||
1586 | if (mddev->bitmap) | 1599 | if (mddev->bitmap) |
1587 | bitmap_print_sb(mddev->bitmap); | 1600 | bitmap_print_sb(mddev->bitmap); |
1588 | else | 1601 | else |
1589 | printk("%s: ", mdname(mddev)); | 1602 | printk("%s: ", mdname(mddev)); |
1590 | ITERATE_RDEV(mddev,rdev,tmp2) | 1603 | rdev_for_each(rdev, tmp2, mddev) |
1591 | printk("<%s>", bdevname(rdev->bdev,b)); | 1604 | printk("<%s>", bdevname(rdev->bdev,b)); |
1592 | printk("\n"); | 1605 | printk("\n"); |
1593 | 1606 | ||
1594 | ITERATE_RDEV(mddev,rdev,tmp2) | 1607 | rdev_for_each(rdev, tmp2, mddev) |
1595 | print_rdev(rdev); | 1608 | print_rdev(rdev); |
1596 | } | 1609 | } |
1597 | printk("md: **********************************\n"); | 1610 | printk("md: **********************************\n"); |
@@ -1610,7 +1623,7 @@ static void sync_sbs(mddev_t * mddev, int nospares) | |||
1610 | mdk_rdev_t *rdev; | 1623 | mdk_rdev_t *rdev; |
1611 | struct list_head *tmp; | 1624 | struct list_head *tmp; |
1612 | 1625 | ||
1613 | ITERATE_RDEV(mddev,rdev,tmp) { | 1626 | rdev_for_each(rdev, tmp, mddev) { |
1614 | if (rdev->sb_events == mddev->events || | 1627 | if (rdev->sb_events == mddev->events || |
1615 | (nospares && | 1628 | (nospares && |
1616 | rdev->raid_disk < 0 && | 1629 | rdev->raid_disk < 0 && |
@@ -1696,18 +1709,20 @@ repeat: | |||
1696 | MD_BUG(); | 1709 | MD_BUG(); |
1697 | mddev->events --; | 1710 | mddev->events --; |
1698 | } | 1711 | } |
1699 | sync_sbs(mddev, nospares); | ||
1700 | 1712 | ||
1701 | /* | 1713 | /* |
1702 | * do not write anything to disk if using | 1714 | * do not write anything to disk if using |
1703 | * nonpersistent superblocks | 1715 | * nonpersistent superblocks |
1704 | */ | 1716 | */ |
1705 | if (!mddev->persistent) { | 1717 | if (!mddev->persistent) { |
1706 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); | 1718 | if (!mddev->external) |
1719 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); | ||
1720 | |||
1707 | spin_unlock_irq(&mddev->write_lock); | 1721 | spin_unlock_irq(&mddev->write_lock); |
1708 | wake_up(&mddev->sb_wait); | 1722 | wake_up(&mddev->sb_wait); |
1709 | return; | 1723 | return; |
1710 | } | 1724 | } |
1725 | sync_sbs(mddev, nospares); | ||
1711 | spin_unlock_irq(&mddev->write_lock); | 1726 | spin_unlock_irq(&mddev->write_lock); |
1712 | 1727 | ||
1713 | dprintk(KERN_INFO | 1728 | dprintk(KERN_INFO |
@@ -1715,7 +1730,7 @@ repeat: | |||
1715 | mdname(mddev),mddev->in_sync); | 1730 | mdname(mddev),mddev->in_sync); |
1716 | 1731 | ||
1717 | bitmap_update_sb(mddev->bitmap); | 1732 | bitmap_update_sb(mddev->bitmap); |
1718 | ITERATE_RDEV(mddev,rdev,tmp) { | 1733 | rdev_for_each(rdev, tmp, mddev) { |
1719 | char b[BDEVNAME_SIZE]; | 1734 | char b[BDEVNAME_SIZE]; |
1720 | dprintk(KERN_INFO "md: "); | 1735 | dprintk(KERN_INFO "md: "); |
1721 | if (rdev->sb_loaded != 1) | 1736 | if (rdev->sb_loaded != 1) |
@@ -1785,7 +1800,7 @@ static ssize_t | |||
1785 | state_show(mdk_rdev_t *rdev, char *page) | 1800 | state_show(mdk_rdev_t *rdev, char *page) |
1786 | { | 1801 | { |
1787 | char *sep = ""; | 1802 | char *sep = ""; |
1788 | int len=0; | 1803 | size_t len = 0; |
1789 | 1804 | ||
1790 | if (test_bit(Faulty, &rdev->flags)) { | 1805 | if (test_bit(Faulty, &rdev->flags)) { |
1791 | len+= sprintf(page+len, "%sfaulty",sep); | 1806 | len+= sprintf(page+len, "%sfaulty",sep); |
@@ -1887,20 +1902,45 @@ static ssize_t | |||
1887 | slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | 1902 | slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) |
1888 | { | 1903 | { |
1889 | char *e; | 1904 | char *e; |
1905 | int err; | ||
1906 | char nm[20]; | ||
1890 | int slot = simple_strtoul(buf, &e, 10); | 1907 | int slot = simple_strtoul(buf, &e, 10); |
1891 | if (strncmp(buf, "none", 4)==0) | 1908 | if (strncmp(buf, "none", 4)==0) |
1892 | slot = -1; | 1909 | slot = -1; |
1893 | else if (e==buf || (*e && *e!= '\n')) | 1910 | else if (e==buf || (*e && *e!= '\n')) |
1894 | return -EINVAL; | 1911 | return -EINVAL; |
1895 | if (rdev->mddev->pers) | 1912 | if (rdev->mddev->pers) { |
1896 | /* Cannot set slot in active array (yet) */ | 1913 | /* Setting 'slot' on an active array requires also |
1897 | return -EBUSY; | 1914 | * updating the 'rd%d' link, and communicating |
1898 | if (slot >= rdev->mddev->raid_disks) | 1915 | * with the personality with ->hot_*_disk. |
1899 | return -ENOSPC; | 1916 | * For now we only support removing |
1900 | rdev->raid_disk = slot; | 1917 | * failed/spare devices. This normally happens automatically, |
1901 | /* assume it is working */ | 1918 | * but not when the metadata is externally managed. |
1902 | rdev->flags = 0; | 1919 | */ |
1903 | set_bit(In_sync, &rdev->flags); | 1920 | if (slot != -1) |
1921 | return -EBUSY; | ||
1922 | if (rdev->raid_disk == -1) | ||
1923 | return -EEXIST; | ||
1924 | /* personality does all needed checks */ | ||
1925 | if (rdev->mddev->pers->hot_add_disk == NULL) | ||
1926 | return -EINVAL; | ||
1927 | err = rdev->mddev->pers-> | ||
1928 | hot_remove_disk(rdev->mddev, rdev->raid_disk); | ||
1929 | if (err) | ||
1930 | return err; | ||
1931 | sprintf(nm, "rd%d", rdev->raid_disk); | ||
1932 | sysfs_remove_link(&rdev->mddev->kobj, nm); | ||
1933 | set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); | ||
1934 | md_wakeup_thread(rdev->mddev->thread); | ||
1935 | } else { | ||
1936 | if (slot >= rdev->mddev->raid_disks) | ||
1937 | return -ENOSPC; | ||
1938 | rdev->raid_disk = slot; | ||
1939 | /* assume it is working */ | ||
1940 | clear_bit(Faulty, &rdev->flags); | ||
1941 | clear_bit(WriteMostly, &rdev->flags); | ||
1942 | set_bit(In_sync, &rdev->flags); | ||
1943 | } | ||
1904 | return len; | 1944 | return len; |
1905 | } | 1945 | } |
1906 | 1946 | ||
@@ -1923,6 +1963,10 @@ offset_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
1923 | return -EINVAL; | 1963 | return -EINVAL; |
1924 | if (rdev->mddev->pers) | 1964 | if (rdev->mddev->pers) |
1925 | return -EBUSY; | 1965 | return -EBUSY; |
1966 | if (rdev->size && rdev->mddev->external) | ||
1967 | /* Must set offset before size, so overlap checks | ||
1968 | * can be sane */ | ||
1969 | return -EBUSY; | ||
1926 | rdev->data_offset = offset; | 1970 | rdev->data_offset = offset; |
1927 | return len; | 1971 | return len; |
1928 | } | 1972 | } |
@@ -1936,16 +1980,69 @@ rdev_size_show(mdk_rdev_t *rdev, char *page) | |||
1936 | return sprintf(page, "%llu\n", (unsigned long long)rdev->size); | 1980 | return sprintf(page, "%llu\n", (unsigned long long)rdev->size); |
1937 | } | 1981 | } |
1938 | 1982 | ||
1983 | static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2) | ||
1984 | { | ||
1985 | /* check if two start/length pairs overlap */ | ||
1986 | if (s1+l1 <= s2) | ||
1987 | return 0; | ||
1988 | if (s2+l2 <= s1) | ||
1989 | return 0; | ||
1990 | return 1; | ||
1991 | } | ||
1992 | |||
1939 | static ssize_t | 1993 | static ssize_t |
1940 | rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) | 1994 | rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) |
1941 | { | 1995 | { |
1942 | char *e; | 1996 | char *e; |
1943 | unsigned long long size = simple_strtoull(buf, &e, 10); | 1997 | unsigned long long size = simple_strtoull(buf, &e, 10); |
1998 | unsigned long long oldsize = rdev->size; | ||
1944 | if (e==buf || (*e && *e != '\n')) | 1999 | if (e==buf || (*e && *e != '\n')) |
1945 | return -EINVAL; | 2000 | return -EINVAL; |
1946 | if (rdev->mddev->pers) | 2001 | if (rdev->mddev->pers) |
1947 | return -EBUSY; | 2002 | return -EBUSY; |
1948 | rdev->size = size; | 2003 | rdev->size = size; |
2004 | if (size > oldsize && rdev->mddev->external) { | ||
2005 | /* need to check that all other rdevs with the same ->bdev | ||
2006 | * do not overlap. We need to unlock the mddev to avoid | ||
2007 | * a deadlock. We have already changed rdev->size, and if | ||
2008 | * we have to change it back, we will have the lock again. | ||
2009 | */ | ||
2010 | mddev_t *mddev; | ||
2011 | int overlap = 0; | ||
2012 | struct list_head *tmp, *tmp2; | ||
2013 | |||
2014 | mddev_unlock(rdev->mddev); | ||
2015 | for_each_mddev(mddev, tmp) { | ||
2016 | mdk_rdev_t *rdev2; | ||
2017 | |||
2018 | mddev_lock(mddev); | ||
2019 | rdev_for_each(rdev2, tmp2, mddev) | ||
2020 | if (test_bit(AllReserved, &rdev2->flags) || | ||
2021 | (rdev->bdev == rdev2->bdev && | ||
2022 | rdev != rdev2 && | ||
2023 | overlaps(rdev->data_offset, rdev->size, | ||
2024 | rdev2->data_offset, rdev2->size))) { | ||
2025 | overlap = 1; | ||
2026 | break; | ||
2027 | } | ||
2028 | mddev_unlock(mddev); | ||
2029 | if (overlap) { | ||
2030 | mddev_put(mddev); | ||
2031 | break; | ||
2032 | } | ||
2033 | } | ||
2034 | mddev_lock(rdev->mddev); | ||
2035 | if (overlap) { | ||
2036 | /* Someone else could have slipped in a size | ||
2037 | * change here, but doing so is just silly. | ||
2038 | * We put oldsize back because we *know* it is | ||
2039 | * safe, and trust userspace not to race with | ||
2040 | * itself | ||
2041 | */ | ||
2042 | rdev->size = oldsize; | ||
2043 | return -EBUSY; | ||
2044 | } | ||
2045 | } | ||
1949 | if (size < rdev->mddev->size || rdev->mddev->size == 0) | 2046 | if (size < rdev->mddev->size || rdev->mddev->size == 0) |
1950 | rdev->mddev->size = size; | 2047 | rdev->mddev->size = size; |
1951 | return len; | 2048 | return len; |
@@ -1980,12 +2077,18 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr, | |||
1980 | { | 2077 | { |
1981 | struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); | 2078 | struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); |
1982 | mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); | 2079 | mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); |
2080 | int rv; | ||
1983 | 2081 | ||
1984 | if (!entry->store) | 2082 | if (!entry->store) |
1985 | return -EIO; | 2083 | return -EIO; |
1986 | if (!capable(CAP_SYS_ADMIN)) | 2084 | if (!capable(CAP_SYS_ADMIN)) |
1987 | return -EACCES; | 2085 | return -EACCES; |
1988 | return entry->store(rdev, page, length); | 2086 | rv = mddev_lock(rdev->mddev); |
2087 | if (!rv) { | ||
2088 | rv = entry->store(rdev, page, length); | ||
2089 | mddev_unlock(rdev->mddev); | ||
2090 | } | ||
2091 | return rv; | ||
1989 | } | 2092 | } |
1990 | 2093 | ||
1991 | static void rdev_free(struct kobject *ko) | 2094 | static void rdev_free(struct kobject *ko) |
@@ -2029,7 +2132,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi | |||
2029 | if ((err = alloc_disk_sb(rdev))) | 2132 | if ((err = alloc_disk_sb(rdev))) |
2030 | goto abort_free; | 2133 | goto abort_free; |
2031 | 2134 | ||
2032 | err = lock_rdev(rdev, newdev); | 2135 | err = lock_rdev(rdev, newdev, super_format == -2); |
2033 | if (err) | 2136 | if (err) |
2034 | goto abort_free; | 2137 | goto abort_free; |
2035 | 2138 | ||
@@ -2099,7 +2202,7 @@ static void analyze_sbs(mddev_t * mddev) | |||
2099 | char b[BDEVNAME_SIZE]; | 2202 | char b[BDEVNAME_SIZE]; |
2100 | 2203 | ||
2101 | freshest = NULL; | 2204 | freshest = NULL; |
2102 | ITERATE_RDEV(mddev,rdev,tmp) | 2205 | rdev_for_each(rdev, tmp, mddev) |
2103 | switch (super_types[mddev->major_version]. | 2206 | switch (super_types[mddev->major_version]. |
2104 | load_super(rdev, freshest, mddev->minor_version)) { | 2207 | load_super(rdev, freshest, mddev->minor_version)) { |
2105 | case 1: | 2208 | case 1: |
@@ -2120,7 +2223,7 @@ static void analyze_sbs(mddev_t * mddev) | |||
2120 | validate_super(mddev, freshest); | 2223 | validate_super(mddev, freshest); |
2121 | 2224 | ||
2122 | i = 0; | 2225 | i = 0; |
2123 | ITERATE_RDEV(mddev,rdev,tmp) { | 2226 | rdev_for_each(rdev, tmp, mddev) { |
2124 | if (rdev != freshest) | 2227 | if (rdev != freshest) |
2125 | if (super_types[mddev->major_version]. | 2228 | if (super_types[mddev->major_version]. |
2126 | validate_super(mddev, rdev)) { | 2229 | validate_super(mddev, rdev)) { |
@@ -2215,7 +2318,7 @@ level_show(mddev_t *mddev, char *page) | |||
2215 | static ssize_t | 2318 | static ssize_t |
2216 | level_store(mddev_t *mddev, const char *buf, size_t len) | 2319 | level_store(mddev_t *mddev, const char *buf, size_t len) |
2217 | { | 2320 | { |
2218 | int rv = len; | 2321 | ssize_t rv = len; |
2219 | if (mddev->pers) | 2322 | if (mddev->pers) |
2220 | return -EBUSY; | 2323 | return -EBUSY; |
2221 | if (len == 0) | 2324 | if (len == 0) |
@@ -2425,6 +2528,8 @@ array_state_show(mddev_t *mddev, char *page) | |||
2425 | case 0: | 2528 | case 0: |
2426 | if (mddev->in_sync) | 2529 | if (mddev->in_sync) |
2427 | st = clean; | 2530 | st = clean; |
2531 | else if (test_bit(MD_CHANGE_CLEAN, &mddev->flags)) | ||
2532 | st = write_pending; | ||
2428 | else if (mddev->safemode) | 2533 | else if (mddev->safemode) |
2429 | st = active_idle; | 2534 | st = active_idle; |
2430 | else | 2535 | else |
@@ -2455,11 +2560,9 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2455 | break; | 2560 | break; |
2456 | case clear: | 2561 | case clear: |
2457 | /* stopping an active array */ | 2562 | /* stopping an active array */ |
2458 | if (mddev->pers) { | 2563 | if (atomic_read(&mddev->active) > 1) |
2459 | if (atomic_read(&mddev->active) > 1) | 2564 | return -EBUSY; |
2460 | return -EBUSY; | 2565 | err = do_md_stop(mddev, 0); |
2461 | err = do_md_stop(mddev, 0); | ||
2462 | } | ||
2463 | break; | 2566 | break; |
2464 | case inactive: | 2567 | case inactive: |
2465 | /* stopping an active array */ | 2568 | /* stopping an active array */ |
@@ -2467,7 +2570,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2467 | if (atomic_read(&mddev->active) > 1) | 2570 | if (atomic_read(&mddev->active) > 1) |
2468 | return -EBUSY; | 2571 | return -EBUSY; |
2469 | err = do_md_stop(mddev, 2); | 2572 | err = do_md_stop(mddev, 2); |
2470 | } | 2573 | } else |
2574 | err = 0; /* already inactive */ | ||
2471 | break; | 2575 | break; |
2472 | case suspended: | 2576 | case suspended: |
2473 | break; /* not supported yet */ | 2577 | break; /* not supported yet */ |
@@ -2495,9 +2599,15 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2495 | restart_array(mddev); | 2599 | restart_array(mddev); |
2496 | spin_lock_irq(&mddev->write_lock); | 2600 | spin_lock_irq(&mddev->write_lock); |
2497 | if (atomic_read(&mddev->writes_pending) == 0) { | 2601 | if (atomic_read(&mddev->writes_pending) == 0) { |
2498 | mddev->in_sync = 1; | 2602 | if (mddev->in_sync == 0) { |
2499 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | 2603 | mddev->in_sync = 1; |
2500 | } | 2604 | if (mddev->persistent) |
2605 | set_bit(MD_CHANGE_CLEAN, | ||
2606 | &mddev->flags); | ||
2607 | } | ||
2608 | err = 0; | ||
2609 | } else | ||
2610 | err = -EBUSY; | ||
2501 | spin_unlock_irq(&mddev->write_lock); | 2611 | spin_unlock_irq(&mddev->write_lock); |
2502 | } else { | 2612 | } else { |
2503 | mddev->ro = 0; | 2613 | mddev->ro = 0; |
@@ -2508,7 +2618,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2508 | case active: | 2618 | case active: |
2509 | if (mddev->pers) { | 2619 | if (mddev->pers) { |
2510 | restart_array(mddev); | 2620 | restart_array(mddev); |
2511 | clear_bit(MD_CHANGE_CLEAN, &mddev->flags); | 2621 | if (mddev->external) |
2622 | clear_bit(MD_CHANGE_CLEAN, &mddev->flags); | ||
2512 | wake_up(&mddev->sb_wait); | 2623 | wake_up(&mddev->sb_wait); |
2513 | err = 0; | 2624 | err = 0; |
2514 | } else { | 2625 | } else { |
@@ -2574,7 +2685,9 @@ new_dev_store(mddev_t *mddev, const char *buf, size_t len) | |||
2574 | if (err < 0) | 2685 | if (err < 0) |
2575 | goto out; | 2686 | goto out; |
2576 | } | 2687 | } |
2577 | } else | 2688 | } else if (mddev->external) |
2689 | rdev = md_import_device(dev, -2, -1); | ||
2690 | else | ||
2578 | rdev = md_import_device(dev, -1, -1); | 2691 | rdev = md_import_device(dev, -1, -1); |
2579 | 2692 | ||
2580 | if (IS_ERR(rdev)) | 2693 | if (IS_ERR(rdev)) |
@@ -2659,7 +2772,9 @@ __ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store); | |||
2659 | 2772 | ||
2660 | 2773 | ||
2661 | /* Metdata version. | 2774 | /* Metdata version. |
2662 | * This is either 'none' for arrays with externally managed metadata, | 2775 | * This is one of |
2776 | * 'none' for arrays with no metadata (good luck...) | ||
2777 | * 'external' for arrays with externally managed metadata, | ||
2663 | * or N.M for internally known formats | 2778 | * or N.M for internally known formats |
2664 | */ | 2779 | */ |
2665 | static ssize_t | 2780 | static ssize_t |
@@ -2668,6 +2783,8 @@ metadata_show(mddev_t *mddev, char *page) | |||
2668 | if (mddev->persistent) | 2783 | if (mddev->persistent) |
2669 | return sprintf(page, "%d.%d\n", | 2784 | return sprintf(page, "%d.%d\n", |
2670 | mddev->major_version, mddev->minor_version); | 2785 | mddev->major_version, mddev->minor_version); |
2786 | else if (mddev->external) | ||
2787 | return sprintf(page, "external:%s\n", mddev->metadata_type); | ||
2671 | else | 2788 | else |
2672 | return sprintf(page, "none\n"); | 2789 | return sprintf(page, "none\n"); |
2673 | } | 2790 | } |
@@ -2682,6 +2799,21 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) | |||
2682 | 2799 | ||
2683 | if (cmd_match(buf, "none")) { | 2800 | if (cmd_match(buf, "none")) { |
2684 | mddev->persistent = 0; | 2801 | mddev->persistent = 0; |
2802 | mddev->external = 0; | ||
2803 | mddev->major_version = 0; | ||
2804 | mddev->minor_version = 90; | ||
2805 | return len; | ||
2806 | } | ||
2807 | if (strncmp(buf, "external:", 9) == 0) { | ||
2808 | size_t namelen = len-9; | ||
2809 | if (namelen >= sizeof(mddev->metadata_type)) | ||
2810 | namelen = sizeof(mddev->metadata_type)-1; | ||
2811 | strncpy(mddev->metadata_type, buf+9, namelen); | ||
2812 | mddev->metadata_type[namelen] = 0; | ||
2813 | if (namelen && mddev->metadata_type[namelen-1] == '\n') | ||
2814 | mddev->metadata_type[--namelen] = 0; | ||
2815 | mddev->persistent = 0; | ||
2816 | mddev->external = 1; | ||
2685 | mddev->major_version = 0; | 2817 | mddev->major_version = 0; |
2686 | mddev->minor_version = 90; | 2818 | mddev->minor_version = 90; |
2687 | return len; | 2819 | return len; |
@@ -2698,6 +2830,7 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) | |||
2698 | mddev->major_version = major; | 2830 | mddev->major_version = major; |
2699 | mddev->minor_version = minor; | 2831 | mddev->minor_version = minor; |
2700 | mddev->persistent = 1; | 2832 | mddev->persistent = 1; |
2833 | mddev->external = 0; | ||
2701 | return len; | 2834 | return len; |
2702 | } | 2835 | } |
2703 | 2836 | ||
@@ -2865,6 +2998,43 @@ sync_completed_show(mddev_t *mddev, char *page) | |||
2865 | static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); | 2998 | static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); |
2866 | 2999 | ||
2867 | static ssize_t | 3000 | static ssize_t |
3001 | max_sync_show(mddev_t *mddev, char *page) | ||
3002 | { | ||
3003 | if (mddev->resync_max == MaxSector) | ||
3004 | return sprintf(page, "max\n"); | ||
3005 | else | ||
3006 | return sprintf(page, "%llu\n", | ||
3007 | (unsigned long long)mddev->resync_max); | ||
3008 | } | ||
3009 | static ssize_t | ||
3010 | max_sync_store(mddev_t *mddev, const char *buf, size_t len) | ||
3011 | { | ||
3012 | if (strncmp(buf, "max", 3) == 0) | ||
3013 | mddev->resync_max = MaxSector; | ||
3014 | else { | ||
3015 | char *ep; | ||
3016 | unsigned long long max = simple_strtoull(buf, &ep, 10); | ||
3017 | if (ep == buf || (*ep != 0 && *ep != '\n')) | ||
3018 | return -EINVAL; | ||
3019 | if (max < mddev->resync_max && | ||
3020 | test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | ||
3021 | return -EBUSY; | ||
3022 | |||
3023 | /* Must be a multiple of chunk_size */ | ||
3024 | if (mddev->chunk_size) { | ||
3025 | if (max & (sector_t)((mddev->chunk_size>>9)-1)) | ||
3026 | return -EINVAL; | ||
3027 | } | ||
3028 | mddev->resync_max = max; | ||
3029 | } | ||
3030 | wake_up(&mddev->recovery_wait); | ||
3031 | return len; | ||
3032 | } | ||
3033 | |||
3034 | static struct md_sysfs_entry md_max_sync = | ||
3035 | __ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store); | ||
3036 | |||
3037 | static ssize_t | ||
2868 | suspend_lo_show(mddev_t *mddev, char *page) | 3038 | suspend_lo_show(mddev_t *mddev, char *page) |
2869 | { | 3039 | { |
2870 | return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo); | 3040 | return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo); |
@@ -2974,6 +3144,7 @@ static struct attribute *md_redundancy_attrs[] = { | |||
2974 | &md_sync_max.attr, | 3144 | &md_sync_max.attr, |
2975 | &md_sync_speed.attr, | 3145 | &md_sync_speed.attr, |
2976 | &md_sync_completed.attr, | 3146 | &md_sync_completed.attr, |
3147 | &md_max_sync.attr, | ||
2977 | &md_suspend_lo.attr, | 3148 | &md_suspend_lo.attr, |
2978 | &md_suspend_hi.attr, | 3149 | &md_suspend_hi.attr, |
2979 | &md_bitmap.attr, | 3150 | &md_bitmap.attr, |
@@ -3118,8 +3289,11 @@ static int do_md_run(mddev_t * mddev) | |||
3118 | /* | 3289 | /* |
3119 | * Analyze all RAID superblock(s) | 3290 | * Analyze all RAID superblock(s) |
3120 | */ | 3291 | */ |
3121 | if (!mddev->raid_disks) | 3292 | if (!mddev->raid_disks) { |
3293 | if (!mddev->persistent) | ||
3294 | return -EINVAL; | ||
3122 | analyze_sbs(mddev); | 3295 | analyze_sbs(mddev); |
3296 | } | ||
3123 | 3297 | ||
3124 | chunk_size = mddev->chunk_size; | 3298 | chunk_size = mddev->chunk_size; |
3125 | 3299 | ||
@@ -3143,7 +3317,7 @@ static int do_md_run(mddev_t * mddev) | |||
3143 | } | 3317 | } |
3144 | 3318 | ||
3145 | /* devices must have minimum size of one chunk */ | 3319 | /* devices must have minimum size of one chunk */ |
3146 | ITERATE_RDEV(mddev,rdev,tmp) { | 3320 | rdev_for_each(rdev, tmp, mddev) { |
3147 | if (test_bit(Faulty, &rdev->flags)) | 3321 | if (test_bit(Faulty, &rdev->flags)) |
3148 | continue; | 3322 | continue; |
3149 | if (rdev->size < chunk_size / 1024) { | 3323 | if (rdev->size < chunk_size / 1024) { |
@@ -3170,7 +3344,7 @@ static int do_md_run(mddev_t * mddev) | |||
3170 | * the only valid external interface is through the md | 3344 | * the only valid external interface is through the md |
3171 | * device. | 3345 | * device. |
3172 | */ | 3346 | */ |
3173 | ITERATE_RDEV(mddev,rdev,tmp) { | 3347 | rdev_for_each(rdev, tmp, mddev) { |
3174 | if (test_bit(Faulty, &rdev->flags)) | 3348 | if (test_bit(Faulty, &rdev->flags)) |
3175 | continue; | 3349 | continue; |
3176 | sync_blockdev(rdev->bdev); | 3350 | sync_blockdev(rdev->bdev); |
@@ -3236,8 +3410,8 @@ static int do_md_run(mddev_t * mddev) | |||
3236 | mdk_rdev_t *rdev2; | 3410 | mdk_rdev_t *rdev2; |
3237 | struct list_head *tmp2; | 3411 | struct list_head *tmp2; |
3238 | int warned = 0; | 3412 | int warned = 0; |
3239 | ITERATE_RDEV(mddev, rdev, tmp) { | 3413 | rdev_for_each(rdev, tmp, mddev) { |
3240 | ITERATE_RDEV(mddev, rdev2, tmp2) { | 3414 | rdev_for_each(rdev2, tmp2, mddev) { |
3241 | if (rdev < rdev2 && | 3415 | if (rdev < rdev2 && |
3242 | rdev->bdev->bd_contains == | 3416 | rdev->bdev->bd_contains == |
3243 | rdev2->bdev->bd_contains) { | 3417 | rdev2->bdev->bd_contains) { |
@@ -3297,7 +3471,7 @@ static int do_md_run(mddev_t * mddev) | |||
3297 | mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */ | 3471 | mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */ |
3298 | mddev->in_sync = 1; | 3472 | mddev->in_sync = 1; |
3299 | 3473 | ||
3300 | ITERATE_RDEV(mddev,rdev,tmp) | 3474 | rdev_for_each(rdev, tmp, mddev) |
3301 | if (rdev->raid_disk >= 0) { | 3475 | if (rdev->raid_disk >= 0) { |
3302 | char nm[20]; | 3476 | char nm[20]; |
3303 | sprintf(nm, "rd%d", rdev->raid_disk); | 3477 | sprintf(nm, "rd%d", rdev->raid_disk); |
@@ -3330,7 +3504,7 @@ static int do_md_run(mddev_t * mddev) | |||
3330 | if (mddev->degraded && !mddev->sync_thread) { | 3504 | if (mddev->degraded && !mddev->sync_thread) { |
3331 | struct list_head *rtmp; | 3505 | struct list_head *rtmp; |
3332 | int spares = 0; | 3506 | int spares = 0; |
3333 | ITERATE_RDEV(mddev,rdev,rtmp) | 3507 | rdev_for_each(rdev, rtmp, mddev) |
3334 | if (rdev->raid_disk >= 0 && | 3508 | if (rdev->raid_disk >= 0 && |
3335 | !test_bit(In_sync, &rdev->flags) && | 3509 | !test_bit(In_sync, &rdev->flags) && |
3336 | !test_bit(Faulty, &rdev->flags)) | 3510 | !test_bit(Faulty, &rdev->flags)) |
@@ -3507,14 +3681,14 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3507 | } | 3681 | } |
3508 | mddev->bitmap_offset = 0; | 3682 | mddev->bitmap_offset = 0; |
3509 | 3683 | ||
3510 | ITERATE_RDEV(mddev,rdev,tmp) | 3684 | rdev_for_each(rdev, tmp, mddev) |
3511 | if (rdev->raid_disk >= 0) { | 3685 | if (rdev->raid_disk >= 0) { |
3512 | char nm[20]; | 3686 | char nm[20]; |
3513 | sprintf(nm, "rd%d", rdev->raid_disk); | 3687 | sprintf(nm, "rd%d", rdev->raid_disk); |
3514 | sysfs_remove_link(&mddev->kobj, nm); | 3688 | sysfs_remove_link(&mddev->kobj, nm); |
3515 | } | 3689 | } |
3516 | 3690 | ||
3517 | /* make sure all delayed_delete calls have finished */ | 3691 | /* make sure all md_delayed_delete calls have finished */ |
3518 | flush_scheduled_work(); | 3692 | flush_scheduled_work(); |
3519 | 3693 | ||
3520 | export_array(mddev); | 3694 | export_array(mddev); |
@@ -3523,7 +3697,10 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3523 | mddev->size = 0; | 3697 | mddev->size = 0; |
3524 | mddev->raid_disks = 0; | 3698 | mddev->raid_disks = 0; |
3525 | mddev->recovery_cp = 0; | 3699 | mddev->recovery_cp = 0; |
3700 | mddev->resync_max = MaxSector; | ||
3526 | mddev->reshape_position = MaxSector; | 3701 | mddev->reshape_position = MaxSector; |
3702 | mddev->external = 0; | ||
3703 | mddev->persistent = 0; | ||
3527 | 3704 | ||
3528 | } else if (mddev->pers) | 3705 | } else if (mddev->pers) |
3529 | printk(KERN_INFO "md: %s switched to read-only mode.\n", | 3706 | printk(KERN_INFO "md: %s switched to read-only mode.\n", |
@@ -3546,7 +3723,7 @@ static void autorun_array(mddev_t *mddev) | |||
3546 | 3723 | ||
3547 | printk(KERN_INFO "md: running: "); | 3724 | printk(KERN_INFO "md: running: "); |
3548 | 3725 | ||
3549 | ITERATE_RDEV(mddev,rdev,tmp) { | 3726 | rdev_for_each(rdev, tmp, mddev) { |
3550 | char b[BDEVNAME_SIZE]; | 3727 | char b[BDEVNAME_SIZE]; |
3551 | printk("<%s>", bdevname(rdev->bdev,b)); | 3728 | printk("<%s>", bdevname(rdev->bdev,b)); |
3552 | } | 3729 | } |
@@ -3589,7 +3766,7 @@ static void autorun_devices(int part) | |||
3589 | printk(KERN_INFO "md: considering %s ...\n", | 3766 | printk(KERN_INFO "md: considering %s ...\n", |
3590 | bdevname(rdev0->bdev,b)); | 3767 | bdevname(rdev0->bdev,b)); |
3591 | INIT_LIST_HEAD(&candidates); | 3768 | INIT_LIST_HEAD(&candidates); |
3592 | ITERATE_RDEV_PENDING(rdev,tmp) | 3769 | rdev_for_each_list(rdev, tmp, pending_raid_disks) |
3593 | if (super_90_load(rdev, rdev0, 0) >= 0) { | 3770 | if (super_90_load(rdev, rdev0, 0) >= 0) { |
3594 | printk(KERN_INFO "md: adding %s ...\n", | 3771 | printk(KERN_INFO "md: adding %s ...\n", |
3595 | bdevname(rdev->bdev,b)); | 3772 | bdevname(rdev->bdev,b)); |
@@ -3632,7 +3809,8 @@ static void autorun_devices(int part) | |||
3632 | mddev_unlock(mddev); | 3809 | mddev_unlock(mddev); |
3633 | } else { | 3810 | } else { |
3634 | printk(KERN_INFO "md: created %s\n", mdname(mddev)); | 3811 | printk(KERN_INFO "md: created %s\n", mdname(mddev)); |
3635 | ITERATE_RDEV_GENERIC(candidates,rdev,tmp) { | 3812 | mddev->persistent = 1; |
3813 | rdev_for_each_list(rdev, tmp, candidates) { | ||
3636 | list_del_init(&rdev->same_set); | 3814 | list_del_init(&rdev->same_set); |
3637 | if (bind_rdev_to_array(rdev, mddev)) | 3815 | if (bind_rdev_to_array(rdev, mddev)) |
3638 | export_rdev(rdev); | 3816 | export_rdev(rdev); |
@@ -3643,7 +3821,7 @@ static void autorun_devices(int part) | |||
3643 | /* on success, candidates will be empty, on error | 3821 | /* on success, candidates will be empty, on error |
3644 | * it won't... | 3822 | * it won't... |
3645 | */ | 3823 | */ |
3646 | ITERATE_RDEV_GENERIC(candidates,rdev,tmp) | 3824 | rdev_for_each_list(rdev, tmp, candidates) |
3647 | export_rdev(rdev); | 3825 | export_rdev(rdev); |
3648 | mddev_put(mddev); | 3826 | mddev_put(mddev); |
3649 | } | 3827 | } |
@@ -3673,7 +3851,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg) | |||
3673 | struct list_head *tmp; | 3851 | struct list_head *tmp; |
3674 | 3852 | ||
3675 | nr=working=active=failed=spare=0; | 3853 | nr=working=active=failed=spare=0; |
3676 | ITERATE_RDEV(mddev,rdev,tmp) { | 3854 | rdev_for_each(rdev, tmp, mddev) { |
3677 | nr++; | 3855 | nr++; |
3678 | if (test_bit(Faulty, &rdev->flags)) | 3856 | if (test_bit(Faulty, &rdev->flags)) |
3679 | failed++; | 3857 | failed++; |
@@ -3919,8 +4097,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
3919 | else | 4097 | else |
3920 | rdev->raid_disk = -1; | 4098 | rdev->raid_disk = -1; |
3921 | 4099 | ||
3922 | rdev->flags = 0; | ||
3923 | |||
3924 | if (rdev->raid_disk < mddev->raid_disks) | 4100 | if (rdev->raid_disk < mddev->raid_disks) |
3925 | if (info->state & (1<<MD_DISK_SYNC)) | 4101 | if (info->state & (1<<MD_DISK_SYNC)) |
3926 | set_bit(In_sync, &rdev->flags); | 4102 | set_bit(In_sync, &rdev->flags); |
@@ -4165,13 +4341,15 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) | |||
4165 | else | 4341 | else |
4166 | mddev->recovery_cp = 0; | 4342 | mddev->recovery_cp = 0; |
4167 | mddev->persistent = ! info->not_persistent; | 4343 | mddev->persistent = ! info->not_persistent; |
4344 | mddev->external = 0; | ||
4168 | 4345 | ||
4169 | mddev->layout = info->layout; | 4346 | mddev->layout = info->layout; |
4170 | mddev->chunk_size = info->chunk_size; | 4347 | mddev->chunk_size = info->chunk_size; |
4171 | 4348 | ||
4172 | mddev->max_disks = MD_SB_DISKS; | 4349 | mddev->max_disks = MD_SB_DISKS; |
4173 | 4350 | ||
4174 | mddev->flags = 0; | 4351 | if (mddev->persistent) |
4352 | mddev->flags = 0; | ||
4175 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | 4353 | set_bit(MD_CHANGE_DEVS, &mddev->flags); |
4176 | 4354 | ||
4177 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; | 4355 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; |
@@ -4213,7 +4391,7 @@ static int update_size(mddev_t *mddev, unsigned long size) | |||
4213 | */ | 4391 | */ |
4214 | if (mddev->sync_thread) | 4392 | if (mddev->sync_thread) |
4215 | return -EBUSY; | 4393 | return -EBUSY; |
4216 | ITERATE_RDEV(mddev,rdev,tmp) { | 4394 | rdev_for_each(rdev, tmp, mddev) { |
4217 | sector_t avail; | 4395 | sector_t avail; |
4218 | avail = rdev->size * 2; | 4396 | avail = rdev->size * 2; |
4219 | 4397 | ||
@@ -4471,9 +4649,10 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
4471 | */ | 4649 | */ |
4472 | /* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY, | 4650 | /* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY, |
4473 | * RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */ | 4651 | * RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */ |
4474 | if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY | 4652 | if ((!mddev->raid_disks && !mddev->external) |
4475 | && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE | 4653 | && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY |
4476 | && cmd != GET_BITMAP_FILE) { | 4654 | && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE |
4655 | && cmd != GET_BITMAP_FILE) { | ||
4477 | err = -ENODEV; | 4656 | err = -ENODEV; |
4478 | goto abort_unlock; | 4657 | goto abort_unlock; |
4479 | } | 4658 | } |
@@ -4757,7 +4936,7 @@ static void status_unused(struct seq_file *seq) | |||
4757 | 4936 | ||
4758 | seq_printf(seq, "unused devices: "); | 4937 | seq_printf(seq, "unused devices: "); |
4759 | 4938 | ||
4760 | ITERATE_RDEV_PENDING(rdev,tmp) { | 4939 | rdev_for_each_list(rdev, tmp, pending_raid_disks) { |
4761 | char b[BDEVNAME_SIZE]; | 4940 | char b[BDEVNAME_SIZE]; |
4762 | i++; | 4941 | i++; |
4763 | seq_printf(seq, "%s ", | 4942 | seq_printf(seq, "%s ", |
@@ -4953,7 +5132,7 @@ static int md_seq_show(struct seq_file *seq, void *v) | |||
4953 | } | 5132 | } |
4954 | 5133 | ||
4955 | size = 0; | 5134 | size = 0; |
4956 | ITERATE_RDEV(mddev,rdev,tmp2) { | 5135 | rdev_for_each(rdev, tmp2, mddev) { |
4957 | char b[BDEVNAME_SIZE]; | 5136 | char b[BDEVNAME_SIZE]; |
4958 | seq_printf(seq, " %s[%d]", | 5137 | seq_printf(seq, " %s[%d]", |
4959 | bdevname(rdev->bdev,b), rdev->desc_nr); | 5138 | bdevname(rdev->bdev,b), rdev->desc_nr); |
@@ -4982,7 +5161,10 @@ static int md_seq_show(struct seq_file *seq, void *v) | |||
4982 | mddev->major_version, | 5161 | mddev->major_version, |
4983 | mddev->minor_version); | 5162 | mddev->minor_version); |
4984 | } | 5163 | } |
4985 | } else | 5164 | } else if (mddev->external) |
5165 | seq_printf(seq, " super external:%s", | ||
5166 | mddev->metadata_type); | ||
5167 | else | ||
4986 | seq_printf(seq, " super non-persistent"); | 5168 | seq_printf(seq, " super non-persistent"); |
4987 | 5169 | ||
4988 | if (mddev->pers) { | 5170 | if (mddev->pers) { |
@@ -5106,7 +5288,7 @@ static int is_mddev_idle(mddev_t *mddev) | |||
5106 | long curr_events; | 5288 | long curr_events; |
5107 | 5289 | ||
5108 | idle = 1; | 5290 | idle = 1; |
5109 | ITERATE_RDEV(mddev,rdev,tmp) { | 5291 | rdev_for_each(rdev, tmp, mddev) { |
5110 | struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; | 5292 | struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; |
5111 | curr_events = disk_stat_read(disk, sectors[0]) + | 5293 | curr_events = disk_stat_read(disk, sectors[0]) + |
5112 | disk_stat_read(disk, sectors[1]) - | 5294 | disk_stat_read(disk, sectors[1]) - |
@@ -5283,7 +5465,7 @@ void md_do_sync(mddev_t *mddev) | |||
5283 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 5465 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
5284 | goto skip; | 5466 | goto skip; |
5285 | } | 5467 | } |
5286 | ITERATE_MDDEV(mddev2,tmp) { | 5468 | for_each_mddev(mddev2, tmp) { |
5287 | if (mddev2 == mddev) | 5469 | if (mddev2 == mddev) |
5288 | continue; | 5470 | continue; |
5289 | if (mddev2->curr_resync && | 5471 | if (mddev2->curr_resync && |
@@ -5333,7 +5515,7 @@ void md_do_sync(mddev_t *mddev) | |||
5333 | /* recovery follows the physical size of devices */ | 5515 | /* recovery follows the physical size of devices */ |
5334 | max_sectors = mddev->size << 1; | 5516 | max_sectors = mddev->size << 1; |
5335 | j = MaxSector; | 5517 | j = MaxSector; |
5336 | ITERATE_RDEV(mddev,rdev,rtmp) | 5518 | rdev_for_each(rdev, rtmp, mddev) |
5337 | if (rdev->raid_disk >= 0 && | 5519 | if (rdev->raid_disk >= 0 && |
5338 | !test_bit(Faulty, &rdev->flags) && | 5520 | !test_bit(Faulty, &rdev->flags) && |
5339 | !test_bit(In_sync, &rdev->flags) && | 5521 | !test_bit(In_sync, &rdev->flags) && |
@@ -5381,8 +5563,16 @@ void md_do_sync(mddev_t *mddev) | |||
5381 | sector_t sectors; | 5563 | sector_t sectors; |
5382 | 5564 | ||
5383 | skipped = 0; | 5565 | skipped = 0; |
5566 | if (j >= mddev->resync_max) { | ||
5567 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | ||
5568 | wait_event(mddev->recovery_wait, | ||
5569 | mddev->resync_max > j | ||
5570 | || kthread_should_stop()); | ||
5571 | } | ||
5572 | if (kthread_should_stop()) | ||
5573 | goto interrupted; | ||
5384 | sectors = mddev->pers->sync_request(mddev, j, &skipped, | 5574 | sectors = mddev->pers->sync_request(mddev, j, &skipped, |
5385 | currspeed < speed_min(mddev)); | 5575 | currspeed < speed_min(mddev)); |
5386 | if (sectors == 0) { | 5576 | if (sectors == 0) { |
5387 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); | 5577 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); |
5388 | goto out; | 5578 | goto out; |
@@ -5424,15 +5614,9 @@ void md_do_sync(mddev_t *mddev) | |||
5424 | } | 5614 | } |
5425 | 5615 | ||
5426 | 5616 | ||
5427 | if (kthread_should_stop()) { | 5617 | if (kthread_should_stop()) |
5428 | /* | 5618 | goto interrupted; |
5429 | * got a signal, exit. | 5619 | |
5430 | */ | ||
5431 | printk(KERN_INFO | ||
5432 | "md: md_do_sync() got signal ... exiting\n"); | ||
5433 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | ||
5434 | goto out; | ||
5435 | } | ||
5436 | 5620 | ||
5437 | /* | 5621 | /* |
5438 | * this loop exits only if either when we are slower than | 5622 | * this loop exits only if either when we are slower than |
@@ -5484,7 +5668,7 @@ void md_do_sync(mddev_t *mddev) | |||
5484 | } else { | 5668 | } else { |
5485 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) | 5669 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) |
5486 | mddev->curr_resync = MaxSector; | 5670 | mddev->curr_resync = MaxSector; |
5487 | ITERATE_RDEV(mddev,rdev,rtmp) | 5671 | rdev_for_each(rdev, rtmp, mddev) |
5488 | if (rdev->raid_disk >= 0 && | 5672 | if (rdev->raid_disk >= 0 && |
5489 | !test_bit(Faulty, &rdev->flags) && | 5673 | !test_bit(Faulty, &rdev->flags) && |
5490 | !test_bit(In_sync, &rdev->flags) && | 5674 | !test_bit(In_sync, &rdev->flags) && |
@@ -5496,9 +5680,22 @@ void md_do_sync(mddev_t *mddev) | |||
5496 | 5680 | ||
5497 | skip: | 5681 | skip: |
5498 | mddev->curr_resync = 0; | 5682 | mddev->curr_resync = 0; |
5683 | mddev->resync_max = MaxSector; | ||
5684 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | ||
5499 | wake_up(&resync_wait); | 5685 | wake_up(&resync_wait); |
5500 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); | 5686 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); |
5501 | md_wakeup_thread(mddev->thread); | 5687 | md_wakeup_thread(mddev->thread); |
5688 | return; | ||
5689 | |||
5690 | interrupted: | ||
5691 | /* | ||
5692 | * got a signal, exit. | ||
5693 | */ | ||
5694 | printk(KERN_INFO | ||
5695 | "md: md_do_sync() got signal ... exiting\n"); | ||
5696 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | ||
5697 | goto out; | ||
5698 | |||
5502 | } | 5699 | } |
5503 | EXPORT_SYMBOL_GPL(md_do_sync); | 5700 | EXPORT_SYMBOL_GPL(md_do_sync); |
5504 | 5701 | ||
@@ -5509,8 +5706,9 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
5509 | struct list_head *rtmp; | 5706 | struct list_head *rtmp; |
5510 | int spares = 0; | 5707 | int spares = 0; |
5511 | 5708 | ||
5512 | ITERATE_RDEV(mddev,rdev,rtmp) | 5709 | rdev_for_each(rdev, rtmp, mddev) |
5513 | if (rdev->raid_disk >= 0 && | 5710 | if (rdev->raid_disk >= 0 && |
5711 | !mddev->external && | ||
5514 | (test_bit(Faulty, &rdev->flags) || | 5712 | (test_bit(Faulty, &rdev->flags) || |
5515 | ! test_bit(In_sync, &rdev->flags)) && | 5713 | ! test_bit(In_sync, &rdev->flags)) && |
5516 | atomic_read(&rdev->nr_pending)==0) { | 5714 | atomic_read(&rdev->nr_pending)==0) { |
@@ -5524,7 +5722,7 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
5524 | } | 5722 | } |
5525 | 5723 | ||
5526 | if (mddev->degraded) { | 5724 | if (mddev->degraded) { |
5527 | ITERATE_RDEV(mddev,rdev,rtmp) | 5725 | rdev_for_each(rdev, rtmp, mddev) |
5528 | if (rdev->raid_disk < 0 | 5726 | if (rdev->raid_disk < 0 |
5529 | && !test_bit(Faulty, &rdev->flags)) { | 5727 | && !test_bit(Faulty, &rdev->flags)) { |
5530 | rdev->recovery_offset = 0; | 5728 | rdev->recovery_offset = 0; |
@@ -5589,7 +5787,7 @@ void md_check_recovery(mddev_t *mddev) | |||
5589 | } | 5787 | } |
5590 | 5788 | ||
5591 | if ( ! ( | 5789 | if ( ! ( |
5592 | mddev->flags || | 5790 | (mddev->flags && !mddev->external) || |
5593 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || | 5791 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || |
5594 | test_bit(MD_RECOVERY_DONE, &mddev->recovery) || | 5792 | test_bit(MD_RECOVERY_DONE, &mddev->recovery) || |
5595 | (mddev->safemode == 1) || | 5793 | (mddev->safemode == 1) || |
@@ -5605,7 +5803,8 @@ void md_check_recovery(mddev_t *mddev) | |||
5605 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && | 5803 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && |
5606 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { | 5804 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { |
5607 | mddev->in_sync = 1; | 5805 | mddev->in_sync = 1; |
5608 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | 5806 | if (mddev->persistent) |
5807 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | ||
5609 | } | 5808 | } |
5610 | if (mddev->safemode == 1) | 5809 | if (mddev->safemode == 1) |
5611 | mddev->safemode = 0; | 5810 | mddev->safemode = 0; |
@@ -5637,7 +5836,7 @@ void md_check_recovery(mddev_t *mddev) | |||
5637 | * information must be scrapped | 5836 | * information must be scrapped |
5638 | */ | 5837 | */ |
5639 | if (!mddev->degraded) | 5838 | if (!mddev->degraded) |
5640 | ITERATE_RDEV(mddev,rdev,rtmp) | 5839 | rdev_for_each(rdev, rtmp, mddev) |
5641 | rdev->saved_raid_disk = -1; | 5840 | rdev->saved_raid_disk = -1; |
5642 | 5841 | ||
5643 | mddev->recovery = 0; | 5842 | mddev->recovery = 0; |
@@ -5714,7 +5913,7 @@ static int md_notify_reboot(struct notifier_block *this, | |||
5714 | 5913 | ||
5715 | printk(KERN_INFO "md: stopping all md devices.\n"); | 5914 | printk(KERN_INFO "md: stopping all md devices.\n"); |
5716 | 5915 | ||
5717 | ITERATE_MDDEV(mddev,tmp) | 5916 | for_each_mddev(mddev, tmp) |
5718 | if (mddev_trylock(mddev)) { | 5917 | if (mddev_trylock(mddev)) { |
5719 | do_md_stop (mddev, 1); | 5918 | do_md_stop (mddev, 1); |
5720 | mddev_unlock(mddev); | 5919 | mddev_unlock(mddev); |
@@ -5848,7 +6047,7 @@ static __exit void md_exit(void) | |||
5848 | unregister_reboot_notifier(&md_notifier); | 6047 | unregister_reboot_notifier(&md_notifier); |
5849 | unregister_sysctl_table(raid_table_header); | 6048 | unregister_sysctl_table(raid_table_header); |
5850 | remove_proc_entry("mdstat", NULL); | 6049 | remove_proc_entry("mdstat", NULL); |
5851 | ITERATE_MDDEV(mddev,tmp) { | 6050 | for_each_mddev(mddev, tmp) { |
5852 | struct gendisk *disk = mddev->gendisk; | 6051 | struct gendisk *disk = mddev->gendisk; |
5853 | if (!disk) | 6052 | if (!disk) |
5854 | continue; | 6053 | continue; |
diff --git a/drivers/md/mktables.c b/drivers/md/mktables.c index adef299908cf..b61d5767aae7 100644 --- a/drivers/md/mktables.c +++ b/drivers/md/mktables.c | |||
@@ -1,13 +1,10 @@ | |||
1 | #ident "$Id: mktables.c,v 1.2 2002/12/12 22:41:27 hpa Exp $" | 1 | /* -*- linux-c -*- ------------------------------------------------------- * |
2 | /* ----------------------------------------------------------------------- * | ||
3 | * | 2 | * |
4 | * Copyright 2002 H. Peter Anvin - All Rights Reserved | 3 | * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved |
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or modify | 5 | * This file is part of the Linux kernel, and is made available under |
7 | * it under the terms of the GNU General Public License as published by | 6 | * the terms of the GNU General Public License version 2 or (at your |
8 | * the Free Software Foundation, Inc., 53 Temple Place Ste 330, | 7 | * option) any later version; incorporated herein by reference. |
9 | * Bostom MA 02111-1307, USA; either version 2 of the License, or | ||
10 | * (at your option) any later version; incorporated herein by reference. | ||
11 | * | 8 | * |
12 | * ----------------------------------------------------------------------- */ | 9 | * ----------------------------------------------------------------------- */ |
13 | 10 | ||
@@ -26,100 +23,98 @@ | |||
26 | 23 | ||
27 | static uint8_t gfmul(uint8_t a, uint8_t b) | 24 | static uint8_t gfmul(uint8_t a, uint8_t b) |
28 | { | 25 | { |
29 | uint8_t v = 0; | 26 | uint8_t v = 0; |
30 | 27 | ||
31 | while ( b ) { | 28 | while (b) { |
32 | if ( b & 1 ) v ^= a; | 29 | if (b & 1) |
33 | a = (a << 1) ^ (a & 0x80 ? 0x1d : 0); | 30 | v ^= a; |
34 | b >>= 1; | 31 | a = (a << 1) ^ (a & 0x80 ? 0x1d : 0); |
35 | } | 32 | b >>= 1; |
36 | return v; | 33 | } |
34 | |||
35 | return v; | ||
37 | } | 36 | } |
38 | 37 | ||
39 | static uint8_t gfpow(uint8_t a, int b) | 38 | static uint8_t gfpow(uint8_t a, int b) |
40 | { | 39 | { |
41 | uint8_t v = 1; | 40 | uint8_t v = 1; |
42 | 41 | ||
43 | b %= 255; | 42 | b %= 255; |
44 | if ( b < 0 ) | 43 | if (b < 0) |
45 | b += 255; | 44 | b += 255; |
46 | 45 | ||
47 | while ( b ) { | 46 | while (b) { |
48 | if ( b & 1 ) v = gfmul(v,a); | 47 | if (b & 1) |
49 | a = gfmul(a,a); | 48 | v = gfmul(v, a); |
50 | b >>= 1; | 49 | a = gfmul(a, a); |
51 | } | 50 | b >>= 1; |
52 | return v; | 51 | } |
52 | |||
53 | return v; | ||
53 | } | 54 | } |
54 | 55 | ||
55 | int main(int argc, char *argv[]) | 56 | int main(int argc, char *argv[]) |
56 | { | 57 | { |
57 | int i, j, k; | 58 | int i, j, k; |
58 | uint8_t v; | 59 | uint8_t v; |
59 | uint8_t exptbl[256], invtbl[256]; | 60 | uint8_t exptbl[256], invtbl[256]; |
60 | 61 | ||
61 | printf("#include \"raid6.h\"\n"); | 62 | printf("#include \"raid6.h\"\n"); |
62 | 63 | ||
63 | /* Compute multiplication table */ | 64 | /* Compute multiplication table */ |
64 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 65 | printf("\nconst u8 __attribute__((aligned(256)))\n" |
65 | "raid6_gfmul[256][256] =\n" | 66 | "raid6_gfmul[256][256] =\n" |
66 | "{\n"); | 67 | "{\n"); |
67 | for ( i = 0 ; i < 256 ; i++ ) { | 68 | for (i = 0; i < 256; i++) { |
68 | printf("\t{\n"); | 69 | printf("\t{\n"); |
69 | for ( j = 0 ; j < 256 ; j += 8 ) { | 70 | for (j = 0; j < 256; j += 8) { |
70 | printf("\t\t"); | 71 | printf("\t\t"); |
71 | for ( k = 0 ; k < 8 ; k++ ) { | 72 | for (k = 0; k < 8; k++) |
72 | printf("0x%02x, ", gfmul(i,j+k)); | 73 | printf("0x%02x,%c", gfmul(i, j + k), |
73 | } | 74 | (k == 7) ? '\n' : ' '); |
74 | printf("\n"); | 75 | } |
75 | } | 76 | printf("\t},\n"); |
76 | printf("\t},\n"); | 77 | } |
77 | } | 78 | printf("};\n"); |
78 | printf("};\n"); | 79 | |
79 | 80 | /* Compute power-of-2 table (exponent) */ | |
80 | /* Compute power-of-2 table (exponent) */ | 81 | v = 1; |
81 | v = 1; | 82 | printf("\nconst u8 __attribute__((aligned(256)))\n" |
82 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 83 | "raid6_gfexp[256] =\n" "{\n"); |
83 | "raid6_gfexp[256] =\n" | 84 | for (i = 0; i < 256; i += 8) { |
84 | "{\n"); | 85 | printf("\t"); |
85 | for ( i = 0 ; i < 256 ; i += 8 ) { | 86 | for (j = 0; j < 8; j++) { |
86 | printf("\t"); | 87 | exptbl[i + j] = v; |
87 | for ( j = 0 ; j < 8 ; j++ ) { | 88 | printf("0x%02x,%c", v, (j == 7) ? '\n' : ' '); |
88 | exptbl[i+j] = v; | 89 | v = gfmul(v, 2); |
89 | printf("0x%02x, ", v); | 90 | if (v == 1) |
90 | v = gfmul(v,2); | 91 | v = 0; /* For entry 255, not a real entry */ |
91 | if ( v == 1 ) v = 0; /* For entry 255, not a real entry */ | 92 | } |
92 | } | 93 | } |
93 | printf("\n"); | 94 | printf("};\n"); |
94 | } | 95 | |
95 | printf("};\n"); | 96 | /* Compute inverse table x^-1 == x^254 */ |
96 | 97 | printf("\nconst u8 __attribute__((aligned(256)))\n" | |
97 | /* Compute inverse table x^-1 == x^254 */ | 98 | "raid6_gfinv[256] =\n" "{\n"); |
98 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 99 | for (i = 0; i < 256; i += 8) { |
99 | "raid6_gfinv[256] =\n" | 100 | printf("\t"); |
100 | "{\n"); | 101 | for (j = 0; j < 8; j++) { |
101 | for ( i = 0 ; i < 256 ; i += 8 ) { | 102 | invtbl[i + j] = v = gfpow(i + j, 254); |
102 | printf("\t"); | 103 | printf("0x%02x,%c", v, (j == 7) ? '\n' : ' '); |
103 | for ( j = 0 ; j < 8 ; j++ ) { | 104 | } |
104 | invtbl[i+j] = v = gfpow(i+j,254); | 105 | } |
105 | printf("0x%02x, ", v); | 106 | printf("};\n"); |
106 | } | 107 | |
107 | printf("\n"); | 108 | /* Compute inv(2^x + 1) (exponent-xor-inverse) table */ |
108 | } | 109 | printf("\nconst u8 __attribute__((aligned(256)))\n" |
109 | printf("};\n"); | 110 | "raid6_gfexi[256] =\n" "{\n"); |
110 | 111 | for (i = 0; i < 256; i += 8) { | |
111 | /* Compute inv(2^x + 1) (exponent-xor-inverse) table */ | 112 | printf("\t"); |
112 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 113 | for (j = 0; j < 8; j++) |
113 | "raid6_gfexi[256] =\n" | 114 | printf("0x%02x,%c", invtbl[exptbl[i + j] ^ 1], |
114 | "{\n"); | 115 | (j == 7) ? '\n' : ' '); |
115 | for ( i = 0 ; i < 256 ; i += 8 ) { | 116 | } |
116 | printf("\t"); | 117 | printf("};\n"); |
117 | for ( j = 0 ; j < 8 ; j++ ) { | 118 | |
118 | printf("0x%02x, ", invtbl[exptbl[i+j]^1]); | 119 | return 0; |
119 | } | ||
120 | printf("\n"); | ||
121 | } | ||
122 | printf("};\n\n"); | ||
123 | |||
124 | return 0; | ||
125 | } | 120 | } |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index eb631ebed686..3f299d835a2b 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -436,7 +436,7 @@ static int multipath_run (mddev_t *mddev) | |||
436 | } | 436 | } |
437 | 437 | ||
438 | conf->working_disks = 0; | 438 | conf->working_disks = 0; |
439 | ITERATE_RDEV(mddev,rdev,tmp) { | 439 | rdev_for_each(rdev, tmp, mddev) { |
440 | disk_idx = rdev->raid_disk; | 440 | disk_idx = rdev->raid_disk; |
441 | if (disk_idx < 0 || | 441 | if (disk_idx < 0 || |
442 | disk_idx >= mddev->raid_disks) | 442 | disk_idx >= mddev->raid_disks) |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index f8e591708d1f..818b48284096 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -72,11 +72,11 @@ static int create_strip_zones (mddev_t *mddev) | |||
72 | */ | 72 | */ |
73 | conf->nr_strip_zones = 0; | 73 | conf->nr_strip_zones = 0; |
74 | 74 | ||
75 | ITERATE_RDEV(mddev,rdev1,tmp1) { | 75 | rdev_for_each(rdev1, tmp1, mddev) { |
76 | printk("raid0: looking at %s\n", | 76 | printk("raid0: looking at %s\n", |
77 | bdevname(rdev1->bdev,b)); | 77 | bdevname(rdev1->bdev,b)); |
78 | c = 0; | 78 | c = 0; |
79 | ITERATE_RDEV(mddev,rdev2,tmp2) { | 79 | rdev_for_each(rdev2, tmp2, mddev) { |
80 | printk("raid0: comparing %s(%llu)", | 80 | printk("raid0: comparing %s(%llu)", |
81 | bdevname(rdev1->bdev,b), | 81 | bdevname(rdev1->bdev,b), |
82 | (unsigned long long)rdev1->size); | 82 | (unsigned long long)rdev1->size); |
@@ -124,7 +124,7 @@ static int create_strip_zones (mddev_t *mddev) | |||
124 | cnt = 0; | 124 | cnt = 0; |
125 | smallest = NULL; | 125 | smallest = NULL; |
126 | zone->dev = conf->devlist; | 126 | zone->dev = conf->devlist; |
127 | ITERATE_RDEV(mddev, rdev1, tmp1) { | 127 | rdev_for_each(rdev1, tmp1, mddev) { |
128 | int j = rdev1->raid_disk; | 128 | int j = rdev1->raid_disk; |
129 | 129 | ||
130 | if (j < 0 || j >= mddev->raid_disks) { | 130 | if (j < 0 || j >= mddev->raid_disks) { |
@@ -293,7 +293,7 @@ static int raid0_run (mddev_t *mddev) | |||
293 | 293 | ||
294 | /* calculate array device size */ | 294 | /* calculate array device size */ |
295 | mddev->array_size = 0; | 295 | mddev->array_size = 0; |
296 | ITERATE_RDEV(mddev,rdev,tmp) | 296 | rdev_for_each(rdev, tmp, mddev) |
297 | mddev->array_size += rdev->size; | 297 | mddev->array_size += rdev->size; |
298 | 298 | ||
299 | printk("raid0 : md_size is %llu blocks.\n", | 299 | printk("raid0 : md_size is %llu blocks.\n", |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4a69c416e045..5c7fef091cec 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1684,6 +1684,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1684 | if (!go_faster && conf->nr_waiting) | 1684 | if (!go_faster && conf->nr_waiting) |
1685 | msleep_interruptible(1000); | 1685 | msleep_interruptible(1000); |
1686 | 1686 | ||
1687 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
1687 | raise_barrier(conf); | 1688 | raise_barrier(conf); |
1688 | 1689 | ||
1689 | conf->next_resync = sector_nr; | 1690 | conf->next_resync = sector_nr; |
@@ -1766,6 +1767,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1766 | return rv; | 1767 | return rv; |
1767 | } | 1768 | } |
1768 | 1769 | ||
1770 | if (max_sector > mddev->resync_max) | ||
1771 | max_sector = mddev->resync_max; /* Don't do IO beyond here */ | ||
1769 | nr_sectors = 0; | 1772 | nr_sectors = 0; |
1770 | sync_blocks = 0; | 1773 | sync_blocks = 0; |
1771 | do { | 1774 | do { |
@@ -1884,7 +1887,7 @@ static int run(mddev_t *mddev) | |||
1884 | if (!conf->r1bio_pool) | 1887 | if (!conf->r1bio_pool) |
1885 | goto out_no_mem; | 1888 | goto out_no_mem; |
1886 | 1889 | ||
1887 | ITERATE_RDEV(mddev, rdev, tmp) { | 1890 | rdev_for_each(rdev, tmp, mddev) { |
1888 | disk_idx = rdev->raid_disk; | 1891 | disk_idx = rdev->raid_disk; |
1889 | if (disk_idx >= mddev->raid_disks | 1892 | if (disk_idx >= mddev->raid_disks |
1890 | || disk_idx < 0) | 1893 | || disk_idx < 0) |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 5cdcc9386200..017f58113c33 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1657,6 +1657,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1657 | return (max_sector - sector_nr) + sectors_skipped; | 1657 | return (max_sector - sector_nr) + sectors_skipped; |
1658 | } | 1658 | } |
1659 | 1659 | ||
1660 | if (max_sector > mddev->resync_max) | ||
1661 | max_sector = mddev->resync_max; /* Don't do IO beyond here */ | ||
1662 | |||
1660 | /* make sure whole request will fit in a chunk - if chunks | 1663 | /* make sure whole request will fit in a chunk - if chunks |
1661 | * are meaningful | 1664 | * are meaningful |
1662 | */ | 1665 | */ |
@@ -1670,6 +1673,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1670 | if (!go_faster && conf->nr_waiting) | 1673 | if (!go_faster && conf->nr_waiting) |
1671 | msleep_interruptible(1000); | 1674 | msleep_interruptible(1000); |
1672 | 1675 | ||
1676 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
1677 | |||
1673 | /* Again, very different code for resync and recovery. | 1678 | /* Again, very different code for resync and recovery. |
1674 | * Both must result in an r10bio with a list of bios that | 1679 | * Both must result in an r10bio with a list of bios that |
1675 | * have bi_end_io, bi_sector, bi_bdev set, | 1680 | * have bi_end_io, bi_sector, bi_bdev set, |
@@ -2021,7 +2026,7 @@ static int run(mddev_t *mddev) | |||
2021 | goto out_free_conf; | 2026 | goto out_free_conf; |
2022 | } | 2027 | } |
2023 | 2028 | ||
2024 | ITERATE_RDEV(mddev, rdev, tmp) { | 2029 | rdev_for_each(rdev, tmp, mddev) { |
2025 | disk_idx = rdev->raid_disk; | 2030 | disk_idx = rdev->raid_disk; |
2026 | if (disk_idx >= mddev->raid_disks | 2031 | if (disk_idx >= mddev->raid_disks |
2027 | || disk_idx < 0) | 2032 | || disk_idx < 0) |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e8c8157b02fc..2d6f1a51359c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3159,7 +3159,8 @@ static void raid5_activate_delayed(raid5_conf_t *conf) | |||
3159 | atomic_inc(&conf->preread_active_stripes); | 3159 | atomic_inc(&conf->preread_active_stripes); |
3160 | list_add_tail(&sh->lru, &conf->handle_list); | 3160 | list_add_tail(&sh->lru, &conf->handle_list); |
3161 | } | 3161 | } |
3162 | } | 3162 | } else |
3163 | blk_plug_device(conf->mddev->queue); | ||
3163 | } | 3164 | } |
3164 | 3165 | ||
3165 | static void activate_bit_delay(raid5_conf_t *conf) | 3166 | static void activate_bit_delay(raid5_conf_t *conf) |
@@ -3549,7 +3550,8 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
3549 | goto retry; | 3550 | goto retry; |
3550 | } | 3551 | } |
3551 | finish_wait(&conf->wait_for_overlap, &w); | 3552 | finish_wait(&conf->wait_for_overlap, &w); |
3552 | handle_stripe(sh, NULL); | 3553 | set_bit(STRIPE_HANDLE, &sh->state); |
3554 | clear_bit(STRIPE_DELAYED, &sh->state); | ||
3553 | release_stripe(sh); | 3555 | release_stripe(sh); |
3554 | } else { | 3556 | } else { |
3555 | /* cannot get stripe for read-ahead, just give-up */ | 3557 | /* cannot get stripe for read-ahead, just give-up */ |
@@ -3698,6 +3700,25 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
3698 | release_stripe(sh); | 3700 | release_stripe(sh); |
3699 | first_sector += STRIPE_SECTORS; | 3701 | first_sector += STRIPE_SECTORS; |
3700 | } | 3702 | } |
3703 | /* If this takes us to the resync_max point where we have to pause, | ||
3704 | * then we need to write out the superblock. | ||
3705 | */ | ||
3706 | sector_nr += conf->chunk_size>>9; | ||
3707 | if (sector_nr >= mddev->resync_max) { | ||
3708 | /* Cannot proceed until we've updated the superblock... */ | ||
3709 | wait_event(conf->wait_for_overlap, | ||
3710 | atomic_read(&conf->reshape_stripes) == 0); | ||
3711 | mddev->reshape_position = conf->expand_progress; | ||
3712 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | ||
3713 | md_wakeup_thread(mddev->thread); | ||
3714 | wait_event(mddev->sb_wait, | ||
3715 | !test_bit(MD_CHANGE_DEVS, &mddev->flags) | ||
3716 | || kthread_should_stop()); | ||
3717 | spin_lock_irq(&conf->device_lock); | ||
3718 | conf->expand_lo = mddev->reshape_position; | ||
3719 | spin_unlock_irq(&conf->device_lock); | ||
3720 | wake_up(&conf->wait_for_overlap); | ||
3721 | } | ||
3701 | return conf->chunk_size>>9; | 3722 | return conf->chunk_size>>9; |
3702 | } | 3723 | } |
3703 | 3724 | ||
@@ -3734,6 +3755,12 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
3734 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) | 3755 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) |
3735 | return reshape_request(mddev, sector_nr, skipped); | 3756 | return reshape_request(mddev, sector_nr, skipped); |
3736 | 3757 | ||
3758 | /* No need to check resync_max as we never do more than one | ||
3759 | * stripe, and as resync_max will always be on a chunk boundary, | ||
3760 | * if the check in md_do_sync didn't fire, there is no chance | ||
3761 | * of overstepping resync_max here | ||
3762 | */ | ||
3763 | |||
3737 | /* if there is too many failed drives and we are trying | 3764 | /* if there is too many failed drives and we are trying |
3738 | * to resync, then assert that we are finished, because there is | 3765 | * to resync, then assert that we are finished, because there is |
3739 | * nothing we can do. | 3766 | * nothing we can do. |
@@ -3753,6 +3780,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
3753 | return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ | 3780 | return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ |
3754 | } | 3781 | } |
3755 | 3782 | ||
3783 | |||
3784 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
3785 | |||
3756 | pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks); | 3786 | pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks); |
3757 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); | 3787 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); |
3758 | if (sh == NULL) { | 3788 | if (sh == NULL) { |
@@ -3864,7 +3894,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) | |||
3864 | * During the scan, completed stripes are saved for us by the interrupt | 3894 | * During the scan, completed stripes are saved for us by the interrupt |
3865 | * handler, so that they will not have to wait for our next wakeup. | 3895 | * handler, so that they will not have to wait for our next wakeup. |
3866 | */ | 3896 | */ |
3867 | static void raid5d (mddev_t *mddev) | 3897 | static void raid5d(mddev_t *mddev) |
3868 | { | 3898 | { |
3869 | struct stripe_head *sh; | 3899 | struct stripe_head *sh; |
3870 | raid5_conf_t *conf = mddev_to_conf(mddev); | 3900 | raid5_conf_t *conf = mddev_to_conf(mddev); |
@@ -3889,12 +3919,6 @@ static void raid5d (mddev_t *mddev) | |||
3889 | activate_bit_delay(conf); | 3919 | activate_bit_delay(conf); |
3890 | } | 3920 | } |
3891 | 3921 | ||
3892 | if (list_empty(&conf->handle_list) && | ||
3893 | atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD && | ||
3894 | !blk_queue_plugged(mddev->queue) && | ||
3895 | !list_empty(&conf->delayed_list)) | ||
3896 | raid5_activate_delayed(conf); | ||
3897 | |||
3898 | while ((bio = remove_bio_from_retry(conf))) { | 3922 | while ((bio = remove_bio_from_retry(conf))) { |
3899 | int ok; | 3923 | int ok; |
3900 | spin_unlock_irq(&conf->device_lock); | 3924 | spin_unlock_irq(&conf->device_lock); |
@@ -4108,7 +4132,7 @@ static int run(mddev_t *mddev) | |||
4108 | 4132 | ||
4109 | pr_debug("raid5: run(%s) called.\n", mdname(mddev)); | 4133 | pr_debug("raid5: run(%s) called.\n", mdname(mddev)); |
4110 | 4134 | ||
4111 | ITERATE_RDEV(mddev,rdev,tmp) { | 4135 | rdev_for_each(rdev, tmp, mddev) { |
4112 | raid_disk = rdev->raid_disk; | 4136 | raid_disk = rdev->raid_disk; |
4113 | if (raid_disk >= conf->raid_disks | 4137 | if (raid_disk >= conf->raid_disks |
4114 | || raid_disk < 0) | 4138 | || raid_disk < 0) |
@@ -4521,7 +4545,7 @@ static int raid5_start_reshape(mddev_t *mddev) | |||
4521 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | 4545 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) |
4522 | return -EBUSY; | 4546 | return -EBUSY; |
4523 | 4547 | ||
4524 | ITERATE_RDEV(mddev, rdev, rtmp) | 4548 | rdev_for_each(rdev, rtmp, mddev) |
4525 | if (rdev->raid_disk < 0 && | 4549 | if (rdev->raid_disk < 0 && |
4526 | !test_bit(Faulty, &rdev->flags)) | 4550 | !test_bit(Faulty, &rdev->flags)) |
4527 | spares++; | 4551 | spares++; |
@@ -4543,7 +4567,7 @@ static int raid5_start_reshape(mddev_t *mddev) | |||
4543 | /* Add some new drives, as many as will fit. | 4567 | /* Add some new drives, as many as will fit. |
4544 | * We know there are enough to make the newly sized array work. | 4568 | * We know there are enough to make the newly sized array work. |
4545 | */ | 4569 | */ |
4546 | ITERATE_RDEV(mddev, rdev, rtmp) | 4570 | rdev_for_each(rdev, rtmp, mddev) |
4547 | if (rdev->raid_disk < 0 && | 4571 | if (rdev->raid_disk < 0 && |
4548 | !test_bit(Faulty, &rdev->flags)) { | 4572 | !test_bit(Faulty, &rdev->flags)) { |
4549 | if (raid5_add_disk(mddev, rdev)) { | 4573 | if (raid5_add_disk(mddev, rdev)) { |
diff --git a/drivers/md/raid6test/test.c b/drivers/md/raid6test/test.c index 0d5cd57accd7..559cc41b2585 100644 --- a/drivers/md/raid6test/test.c +++ b/drivers/md/raid6test/test.c | |||
@@ -1,12 +1,10 @@ | |||
1 | /* -*- linux-c -*- ------------------------------------------------------- * | 1 | /* -*- linux-c -*- ------------------------------------------------------- * |
2 | * | 2 | * |
3 | * Copyright 2002 H. Peter Anvin - All Rights Reserved | 3 | * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This file is part of the Linux kernel, and is made available under |
6 | * it under the terms of the GNU General Public License as published by | 6 | * the terms of the GNU General Public License version 2 or (at your |
7 | * the Free Software Foundation, Inc., 53 Temple Place Ste 330, | 7 | * option) any later version; incorporated herein by reference. |
8 | * Bostom MA 02111-1307, USA; either version 2 of the License, or | ||
9 | * (at your option) any later version; incorporated herein by reference. | ||
10 | * | 8 | * |
11 | * ----------------------------------------------------------------------- */ | 9 | * ----------------------------------------------------------------------- */ |
12 | 10 | ||
@@ -30,67 +28,87 @@ char *dataptrs[NDISKS]; | |||
30 | char data[NDISKS][PAGE_SIZE]; | 28 | char data[NDISKS][PAGE_SIZE]; |
31 | char recovi[PAGE_SIZE], recovj[PAGE_SIZE]; | 29 | char recovi[PAGE_SIZE], recovj[PAGE_SIZE]; |
32 | 30 | ||
33 | void makedata(void) | 31 | static void makedata(void) |
34 | { | 32 | { |
35 | int i, j; | 33 | int i, j; |
36 | 34 | ||
37 | for ( i = 0 ; i < NDISKS ; i++ ) { | 35 | for (i = 0; i < NDISKS; i++) { |
38 | for ( j = 0 ; j < PAGE_SIZE ; j++ ) { | 36 | for (j = 0; j < PAGE_SIZE; j++) |
39 | data[i][j] = rand(); | 37 | data[i][j] = rand(); |
40 | } | 38 | |
41 | dataptrs[i] = data[i]; | 39 | dataptrs[i] = data[i]; |
42 | } | 40 | } |
43 | } | 41 | } |
44 | 42 | ||
43 | static char disk_type(int d) | ||
44 | { | ||
45 | switch (d) { | ||
46 | case NDISKS-2: | ||
47 | return 'P'; | ||
48 | case NDISKS-1: | ||
49 | return 'Q'; | ||
50 | default: | ||
51 | return 'D'; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static int test_disks(int i, int j) | ||
56 | { | ||
57 | int erra, errb; | ||
58 | |||
59 | memset(recovi, 0xf0, PAGE_SIZE); | ||
60 | memset(recovj, 0xba, PAGE_SIZE); | ||
61 | |||
62 | dataptrs[i] = recovi; | ||
63 | dataptrs[j] = recovj; | ||
64 | |||
65 | raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); | ||
66 | |||
67 | erra = memcmp(data[i], recovi, PAGE_SIZE); | ||
68 | errb = memcmp(data[j], recovj, PAGE_SIZE); | ||
69 | |||
70 | if (i < NDISKS-2 && j == NDISKS-1) { | ||
71 | /* We don't implement the DQ failure scenario, since it's | ||
72 | equivalent to a RAID-5 failure (XOR, then recompute Q) */ | ||
73 | erra = errb = 0; | ||
74 | } else { | ||
75 | printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n", | ||
76 | raid6_call.name, | ||
77 | i, disk_type(i), | ||
78 | j, disk_type(j), | ||
79 | (!erra && !errb) ? "OK" : | ||
80 | !erra ? "ERRB" : | ||
81 | !errb ? "ERRA" : "ERRAB"); | ||
82 | } | ||
83 | |||
84 | dataptrs[i] = data[i]; | ||
85 | dataptrs[j] = data[j]; | ||
86 | |||
87 | return erra || errb; | ||
88 | } | ||
89 | |||
45 | int main(int argc, char *argv[]) | 90 | int main(int argc, char *argv[]) |
46 | { | 91 | { |
47 | const struct raid6_calls * const * algo; | 92 | const struct raid6_calls *const *algo; |
48 | int i, j; | 93 | int i, j; |
49 | int erra, errb; | 94 | int err = 0; |
50 | 95 | ||
51 | makedata(); | 96 | makedata(); |
52 | 97 | ||
53 | for ( algo = raid6_algos ; *algo ; algo++ ) { | 98 | for (algo = raid6_algos; *algo; algo++) { |
54 | if ( !(*algo)->valid || (*algo)->valid() ) { | 99 | if (!(*algo)->valid || (*algo)->valid()) { |
55 | raid6_call = **algo; | 100 | raid6_call = **algo; |
56 | 101 | ||
57 | /* Nuke syndromes */ | 102 | /* Nuke syndromes */ |
58 | memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE); | 103 | memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE); |
59 | 104 | ||
60 | /* Generate assumed good syndrome */ | 105 | /* Generate assumed good syndrome */ |
61 | raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, (void **)&dataptrs); | 106 | raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, |
62 | 107 | (void **)&dataptrs); | |
63 | for ( i = 0 ; i < NDISKS-1 ; i++ ) { | 108 | |
64 | for ( j = i+1 ; j < NDISKS ; j++ ) { | 109 | for (i = 0; i < NDISKS-1; i++) |
65 | memset(recovi, 0xf0, PAGE_SIZE); | 110 | for (j = i+1; j < NDISKS; j++) |
66 | memset(recovj, 0xba, PAGE_SIZE); | 111 | err += test_disks(i, j); |
67 | |||
68 | dataptrs[i] = recovi; | ||
69 | dataptrs[j] = recovj; | ||
70 | |||
71 | raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); | ||
72 | |||
73 | erra = memcmp(data[i], recovi, PAGE_SIZE); | ||
74 | errb = memcmp(data[j], recovj, PAGE_SIZE); | ||
75 | |||
76 | if ( i < NDISKS-2 && j == NDISKS-1 ) { | ||
77 | /* We don't implement the DQ failure scenario, since it's | ||
78 | equivalent to a RAID-5 failure (XOR, then recompute Q) */ | ||
79 | } else { | ||
80 | printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n", | ||
81 | raid6_call.name, | ||
82 | i, (i==NDISKS-2)?'P':'D', | ||
83 | j, (j==NDISKS-1)?'Q':(j==NDISKS-2)?'P':'D', | ||
84 | (!erra && !errb) ? "OK" : | ||
85 | !erra ? "ERRB" : | ||
86 | !errb ? "ERRA" : | ||
87 | "ERRAB"); | ||
88 | } | ||
89 | |||
90 | dataptrs[i] = data[i]; | ||
91 | dataptrs[j] = data[j]; | ||
92 | } | ||
93 | } | ||
94 | } | 112 | } |
95 | printf("\n"); | 113 | printf("\n"); |
96 | } | 114 | } |
@@ -99,5 +117,8 @@ int main(int argc, char *argv[]) | |||
99 | /* Pick the best algorithm test */ | 117 | /* Pick the best algorithm test */ |
100 | raid6_select_algo(); | 118 | raid6_select_algo(); |
101 | 119 | ||
102 | return 0; | 120 | if (err) |
121 | printf("\n*** ERRORS FOUND ***\n"); | ||
122 | |||
123 | return err; | ||
103 | } | 124 | } |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 28ddd146c1c5..850b8c6f4577 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -22,7 +22,6 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o | |||
22 | obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o | 22 | obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o |
23 | obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o | 23 | obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o |
24 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o | 24 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o |
25 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o | ||
26 | 25 | ||
27 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o | 26 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o |
28 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o | 27 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o |
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c deleted file mode 100644 index 9fa5b702e073..000000000000 --- a/drivers/media/video/tvmixer.c +++ /dev/null | |||
@@ -1,336 +0,0 @@ | |||
1 | /* | ||
2 | */ | ||
3 | |||
4 | #include <linux/module.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/string.h> | ||
7 | #include <linux/timer.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/i2c.h> | ||
12 | #include <linux/videodev.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kdev_t.h> | ||
15 | #include <linux/sound.h> | ||
16 | #include <linux/soundcard.h> | ||
17 | |||
18 | #include <asm/semaphore.h> | ||
19 | #include <asm/uaccess.h> | ||
20 | |||
21 | |||
22 | #define DEV_MAX 4 | ||
23 | |||
24 | static int devnr = -1; | ||
25 | module_param(devnr, int, 0644); | ||
26 | |||
27 | MODULE_AUTHOR("Gerd Knorr"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* ----------------------------------------------------------------------- */ | ||
31 | |||
32 | struct TVMIXER { | ||
33 | struct i2c_client *dev; | ||
34 | int minor; | ||
35 | int count; | ||
36 | }; | ||
37 | |||
38 | static struct TVMIXER devices[DEV_MAX]; | ||
39 | |||
40 | static int tvmixer_adapters(struct i2c_adapter *adap); | ||
41 | static int tvmixer_clients(struct i2c_client *client); | ||
42 | |||
43 | /* ----------------------------------------------------------------------- */ | ||
44 | |||
45 | static int mix_to_v4l(int i) | ||
46 | { | ||
47 | int r; | ||
48 | |||
49 | r = ((i & 0xff) * 65536 + 50) / 100; | ||
50 | if (r > 65535) r = 65535; | ||
51 | if (r < 0) r = 0; | ||
52 | return r; | ||
53 | } | ||
54 | |||
55 | static int v4l_to_mix(int i) | ||
56 | { | ||
57 | int r; | ||
58 | |||
59 | r = (i * 100 + 32768) / 65536; | ||
60 | if (r > 100) r = 100; | ||
61 | if (r < 0) r = 0; | ||
62 | return r | (r << 8); | ||
63 | } | ||
64 | |||
65 | static int v4l_to_mix2(int l, int r) | ||
66 | { | ||
67 | r = (r * 100 + 32768) / 65536; | ||
68 | if (r > 100) r = 100; | ||
69 | if (r < 0) r = 0; | ||
70 | l = (l * 100 + 32768) / 65536; | ||
71 | if (l > 100) l = 100; | ||
72 | if (l < 0) l = 0; | ||
73 | return (r << 8) | l; | ||
74 | } | ||
75 | |||
76 | static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
77 | { | ||
78 | struct video_audio va; | ||
79 | int left,right,ret,val = 0; | ||
80 | struct TVMIXER *mix = file->private_data; | ||
81 | struct i2c_client *client = mix->dev; | ||
82 | void __user *argp = (void __user *)arg; | ||
83 | int __user *p = argp; | ||
84 | |||
85 | if (NULL == client) | ||
86 | return -ENODEV; | ||
87 | |||
88 | if (cmd == SOUND_MIXER_INFO) { | ||
89 | mixer_info info; | ||
90 | strlcpy(info.id, "tv card", sizeof(info.id)); | ||
91 | strlcpy(info.name, client->name, sizeof(info.name)); | ||
92 | info.modify_counter = 42 /* FIXME */; | ||
93 | if (copy_to_user(argp, &info, sizeof(info))) | ||
94 | return -EFAULT; | ||
95 | return 0; | ||
96 | } | ||
97 | if (cmd == SOUND_OLD_MIXER_INFO) { | ||
98 | _old_mixer_info info; | ||
99 | strlcpy(info.id, "tv card", sizeof(info.id)); | ||
100 | strlcpy(info.name, client->name, sizeof(info.name)); | ||
101 | if (copy_to_user(argp, &info, sizeof(info))) | ||
102 | return -EFAULT; | ||
103 | return 0; | ||
104 | } | ||
105 | if (cmd == OSS_GETVERSION) | ||
106 | return put_user(SOUND_VERSION, p); | ||
107 | |||
108 | if (_SIOC_DIR(cmd) & _SIOC_WRITE) | ||
109 | if (get_user(val, p)) | ||
110 | return -EFAULT; | ||
111 | |||
112 | /* read state */ | ||
113 | memset(&va,0,sizeof(va)); | ||
114 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
115 | |||
116 | switch (cmd) { | ||
117 | case MIXER_READ(SOUND_MIXER_RECMASK): | ||
118 | case MIXER_READ(SOUND_MIXER_CAPS): | ||
119 | case MIXER_READ(SOUND_MIXER_RECSRC): | ||
120 | case MIXER_WRITE(SOUND_MIXER_RECSRC): | ||
121 | ret = 0; | ||
122 | break; | ||
123 | |||
124 | case MIXER_READ(SOUND_MIXER_STEREODEVS): | ||
125 | ret = SOUND_MASK_VOLUME; | ||
126 | break; | ||
127 | case MIXER_READ(SOUND_MIXER_DEVMASK): | ||
128 | ret = SOUND_MASK_VOLUME; | ||
129 | if (va.flags & VIDEO_AUDIO_BASS) | ||
130 | ret |= SOUND_MASK_BASS; | ||
131 | if (va.flags & VIDEO_AUDIO_TREBLE) | ||
132 | ret |= SOUND_MASK_TREBLE; | ||
133 | break; | ||
134 | |||
135 | case MIXER_WRITE(SOUND_MIXER_VOLUME): | ||
136 | left = mix_to_v4l(val); | ||
137 | right = mix_to_v4l(val >> 8); | ||
138 | va.volume = max(left,right); | ||
139 | va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1); | ||
140 | va.balance = (left<right) ? (65535-va.balance) : va.balance; | ||
141 | if (va.volume) | ||
142 | va.flags &= ~VIDEO_AUDIO_MUTE; | ||
143 | client->driver->command(client,VIDIOCSAUDIO,&va); | ||
144 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
145 | /* fall throuth */ | ||
146 | case MIXER_READ(SOUND_MIXER_VOLUME): | ||
147 | left = (min(65536 - va.balance,32768) * | ||
148 | va.volume) / 32768; | ||
149 | right = (min(va.balance,(u16)32768) * | ||
150 | va.volume) / 32768; | ||
151 | ret = v4l_to_mix2(left,right); | ||
152 | break; | ||
153 | |||
154 | case MIXER_WRITE(SOUND_MIXER_BASS): | ||
155 | va.bass = mix_to_v4l(val); | ||
156 | client->driver->command(client,VIDIOCSAUDIO,&va); | ||
157 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
158 | /* fall throuth */ | ||
159 | case MIXER_READ(SOUND_MIXER_BASS): | ||
160 | ret = v4l_to_mix(va.bass); | ||
161 | break; | ||
162 | |||
163 | case MIXER_WRITE(SOUND_MIXER_TREBLE): | ||
164 | va.treble = mix_to_v4l(val); | ||
165 | client->driver->command(client,VIDIOCSAUDIO,&va); | ||
166 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
167 | /* fall throuth */ | ||
168 | case MIXER_READ(SOUND_MIXER_TREBLE): | ||
169 | ret = v4l_to_mix(va.treble); | ||
170 | break; | ||
171 | |||
172 | default: | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | if (put_user(ret, p)) | ||
176 | return -EFAULT; | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int tvmixer_open(struct inode *inode, struct file *file) | ||
181 | { | ||
182 | int i, minor = iminor(inode); | ||
183 | struct TVMIXER *mix = NULL; | ||
184 | struct i2c_client *client = NULL; | ||
185 | |||
186 | for (i = 0; i < DEV_MAX; i++) { | ||
187 | if (devices[i].minor == minor) { | ||
188 | mix = devices+i; | ||
189 | client = mix->dev; | ||
190 | break; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | if (NULL == client) | ||
195 | return -ENODEV; | ||
196 | |||
197 | /* lock bttv in memory while the mixer is in use */ | ||
198 | file->private_data = mix; | ||
199 | if (client->adapter->owner) | ||
200 | try_module_get(client->adapter->owner); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int tvmixer_release(struct inode *inode, struct file *file) | ||
205 | { | ||
206 | struct TVMIXER *mix = file->private_data; | ||
207 | struct i2c_client *client; | ||
208 | |||
209 | client = mix->dev; | ||
210 | if (NULL == client) { | ||
211 | return -ENODEV; | ||
212 | } | ||
213 | |||
214 | module_put(client->adapter->owner); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static struct i2c_driver driver = { | ||
219 | .driver = { | ||
220 | .name = "tvmixer", | ||
221 | }, | ||
222 | .id = I2C_DRIVERID_TVMIXER, | ||
223 | .detach_adapter = tvmixer_adapters, | ||
224 | .attach_adapter = tvmixer_adapters, | ||
225 | .detach_client = tvmixer_clients, | ||
226 | }; | ||
227 | |||
228 | static const struct file_operations tvmixer_fops = { | ||
229 | .owner = THIS_MODULE, | ||
230 | .llseek = no_llseek, | ||
231 | .ioctl = tvmixer_ioctl, | ||
232 | .open = tvmixer_open, | ||
233 | .release = tvmixer_release, | ||
234 | }; | ||
235 | |||
236 | /* ----------------------------------------------------------------------- */ | ||
237 | |||
238 | static int tvmixer_adapters(struct i2c_adapter *adap) | ||
239 | { | ||
240 | struct i2c_client *client; | ||
241 | |||
242 | list_for_each_entry(client, &adap->clients, list) | ||
243 | tvmixer_clients(client); | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int tvmixer_clients(struct i2c_client *client) | ||
248 | { | ||
249 | struct video_audio va; | ||
250 | int i,minor; | ||
251 | |||
252 | if (!(client->adapter->class & I2C_CLASS_TV_ANALOG)) | ||
253 | return -1; | ||
254 | |||
255 | /* unregister ?? */ | ||
256 | for (i = 0; i < DEV_MAX; i++) { | ||
257 | if (devices[i].dev == client) { | ||
258 | /* unregister */ | ||
259 | unregister_sound_mixer(devices[i].minor); | ||
260 | devices[i].dev = NULL; | ||
261 | devices[i].minor = -1; | ||
262 | printk("tvmixer: %s unregistered (#1)\n", | ||
263 | client->name); | ||
264 | return 0; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | /* look for a free slot */ | ||
269 | for (i = 0; i < DEV_MAX; i++) | ||
270 | if (NULL == devices[i].dev) | ||
271 | break; | ||
272 | if (i == DEV_MAX) { | ||
273 | printk(KERN_WARNING "tvmixer: DEV_MAX too small\n"); | ||
274 | return -1; | ||
275 | } | ||
276 | |||
277 | /* audio chip with mixer ??? */ | ||
278 | if (NULL == client->driver->command) | ||
279 | return -1; | ||
280 | memset(&va,0,sizeof(va)); | ||
281 | if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) | ||
282 | return -1; | ||
283 | if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) | ||
284 | return -1; | ||
285 | |||
286 | /* everything is fine, register */ | ||
287 | if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) { | ||
288 | printk(KERN_ERR "tvmixer: cannot allocate mixer device\n"); | ||
289 | return -1; | ||
290 | } | ||
291 | |||
292 | devices[i].minor = minor; | ||
293 | devices[i].count = 0; | ||
294 | devices[i].dev = client; | ||
295 | printk("tvmixer: %s (%s) registered with minor %d\n", | ||
296 | client->name,client->adapter->name,minor); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | /* ----------------------------------------------------------------------- */ | ||
302 | |||
303 | static int __init tvmixer_init_module(void) | ||
304 | { | ||
305 | int i; | ||
306 | |||
307 | for (i = 0; i < DEV_MAX; i++) | ||
308 | devices[i].minor = -1; | ||
309 | |||
310 | return i2c_add_driver(&driver); | ||
311 | } | ||
312 | |||
313 | static void __exit tvmixer_cleanup_module(void) | ||
314 | { | ||
315 | int i; | ||
316 | |||
317 | i2c_del_driver(&driver); | ||
318 | for (i = 0; i < DEV_MAX; i++) { | ||
319 | if (devices[i].minor != -1) { | ||
320 | unregister_sound_mixer(devices[i].minor); | ||
321 | printk("tvmixer: %s unregistered (#2)\n", | ||
322 | devices[i].dev->name); | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | |||
327 | module_init(tvmixer_init_module); | ||
328 | module_exit(tvmixer_cleanup_module); | ||
329 | |||
330 | /* | ||
331 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
332 | * --------------------------------------------------------------------------- | ||
333 | * Local variables: | ||
334 | * c-basic-offset: 8 | ||
335 | * End: | ||
336 | */ | ||
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 7dce318df1bd..0846c33296bc 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c | |||
@@ -33,7 +33,6 @@ | |||
33 | * Sam Lin - GPS support | 33 | * Sam Lin - GPS support |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <linux/autoconf.h> | ||
37 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
38 | #include <linux/module.h> | 37 | #include <linux/module.h> |
39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index c8d62c268b11..1cfd7f3f1294 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <linux/dmi.h> | 50 | #include <linux/dmi.h> |
51 | #include <linux/backlight.h> | 51 | #include <linux/backlight.h> |
52 | #include <linux/platform_device.h> | 52 | #include <linux/platform_device.h> |
53 | #include <linux/autoconf.h> | ||
54 | 53 | ||
55 | #define FUJITSU_DRIVER_VERSION "0.3" | 54 | #define FUJITSU_DRIVER_VERSION "0.3" |
56 | 55 | ||
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 552b7957a92a..c884730c5eaf 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -129,27 +129,28 @@ module_param(cpoint_count, int, 0644); | |||
129 | MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ | 129 | MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ |
130 | "crash point is to be hit to trigger action"); | 130 | "crash point is to be hit to trigger action"); |
131 | 131 | ||
132 | unsigned int jp_do_irq(unsigned int irq) | 132 | static unsigned int jp_do_irq(unsigned int irq) |
133 | { | 133 | { |
134 | lkdtm_handler(); | 134 | lkdtm_handler(); |
135 | jprobe_return(); | 135 | jprobe_return(); |
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
138 | 138 | ||
139 | irqreturn_t jp_handle_irq_event(unsigned int irq, struct irqaction *action) | 139 | static irqreturn_t jp_handle_irq_event(unsigned int irq, |
140 | struct irqaction *action) | ||
140 | { | 141 | { |
141 | lkdtm_handler(); | 142 | lkdtm_handler(); |
142 | jprobe_return(); | 143 | jprobe_return(); |
143 | return 0; | 144 | return 0; |
144 | } | 145 | } |
145 | 146 | ||
146 | void jp_tasklet_action(struct softirq_action *a) | 147 | static void jp_tasklet_action(struct softirq_action *a) |
147 | { | 148 | { |
148 | lkdtm_handler(); | 149 | lkdtm_handler(); |
149 | jprobe_return(); | 150 | jprobe_return(); |
150 | } | 151 | } |
151 | 152 | ||
152 | void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) | 153 | static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) |
153 | { | 154 | { |
154 | lkdtm_handler(); | 155 | lkdtm_handler(); |
155 | jprobe_return(); | 156 | jprobe_return(); |
@@ -157,23 +158,24 @@ void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) | |||
157 | 158 | ||
158 | struct scan_control; | 159 | struct scan_control; |
159 | 160 | ||
160 | unsigned long jp_shrink_inactive_list(unsigned long max_scan, | 161 | static unsigned long jp_shrink_inactive_list(unsigned long max_scan, |
161 | struct zone *zone, struct scan_control *sc) | 162 | struct zone *zone, |
163 | struct scan_control *sc) | ||
162 | { | 164 | { |
163 | lkdtm_handler(); | 165 | lkdtm_handler(); |
164 | jprobe_return(); | 166 | jprobe_return(); |
165 | return 0; | 167 | return 0; |
166 | } | 168 | } |
167 | 169 | ||
168 | int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim, | 170 | static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim, |
169 | const enum hrtimer_mode mode) | 171 | const enum hrtimer_mode mode) |
170 | { | 172 | { |
171 | lkdtm_handler(); | 173 | lkdtm_handler(); |
172 | jprobe_return(); | 174 | jprobe_return(); |
173 | return 0; | 175 | return 0; |
174 | } | 176 | } |
175 | 177 | ||
176 | int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd) | 178 | static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd) |
177 | { | 179 | { |
178 | lkdtm_handler(); | 180 | lkdtm_handler(); |
179 | jprobe_return(); | 181 | jprobe_return(); |
@@ -270,7 +272,7 @@ void lkdtm_handler(void) | |||
270 | } | 272 | } |
271 | } | 273 | } |
272 | 274 | ||
273 | int lkdtm_module_init(void) | 275 | static int __init lkdtm_module_init(void) |
274 | { | 276 | { |
275 | int ret; | 277 | int ret; |
276 | 278 | ||
@@ -331,7 +333,7 @@ int lkdtm_module_init(void) | |||
331 | return 0; | 333 | return 0; |
332 | } | 334 | } |
333 | 335 | ||
334 | void lkdtm_module_exit(void) | 336 | static void __exit lkdtm_module_exit(void) |
335 | { | 337 | { |
336 | unregister_jprobe(&lkdtm); | 338 | unregister_jprobe(&lkdtm); |
337 | printk(KERN_INFO "lkdtm : Crash point unregistered\n"); | 339 | printk(KERN_INFO "lkdtm : Crash point unregistered\n"); |
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c index 83679c762925..de898c6938f3 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c | |||
@@ -58,7 +58,6 @@ | |||
58 | #include <linux/dmi.h> | 58 | #include <linux/dmi.h> |
59 | #include <linux/backlight.h> | 59 | #include <linux/backlight.h> |
60 | #include <linux/platform_device.h> | 60 | #include <linux/platform_device.h> |
61 | #include <linux/autoconf.h> | ||
62 | 61 | ||
63 | #define MSI_DRIVER_VERSION "0.5" | 62 | #define MSI_DRIVER_VERSION "0.5" |
64 | 63 | ||
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index cd221fd0fb94..7fa61e907e1c 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <asm/atomic.h> | 25 | #include <asm/atomic.h> |
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | 27 | ||
28 | #define PHANTOM_VERSION "n0.9.7" | 28 | #define PHANTOM_VERSION "n0.9.8" |
29 | 29 | ||
30 | #define PHANTOM_MAX_MINORS 8 | 30 | #define PHANTOM_MAX_MINORS 8 |
31 | 31 | ||
@@ -456,8 +456,9 @@ static int phantom_resume(struct pci_dev *pdev) | |||
456 | #endif | 456 | #endif |
457 | 457 | ||
458 | static struct pci_device_id phantom_pci_tbl[] __devinitdata = { | 458 | static struct pci_device_id phantom_pci_tbl[] __devinitdata = { |
459 | { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050), | 459 | { .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050, |
460 | .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 }, | 460 | .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050, |
461 | .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 }, | ||
461 | { 0, } | 462 | { 0, } |
462 | }; | 463 | }; |
463 | MODULE_DEVICE_TABLE(pci, phantom_pci_tbl); | 464 | MODULE_DEVICE_TABLE(pci, phantom_pci_tbl); |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index be4b9948c762..eeaaa9dce6ef 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * block2mtd.c - create an mtd from a block device | 4 | * block2mtd.c - create an mtd from a block device |
5 | * | 5 | * |
6 | * Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk> | 6 | * Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk> |
7 | * Copyright (C) 2004-2006 Jörn Engel <joern@wh.fh-wedel.de> | 7 | * Copyright (C) 2004-2006 Joern Engel <joern@wh.fh-wedel.de> |
8 | * | 8 | * |
9 | * Licence: GPL | 9 | * Licence: GPL |
10 | */ | 10 | */ |
@@ -485,5 +485,5 @@ module_init(block2mtd_init); | |||
485 | module_exit(block2mtd_exit); | 485 | module_exit(block2mtd_exit); |
486 | 486 | ||
487 | MODULE_LICENSE("GPL"); | 487 | MODULE_LICENSE("GPL"); |
488 | MODULE_AUTHOR("Simon Evans <spse@secret.org.uk> and others"); | 488 | MODULE_AUTHOR("Joern Engel <joern@lazybastard.org>"); |
489 | MODULE_DESCRIPTION("Emulate an MTD using a block device"); | 489 | MODULE_DESCRIPTION("Emulate an MTD using a block device"); |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 56cc1ca7ffd5..180298b92a7a 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $ | 2 | * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $ |
3 | * | 3 | * |
4 | * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de> | 4 | * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de> |
5 | * Copyright (c) 2003-2004 Jörn Engel <joern@wh.fh-wedel.de> | 5 | * Copyright (c) 2003-2004 Joern Engel <joern@wh.fh-wedel.de> |
6 | * | 6 | * |
7 | * Usage: | 7 | * Usage: |
8 | * | 8 | * |
@@ -299,5 +299,5 @@ module_init(init_phram); | |||
299 | module_exit(cleanup_phram); | 299 | module_exit(cleanup_phram); |
300 | 300 | ||
301 | MODULE_LICENSE("GPL"); | 301 | MODULE_LICENSE("GPL"); |
302 | MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>"); | 302 | MODULE_AUTHOR("Joern Engel <joern@wh.fh-wedel.de>"); |
303 | MODULE_DESCRIPTION("MTD driver for physical RAM"); | 303 | MODULE_DESCRIPTION("MTD driver for physical RAM"); |
diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c index d884f2be28f6..2a8fde9b92f0 100644 --- a/drivers/mtd/maps/mtx-1_flash.c +++ b/drivers/mtd/maps/mtx-1_flash.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $ | 4 | * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $ |
5 | * | 5 | * |
6 | * (C) 2005 Bruno Randolf <bruno.randolf@4g-systems.biz> | 6 | * (C) 2005 Bruno Randolf <bruno.randolf@4g-systems.biz> |
7 | * (C) 2005 Jörn Engel <joern@wohnheim.fh-wedel.de> | 7 | * (C) 2005 Joern Engel <joern@wohnheim.fh-wedel.de> |
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 36342230a6de..d4843d014bc9 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -323,8 +323,8 @@ enum { | |||
323 | NvRegMIIStatus = 0x180, | 323 | NvRegMIIStatus = 0x180, |
324 | #define NVREG_MIISTAT_ERROR 0x0001 | 324 | #define NVREG_MIISTAT_ERROR 0x0001 |
325 | #define NVREG_MIISTAT_LINKCHANGE 0x0008 | 325 | #define NVREG_MIISTAT_LINKCHANGE 0x0008 |
326 | #define NVREG_MIISTAT_MASK 0x000f | 326 | #define NVREG_MIISTAT_MASK_RW 0x0007 |
327 | #define NVREG_MIISTAT_MASK2 0x000f | 327 | #define NVREG_MIISTAT_MASK_ALL 0x000f |
328 | NvRegMIIMask = 0x184, | 328 | NvRegMIIMask = 0x184, |
329 | #define NVREG_MII_LINKCHANGE 0x0008 | 329 | #define NVREG_MII_LINKCHANGE 0x0008 |
330 | 330 | ||
@@ -624,6 +624,9 @@ union ring_type { | |||
624 | #define NV_MSI_X_VECTOR_TX 0x1 | 624 | #define NV_MSI_X_VECTOR_TX 0x1 |
625 | #define NV_MSI_X_VECTOR_OTHER 0x2 | 625 | #define NV_MSI_X_VECTOR_OTHER 0x2 |
626 | 626 | ||
627 | #define NV_RESTART_TX 0x1 | ||
628 | #define NV_RESTART_RX 0x2 | ||
629 | |||
627 | /* statistics */ | 630 | /* statistics */ |
628 | struct nv_ethtool_str { | 631 | struct nv_ethtool_str { |
629 | char name[ETH_GSTRING_LEN]; | 632 | char name[ETH_GSTRING_LEN]; |
@@ -1061,7 +1064,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value) | |||
1061 | u32 reg; | 1064 | u32 reg; |
1062 | int retval; | 1065 | int retval; |
1063 | 1066 | ||
1064 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 1067 | writel(NVREG_MIISTAT_MASK_RW, base + NvRegMIIStatus); |
1065 | 1068 | ||
1066 | reg = readl(base + NvRegMIIControl); | 1069 | reg = readl(base + NvRegMIIControl); |
1067 | if (reg & NVREG_MIICTL_INUSE) { | 1070 | if (reg & NVREG_MIICTL_INUSE) { |
@@ -1432,16 +1435,30 @@ static void nv_mac_reset(struct net_device *dev) | |||
1432 | { | 1435 | { |
1433 | struct fe_priv *np = netdev_priv(dev); | 1436 | struct fe_priv *np = netdev_priv(dev); |
1434 | u8 __iomem *base = get_hwbase(dev); | 1437 | u8 __iomem *base = get_hwbase(dev); |
1438 | u32 temp1, temp2, temp3; | ||
1435 | 1439 | ||
1436 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); | 1440 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); |
1441 | |||
1437 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); | 1442 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); |
1438 | pci_push(base); | 1443 | pci_push(base); |
1444 | |||
1445 | /* save registers since they will be cleared on reset */ | ||
1446 | temp1 = readl(base + NvRegMacAddrA); | ||
1447 | temp2 = readl(base + NvRegMacAddrB); | ||
1448 | temp3 = readl(base + NvRegTransmitPoll); | ||
1449 | |||
1439 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); | 1450 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); |
1440 | pci_push(base); | 1451 | pci_push(base); |
1441 | udelay(NV_MAC_RESET_DELAY); | 1452 | udelay(NV_MAC_RESET_DELAY); |
1442 | writel(0, base + NvRegMacReset); | 1453 | writel(0, base + NvRegMacReset); |
1443 | pci_push(base); | 1454 | pci_push(base); |
1444 | udelay(NV_MAC_RESET_DELAY); | 1455 | udelay(NV_MAC_RESET_DELAY); |
1456 | |||
1457 | /* restore saved registers */ | ||
1458 | writel(temp1, base + NvRegMacAddrA); | ||
1459 | writel(temp2, base + NvRegMacAddrB); | ||
1460 | writel(temp3, base + NvRegTransmitPoll); | ||
1461 | |||
1445 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); | 1462 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); |
1446 | pci_push(base); | 1463 | pci_push(base); |
1447 | } | 1464 | } |
@@ -2767,6 +2784,7 @@ static int nv_update_linkspeed(struct net_device *dev) | |||
2767 | int mii_status; | 2784 | int mii_status; |
2768 | int retval = 0; | 2785 | int retval = 0; |
2769 | u32 control_1000, status_1000, phyreg, pause_flags, txreg; | 2786 | u32 control_1000, status_1000, phyreg, pause_flags, txreg; |
2787 | u32 txrxFlags = 0; | ||
2770 | 2788 | ||
2771 | /* BMSR_LSTATUS is latched, read it twice: | 2789 | /* BMSR_LSTATUS is latched, read it twice: |
2772 | * we want the current value. | 2790 | * we want the current value. |
@@ -2862,6 +2880,16 @@ set_speed: | |||
2862 | np->duplex = newdup; | 2880 | np->duplex = newdup; |
2863 | np->linkspeed = newls; | 2881 | np->linkspeed = newls; |
2864 | 2882 | ||
2883 | /* The transmitter and receiver must be restarted for safe update */ | ||
2884 | if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START) { | ||
2885 | txrxFlags |= NV_RESTART_TX; | ||
2886 | nv_stop_tx(dev); | ||
2887 | } | ||
2888 | if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { | ||
2889 | txrxFlags |= NV_RESTART_RX; | ||
2890 | nv_stop_rx(dev); | ||
2891 | } | ||
2892 | |||
2865 | if (np->gigabit == PHY_GIGABIT) { | 2893 | if (np->gigabit == PHY_GIGABIT) { |
2866 | phyreg = readl(base + NvRegRandomSeed); | 2894 | phyreg = readl(base + NvRegRandomSeed); |
2867 | phyreg &= ~(0x3FF00); | 2895 | phyreg &= ~(0x3FF00); |
@@ -2950,6 +2978,11 @@ set_speed: | |||
2950 | } | 2978 | } |
2951 | nv_update_pause(dev, pause_flags); | 2979 | nv_update_pause(dev, pause_flags); |
2952 | 2980 | ||
2981 | if (txrxFlags & NV_RESTART_TX) | ||
2982 | nv_start_tx(dev); | ||
2983 | if (txrxFlags & NV_RESTART_RX) | ||
2984 | nv_start_rx(dev); | ||
2985 | |||
2953 | return retval; | 2986 | return retval; |
2954 | } | 2987 | } |
2955 | 2988 | ||
@@ -2976,7 +3009,7 @@ static void nv_link_irq(struct net_device *dev) | |||
2976 | u32 miistat; | 3009 | u32 miistat; |
2977 | 3010 | ||
2978 | miistat = readl(base + NvRegMIIStatus); | 3011 | miistat = readl(base + NvRegMIIStatus); |
2979 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 3012 | writel(NVREG_MIISTAT_LINKCHANGE, base + NvRegMIIStatus); |
2980 | dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat); | 3013 | dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat); |
2981 | 3014 | ||
2982 | if (miistat & (NVREG_MIISTAT_LINKCHANGE)) | 3015 | if (miistat & (NVREG_MIISTAT_LINKCHANGE)) |
@@ -4851,7 +4884,7 @@ static int nv_open(struct net_device *dev) | |||
4851 | 4884 | ||
4852 | writel(0, base + NvRegMIIMask); | 4885 | writel(0, base + NvRegMIIMask); |
4853 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 4886 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
4854 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); | 4887 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
4855 | 4888 | ||
4856 | writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1); | 4889 | writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1); |
4857 | writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus); | 4890 | writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus); |
@@ -4889,7 +4922,7 @@ static int nv_open(struct net_device *dev) | |||
4889 | 4922 | ||
4890 | nv_disable_hw_interrupts(dev, np->irqmask); | 4923 | nv_disable_hw_interrupts(dev, np->irqmask); |
4891 | pci_push(base); | 4924 | pci_push(base); |
4892 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); | 4925 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
4893 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 4926 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
4894 | pci_push(base); | 4927 | pci_push(base); |
4895 | 4928 | ||
@@ -4912,7 +4945,7 @@ static int nv_open(struct net_device *dev) | |||
4912 | { | 4945 | { |
4913 | u32 miistat; | 4946 | u32 miistat; |
4914 | miistat = readl(base + NvRegMIIStatus); | 4947 | miistat = readl(base + NvRegMIIStatus); |
4915 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 4948 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
4916 | dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat); | 4949 | dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat); |
4917 | } | 4950 | } |
4918 | /* set linkspeed to invalid value, thus force nv_update_linkspeed | 4951 | /* set linkspeed to invalid value, thus force nv_update_linkspeed |
@@ -5280,7 +5313,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
5280 | phystate &= ~NVREG_ADAPTCTL_RUNNING; | 5313 | phystate &= ~NVREG_ADAPTCTL_RUNNING; |
5281 | writel(phystate, base + NvRegAdapterControl); | 5314 | writel(phystate, base + NvRegAdapterControl); |
5282 | } | 5315 | } |
5283 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 5316 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
5284 | 5317 | ||
5285 | if (id->driver_data & DEV_HAS_MGMT_UNIT) { | 5318 | if (id->driver_data & DEV_HAS_MGMT_UNIT) { |
5286 | /* management unit running on the mac? */ | 5319 | /* management unit running on the mac? */ |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 100bf410bf5f..6a647d95e6ea 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c | |||
@@ -127,7 +127,7 @@ int gfar_mdio_reset(struct mii_bus *bus) | |||
127 | struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; | 127 | struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; |
128 | unsigned int timeout = PHY_INIT_TIMEOUT; | 128 | unsigned int timeout = PHY_INIT_TIMEOUT; |
129 | 129 | ||
130 | spin_lock_bh(&bus->mdio_lock); | 130 | mutex_lock(&bus->mdio_lock); |
131 | 131 | ||
132 | /* Reset the management interface */ | 132 | /* Reset the management interface */ |
133 | gfar_write(®s->miimcfg, MIIMCFG_RESET); | 133 | gfar_write(®s->miimcfg, MIIMCFG_RESET); |
@@ -140,7 +140,7 @@ int gfar_mdio_reset(struct mii_bus *bus) | |||
140 | timeout--) | 140 | timeout--) |
141 | cpu_relax(); | 141 | cpu_relax(); |
142 | 142 | ||
143 | spin_unlock_bh(&bus->mdio_lock); | 143 | mutex_unlock(&bus->mdio_lock); |
144 | 144 | ||
145 | if(timeout <= 0) { | 145 | if(timeout <= 0) { |
146 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", | 146 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", |
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 419861cbc65e..58d3bb622da6 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c | |||
@@ -1020,7 +1020,7 @@ static const struct ethtool_ops ops = { | |||
1020 | .get_link = veth_get_link, | 1020 | .get_link = veth_get_link, |
1021 | }; | 1021 | }; |
1022 | 1022 | ||
1023 | static struct net_device * __init veth_probe_one(int vlan, | 1023 | static struct net_device *veth_probe_one(int vlan, |
1024 | struct vio_dev *vio_dev) | 1024 | struct vio_dev *vio_dev) |
1025 | { | 1025 | { |
1026 | struct net_device *dev; | 1026 | struct net_device *dev; |
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index a021a6e72641..d0bf206632ca 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
@@ -136,8 +136,6 @@ struct ixgbe_ring { | |||
136 | u16 head; | 136 | u16 head; |
137 | u16 tail; | 137 | u16 tail; |
138 | 138 | ||
139 | /* To protect race between sender and clean_tx_irq */ | ||
140 | spinlock_t tx_lock; | ||
141 | 139 | ||
142 | struct ixgbe_queue_stats stats; | 140 | struct ixgbe_queue_stats stats; |
143 | 141 | ||
@@ -174,7 +172,6 @@ struct ixgbe_adapter { | |||
174 | struct vlan_group *vlgrp; | 172 | struct vlan_group *vlgrp; |
175 | u16 bd_number; | 173 | u16 bd_number; |
176 | u16 rx_buf_len; | 174 | u16 rx_buf_len; |
177 | atomic_t irq_sem; | ||
178 | struct work_struct reset_task; | 175 | struct work_struct reset_task; |
179 | 176 | ||
180 | /* TX */ | 177 | /* TX */ |
@@ -244,6 +241,7 @@ extern const char ixgbe_driver_version[]; | |||
244 | 241 | ||
245 | extern int ixgbe_up(struct ixgbe_adapter *adapter); | 242 | extern int ixgbe_up(struct ixgbe_adapter *adapter); |
246 | extern void ixgbe_down(struct ixgbe_adapter *adapter); | 243 | extern void ixgbe_down(struct ixgbe_adapter *adapter); |
244 | extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); | ||
247 | extern void ixgbe_reset(struct ixgbe_adapter *adapter); | 245 | extern void ixgbe_reset(struct ixgbe_adapter *adapter); |
248 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); | 246 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); |
249 | extern void ixgbe_set_ethtool_ops(struct net_device *netdev); | 247 | extern void ixgbe_set_ethtool_ops(struct net_device *netdev); |
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 36353447716d..a119cbd8dbb8 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
@@ -103,21 +103,41 @@ static int ixgbe_get_settings(struct net_device *netdev, | |||
103 | struct ethtool_cmd *ecmd) | 103 | struct ethtool_cmd *ecmd) |
104 | { | 104 | { |
105 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 105 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
106 | struct ixgbe_hw *hw = &adapter->hw; | ||
107 | u32 link_speed = 0; | ||
108 | bool link_up; | ||
106 | 109 | ||
107 | ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); | 110 | ecmd->supported = SUPPORTED_10000baseT_Full; |
108 | ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); | 111 | ecmd->autoneg = AUTONEG_ENABLE; |
109 | ecmd->port = PORT_FIBRE; | ||
110 | ecmd->transceiver = XCVR_EXTERNAL; | 112 | ecmd->transceiver = XCVR_EXTERNAL; |
113 | if (hw->phy.media_type == ixgbe_media_type_copper) { | ||
114 | ecmd->supported |= (SUPPORTED_1000baseT_Full | | ||
115 | SUPPORTED_TP | SUPPORTED_Autoneg); | ||
116 | |||
117 | ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg); | ||
118 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) | ||
119 | ecmd->advertising |= ADVERTISED_10000baseT_Full; | ||
120 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) | ||
121 | ecmd->advertising |= ADVERTISED_1000baseT_Full; | ||
122 | |||
123 | ecmd->port = PORT_TP; | ||
124 | } else { | ||
125 | ecmd->supported |= SUPPORTED_FIBRE; | ||
126 | ecmd->advertising = (ADVERTISED_10000baseT_Full | | ||
127 | ADVERTISED_FIBRE); | ||
128 | ecmd->port = PORT_FIBRE; | ||
129 | } | ||
111 | 130 | ||
112 | if (netif_carrier_ok(adapter->netdev)) { | 131 | adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up); |
113 | ecmd->speed = SPEED_10000; | 132 | if (link_up) { |
133 | ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? | ||
134 | SPEED_10000 : SPEED_1000; | ||
114 | ecmd->duplex = DUPLEX_FULL; | 135 | ecmd->duplex = DUPLEX_FULL; |
115 | } else { | 136 | } else { |
116 | ecmd->speed = -1; | 137 | ecmd->speed = -1; |
117 | ecmd->duplex = -1; | 138 | ecmd->duplex = -1; |
118 | } | 139 | } |
119 | 140 | ||
120 | ecmd->autoneg = AUTONEG_DISABLE; | ||
121 | return 0; | 141 | return 0; |
122 | } | 142 | } |
123 | 143 | ||
@@ -125,17 +145,17 @@ static int ixgbe_set_settings(struct net_device *netdev, | |||
125 | struct ethtool_cmd *ecmd) | 145 | struct ethtool_cmd *ecmd) |
126 | { | 146 | { |
127 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 147 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
148 | struct ixgbe_hw *hw = &adapter->hw; | ||
128 | 149 | ||
129 | if (ecmd->autoneg == AUTONEG_ENABLE || | 150 | switch (hw->phy.media_type) { |
130 | ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL) | 151 | case ixgbe_media_type_fiber: |
131 | return -EINVAL; | 152 | if ((ecmd->autoneg == AUTONEG_ENABLE) || |
132 | 153 | (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) | |
133 | if (netif_running(adapter->netdev)) { | 154 | return -EINVAL; |
134 | ixgbe_down(adapter); | 155 | /* in this case we currently only support 10Gb/FULL */ |
135 | ixgbe_reset(adapter); | 156 | break; |
136 | ixgbe_up(adapter); | 157 | default: |
137 | } else { | 158 | break; |
138 | ixgbe_reset(adapter); | ||
139 | } | 159 | } |
140 | 160 | ||
141 | return 0; | 161 | return 0; |
@@ -147,7 +167,7 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, | |||
147 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 167 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
148 | struct ixgbe_hw *hw = &adapter->hw; | 168 | struct ixgbe_hw *hw = &adapter->hw; |
149 | 169 | ||
150 | pause->autoneg = AUTONEG_DISABLE; | 170 | pause->autoneg = (hw->fc.type == ixgbe_fc_full ? 1 : 0); |
151 | 171 | ||
152 | if (hw->fc.type == ixgbe_fc_rx_pause) { | 172 | if (hw->fc.type == ixgbe_fc_rx_pause) { |
153 | pause->rx_pause = 1; | 173 | pause->rx_pause = 1; |
@@ -165,10 +185,8 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, | |||
165 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 185 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
166 | struct ixgbe_hw *hw = &adapter->hw; | 186 | struct ixgbe_hw *hw = &adapter->hw; |
167 | 187 | ||
168 | if (pause->autoneg == AUTONEG_ENABLE) | 188 | if ((pause->autoneg == AUTONEG_ENABLE) || |
169 | return -EINVAL; | 189 | (pause->rx_pause && pause->tx_pause)) |
170 | |||
171 | if (pause->rx_pause && pause->tx_pause) | ||
172 | hw->fc.type = ixgbe_fc_full; | 190 | hw->fc.type = ixgbe_fc_full; |
173 | else if (pause->rx_pause && !pause->tx_pause) | 191 | else if (pause->rx_pause && !pause->tx_pause) |
174 | hw->fc.type = ixgbe_fc_rx_pause; | 192 | hw->fc.type = ixgbe_fc_rx_pause; |
@@ -176,15 +194,15 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, | |||
176 | hw->fc.type = ixgbe_fc_tx_pause; | 194 | hw->fc.type = ixgbe_fc_tx_pause; |
177 | else if (!pause->rx_pause && !pause->tx_pause) | 195 | else if (!pause->rx_pause && !pause->tx_pause) |
178 | hw->fc.type = ixgbe_fc_none; | 196 | hw->fc.type = ixgbe_fc_none; |
197 | else | ||
198 | return -EINVAL; | ||
179 | 199 | ||
180 | hw->fc.original_type = hw->fc.type; | 200 | hw->fc.original_type = hw->fc.type; |
181 | 201 | ||
182 | if (netif_running(adapter->netdev)) { | 202 | if (netif_running(netdev)) |
183 | ixgbe_down(adapter); | 203 | ixgbe_reinit_locked(adapter); |
184 | ixgbe_up(adapter); | 204 | else |
185 | } else { | ||
186 | ixgbe_reset(adapter); | 205 | ixgbe_reset(adapter); |
187 | } | ||
188 | 206 | ||
189 | return 0; | 207 | return 0; |
190 | } | 208 | } |
@@ -203,12 +221,10 @@ static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data) | |||
203 | else | 221 | else |
204 | adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; | 222 | adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; |
205 | 223 | ||
206 | if (netif_running(netdev)) { | 224 | if (netif_running(netdev)) |
207 | ixgbe_down(adapter); | 225 | ixgbe_reinit_locked(adapter); |
208 | ixgbe_up(adapter); | 226 | else |
209 | } else { | ||
210 | ixgbe_reset(adapter); | 227 | ixgbe_reset(adapter); |
211 | } | ||
212 | 228 | ||
213 | return 0; | 229 | return 0; |
214 | } | 230 | } |
@@ -662,7 +678,10 @@ static int ixgbe_set_ringparam(struct net_device *netdev, | |||
662 | return 0; | 678 | return 0; |
663 | } | 679 | } |
664 | 680 | ||
665 | if (netif_running(adapter->netdev)) | 681 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) |
682 | msleep(1); | ||
683 | |||
684 | if (netif_running(netdev)) | ||
666 | ixgbe_down(adapter); | 685 | ixgbe_down(adapter); |
667 | 686 | ||
668 | /* | 687 | /* |
@@ -733,6 +752,7 @@ err_setup: | |||
733 | if (netif_running(adapter->netdev)) | 752 | if (netif_running(adapter->netdev)) |
734 | ixgbe_up(adapter); | 753 | ixgbe_up(adapter); |
735 | 754 | ||
755 | clear_bit(__IXGBE_RESETTING, &adapter->state); | ||
736 | return err; | 756 | return err; |
737 | } | 757 | } |
738 | 758 | ||
@@ -820,11 +840,8 @@ static int ixgbe_nway_reset(struct net_device *netdev) | |||
820 | { | 840 | { |
821 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 841 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
822 | 842 | ||
823 | if (netif_running(netdev)) { | 843 | if (netif_running(netdev)) |
824 | ixgbe_down(adapter); | 844 | ixgbe_reinit_locked(adapter); |
825 | ixgbe_reset(adapter); | ||
826 | ixgbe_up(adapter); | ||
827 | } | ||
828 | 845 | ||
829 | return 0; | 846 | return 0; |
830 | } | 847 | } |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 3732dd6c4b2a..ead49e54f31b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -87,6 +87,25 @@ MODULE_VERSION(DRV_VERSION); | |||
87 | 87 | ||
88 | #define DEFAULT_DEBUG_LEVEL_SHIFT 3 | 88 | #define DEFAULT_DEBUG_LEVEL_SHIFT 3 |
89 | 89 | ||
90 | static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter) | ||
91 | { | ||
92 | u32 ctrl_ext; | ||
93 | |||
94 | /* Let firmware take over control of h/w */ | ||
95 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ||
96 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
97 | ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD); | ||
98 | } | ||
99 | |||
100 | static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) | ||
101 | { | ||
102 | u32 ctrl_ext; | ||
103 | |||
104 | /* Let firmware know the driver has taken over */ | ||
105 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ||
106 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
107 | ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); | ||
108 | } | ||
90 | 109 | ||
91 | #ifdef DEBUG | 110 | #ifdef DEBUG |
92 | /** | 111 | /** |
@@ -165,6 +184,15 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, | |||
165 | return false; | 184 | return false; |
166 | } | 185 | } |
167 | 186 | ||
187 | #define IXGBE_MAX_TXD_PWR 14 | ||
188 | #define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) | ||
189 | |||
190 | /* Tx Descriptors needed, worst case */ | ||
191 | #define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \ | ||
192 | (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) | ||
193 | #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ | ||
194 | MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ | ||
195 | |||
168 | /** | 196 | /** |
169 | * ixgbe_clean_tx_irq - Reclaim resources after transmit completes | 197 | * ixgbe_clean_tx_irq - Reclaim resources after transmit completes |
170 | * @adapter: board private structure | 198 | * @adapter: board private structure |
@@ -177,18 +205,34 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, | |||
177 | struct ixgbe_tx_buffer *tx_buffer_info; | 205 | struct ixgbe_tx_buffer *tx_buffer_info; |
178 | unsigned int i, eop; | 206 | unsigned int i, eop; |
179 | bool cleaned = false; | 207 | bool cleaned = false; |
180 | int count = 0; | 208 | unsigned int total_tx_bytes = 0, total_tx_packets = 0; |
181 | 209 | ||
182 | i = tx_ring->next_to_clean; | 210 | i = tx_ring->next_to_clean; |
183 | eop = tx_ring->tx_buffer_info[i].next_to_watch; | 211 | eop = tx_ring->tx_buffer_info[i].next_to_watch; |
184 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); | 212 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); |
185 | while (eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) { | 213 | while (eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) { |
186 | for (cleaned = false; !cleaned;) { | 214 | cleaned = false; |
215 | while (!cleaned) { | ||
187 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); | 216 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); |
188 | tx_buffer_info = &tx_ring->tx_buffer_info[i]; | 217 | tx_buffer_info = &tx_ring->tx_buffer_info[i]; |
189 | cleaned = (i == eop); | 218 | cleaned = (i == eop); |
190 | 219 | ||
191 | tx_ring->stats.bytes += tx_buffer_info->length; | 220 | tx_ring->stats.bytes += tx_buffer_info->length; |
221 | if (cleaned) { | ||
222 | struct sk_buff *skb = tx_buffer_info->skb; | ||
223 | #ifdef NETIF_F_TSO | ||
224 | unsigned int segs, bytecount; | ||
225 | segs = skb_shinfo(skb)->gso_segs ?: 1; | ||
226 | /* multiply data chunks by size of headers */ | ||
227 | bytecount = ((segs - 1) * skb_headlen(skb)) + | ||
228 | skb->len; | ||
229 | total_tx_packets += segs; | ||
230 | total_tx_bytes += bytecount; | ||
231 | #else | ||
232 | total_tx_packets++; | ||
233 | total_tx_bytes += skb->len; | ||
234 | #endif | ||
235 | } | ||
192 | ixgbe_unmap_and_free_tx_resource(adapter, | 236 | ixgbe_unmap_and_free_tx_resource(adapter, |
193 | tx_buffer_info); | 237 | tx_buffer_info); |
194 | tx_desc->wb.status = 0; | 238 | tx_desc->wb.status = 0; |
@@ -204,29 +248,36 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, | |||
204 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); | 248 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); |
205 | 249 | ||
206 | /* weight of a sort for tx, avoid endless transmit cleanup */ | 250 | /* weight of a sort for tx, avoid endless transmit cleanup */ |
207 | if (count++ >= tx_ring->work_limit) | 251 | if (total_tx_packets >= tx_ring->work_limit) |
208 | break; | 252 | break; |
209 | } | 253 | } |
210 | 254 | ||
211 | tx_ring->next_to_clean = i; | 255 | tx_ring->next_to_clean = i; |
212 | 256 | ||
213 | #define TX_WAKE_THRESHOLD 32 | 257 | #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) |
214 | spin_lock(&tx_ring->tx_lock); | 258 | if (total_tx_packets && netif_carrier_ok(netdev) && |
215 | 259 | (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { | |
216 | if (cleaned && netif_carrier_ok(netdev) && | 260 | /* Make sure that anybody stopping the queue after this |
217 | (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD) && | 261 | * sees the new next_to_clean. |
218 | !test_bit(__IXGBE_DOWN, &adapter->state)) | 262 | */ |
219 | netif_wake_queue(netdev); | 263 | smp_mb(); |
220 | 264 | if (netif_queue_stopped(netdev) && | |
221 | spin_unlock(&tx_ring->tx_lock); | 265 | !test_bit(__IXGBE_DOWN, &adapter->state)) { |
266 | netif_wake_queue(netdev); | ||
267 | adapter->restart_queue++; | ||
268 | } | ||
269 | } | ||
222 | 270 | ||
223 | if (adapter->detect_tx_hung) | 271 | if (adapter->detect_tx_hung) |
224 | if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc)) | 272 | if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc)) |
225 | netif_stop_queue(netdev); | 273 | netif_stop_queue(netdev); |
226 | 274 | ||
227 | if (count >= tx_ring->work_limit) | 275 | if (total_tx_packets >= tx_ring->work_limit) |
228 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value); | 276 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value); |
229 | 277 | ||
278 | adapter->net_stats.tx_bytes += total_tx_bytes; | ||
279 | adapter->net_stats.tx_packets += total_tx_packets; | ||
280 | cleaned = total_tx_packets ? true : false; | ||
230 | return cleaned; | 281 | return cleaned; |
231 | } | 282 | } |
232 | 283 | ||
@@ -255,25 +306,40 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, | |||
255 | } | 306 | } |
256 | } | 307 | } |
257 | 308 | ||
309 | /** | ||
310 | * ixgbe_rx_checksum - indicate in skb if hw indicated a good cksum | ||
311 | * @adapter: address of board private structure | ||
312 | * @status_err: hardware indication of status of receive | ||
313 | * @skb: skb currently being received and modified | ||
314 | **/ | ||
258 | static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, | 315 | static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, |
259 | u32 status_err, | 316 | u32 status_err, |
260 | struct sk_buff *skb) | 317 | struct sk_buff *skb) |
261 | { | 318 | { |
262 | skb->ip_summed = CHECKSUM_NONE; | 319 | skb->ip_summed = CHECKSUM_NONE; |
263 | 320 | ||
264 | /* Ignore Checksum bit is set */ | 321 | /* Ignore Checksum bit is set, or rx csum disabled */ |
265 | if ((status_err & IXGBE_RXD_STAT_IXSM) || | 322 | if ((status_err & IXGBE_RXD_STAT_IXSM) || |
266 | !(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) | 323 | !(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) |
267 | return; | 324 | return; |
268 | /* TCP/UDP checksum error bit is set */ | 325 | |
269 | if (status_err & (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE)) { | 326 | /* if IP and error */ |
270 | /* let the stack verify checksum errors */ | 327 | if ((status_err & IXGBE_RXD_STAT_IPCS) && |
328 | (status_err & IXGBE_RXDADV_ERR_IPE)) { | ||
271 | adapter->hw_csum_rx_error++; | 329 | adapter->hw_csum_rx_error++; |
272 | return; | 330 | return; |
273 | } | 331 | } |
332 | |||
333 | if (!(status_err & IXGBE_RXD_STAT_L4CS)) | ||
334 | return; | ||
335 | |||
336 | if (status_err & IXGBE_RXDADV_ERR_TCPE) { | ||
337 | adapter->hw_csum_rx_error++; | ||
338 | return; | ||
339 | } | ||
340 | |||
274 | /* It must be a TCP or UDP packet with a valid checksum */ | 341 | /* It must be a TCP or UDP packet with a valid checksum */ |
275 | if (status_err & (IXGBE_RXD_STAT_L4CS | IXGBE_RXD_STAT_UDPCS)) | 342 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
276 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
277 | adapter->hw_csum_rx_good++; | 343 | adapter->hw_csum_rx_good++; |
278 | } | 344 | } |
279 | 345 | ||
@@ -379,6 +445,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, | |||
379 | u16 hdr_info, vlan_tag; | 445 | u16 hdr_info, vlan_tag; |
380 | bool is_vlan, cleaned = false; | 446 | bool is_vlan, cleaned = false; |
381 | int cleaned_count = 0; | 447 | int cleaned_count = 0; |
448 | unsigned int total_rx_bytes = 0, total_rx_packets = 0; | ||
382 | 449 | ||
383 | i = rx_ring->next_to_clean; | 450 | i = rx_ring->next_to_clean; |
384 | upper_len = 0; | 451 | upper_len = 0; |
@@ -458,6 +525,11 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, | |||
458 | } | 525 | } |
459 | 526 | ||
460 | ixgbe_rx_checksum(adapter, staterr, skb); | 527 | ixgbe_rx_checksum(adapter, staterr, skb); |
528 | |||
529 | /* probably a little skewed due to removing CRC */ | ||
530 | total_rx_bytes += skb->len; | ||
531 | total_rx_packets++; | ||
532 | |||
461 | skb->protocol = eth_type_trans(skb, netdev); | 533 | skb->protocol = eth_type_trans(skb, netdev); |
462 | ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag); | 534 | ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag); |
463 | netdev->last_rx = jiffies; | 535 | netdev->last_rx = jiffies; |
@@ -486,6 +558,9 @@ next_desc: | |||
486 | if (cleaned_count) | 558 | if (cleaned_count) |
487 | ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count); | 559 | ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count); |
488 | 560 | ||
561 | adapter->net_stats.rx_bytes += total_rx_bytes; | ||
562 | adapter->net_stats.rx_packets += total_rx_packets; | ||
563 | |||
489 | return cleaned; | 564 | return cleaned; |
490 | } | 565 | } |
491 | 566 | ||
@@ -535,7 +610,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) | |||
535 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | 610 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
536 | mod_timer(&adapter->watchdog_timer, jiffies); | 611 | mod_timer(&adapter->watchdog_timer, jiffies); |
537 | } | 612 | } |
538 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); | 613 | |
614 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | ||
615 | IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); | ||
539 | 616 | ||
540 | return IRQ_HANDLED; | 617 | return IRQ_HANDLED; |
541 | } | 618 | } |
@@ -713,7 +790,6 @@ static irqreturn_t ixgbe_intr(int irq, void *data) | |||
713 | if (netif_rx_schedule_prep(netdev, &adapter->napi)) { | 790 | if (netif_rx_schedule_prep(netdev, &adapter->napi)) { |
714 | /* Disable interrupts and register for poll. The flush of the | 791 | /* Disable interrupts and register for poll. The flush of the |
715 | * posted write is intentionally left out. */ | 792 | * posted write is intentionally left out. */ |
716 | atomic_inc(&adapter->irq_sem); | ||
717 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); | 793 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); |
718 | __netif_rx_schedule(netdev, &adapter->napi); | 794 | __netif_rx_schedule(netdev, &adapter->napi); |
719 | } | 795 | } |
@@ -801,7 +877,6 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) | |||
801 | **/ | 877 | **/ |
802 | static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) | 878 | static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) |
803 | { | 879 | { |
804 | atomic_inc(&adapter->irq_sem); | ||
805 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); | 880 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); |
806 | IXGBE_WRITE_FLUSH(&adapter->hw); | 881 | IXGBE_WRITE_FLUSH(&adapter->hw); |
807 | synchronize_irq(adapter->pdev->irq); | 882 | synchronize_irq(adapter->pdev->irq); |
@@ -813,15 +888,13 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) | |||
813 | **/ | 888 | **/ |
814 | static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) | 889 | static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) |
815 | { | 890 | { |
816 | if (atomic_dec_and_test(&adapter->irq_sem)) { | 891 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) |
817 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) | 892 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, |
818 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, | 893 | (IXGBE_EIMS_ENABLE_MASK & |
819 | (IXGBE_EIMS_ENABLE_MASK & | 894 | ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC))); |
820 | ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC))); | 895 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, |
821 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, | 896 | IXGBE_EIMS_ENABLE_MASK); |
822 | IXGBE_EIMS_ENABLE_MASK); | 897 | IXGBE_WRITE_FLUSH(&adapter->hw); |
823 | IXGBE_WRITE_FLUSH(&adapter->hw); | ||
824 | } | ||
825 | } | 898 | } |
826 | 899 | ||
827 | /** | 900 | /** |
@@ -1040,7 +1113,8 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, | |||
1040 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 1113 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1041 | u32 ctrl; | 1114 | u32 ctrl; |
1042 | 1115 | ||
1043 | ixgbe_irq_disable(adapter); | 1116 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1117 | ixgbe_irq_disable(adapter); | ||
1044 | adapter->vlgrp = grp; | 1118 | adapter->vlgrp = grp; |
1045 | 1119 | ||
1046 | if (grp) { | 1120 | if (grp) { |
@@ -1051,7 +1125,8 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, | |||
1051 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); | 1125 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); |
1052 | } | 1126 | } |
1053 | 1127 | ||
1054 | ixgbe_irq_enable(adapter); | 1128 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1129 | ixgbe_irq_enable(adapter); | ||
1055 | } | 1130 | } |
1056 | 1131 | ||
1057 | static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) | 1132 | static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) |
@@ -1066,9 +1141,13 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) | |||
1066 | { | 1141 | { |
1067 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 1142 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1068 | 1143 | ||
1069 | ixgbe_irq_disable(adapter); | 1144 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1145 | ixgbe_irq_disable(adapter); | ||
1146 | |||
1070 | vlan_group_set_device(adapter->vlgrp, vid, NULL); | 1147 | vlan_group_set_device(adapter->vlgrp, vid, NULL); |
1071 | ixgbe_irq_enable(adapter); | 1148 | |
1149 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | ||
1150 | ixgbe_irq_enable(adapter); | ||
1072 | 1151 | ||
1073 | /* remove VID from filter table */ | 1152 | /* remove VID from filter table */ |
1074 | ixgbe_set_vfta(&adapter->hw, vid, 0, false); | 1153 | ixgbe_set_vfta(&adapter->hw, vid, 0, false); |
@@ -1170,6 +1249,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) | |||
1170 | u32 txdctl, rxdctl, mhadd; | 1249 | u32 txdctl, rxdctl, mhadd; |
1171 | int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; | 1250 | int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; |
1172 | 1251 | ||
1252 | ixgbe_get_hw_control(adapter); | ||
1253 | |||
1173 | if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED | | 1254 | if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED | |
1174 | IXGBE_FLAG_MSI_ENABLED)) { | 1255 | IXGBE_FLAG_MSI_ENABLED)) { |
1175 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { | 1256 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { |
@@ -1224,6 +1305,16 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) | |||
1224 | return 0; | 1305 | return 0; |
1225 | } | 1306 | } |
1226 | 1307 | ||
1308 | void ixgbe_reinit_locked(struct ixgbe_adapter *adapter) | ||
1309 | { | ||
1310 | WARN_ON(in_interrupt()); | ||
1311 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) | ||
1312 | msleep(1); | ||
1313 | ixgbe_down(adapter); | ||
1314 | ixgbe_up(adapter); | ||
1315 | clear_bit(__IXGBE_RESETTING, &adapter->state); | ||
1316 | } | ||
1317 | |||
1227 | int ixgbe_up(struct ixgbe_adapter *adapter) | 1318 | int ixgbe_up(struct ixgbe_adapter *adapter) |
1228 | { | 1319 | { |
1229 | /* hardware has been reset, we need to reload some things */ | 1320 | /* hardware has been reset, we need to reload some things */ |
@@ -1408,7 +1499,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) | |||
1408 | msleep(10); | 1499 | msleep(10); |
1409 | 1500 | ||
1410 | napi_disable(&adapter->napi); | 1501 | napi_disable(&adapter->napi); |
1411 | atomic_set(&adapter->irq_sem, 0); | ||
1412 | 1502 | ||
1413 | ixgbe_irq_disable(adapter); | 1503 | ixgbe_irq_disable(adapter); |
1414 | 1504 | ||
@@ -1447,6 +1537,8 @@ static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state) | |||
1447 | pci_enable_wake(pdev, PCI_D3hot, 0); | 1537 | pci_enable_wake(pdev, PCI_D3hot, 0); |
1448 | pci_enable_wake(pdev, PCI_D3cold, 0); | 1538 | pci_enable_wake(pdev, PCI_D3cold, 0); |
1449 | 1539 | ||
1540 | ixgbe_release_hw_control(adapter); | ||
1541 | |||
1450 | pci_disable_device(pdev); | 1542 | pci_disable_device(pdev); |
1451 | 1543 | ||
1452 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 1544 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
@@ -1481,7 +1573,8 @@ static int ixgbe_clean(struct napi_struct *napi, int budget) | |||
1481 | /* If budget not fully consumed, exit the polling mode */ | 1573 | /* If budget not fully consumed, exit the polling mode */ |
1482 | if (work_done < budget) { | 1574 | if (work_done < budget) { |
1483 | netif_rx_complete(netdev, napi); | 1575 | netif_rx_complete(netdev, napi); |
1484 | ixgbe_irq_enable(adapter); | 1576 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1577 | ixgbe_irq_enable(adapter); | ||
1485 | } | 1578 | } |
1486 | 1579 | ||
1487 | return work_done; | 1580 | return work_done; |
@@ -1506,8 +1599,7 @@ static void ixgbe_reset_task(struct work_struct *work) | |||
1506 | 1599 | ||
1507 | adapter->tx_timeout_count++; | 1600 | adapter->tx_timeout_count++; |
1508 | 1601 | ||
1509 | ixgbe_down(adapter); | 1602 | ixgbe_reinit_locked(adapter); |
1510 | ixgbe_up(adapter); | ||
1511 | } | 1603 | } |
1512 | 1604 | ||
1513 | /** | 1605 | /** |
@@ -1590,7 +1682,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) | |||
1590 | return -ENOMEM; | 1682 | return -ENOMEM; |
1591 | } | 1683 | } |
1592 | 1684 | ||
1593 | atomic_set(&adapter->irq_sem, 1); | ||
1594 | set_bit(__IXGBE_DOWN, &adapter->state); | 1685 | set_bit(__IXGBE_DOWN, &adapter->state); |
1595 | 1686 | ||
1596 | return 0; | 1687 | return 0; |
@@ -1634,7 +1725,6 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, | |||
1634 | txdr->next_to_use = 0; | 1725 | txdr->next_to_use = 0; |
1635 | txdr->next_to_clean = 0; | 1726 | txdr->next_to_clean = 0; |
1636 | txdr->work_limit = txdr->count; | 1727 | txdr->work_limit = txdr->count; |
1637 | spin_lock_init(&txdr->tx_lock); | ||
1638 | 1728 | ||
1639 | return 0; | 1729 | return 0; |
1640 | } | 1730 | } |
@@ -1828,10 +1918,8 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) | |||
1828 | 1918 | ||
1829 | netdev->mtu = new_mtu; | 1919 | netdev->mtu = new_mtu; |
1830 | 1920 | ||
1831 | if (netif_running(netdev)) { | 1921 | if (netif_running(netdev)) |
1832 | ixgbe_down(adapter); | 1922 | ixgbe_reinit_locked(adapter); |
1833 | ixgbe_up(adapter); | ||
1834 | } | ||
1835 | 1923 | ||
1836 | return 0; | 1924 | return 0; |
1837 | } | 1925 | } |
@@ -1852,14 +1940,8 @@ static int ixgbe_open(struct net_device *netdev) | |||
1852 | { | 1940 | { |
1853 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 1941 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1854 | int err; | 1942 | int err; |
1855 | u32 ctrl_ext; | ||
1856 | u32 num_rx_queues = adapter->num_rx_queues; | 1943 | u32 num_rx_queues = adapter->num_rx_queues; |
1857 | 1944 | ||
1858 | /* Let firmware know the driver has taken over */ | ||
1859 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ||
1860 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
1861 | ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); | ||
1862 | |||
1863 | try_intr_reinit: | 1945 | try_intr_reinit: |
1864 | /* allocate transmit descriptors */ | 1946 | /* allocate transmit descriptors */ |
1865 | err = ixgbe_setup_all_tx_resources(adapter); | 1947 | err = ixgbe_setup_all_tx_resources(adapter); |
@@ -1910,6 +1992,7 @@ try_intr_reinit: | |||
1910 | return 0; | 1992 | return 0; |
1911 | 1993 | ||
1912 | err_up: | 1994 | err_up: |
1995 | ixgbe_release_hw_control(adapter); | ||
1913 | ixgbe_free_irq(adapter); | 1996 | ixgbe_free_irq(adapter); |
1914 | err_req_irq: | 1997 | err_req_irq: |
1915 | ixgbe_free_all_rx_resources(adapter); | 1998 | ixgbe_free_all_rx_resources(adapter); |
@@ -1935,7 +2018,6 @@ err_setup_tx: | |||
1935 | static int ixgbe_close(struct net_device *netdev) | 2018 | static int ixgbe_close(struct net_device *netdev) |
1936 | { | 2019 | { |
1937 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 2020 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1938 | u32 ctrl_ext; | ||
1939 | 2021 | ||
1940 | ixgbe_down(adapter); | 2022 | ixgbe_down(adapter); |
1941 | ixgbe_free_irq(adapter); | 2023 | ixgbe_free_irq(adapter); |
@@ -1943,9 +2025,7 @@ static int ixgbe_close(struct net_device *netdev) | |||
1943 | ixgbe_free_all_tx_resources(adapter); | 2025 | ixgbe_free_all_tx_resources(adapter); |
1944 | ixgbe_free_all_rx_resources(adapter); | 2026 | ixgbe_free_all_rx_resources(adapter); |
1945 | 2027 | ||
1946 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | 2028 | ixgbe_release_hw_control(adapter); |
1947 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
1948 | ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD); | ||
1949 | 2029 | ||
1950 | return 0; | 2030 | return 0; |
1951 | } | 2031 | } |
@@ -1957,22 +2037,26 @@ static int ixgbe_close(struct net_device *netdev) | |||
1957 | void ixgbe_update_stats(struct ixgbe_adapter *adapter) | 2037 | void ixgbe_update_stats(struct ixgbe_adapter *adapter) |
1958 | { | 2038 | { |
1959 | struct ixgbe_hw *hw = &adapter->hw; | 2039 | struct ixgbe_hw *hw = &adapter->hw; |
1960 | u64 good_rx, missed_rx, bprc; | 2040 | u64 total_mpc = 0; |
2041 | u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; | ||
1961 | 2042 | ||
1962 | adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); | 2043 | adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); |
1963 | good_rx = IXGBE_READ_REG(hw, IXGBE_GPRC); | 2044 | for (i = 0; i < 8; i++) { |
1964 | missed_rx = IXGBE_READ_REG(hw, IXGBE_MPC(0)); | 2045 | /* for packet buffers not used, the register should read 0 */ |
1965 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(1)); | 2046 | mpc = IXGBE_READ_REG(hw, IXGBE_MPC(i)); |
1966 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(2)); | 2047 | missed_rx += mpc; |
1967 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(3)); | 2048 | adapter->stats.mpc[i] += mpc; |
1968 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(4)); | 2049 | total_mpc += adapter->stats.mpc[i]; |
1969 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(5)); | 2050 | adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); |
1970 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(6)); | 2051 | } |
1971 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(7)); | 2052 | adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); |
1972 | adapter->stats.gprc += (good_rx - missed_rx); | 2053 | /* work around hardware counting issue */ |
1973 | 2054 | adapter->stats.gprc -= missed_rx; | |
1974 | adapter->stats.mpc[0] += missed_rx; | 2055 | |
2056 | /* 82598 hardware only has a 32 bit counter in the high register */ | ||
1975 | adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); | 2057 | adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); |
2058 | adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); | ||
2059 | adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH); | ||
1976 | bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); | 2060 | bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); |
1977 | adapter->stats.bprc += bprc; | 2061 | adapter->stats.bprc += bprc; |
1978 | adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); | 2062 | adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); |
@@ -1984,35 +2068,37 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) | |||
1984 | adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); | 2068 | adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); |
1985 | adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); | 2069 | adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); |
1986 | adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); | 2070 | adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); |
1987 | |||
1988 | adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); | 2071 | adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); |
1989 | adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); | 2072 | adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); |
1990 | adapter->stats.lxontxc += IXGBE_READ_REG(hw, IXGBE_LXONTXC); | ||
1991 | adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); | 2073 | adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); |
1992 | adapter->stats.lxofftxc += IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); | 2074 | lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); |
2075 | adapter->stats.lxontxc += lxon; | ||
2076 | lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); | ||
2077 | adapter->stats.lxofftxc += lxoff; | ||
1993 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); | 2078 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); |
1994 | adapter->stats.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); | 2079 | adapter->stats.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); |
1995 | adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); | 2080 | adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); |
1996 | adapter->stats.rnbc[0] += IXGBE_READ_REG(hw, IXGBE_RNBC(0)); | 2081 | /* |
2082 | * 82598 errata - tx of flow control packets is included in tx counters | ||
2083 | */ | ||
2084 | xon_off_tot = lxon + lxoff; | ||
2085 | adapter->stats.gptc -= xon_off_tot; | ||
2086 | adapter->stats.mptc -= xon_off_tot; | ||
2087 | adapter->stats.gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN)); | ||
1997 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); | 2088 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); |
1998 | adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC); | 2089 | adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC); |
1999 | adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC); | 2090 | adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC); |
2000 | adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH); | ||
2001 | adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR); | 2091 | adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR); |
2002 | adapter->stats.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); | 2092 | adapter->stats.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); |
2093 | adapter->stats.ptc64 -= xon_off_tot; | ||
2003 | adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); | 2094 | adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); |
2004 | adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); | 2095 | adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); |
2005 | adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); | 2096 | adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); |
2006 | adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); | 2097 | adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); |
2007 | adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); | 2098 | adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); |
2008 | adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); | ||
2009 | adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); | 2099 | adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); |
2010 | 2100 | ||
2011 | /* Fill out the OS statistics structure */ | 2101 | /* Fill out the OS statistics structure */ |
2012 | adapter->net_stats.rx_packets = adapter->stats.gprc; | ||
2013 | adapter->net_stats.tx_packets = adapter->stats.gptc; | ||
2014 | adapter->net_stats.rx_bytes = adapter->stats.gorc; | ||
2015 | adapter->net_stats.tx_bytes = adapter->stats.gotc; | ||
2016 | adapter->net_stats.multicast = adapter->stats.mprc; | 2102 | adapter->net_stats.multicast = adapter->stats.mprc; |
2017 | 2103 | ||
2018 | /* Rx Errors */ | 2104 | /* Rx Errors */ |
@@ -2021,8 +2107,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) | |||
2021 | adapter->net_stats.rx_dropped = 0; | 2107 | adapter->net_stats.rx_dropped = 0; |
2022 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; | 2108 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; |
2023 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; | 2109 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; |
2024 | adapter->net_stats.rx_missed_errors = adapter->stats.mpc[0]; | 2110 | adapter->net_stats.rx_missed_errors = total_mpc; |
2025 | |||
2026 | } | 2111 | } |
2027 | 2112 | ||
2028 | /** | 2113 | /** |
@@ -2076,15 +2161,6 @@ static void ixgbe_watchdog(unsigned long data) | |||
2076 | round_jiffies(jiffies + 2 * HZ)); | 2161 | round_jiffies(jiffies + 2 * HZ)); |
2077 | } | 2162 | } |
2078 | 2163 | ||
2079 | #define IXGBE_MAX_TXD_PWR 14 | ||
2080 | #define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) | ||
2081 | |||
2082 | /* Tx Descriptors needed, worst case */ | ||
2083 | #define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \ | ||
2084 | (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) | ||
2085 | #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ | ||
2086 | MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ | ||
2087 | |||
2088 | static int ixgbe_tso(struct ixgbe_adapter *adapter, | 2164 | static int ixgbe_tso(struct ixgbe_adapter *adapter, |
2089 | struct ixgbe_ring *tx_ring, struct sk_buff *skb, | 2165 | struct ixgbe_ring *tx_ring, struct sk_buff *skb, |
2090 | u32 tx_flags, u8 *hdr_len) | 2166 | u32 tx_flags, u8 *hdr_len) |
@@ -2356,6 +2432,37 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, | |||
2356 | writel(i, adapter->hw.hw_addr + tx_ring->tail); | 2432 | writel(i, adapter->hw.hw_addr + tx_ring->tail); |
2357 | } | 2433 | } |
2358 | 2434 | ||
2435 | static int __ixgbe_maybe_stop_tx(struct net_device *netdev, | ||
2436 | struct ixgbe_ring *tx_ring, int size) | ||
2437 | { | ||
2438 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
2439 | |||
2440 | netif_stop_queue(netdev); | ||
2441 | /* Herbert's original patch had: | ||
2442 | * smp_mb__after_netif_stop_queue(); | ||
2443 | * but since that doesn't exist yet, just open code it. */ | ||
2444 | smp_mb(); | ||
2445 | |||
2446 | /* We need to check again in a case another CPU has just | ||
2447 | * made room available. */ | ||
2448 | if (likely(IXGBE_DESC_UNUSED(tx_ring) < size)) | ||
2449 | return -EBUSY; | ||
2450 | |||
2451 | /* A reprieve! - use start_queue because it doesn't call schedule */ | ||
2452 | netif_wake_queue(netdev); | ||
2453 | ++adapter->restart_queue; | ||
2454 | return 0; | ||
2455 | } | ||
2456 | |||
2457 | static int ixgbe_maybe_stop_tx(struct net_device *netdev, | ||
2458 | struct ixgbe_ring *tx_ring, int size) | ||
2459 | { | ||
2460 | if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size)) | ||
2461 | return 0; | ||
2462 | return __ixgbe_maybe_stop_tx(netdev, tx_ring, size); | ||
2463 | } | ||
2464 | |||
2465 | |||
2359 | static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | 2466 | static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) |
2360 | { | 2467 | { |
2361 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 2468 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
@@ -2363,7 +2470,6 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2363 | unsigned int len = skb->len; | 2470 | unsigned int len = skb->len; |
2364 | unsigned int first; | 2471 | unsigned int first; |
2365 | unsigned int tx_flags = 0; | 2472 | unsigned int tx_flags = 0; |
2366 | unsigned long flags = 0; | ||
2367 | u8 hdr_len; | 2473 | u8 hdr_len; |
2368 | int tso; | 2474 | int tso; |
2369 | unsigned int mss = 0; | 2475 | unsigned int mss = 0; |
@@ -2389,14 +2495,10 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2389 | for (f = 0; f < nr_frags; f++) | 2495 | for (f = 0; f < nr_frags; f++) |
2390 | count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); | 2496 | count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); |
2391 | 2497 | ||
2392 | spin_lock_irqsave(&tx_ring->tx_lock, flags); | 2498 | if (ixgbe_maybe_stop_tx(netdev, tx_ring, count)) { |
2393 | if (IXGBE_DESC_UNUSED(tx_ring) < (count + 2)) { | ||
2394 | adapter->tx_busy++; | 2499 | adapter->tx_busy++; |
2395 | netif_stop_queue(netdev); | ||
2396 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); | ||
2397 | return NETDEV_TX_BUSY; | 2500 | return NETDEV_TX_BUSY; |
2398 | } | 2501 | } |
2399 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); | ||
2400 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { | 2502 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { |
2401 | tx_flags |= IXGBE_TX_FLAGS_VLAN; | 2503 | tx_flags |= IXGBE_TX_FLAGS_VLAN; |
2402 | tx_flags |= (vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT); | 2504 | tx_flags |= (vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT); |
@@ -2423,11 +2525,7 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2423 | 2525 | ||
2424 | netdev->trans_start = jiffies; | 2526 | netdev->trans_start = jiffies; |
2425 | 2527 | ||
2426 | spin_lock_irqsave(&tx_ring->tx_lock, flags); | 2528 | ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); |
2427 | /* Make sure there is space in the ring for the next send. */ | ||
2428 | if (IXGBE_DESC_UNUSED(tx_ring) < DESC_NEEDED) | ||
2429 | netif_stop_queue(netdev); | ||
2430 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); | ||
2431 | 2529 | ||
2432 | return NETDEV_TX_OK; | 2530 | return NETDEV_TX_OK; |
2433 | } | 2531 | } |
@@ -2697,6 +2795,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
2697 | return 0; | 2795 | return 0; |
2698 | 2796 | ||
2699 | err_register: | 2797 | err_register: |
2798 | ixgbe_release_hw_control(adapter); | ||
2700 | err_hw_init: | 2799 | err_hw_init: |
2701 | err_sw_init: | 2800 | err_sw_init: |
2702 | err_eeprom: | 2801 | err_eeprom: |
@@ -2732,6 +2831,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) | |||
2732 | 2831 | ||
2733 | unregister_netdev(netdev); | 2832 | unregister_netdev(netdev); |
2734 | 2833 | ||
2834 | ixgbe_release_hw_control(adapter); | ||
2835 | |||
2735 | kfree(adapter->tx_ring); | 2836 | kfree(adapter->tx_ring); |
2736 | kfree(adapter->rx_ring); | 2837 | kfree(adapter->rx_ring); |
2737 | 2838 | ||
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 651c2699d5e1..b528ce77c406 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -1652,6 +1652,11 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, | |||
1652 | } | 1652 | } |
1653 | } | 1653 | } |
1654 | 1654 | ||
1655 | static inline __be16 sum16_as_be(__sum16 sum) | ||
1656 | { | ||
1657 | return (__force __be16)sum; | ||
1658 | } | ||
1659 | |||
1655 | /** | 1660 | /** |
1656 | * eth_tx_submit_descs_for_skb - submit data from an skb to the tx hw | 1661 | * eth_tx_submit_descs_for_skb - submit data from an skb to the tx hw |
1657 | * | 1662 | * |
@@ -1689,7 +1694,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, | |||
1689 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); | 1694 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); |
1690 | 1695 | ||
1691 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 1696 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
1692 | BUG_ON(skb->protocol != ETH_P_IP); | 1697 | BUG_ON(skb->protocol != htons(ETH_P_IP)); |
1693 | 1698 | ||
1694 | cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | | 1699 | cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | |
1695 | ETH_GEN_IP_V_4_CHECKSUM | | 1700 | ETH_GEN_IP_V_4_CHECKSUM | |
@@ -1698,10 +1703,10 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, | |||
1698 | switch (ip_hdr(skb)->protocol) { | 1703 | switch (ip_hdr(skb)->protocol) { |
1699 | case IPPROTO_UDP: | 1704 | case IPPROTO_UDP: |
1700 | cmd_sts |= ETH_UDP_FRAME; | 1705 | cmd_sts |= ETH_UDP_FRAME; |
1701 | desc->l4i_chk = udp_hdr(skb)->check; | 1706 | desc->l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check)); |
1702 | break; | 1707 | break; |
1703 | case IPPROTO_TCP: | 1708 | case IPPROTO_TCP: |
1704 | desc->l4i_chk = tcp_hdr(skb)->check; | 1709 | desc->l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check)); |
1705 | break; | 1710 | break; |
1706 | default: | 1711 | default: |
1707 | BUG(); | 1712 | BUG(); |
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 1b51bb668d39..5aa0a8089694 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c | |||
@@ -2468,9 +2468,10 @@ static int __init pppol2tp_init(void) | |||
2468 | 2468 | ||
2469 | out: | 2469 | out: |
2470 | return err; | 2470 | return err; |
2471 | 2471 | #ifdef CONFIG_PROC_FS | |
2472 | out_unregister_pppox_proto: | 2472 | out_unregister_pppox_proto: |
2473 | unregister_pppox_proto(PX_PROTO_OL2TP); | 2473 | unregister_pppox_proto(PX_PROTO_OL2TP); |
2474 | #endif | ||
2474 | out_unregister_pppol2tp_proto: | 2475 | out_unregister_pppol2tp_proto: |
2475 | proto_unregister(&pppol2tp_sk_proto); | 2476 | proto_unregister(&pppol2tp_sk_proto); |
2476 | goto out; | 2477 | goto out; |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index dc062367a1c8..9a6295909e43 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -857,7 +857,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
857 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); | 857 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); |
858 | 858 | ||
859 | /* On chips without ram buffer, pause is controled by MAC level */ | 859 | /* On chips without ram buffer, pause is controled by MAC level */ |
860 | if (sky2_read8(hw, B2_E_0) == 0) { | 860 | if (!(hw->flags & SKY2_HW_RAM_BUFFER)) { |
861 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); | 861 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); |
862 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); | 862 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); |
863 | 863 | ||
@@ -1194,7 +1194,7 @@ static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2) | |||
1194 | struct sk_buff *skb; | 1194 | struct sk_buff *skb; |
1195 | int i; | 1195 | int i; |
1196 | 1196 | ||
1197 | if (sky2->hw->flags & SKY2_HW_FIFO_HANG_CHECK) { | 1197 | if (sky2->hw->flags & SKY2_HW_RAM_BUFFER) { |
1198 | unsigned char *start; | 1198 | unsigned char *start; |
1199 | /* | 1199 | /* |
1200 | * Workaround for a bug in FIFO that cause hang | 1200 | * Workaround for a bug in FIFO that cause hang |
@@ -1387,6 +1387,7 @@ static int sky2_up(struct net_device *dev) | |||
1387 | if (ramsize > 0) { | 1387 | if (ramsize > 0) { |
1388 | u32 rxspace; | 1388 | u32 rxspace; |
1389 | 1389 | ||
1390 | hw->flags |= SKY2_HW_RAM_BUFFER; | ||
1390 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); | 1391 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); |
1391 | if (ramsize < 16) | 1392 | if (ramsize < 16) |
1392 | rxspace = ramsize / 2; | 1393 | rxspace = ramsize / 2; |
@@ -2026,7 +2027,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
2026 | 2027 | ||
2027 | synchronize_irq(hw->pdev->irq); | 2028 | synchronize_irq(hw->pdev->irq); |
2028 | 2029 | ||
2029 | if (sky2_read8(hw, B2_E_0) == 0) | 2030 | if (!(hw->flags & SKY2_HW_RAM_BUFFER)) |
2030 | sky2_set_tx_stfwd(hw, port); | 2031 | sky2_set_tx_stfwd(hw, port); |
2031 | 2032 | ||
2032 | ctl = gma_read16(hw, port, GM_GP_CTRL); | 2033 | ctl = gma_read16(hw, port, GM_GP_CTRL); |
@@ -2566,7 +2567,7 @@ static void sky2_watchdog(unsigned long arg) | |||
2566 | ++active; | 2567 | ++active; |
2567 | 2568 | ||
2568 | /* For chips with Rx FIFO, check if stuck */ | 2569 | /* For chips with Rx FIFO, check if stuck */ |
2569 | if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) && | 2570 | if ((hw->flags & SKY2_HW_RAM_BUFFER) && |
2570 | sky2_rx_hung(dev)) { | 2571 | sky2_rx_hung(dev)) { |
2571 | pr_info(PFX "%s: receiver hang detected\n", | 2572 | pr_info(PFX "%s: receiver hang detected\n", |
2572 | dev->name); | 2573 | dev->name); |
@@ -2722,11 +2723,7 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2722 | 2723 | ||
2723 | switch(hw->chip_id) { | 2724 | switch(hw->chip_id) { |
2724 | case CHIP_ID_YUKON_XL: | 2725 | case CHIP_ID_YUKON_XL: |
2725 | hw->flags = SKY2_HW_GIGABIT | 2726 | hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY; |
2726 | | SKY2_HW_NEWER_PHY; | ||
2727 | if (hw->chip_rev < 3) | ||
2728 | hw->flags |= SKY2_HW_FIFO_HANG_CHECK; | ||
2729 | |||
2730 | break; | 2727 | break; |
2731 | 2728 | ||
2732 | case CHIP_ID_YUKON_EC_U: | 2729 | case CHIP_ID_YUKON_EC_U: |
@@ -2752,7 +2749,7 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2752 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); | 2749 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); |
2753 | return -EOPNOTSUPP; | 2750 | return -EOPNOTSUPP; |
2754 | } | 2751 | } |
2755 | hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK; | 2752 | hw->flags = SKY2_HW_GIGABIT; |
2756 | break; | 2753 | break; |
2757 | 2754 | ||
2758 | case CHIP_ID_YUKON_FE: | 2755 | case CHIP_ID_YUKON_FE: |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 2bced1a0898f..5ab5c1c7c5aa 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -2045,7 +2045,7 @@ struct sky2_hw { | |||
2045 | #define SKY2_HW_FIBRE_PHY 0x00000002 | 2045 | #define SKY2_HW_FIBRE_PHY 0x00000002 |
2046 | #define SKY2_HW_GIGABIT 0x00000004 | 2046 | #define SKY2_HW_GIGABIT 0x00000004 |
2047 | #define SKY2_HW_NEWER_PHY 0x00000008 | 2047 | #define SKY2_HW_NEWER_PHY 0x00000008 |
2048 | #define SKY2_HW_FIFO_HANG_CHECK 0x00000010 | 2048 | #define SKY2_HW_RAM_BUFFER 0x00000010 |
2049 | #define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ | 2049 | #define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ |
2050 | #define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ | 2050 | #define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ |
2051 | #define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ | 2051 | #define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ |
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index c99ce74a7aff..3af5b92b48c8 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c | |||
@@ -465,7 +465,7 @@ static struct pci_driver tlan_driver = { | |||
465 | 465 | ||
466 | static int __init tlan_probe(void) | 466 | static int __init tlan_probe(void) |
467 | { | 467 | { |
468 | static int pad_allocated; | 468 | int rc = -ENODEV; |
469 | 469 | ||
470 | printk(KERN_INFO "%s", tlan_banner); | 470 | printk(KERN_INFO "%s", tlan_banner); |
471 | 471 | ||
@@ -473,17 +473,22 @@ static int __init tlan_probe(void) | |||
473 | 473 | ||
474 | if (TLanPadBuffer == NULL) { | 474 | if (TLanPadBuffer == NULL) { |
475 | printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n"); | 475 | printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n"); |
476 | return -ENOMEM; | 476 | rc = -ENOMEM; |
477 | goto err_out; | ||
477 | } | 478 | } |
478 | 479 | ||
479 | memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE); | 480 | memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE); |
480 | pad_allocated = 1; | ||
481 | 481 | ||
482 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n"); | 482 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n"); |
483 | 483 | ||
484 | /* Use new style PCI probing. Now the kernel will | 484 | /* Use new style PCI probing. Now the kernel will |
485 | do most of this for us */ | 485 | do most of this for us */ |
486 | pci_register_driver(&tlan_driver); | 486 | rc = pci_register_driver(&tlan_driver); |
487 | |||
488 | if (rc != 0) { | ||
489 | printk(KERN_ERR "TLAN: Could not register pci driver.\n"); | ||
490 | goto err_out_pci_free; | ||
491 | } | ||
487 | 492 | ||
488 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n"); | 493 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n"); |
489 | TLan_EisaProbe(); | 494 | TLan_EisaProbe(); |
@@ -493,11 +498,17 @@ static int __init tlan_probe(void) | |||
493 | tlan_have_pci, tlan_have_eisa); | 498 | tlan_have_pci, tlan_have_eisa); |
494 | 499 | ||
495 | if (TLanDevicesInstalled == 0) { | 500 | if (TLanDevicesInstalled == 0) { |
496 | pci_unregister_driver(&tlan_driver); | 501 | rc = -ENODEV; |
497 | pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA); | 502 | goto err_out_pci_unreg; |
498 | return -ENODEV; | ||
499 | } | 503 | } |
500 | return 0; | 504 | return 0; |
505 | |||
506 | err_out_pci_unreg: | ||
507 | pci_unregister_driver(&tlan_driver); | ||
508 | err_out_pci_free: | ||
509 | pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA); | ||
510 | err_out: | ||
511 | return rc; | ||
501 | } | 512 | } |
502 | 513 | ||
503 | 514 | ||
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 8fc7274642eb..6b93d0169116 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c | |||
@@ -441,7 +441,7 @@ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
441 | spin_unlock_irqrestore(&card->lock,flags); | 441 | spin_unlock_irqrestore(&card->lock,flags); |
442 | trigger_transmit(card); | 442 | trigger_transmit(card); |
443 | 443 | ||
444 | return -EIO; | 444 | return NETDEV_TX_BUSY; |
445 | } | 445 | } |
446 | 446 | ||
447 | 447 | ||
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c index e3ba14a19915..c69e654d539f 100644 --- a/drivers/net/ucc_geth_mii.c +++ b/drivers/net/ucc_geth_mii.c | |||
@@ -109,7 +109,7 @@ int uec_mdio_reset(struct mii_bus *bus) | |||
109 | struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; | 109 | struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; |
110 | unsigned int timeout = PHY_INIT_TIMEOUT; | 110 | unsigned int timeout = PHY_INIT_TIMEOUT; |
111 | 111 | ||
112 | spin_lock_bh(&bus->mdio_lock); | 112 | mutex_lock(&bus->mdio_lock); |
113 | 113 | ||
114 | /* Reset the management interface */ | 114 | /* Reset the management interface */ |
115 | out_be32(®s->miimcfg, MIIMCFG_RESET_MANAGEMENT); | 115 | out_be32(®s->miimcfg, MIIMCFG_RESET_MANAGEMENT); |
@@ -121,7 +121,7 @@ int uec_mdio_reset(struct mii_bus *bus) | |||
121 | while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) | 121 | while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) |
122 | cpu_relax(); | 122 | cpu_relax(); |
123 | 123 | ||
124 | spin_unlock_bh(&bus->mdio_lock); | 124 | mutex_unlock(&bus->mdio_lock); |
125 | 125 | ||
126 | if (timeout <= 0) { | 126 | if (timeout <= 0) { |
127 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); | 127 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e66de0c12fc1..fdc23678117b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -302,10 +302,12 @@ static int virtnet_open(struct net_device *dev) | |||
302 | 302 | ||
303 | /* If all buffers were filled by other side before we napi_enabled, we | 303 | /* If all buffers were filled by other side before we napi_enabled, we |
304 | * won't get another interrupt, so process any outstanding packets | 304 | * won't get another interrupt, so process any outstanding packets |
305 | * now. virtnet_poll wants re-enable the queue, so we disable here. */ | 305 | * now. virtnet_poll wants re-enable the queue, so we disable here. |
306 | vi->rvq->vq_ops->disable_cb(vi->rvq); | 306 | * We synchronize against interrupts via NAPI_STATE_SCHED */ |
307 | netif_rx_schedule(vi->dev, &vi->napi); | 307 | if (netif_rx_schedule_prep(dev, &vi->napi)) { |
308 | 308 | vi->rvq->vq_ops->disable_cb(vi->rvq); | |
309 | __netif_rx_schedule(dev, &vi->napi); | ||
310 | } | ||
309 | return 0; | 311 | return 0; |
310 | } | 312 | } |
311 | 313 | ||
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index d553e6f32851..39951d0c34d6 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Generic HDLC support routines for Linux | 2 | * Generic HDLC support routines for Linux |
3 | * | 3 | * |
4 | * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl> | 4 | * Copyright (C) 1999 - 2008 Krzysztof Halasa <khc@pm.waw.pl> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of version 2 of the GNU General Public License | 7 | * under the terms of version 2 of the GNU General Public License |
@@ -39,7 +39,7 @@ | |||
39 | #include <net/net_namespace.h> | 39 | #include <net/net_namespace.h> |
40 | 40 | ||
41 | 41 | ||
42 | static const char* version = "HDLC support module revision 1.21"; | 42 | static const char* version = "HDLC support module revision 1.22"; |
43 | 43 | ||
44 | #undef DEBUG_LINK | 44 | #undef DEBUG_LINK |
45 | 45 | ||
@@ -66,19 +66,15 @@ static struct net_device_stats *hdlc_get_stats(struct net_device *dev) | |||
66 | static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, | 66 | static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, |
67 | struct packet_type *p, struct net_device *orig_dev) | 67 | struct packet_type *p, struct net_device *orig_dev) |
68 | { | 68 | { |
69 | struct hdlc_device_desc *desc = dev_to_desc(dev); | 69 | struct hdlc_device *hdlc = dev_to_hdlc(dev); |
70 | 70 | ||
71 | if (dev->nd_net != &init_net) { | 71 | if (dev->nd_net != &init_net) { |
72 | kfree_skb(skb); | 72 | kfree_skb(skb); |
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | if (desc->netif_rx) | 76 | BUG_ON(!hdlc->proto->netif_rx); |
77 | return desc->netif_rx(skb); | 77 | return hdlc->proto->netif_rx(skb); |
78 | |||
79 | desc->stats.rx_dropped++; /* Shouldn't happen */ | ||
80 | dev_kfree_skb(skb); | ||
81 | return NET_RX_DROP; | ||
82 | } | 78 | } |
83 | 79 | ||
84 | 80 | ||
@@ -87,7 +83,7 @@ static inline void hdlc_proto_start(struct net_device *dev) | |||
87 | { | 83 | { |
88 | hdlc_device *hdlc = dev_to_hdlc(dev); | 84 | hdlc_device *hdlc = dev_to_hdlc(dev); |
89 | if (hdlc->proto->start) | 85 | if (hdlc->proto->start) |
90 | return hdlc->proto->start(dev); | 86 | hdlc->proto->start(dev); |
91 | } | 87 | } |
92 | 88 | ||
93 | 89 | ||
@@ -96,7 +92,7 @@ static inline void hdlc_proto_stop(struct net_device *dev) | |||
96 | { | 92 | { |
97 | hdlc_device *hdlc = dev_to_hdlc(dev); | 93 | hdlc_device *hdlc = dev_to_hdlc(dev); |
98 | if (hdlc->proto->stop) | 94 | if (hdlc->proto->stop) |
99 | return hdlc->proto->stop(dev); | 95 | hdlc->proto->stop(dev); |
100 | } | 96 | } |
101 | 97 | ||
102 | 98 | ||
@@ -263,8 +259,7 @@ static void hdlc_setup(struct net_device *dev) | |||
263 | struct net_device *alloc_hdlcdev(void *priv) | 259 | struct net_device *alloc_hdlcdev(void *priv) |
264 | { | 260 | { |
265 | struct net_device *dev; | 261 | struct net_device *dev; |
266 | dev = alloc_netdev(sizeof(struct hdlc_device_desc) + | 262 | dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d", hdlc_setup); |
267 | sizeof(hdlc_device), "hdlc%d", hdlc_setup); | ||
268 | if (dev) | 263 | if (dev) |
269 | dev_to_hdlc(dev)->priv = priv; | 264 | dev_to_hdlc(dev)->priv = priv; |
270 | return dev; | 265 | return dev; |
@@ -281,7 +276,7 @@ void unregister_hdlc_device(struct net_device *dev) | |||
281 | 276 | ||
282 | 277 | ||
283 | int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, | 278 | int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, |
284 | int (*rx)(struct sk_buff *skb), size_t size) | 279 | size_t size) |
285 | { | 280 | { |
286 | detach_hdlc_protocol(dev); | 281 | detach_hdlc_protocol(dev); |
287 | 282 | ||
@@ -297,7 +292,6 @@ int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, | |||
297 | return -ENOBUFS; | 292 | return -ENOBUFS; |
298 | } | 293 | } |
299 | dev_to_hdlc(dev)->proto = proto; | 294 | dev_to_hdlc(dev)->proto = proto; |
300 | dev_to_desc(dev)->netif_rx = rx; | ||
301 | return 0; | 295 | return 0; |
302 | } | 296 | } |
303 | 297 | ||
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 038a6e748bbf..7133c688cf20 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c | |||
@@ -250,7 +250,7 @@ static int cisco_rx(struct sk_buff *skb) | |||
250 | return NET_RX_DROP; | 250 | return NET_RX_DROP; |
251 | 251 | ||
252 | rx_error: | 252 | rx_error: |
253 | dev_to_desc(dev)->stats.rx_errors++; /* Mark error */ | 253 | dev_to_hdlc(dev)->stats.rx_errors++; /* Mark error */ |
254 | dev_kfree_skb_any(skb); | 254 | dev_kfree_skb_any(skb); |
255 | return NET_RX_DROP; | 255 | return NET_RX_DROP; |
256 | } | 256 | } |
@@ -314,6 +314,7 @@ static struct hdlc_proto proto = { | |||
314 | .stop = cisco_stop, | 314 | .stop = cisco_stop, |
315 | .type_trans = cisco_type_trans, | 315 | .type_trans = cisco_type_trans, |
316 | .ioctl = cisco_ioctl, | 316 | .ioctl = cisco_ioctl, |
317 | .netif_rx = cisco_rx, | ||
317 | .module = THIS_MODULE, | 318 | .module = THIS_MODULE, |
318 | }; | 319 | }; |
319 | 320 | ||
@@ -360,7 +361,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
360 | if (result) | 361 | if (result) |
361 | return result; | 362 | return result; |
362 | 363 | ||
363 | result = attach_hdlc_protocol(dev, &proto, cisco_rx, | 364 | result = attach_hdlc_protocol(dev, &proto, |
364 | sizeof(struct cisco_state)); | 365 | sizeof(struct cisco_state)); |
365 | if (result) | 366 | if (result) |
366 | return result; | 367 | return result; |
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 071a64cacd5c..c4ab0326f911 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | #include <linux/skbuff.h> | 43 | #include <linux/skbuff.h> |
44 | #include <linux/pkt_sched.h> | 44 | #include <linux/pkt_sched.h> |
45 | #include <linux/random.h> | ||
46 | #include <linux/inetdevice.h> | 45 | #include <linux/inetdevice.h> |
47 | #include <linux/lapb.h> | 46 | #include <linux/lapb.h> |
48 | #include <linux/rtnetlink.h> | 47 | #include <linux/rtnetlink.h> |
@@ -136,6 +135,10 @@ typedef struct pvc_device_struct { | |||
136 | }state; | 135 | }state; |
137 | }pvc_device; | 136 | }pvc_device; |
138 | 137 | ||
138 | struct pvc_desc { | ||
139 | struct net_device_stats stats; | ||
140 | pvc_device *pvc; | ||
141 | }; | ||
139 | 142 | ||
140 | struct frad_state { | 143 | struct frad_state { |
141 | fr_proto settings; | 144 | fr_proto settings; |
@@ -171,17 +174,20 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci) | |||
171 | } | 174 | } |
172 | 175 | ||
173 | 176 | ||
174 | static inline struct frad_state * state(hdlc_device *hdlc) | 177 | static inline struct frad_state* state(hdlc_device *hdlc) |
175 | { | 178 | { |
176 | return(struct frad_state *)(hdlc->state); | 179 | return(struct frad_state *)(hdlc->state); |
177 | } | 180 | } |
178 | 181 | ||
179 | 182 | static inline struct pvc_desc* pvcdev_to_desc(struct net_device *dev) | |
180 | static __inline__ pvc_device* dev_to_pvc(struct net_device *dev) | ||
181 | { | 183 | { |
182 | return dev->priv; | 184 | return dev->priv; |
183 | } | 185 | } |
184 | 186 | ||
187 | static inline struct net_device_stats* pvc_get_stats(struct net_device *dev) | ||
188 | { | ||
189 | return &pvcdev_to_desc(dev)->stats; | ||
190 | } | ||
185 | 191 | ||
186 | static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) | 192 | static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) |
187 | { | 193 | { |
@@ -351,7 +357,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) | |||
351 | 357 | ||
352 | static int pvc_open(struct net_device *dev) | 358 | static int pvc_open(struct net_device *dev) |
353 | { | 359 | { |
354 | pvc_device *pvc = dev_to_pvc(dev); | 360 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
355 | 361 | ||
356 | if ((pvc->frad->flags & IFF_UP) == 0) | 362 | if ((pvc->frad->flags & IFF_UP) == 0) |
357 | return -EIO; /* Frad must be UP in order to activate PVC */ | 363 | return -EIO; /* Frad must be UP in order to activate PVC */ |
@@ -371,7 +377,7 @@ static int pvc_open(struct net_device *dev) | |||
371 | 377 | ||
372 | static int pvc_close(struct net_device *dev) | 378 | static int pvc_close(struct net_device *dev) |
373 | { | 379 | { |
374 | pvc_device *pvc = dev_to_pvc(dev); | 380 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
375 | 381 | ||
376 | if (--pvc->open_count == 0) { | 382 | if (--pvc->open_count == 0) { |
377 | hdlc_device *hdlc = dev_to_hdlc(pvc->frad); | 383 | hdlc_device *hdlc = dev_to_hdlc(pvc->frad); |
@@ -390,7 +396,7 @@ static int pvc_close(struct net_device *dev) | |||
390 | 396 | ||
391 | static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 397 | static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
392 | { | 398 | { |
393 | pvc_device *pvc = dev_to_pvc(dev); | 399 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
394 | fr_proto_pvc_info info; | 400 | fr_proto_pvc_info info; |
395 | 401 | ||
396 | if (ifr->ifr_settings.type == IF_GET_PROTO) { | 402 | if (ifr->ifr_settings.type == IF_GET_PROTO) { |
@@ -416,17 +422,9 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
416 | return -EINVAL; | 422 | return -EINVAL; |
417 | } | 423 | } |
418 | 424 | ||
419 | |||
420 | static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) | ||
421 | { | ||
422 | return &dev_to_desc(dev)->stats; | ||
423 | } | ||
424 | |||
425 | |||
426 | |||
427 | static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) | 425 | static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) |
428 | { | 426 | { |
429 | pvc_device *pvc = dev_to_pvc(dev); | 427 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
430 | struct net_device_stats *stats = pvc_get_stats(dev); | 428 | struct net_device_stats *stats = pvc_get_stats(dev); |
431 | 429 | ||
432 | if (pvc->state.active) { | 430 | if (pvc->state.active) { |
@@ -957,7 +955,7 @@ static int fr_rx(struct sk_buff *skb) | |||
957 | 955 | ||
958 | 956 | ||
959 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 957 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
960 | dev_to_desc(frad)->stats.rx_dropped++; | 958 | dev_to_hdlc(frad)->stats.rx_dropped++; |
961 | return NET_RX_DROP; | 959 | return NET_RX_DROP; |
962 | } | 960 | } |
963 | 961 | ||
@@ -1018,7 +1016,7 @@ static int fr_rx(struct sk_buff *skb) | |||
1018 | } | 1016 | } |
1019 | 1017 | ||
1020 | rx_error: | 1018 | rx_error: |
1021 | dev_to_desc(frad)->stats.rx_errors++; /* Mark error */ | 1019 | dev_to_hdlc(frad)->stats.rx_errors++; /* Mark error */ |
1022 | dev_kfree_skb_any(skb); | 1020 | dev_kfree_skb_any(skb); |
1023 | return NET_RX_DROP; | 1021 | return NET_RX_DROP; |
1024 | } | 1022 | } |
@@ -1109,11 +1107,10 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1109 | used = pvc_is_used(pvc); | 1107 | used = pvc_is_used(pvc); |
1110 | 1108 | ||
1111 | if (type == ARPHRD_ETHER) | 1109 | if (type == ARPHRD_ETHER) |
1112 | dev = alloc_netdev(sizeof(struct net_device_stats), | 1110 | dev = alloc_netdev(sizeof(struct pvc_desc), "pvceth%d", |
1113 | "pvceth%d", ether_setup); | 1111 | ether_setup); |
1114 | else | 1112 | else |
1115 | dev = alloc_netdev(sizeof(struct net_device_stats), | 1113 | dev = alloc_netdev(sizeof(struct pvc_desc), "pvc%d", pvc_setup); |
1116 | "pvc%d", pvc_setup); | ||
1117 | 1114 | ||
1118 | if (!dev) { | 1115 | if (!dev) { |
1119 | printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", | 1116 | printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", |
@@ -1122,10 +1119,9 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1122 | return -ENOBUFS; | 1119 | return -ENOBUFS; |
1123 | } | 1120 | } |
1124 | 1121 | ||
1125 | if (type == ARPHRD_ETHER) { | 1122 | if (type == ARPHRD_ETHER) |
1126 | memcpy(dev->dev_addr, "\x00\x01", 2); | 1123 | random_ether_addr(dev->dev_addr); |
1127 | get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); | 1124 | else { |
1128 | } else { | ||
1129 | *(__be16*)dev->dev_addr = htons(dlci); | 1125 | *(__be16*)dev->dev_addr = htons(dlci); |
1130 | dlci_to_q922(dev->broadcast, dlci); | 1126 | dlci_to_q922(dev->broadcast, dlci); |
1131 | } | 1127 | } |
@@ -1137,7 +1133,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1137 | dev->change_mtu = pvc_change_mtu; | 1133 | dev->change_mtu = pvc_change_mtu; |
1138 | dev->mtu = HDLC_MAX_MTU; | 1134 | dev->mtu = HDLC_MAX_MTU; |
1139 | dev->tx_queue_len = 0; | 1135 | dev->tx_queue_len = 0; |
1140 | dev->priv = pvc; | 1136 | pvcdev_to_desc(dev)->pvc = pvc; |
1141 | 1137 | ||
1142 | result = dev_alloc_name(dev, dev->name); | 1138 | result = dev_alloc_name(dev, dev->name); |
1143 | if (result < 0) { | 1139 | if (result < 0) { |
@@ -1219,6 +1215,7 @@ static struct hdlc_proto proto = { | |||
1219 | .stop = fr_stop, | 1215 | .stop = fr_stop, |
1220 | .detach = fr_destroy, | 1216 | .detach = fr_destroy, |
1221 | .ioctl = fr_ioctl, | 1217 | .ioctl = fr_ioctl, |
1218 | .netif_rx = fr_rx, | ||
1222 | .module = THIS_MODULE, | 1219 | .module = THIS_MODULE, |
1223 | }; | 1220 | }; |
1224 | 1221 | ||
@@ -1277,7 +1274,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
1277 | return result; | 1274 | return result; |
1278 | 1275 | ||
1279 | if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */ | 1276 | if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */ |
1280 | result = attach_hdlc_protocol(dev, &proto, fr_rx, | 1277 | result = attach_hdlc_protocol(dev, &proto, |
1281 | sizeof(struct frad_state)); | 1278 | sizeof(struct frad_state)); |
1282 | if (result) | 1279 | if (result) |
1283 | return result; | 1280 | return result; |
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 519e1550e2e7..10396d9686f4 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c | |||
@@ -122,7 +122,7 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
122 | if (result) | 122 | if (result) |
123 | return result; | 123 | return result; |
124 | 124 | ||
125 | result = attach_hdlc_protocol(dev, &proto, NULL, | 125 | result = attach_hdlc_protocol(dev, &proto, |
126 | sizeof(struct ppp_state)); | 126 | sizeof(struct ppp_state)); |
127 | if (result) | 127 | if (result) |
128 | return result; | 128 | return result; |
diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index e23bc6656267..bbbb819d764c 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c | |||
@@ -82,7 +82,7 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
82 | if (result) | 82 | if (result) |
83 | return result; | 83 | return result; |
84 | 84 | ||
85 | result = attach_hdlc_protocol(dev, &proto, NULL, | 85 | result = attach_hdlc_protocol(dev, &proto, |
86 | sizeof(raw_hdlc_proto)); | 86 | sizeof(raw_hdlc_proto)); |
87 | if (result) | 87 | if (result) |
88 | return result; | 88 | return result; |
diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c index 8895394e6006..d20c685f6711 100644 --- a/drivers/net/wan/hdlc_raw_eth.c +++ b/drivers/net/wan/hdlc_raw_eth.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | #include <linux/pkt_sched.h> | 20 | #include <linux/pkt_sched.h> |
21 | #include <linux/random.h> | ||
22 | #include <linux/inetdevice.h> | 21 | #include <linux/inetdevice.h> |
23 | #include <linux/lapb.h> | 22 | #include <linux/lapb.h> |
24 | #include <linux/rtnetlink.h> | 23 | #include <linux/rtnetlink.h> |
@@ -96,7 +95,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
96 | if (result) | 95 | if (result) |
97 | return result; | 96 | return result; |
98 | 97 | ||
99 | result = attach_hdlc_protocol(dev, &proto, NULL, | 98 | result = attach_hdlc_protocol(dev, &proto, |
100 | sizeof(raw_hdlc_proto)); | 99 | sizeof(raw_hdlc_proto)); |
101 | if (result) | 100 | if (result) |
102 | return result; | 101 | return result; |
@@ -107,8 +106,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
107 | ether_setup(dev); | 106 | ether_setup(dev); |
108 | dev->change_mtu = old_ch_mtu; | 107 | dev->change_mtu = old_ch_mtu; |
109 | dev->tx_queue_len = old_qlen; | 108 | dev->tx_queue_len = old_qlen; |
110 | memcpy(dev->dev_addr, "\x00\x01", 2); | 109 | random_ether_addr(dev->dev_addr); |
111 | get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); | ||
112 | netif_dormant_off(dev); | 110 | netif_dormant_off(dev); |
113 | return 0; | 111 | return 0; |
114 | } | 112 | } |
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index cd7b22f50edc..c15cc11e399b 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c | |||
@@ -164,17 +164,17 @@ static void x25_close(struct net_device *dev) | |||
164 | 164 | ||
165 | static int x25_rx(struct sk_buff *skb) | 165 | static int x25_rx(struct sk_buff *skb) |
166 | { | 166 | { |
167 | struct hdlc_device_desc *desc = dev_to_desc(skb->dev); | 167 | struct hdlc_device *hdlc = dev_to_hdlc(skb->dev); |
168 | 168 | ||
169 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 169 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
170 | desc->stats.rx_dropped++; | 170 | hdlc->stats.rx_dropped++; |
171 | return NET_RX_DROP; | 171 | return NET_RX_DROP; |
172 | } | 172 | } |
173 | 173 | ||
174 | if (lapb_data_received(skb->dev, skb) == LAPB_OK) | 174 | if (lapb_data_received(skb->dev, skb) == LAPB_OK) |
175 | return NET_RX_SUCCESS; | 175 | return NET_RX_SUCCESS; |
176 | 176 | ||
177 | desc->stats.rx_errors++; | 177 | hdlc->stats.rx_errors++; |
178 | dev_kfree_skb_any(skb); | 178 | dev_kfree_skb_any(skb); |
179 | return NET_RX_DROP; | 179 | return NET_RX_DROP; |
180 | } | 180 | } |
@@ -184,6 +184,7 @@ static struct hdlc_proto proto = { | |||
184 | .open = x25_open, | 184 | .open = x25_open, |
185 | .close = x25_close, | 185 | .close = x25_close, |
186 | .ioctl = x25_ioctl, | 186 | .ioctl = x25_ioctl, |
187 | .netif_rx = x25_rx, | ||
187 | .module = THIS_MODULE, | 188 | .module = THIS_MODULE, |
188 | }; | 189 | }; |
189 | 190 | ||
@@ -211,8 +212,7 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
211 | if (result) | 212 | if (result) |
212 | return result; | 213 | return result; |
213 | 214 | ||
214 | if ((result = attach_hdlc_protocol(dev, &proto, | 215 | if ((result = attach_hdlc_protocol(dev, &proto, 0))) |
215 | x25_rx, 0)) != 0) | ||
216 | return result; | 216 | return result; |
217 | dev->hard_start_xmit = x25_xmit; | 217 | dev->hard_start_xmit = x25_xmit; |
218 | dev->type = ARPHRD_X25; | 218 | dev->type = ARPHRD_X25; |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 8a708b77925d..3dfb28a34be9 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -337,7 +337,7 @@ static inline int txring_to_priority(struct b43_dmaring *ring) | |||
337 | return idx_to_prio[index]; | 337 | return idx_to_prio[index]; |
338 | } | 338 | } |
339 | 339 | ||
340 | u16 b43_dmacontroller_base(int dma64bit, int controller_idx) | 340 | static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) |
341 | { | 341 | { |
342 | static const u16 map64[] = { | 342 | static const u16 map64[] = { |
343 | B43_MMIO_DMA64_BASE0, | 343 | B43_MMIO_DMA64_BASE0, |
@@ -356,7 +356,7 @@ u16 b43_dmacontroller_base(int dma64bit, int controller_idx) | |||
356 | B43_MMIO_DMA32_BASE5, | 356 | B43_MMIO_DMA32_BASE5, |
357 | }; | 357 | }; |
358 | 358 | ||
359 | if (dma64bit) { | 359 | if (type == B43_DMA_64BIT) { |
360 | B43_WARN_ON(!(controller_idx >= 0 && | 360 | B43_WARN_ON(!(controller_idx >= 0 && |
361 | controller_idx < ARRAY_SIZE(map64))); | 361 | controller_idx < ARRAY_SIZE(map64))); |
362 | return map64[controller_idx]; | 362 | return map64[controller_idx]; |
@@ -437,7 +437,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring) | |||
437 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, | 437 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, |
438 | * which accounts for the GFP_DMA flag below. | 438 | * which accounts for the GFP_DMA flag below. |
439 | */ | 439 | */ |
440 | if (ring->dma64) | 440 | if (ring->type == B43_DMA_64BIT) |
441 | flags |= GFP_DMA; | 441 | flags |= GFP_DMA; |
442 | ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE, | 442 | ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE, |
443 | &(ring->dmabase), flags); | 443 | &(ring->dmabase), flags); |
@@ -459,7 +459,8 @@ static void free_ringmemory(struct b43_dmaring *ring) | |||
459 | } | 459 | } |
460 | 460 | ||
461 | /* Reset the RX DMA channel */ | 461 | /* Reset the RX DMA channel */ |
462 | int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | 462 | static int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, |
463 | enum b43_dmatype type) | ||
463 | { | 464 | { |
464 | int i; | 465 | int i; |
465 | u32 value; | 466 | u32 value; |
@@ -467,12 +468,13 @@ int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
467 | 468 | ||
468 | might_sleep(); | 469 | might_sleep(); |
469 | 470 | ||
470 | offset = dma64 ? B43_DMA64_RXCTL : B43_DMA32_RXCTL; | 471 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXCTL : B43_DMA32_RXCTL; |
471 | b43_write32(dev, mmio_base + offset, 0); | 472 | b43_write32(dev, mmio_base + offset, 0); |
472 | for (i = 0; i < 10; i++) { | 473 | for (i = 0; i < 10; i++) { |
473 | offset = dma64 ? B43_DMA64_RXSTATUS : B43_DMA32_RXSTATUS; | 474 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXSTATUS : |
475 | B43_DMA32_RXSTATUS; | ||
474 | value = b43_read32(dev, mmio_base + offset); | 476 | value = b43_read32(dev, mmio_base + offset); |
475 | if (dma64) { | 477 | if (type == B43_DMA_64BIT) { |
476 | value &= B43_DMA64_RXSTAT; | 478 | value &= B43_DMA64_RXSTAT; |
477 | if (value == B43_DMA64_RXSTAT_DISABLED) { | 479 | if (value == B43_DMA64_RXSTAT_DISABLED) { |
478 | i = -1; | 480 | i = -1; |
@@ -496,7 +498,8 @@ int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
496 | } | 498 | } |
497 | 499 | ||
498 | /* Reset the TX DMA channel */ | 500 | /* Reset the TX DMA channel */ |
499 | int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | 501 | static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, |
502 | enum b43_dmatype type) | ||
500 | { | 503 | { |
501 | int i; | 504 | int i; |
502 | u32 value; | 505 | u32 value; |
@@ -505,9 +508,10 @@ int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
505 | might_sleep(); | 508 | might_sleep(); |
506 | 509 | ||
507 | for (i = 0; i < 10; i++) { | 510 | for (i = 0; i < 10; i++) { |
508 | offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS; | 511 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS : |
512 | B43_DMA32_TXSTATUS; | ||
509 | value = b43_read32(dev, mmio_base + offset); | 513 | value = b43_read32(dev, mmio_base + offset); |
510 | if (dma64) { | 514 | if (type == B43_DMA_64BIT) { |
511 | value &= B43_DMA64_TXSTAT; | 515 | value &= B43_DMA64_TXSTAT; |
512 | if (value == B43_DMA64_TXSTAT_DISABLED || | 516 | if (value == B43_DMA64_TXSTAT_DISABLED || |
513 | value == B43_DMA64_TXSTAT_IDLEWAIT || | 517 | value == B43_DMA64_TXSTAT_IDLEWAIT || |
@@ -522,12 +526,13 @@ int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
522 | } | 526 | } |
523 | msleep(1); | 527 | msleep(1); |
524 | } | 528 | } |
525 | offset = dma64 ? B43_DMA64_TXCTL : B43_DMA32_TXCTL; | 529 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXCTL : B43_DMA32_TXCTL; |
526 | b43_write32(dev, mmio_base + offset, 0); | 530 | b43_write32(dev, mmio_base + offset, 0); |
527 | for (i = 0; i < 10; i++) { | 531 | for (i = 0; i < 10; i++) { |
528 | offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS; | 532 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS : |
533 | B43_DMA32_TXSTATUS; | ||
529 | value = b43_read32(dev, mmio_base + offset); | 534 | value = b43_read32(dev, mmio_base + offset); |
530 | if (dma64) { | 535 | if (type == B43_DMA_64BIT) { |
531 | value &= B43_DMA64_TXSTAT; | 536 | value &= B43_DMA64_TXSTAT; |
532 | if (value == B43_DMA64_TXSTAT_DISABLED) { | 537 | if (value == B43_DMA64_TXSTAT_DISABLED) { |
533 | i = -1; | 538 | i = -1; |
@@ -552,6 +557,33 @@ int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
552 | return 0; | 557 | return 0; |
553 | } | 558 | } |
554 | 559 | ||
560 | /* Check if a DMA mapping address is invalid. */ | ||
561 | static bool b43_dma_mapping_error(struct b43_dmaring *ring, | ||
562 | dma_addr_t addr, | ||
563 | size_t buffersize) | ||
564 | { | ||
565 | if (unlikely(dma_mapping_error(addr))) | ||
566 | return 1; | ||
567 | |||
568 | switch (ring->type) { | ||
569 | case B43_DMA_30BIT: | ||
570 | if ((u64)addr + buffersize > (1ULL << 30)) | ||
571 | return 1; | ||
572 | break; | ||
573 | case B43_DMA_32BIT: | ||
574 | if ((u64)addr + buffersize > (1ULL << 32)) | ||
575 | return 1; | ||
576 | break; | ||
577 | case B43_DMA_64BIT: | ||
578 | /* Currently we can't have addresses beyond | ||
579 | * 64bit in the kernel. */ | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | /* The address is OK. */ | ||
584 | return 0; | ||
585 | } | ||
586 | |||
555 | static int setup_rx_descbuffer(struct b43_dmaring *ring, | 587 | static int setup_rx_descbuffer(struct b43_dmaring *ring, |
556 | struct b43_dmadesc_generic *desc, | 588 | struct b43_dmadesc_generic *desc, |
557 | struct b43_dmadesc_meta *meta, gfp_t gfp_flags) | 589 | struct b43_dmadesc_meta *meta, gfp_t gfp_flags) |
@@ -567,7 +599,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, | |||
567 | if (unlikely(!skb)) | 599 | if (unlikely(!skb)) |
568 | return -ENOMEM; | 600 | return -ENOMEM; |
569 | dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); | 601 | dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); |
570 | if (dma_mapping_error(dmaaddr)) { | 602 | if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { |
571 | /* ugh. try to realloc in zone_dma */ | 603 | /* ugh. try to realloc in zone_dma */ |
572 | gfp_flags |= GFP_DMA; | 604 | gfp_flags |= GFP_DMA; |
573 | 605 | ||
@@ -580,7 +612,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, | |||
580 | ring->rx_buffersize, 0); | 612 | ring->rx_buffersize, 0); |
581 | } | 613 | } |
582 | 614 | ||
583 | if (dma_mapping_error(dmaaddr)) { | 615 | if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { |
584 | dev_kfree_skb_any(skb); | 616 | dev_kfree_skb_any(skb); |
585 | return -EIO; | 617 | return -EIO; |
586 | } | 618 | } |
@@ -645,7 +677,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) | |||
645 | u32 trans = ssb_dma_translation(ring->dev->dev); | 677 | u32 trans = ssb_dma_translation(ring->dev->dev); |
646 | 678 | ||
647 | if (ring->tx) { | 679 | if (ring->tx) { |
648 | if (ring->dma64) { | 680 | if (ring->type == B43_DMA_64BIT) { |
649 | u64 ringbase = (u64) (ring->dmabase); | 681 | u64 ringbase = (u64) (ring->dmabase); |
650 | 682 | ||
651 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) | 683 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) |
@@ -677,7 +709,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) | |||
677 | err = alloc_initial_descbuffers(ring); | 709 | err = alloc_initial_descbuffers(ring); |
678 | if (err) | 710 | if (err) |
679 | goto out; | 711 | goto out; |
680 | if (ring->dma64) { | 712 | if (ring->type == B43_DMA_64BIT) { |
681 | u64 ringbase = (u64) (ring->dmabase); | 713 | u64 ringbase = (u64) (ring->dmabase); |
682 | 714 | ||
683 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) | 715 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) |
@@ -722,16 +754,16 @@ static void dmacontroller_cleanup(struct b43_dmaring *ring) | |||
722 | { | 754 | { |
723 | if (ring->tx) { | 755 | if (ring->tx) { |
724 | b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base, | 756 | b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base, |
725 | ring->dma64); | 757 | ring->type); |
726 | if (ring->dma64) { | 758 | if (ring->type == B43_DMA_64BIT) { |
727 | b43_dma_write(ring, B43_DMA64_TXRINGLO, 0); | 759 | b43_dma_write(ring, B43_DMA64_TXRINGLO, 0); |
728 | b43_dma_write(ring, B43_DMA64_TXRINGHI, 0); | 760 | b43_dma_write(ring, B43_DMA64_TXRINGHI, 0); |
729 | } else | 761 | } else |
730 | b43_dma_write(ring, B43_DMA32_TXRING, 0); | 762 | b43_dma_write(ring, B43_DMA32_TXRING, 0); |
731 | } else { | 763 | } else { |
732 | b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base, | 764 | b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base, |
733 | ring->dma64); | 765 | ring->type); |
734 | if (ring->dma64) { | 766 | if (ring->type == B43_DMA_64BIT) { |
735 | b43_dma_write(ring, B43_DMA64_RXRINGLO, 0); | 767 | b43_dma_write(ring, B43_DMA64_RXRINGLO, 0); |
736 | b43_dma_write(ring, B43_DMA64_RXRINGHI, 0); | 768 | b43_dma_write(ring, B43_DMA64_RXRINGHI, 0); |
737 | } else | 769 | } else |
@@ -786,7 +818,8 @@ static u64 supported_dma_mask(struct b43_wldev *dev) | |||
786 | static | 818 | static |
787 | struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | 819 | struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, |
788 | int controller_index, | 820 | int controller_index, |
789 | int for_tx, int dma64) | 821 | int for_tx, |
822 | enum b43_dmatype type) | ||
790 | { | 823 | { |
791 | struct b43_dmaring *ring; | 824 | struct b43_dmaring *ring; |
792 | int err; | 825 | int err; |
@@ -796,6 +829,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
796 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 829 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
797 | if (!ring) | 830 | if (!ring) |
798 | goto out; | 831 | goto out; |
832 | ring->type = type; | ||
799 | 833 | ||
800 | nr_slots = B43_RXRING_SLOTS; | 834 | nr_slots = B43_RXRING_SLOTS; |
801 | if (for_tx) | 835 | if (for_tx) |
@@ -818,7 +852,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
818 | b43_txhdr_size(dev), | 852 | b43_txhdr_size(dev), |
819 | DMA_TO_DEVICE); | 853 | DMA_TO_DEVICE); |
820 | 854 | ||
821 | if (dma_mapping_error(dma_test)) { | 855 | if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev))) { |
822 | /* ugh realloc */ | 856 | /* ugh realloc */ |
823 | kfree(ring->txhdr_cache); | 857 | kfree(ring->txhdr_cache); |
824 | ring->txhdr_cache = kcalloc(nr_slots, | 858 | ring->txhdr_cache = kcalloc(nr_slots, |
@@ -832,7 +866,8 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
832 | b43_txhdr_size(dev), | 866 | b43_txhdr_size(dev), |
833 | DMA_TO_DEVICE); | 867 | DMA_TO_DEVICE); |
834 | 868 | ||
835 | if (dma_mapping_error(dma_test)) | 869 | if (b43_dma_mapping_error(ring, dma_test, |
870 | b43_txhdr_size(dev))) | ||
836 | goto err_kfree_txhdr_cache; | 871 | goto err_kfree_txhdr_cache; |
837 | } | 872 | } |
838 | 873 | ||
@@ -843,10 +878,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
843 | 878 | ||
844 | ring->dev = dev; | 879 | ring->dev = dev; |
845 | ring->nr_slots = nr_slots; | 880 | ring->nr_slots = nr_slots; |
846 | ring->mmio_base = b43_dmacontroller_base(dma64, controller_index); | 881 | ring->mmio_base = b43_dmacontroller_base(type, controller_index); |
847 | ring->index = controller_index; | 882 | ring->index = controller_index; |
848 | ring->dma64 = !!dma64; | 883 | if (type == B43_DMA_64BIT) |
849 | if (dma64) | ||
850 | ring->ops = &dma64_ops; | 884 | ring->ops = &dma64_ops; |
851 | else | 885 | else |
852 | ring->ops = &dma32_ops; | 886 | ring->ops = &dma32_ops; |
@@ -896,8 +930,8 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring) | |||
896 | if (!ring) | 930 | if (!ring) |
897 | return; | 931 | return; |
898 | 932 | ||
899 | b43dbg(ring->dev->wl, "DMA-%s 0x%04X (%s) max used slots: %d/%d\n", | 933 | b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n", |
900 | (ring->dma64) ? "64" : "32", | 934 | (unsigned int)(ring->type), |
901 | ring->mmio_base, | 935 | ring->mmio_base, |
902 | (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots); | 936 | (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots); |
903 | /* Device IRQs are disabled prior entering this function, | 937 | /* Device IRQs are disabled prior entering this function, |
@@ -941,12 +975,22 @@ int b43_dma_init(struct b43_wldev *dev) | |||
941 | struct b43_dmaring *ring; | 975 | struct b43_dmaring *ring; |
942 | int err; | 976 | int err; |
943 | u64 dmamask; | 977 | u64 dmamask; |
944 | int dma64 = 0; | 978 | enum b43_dmatype type; |
945 | 979 | ||
946 | dmamask = supported_dma_mask(dev); | 980 | dmamask = supported_dma_mask(dev); |
947 | if (dmamask == DMA_64BIT_MASK) | 981 | switch (dmamask) { |
948 | dma64 = 1; | 982 | default: |
949 | 983 | B43_WARN_ON(1); | |
984 | case DMA_30BIT_MASK: | ||
985 | type = B43_DMA_30BIT; | ||
986 | break; | ||
987 | case DMA_32BIT_MASK: | ||
988 | type = B43_DMA_32BIT; | ||
989 | break; | ||
990 | case DMA_64BIT_MASK: | ||
991 | type = B43_DMA_64BIT; | ||
992 | break; | ||
993 | } | ||
950 | err = ssb_dma_set_mask(dev->dev, dmamask); | 994 | err = ssb_dma_set_mask(dev->dev, dmamask); |
951 | if (err) { | 995 | if (err) { |
952 | b43err(dev->wl, "The machine/kernel does not support " | 996 | b43err(dev->wl, "The machine/kernel does not support " |
@@ -958,52 +1002,51 @@ int b43_dma_init(struct b43_wldev *dev) | |||
958 | 1002 | ||
959 | err = -ENOMEM; | 1003 | err = -ENOMEM; |
960 | /* setup TX DMA channels. */ | 1004 | /* setup TX DMA channels. */ |
961 | ring = b43_setup_dmaring(dev, 0, 1, dma64); | 1005 | ring = b43_setup_dmaring(dev, 0, 1, type); |
962 | if (!ring) | 1006 | if (!ring) |
963 | goto out; | 1007 | goto out; |
964 | dma->tx_ring0 = ring; | 1008 | dma->tx_ring0 = ring; |
965 | 1009 | ||
966 | ring = b43_setup_dmaring(dev, 1, 1, dma64); | 1010 | ring = b43_setup_dmaring(dev, 1, 1, type); |
967 | if (!ring) | 1011 | if (!ring) |
968 | goto err_destroy_tx0; | 1012 | goto err_destroy_tx0; |
969 | dma->tx_ring1 = ring; | 1013 | dma->tx_ring1 = ring; |
970 | 1014 | ||
971 | ring = b43_setup_dmaring(dev, 2, 1, dma64); | 1015 | ring = b43_setup_dmaring(dev, 2, 1, type); |
972 | if (!ring) | 1016 | if (!ring) |
973 | goto err_destroy_tx1; | 1017 | goto err_destroy_tx1; |
974 | dma->tx_ring2 = ring; | 1018 | dma->tx_ring2 = ring; |
975 | 1019 | ||
976 | ring = b43_setup_dmaring(dev, 3, 1, dma64); | 1020 | ring = b43_setup_dmaring(dev, 3, 1, type); |
977 | if (!ring) | 1021 | if (!ring) |
978 | goto err_destroy_tx2; | 1022 | goto err_destroy_tx2; |
979 | dma->tx_ring3 = ring; | 1023 | dma->tx_ring3 = ring; |
980 | 1024 | ||
981 | ring = b43_setup_dmaring(dev, 4, 1, dma64); | 1025 | ring = b43_setup_dmaring(dev, 4, 1, type); |
982 | if (!ring) | 1026 | if (!ring) |
983 | goto err_destroy_tx3; | 1027 | goto err_destroy_tx3; |
984 | dma->tx_ring4 = ring; | 1028 | dma->tx_ring4 = ring; |
985 | 1029 | ||
986 | ring = b43_setup_dmaring(dev, 5, 1, dma64); | 1030 | ring = b43_setup_dmaring(dev, 5, 1, type); |
987 | if (!ring) | 1031 | if (!ring) |
988 | goto err_destroy_tx4; | 1032 | goto err_destroy_tx4; |
989 | dma->tx_ring5 = ring; | 1033 | dma->tx_ring5 = ring; |
990 | 1034 | ||
991 | /* setup RX DMA channels. */ | 1035 | /* setup RX DMA channels. */ |
992 | ring = b43_setup_dmaring(dev, 0, 0, dma64); | 1036 | ring = b43_setup_dmaring(dev, 0, 0, type); |
993 | if (!ring) | 1037 | if (!ring) |
994 | goto err_destroy_tx5; | 1038 | goto err_destroy_tx5; |
995 | dma->rx_ring0 = ring; | 1039 | dma->rx_ring0 = ring; |
996 | 1040 | ||
997 | if (dev->dev->id.revision < 5) { | 1041 | if (dev->dev->id.revision < 5) { |
998 | ring = b43_setup_dmaring(dev, 3, 0, dma64); | 1042 | ring = b43_setup_dmaring(dev, 3, 0, type); |
999 | if (!ring) | 1043 | if (!ring) |
1000 | goto err_destroy_rx0; | 1044 | goto err_destroy_rx0; |
1001 | dma->rx_ring3 = ring; | 1045 | dma->rx_ring3 = ring; |
1002 | } | 1046 | } |
1003 | 1047 | ||
1004 | b43dbg(dev->wl, "%d-bit DMA initialized\n", | 1048 | b43dbg(dev->wl, "%u-bit DMA initialized\n", |
1005 | (dmamask == DMA_64BIT_MASK) ? 64 : | 1049 | (unsigned int)type); |
1006 | (dmamask == DMA_32BIT_MASK) ? 32 : 30); | ||
1007 | err = 0; | 1050 | err = 0; |
1008 | out: | 1051 | out: |
1009 | return err; | 1052 | return err; |
@@ -1146,7 +1189,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1146 | 1189 | ||
1147 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, | 1190 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, |
1148 | hdrsize, 1); | 1191 | hdrsize, 1); |
1149 | if (dma_mapping_error(meta_hdr->dmaaddr)) { | 1192 | if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize)) { |
1150 | ring->current_slot = old_top_slot; | 1193 | ring->current_slot = old_top_slot; |
1151 | ring->used_slots = old_used_slots; | 1194 | ring->used_slots = old_used_slots; |
1152 | return -EIO; | 1195 | return -EIO; |
@@ -1165,7 +1208,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1165 | 1208 | ||
1166 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1209 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1167 | /* create a bounce buffer in zone_dma on mapping failure. */ | 1210 | /* create a bounce buffer in zone_dma on mapping failure. */ |
1168 | if (dma_mapping_error(meta->dmaaddr)) { | 1211 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { |
1169 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); | 1212 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); |
1170 | if (!bounce_skb) { | 1213 | if (!bounce_skb) { |
1171 | ring->current_slot = old_top_slot; | 1214 | ring->current_slot = old_top_slot; |
@@ -1179,7 +1222,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1179 | skb = bounce_skb; | 1222 | skb = bounce_skb; |
1180 | meta->skb = skb; | 1223 | meta->skb = skb; |
1181 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1224 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1182 | if (dma_mapping_error(meta->dmaaddr)) { | 1225 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { |
1183 | ring->current_slot = old_top_slot; | 1226 | ring->current_slot = old_top_slot; |
1184 | ring->used_slots = old_used_slots; | 1227 | ring->used_slots = old_used_slots; |
1185 | err = -EIO; | 1228 | err = -EIO; |
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 58db03ac536e..c0d6b69e6501 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
@@ -203,6 +203,12 @@ struct b43_dma_ops { | |||
203 | void (*set_current_rxslot) (struct b43_dmaring * ring, int slot); | 203 | void (*set_current_rxslot) (struct b43_dmaring * ring, int slot); |
204 | }; | 204 | }; |
205 | 205 | ||
206 | enum b43_dmatype { | ||
207 | B43_DMA_30BIT = 30, | ||
208 | B43_DMA_32BIT = 32, | ||
209 | B43_DMA_64BIT = 64, | ||
210 | }; | ||
211 | |||
206 | struct b43_dmaring { | 212 | struct b43_dmaring { |
207 | /* Lowlevel DMA ops. */ | 213 | /* Lowlevel DMA ops. */ |
208 | const struct b43_dma_ops *ops; | 214 | const struct b43_dma_ops *ops; |
@@ -235,8 +241,8 @@ struct b43_dmaring { | |||
235 | int index; | 241 | int index; |
236 | /* Boolean. Is this a TX ring? */ | 242 | /* Boolean. Is this a TX ring? */ |
237 | bool tx; | 243 | bool tx; |
238 | /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ | 244 | /* The type of DMA engine used. */ |
239 | bool dma64; | 245 | enum b43_dmatype type; |
240 | /* Boolean. Is this ring stopped at ieee80211 level? */ | 246 | /* Boolean. Is this ring stopped at ieee80211 level? */ |
241 | bool stopped; | 247 | bool stopped; |
242 | /* Lock, only used for TX. */ | 248 | /* Lock, only used for TX. */ |
@@ -255,8 +261,7 @@ static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) | |||
255 | return b43_read32(ring->dev, ring->mmio_base + offset); | 261 | return b43_read32(ring->dev, ring->mmio_base + offset); |
256 | } | 262 | } |
257 | 263 | ||
258 | static inline | 264 | static inline void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value) |
259 | void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value) | ||
260 | { | 265 | { |
261 | b43_write32(ring->dev, ring->mmio_base + offset, value); | 266 | b43_write32(ring->dev, ring->mmio_base + offset, value); |
262 | } | 267 | } |
@@ -264,13 +269,6 @@ static inline | |||
264 | int b43_dma_init(struct b43_wldev *dev); | 269 | int b43_dma_init(struct b43_wldev *dev); |
265 | void b43_dma_free(struct b43_wldev *dev); | 270 | void b43_dma_free(struct b43_wldev *dev); |
266 | 271 | ||
267 | int b43_dmacontroller_rx_reset(struct b43_wldev *dev, | ||
268 | u16 dmacontroller_mmio_base, int dma64); | ||
269 | int b43_dmacontroller_tx_reset(struct b43_wldev *dev, | ||
270 | u16 dmacontroller_mmio_base, int dma64); | ||
271 | |||
272 | u16 b43_dmacontroller_base(int dma64bit, int dmacontroller_idx); | ||
273 | |||
274 | void b43_dma_tx_suspend(struct b43_wldev *dev); | 272 | void b43_dma_tx_suspend(struct b43_wldev *dev); |
275 | void b43_dma_tx_resume(struct b43_wldev *dev); | 273 | void b43_dma_tx_resume(struct b43_wldev *dev); |
276 | 274 | ||
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 83161d9af813..6e08405e8026 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -1164,7 +1164,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1164 | { | 1164 | { |
1165 | const struct b43legacy_dma_ops *ops = ring->ops; | 1165 | const struct b43legacy_dma_ops *ops = ring->ops; |
1166 | u8 *header; | 1166 | u8 *header; |
1167 | int slot; | 1167 | int slot, old_top_slot, old_used_slots; |
1168 | int err; | 1168 | int err; |
1169 | struct b43legacy_dmadesc_generic *desc; | 1169 | struct b43legacy_dmadesc_generic *desc; |
1170 | struct b43legacy_dmadesc_meta *meta; | 1170 | struct b43legacy_dmadesc_meta *meta; |
@@ -1174,6 +1174,9 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1174 | #define SLOTS_PER_PACKET 2 | 1174 | #define SLOTS_PER_PACKET 2 |
1175 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); | 1175 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); |
1176 | 1176 | ||
1177 | old_top_slot = ring->current_slot; | ||
1178 | old_used_slots = ring->used_slots; | ||
1179 | |||
1177 | /* Get a slot for the header. */ | 1180 | /* Get a slot for the header. */ |
1178 | slot = request_slot(ring); | 1181 | slot = request_slot(ring); |
1179 | desc = ops->idx2desc(ring, slot, &meta_hdr); | 1182 | desc = ops->idx2desc(ring, slot, &meta_hdr); |
@@ -1181,9 +1184,14 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1181 | 1184 | ||
1182 | header = &(ring->txhdr_cache[slot * sizeof( | 1185 | header = &(ring->txhdr_cache[slot * sizeof( |
1183 | struct b43legacy_txhdr_fw3)]); | 1186 | struct b43legacy_txhdr_fw3)]); |
1184 | b43legacy_generate_txhdr(ring->dev, header, | 1187 | err = b43legacy_generate_txhdr(ring->dev, header, |
1185 | skb->data, skb->len, ctl, | 1188 | skb->data, skb->len, ctl, |
1186 | generate_cookie(ring, slot)); | 1189 | generate_cookie(ring, slot)); |
1190 | if (unlikely(err)) { | ||
1191 | ring->current_slot = old_top_slot; | ||
1192 | ring->used_slots = old_used_slots; | ||
1193 | return err; | ||
1194 | } | ||
1187 | 1195 | ||
1188 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, | 1196 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, |
1189 | sizeof(struct b43legacy_txhdr_fw3), 1); | 1197 | sizeof(struct b43legacy_txhdr_fw3), 1); |
@@ -1206,6 +1214,8 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1206 | if (dma_mapping_error(meta->dmaaddr)) { | 1214 | if (dma_mapping_error(meta->dmaaddr)) { |
1207 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); | 1215 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); |
1208 | if (!bounce_skb) { | 1216 | if (!bounce_skb) { |
1217 | ring->current_slot = old_top_slot; | ||
1218 | ring->used_slots = old_used_slots; | ||
1209 | err = -ENOMEM; | 1219 | err = -ENOMEM; |
1210 | goto out_unmap_hdr; | 1220 | goto out_unmap_hdr; |
1211 | } | 1221 | } |
@@ -1216,6 +1226,8 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1216 | meta->skb = skb; | 1226 | meta->skb = skb; |
1217 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1227 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1218 | if (dma_mapping_error(meta->dmaaddr)) { | 1228 | if (dma_mapping_error(meta->dmaaddr)) { |
1229 | ring->current_slot = old_top_slot; | ||
1230 | ring->used_slots = old_used_slots; | ||
1219 | err = -EIO; | 1231 | err = -EIO; |
1220 | goto out_free_bounce; | 1232 | goto out_free_bounce; |
1221 | } | 1233 | } |
@@ -1282,6 +1294,13 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
1282 | B43legacy_BUG_ON(ring->stopped); | 1294 | B43legacy_BUG_ON(ring->stopped); |
1283 | 1295 | ||
1284 | err = dma_tx_fragment(ring, skb, ctl); | 1296 | err = dma_tx_fragment(ring, skb, ctl); |
1297 | if (unlikely(err == -ENOKEY)) { | ||
1298 | /* Drop this packet, as we don't have the encryption key | ||
1299 | * anymore and must not transmit it unencrypted. */ | ||
1300 | dev_kfree_skb_any(skb); | ||
1301 | err = 0; | ||
1302 | goto out_unlock; | ||
1303 | } | ||
1285 | if (unlikely(err)) { | 1304 | if (unlikely(err)) { |
1286 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); | 1305 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); |
1287 | goto out_unlock; | 1306 | goto out_unlock; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index aa20d5d56e2f..53f7f2e97615 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3160,8 +3160,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) | |||
3160 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); | 3160 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); |
3161 | 3161 | ||
3162 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ | 3162 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ |
3163 | memset(wl->bssid, 0, ETH_ALEN); | ||
3164 | memset(wl->mac_addr, 0, ETH_ALEN); | ||
3165 | b43legacy_upload_card_macaddress(dev); | 3163 | b43legacy_upload_card_macaddress(dev); |
3166 | b43legacy_security_init(dev); | 3164 | b43legacy_security_init(dev); |
3167 | b43legacy_rng_init(wl); | 3165 | b43legacy_rng_init(wl); |
@@ -3263,6 +3261,13 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) | |||
3263 | * LEDs that are registered later depend on it. */ | 3261 | * LEDs that are registered later depend on it. */ |
3264 | b43legacy_rfkill_init(dev); | 3262 | b43legacy_rfkill_init(dev); |
3265 | 3263 | ||
3264 | /* Kill all old instance specific information to make sure | ||
3265 | * the card won't use it in the short timeframe between start | ||
3266 | * and mac80211 reconfiguring it. */ | ||
3267 | memset(wl->bssid, 0, ETH_ALEN); | ||
3268 | memset(wl->mac_addr, 0, ETH_ALEN); | ||
3269 | wl->filter_flags = 0; | ||
3270 | |||
3266 | mutex_lock(&wl->mutex); | 3271 | mutex_lock(&wl->mutex); |
3267 | 3272 | ||
3268 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { | 3273 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { |
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index e4f4c5c39e33..bcdd54eb2edb 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c | |||
@@ -181,7 +181,7 @@ union txhdr_union { | |||
181 | struct b43legacy_txhdr_fw3 txhdr_fw3; | 181 | struct b43legacy_txhdr_fw3 txhdr_fw3; |
182 | }; | 182 | }; |
183 | 183 | ||
184 | static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue, | 184 | static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue, |
185 | struct sk_buff *skb, | 185 | struct sk_buff *skb, |
186 | struct b43legacy_pio_txpacket *packet, | 186 | struct b43legacy_pio_txpacket *packet, |
187 | size_t txhdr_size) | 187 | size_t txhdr_size) |
@@ -189,14 +189,17 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue, | |||
189 | union txhdr_union txhdr_data; | 189 | union txhdr_union txhdr_data; |
190 | u8 *txhdr = NULL; | 190 | u8 *txhdr = NULL; |
191 | unsigned int octets; | 191 | unsigned int octets; |
192 | int err; | ||
192 | 193 | ||
193 | txhdr = (u8 *)(&txhdr_data.txhdr_fw3); | 194 | txhdr = (u8 *)(&txhdr_data.txhdr_fw3); |
194 | 195 | ||
195 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); | 196 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); |
196 | b43legacy_generate_txhdr(queue->dev, | 197 | err = b43legacy_generate_txhdr(queue->dev, |
197 | txhdr, skb->data, skb->len, | 198 | txhdr, skb->data, skb->len, |
198 | &packet->txstat.control, | 199 | &packet->txstat.control, |
199 | generate_cookie(queue, packet)); | 200 | generate_cookie(queue, packet)); |
201 | if (err) | ||
202 | return err; | ||
200 | 203 | ||
201 | tx_start(queue); | 204 | tx_start(queue); |
202 | octets = skb->len + txhdr_size; | 205 | octets = skb->len + txhdr_size; |
@@ -204,6 +207,8 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue, | |||
204 | octets--; | 207 | octets--; |
205 | tx_data(queue, txhdr, (u8 *)skb->data, octets); | 208 | tx_data(queue, txhdr, (u8 *)skb->data, octets); |
206 | tx_complete(queue, skb); | 209 | tx_complete(queue, skb); |
210 | |||
211 | return 0; | ||
207 | } | 212 | } |
208 | 213 | ||
209 | static void free_txpacket(struct b43legacy_pio_txpacket *packet, | 214 | static void free_txpacket(struct b43legacy_pio_txpacket *packet, |
@@ -226,6 +231,7 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet) | |||
226 | struct b43legacy_pioqueue *queue = packet->queue; | 231 | struct b43legacy_pioqueue *queue = packet->queue; |
227 | struct sk_buff *skb = packet->skb; | 232 | struct sk_buff *skb = packet->skb; |
228 | u16 octets; | 233 | u16 octets; |
234 | int err; | ||
229 | 235 | ||
230 | octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3); | 236 | octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3); |
231 | if (queue->tx_devq_size < octets) { | 237 | if (queue->tx_devq_size < octets) { |
@@ -247,8 +253,14 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet) | |||
247 | if (queue->tx_devq_used + octets > queue->tx_devq_size) | 253 | if (queue->tx_devq_used + octets > queue->tx_devq_size) |
248 | return -EBUSY; | 254 | return -EBUSY; |
249 | /* Now poke the device. */ | 255 | /* Now poke the device. */ |
250 | pio_tx_write_fragment(queue, skb, packet, | 256 | err = pio_tx_write_fragment(queue, skb, packet, |
251 | sizeof(struct b43legacy_txhdr_fw3)); | 257 | sizeof(struct b43legacy_txhdr_fw3)); |
258 | if (unlikely(err == -ENOKEY)) { | ||
259 | /* Drop this packet, as we don't have the encryption key | ||
260 | * anymore and must not transmit it unencrypted. */ | ||
261 | free_txpacket(packet, 1); | ||
262 | return 0; | ||
263 | } | ||
252 | 264 | ||
253 | /* Account for the packet size. | 265 | /* Account for the packet size. |
254 | * (We must not overflow the device TX queue) | 266 | * (We must not overflow the device TX queue) |
@@ -486,6 +498,9 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, | |||
486 | queue = parse_cookie(dev, status->cookie, &packet); | 498 | queue = parse_cookie(dev, status->cookie, &packet); |
487 | B43legacy_WARN_ON(!queue); | 499 | B43legacy_WARN_ON(!queue); |
488 | 500 | ||
501 | if (!packet->skb) | ||
502 | return; | ||
503 | |||
489 | queue->tx_devq_packets--; | 504 | queue->tx_devq_packets--; |
490 | queue->tx_devq_used -= (packet->skb->len + | 505 | queue->tx_devq_used -= (packet->skb->len + |
491 | sizeof(struct b43legacy_txhdr_fw3)); | 506 | sizeof(struct b43legacy_txhdr_fw3)); |
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index e20c552442d5..d84408a82db9 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
@@ -181,7 +181,7 @@ static u8 b43legacy_calc_fallback_rate(u8 bitrate) | |||
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
184 | static void generate_txhdr_fw3(struct b43legacy_wldev *dev, | 184 | static int generate_txhdr_fw3(struct b43legacy_wldev *dev, |
185 | struct b43legacy_txhdr_fw3 *txhdr, | 185 | struct b43legacy_txhdr_fw3 *txhdr, |
186 | const unsigned char *fragment_data, | 186 | const unsigned char *fragment_data, |
187 | unsigned int fragment_len, | 187 | unsigned int fragment_len, |
@@ -252,6 +252,13 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
252 | iv_len = min((size_t)txctl->iv_len, | 252 | iv_len = min((size_t)txctl->iv_len, |
253 | ARRAY_SIZE(txhdr->iv)); | 253 | ARRAY_SIZE(txhdr->iv)); |
254 | memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); | 254 | memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); |
255 | } else { | ||
256 | /* This key is invalid. This might only happen | ||
257 | * in a short timeframe after machine resume before | ||
258 | * we were able to reconfigure keys. | ||
259 | * Drop this packet completely. Do not transmit it | ||
260 | * unencrypted to avoid leaking information. */ | ||
261 | return -ENOKEY; | ||
255 | } | 262 | } |
256 | } | 263 | } |
257 | b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) | 264 | b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) |
@@ -345,16 +352,18 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
345 | /* Apply the bitfields */ | 352 | /* Apply the bitfields */ |
346 | txhdr->mac_ctl = cpu_to_le32(mac_ctl); | 353 | txhdr->mac_ctl = cpu_to_le32(mac_ctl); |
347 | txhdr->phy_ctl = cpu_to_le16(phy_ctl); | 354 | txhdr->phy_ctl = cpu_to_le16(phy_ctl); |
355 | |||
356 | return 0; | ||
348 | } | 357 | } |
349 | 358 | ||
350 | void b43legacy_generate_txhdr(struct b43legacy_wldev *dev, | 359 | int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, |
351 | u8 *txhdr, | 360 | u8 *txhdr, |
352 | const unsigned char *fragment_data, | 361 | const unsigned char *fragment_data, |
353 | unsigned int fragment_len, | 362 | unsigned int fragment_len, |
354 | const struct ieee80211_tx_control *txctl, | 363 | const struct ieee80211_tx_control *txctl, |
355 | u16 cookie) | 364 | u16 cookie) |
356 | { | 365 | { |
357 | generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, | 366 | return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, |
358 | fragment_data, fragment_len, | 367 | fragment_data, fragment_len, |
359 | txctl, cookie); | 368 | txctl, cookie); |
360 | } | 369 | } |
diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h index 8a155d0a5d1f..bab47928a0c9 100644 --- a/drivers/net/wireless/b43legacy/xmit.h +++ b/drivers/net/wireless/b43legacy/xmit.h | |||
@@ -76,7 +76,7 @@ struct b43legacy_txhdr_fw3 { | |||
76 | 76 | ||
77 | 77 | ||
78 | 78 | ||
79 | void b43legacy_generate_txhdr(struct b43legacy_wldev *dev, | 79 | int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, |
80 | u8 *txhdr, | 80 | u8 *txhdr, |
81 | const unsigned char *fragment_data, | 81 | const unsigned char *fragment_data, |
82 | unsigned int fragment_len, | 82 | unsigned int fragment_len, |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f55c75712b55..5ee1ad69898b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -4207,13 +4207,13 @@ static u8 ratio2dB[100] = { | |||
4207 | * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ | 4207 | * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ |
4208 | int iwl3945_calc_db_from_ratio(int sig_ratio) | 4208 | int iwl3945_calc_db_from_ratio(int sig_ratio) |
4209 | { | 4209 | { |
4210 | /* Anything above 1000:1 just report as 60 dB */ | 4210 | /* 1000:1 or higher just report as 60 dB */ |
4211 | if (sig_ratio > 1000) | 4211 | if (sig_ratio >= 1000) |
4212 | return 60; | 4212 | return 60; |
4213 | 4213 | ||
4214 | /* Above 100:1, divide by 10 and use table, | 4214 | /* 100:1 or higher, divide by 10 and use table, |
4215 | * add 20 dB to make up for divide by 10 */ | 4215 | * add 20 dB to make up for divide by 10 */ |
4216 | if (sig_ratio > 100) | 4216 | if (sig_ratio >= 100) |
4217 | return (20 + (int)ratio2dB[sig_ratio/10]); | 4217 | return (20 + (int)ratio2dB[sig_ratio/10]); |
4218 | 4218 | ||
4219 | /* We shouldn't see this */ | 4219 | /* We shouldn't see this */ |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index e9743d3efaf6..238628d3a854 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -1540,6 +1540,38 @@ static void __devinit detect_and_report_smsc (void) | |||
1540 | smsc_check(0x3f0,0x44); | 1540 | smsc_check(0x3f0,0x44); |
1541 | smsc_check(0x370,0x44); | 1541 | smsc_check(0x370,0x44); |
1542 | } | 1542 | } |
1543 | |||
1544 | static void __devinit detect_and_report_it87(void) | ||
1545 | { | ||
1546 | u16 dev; | ||
1547 | u8 r; | ||
1548 | if (verbose_probing) | ||
1549 | printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n"); | ||
1550 | if (!request_region(0x2e, 1, __FUNCTION__)) | ||
1551 | return; | ||
1552 | outb(0x87, 0x2e); | ||
1553 | outb(0x01, 0x2e); | ||
1554 | outb(0x55, 0x2e); | ||
1555 | outb(0x55, 0x2e); | ||
1556 | outb(0x20, 0x2e); | ||
1557 | dev = inb(0x2f) << 8; | ||
1558 | outb(0x21, 0x2e); | ||
1559 | dev |= inb(0x2f); | ||
1560 | if (dev == 0x8712 || dev == 0x8705 || dev == 0x8715 || | ||
1561 | dev == 0x8716 || dev == 0x8718 || dev == 0x8726) { | ||
1562 | printk(KERN_INFO "IT%04X SuperIO detected.\n", dev); | ||
1563 | outb(0x07, 0x2E); /* Parallel Port */ | ||
1564 | outb(0x03, 0x2F); | ||
1565 | outb(0xF0, 0x2E); /* BOOT 0x80 off */ | ||
1566 | r = inb(0x2f); | ||
1567 | outb(0xF0, 0x2E); | ||
1568 | outb(r | 8, 0x2F); | ||
1569 | outb(0x02, 0x2E); /* Lock */ | ||
1570 | outb(0x02, 0x2F); | ||
1571 | |||
1572 | release_region(0x2e, 1); | ||
1573 | } | ||
1574 | } | ||
1543 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ | 1575 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ |
1544 | 1576 | ||
1545 | static int get_superio_dma (struct parport *p) | 1577 | static int get_superio_dma (struct parport *p) |
@@ -2767,6 +2799,7 @@ enum parport_pc_pci_cards { | |||
2767 | netmos_9755, | 2799 | netmos_9755, |
2768 | netmos_9805, | 2800 | netmos_9805, |
2769 | netmos_9815, | 2801 | netmos_9815, |
2802 | quatech_sppxp100, | ||
2770 | }; | 2803 | }; |
2771 | 2804 | ||
2772 | 2805 | ||
@@ -2843,6 +2876,7 @@ static struct parport_pc_pci { | |||
2843 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ | 2876 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ |
2844 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ | 2877 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ |
2845 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ | 2878 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ |
2879 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, | ||
2846 | }; | 2880 | }; |
2847 | 2881 | ||
2848 | static const struct pci_device_id parport_pc_pci_tbl[] = { | 2882 | static const struct pci_device_id parport_pc_pci_tbl[] = { |
@@ -2926,6 +2960,9 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
2926 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, | 2960 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, |
2927 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, | 2961 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, |
2928 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, | 2962 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, |
2963 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ | ||
2964 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, | ||
2965 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, | ||
2929 | { 0, } /* terminate list */ | 2966 | { 0, } /* terminate list */ |
2930 | }; | 2967 | }; |
2931 | MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); | 2968 | MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); |
@@ -3159,24 +3196,25 @@ static void __init parport_pc_find_ports (int autoirq, int autodma) | |||
3159 | int count = 0, err; | 3196 | int count = 0, err; |
3160 | 3197 | ||
3161 | #ifdef CONFIG_PARPORT_PC_SUPERIO | 3198 | #ifdef CONFIG_PARPORT_PC_SUPERIO |
3162 | detect_and_report_winbond (); | 3199 | detect_and_report_it87(); |
3163 | detect_and_report_smsc (); | 3200 | detect_and_report_winbond(); |
3201 | detect_and_report_smsc(); | ||
3164 | #endif | 3202 | #endif |
3165 | 3203 | ||
3166 | /* Onboard SuperIO chipsets that show themselves on the PCI bus. */ | 3204 | /* Onboard SuperIO chipsets that show themselves on the PCI bus. */ |
3167 | count += parport_pc_init_superio (autoirq, autodma); | 3205 | count += parport_pc_init_superio(autoirq, autodma); |
3168 | 3206 | ||
3169 | /* PnP ports, skip detection if SuperIO already found them */ | 3207 | /* PnP ports, skip detection if SuperIO already found them */ |
3170 | if (!count) { | 3208 | if (!count) { |
3171 | err = pnp_register_driver (&parport_pc_pnp_driver); | 3209 | err = pnp_register_driver(&parport_pc_pnp_driver); |
3172 | if (!err) | 3210 | if (!err) |
3173 | pnp_registered_parport = 1; | 3211 | pnp_registered_parport = 1; |
3174 | } | 3212 | } |
3175 | 3213 | ||
3176 | /* ISA ports and whatever (see asm/parport.h). */ | 3214 | /* ISA ports and whatever (see asm/parport.h). */ |
3177 | parport_pc_find_nonpci_ports (autoirq, autodma); | 3215 | parport_pc_find_nonpci_ports(autoirq, autodma); |
3178 | 3216 | ||
3179 | err = pci_register_driver (&parport_pc_pci_driver); | 3217 | err = pci_register_driver(&parport_pc_pci_driver); |
3180 | if (!err) | 3218 | if (!err) |
3181 | pci_registered_parport = 1; | 3219 | pci_registered_parport = 1; |
3182 | } | 3220 | } |
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index bd6ad8b38168..e2e95b36a603 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c | |||
@@ -77,7 +77,7 @@ static struct parport_pc_pci cards[] __devinitdata = { | |||
77 | /* titan_110l */ { 1, { { 3, -1 }, } }, | 77 | /* titan_110l */ { 1, { { 3, -1 }, } }, |
78 | /* titan_210l */ { 1, { { 3, -1 }, } }, | 78 | /* titan_210l */ { 1, { { 3, -1 }, } }, |
79 | /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, | 79 | /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, |
80 | /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init }, | 80 | /* netmos_9855 */ { 1, { { 2, -1 }, }, netmos_parallel_init }, |
81 | /* avlab_1s1p */ { 1, { { 1, 2}, } }, | 81 | /* avlab_1s1p */ { 1, { { 1, 2}, } }, |
82 | /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} }, | 82 | /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} }, |
83 | /* avlab_2s1p */ { 1, { { 2, 3}, } }, | 83 | /* avlab_2s1p */ { 1, { { 2, 3}, } }, |
@@ -185,7 +185,7 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = { | |||
185 | .uart_offset = 8, | 185 | .uart_offset = 8, |
186 | }, | 186 | }, |
187 | [netmos_9855] = { | 187 | [netmos_9855] = { |
188 | .flags = FL_BASE2 | FL_BASE_BARS, | 188 | .flags = FL_BASE4 | FL_BASE_BARS, |
189 | .num_ports = 1, | 189 | .num_ports = 1, |
190 | .base_baud = 115200, | 190 | .base_baud = 115200, |
191 | .uart_offset = 8, | 191 | .uart_offset = 8, |
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 91b2dc956be5..8ed26480371f 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/dmar.h> | 27 | #include <linux/dmar.h> |
28 | #include "iova.h" | 28 | #include "iova.h" |
29 | #include "intel-iommu.h" | ||
29 | 30 | ||
30 | #undef PREFIX | 31 | #undef PREFIX |
31 | #define PREFIX "DMAR:" | 32 | #define PREFIX "DMAR:" |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4e01df99681a..31fa6c92aa5e 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1088,7 +1088,7 @@ static void dmar_init_reserved_ranges(void) | |||
1088 | int i; | 1088 | int i; |
1089 | u64 addr, size; | 1089 | u64 addr, size; |
1090 | 1090 | ||
1091 | init_iova_domain(&reserved_iova_list); | 1091 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); |
1092 | 1092 | ||
1093 | /* IOAPIC ranges shouldn't be accessed by DMA */ | 1093 | /* IOAPIC ranges shouldn't be accessed by DMA */ |
1094 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START), | 1094 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START), |
@@ -1142,7 +1142,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
1142 | int adjust_width, agaw; | 1142 | int adjust_width, agaw; |
1143 | unsigned long sagaw; | 1143 | unsigned long sagaw; |
1144 | 1144 | ||
1145 | init_iova_domain(&domain->iovad); | 1145 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
1146 | spin_lock_init(&domain->mapping_lock); | 1146 | spin_lock_init(&domain->mapping_lock); |
1147 | 1147 | ||
1148 | domain_reserve_special_ranges(domain); | 1148 | domain_reserve_special_ranges(domain); |
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 459ad1f9dc54..0e4862675ad2 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h | |||
@@ -23,10 +23,24 @@ | |||
23 | 23 | ||
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/msi.h> | 25 | #include <linux/msi.h> |
26 | #include <linux/sysdev.h> | ||
26 | #include "iova.h" | 27 | #include "iova.h" |
27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
28 | 29 | ||
29 | /* | 30 | /* |
31 | * We need a fixed PAGE_SIZE of 4K irrespective of | ||
32 | * arch PAGE_SIZE for IOMMU page tables. | ||
33 | */ | ||
34 | #define PAGE_SHIFT_4K (12) | ||
35 | #define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) | ||
36 | #define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) | ||
37 | #define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K) | ||
38 | |||
39 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K) | ||
40 | #define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK) | ||
41 | #define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK) | ||
42 | |||
43 | /* | ||
30 | * Intel IOMMU register specification per version 1.0 public spec. | 44 | * Intel IOMMU register specification per version 1.0 public spec. |
31 | */ | 45 | */ |
32 | 46 | ||
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c index a84571c29360..8de7ab6c6d0c 100644 --- a/drivers/pci/iova.c +++ b/drivers/pci/iova.c | |||
@@ -9,19 +9,19 @@ | |||
9 | #include "iova.h" | 9 | #include "iova.h" |
10 | 10 | ||
11 | void | 11 | void |
12 | init_iova_domain(struct iova_domain *iovad) | 12 | init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit) |
13 | { | 13 | { |
14 | spin_lock_init(&iovad->iova_alloc_lock); | 14 | spin_lock_init(&iovad->iova_alloc_lock); |
15 | spin_lock_init(&iovad->iova_rbtree_lock); | 15 | spin_lock_init(&iovad->iova_rbtree_lock); |
16 | iovad->rbroot = RB_ROOT; | 16 | iovad->rbroot = RB_ROOT; |
17 | iovad->cached32_node = NULL; | 17 | iovad->cached32_node = NULL; |
18 | 18 | iovad->dma_32bit_pfn = pfn_32bit; | |
19 | } | 19 | } |
20 | 20 | ||
21 | static struct rb_node * | 21 | static struct rb_node * |
22 | __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn) | 22 | __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn) |
23 | { | 23 | { |
24 | if ((*limit_pfn != DMA_32BIT_PFN) || | 24 | if ((*limit_pfn != iovad->dma_32bit_pfn) || |
25 | (iovad->cached32_node == NULL)) | 25 | (iovad->cached32_node == NULL)) |
26 | return rb_last(&iovad->rbroot); | 26 | return rb_last(&iovad->rbroot); |
27 | else { | 27 | else { |
@@ -37,7 +37,7 @@ static void | |||
37 | __cached_rbnode_insert_update(struct iova_domain *iovad, | 37 | __cached_rbnode_insert_update(struct iova_domain *iovad, |
38 | unsigned long limit_pfn, struct iova *new) | 38 | unsigned long limit_pfn, struct iova *new) |
39 | { | 39 | { |
40 | if (limit_pfn != DMA_32BIT_PFN) | 40 | if (limit_pfn != iovad->dma_32bit_pfn) |
41 | return; | 41 | return; |
42 | iovad->cached32_node = &new->node; | 42 | iovad->cached32_node = &new->node; |
43 | } | 43 | } |
diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h index ae3028d5a941..d521b5b7319c 100644 --- a/drivers/pci/iova.h +++ b/drivers/pci/iova.h | |||
@@ -15,22 +15,9 @@ | |||
15 | #include <linux/rbtree.h> | 15 | #include <linux/rbtree.h> |
16 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
17 | 17 | ||
18 | /* | ||
19 | * We need a fixed PAGE_SIZE of 4K irrespective of | ||
20 | * arch PAGE_SIZE for IOMMU page tables. | ||
21 | */ | ||
22 | #define PAGE_SHIFT_4K (12) | ||
23 | #define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) | ||
24 | #define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) | ||
25 | #define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K) | ||
26 | |||
27 | /* IO virtual address start page frame number */ | 18 | /* IO virtual address start page frame number */ |
28 | #define IOVA_START_PFN (1) | 19 | #define IOVA_START_PFN (1) |
29 | 20 | ||
30 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K) | ||
31 | #define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK) | ||
32 | #define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK) | ||
33 | |||
34 | /* iova structure */ | 21 | /* iova structure */ |
35 | struct iova { | 22 | struct iova { |
36 | struct rb_node node; | 23 | struct rb_node node; |
@@ -44,6 +31,7 @@ struct iova_domain { | |||
44 | spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */ | 31 | spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */ |
45 | struct rb_root rbroot; /* iova domain rbtree root */ | 32 | struct rb_root rbroot; /* iova domain rbtree root */ |
46 | struct rb_node *cached32_node; /* Save last alloced node */ | 33 | struct rb_node *cached32_node; /* Save last alloced node */ |
34 | unsigned long dma_32bit_pfn; | ||
47 | }; | 35 | }; |
48 | 36 | ||
49 | struct iova *alloc_iova_mem(void); | 37 | struct iova *alloc_iova_mem(void); |
@@ -56,7 +44,7 @@ struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size, | |||
56 | struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo, | 44 | struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo, |
57 | unsigned long pfn_hi); | 45 | unsigned long pfn_hi); |
58 | void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to); | 46 | void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to); |
59 | void init_iova_domain(struct iova_domain *iovad); | 47 | void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit); |
60 | struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn); | 48 | struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn); |
61 | void put_iova_domain(struct iova_domain *iovad); | 49 | void put_iova_domain(struct iova_domain *iovad); |
62 | 50 | ||
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index a262762c5b88..12a1645a2e43 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
@@ -161,8 +161,7 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state) | |||
161 | return error; | 161 | return error; |
162 | } | 162 | } |
163 | 163 | ||
164 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) && | 164 | if (pnp_can_disable(pnp_dev)) { |
165 | pnp_can_disable(pnp_dev)) { | ||
166 | error = pnp_stop_dev(pnp_dev); | 165 | error = pnp_stop_dev(pnp_dev); |
167 | if (error) | 166 | if (error) |
168 | return error; | 167 | return error; |
@@ -185,14 +184,17 @@ static int pnp_bus_resume(struct device *dev) | |||
185 | if (pnp_dev->protocol && pnp_dev->protocol->resume) | 184 | if (pnp_dev->protocol && pnp_dev->protocol->resume) |
186 | pnp_dev->protocol->resume(pnp_dev); | 185 | pnp_dev->protocol->resume(pnp_dev); |
187 | 186 | ||
188 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { | 187 | if (pnp_can_write(pnp_dev)) { |
189 | error = pnp_start_dev(pnp_dev); | 188 | error = pnp_start_dev(pnp_dev); |
190 | if (error) | 189 | if (error) |
191 | return error; | 190 | return error; |
192 | } | 191 | } |
193 | 192 | ||
194 | if (pnp_drv->resume) | 193 | if (pnp_drv->resume) { |
195 | return pnp_drv->resume(pnp_dev); | 194 | error = pnp_drv->resume(pnp_dev); |
195 | if (error) | ||
196 | return error; | ||
197 | } | ||
196 | 198 | ||
197 | return 0; | 199 | return 0; |
198 | } | 200 | } |
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 31548044fdde..982658477a58 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c | |||
@@ -10,9 +10,12 @@ | |||
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/pnp.h> | ||
13 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
14 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/mutex.h> | ||
18 | |||
16 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
17 | 20 | ||
18 | #include "base.h" | 21 | #include "base.h" |
@@ -315,8 +318,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, | |||
315 | return ret; | 318 | return ret; |
316 | } | 319 | } |
317 | 320 | ||
318 | extern struct semaphore pnp_res_mutex; | ||
319 | |||
320 | static ssize_t | 321 | static ssize_t |
321 | pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | 322 | pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, |
322 | const char *ubuf, size_t count) | 323 | const char *ubuf, size_t count) |
@@ -361,10 +362,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
361 | goto done; | 362 | goto done; |
362 | } | 363 | } |
363 | if (!strnicmp(buf, "get", 3)) { | 364 | if (!strnicmp(buf, "get", 3)) { |
364 | down(&pnp_res_mutex); | 365 | mutex_lock(&pnp_res_mutex); |
365 | if (pnp_can_read(dev)) | 366 | if (pnp_can_read(dev)) |
366 | dev->protocol->get(dev, &dev->res); | 367 | dev->protocol->get(dev, &dev->res); |
367 | up(&pnp_res_mutex); | 368 | mutex_unlock(&pnp_res_mutex); |
368 | goto done; | 369 | goto done; |
369 | } | 370 | } |
370 | if (!strnicmp(buf, "set", 3)) { | 371 | if (!strnicmp(buf, "set", 3)) { |
@@ -373,7 +374,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
373 | goto done; | 374 | goto done; |
374 | buf += 3; | 375 | buf += 3; |
375 | pnp_init_resource_table(&dev->res); | 376 | pnp_init_resource_table(&dev->res); |
376 | down(&pnp_res_mutex); | 377 | mutex_lock(&pnp_res_mutex); |
377 | while (1) { | 378 | while (1) { |
378 | while (isspace(*buf)) | 379 | while (isspace(*buf)) |
379 | ++buf; | 380 | ++buf; |
@@ -455,7 +456,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
455 | } | 456 | } |
456 | break; | 457 | break; |
457 | } | 458 | } |
458 | up(&pnp_res_mutex); | 459 | mutex_unlock(&pnp_res_mutex); |
459 | goto done; | 460 | goto done; |
460 | } | 461 | } |
461 | 462 | ||
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index c6b3d4e63ccc..c28caf272c11 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
@@ -12,9 +12,10 @@ | |||
12 | #include <linux/pnp.h> | 12 | #include <linux/pnp.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/bitmap.h> | 14 | #include <linux/bitmap.h> |
15 | #include <linux/mutex.h> | ||
15 | #include "base.h" | 16 | #include "base.h" |
16 | 17 | ||
17 | DECLARE_MUTEX(pnp_res_mutex); | 18 | DEFINE_MUTEX(pnp_res_mutex); |
18 | 19 | ||
19 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) | 20 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) |
20 | { | 21 | { |
@@ -297,7 +298,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
297 | if (!pnp_can_configure(dev)) | 298 | if (!pnp_can_configure(dev)) |
298 | return -ENODEV; | 299 | return -ENODEV; |
299 | 300 | ||
300 | down(&pnp_res_mutex); | 301 | mutex_lock(&pnp_res_mutex); |
301 | pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ | 302 | pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ |
302 | if (dev->independent) { | 303 | if (dev->independent) { |
303 | port = dev->independent->port; | 304 | port = dev->independent->port; |
@@ -366,12 +367,12 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
366 | } else if (dev->dependent) | 367 | } else if (dev->dependent) |
367 | goto fail; | 368 | goto fail; |
368 | 369 | ||
369 | up(&pnp_res_mutex); | 370 | mutex_unlock(&pnp_res_mutex); |
370 | return 1; | 371 | return 1; |
371 | 372 | ||
372 | fail: | 373 | fail: |
373 | pnp_clean_resource_table(&dev->res); | 374 | pnp_clean_resource_table(&dev->res); |
374 | up(&pnp_res_mutex); | 375 | mutex_unlock(&pnp_res_mutex); |
375 | return 0; | 376 | return 0; |
376 | } | 377 | } |
377 | 378 | ||
@@ -396,7 +397,7 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, | |||
396 | return -ENOMEM; | 397 | return -ENOMEM; |
397 | *bak = dev->res; | 398 | *bak = dev->res; |
398 | 399 | ||
399 | down(&pnp_res_mutex); | 400 | mutex_lock(&pnp_res_mutex); |
400 | dev->res = *res; | 401 | dev->res = *res; |
401 | if (!(mode & PNP_CONFIG_FORCE)) { | 402 | if (!(mode & PNP_CONFIG_FORCE)) { |
402 | for (i = 0; i < PNP_MAX_PORT; i++) { | 403 | for (i = 0; i < PNP_MAX_PORT; i++) { |
@@ -416,14 +417,14 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, | |||
416 | goto fail; | 417 | goto fail; |
417 | } | 418 | } |
418 | } | 419 | } |
419 | up(&pnp_res_mutex); | 420 | mutex_unlock(&pnp_res_mutex); |
420 | 421 | ||
421 | kfree(bak); | 422 | kfree(bak); |
422 | return 0; | 423 | return 0; |
423 | 424 | ||
424 | fail: | 425 | fail: |
425 | dev->res = *bak; | 426 | dev->res = *bak; |
426 | up(&pnp_res_mutex); | 427 | mutex_unlock(&pnp_res_mutex); |
427 | kfree(bak); | 428 | kfree(bak); |
428 | return -EINVAL; | 429 | return -EINVAL; |
429 | } | 430 | } |
@@ -513,7 +514,7 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
513 | int error; | 514 | int error; |
514 | 515 | ||
515 | if (dev->active) | 516 | if (dev->active) |
516 | return 0; /* the device is already active */ | 517 | return 0; |
517 | 518 | ||
518 | /* ensure resources are allocated */ | 519 | /* ensure resources are allocated */ |
519 | if (pnp_auto_config_dev(dev)) | 520 | if (pnp_auto_config_dev(dev)) |
@@ -524,7 +525,7 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
524 | return error; | 525 | return error; |
525 | 526 | ||
526 | dev->active = 1; | 527 | dev->active = 1; |
527 | return 1; | 528 | return 0; |
528 | } | 529 | } |
529 | 530 | ||
530 | /** | 531 | /** |
@@ -538,7 +539,7 @@ int pnp_disable_dev(struct pnp_dev *dev) | |||
538 | int error; | 539 | int error; |
539 | 540 | ||
540 | if (!dev->active) | 541 | if (!dev->active) |
541 | return 0; /* the device is already disabled */ | 542 | return 0; |
542 | 543 | ||
543 | error = pnp_stop_dev(dev); | 544 | error = pnp_stop_dev(dev); |
544 | if (error) | 545 | if (error) |
@@ -547,11 +548,11 @@ int pnp_disable_dev(struct pnp_dev *dev) | |||
547 | dev->active = 0; | 548 | dev->active = 0; |
548 | 549 | ||
549 | /* release the resources so that other devices can use them */ | 550 | /* release the resources so that other devices can use them */ |
550 | down(&pnp_res_mutex); | 551 | mutex_lock(&pnp_res_mutex); |
551 | pnp_clean_resource_table(&dev->res); | 552 | pnp_clean_resource_table(&dev->res); |
552 | up(&pnp_res_mutex); | 553 | mutex_unlock(&pnp_res_mutex); |
553 | 554 | ||
554 | return 1; | 555 | return 0; |
555 | } | 556 | } |
556 | 557 | ||
557 | /** | 558 | /** |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 6b9840cce0f4..6aa231ef642d 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -391,8 +391,8 @@ acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, | |||
391 | pnpacpi_allocated_resource, res); | 391 | pnpacpi_allocated_resource, res); |
392 | } | 392 | } |
393 | 393 | ||
394 | static void pnpacpi_parse_dma_option(struct pnp_option *option, | 394 | static __init void pnpacpi_parse_dma_option(struct pnp_option *option, |
395 | struct acpi_resource_dma *p) | 395 | struct acpi_resource_dma *p) |
396 | { | 396 | { |
397 | int i; | 397 | int i; |
398 | struct pnp_dma *dma; | 398 | struct pnp_dma *dma; |
@@ -411,8 +411,8 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, | |||
411 | pnp_register_dma_resource(option, dma); | 411 | pnp_register_dma_resource(option, dma); |
412 | } | 412 | } |
413 | 413 | ||
414 | static void pnpacpi_parse_irq_option(struct pnp_option *option, | 414 | static __init void pnpacpi_parse_irq_option(struct pnp_option *option, |
415 | struct acpi_resource_irq *p) | 415 | struct acpi_resource_irq *p) |
416 | { | 416 | { |
417 | int i; | 417 | int i; |
418 | struct pnp_irq *irq; | 418 | struct pnp_irq *irq; |
@@ -431,8 +431,8 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option, | |||
431 | pnp_register_irq_resource(option, irq); | 431 | pnp_register_irq_resource(option, irq); |
432 | } | 432 | } |
433 | 433 | ||
434 | static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, | 434 | static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, |
435 | struct acpi_resource_extended_irq *p) | 435 | struct acpi_resource_extended_irq *p) |
436 | { | 436 | { |
437 | int i; | 437 | int i; |
438 | struct pnp_irq *irq; | 438 | struct pnp_irq *irq; |
@@ -451,8 +451,8 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, | |||
451 | pnp_register_irq_resource(option, irq); | 451 | pnp_register_irq_resource(option, irq); |
452 | } | 452 | } |
453 | 453 | ||
454 | static void pnpacpi_parse_port_option(struct pnp_option *option, | 454 | static __init void pnpacpi_parse_port_option(struct pnp_option *option, |
455 | struct acpi_resource_io *io) | 455 | struct acpi_resource_io *io) |
456 | { | 456 | { |
457 | struct pnp_port *port; | 457 | struct pnp_port *port; |
458 | 458 | ||
@@ -470,8 +470,8 @@ static void pnpacpi_parse_port_option(struct pnp_option *option, | |||
470 | pnp_register_port_resource(option, port); | 470 | pnp_register_port_resource(option, port); |
471 | } | 471 | } |
472 | 472 | ||
473 | static void pnpacpi_parse_fixed_port_option(struct pnp_option *option, | 473 | static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, |
474 | struct acpi_resource_fixed_io *io) | 474 | struct acpi_resource_fixed_io *io) |
475 | { | 475 | { |
476 | struct pnp_port *port; | 476 | struct pnp_port *port; |
477 | 477 | ||
@@ -487,8 +487,8 @@ static void pnpacpi_parse_fixed_port_option(struct pnp_option *option, | |||
487 | pnp_register_port_resource(option, port); | 487 | pnp_register_port_resource(option, port); |
488 | } | 488 | } |
489 | 489 | ||
490 | static void pnpacpi_parse_mem24_option(struct pnp_option *option, | 490 | static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, |
491 | struct acpi_resource_memory24 *p) | 491 | struct acpi_resource_memory24 *p) |
492 | { | 492 | { |
493 | struct pnp_mem *mem; | 493 | struct pnp_mem *mem; |
494 | 494 | ||
@@ -508,8 +508,8 @@ static void pnpacpi_parse_mem24_option(struct pnp_option *option, | |||
508 | pnp_register_mem_resource(option, mem); | 508 | pnp_register_mem_resource(option, mem); |
509 | } | 509 | } |
510 | 510 | ||
511 | static void pnpacpi_parse_mem32_option(struct pnp_option *option, | 511 | static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, |
512 | struct acpi_resource_memory32 *p) | 512 | struct acpi_resource_memory32 *p) |
513 | { | 513 | { |
514 | struct pnp_mem *mem; | 514 | struct pnp_mem *mem; |
515 | 515 | ||
@@ -529,8 +529,8 @@ static void pnpacpi_parse_mem32_option(struct pnp_option *option, | |||
529 | pnp_register_mem_resource(option, mem); | 529 | pnp_register_mem_resource(option, mem); |
530 | } | 530 | } |
531 | 531 | ||
532 | static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, | 532 | static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, |
533 | struct acpi_resource_fixed_memory32 *p) | 533 | struct acpi_resource_fixed_memory32 *p) |
534 | { | 534 | { |
535 | struct pnp_mem *mem; | 535 | struct pnp_mem *mem; |
536 | 536 | ||
@@ -549,8 +549,8 @@ static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, | |||
549 | pnp_register_mem_resource(option, mem); | 549 | pnp_register_mem_resource(option, mem); |
550 | } | 550 | } |
551 | 551 | ||
552 | static void pnpacpi_parse_address_option(struct pnp_option *option, | 552 | static __init void pnpacpi_parse_address_option(struct pnp_option *option, |
553 | struct acpi_resource *r) | 553 | struct acpi_resource *r) |
554 | { | 554 | { |
555 | struct acpi_resource_address64 addr, *p = &addr; | 555 | struct acpi_resource_address64 addr, *p = &addr; |
556 | acpi_status status; | 556 | acpi_status status; |
@@ -596,8 +596,8 @@ struct acpipnp_parse_option_s { | |||
596 | struct pnp_dev *dev; | 596 | struct pnp_dev *dev; |
597 | }; | 597 | }; |
598 | 598 | ||
599 | static acpi_status pnpacpi_option_resource(struct acpi_resource *res, | 599 | static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, |
600 | void *data) | 600 | void *data) |
601 | { | 601 | { |
602 | int priority = 0; | 602 | int priority = 0; |
603 | struct acpipnp_parse_option_s *parse_data = data; | 603 | struct acpipnp_parse_option_s *parse_data = data; |
@@ -696,8 +696,8 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
696 | return AE_OK; | 696 | return AE_OK; |
697 | } | 697 | } |
698 | 698 | ||
699 | acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, | 699 | acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle, |
700 | struct pnp_dev * dev) | 700 | struct pnp_dev *dev) |
701 | { | 701 | { |
702 | acpi_status status; | 702 | acpi_status status; |
703 | struct acpipnp_parse_option_s parse_data; | 703 | struct acpipnp_parse_option_s parse_data; |
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index e33e03f71084..f7e67197a568 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c | |||
@@ -315,7 +315,7 @@ struct pnp_protocol pnpbios_protocol = { | |||
315 | .disable = pnpbios_disable_resources, | 315 | .disable = pnpbios_disable_resources, |
316 | }; | 316 | }; |
317 | 317 | ||
318 | static int insert_device(struct pnp_bios_node *node) | 318 | static int __init insert_device(struct pnp_bios_node *node) |
319 | { | 319 | { |
320 | struct list_head *pos; | 320 | struct list_head *pos; |
321 | struct pnp_dev *dev; | 321 | struct pnp_dev *dev; |
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 3fabf11b0027..caade3531416 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c | |||
@@ -262,8 +262,8 @@ len_err: | |||
262 | * Resource Configuration Options | 262 | * Resource Configuration Options |
263 | */ | 263 | */ |
264 | 264 | ||
265 | static void pnpbios_parse_mem_option(unsigned char *p, int size, | 265 | static __init void pnpbios_parse_mem_option(unsigned char *p, int size, |
266 | struct pnp_option *option) | 266 | struct pnp_option *option) |
267 | { | 267 | { |
268 | struct pnp_mem *mem; | 268 | struct pnp_mem *mem; |
269 | 269 | ||
@@ -278,8 +278,8 @@ static void pnpbios_parse_mem_option(unsigned char *p, int size, | |||
278 | pnp_register_mem_resource(option, mem); | 278 | pnp_register_mem_resource(option, mem); |
279 | } | 279 | } |
280 | 280 | ||
281 | static void pnpbios_parse_mem32_option(unsigned char *p, int size, | 281 | static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, |
282 | struct pnp_option *option) | 282 | struct pnp_option *option) |
283 | { | 283 | { |
284 | struct pnp_mem *mem; | 284 | struct pnp_mem *mem; |
285 | 285 | ||
@@ -294,8 +294,8 @@ static void pnpbios_parse_mem32_option(unsigned char *p, int size, | |||
294 | pnp_register_mem_resource(option, mem); | 294 | pnp_register_mem_resource(option, mem); |
295 | } | 295 | } |
296 | 296 | ||
297 | static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, | 297 | static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, |
298 | struct pnp_option *option) | 298 | struct pnp_option *option) |
299 | { | 299 | { |
300 | struct pnp_mem *mem; | 300 | struct pnp_mem *mem; |
301 | 301 | ||
@@ -309,7 +309,7 @@ static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, | |||
309 | pnp_register_mem_resource(option, mem); | 309 | pnp_register_mem_resource(option, mem); |
310 | } | 310 | } |
311 | 311 | ||
312 | static void pnpbios_parse_irq_option(unsigned char *p, int size, | 312 | static __init void pnpbios_parse_irq_option(unsigned char *p, int size, |
313 | struct pnp_option *option) | 313 | struct pnp_option *option) |
314 | { | 314 | { |
315 | struct pnp_irq *irq; | 315 | struct pnp_irq *irq; |
@@ -327,7 +327,7 @@ static void pnpbios_parse_irq_option(unsigned char *p, int size, | |||
327 | pnp_register_irq_resource(option, irq); | 327 | pnp_register_irq_resource(option, irq); |
328 | } | 328 | } |
329 | 329 | ||
330 | static void pnpbios_parse_dma_option(unsigned char *p, int size, | 330 | static __init void pnpbios_parse_dma_option(unsigned char *p, int size, |
331 | struct pnp_option *option) | 331 | struct pnp_option *option) |
332 | { | 332 | { |
333 | struct pnp_dma *dma; | 333 | struct pnp_dma *dma; |
@@ -340,8 +340,8 @@ static void pnpbios_parse_dma_option(unsigned char *p, int size, | |||
340 | pnp_register_dma_resource(option, dma); | 340 | pnp_register_dma_resource(option, dma); |
341 | } | 341 | } |
342 | 342 | ||
343 | static void pnpbios_parse_port_option(unsigned char *p, int size, | 343 | static __init void pnpbios_parse_port_option(unsigned char *p, int size, |
344 | struct pnp_option *option) | 344 | struct pnp_option *option) |
345 | { | 345 | { |
346 | struct pnp_port *port; | 346 | struct pnp_port *port; |
347 | 347 | ||
@@ -356,8 +356,8 @@ static void pnpbios_parse_port_option(unsigned char *p, int size, | |||
356 | pnp_register_port_resource(option, port); | 356 | pnp_register_port_resource(option, port); |
357 | } | 357 | } |
358 | 358 | ||
359 | static void pnpbios_parse_fixed_port_option(unsigned char *p, int size, | 359 | static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, |
360 | struct pnp_option *option) | 360 | struct pnp_option *option) |
361 | { | 361 | { |
362 | struct pnp_port *port; | 362 | struct pnp_port *port; |
363 | 363 | ||
@@ -371,9 +371,9 @@ static void pnpbios_parse_fixed_port_option(unsigned char *p, int size, | |||
371 | pnp_register_port_resource(option, port); | 371 | pnp_register_port_resource(option, port); |
372 | } | 372 | } |
373 | 373 | ||
374 | static unsigned char *pnpbios_parse_resource_option_data(unsigned char *p, | 374 | static __init unsigned char * |
375 | unsigned char *end, | 375 | pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, |
376 | struct pnp_dev *dev) | 376 | struct pnp_dev *dev) |
377 | { | 377 | { |
378 | unsigned int len, tag; | 378 | unsigned int len, tag; |
379 | int priority = 0; | 379 | int priority = 0; |
@@ -781,7 +781,8 @@ len_err: | |||
781 | * Core Parsing Functions | 781 | * Core Parsing Functions |
782 | */ | 782 | */ |
783 | 783 | ||
784 | int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node *node) | 784 | int __init pnpbios_parse_data_stream(struct pnp_dev *dev, |
785 | struct pnp_bios_node *node) | ||
785 | { | 786 | { |
786 | unsigned char *p = (char *)node->data; | 787 | unsigned char *p = (char *)node->data; |
787 | unsigned char *end = (char *)(node->data + node->size); | 788 | unsigned char *end = (char *)(node->data + node->size); |
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index e903b8c2b1fa..4065139753b6 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/pnp.h> | 18 | #include <linux/pnp.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/dmi.h> | ||
20 | #include <linux/kallsyms.h> | 21 | #include <linux/kallsyms.h> |
21 | #include "base.h" | 22 | #include "base.h" |
22 | 23 | ||
@@ -108,6 +109,46 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) | |||
108 | "pnp: SB audio device quirk - increasing port range\n"); | 109 | "pnp: SB audio device quirk - increasing port range\n"); |
109 | } | 110 | } |
110 | 111 | ||
112 | static void quirk_supermicro_h8dce_system(struct pnp_dev *dev) | ||
113 | { | ||
114 | int i; | ||
115 | static struct dmi_system_id supermicro_h8dce[] = { | ||
116 | { | ||
117 | .ident = "Supermicro H8DCE", | ||
118 | .matches = { | ||
119 | DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), | ||
120 | DMI_MATCH(DMI_PRODUCT_NAME, "H8DCE"), | ||
121 | }, | ||
122 | }, | ||
123 | { } | ||
124 | }; | ||
125 | |||
126 | if (!dmi_check_system(supermicro_h8dce)) | ||
127 | return; | ||
128 | |||
129 | /* | ||
130 | * On the Supermicro H8DCE, there's a system device with resources | ||
131 | * that overlap BAR 6 of the built-in SATA PCI adapter. If the PNP | ||
132 | * system device claims them, the sata_nv driver won't be able to. | ||
133 | * More details at: | ||
134 | * https://bugzilla.redhat.com/show_bug.cgi?id=280641 | ||
135 | * https://bugzilla.redhat.com/show_bug.cgi?id=313491 | ||
136 | * http://lkml.org/lkml/2008/1/9/449 | ||
137 | * http://thread.gmane.org/gmane.linux.acpi.devel/27312 | ||
138 | */ | ||
139 | for (i = 0; i < PNP_MAX_MEM; i++) { | ||
140 | if (pnp_mem_valid(dev, i) && pnp_mem_len(dev, i) && | ||
141 | (pnp_mem_start(dev, i) & 0xdfef0000) == 0xdfef0000) { | ||
142 | dev_warn(&dev->dev, "disabling 0x%llx-0x%llx to prevent" | ||
143 | " conflict with sata_nv PCI device\n", | ||
144 | (unsigned long long) pnp_mem_start(dev, i), | ||
145 | (unsigned long long) (pnp_mem_start(dev, i) + | ||
146 | pnp_mem_len(dev, i) - 1)); | ||
147 | pnp_mem_flags(dev, i) = 0; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | |||
111 | /* | 152 | /* |
112 | * PnP Quirks | 153 | * PnP Quirks |
113 | * Cards or devices that need some tweaking due to incomplete resource info | 154 | * Cards or devices that need some tweaking due to incomplete resource info |
@@ -128,6 +169,8 @@ static struct pnp_fixup pnp_fixups[] = { | |||
128 | {"CTL0043", quirk_sb16audio_resources}, | 169 | {"CTL0043", quirk_sb16audio_resources}, |
129 | {"CTL0044", quirk_sb16audio_resources}, | 170 | {"CTL0044", quirk_sb16audio_resources}, |
130 | {"CTL0045", quirk_sb16audio_resources}, | 171 | {"CTL0045", quirk_sb16audio_resources}, |
172 | {"PNP0c01", quirk_supermicro_h8dce_system}, | ||
173 | {"PNP0c02", quirk_supermicro_h8dce_system}, | ||
131 | {""} | 174 | {""} |
132 | }; | 175 | }; |
133 | 176 | ||
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index 87b3493d88e5..6f2f90ebb020 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c | |||
@@ -78,23 +78,21 @@ static const struct avset_video_mode { | |||
78 | u32 aspect; | 78 | u32 aspect; |
79 | u32 x; | 79 | u32 x; |
80 | u32 y; | 80 | u32 y; |
81 | u32 interlace; | ||
82 | u32 freq; | ||
83 | } video_mode_table[] = { | 81 | } video_mode_table[] = { |
84 | { 0, }, /* auto */ | 82 | { 0, }, /* auto */ |
85 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480, 1, 60}, | 83 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480}, |
86 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480, 0, 60}, | 84 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480}, |
87 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720, 0, 60}, | 85 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720}, |
88 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60}, | 86 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080}, |
89 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60}, | 87 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080}, |
90 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576, 1, 50}, | 88 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576}, |
91 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576, 0, 50}, | 89 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576}, |
92 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720, 0, 50}, | 90 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720}, |
93 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50}, | 91 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080}, |
94 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50}, | 92 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080}, |
95 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768, 0, 60}, | 93 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768}, |
96 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024, 0, 60}, | 94 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024}, |
97 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200, 0, 60}, | 95 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200}, |
98 | }; | 96 | }; |
99 | 97 | ||
100 | /* supported CIDs */ | 98 | /* supported CIDs */ |
@@ -544,7 +542,7 @@ static void ps3av_set_videomode_packet(u32 id) | |||
544 | 542 | ||
545 | static void ps3av_set_videomode_cont(u32 id, u32 old_id) | 543 | static void ps3av_set_videomode_cont(u32 id, u32 old_id) |
546 | { | 544 | { |
547 | static int vesa = 0; | 545 | static int vesa; |
548 | int res; | 546 | int res; |
549 | 547 | ||
550 | /* video signal off */ | 548 | /* video signal off */ |
@@ -554,9 +552,9 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
554 | * AV backend needs non-VESA mode setting at least one time | 552 | * AV backend needs non-VESA mode setting at least one time |
555 | * when VESA mode is used. | 553 | * when VESA mode is used. |
556 | */ | 554 | */ |
557 | if (vesa == 0 && (id & PS3AV_MODE_MASK) >= 11) { | 555 | if (vesa == 0 && (id & PS3AV_MODE_MASK) >= PS3AV_MODE_WXGA) { |
558 | /* vesa mode */ | 556 | /* vesa mode */ |
559 | ps3av_set_videomode_packet(2); /* 480P */ | 557 | ps3av_set_videomode_packet(PS3AV_MODE_480P); |
560 | } | 558 | } |
561 | vesa = 1; | 559 | vesa = 1; |
562 | 560 | ||
@@ -596,20 +594,21 @@ static const struct { | |||
596 | unsigned mask : 19; | 594 | unsigned mask : 19; |
597 | unsigned id : 4; | 595 | unsigned id : 4; |
598 | } ps3av_preferred_modes[] = { | 596 | } ps3av_preferred_modes[] = { |
599 | { .mask = PS3AV_RESBIT_WUXGA << SHIFT_VESA, .id = 13 }, | 597 | { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA }, |
600 | { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_60, .id = 5 }, | 598 | { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 }, |
601 | { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_50, .id = 10 }, | 599 | { PS3AV_RESBIT_1920x1080P << SHIFT_50, PS3AV_MODE_1080P50 }, |
602 | { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_60, .id = 4 }, | 600 | { PS3AV_RESBIT_1920x1080I << SHIFT_60, PS3AV_MODE_1080I60 }, |
603 | { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_50, .id = 9 }, | 601 | { PS3AV_RESBIT_1920x1080I << SHIFT_50, PS3AV_MODE_1080I50 }, |
604 | { .mask = PS3AV_RESBIT_SXGA << SHIFT_VESA, .id = 12 }, | 602 | { PS3AV_RESBIT_SXGA << SHIFT_VESA, PS3AV_MODE_SXGA }, |
605 | { .mask = PS3AV_RESBIT_WXGA << SHIFT_VESA, .id = 11 }, | 603 | { PS3AV_RESBIT_WXGA << SHIFT_VESA, PS3AV_MODE_WXGA }, |
606 | { .mask = PS3AV_RESBIT_1280x720P << SHIFT_60, .id = 3 }, | 604 | { PS3AV_RESBIT_1280x720P << SHIFT_60, PS3AV_MODE_720P60 }, |
607 | { .mask = PS3AV_RESBIT_1280x720P << SHIFT_50, .id = 8 }, | 605 | { PS3AV_RESBIT_1280x720P << SHIFT_50, PS3AV_MODE_720P50 }, |
608 | { .mask = PS3AV_RESBIT_720x480P << SHIFT_60, .id = 2 }, | 606 | { PS3AV_RESBIT_720x480P << SHIFT_60, PS3AV_MODE_480P }, |
609 | { .mask = PS3AV_RESBIT_720x576P << SHIFT_50, .id = 7 }, | 607 | { PS3AV_RESBIT_720x576P << SHIFT_50, PS3AV_MODE_576P }, |
610 | }; | 608 | }; |
611 | 609 | ||
612 | static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa) | 610 | static enum ps3av_mode_num ps3av_resbit2id(u32 res_50, u32 res_60, |
611 | u32 res_vesa) | ||
613 | { | 612 | { |
614 | unsigned int i; | 613 | unsigned int i; |
615 | u32 res_all; | 614 | u32 res_all; |
@@ -638,9 +637,9 @@ static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa) | |||
638 | return 0; | 637 | return 0; |
639 | } | 638 | } |
640 | 639 | ||
641 | static int ps3av_hdmi_get_id(struct ps3av_info_monitor *info) | 640 | static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info) |
642 | { | 641 | { |
643 | int id; | 642 | enum ps3av_mode_num id; |
644 | 643 | ||
645 | if (safe_mode) | 644 | if (safe_mode) |
646 | return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; | 645 | return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; |
@@ -854,7 +853,7 @@ int ps3av_set_video_mode(u32 id) | |||
854 | 853 | ||
855 | /* auto mode */ | 854 | /* auto mode */ |
856 | option = id & ~PS3AV_MODE_MASK; | 855 | option = id & ~PS3AV_MODE_MASK; |
857 | if ((id & PS3AV_MODE_MASK) == 0) { | 856 | if ((id & PS3AV_MODE_MASK) == PS3AV_MODE_AUTO) { |
858 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); | 857 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); |
859 | if (id < 1) { | 858 | if (id < 1) { |
860 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); | 859 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); |
@@ -889,36 +888,6 @@ int ps3av_get_mode(void) | |||
889 | 888 | ||
890 | EXPORT_SYMBOL_GPL(ps3av_get_mode); | 889 | EXPORT_SYMBOL_GPL(ps3av_get_mode); |
891 | 890 | ||
892 | int ps3av_get_scanmode(int id) | ||
893 | { | ||
894 | int size; | ||
895 | |||
896 | id = id & PS3AV_MODE_MASK; | ||
897 | size = ARRAY_SIZE(video_mode_table); | ||
898 | if (id > size - 1 || id < 0) { | ||
899 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); | ||
900 | return -EINVAL; | ||
901 | } | ||
902 | return video_mode_table[id].interlace; | ||
903 | } | ||
904 | |||
905 | EXPORT_SYMBOL_GPL(ps3av_get_scanmode); | ||
906 | |||
907 | int ps3av_get_refresh_rate(int id) | ||
908 | { | ||
909 | int size; | ||
910 | |||
911 | id = id & PS3AV_MODE_MASK; | ||
912 | size = ARRAY_SIZE(video_mode_table); | ||
913 | if (id > size - 1 || id < 0) { | ||
914 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); | ||
915 | return -EINVAL; | ||
916 | } | ||
917 | return video_mode_table[id].freq; | ||
918 | } | ||
919 | |||
920 | EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate); | ||
921 | |||
922 | /* get resolution by video_mode */ | 891 | /* get resolution by video_mode */ |
923 | int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) | 892 | int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) |
924 | { | 893 | { |
@@ -990,7 +959,7 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) | |||
990 | return -ENOMEM; | 959 | return -ENOMEM; |
991 | 960 | ||
992 | mutex_init(&ps3av->mutex); | 961 | mutex_init(&ps3av->mutex); |
993 | ps3av->ps3av_mode = 0; | 962 | ps3av->ps3av_mode = PS3AV_MODE_AUTO; |
994 | ps3av->dev = dev; | 963 | ps3av->dev = dev; |
995 | 964 | ||
996 | INIT_WORK(&ps3av->work, ps3avd); | 965 | INIT_WORK(&ps3av->work, ps3avd); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 45e4b9648176..6402d699072b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -20,6 +20,10 @@ menuconfig RTC_CLASS | |||
20 | 20 | ||
21 | if RTC_CLASS | 21 | if RTC_CLASS |
22 | 22 | ||
23 | if GEN_RTC || RTC | ||
24 | comment "Conflicting RTC option has been selected, check GEN_RTC and RTC" | ||
25 | endif | ||
26 | |||
23 | config RTC_HCTOSYS | 27 | config RTC_HCTOSYS |
24 | bool "Set system time from RTC on startup and resume" | 28 | bool "Set system time from RTC on startup and resume" |
25 | depends on RTC_CLASS = y | 29 | depends on RTC_CLASS = y |
@@ -49,7 +53,7 @@ config RTC_HCTOSYS_DEVICE | |||
49 | 53 | ||
50 | If the clock you specify here is not battery backed, it may still | 54 | If the clock you specify here is not battery backed, it may still |
51 | be useful to reinitialize system time when resuming from system | 55 | be useful to reinitialize system time when resuming from system |
52 | sleep states. Do not specify an RTC here unless it stays powered | 56 | sleep states. Do not specify an RTC here unless it stays powered |
53 | during all this system's supported sleep states. | 57 | during all this system's supported sleep states. |
54 | 58 | ||
55 | config RTC_DEBUG | 59 | config RTC_DEBUG |
@@ -142,7 +146,7 @@ config RTC_DRV_DS1307 | |||
142 | will be called rtc-ds1307. | 146 | will be called rtc-ds1307. |
143 | 147 | ||
144 | config RTC_DRV_DS1374 | 148 | config RTC_DRV_DS1374 |
145 | tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" | 149 | tristate "Dallas/Maxim DS1374" |
146 | depends on RTC_CLASS && I2C | 150 | depends on RTC_CLASS && I2C |
147 | help | 151 | help |
148 | If you say yes here you get support for Dallas Semiconductor | 152 | If you say yes here you get support for Dallas Semiconductor |
@@ -162,7 +166,7 @@ config RTC_DRV_DS1672 | |||
162 | will be called rtc-ds1672. | 166 | will be called rtc-ds1672. |
163 | 167 | ||
164 | config RTC_DRV_MAX6900 | 168 | config RTC_DRV_MAX6900 |
165 | tristate "Maxim 6900" | 169 | tristate "Maxim MAX6900" |
166 | help | 170 | help |
167 | If you say yes here you will get support for the | 171 | If you say yes here you will get support for the |
168 | Maxim MAX6900 I2C RTC chip. | 172 | Maxim MAX6900 I2C RTC chip. |
@@ -180,10 +184,10 @@ config RTC_DRV_RS5C372 | |||
180 | will be called rtc-rs5c372. | 184 | will be called rtc-rs5c372. |
181 | 185 | ||
182 | config RTC_DRV_ISL1208 | 186 | config RTC_DRV_ISL1208 |
183 | tristate "Intersil 1208" | 187 | tristate "Intersil ISL1208" |
184 | help | 188 | help |
185 | If you say yes here you get support for the | 189 | If you say yes here you get support for the |
186 | Intersil 1208 RTC chip. | 190 | Intersil ISL1208 RTC chip. |
187 | 191 | ||
188 | This driver can also be built as a module. If so, the module | 192 | This driver can also be built as a module. If so, the module |
189 | will be called rtc-isl1208. | 193 | will be called rtc-isl1208. |
@@ -220,7 +224,7 @@ config RTC_DRV_PCF8583 | |||
220 | will be called rtc-pcf8583. | 224 | will be called rtc-pcf8583. |
221 | 225 | ||
222 | config RTC_DRV_M41T80 | 226 | config RTC_DRV_M41T80 |
223 | tristate "ST M41T80 series RTC" | 227 | tristate "ST M41T80/81/82/83/84/85/87" |
224 | help | 228 | help |
225 | If you say Y here you will get support for the | 229 | If you say Y here you will get support for the |
226 | ST M41T80 RTC chips series. Currently following chips are | 230 | ST M41T80 RTC chips series. Currently following chips are |
@@ -252,23 +256,32 @@ comment "SPI RTC drivers" | |||
252 | 256 | ||
253 | if SPI_MASTER | 257 | if SPI_MASTER |
254 | 258 | ||
255 | config RTC_DRV_RS5C348 | 259 | config RTC_DRV_MAX6902 |
256 | tristate "Ricoh RS5C348A/B" | 260 | tristate "Maxim MAX6902" |
257 | help | 261 | help |
258 | If you say yes here you get support for the | 262 | If you say yes here you will get support for the |
259 | Ricoh RS5C348A and RS5C348B RTC chips. | 263 | Maxim MAX6902 SPI RTC chip. |
260 | 264 | ||
261 | This driver can also be built as a module. If so, the module | 265 | This driver can also be built as a module. If so, the module |
262 | will be called rtc-rs5c348. | 266 | will be called rtc-max6902. |
263 | 267 | ||
264 | config RTC_DRV_MAX6902 | 268 | config RTC_DRV_R9701 |
265 | tristate "Maxim 6902" | 269 | tristate "Epson RTC-9701JE" |
266 | help | 270 | help |
267 | If you say yes here you will get support for the | 271 | If you say yes here you will get support for the |
268 | Maxim MAX6902 SPI RTC chip. | 272 | Epson RTC-9701JE SPI RTC chip. |
269 | 273 | ||
270 | This driver can also be built as a module. If so, the module | 274 | This driver can also be built as a module. If so, the module |
271 | will be called rtc-max6902. | 275 | will be called rtc-r9701. |
276 | |||
277 | config RTC_DRV_RS5C348 | ||
278 | tristate "Ricoh RS5C348A/B" | ||
279 | help | ||
280 | If you say yes here you get support for the | ||
281 | Ricoh RS5C348A and RS5C348B RTC chips. | ||
282 | |||
283 | This driver can also be built as a module. If so, the module | ||
284 | will be called rtc-rs5c348. | ||
272 | 285 | ||
273 | endif # SPI_MASTER | 286 | endif # SPI_MASTER |
274 | 287 | ||
@@ -302,34 +315,50 @@ config RTC_DRV_DS1216 | |||
302 | help | 315 | help |
303 | If you say yes here you get support for the Dallas DS1216 RTC chips. | 316 | If you say yes here you get support for the Dallas DS1216 RTC chips. |
304 | 317 | ||
305 | config RTC_DRV_DS1553 | 318 | config RTC_DRV_DS1302 |
306 | tristate "Dallas DS1553" | 319 | tristate "Dallas DS1302" |
320 | depends on SH_SECUREEDGE5410 | ||
321 | help | ||
322 | If you say yes here you get support for the Dallas DS1302 RTC chips. | ||
323 | |||
324 | config RTC_DRV_DS1511 | ||
325 | tristate "Dallas DS1511" | ||
326 | depends on RTC_CLASS | ||
307 | help | 327 | help |
308 | If you say yes here you get support for the | 328 | If you say yes here you get support for the |
309 | Dallas DS1553 timekeeping chip. | 329 | Dallas DS1511 timekeeping/watchdog chip. |
310 | 330 | ||
311 | This driver can also be built as a module. If so, the module | 331 | This driver can also be built as a module. If so, the module |
312 | will be called rtc-ds1553. | 332 | will be called rtc-ds1511. |
313 | 333 | ||
314 | config RTC_DRV_STK17TA8 | 334 | config RTC_DRV_DS1553 |
315 | tristate "Simtek STK17TA8" | 335 | tristate "Maxim/Dallas DS1553" |
316 | depends on RTC_CLASS | ||
317 | help | 336 | help |
318 | If you say yes here you get support for the | 337 | If you say yes here you get support for the |
319 | Simtek STK17TA8 timekeeping chip. | 338 | Maxim/Dallas DS1553 timekeeping chip. |
320 | 339 | ||
321 | 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 |
322 | will be called rtc-stk17ta8. | 341 | will be called rtc-ds1553. |
323 | 342 | ||
324 | config RTC_DRV_DS1742 | 343 | config RTC_DRV_DS1742 |
325 | tristate "Dallas DS1742/1743" | 344 | tristate "Maxim/Dallas DS1742/1743" |
326 | help | 345 | help |
327 | If you say yes here you get support for the | 346 | If you say yes here you get support for the |
328 | Dallas DS1742/1743 timekeeping chip. | 347 | Maxim/Dallas DS1742/1743 timekeeping chip. |
329 | 348 | ||
330 | This driver can also be built as a module. If so, the module | 349 | This driver can also be built as a module. If so, the module |
331 | will be called rtc-ds1742. | 350 | will be called rtc-ds1742. |
332 | 351 | ||
352 | config RTC_DRV_STK17TA8 | ||
353 | tristate "Simtek STK17TA8" | ||
354 | depends on RTC_CLASS | ||
355 | help | ||
356 | If you say yes here you get support for the | ||
357 | Simtek STK17TA8 timekeeping chip. | ||
358 | |||
359 | This driver can also be built as a module. If so, the module | ||
360 | will be called rtc-stk17ta8. | ||
361 | |||
333 | config RTC_DRV_M48T86 | 362 | config RTC_DRV_M48T86 |
334 | tristate "ST M48T86/Dallas DS12887" | 363 | tristate "ST M48T86/Dallas DS12887" |
335 | help | 364 | help |
@@ -440,10 +469,47 @@ config RTC_DRV_AT32AP700X | |||
440 | AT32AP700x family processors. | 469 | AT32AP700x family processors. |
441 | 470 | ||
442 | config RTC_DRV_AT91RM9200 | 471 | config RTC_DRV_AT91RM9200 |
443 | tristate "AT91RM9200" | 472 | tristate "AT91RM9200 or AT91SAM9RL" |
444 | depends on ARCH_AT91RM9200 | 473 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL |
445 | help | 474 | help |
446 | Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock). | 475 | Driver for the internal RTC (Realtime Clock) module found on |
476 | Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips | ||
477 | this is powered by the backup power supply. | ||
478 | |||
479 | config RTC_DRV_AT91SAM9 | ||
480 | tristate "AT91SAM9x" | ||
481 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) | ||
482 | help | ||
483 | RTC driver for the Atmel AT91SAM9x internal RTT (Real Time Timer). | ||
484 | These timers are powered by the backup power supply (such as a | ||
485 | small coin cell battery), but do not need to be used as RTCs. | ||
486 | |||
487 | (On AT91SAM9rl chips you probably want to use the dedicated RTC | ||
488 | module and leave the RTT available for other uses.) | ||
489 | |||
490 | config RTC_DRV_AT91SAM9_RTT | ||
491 | int | ||
492 | range 0 1 | ||
493 | default 0 | ||
494 | prompt "RTT module Number" if ARCH_AT91SAM9263 | ||
495 | depends on RTC_DRV_AT91SAM9 | ||
496 | help | ||
497 | More than one RTT module is available. You can choose which | ||
498 | one will be used as an RTC. The default of zero is normally | ||
499 | OK to use, though some systems use that for non-RTC purposes. | ||
500 | |||
501 | config RTC_DRV_AT91SAM9_GPBR | ||
502 | int | ||
503 | range 0 3 if !ARCH_AT91SAM9263 | ||
504 | range 0 15 if ARCH_AT91SAM9263 | ||
505 | default 0 | ||
506 | prompt "Backup Register Number" | ||
507 | depends on RTC_DRV_AT91SAM9 | ||
508 | help | ||
509 | The RTC driver needs to use one of the General Purpose Backup | ||
510 | Registers (GPBRs) as well as the RTT. You can choose which one | ||
511 | will be used. The default of zero is normally OK to use, but | ||
512 | on some systems other software needs to use that register. | ||
447 | 513 | ||
448 | config RTC_DRV_BFIN | 514 | config RTC_DRV_BFIN |
449 | tristate "Blackfin On-Chip RTC" | 515 | tristate "Blackfin On-Chip RTC" |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 465db4dd50b2..ec703f34ab86 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -19,11 +19,14 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
19 | 19 | ||
20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
22 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | ||
22 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 23 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
23 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
24 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
26 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | ||
25 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 27 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
26 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 28 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
29 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | ||
27 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 30 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
28 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 31 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
29 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 32 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
@@ -38,6 +41,7 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | |||
38 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 41 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
39 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 42 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
40 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 43 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
44 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | ||
41 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 45 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
42 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 46 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
43 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 47 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c new file mode 100644 index 000000000000..bbf10ecf416c --- /dev/null +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -0,0 +1,520 @@ | |||
1 | /* | ||
2 | * "RTT as Real Time Clock" driver for AT91SAM9 SoC family | ||
3 | * | ||
4 | * (C) 2007 Michel Benoit | ||
5 | * | ||
6 | * Based on rtc-at91rm9200.c by Rick Bronson | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/time.h> | ||
18 | #include <linux/rtc.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/ioctl.h> | ||
21 | |||
22 | #include <asm/mach/time.h> | ||
23 | #include <asm/arch/board.h> | ||
24 | #include <asm/arch/at91_rtt.h> | ||
25 | |||
26 | |||
27 | /* | ||
28 | * This driver uses two configurable hardware resources that live in the | ||
29 | * AT91SAM9 backup power domain (intended to be powered at all times) | ||
30 | * to implement the Real Time Clock interfaces | ||
31 | * | ||
32 | * - A "Real-time Timer" (RTT) counts up in seconds from a base time. | ||
33 | * We can't assign the counter value (CRTV) ... but we can reset it. | ||
34 | * | ||
35 | * - One of the "General Purpose Backup Registers" (GPBRs) holds the | ||
36 | * base time, normally an offset from the beginning of the POSIX | ||
37 | * epoch (1970-Jan-1 00:00:00 UTC). Some systems also include the | ||
38 | * local timezone's offset. | ||
39 | * | ||
40 | * The RTC's value is the RTT counter plus that offset. The RTC's alarm | ||
41 | * is likewise a base (ALMV) plus that offset. | ||
42 | * | ||
43 | * Not all RTTs will be used as RTCs; some systems have multiple RTTs to | ||
44 | * choose from, or a "real" RTC module. All systems have multiple GPBR | ||
45 | * registers available, likewise usable for more than "RTC" support. | ||
46 | */ | ||
47 | |||
48 | /* | ||
49 | * We store ALARM_DISABLED in ALMV to record that no alarm is set. | ||
50 | * It's also the reset value for that field. | ||
51 | */ | ||
52 | #define ALARM_DISABLED ((u32)~0) | ||
53 | |||
54 | |||
55 | struct sam9_rtc { | ||
56 | void __iomem *rtt; | ||
57 | struct rtc_device *rtcdev; | ||
58 | u32 imr; | ||
59 | }; | ||
60 | |||
61 | #define rtt_readl(rtc, field) \ | ||
62 | __raw_readl((rtc)->rtt + AT91_RTT_ ## field) | ||
63 | #define rtt_writel(rtc, field, val) \ | ||
64 | __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field) | ||
65 | |||
66 | #define gpbr_readl(rtc) \ | ||
67 | at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR) | ||
68 | #define gpbr_writel(rtc, val) \ | ||
69 | at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val)) | ||
70 | |||
71 | /* | ||
72 | * Read current time and date in RTC | ||
73 | */ | ||
74 | static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) | ||
75 | { | ||
76 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
77 | u32 secs, secs2; | ||
78 | u32 offset; | ||
79 | |||
80 | /* read current time offset */ | ||
81 | offset = gpbr_readl(rtc); | ||
82 | if (offset == 0) | ||
83 | return -EILSEQ; | ||
84 | |||
85 | /* reread the counter to help sync the two clock domains */ | ||
86 | secs = rtt_readl(rtc, VR); | ||
87 | secs2 = rtt_readl(rtc, VR); | ||
88 | if (secs != secs2) | ||
89 | secs = rtt_readl(rtc, VR); | ||
90 | |||
91 | rtc_time_to_tm(offset + secs, tm); | ||
92 | |||
93 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readtime", | ||
94 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
95 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * Set current time and date in RTC | ||
102 | */ | ||
103 | static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | ||
104 | { | ||
105 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
106 | int err; | ||
107 | u32 offset, alarm, mr; | ||
108 | unsigned long secs; | ||
109 | |||
110 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime", | ||
111 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
112 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
113 | |||
114 | err = rtc_tm_to_time(tm, &secs); | ||
115 | if (err != 0) | ||
116 | return err; | ||
117 | |||
118 | mr = rtt_readl(rtc, MR); | ||
119 | |||
120 | /* disable interrupts */ | ||
121 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); | ||
122 | |||
123 | /* read current time offset */ | ||
124 | offset = gpbr_readl(rtc); | ||
125 | |||
126 | /* store the new base time in a battery backup register */ | ||
127 | secs += 1; | ||
128 | gpbr_writel(rtc, secs); | ||
129 | |||
130 | /* adjust the alarm time for the new base */ | ||
131 | alarm = rtt_readl(rtc, AR); | ||
132 | if (alarm != ALARM_DISABLED) { | ||
133 | if (offset > secs) { | ||
134 | /* time jumped backwards, increase time until alarm */ | ||
135 | alarm += (offset - secs); | ||
136 | } else if ((alarm + offset) > secs) { | ||
137 | /* time jumped forwards, decrease time until alarm */ | ||
138 | alarm -= (secs - offset); | ||
139 | } else { | ||
140 | /* time jumped past the alarm, disable alarm */ | ||
141 | alarm = ALARM_DISABLED; | ||
142 | mr &= ~AT91_RTT_ALMIEN; | ||
143 | } | ||
144 | rtt_writel(rtc, AR, alarm); | ||
145 | } | ||
146 | |||
147 | /* reset the timer, and re-enable interrupts */ | ||
148 | rtt_writel(rtc, MR, mr | AT91_RTT_RTTRST); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
154 | { | ||
155 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
156 | struct rtc_time *tm = &alrm->time; | ||
157 | u32 alarm = rtt_readl(rtc, AR); | ||
158 | u32 offset; | ||
159 | |||
160 | offset = gpbr_readl(rtc); | ||
161 | if (offset == 0) | ||
162 | return -EILSEQ; | ||
163 | |||
164 | memset(alrm, 0, sizeof(alrm)); | ||
165 | if (alarm != ALARM_DISABLED && offset != 0) { | ||
166 | rtc_time_to_tm(offset + alarm, tm); | ||
167 | |||
168 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readalarm", | ||
169 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
170 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
171 | |||
172 | if (rtt_readl(rtc, MR) & AT91_RTT_ALMIEN) | ||
173 | alrm->enabled = 1; | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
180 | { | ||
181 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
182 | struct rtc_time *tm = &alrm->time; | ||
183 | unsigned long secs; | ||
184 | u32 offset; | ||
185 | u32 mr; | ||
186 | int err; | ||
187 | |||
188 | err = rtc_tm_to_time(tm, &secs); | ||
189 | if (err != 0) | ||
190 | return err; | ||
191 | |||
192 | offset = gpbr_readl(rtc); | ||
193 | if (offset == 0) { | ||
194 | /* time is not set */ | ||
195 | return -EILSEQ; | ||
196 | } | ||
197 | mr = rtt_readl(rtc, MR); | ||
198 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
199 | |||
200 | /* alarm in the past? finish and leave disabled */ | ||
201 | if (secs <= offset) { | ||
202 | rtt_writel(rtc, AR, ALARM_DISABLED); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* else set alarm and maybe enable it */ | ||
207 | rtt_writel(rtc, AR, secs - offset); | ||
208 | if (alrm->enabled) | ||
209 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
210 | |||
211 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "setalarm", | ||
212 | tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, | ||
213 | tm->tm_min, tm->tm_sec); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Handle commands from user-space | ||
220 | */ | ||
221 | static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
222 | unsigned long arg) | ||
223 | { | ||
224 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
225 | int ret = 0; | ||
226 | u32 mr = rtt_readl(rtc, MR); | ||
227 | |||
228 | dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr); | ||
229 | |||
230 | switch (cmd) { | ||
231 | case RTC_AIE_OFF: /* alarm off */ | ||
232 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
233 | break; | ||
234 | case RTC_AIE_ON: /* alarm on */ | ||
235 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
236 | break; | ||
237 | case RTC_UIE_OFF: /* update off */ | ||
238 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | ||
239 | break; | ||
240 | case RTC_UIE_ON: /* update on */ | ||
241 | rtt_writel(rtc, MR, mr | AT91_RTT_RTTINCIEN); | ||
242 | break; | ||
243 | default: | ||
244 | ret = -ENOIOCTLCMD; | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Provide additional RTC information in /proc/driver/rtc | ||
253 | */ | ||
254 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | ||
255 | { | ||
256 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
257 | u32 mr = mr = rtt_readl(rtc, MR); | ||
258 | |||
259 | seq_printf(seq, "update_IRQ\t: %s\n", | ||
260 | (mr & AT91_RTT_RTTINCIEN) ? "yes" : "no"); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * IRQ handler for the RTC | ||
266 | */ | ||
267 | static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc) | ||
268 | { | ||
269 | struct sam9_rtc *rtc = _rtc; | ||
270 | u32 sr, mr; | ||
271 | unsigned long events = 0; | ||
272 | |||
273 | /* Shared interrupt may be for another device. Note: reading | ||
274 | * SR clears it, so we must only read it in this irq handler! | ||
275 | */ | ||
276 | mr = rtt_readl(rtc, MR) & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
277 | sr = rtt_readl(rtc, SR) & mr; | ||
278 | if (!sr) | ||
279 | return IRQ_NONE; | ||
280 | |||
281 | /* alarm status */ | ||
282 | if (sr & AT91_RTT_ALMS) | ||
283 | events |= (RTC_AF | RTC_IRQF); | ||
284 | |||
285 | /* timer update/increment */ | ||
286 | if (sr & AT91_RTT_RTTINC) | ||
287 | events |= (RTC_UF | RTC_IRQF); | ||
288 | |||
289 | rtc_update_irq(rtc->rtcdev, 1, events); | ||
290 | |||
291 | pr_debug("%s: num=%ld, events=0x%02lx\n", __FUNCTION__, | ||
292 | events >> 8, events & 0x000000FF); | ||
293 | |||
294 | return IRQ_HANDLED; | ||
295 | } | ||
296 | |||
297 | static const struct rtc_class_ops at91_rtc_ops = { | ||
298 | .ioctl = at91_rtc_ioctl, | ||
299 | .read_time = at91_rtc_readtime, | ||
300 | .set_time = at91_rtc_settime, | ||
301 | .read_alarm = at91_rtc_readalarm, | ||
302 | .set_alarm = at91_rtc_setalarm, | ||
303 | .proc = at91_rtc_proc, | ||
304 | }; | ||
305 | |||
306 | /* | ||
307 | * Initialize and install RTC driver | ||
308 | */ | ||
309 | static int __init at91_rtc_probe(struct platform_device *pdev) | ||
310 | { | ||
311 | struct resource *r; | ||
312 | struct sam9_rtc *rtc; | ||
313 | int ret; | ||
314 | u32 mr; | ||
315 | |||
316 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
317 | if (!r) | ||
318 | return -ENODEV; | ||
319 | |||
320 | rtc = kzalloc(sizeof *rtc, GFP_KERNEL); | ||
321 | if (!rtc) | ||
322 | return -ENOMEM; | ||
323 | |||
324 | platform_set_drvdata(pdev, rtc); | ||
325 | rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS); | ||
326 | rtc->rtt += r->start; | ||
327 | |||
328 | mr = rtt_readl(rtc, MR); | ||
329 | |||
330 | /* unless RTT is counting at 1 Hz, re-initialize it */ | ||
331 | if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) { | ||
332 | mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES); | ||
333 | gpbr_writel(rtc, 0); | ||
334 | } | ||
335 | |||
336 | /* disable all interrupts (same as on shutdown path) */ | ||
337 | mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
338 | rtt_writel(rtc, MR, mr); | ||
339 | |||
340 | rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | ||
341 | &at91_rtc_ops, THIS_MODULE); | ||
342 | if (IS_ERR(rtc->rtcdev)) { | ||
343 | ret = PTR_ERR(rtc->rtcdev); | ||
344 | goto fail; | ||
345 | } | ||
346 | |||
347 | /* register irq handler after we know what name we'll use */ | ||
348 | ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, | ||
349 | IRQF_DISABLED | IRQF_SHARED, | ||
350 | rtc->rtcdev->dev.bus_id, rtc); | ||
351 | if (ret) { | ||
352 | dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); | ||
353 | rtc_device_unregister(rtc->rtcdev); | ||
354 | goto fail; | ||
355 | } | ||
356 | |||
357 | /* NOTE: sam9260 rev A silicon has a ROM bug which resets the | ||
358 | * RTT on at least some reboots. If you have that chip, you must | ||
359 | * initialize the time from some external source like a GPS, wall | ||
360 | * clock, discrete RTC, etc | ||
361 | */ | ||
362 | |||
363 | if (gpbr_readl(rtc) == 0) | ||
364 | dev_warn(&pdev->dev, "%s: SET TIME!\n", | ||
365 | rtc->rtcdev->dev.bus_id); | ||
366 | |||
367 | return 0; | ||
368 | |||
369 | fail: | ||
370 | platform_set_drvdata(pdev, NULL); | ||
371 | kfree(rtc); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Disable and remove the RTC driver | ||
377 | */ | ||
378 | static int __exit at91_rtc_remove(struct platform_device *pdev) | ||
379 | { | ||
380 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
381 | u32 mr = rtt_readl(rtc, MR); | ||
382 | |||
383 | /* disable all interrupts */ | ||
384 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); | ||
385 | free_irq(AT91_ID_SYS, rtc); | ||
386 | |||
387 | rtc_device_unregister(rtc->rtcdev); | ||
388 | |||
389 | platform_set_drvdata(pdev, NULL); | ||
390 | kfree(rtc); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static void at91_rtc_shutdown(struct platform_device *pdev) | ||
395 | { | ||
396 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
397 | u32 mr = rtt_readl(rtc, MR); | ||
398 | |||
399 | rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
400 | rtt_writel(rtc, MR, mr & ~rtc->imr); | ||
401 | } | ||
402 | |||
403 | #ifdef CONFIG_PM | ||
404 | |||
405 | /* AT91SAM9 RTC Power management control */ | ||
406 | |||
407 | static int at91_rtc_suspend(struct platform_device *pdev, | ||
408 | pm_message_t state) | ||
409 | { | ||
410 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
411 | u32 mr = rtt_readl(rtc, MR); | ||
412 | |||
413 | /* | ||
414 | * This IRQ is shared with DBGU and other hardware which isn't | ||
415 | * necessarily a wakeup event source. | ||
416 | */ | ||
417 | rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
418 | if (rtc->imr) { | ||
419 | if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) { | ||
420 | enable_irq_wake(AT91_ID_SYS); | ||
421 | /* don't let RTTINC cause wakeups */ | ||
422 | if (mr & AT91_RTT_RTTINCIEN) | ||
423 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | ||
424 | } else | ||
425 | rtt_writel(rtc, MR, mr & ~rtc->imr); | ||
426 | } | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int at91_rtc_resume(struct platform_device *pdev) | ||
432 | { | ||
433 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
434 | u32 mr; | ||
435 | |||
436 | if (rtc->imr) { | ||
437 | if (device_may_wakeup(&pdev->dev)) | ||
438 | disable_irq_wake(AT91_ID_SYS); | ||
439 | mr = rtt_readl(rtc, MR); | ||
440 | rtt_writel(rtc, MR, mr | rtc->imr); | ||
441 | } | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | #else | ||
446 | #define at91_rtc_suspend NULL | ||
447 | #define at91_rtc_resume NULL | ||
448 | #endif | ||
449 | |||
450 | static struct platform_driver at91_rtc_driver = { | ||
451 | .driver.name = "rtc-at91sam9", | ||
452 | .driver.owner = THIS_MODULE, | ||
453 | .remove = __exit_p(at91_rtc_remove), | ||
454 | .shutdown = at91_rtc_shutdown, | ||
455 | .suspend = at91_rtc_suspend, | ||
456 | .resume = at91_rtc_resume, | ||
457 | }; | ||
458 | |||
459 | /* Chips can have more than one RTT module, and they can be used for more | ||
460 | * than just RTCs. So we can't just register as "the" RTT driver. | ||
461 | * | ||
462 | * A normal approach in such cases is to create a library to allocate and | ||
463 | * free the modules. Here we just use bus_find_device() as like such a | ||
464 | * library, binding directly ... no runtime "library" footprint is needed. | ||
465 | */ | ||
466 | static int __init at91_rtc_match(struct device *dev, void *v) | ||
467 | { | ||
468 | struct platform_device *pdev = to_platform_device(dev); | ||
469 | int ret; | ||
470 | |||
471 | /* continue searching if this isn't the RTT we need */ | ||
472 | if (strcmp("at91_rtt", pdev->name) != 0 | ||
473 | || pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT) | ||
474 | goto fail; | ||
475 | |||
476 | /* else we found it ... but fail unless we can bind to the RTC driver */ | ||
477 | if (dev->driver) { | ||
478 | dev_dbg(dev, "busy, can't use as RTC!\n"); | ||
479 | goto fail; | ||
480 | } | ||
481 | dev->driver = &at91_rtc_driver.driver; | ||
482 | if (device_attach(dev) == 0) { | ||
483 | dev_dbg(dev, "can't attach RTC!\n"); | ||
484 | goto fail; | ||
485 | } | ||
486 | ret = at91_rtc_probe(pdev); | ||
487 | if (ret == 0) | ||
488 | return true; | ||
489 | |||
490 | dev_dbg(dev, "RTC probe err %d!\n", ret); | ||
491 | fail: | ||
492 | return false; | ||
493 | } | ||
494 | |||
495 | static int __init at91_rtc_init(void) | ||
496 | { | ||
497 | int status; | ||
498 | struct device *rtc; | ||
499 | |||
500 | status = platform_driver_register(&at91_rtc_driver); | ||
501 | if (status) | ||
502 | return status; | ||
503 | rtc = bus_find_device(&platform_bus_type, NULL, | ||
504 | NULL, at91_rtc_match); | ||
505 | if (!rtc) | ||
506 | platform_driver_unregister(&at91_rtc_driver); | ||
507 | return rtc ? 0 : -ENODEV; | ||
508 | } | ||
509 | module_init(at91_rtc_init); | ||
510 | |||
511 | static void __exit at91_rtc_exit(void) | ||
512 | { | ||
513 | platform_driver_unregister(&at91_rtc_driver); | ||
514 | } | ||
515 | module_exit(at91_rtc_exit); | ||
516 | |||
517 | |||
518 | MODULE_AUTHOR("Michel Benoit"); | ||
519 | MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x"); | ||
520 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 1aa709dda0d6..d90ba860d216 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF53[123]/BF53[467]/BF54[2489] | 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] |
4 | * | 4 | * |
5 | * Copyright 2004-2007 Analog Devices Inc. | 5 | * Copyright 2004-2007 Analog Devices Inc. |
6 | * | 6 | * |
@@ -32,26 +32,25 @@ | |||
32 | * writes to clear status registers complete immediately. | 32 | * writes to clear status registers complete immediately. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/bcd.h> | 35 | #include <linux/bcd.h> |
38 | #include <linux/rtc.h> | 36 | #include <linux/completion.h> |
37 | #include <linux/delay.h> | ||
39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/module.h> | ||
40 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> |
43 | #include <linux/rtc.h> | ||
41 | #include <linux/seq_file.h> | 44 | #include <linux/seq_file.h> |
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/spinlock.h> | ||
44 | #include <linux/delay.h> | ||
45 | 45 | ||
46 | #include <asm/blackfin.h> | 46 | #include <asm/blackfin.h> |
47 | 47 | ||
48 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __FUNCTION__, __LINE__, ## args) | 48 | #define dev_dbg_stamp(dev) dev_dbg(dev, "%s:%i: here i am\n", __func__, __LINE__) |
49 | #define stampit() stamp("here i am") | ||
50 | 49 | ||
51 | struct bfin_rtc { | 50 | struct bfin_rtc { |
52 | struct rtc_device *rtc_dev; | 51 | struct rtc_device *rtc_dev; |
53 | struct rtc_time rtc_alarm; | 52 | struct rtc_time rtc_alarm; |
54 | spinlock_t lock; | 53 | u16 rtc_wrote_regs; |
55 | }; | 54 | }; |
56 | 55 | ||
57 | /* Bit values for the ISTAT / ICTL registers */ | 56 | /* Bit values for the ISTAT / ICTL registers */ |
@@ -72,7 +71,7 @@ struct bfin_rtc { | |||
72 | #define SEC_BITS_OFF 0 | 71 | #define SEC_BITS_OFF 0 |
73 | 72 | ||
74 | /* Some helper functions to convert between the common RTC notion of time | 73 | /* Some helper functions to convert between the common RTC notion of time |
75 | * and the internal Blackfin notion that is stored in 32bits. | 74 | * and the internal Blackfin notion that is encoded in 32bits. |
76 | */ | 75 | */ |
77 | static inline u32 rtc_time_to_bfin(unsigned long now) | 76 | static inline u32 rtc_time_to_bfin(unsigned long now) |
78 | { | 77 | { |
@@ -97,7 +96,10 @@ static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm) | |||
97 | rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm); | 96 | rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm); |
98 | } | 97 | } |
99 | 98 | ||
100 | /* Wait for the previous write to a RTC register to complete. | 99 | /** |
100 | * bfin_rtc_sync_pending - make sure pending writes have complete | ||
101 | * | ||
102 | * Wait for the previous write to a RTC register to complete. | ||
101 | * Unfortunately, we can't sleep here as that introduces a race condition when | 103 | * Unfortunately, we can't sleep here as that introduces a race condition when |
102 | * turning on interrupt events. Consider this: | 104 | * turning on interrupt events. Consider this: |
103 | * - process sets alarm | 105 | * - process sets alarm |
@@ -112,188 +114,202 @@ static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm) | |||
112 | * If anyone can point out the obvious solution here, i'm listening :). This | 114 | * If anyone can point out the obvious solution here, i'm listening :). This |
113 | * shouldn't be an issue on an SMP or preempt system as this function should | 115 | * shouldn't be an issue on an SMP or preempt system as this function should |
114 | * only be called with the rtc lock held. | 116 | * only be called with the rtc lock held. |
117 | * | ||
118 | * Other options: | ||
119 | * - disable PREN so the sync happens at 32.768kHZ ... but this changes the | ||
120 | * inc rate for all RTC registers from 1HZ to 32.768kHZ ... | ||
121 | * - use the write complete IRQ | ||
115 | */ | 122 | */ |
116 | static void rtc_bfin_sync_pending(void) | 123 | /* |
124 | static void bfin_rtc_sync_pending_polled(void) | ||
117 | { | 125 | { |
118 | stampit(); | 126 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) |
119 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) { | ||
120 | if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)) | 127 | if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)) |
121 | break; | 128 | break; |
122 | } | ||
123 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 129 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); |
124 | } | 130 | } |
131 | */ | ||
132 | static DECLARE_COMPLETION(bfin_write_complete); | ||
133 | static void bfin_rtc_sync_pending(struct device *dev) | ||
134 | { | ||
135 | dev_dbg_stamp(dev); | ||
136 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | ||
137 | wait_for_completion_timeout(&bfin_write_complete, HZ * 5); | ||
138 | dev_dbg_stamp(dev); | ||
139 | } | ||
125 | 140 | ||
126 | static void rtc_bfin_reset(struct bfin_rtc *rtc) | 141 | /** |
142 | * bfin_rtc_reset - set RTC to sane/known state | ||
143 | * | ||
144 | * Initialize the RTC. Enable pre-scaler to scale RTC clock | ||
145 | * to 1Hz and clear interrupt/status registers. | ||
146 | */ | ||
147 | static void bfin_rtc_reset(struct device *dev) | ||
127 | { | 148 | { |
128 | /* Initialize the RTC. Enable pre-scaler to scale RTC clock | 149 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
129 | * to 1Hz and clear interrupt/status registers. */ | 150 | dev_dbg_stamp(dev); |
130 | spin_lock_irq(&rtc->lock); | 151 | bfin_rtc_sync_pending(dev); |
131 | rtc_bfin_sync_pending(); | ||
132 | bfin_write_RTC_PREN(0x1); | 152 | bfin_write_RTC_PREN(0x1); |
133 | bfin_write_RTC_ICTL(0); | 153 | bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE); |
134 | bfin_write_RTC_SWCNT(0); | 154 | bfin_write_RTC_SWCNT(0); |
135 | bfin_write_RTC_ALARM(0); | 155 | bfin_write_RTC_ALARM(0); |
136 | bfin_write_RTC_ISTAT(0xFFFF); | 156 | bfin_write_RTC_ISTAT(0xFFFF); |
137 | spin_unlock_irq(&rtc->lock); | 157 | rtc->rtc_wrote_regs = 0; |
138 | } | 158 | } |
139 | 159 | ||
160 | /** | ||
161 | * bfin_rtc_interrupt - handle interrupt from RTC | ||
162 | * | ||
163 | * Since we handle all RTC events here, we have to make sure the requested | ||
164 | * interrupt is enabled (in RTC_ICTL) as the event status register (RTC_ISTAT) | ||
165 | * always gets updated regardless of the interrupt being enabled. So when one | ||
166 | * even we care about (e.g. stopwatch) goes off, we don't want to turn around | ||
167 | * and say that other events have happened as well (e.g. second). We do not | ||
168 | * have to worry about pending writes to the RTC_ICTL register as interrupts | ||
169 | * only fire if they are enabled in the RTC_ICTL register. | ||
170 | */ | ||
140 | static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | 171 | static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) |
141 | { | 172 | { |
142 | struct platform_device *pdev = to_platform_device(dev_id); | 173 | struct device *dev = dev_id; |
143 | struct bfin_rtc *rtc = platform_get_drvdata(pdev); | 174 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
144 | unsigned long events = 0; | 175 | unsigned long events = 0; |
145 | u16 rtc_istat; | 176 | bool write_complete = false; |
146 | 177 | u16 rtc_istat, rtc_ictl; | |
147 | stampit(); | ||
148 | 178 | ||
149 | spin_lock_irq(&rtc->lock); | 179 | dev_dbg_stamp(dev); |
150 | 180 | ||
151 | rtc_istat = bfin_read_RTC_ISTAT(); | 181 | rtc_istat = bfin_read_RTC_ISTAT(); |
182 | rtc_ictl = bfin_read_RTC_ICTL(); | ||
152 | 183 | ||
153 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 184 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { |
154 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 185 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); |
155 | events |= RTC_AF | RTC_IRQF; | 186 | write_complete = true; |
187 | complete(&bfin_write_complete); | ||
156 | } | 188 | } |
157 | 189 | ||
158 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { | 190 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { |
159 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | 191 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { |
160 | events |= RTC_PF | RTC_IRQF; | 192 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
161 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | 193 | events |= RTC_AF | RTC_IRQF; |
194 | } | ||
162 | } | 195 | } |
163 | 196 | ||
164 | if (rtc_istat & RTC_ISTAT_SEC) { | 197 | if (rtc_ictl & RTC_ISTAT_STOPWATCH) { |
165 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 198 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { |
166 | events |= RTC_UF | RTC_IRQF; | 199 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); |
200 | events |= RTC_PF | RTC_IRQF; | ||
201 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
202 | } | ||
167 | } | 203 | } |
168 | 204 | ||
169 | rtc_update_irq(rtc->rtc_dev, 1, events); | 205 | if (rtc_ictl & RTC_ISTAT_SEC) { |
206 | if (rtc_istat & RTC_ISTAT_SEC) { | ||
207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | ||
208 | events |= RTC_UF | RTC_IRQF; | ||
209 | } | ||
210 | } | ||
170 | 211 | ||
171 | spin_unlock_irq(&rtc->lock); | 212 | if (events) |
213 | rtc_update_irq(rtc->rtc_dev, 1, events); | ||
172 | 214 | ||
173 | return IRQ_HANDLED; | 215 | if (write_complete || events) |
216 | return IRQ_HANDLED; | ||
217 | else | ||
218 | return IRQ_NONE; | ||
174 | } | 219 | } |
175 | 220 | ||
176 | static int bfin_rtc_open(struct device *dev) | 221 | static int bfin_rtc_open(struct device *dev) |
177 | { | 222 | { |
178 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | ||
179 | int ret; | 223 | int ret; |
180 | 224 | ||
181 | stampit(); | 225 | dev_dbg_stamp(dev); |
182 | 226 | ||
183 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_DISABLED, "rtc-bfin", dev); | 227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); |
184 | if (unlikely(ret)) { | 228 | if (!ret) |
185 | dev_err(dev, "request RTC IRQ failed with %d\n", ret); | 229 | bfin_rtc_reset(dev); |
186 | return ret; | ||
187 | } | ||
188 | |||
189 | rtc_bfin_reset(rtc); | ||
190 | 230 | ||
191 | return ret; | 231 | return ret; |
192 | } | 232 | } |
193 | 233 | ||
194 | static void bfin_rtc_release(struct device *dev) | 234 | static void bfin_rtc_release(struct device *dev) |
195 | { | 235 | { |
196 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 236 | dev_dbg_stamp(dev); |
197 | stampit(); | 237 | bfin_rtc_reset(dev); |
198 | rtc_bfin_reset(rtc); | ||
199 | free_irq(IRQ_RTC, dev); | 238 | free_irq(IRQ_RTC, dev); |
200 | } | 239 | } |
201 | 240 | ||
241 | static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int) | ||
242 | { | ||
243 | bfin_write_RTC_ISTAT(rtc_int); | ||
244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); | ||
245 | } | ||
246 | static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int) | ||
247 | { | ||
248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); | ||
249 | } | ||
250 | static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) | ||
251 | { | ||
252 | /* Blackfin has different bits for whether the alarm is | ||
253 | * more than 24 hours away. | ||
254 | */ | ||
255 | bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY)); | ||
256 | } | ||
202 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 257 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
203 | { | 258 | { |
204 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 259 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
260 | int ret = 0; | ||
261 | |||
262 | dev_dbg_stamp(dev); | ||
205 | 263 | ||
206 | stampit(); | 264 | bfin_rtc_sync_pending(dev); |
207 | 265 | ||
208 | switch (cmd) { | 266 | switch (cmd) { |
209 | case RTC_PIE_ON: | 267 | case RTC_PIE_ON: |
210 | stampit(); | 268 | dev_dbg_stamp(dev); |
211 | spin_lock_irq(&rtc->lock); | 269 | bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); |
212 | rtc_bfin_sync_pending(); | ||
213 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | ||
214 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | 270 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); |
215 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_STOPWATCH); | 271 | break; |
216 | spin_unlock_irq(&rtc->lock); | ||
217 | return 0; | ||
218 | case RTC_PIE_OFF: | 272 | case RTC_PIE_OFF: |
219 | stampit(); | 273 | dev_dbg_stamp(dev); |
220 | spin_lock_irq(&rtc->lock); | 274 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH); |
221 | rtc_bfin_sync_pending(); | 275 | break; |
222 | bfin_write_RTC_SWCNT(0); | ||
223 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_STOPWATCH); | ||
224 | spin_unlock_irq(&rtc->lock); | ||
225 | return 0; | ||
226 | 276 | ||
227 | case RTC_UIE_ON: | 277 | case RTC_UIE_ON: |
228 | stampit(); | 278 | dev_dbg_stamp(dev); |
229 | spin_lock_irq(&rtc->lock); | 279 | bfin_rtc_int_set(rtc, RTC_ISTAT_SEC); |
230 | rtc_bfin_sync_pending(); | 280 | break; |
231 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | ||
232 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_SEC); | ||
233 | spin_unlock_irq(&rtc->lock); | ||
234 | return 0; | ||
235 | case RTC_UIE_OFF: | 281 | case RTC_UIE_OFF: |
236 | stampit(); | 282 | dev_dbg_stamp(dev); |
237 | spin_lock_irq(&rtc->lock); | 283 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC); |
238 | rtc_bfin_sync_pending(); | 284 | break; |
239 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_SEC); | 285 | |
240 | spin_unlock_irq(&rtc->lock); | 286 | case RTC_AIE_ON: |
241 | return 0; | 287 | dev_dbg_stamp(dev); |
242 | 288 | bfin_rtc_int_set_alarm(rtc); | |
243 | case RTC_AIE_ON: { | 289 | break; |
244 | unsigned long rtc_alarm; | ||
245 | u16 which_alarm; | ||
246 | int ret = 0; | ||
247 | |||
248 | stampit(); | ||
249 | |||
250 | spin_lock_irq(&rtc->lock); | ||
251 | |||
252 | rtc_bfin_sync_pending(); | ||
253 | if (rtc->rtc_alarm.tm_yday == -1) { | ||
254 | struct rtc_time now; | ||
255 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), &now); | ||
256 | now.tm_sec = rtc->rtc_alarm.tm_sec; | ||
257 | now.tm_min = rtc->rtc_alarm.tm_min; | ||
258 | now.tm_hour = rtc->rtc_alarm.tm_hour; | ||
259 | ret = rtc_tm_to_time(&now, &rtc_alarm); | ||
260 | which_alarm = RTC_ISTAT_ALARM; | ||
261 | } else { | ||
262 | ret = rtc_tm_to_time(&rtc->rtc_alarm, &rtc_alarm); | ||
263 | which_alarm = RTC_ISTAT_ALARM_DAY; | ||
264 | } | ||
265 | if (ret == 0) { | ||
266 | bfin_write_RTC_ISTAT(which_alarm); | ||
267 | bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm)); | ||
268 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | which_alarm); | ||
269 | } | ||
270 | |||
271 | spin_unlock_irq(&rtc->lock); | ||
272 | |||
273 | return ret; | ||
274 | } | ||
275 | case RTC_AIE_OFF: | 290 | case RTC_AIE_OFF: |
276 | stampit(); | 291 | dev_dbg_stamp(dev); |
277 | spin_lock_irq(&rtc->lock); | 292 | bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); |
278 | rtc_bfin_sync_pending(); | 293 | break; |
279 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 294 | |
280 | spin_unlock_irq(&rtc->lock); | 295 | default: |
281 | return 0; | 296 | dev_dbg_stamp(dev); |
297 | ret = -ENOIOCTLCMD; | ||
282 | } | 298 | } |
283 | 299 | ||
284 | return -ENOIOCTLCMD; | 300 | return ret; |
285 | } | 301 | } |
286 | 302 | ||
287 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) | 303 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) |
288 | { | 304 | { |
289 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 305 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
290 | 306 | ||
291 | stampit(); | 307 | dev_dbg_stamp(dev); |
308 | |||
309 | if (rtc->rtc_wrote_regs & 0x1) | ||
310 | bfin_rtc_sync_pending(dev); | ||
292 | 311 | ||
293 | spin_lock_irq(&rtc->lock); | ||
294 | rtc_bfin_sync_pending(); | ||
295 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm); | 312 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm); |
296 | spin_unlock_irq(&rtc->lock); | ||
297 | 313 | ||
298 | return 0; | 314 | return 0; |
299 | } | 315 | } |
@@ -304,64 +320,79 @@ static int bfin_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
304 | int ret; | 320 | int ret; |
305 | unsigned long now; | 321 | unsigned long now; |
306 | 322 | ||
307 | stampit(); | 323 | dev_dbg_stamp(dev); |
308 | |||
309 | spin_lock_irq(&rtc->lock); | ||
310 | 324 | ||
311 | ret = rtc_tm_to_time(tm, &now); | 325 | ret = rtc_tm_to_time(tm, &now); |
312 | if (ret == 0) { | 326 | if (ret == 0) { |
313 | rtc_bfin_sync_pending(); | 327 | if (rtc->rtc_wrote_regs & 0x1) |
328 | bfin_rtc_sync_pending(dev); | ||
314 | bfin_write_RTC_STAT(rtc_time_to_bfin(now)); | 329 | bfin_write_RTC_STAT(rtc_time_to_bfin(now)); |
330 | rtc->rtc_wrote_regs = 0x1; | ||
315 | } | 331 | } |
316 | 332 | ||
317 | spin_unlock_irq(&rtc->lock); | ||
318 | |||
319 | return ret; | 333 | return ret; |
320 | } | 334 | } |
321 | 335 | ||
322 | static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 336 | static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
323 | { | 337 | { |
324 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 338 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
325 | stampit(); | 339 | dev_dbg_stamp(dev); |
326 | memcpy(&alrm->time, &rtc->rtc_alarm, sizeof(struct rtc_time)); | 340 | alrm->time = rtc->rtc_alarm; |
327 | alrm->pending = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 341 | bfin_rtc_sync_pending(dev); |
342 | alrm->enabled = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | ||
328 | return 0; | 343 | return 0; |
329 | } | 344 | } |
330 | 345 | ||
331 | static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 346 | static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
332 | { | 347 | { |
333 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 348 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
334 | stampit(); | 349 | unsigned long rtc_alarm; |
335 | memcpy(&rtc->rtc_alarm, &alrm->time, sizeof(struct rtc_time)); | 350 | |
351 | dev_dbg_stamp(dev); | ||
352 | |||
353 | if (rtc_tm_to_time(&alrm->time, &rtc_alarm)) | ||
354 | return -EINVAL; | ||
355 | |||
356 | rtc->rtc_alarm = alrm->time; | ||
357 | |||
358 | bfin_rtc_sync_pending(dev); | ||
359 | bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm)); | ||
360 | if (alrm->enabled) | ||
361 | bfin_rtc_int_set_alarm(rtc); | ||
362 | |||
336 | return 0; | 363 | return 0; |
337 | } | 364 | } |
338 | 365 | ||
339 | static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | 366 | static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) |
340 | { | 367 | { |
341 | #define yesno(x) (x ? "yes" : "no") | 368 | #define yesno(x) ((x) ? "yes" : "no") |
342 | u16 ictl = bfin_read_RTC_ICTL(); | 369 | u16 ictl = bfin_read_RTC_ICTL(); |
343 | stampit(); | 370 | dev_dbg_stamp(dev); |
344 | seq_printf(seq, "alarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM)); | 371 | seq_printf(seq, |
345 | seq_printf(seq, "wkalarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM_DAY)); | 372 | "alarm_IRQ\t: %s\n" |
346 | seq_printf(seq, "seconds_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_SEC)); | 373 | "wkalarm_IRQ\t: %s\n" |
347 | seq_printf(seq, "periodic_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_STOPWATCH)); | 374 | "seconds_IRQ\t: %s\n" |
348 | #ifdef DEBUG | 375 | "periodic_IRQ\t: %s\n", |
349 | seq_printf(seq, "RTC_STAT\t: 0x%08X\n", bfin_read_RTC_STAT()); | 376 | yesno(ictl & RTC_ISTAT_ALARM), |
350 | seq_printf(seq, "RTC_ICTL\t: 0x%04X\n", bfin_read_RTC_ICTL()); | 377 | yesno(ictl & RTC_ISTAT_ALARM_DAY), |
351 | seq_printf(seq, "RTC_ISTAT\t: 0x%04X\n", bfin_read_RTC_ISTAT()); | 378 | yesno(ictl & RTC_ISTAT_SEC), |
352 | seq_printf(seq, "RTC_SWCNT\t: 0x%04X\n", bfin_read_RTC_SWCNT()); | 379 | yesno(ictl & RTC_ISTAT_STOPWATCH)); |
353 | seq_printf(seq, "RTC_ALARM\t: 0x%08X\n", bfin_read_RTC_ALARM()); | ||
354 | seq_printf(seq, "RTC_PREN\t: 0x%04X\n", bfin_read_RTC_PREN()); | ||
355 | #endif | ||
356 | return 0; | 380 | return 0; |
381 | #undef yesno | ||
357 | } | 382 | } |
358 | 383 | ||
384 | /** | ||
385 | * bfin_irq_set_freq - make sure hardware supports requested freq | ||
386 | * @dev: pointer to RTC device structure | ||
387 | * @freq: requested frequency rate | ||
388 | * | ||
389 | * The Blackfin RTC can only generate periodic events at 1 per | ||
390 | * second (1 Hz), so reject any attempt at changing it. | ||
391 | */ | ||
359 | static int bfin_irq_set_freq(struct device *dev, int freq) | 392 | static int bfin_irq_set_freq(struct device *dev, int freq) |
360 | { | 393 | { |
361 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 394 | dev_dbg_stamp(dev); |
362 | stampit(); | 395 | return -ENOTTY; |
363 | rtc->rtc_dev->irq_freq = freq; | ||
364 | return 0; | ||
365 | } | 396 | } |
366 | 397 | ||
367 | static struct rtc_class_ops bfin_rtc_ops = { | 398 | static struct rtc_class_ops bfin_rtc_ops = { |
@@ -381,27 +412,24 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
381 | struct bfin_rtc *rtc; | 412 | struct bfin_rtc *rtc; |
382 | int ret = 0; | 413 | int ret = 0; |
383 | 414 | ||
384 | stampit(); | 415 | dev_dbg_stamp(&pdev->dev); |
385 | 416 | ||
386 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 417 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
387 | if (unlikely(!rtc)) | 418 | if (unlikely(!rtc)) |
388 | return -ENOMEM; | 419 | return -ENOMEM; |
389 | 420 | ||
390 | spin_lock_init(&rtc->lock); | ||
391 | |||
392 | rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); | 421 | rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); |
393 | if (unlikely(IS_ERR(rtc))) { | 422 | if (unlikely(IS_ERR(rtc))) { |
394 | ret = PTR_ERR(rtc->rtc_dev); | 423 | ret = PTR_ERR(rtc->rtc_dev); |
395 | goto err; | 424 | goto err; |
396 | } | 425 | } |
397 | rtc->rtc_dev->irq_freq = 0; | 426 | rtc->rtc_dev->irq_freq = 1; |
398 | rtc->rtc_dev->max_user_freq = (2 << 16); /* stopwatch is an unsigned 16 bit reg */ | ||
399 | 427 | ||
400 | platform_set_drvdata(pdev, rtc); | 428 | platform_set_drvdata(pdev, rtc); |
401 | 429 | ||
402 | return 0; | 430 | return 0; |
403 | 431 | ||
404 | err: | 432 | err: |
405 | kfree(rtc); | 433 | kfree(rtc); |
406 | return ret; | 434 | return ret; |
407 | } | 435 | } |
@@ -428,7 +456,6 @@ static struct platform_driver bfin_rtc_driver = { | |||
428 | 456 | ||
429 | static int __init bfin_rtc_init(void) | 457 | static int __init bfin_rtc_init(void) |
430 | { | 458 | { |
431 | stampit(); | ||
432 | return platform_driver_register(&bfin_rtc_driver); | 459 | return platform_driver_register(&bfin_rtc_driver); |
433 | } | 460 | } |
434 | 461 | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 29cf1457ca10..e059f94c79eb 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -36,9 +36,24 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
38 | 38 | ||
39 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
40 | #include <asm/hpet.h> | ||
41 | #endif | ||
42 | |||
39 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
40 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
41 | 45 | ||
46 | #ifndef CONFIG_HPET_EMULATE_RTC | ||
47 | #define is_hpet_enabled() 0 | ||
48 | #define hpet_set_alarm_time(hrs, min, sec) do { } while (0) | ||
49 | #define hpet_set_periodic_freq(arg) 0 | ||
50 | #define hpet_mask_rtc_irq_bit(arg) do { } while (0) | ||
51 | #define hpet_set_rtc_irq_bit(arg) do { } while (0) | ||
52 | #define hpet_rtc_timer_init() do { } while (0) | ||
53 | #define hpet_register_irq_handler(h) 0 | ||
54 | #define hpet_unregister_irq_handler(h) do { } while (0) | ||
55 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | ||
56 | #endif | ||
42 | 57 | ||
43 | struct cmos_rtc { | 58 | struct cmos_rtc { |
44 | struct rtc_device *rtc; | 59 | struct rtc_device *rtc; |
@@ -199,6 +214,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
199 | sec = t->time.tm_sec; | 214 | sec = t->time.tm_sec; |
200 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; | 215 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; |
201 | 216 | ||
217 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); | ||
202 | spin_lock_irq(&rtc_lock); | 218 | spin_lock_irq(&rtc_lock); |
203 | 219 | ||
204 | /* next rtc irq must not be from previous alarm setting */ | 220 | /* next rtc irq must not be from previous alarm setting */ |
@@ -252,7 +268,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
252 | f = 16 - f; | 268 | f = 16 - f; |
253 | 269 | ||
254 | spin_lock_irqsave(&rtc_lock, flags); | 270 | spin_lock_irqsave(&rtc_lock, flags); |
255 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 271 | if (!hpet_set_periodic_freq(freq)) |
272 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | ||
256 | spin_unlock_irqrestore(&rtc_lock, flags); | 273 | spin_unlock_irqrestore(&rtc_lock, flags); |
257 | 274 | ||
258 | return 0; | 275 | return 0; |
@@ -314,28 +331,37 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
314 | switch (cmd) { | 331 | switch (cmd) { |
315 | case RTC_AIE_OFF: /* alarm off */ | 332 | case RTC_AIE_OFF: /* alarm off */ |
316 | rtc_control &= ~RTC_AIE; | 333 | rtc_control &= ~RTC_AIE; |
334 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
317 | break; | 335 | break; |
318 | case RTC_AIE_ON: /* alarm on */ | 336 | case RTC_AIE_ON: /* alarm on */ |
319 | rtc_control |= RTC_AIE; | 337 | rtc_control |= RTC_AIE; |
338 | hpet_set_rtc_irq_bit(RTC_AIE); | ||
320 | break; | 339 | break; |
321 | case RTC_UIE_OFF: /* update off */ | 340 | case RTC_UIE_OFF: /* update off */ |
322 | rtc_control &= ~RTC_UIE; | 341 | rtc_control &= ~RTC_UIE; |
342 | hpet_mask_rtc_irq_bit(RTC_UIE); | ||
323 | break; | 343 | break; |
324 | case RTC_UIE_ON: /* update on */ | 344 | case RTC_UIE_ON: /* update on */ |
325 | rtc_control |= RTC_UIE; | 345 | rtc_control |= RTC_UIE; |
346 | hpet_set_rtc_irq_bit(RTC_UIE); | ||
326 | break; | 347 | break; |
327 | case RTC_PIE_OFF: /* periodic off */ | 348 | case RTC_PIE_OFF: /* periodic off */ |
328 | rtc_control &= ~RTC_PIE; | 349 | rtc_control &= ~RTC_PIE; |
350 | hpet_mask_rtc_irq_bit(RTC_PIE); | ||
329 | break; | 351 | break; |
330 | case RTC_PIE_ON: /* periodic on */ | 352 | case RTC_PIE_ON: /* periodic on */ |
331 | rtc_control |= RTC_PIE; | 353 | rtc_control |= RTC_PIE; |
354 | hpet_set_rtc_irq_bit(RTC_PIE); | ||
332 | break; | 355 | break; |
333 | } | 356 | } |
334 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 357 | if (!is_hpet_enabled()) |
358 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
359 | |||
335 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 360 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
336 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 361 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
337 | if (is_intr(rtc_intr)) | 362 | if (is_intr(rtc_intr)) |
338 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | 363 | rtc_update_irq(cmos->rtc, 1, rtc_intr); |
364 | |||
339 | spin_unlock_irqrestore(&rtc_lock, flags); | 365 | spin_unlock_irqrestore(&rtc_lock, flags); |
340 | return 0; | 366 | return 0; |
341 | } | 367 | } |
@@ -393,15 +419,111 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
393 | 419 | ||
394 | /*----------------------------------------------------------------*/ | 420 | /*----------------------------------------------------------------*/ |
395 | 421 | ||
422 | /* | ||
423 | * All these chips have at least 64 bytes of address space, shared by | ||
424 | * RTC registers and NVRAM. Most of those bytes of NVRAM are used | ||
425 | * by boot firmware. Modern chips have 128 or 256 bytes. | ||
426 | */ | ||
427 | |||
428 | #define NVRAM_OFFSET (RTC_REG_D + 1) | ||
429 | |||
430 | static ssize_t | ||
431 | cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | ||
432 | char *buf, loff_t off, size_t count) | ||
433 | { | ||
434 | int retval; | ||
435 | |||
436 | if (unlikely(off >= attr->size)) | ||
437 | return 0; | ||
438 | if ((off + count) > attr->size) | ||
439 | count = attr->size - off; | ||
440 | |||
441 | spin_lock_irq(&rtc_lock); | ||
442 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) | ||
443 | *buf++ = CMOS_READ(off); | ||
444 | spin_unlock_irq(&rtc_lock); | ||
445 | |||
446 | return retval; | ||
447 | } | ||
448 | |||
449 | static ssize_t | ||
450 | cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | ||
451 | char *buf, loff_t off, size_t count) | ||
452 | { | ||
453 | struct cmos_rtc *cmos; | ||
454 | int retval; | ||
455 | |||
456 | cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
457 | if (unlikely(off >= attr->size)) | ||
458 | return -EFBIG; | ||
459 | if ((off + count) > attr->size) | ||
460 | count = attr->size - off; | ||
461 | |||
462 | /* NOTE: on at least PCs and Ataris, the boot firmware uses a | ||
463 | * checksum on part of the NVRAM data. That's currently ignored | ||
464 | * here. If userspace is smart enough to know what fields of | ||
465 | * NVRAM to update, updating checksums is also part of its job. | ||
466 | */ | ||
467 | spin_lock_irq(&rtc_lock); | ||
468 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) { | ||
469 | /* don't trash RTC registers */ | ||
470 | if (off == cmos->day_alrm | ||
471 | || off == cmos->mon_alrm | ||
472 | || off == cmos->century) | ||
473 | buf++; | ||
474 | else | ||
475 | CMOS_WRITE(*buf++, off); | ||
476 | } | ||
477 | spin_unlock_irq(&rtc_lock); | ||
478 | |||
479 | return retval; | ||
480 | } | ||
481 | |||
482 | static struct bin_attribute nvram = { | ||
483 | .attr = { | ||
484 | .name = "nvram", | ||
485 | .mode = S_IRUGO | S_IWUSR, | ||
486 | .owner = THIS_MODULE, | ||
487 | }, | ||
488 | |||
489 | .read = cmos_nvram_read, | ||
490 | .write = cmos_nvram_write, | ||
491 | /* size gets set up later */ | ||
492 | }; | ||
493 | |||
494 | /*----------------------------------------------------------------*/ | ||
495 | |||
396 | static struct cmos_rtc cmos_rtc; | 496 | static struct cmos_rtc cmos_rtc; |
397 | 497 | ||
398 | static irqreturn_t cmos_interrupt(int irq, void *p) | 498 | static irqreturn_t cmos_interrupt(int irq, void *p) |
399 | { | 499 | { |
400 | u8 irqstat; | 500 | u8 irqstat; |
501 | u8 rtc_control; | ||
401 | 502 | ||
402 | spin_lock(&rtc_lock); | 503 | spin_lock(&rtc_lock); |
403 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | 504 | /* |
404 | irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF; | 505 | * In this case it is HPET RTC interrupt handler |
506 | * calling us, with the interrupt information | ||
507 | * passed as arg1, instead of irq. | ||
508 | */ | ||
509 | if (is_hpet_enabled()) | ||
510 | irqstat = (unsigned long)irq & 0xF0; | ||
511 | else { | ||
512 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
513 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
514 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
515 | } | ||
516 | |||
517 | /* All Linux RTC alarms should be treated as if they were oneshot. | ||
518 | * Similar code may be needed in system wakeup paths, in case the | ||
519 | * alarm woke the system. | ||
520 | */ | ||
521 | if (irqstat & RTC_AIE) { | ||
522 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
523 | rtc_control &= ~RTC_AIE; | ||
524 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
525 | CMOS_READ(RTC_INTR_FLAGS); | ||
526 | } | ||
405 | spin_unlock(&rtc_lock); | 527 | spin_unlock(&rtc_lock); |
406 | 528 | ||
407 | if (is_intr(irqstat)) { | 529 | if (is_intr(irqstat)) { |
@@ -412,11 +534,9 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
412 | } | 534 | } |
413 | 535 | ||
414 | #ifdef CONFIG_PNP | 536 | #ifdef CONFIG_PNP |
415 | #define is_pnp() 1 | ||
416 | #define INITSECTION | 537 | #define INITSECTION |
417 | 538 | ||
418 | #else | 539 | #else |
419 | #define is_pnp() 0 | ||
420 | #define INITSECTION __init | 540 | #define INITSECTION __init |
421 | #endif | 541 | #endif |
422 | 542 | ||
@@ -426,6 +546,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
426 | struct cmos_rtc_board_info *info = dev->platform_data; | 546 | struct cmos_rtc_board_info *info = dev->platform_data; |
427 | int retval = 0; | 547 | int retval = 0; |
428 | unsigned char rtc_control; | 548 | unsigned char rtc_control; |
549 | unsigned address_space; | ||
429 | 550 | ||
430 | /* there can be only one ... */ | 551 | /* there can be only one ... */ |
431 | if (cmos_rtc.dev) | 552 | if (cmos_rtc.dev) |
@@ -450,15 +571,36 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
450 | cmos_rtc.irq = rtc_irq; | 571 | cmos_rtc.irq = rtc_irq; |
451 | cmos_rtc.iomem = ports; | 572 | cmos_rtc.iomem = ports; |
452 | 573 | ||
574 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM | ||
575 | * driver did, but don't reject unknown configs. Old hardware | ||
576 | * won't address 128 bytes, and for now we ignore the way newer | ||
577 | * chips can address 256 bytes (using two more i/o ports). | ||
578 | */ | ||
579 | #if defined(CONFIG_ATARI) | ||
580 | address_space = 64; | ||
581 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) | ||
582 | address_space = 128; | ||
583 | #else | ||
584 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | ||
585 | address_space = 128; | ||
586 | #endif | ||
587 | |||
453 | /* For ACPI systems extension info comes from the FADT. On others, | 588 | /* For ACPI systems extension info comes from the FADT. On others, |
454 | * board specific setup provides it as appropriate. Systems where | 589 | * board specific setup provides it as appropriate. Systems where |
455 | * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and | 590 | * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and |
456 | * some almost-clones) can provide hooks to make that behave. | 591 | * some almost-clones) can provide hooks to make that behave. |
592 | * | ||
593 | * Note that ACPI doesn't preclude putting these registers into | ||
594 | * "extended" areas of the chip, including some that we won't yet | ||
595 | * expect CMOS_READ and friends to handle. | ||
457 | */ | 596 | */ |
458 | if (info) { | 597 | if (info) { |
459 | cmos_rtc.day_alrm = info->rtc_day_alarm; | 598 | if (info->rtc_day_alarm && info->rtc_day_alarm < 128) |
460 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; | 599 | cmos_rtc.day_alrm = info->rtc_day_alarm; |
461 | cmos_rtc.century = info->rtc_century; | 600 | if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) |
601 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; | ||
602 | if (info->rtc_century && info->rtc_century < 128) | ||
603 | cmos_rtc.century = info->rtc_century; | ||
462 | 604 | ||
463 | if (info->wake_on && info->wake_off) { | 605 | if (info->wake_on && info->wake_off) { |
464 | cmos_rtc.wake_on = info->wake_on; | 606 | cmos_rtc.wake_on = info->wake_on; |
@@ -485,8 +627,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
485 | * doesn't use 32KHz here ... for portability we might need to | 627 | * doesn't use 32KHz here ... for portability we might need to |
486 | * do something about other clock frequencies. | 628 | * do something about other clock frequencies. |
487 | */ | 629 | */ |
488 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
489 | cmos_rtc.rtc->irq_freq = 1024; | 630 | cmos_rtc.rtc->irq_freq = 1024; |
631 | if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq)) | ||
632 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
490 | 633 | ||
491 | /* disable irqs. | 634 | /* disable irqs. |
492 | * | 635 | * |
@@ -509,19 +652,39 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
509 | goto cleanup1; | 652 | goto cleanup1; |
510 | } | 653 | } |
511 | 654 | ||
512 | if (is_valid_irq(rtc_irq)) | 655 | if (is_valid_irq(rtc_irq)) { |
513 | retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED, | 656 | irq_handler_t rtc_cmos_int_handler; |
514 | cmos_rtc.rtc->dev.bus_id, | 657 | |
658 | if (is_hpet_enabled()) { | ||
659 | int err; | ||
660 | |||
661 | rtc_cmos_int_handler = hpet_rtc_interrupt; | ||
662 | err = hpet_register_irq_handler(cmos_interrupt); | ||
663 | if (err != 0) { | ||
664 | printk(KERN_WARNING "hpet_register_irq_handler " | ||
665 | " failed in rtc_init()."); | ||
666 | goto cleanup1; | ||
667 | } | ||
668 | } else | ||
669 | rtc_cmos_int_handler = cmos_interrupt; | ||
670 | |||
671 | retval = request_irq(rtc_irq, rtc_cmos_int_handler, | ||
672 | IRQF_DISABLED, cmos_rtc.rtc->dev.bus_id, | ||
515 | cmos_rtc.rtc); | 673 | cmos_rtc.rtc); |
516 | if (retval < 0) { | 674 | if (retval < 0) { |
517 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); | 675 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); |
518 | goto cleanup1; | 676 | goto cleanup1; |
677 | } | ||
519 | } | 678 | } |
679 | hpet_rtc_timer_init(); | ||
520 | 680 | ||
521 | /* REVISIT optionally make 50 or 114 bytes NVRAM available, | 681 | /* export at least the first block of NVRAM */ |
522 | * like rtc-ds1553, rtc-ds1742 ... this will often include | 682 | nvram.size = address_space - NVRAM_OFFSET; |
523 | * registers for century, and day/month alarm. | 683 | retval = sysfs_create_bin_file(&dev->kobj, &nvram); |
524 | */ | 684 | if (retval < 0) { |
685 | dev_dbg(dev, "can't create nvram file? %d\n", retval); | ||
686 | goto cleanup2; | ||
687 | } | ||
525 | 688 | ||
526 | pr_info("%s: alarms up to one %s%s\n", | 689 | pr_info("%s: alarms up to one %s%s\n", |
527 | cmos_rtc.rtc->dev.bus_id, | 690 | cmos_rtc.rtc->dev.bus_id, |
@@ -536,6 +699,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
536 | 699 | ||
537 | return 0; | 700 | return 0; |
538 | 701 | ||
702 | cleanup2: | ||
703 | if (is_valid_irq(rtc_irq)) | ||
704 | free_irq(rtc_irq, cmos_rtc.rtc); | ||
539 | cleanup1: | 705 | cleanup1: |
540 | cmos_rtc.dev = NULL; | 706 | cmos_rtc.dev = NULL; |
541 | rtc_device_unregister(cmos_rtc.rtc); | 707 | rtc_device_unregister(cmos_rtc.rtc); |
@@ -563,8 +729,12 @@ static void __exit cmos_do_remove(struct device *dev) | |||
563 | 729 | ||
564 | cmos_do_shutdown(); | 730 | cmos_do_shutdown(); |
565 | 731 | ||
566 | if (is_valid_irq(cmos->irq)) | 732 | sysfs_remove_bin_file(&dev->kobj, &nvram); |
733 | |||
734 | if (is_valid_irq(cmos->irq)) { | ||
567 | free_irq(cmos->irq, cmos->rtc); | 735 | free_irq(cmos->irq, cmos->rtc); |
736 | hpet_unregister_irq_handler(cmos_interrupt); | ||
737 | } | ||
568 | 738 | ||
569 | rtc_device_unregister(cmos->rtc); | 739 | rtc_device_unregister(cmos->rtc); |
570 | cmos->rtc = NULL; | 740 | cmos->rtc = NULL; |
@@ -659,9 +829,12 @@ static int cmos_resume(struct device *dev) | |||
659 | 829 | ||
660 | /*----------------------------------------------------------------*/ | 830 | /*----------------------------------------------------------------*/ |
661 | 831 | ||
662 | /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, | 832 | /* On non-x86 systems, a "CMOS" RTC lives most naturally on platform_bus. |
663 | * the device node will always be created as a PNPACPI device. Plus | 833 | * ACPI systems always list these as PNPACPI devices, and pre-ACPI PCs |
664 | * pre-ACPI PCs probably list it in the PNPBIOS tables. | 834 | * probably list them in similar PNPBIOS tables; so PNP is more common. |
835 | * | ||
836 | * We don't use legacy "poke at the hardware" probing. Ancient PCs that | ||
837 | * predate even PNPBIOS should set up platform_bus devices. | ||
665 | */ | 838 | */ |
666 | 839 | ||
667 | #ifdef CONFIG_PNP | 840 | #ifdef CONFIG_PNP |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 025c60a17a4a..90dfa0df747a 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -246,6 +246,15 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
246 | /* if the driver does not provide the ioctl interface | 246 | /* if the driver does not provide the ioctl interface |
247 | * or if that particular ioctl was not implemented | 247 | * or if that particular ioctl was not implemented |
248 | * (-ENOIOCTLCMD), we will try to emulate here. | 248 | * (-ENOIOCTLCMD), we will try to emulate here. |
249 | * | ||
250 | * Drivers *SHOULD NOT* provide ioctl implementations | ||
251 | * for these requests. Instead, provide methods to | ||
252 | * support the following code, so that the RTC's main | ||
253 | * features are accessible without using ioctls. | ||
254 | * | ||
255 | * RTC and alarm times will be in UTC, by preference, | ||
256 | * but dual-booting with MS-Windows implies RTCs must | ||
257 | * use the local wall clock time. | ||
249 | */ | 258 | */ |
250 | 259 | ||
251 | switch (cmd) { | 260 | switch (cmd) { |
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c new file mode 100644 index 000000000000..7b002ceeaa7d --- /dev/null +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * Dallas DS1302 RTC Support | ||
3 | * | ||
4 | * Copyright (C) 2002 David McCullough | ||
5 | * Copyright (C) 2003 - 2007 Paul Mundt | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License version 2. See the file "COPYING" in the main directory of | ||
9 | * this archive for more details. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/time.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/bcd.h> | ||
20 | #include <asm/rtc.h> | ||
21 | |||
22 | #define DRV_NAME "rtc-ds1302" | ||
23 | #define DRV_VERSION "0.1.0" | ||
24 | |||
25 | #define RTC_CMD_READ 0x81 /* Read command */ | ||
26 | #define RTC_CMD_WRITE 0x80 /* Write command */ | ||
27 | |||
28 | #define RTC_ADDR_RAM0 0x20 /* Address of RAM0 */ | ||
29 | #define RTC_ADDR_TCR 0x08 /* Address of trickle charge register */ | ||
30 | #define RTC_ADDR_YEAR 0x06 /* Address of year register */ | ||
31 | #define RTC_ADDR_DAY 0x05 /* Address of day of week register */ | ||
32 | #define RTC_ADDR_MON 0x04 /* Address of month register */ | ||
33 | #define RTC_ADDR_DATE 0x03 /* Address of day of month register */ | ||
34 | #define RTC_ADDR_HOUR 0x02 /* Address of hour register */ | ||
35 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ | ||
36 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ | ||
37 | |||
38 | #define RTC_RESET 0x1000 | ||
39 | #define RTC_IODATA 0x0800 | ||
40 | #define RTC_SCLK 0x0400 | ||
41 | |||
42 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
43 | #include <asm/snapgear.h> | ||
44 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) | ||
45 | #define get_dp() SECUREEDGE_READ_IOPORT() | ||
46 | #else | ||
47 | #error "Add support for your platform" | ||
48 | #endif | ||
49 | |||
50 | struct ds1302_rtc { | ||
51 | struct rtc_device *rtc_dev; | ||
52 | spinlock_t lock; | ||
53 | }; | ||
54 | |||
55 | static void ds1302_sendbits(unsigned int val) | ||
56 | { | ||
57 | int i; | ||
58 | |||
59 | for (i = 8; (i); i--, val >>= 1) { | ||
60 | set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? | ||
61 | RTC_IODATA : 0)); | ||
62 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
63 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static unsigned int ds1302_recvbits(void) | ||
68 | { | ||
69 | unsigned int val; | ||
70 | int i; | ||
71 | |||
72 | for (i = 0, val = 0; (i < 8); i++) { | ||
73 | val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); | ||
74 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
75 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
76 | } | ||
77 | |||
78 | return val; | ||
79 | } | ||
80 | |||
81 | static unsigned int ds1302_readbyte(unsigned int addr) | ||
82 | { | ||
83 | unsigned int val; | ||
84 | |||
85 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
86 | |||
87 | set_dp(get_dp() | RTC_RESET); | ||
88 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); | ||
89 | val = ds1302_recvbits(); | ||
90 | set_dp(get_dp() & ~RTC_RESET); | ||
91 | |||
92 | return val; | ||
93 | } | ||
94 | |||
95 | static void ds1302_writebyte(unsigned int addr, unsigned int val) | ||
96 | { | ||
97 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
98 | set_dp(get_dp() | RTC_RESET); | ||
99 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); | ||
100 | ds1302_sendbits(val); | ||
101 | set_dp(get_dp() & ~RTC_RESET); | ||
102 | } | ||
103 | |||
104 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
105 | { | ||
106 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
107 | |||
108 | spin_lock_irq(&rtc->lock); | ||
109 | |||
110 | tm->tm_sec = BCD2BIN(ds1302_readbyte(RTC_ADDR_SEC)); | ||
111 | tm->tm_min = BCD2BIN(ds1302_readbyte(RTC_ADDR_MIN)); | ||
112 | tm->tm_hour = BCD2BIN(ds1302_readbyte(RTC_ADDR_HOUR)); | ||
113 | tm->tm_wday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DAY)); | ||
114 | tm->tm_mday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DATE)); | ||
115 | tm->tm_mon = BCD2BIN(ds1302_readbyte(RTC_ADDR_MON)) - 1; | ||
116 | tm->tm_year = BCD2BIN(ds1302_readbyte(RTC_ADDR_YEAR)); | ||
117 | |||
118 | if (tm->tm_year < 70) | ||
119 | tm->tm_year += 100; | ||
120 | |||
121 | spin_unlock_irq(&rtc->lock); | ||
122 | |||
123 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
124 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
125 | __FUNCTION__, | ||
126 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
127 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); | ||
128 | |||
129 | if (rtc_valid_tm(tm) < 0) | ||
130 | dev_err(dev, "invalid date\n"); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
136 | { | ||
137 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
138 | |||
139 | spin_lock_irq(&rtc->lock); | ||
140 | |||
141 | /* Stop RTC */ | ||
142 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); | ||
143 | |||
144 | ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec)); | ||
145 | ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min)); | ||
146 | ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour)); | ||
147 | ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday)); | ||
148 | ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday)); | ||
149 | ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1)); | ||
150 | ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year % 100)); | ||
151 | |||
152 | /* Start RTC */ | ||
153 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); | ||
154 | |||
155 | spin_unlock_irq(&rtc->lock); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
161 | unsigned long arg) | ||
162 | { | ||
163 | switch (cmd) { | ||
164 | #ifdef RTC_SET_CHARGE | ||
165 | case RTC_SET_CHARGE: | ||
166 | { | ||
167 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
168 | int tcs_val; | ||
169 | |||
170 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) | ||
171 | return -EFAULT; | ||
172 | |||
173 | spin_lock_irq(&rtc->lock); | ||
174 | ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); | ||
175 | spin_unlock_irq(&rtc->lock); | ||
176 | return 0; | ||
177 | } | ||
178 | #endif | ||
179 | } | ||
180 | |||
181 | return -ENOIOCTLCMD; | ||
182 | } | ||
183 | |||
184 | static struct rtc_class_ops ds1302_rtc_ops = { | ||
185 | .read_time = ds1302_rtc_read_time, | ||
186 | .set_time = ds1302_rtc_set_time, | ||
187 | .ioctl = ds1302_rtc_ioctl, | ||
188 | }; | ||
189 | |||
190 | static int __devinit ds1302_rtc_probe(struct platform_device *pdev) | ||
191 | { | ||
192 | struct ds1302_rtc *rtc; | ||
193 | int ret; | ||
194 | |||
195 | /* Reset */ | ||
196 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
197 | |||
198 | /* Write a magic value to the DS1302 RAM, and see if it sticks. */ | ||
199 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); | ||
200 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) | ||
201 | return -ENODEV; | ||
202 | |||
203 | rtc = kzalloc(sizeof(struct ds1302_rtc), GFP_KERNEL); | ||
204 | if (unlikely(!rtc)) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | spin_lock_init(&rtc->lock); | ||
208 | rtc->rtc_dev = rtc_device_register("ds1302", &pdev->dev, | ||
209 | &ds1302_rtc_ops, THIS_MODULE); | ||
210 | if (IS_ERR(rtc->rtc_dev)) { | ||
211 | ret = PTR_ERR(rtc->rtc_dev); | ||
212 | goto out; | ||
213 | } | ||
214 | |||
215 | platform_set_drvdata(pdev, rtc); | ||
216 | |||
217 | return 0; | ||
218 | out: | ||
219 | kfree(rtc); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static int __devexit ds1302_rtc_remove(struct platform_device *pdev) | ||
224 | { | ||
225 | struct ds1302_rtc *rtc = platform_get_drvdata(pdev); | ||
226 | |||
227 | if (likely(rtc->rtc_dev)) | ||
228 | rtc_device_unregister(rtc->rtc_dev); | ||
229 | |||
230 | platform_set_drvdata(pdev, NULL); | ||
231 | |||
232 | kfree(rtc); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static struct platform_driver ds1302_platform_driver = { | ||
238 | .driver = { | ||
239 | .name = DRV_NAME, | ||
240 | .owner = THIS_MODULE, | ||
241 | }, | ||
242 | .probe = ds1302_rtc_probe, | ||
243 | .remove = __devexit_p(ds1302_rtc_remove), | ||
244 | }; | ||
245 | |||
246 | static int __init ds1302_rtc_init(void) | ||
247 | { | ||
248 | return platform_driver_register(&ds1302_platform_driver); | ||
249 | } | ||
250 | |||
251 | static void __exit ds1302_rtc_exit(void) | ||
252 | { | ||
253 | platform_driver_unregister(&ds1302_platform_driver); | ||
254 | } | ||
255 | |||
256 | module_init(ds1302_rtc_init); | ||
257 | module_exit(ds1302_rtc_exit); | ||
258 | |||
259 | MODULE_DESCRIPTION("Dallas DS1302 RTC driver"); | ||
260 | MODULE_VERSION(DRV_VERSION); | ||
261 | MODULE_AUTHOR("Paul Mundt, David McCullough"); | ||
262 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bc1c7fe94ad3..f389a28720d2 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -256,7 +256,7 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
256 | struct i2c_msg msg[2]; | 256 | struct i2c_msg msg[2]; |
257 | int result; | 257 | int result; |
258 | 258 | ||
259 | client = to_i2c_client(container_of(kobj, struct device, kobj)); | 259 | client = kobj_to_i2c_client(kobj); |
260 | ds1307 = i2c_get_clientdata(client); | 260 | ds1307 = i2c_get_clientdata(client); |
261 | 261 | ||
262 | if (unlikely(off >= NVRAM_SIZE)) | 262 | if (unlikely(off >= NVRAM_SIZE)) |
@@ -294,7 +294,7 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
294 | u8 buffer[NVRAM_SIZE + 1]; | 294 | u8 buffer[NVRAM_SIZE + 1]; |
295 | int ret; | 295 | int ret; |
296 | 296 | ||
297 | client = to_i2c_client(container_of(kobj, struct device, kobj)); | 297 | client = kobj_to_i2c_client(kobj); |
298 | 298 | ||
299 | if (unlikely(off >= NVRAM_SIZE)) | 299 | if (unlikely(off >= NVRAM_SIZE)) |
300 | return -EFBIG; | 300 | return -EFBIG; |
@@ -412,11 +412,6 @@ read_rtc: | |||
412 | */ | 412 | */ |
413 | tmp = ds1307->regs[DS1307_REG_SECS]; | 413 | tmp = ds1307->regs[DS1307_REG_SECS]; |
414 | switch (ds1307->type) { | 414 | switch (ds1307->type) { |
415 | case ds_1340: | ||
416 | /* FIXME read register with DS1340_BIT_OSF, use that to | ||
417 | * trigger the "set time" warning (*after* restarting the | ||
418 | * oscillator!) instead of this weaker ds1307/m41t00 test. | ||
419 | */ | ||
420 | case ds_1307: | 415 | case ds_1307: |
421 | case m41t00: | 416 | case m41t00: |
422 | /* clock halted? turn it on, so clock can tick. */ | 417 | /* clock halted? turn it on, so clock can tick. */ |
@@ -440,6 +435,24 @@ read_rtc: | |||
440 | goto read_rtc; | 435 | goto read_rtc; |
441 | } | 436 | } |
442 | break; | 437 | break; |
438 | case ds_1340: | ||
439 | /* clock halted? turn it on, so clock can tick. */ | ||
440 | if (tmp & DS1340_BIT_nEOSC) | ||
441 | i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0); | ||
442 | |||
443 | tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG); | ||
444 | if (tmp < 0) { | ||
445 | pr_debug("read error %d\n", tmp); | ||
446 | err = -EIO; | ||
447 | goto exit_free; | ||
448 | } | ||
449 | |||
450 | /* oscillator fault? clear flag, and warn */ | ||
451 | if (tmp & DS1340_BIT_OSF) { | ||
452 | i2c_smbus_write_byte_data(client, DS1340_REG_FLAG, 0); | ||
453 | dev_warn(&client->dev, "SET TIME!\n"); | ||
454 | } | ||
455 | break; | ||
443 | case ds_1337: | 456 | case ds_1337: |
444 | case ds_1339: | 457 | case ds_1339: |
445 | break; | 458 | break; |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c new file mode 100644 index 000000000000..d74b8086fa31 --- /dev/null +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -0,0 +1,656 @@ | |||
1 | /* | ||
2 | * An rtc driver for the Dallas DS1511 | ||
3 | * | ||
4 | * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> | ||
5 | * Copyright (C) 2007 Andrew Sharp <andy.sharp@onstor.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Real time clock driver for the Dallas 1511 chip, which also | ||
12 | * contains a watchdog timer. There is a tiny amount of code that | ||
13 | * platform code could use to mess with the watchdog device a little | ||
14 | * bit, but not a full watchdog driver. | ||
15 | */ | ||
16 | |||
17 | #include <linux/bcd.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #define DRV_VERSION "0.6" | ||
27 | |||
28 | enum ds1511reg { | ||
29 | DS1511_SEC = 0x0, | ||
30 | DS1511_MIN = 0x1, | ||
31 | DS1511_HOUR = 0x2, | ||
32 | DS1511_DOW = 0x3, | ||
33 | DS1511_DOM = 0x4, | ||
34 | DS1511_MONTH = 0x5, | ||
35 | DS1511_YEAR = 0x6, | ||
36 | DS1511_CENTURY = 0x7, | ||
37 | DS1511_AM1_SEC = 0x8, | ||
38 | DS1511_AM2_MIN = 0x9, | ||
39 | DS1511_AM3_HOUR = 0xa, | ||
40 | DS1511_AM4_DATE = 0xb, | ||
41 | DS1511_WD_MSEC = 0xc, | ||
42 | DS1511_WD_SEC = 0xd, | ||
43 | DS1511_CONTROL_A = 0xe, | ||
44 | DS1511_CONTROL_B = 0xf, | ||
45 | DS1511_RAMADDR_LSB = 0x10, | ||
46 | DS1511_RAMDATA = 0x13 | ||
47 | }; | ||
48 | |||
49 | #define DS1511_BLF1 0x80 | ||
50 | #define DS1511_BLF2 0x40 | ||
51 | #define DS1511_PRS 0x20 | ||
52 | #define DS1511_PAB 0x10 | ||
53 | #define DS1511_TDF 0x08 | ||
54 | #define DS1511_KSF 0x04 | ||
55 | #define DS1511_WDF 0x02 | ||
56 | #define DS1511_IRQF 0x01 | ||
57 | #define DS1511_TE 0x80 | ||
58 | #define DS1511_CS 0x40 | ||
59 | #define DS1511_BME 0x20 | ||
60 | #define DS1511_TPE 0x10 | ||
61 | #define DS1511_TIE 0x08 | ||
62 | #define DS1511_KIE 0x04 | ||
63 | #define DS1511_WDE 0x02 | ||
64 | #define DS1511_WDS 0x01 | ||
65 | #define DS1511_RAM_MAX 0xff | ||
66 | |||
67 | #define RTC_CMD DS1511_CONTROL_B | ||
68 | #define RTC_CMD1 DS1511_CONTROL_A | ||
69 | |||
70 | #define RTC_ALARM_SEC DS1511_AM1_SEC | ||
71 | #define RTC_ALARM_MIN DS1511_AM2_MIN | ||
72 | #define RTC_ALARM_HOUR DS1511_AM3_HOUR | ||
73 | #define RTC_ALARM_DATE DS1511_AM4_DATE | ||
74 | |||
75 | #define RTC_SEC DS1511_SEC | ||
76 | #define RTC_MIN DS1511_MIN | ||
77 | #define RTC_HOUR DS1511_HOUR | ||
78 | #define RTC_DOW DS1511_DOW | ||
79 | #define RTC_DOM DS1511_DOM | ||
80 | #define RTC_MON DS1511_MONTH | ||
81 | #define RTC_YEAR DS1511_YEAR | ||
82 | #define RTC_CENTURY DS1511_CENTURY | ||
83 | |||
84 | #define RTC_TIE DS1511_TIE | ||
85 | #define RTC_TE DS1511_TE | ||
86 | |||
87 | struct rtc_plat_data { | ||
88 | struct rtc_device *rtc; | ||
89 | void __iomem *ioaddr; /* virtual base address */ | ||
90 | unsigned long baseaddr; /* physical base address */ | ||
91 | int size; /* amount of memory mapped */ | ||
92 | int irq; | ||
93 | unsigned int irqen; | ||
94 | int alrm_sec; | ||
95 | int alrm_min; | ||
96 | int alrm_hour; | ||
97 | int alrm_mday; | ||
98 | }; | ||
99 | |||
100 | static DEFINE_SPINLOCK(ds1511_lock); | ||
101 | |||
102 | static __iomem char *ds1511_base; | ||
103 | static u32 reg_spacing = 1; | ||
104 | |||
105 | static noinline void | ||
106 | rtc_write(uint8_t val, uint32_t reg) | ||
107 | { | ||
108 | writeb(val, ds1511_base + (reg * reg_spacing)); | ||
109 | } | ||
110 | |||
111 | static inline void | ||
112 | rtc_write_alarm(uint8_t val, enum ds1511reg reg) | ||
113 | { | ||
114 | rtc_write((val | 0x80), reg); | ||
115 | } | ||
116 | |||
117 | static noinline uint8_t | ||
118 | rtc_read(enum ds1511reg reg) | ||
119 | { | ||
120 | return readb(ds1511_base + (reg * reg_spacing)); | ||
121 | } | ||
122 | |||
123 | static inline void | ||
124 | rtc_disable_update(void) | ||
125 | { | ||
126 | rtc_write((rtc_read(RTC_CMD) & ~RTC_TE), RTC_CMD); | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | rtc_enable_update(void) | ||
131 | { | ||
132 | rtc_write((rtc_read(RTC_CMD) | RTC_TE), RTC_CMD); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * #define DS1511_WDOG_RESET_SUPPORT | ||
137 | * | ||
138 | * Uncomment this if you want to use these routines in | ||
139 | * some platform code. | ||
140 | */ | ||
141 | #ifdef DS1511_WDOG_RESET_SUPPORT | ||
142 | /* | ||
143 | * just enough code to set the watchdog timer so that it | ||
144 | * will reboot the system | ||
145 | */ | ||
146 | void | ||
147 | ds1511_wdog_set(unsigned long deciseconds) | ||
148 | { | ||
149 | /* | ||
150 | * the wdog timer can take 99.99 seconds | ||
151 | */ | ||
152 | deciseconds %= 10000; | ||
153 | /* | ||
154 | * set the wdog values in the wdog registers | ||
155 | */ | ||
156 | rtc_write(BIN2BCD(deciseconds % 100), DS1511_WD_MSEC); | ||
157 | rtc_write(BIN2BCD(deciseconds / 100), DS1511_WD_SEC); | ||
158 | /* | ||
159 | * set wdog enable and wdog 'steering' bit to issue a reset | ||
160 | */ | ||
161 | rtc_write(DS1511_WDE | DS1511_WDS, RTC_CMD); | ||
162 | } | ||
163 | |||
164 | void | ||
165 | ds1511_wdog_disable(void) | ||
166 | { | ||
167 | /* | ||
168 | * clear wdog enable and wdog 'steering' bits | ||
169 | */ | ||
170 | rtc_write(rtc_read(RTC_CMD) & ~(DS1511_WDE | DS1511_WDS), RTC_CMD); | ||
171 | /* | ||
172 | * clear the wdog counter | ||
173 | */ | ||
174 | rtc_write(0, DS1511_WD_MSEC); | ||
175 | rtc_write(0, DS1511_WD_SEC); | ||
176 | } | ||
177 | #endif | ||
178 | |||
179 | /* | ||
180 | * set the rtc chip's idea of the time. | ||
181 | * stupidly, some callers call with year unmolested; | ||
182 | * and some call with year = year - 1900. thanks. | ||
183 | */ | ||
184 | int | ||
185 | ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) | ||
186 | { | ||
187 | u8 mon, day, dow, hrs, min, sec, yrs, cen; | ||
188 | unsigned int flags; | ||
189 | |||
190 | /* | ||
191 | * won't have to change this for a while | ||
192 | */ | ||
193 | if (rtc_tm->tm_year < 1900) { | ||
194 | rtc_tm->tm_year += 1900; | ||
195 | } | ||
196 | |||
197 | if (rtc_tm->tm_year < 1970) { | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | yrs = rtc_tm->tm_year % 100; | ||
201 | cen = rtc_tm->tm_year / 100; | ||
202 | mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
203 | day = rtc_tm->tm_mday; | ||
204 | dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */ | ||
205 | hrs = rtc_tm->tm_hour; | ||
206 | min = rtc_tm->tm_min; | ||
207 | sec = rtc_tm->tm_sec; | ||
208 | |||
209 | if ((mon > 12) || (day == 0)) { | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | if (day > rtc_month_days(rtc_tm->tm_mon, rtc_tm->tm_year)) { | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | if ((hrs >= 24) || (min >= 60) || (sec >= 60)) { | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * each register is a different number of valid bits | ||
223 | */ | ||
224 | sec = BIN2BCD(sec) & 0x7f; | ||
225 | min = BIN2BCD(min) & 0x7f; | ||
226 | hrs = BIN2BCD(hrs) & 0x3f; | ||
227 | day = BIN2BCD(day) & 0x3f; | ||
228 | mon = BIN2BCD(mon) & 0x1f; | ||
229 | yrs = BIN2BCD(yrs) & 0xff; | ||
230 | cen = BIN2BCD(cen) & 0xff; | ||
231 | |||
232 | spin_lock_irqsave(&ds1511_lock, flags); | ||
233 | rtc_disable_update(); | ||
234 | rtc_write(cen, RTC_CENTURY); | ||
235 | rtc_write(yrs, RTC_YEAR); | ||
236 | rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON); | ||
237 | rtc_write(day, RTC_DOM); | ||
238 | rtc_write(hrs, RTC_HOUR); | ||
239 | rtc_write(min, RTC_MIN); | ||
240 | rtc_write(sec, RTC_SEC); | ||
241 | rtc_write(dow, RTC_DOW); | ||
242 | rtc_enable_update(); | ||
243 | spin_unlock_irqrestore(&ds1511_lock, flags); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | int | ||
249 | ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | ||
250 | { | ||
251 | unsigned int century; | ||
252 | unsigned int flags; | ||
253 | |||
254 | spin_lock_irqsave(&ds1511_lock, flags); | ||
255 | rtc_disable_update(); | ||
256 | |||
257 | rtc_tm->tm_sec = rtc_read(RTC_SEC) & 0x7f; | ||
258 | rtc_tm->tm_min = rtc_read(RTC_MIN) & 0x7f; | ||
259 | rtc_tm->tm_hour = rtc_read(RTC_HOUR) & 0x3f; | ||
260 | rtc_tm->tm_mday = rtc_read(RTC_DOM) & 0x3f; | ||
261 | rtc_tm->tm_wday = rtc_read(RTC_DOW) & 0x7; | ||
262 | rtc_tm->tm_mon = rtc_read(RTC_MON) & 0x1f; | ||
263 | rtc_tm->tm_year = rtc_read(RTC_YEAR) & 0x7f; | ||
264 | century = rtc_read(RTC_CENTURY); | ||
265 | |||
266 | rtc_enable_update(); | ||
267 | spin_unlock_irqrestore(&ds1511_lock, flags); | ||
268 | |||
269 | rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec); | ||
270 | rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min); | ||
271 | rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour); | ||
272 | rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday); | ||
273 | rtc_tm->tm_wday = BCD2BIN(rtc_tm->tm_wday); | ||
274 | rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon); | ||
275 | rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year); | ||
276 | century = BCD2BIN(century) * 100; | ||
277 | |||
278 | /* | ||
279 | * Account for differences between how the RTC uses the values | ||
280 | * and how they are defined in a struct rtc_time; | ||
281 | */ | ||
282 | century += rtc_tm->tm_year; | ||
283 | rtc_tm->tm_year = century - 1900; | ||
284 | |||
285 | rtc_tm->tm_mon--; | ||
286 | |||
287 | if (rtc_valid_tm(rtc_tm) < 0) { | ||
288 | dev_err(dev, "retrieved date/time is not valid.\n"); | ||
289 | rtc_time_to_tm(0, rtc_tm); | ||
290 | } | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * write the alarm register settings | ||
296 | * | ||
297 | * we only have the use to interrupt every second, otherwise | ||
298 | * known as the update interrupt, or the interrupt if the whole | ||
299 | * date/hours/mins/secs matches. the ds1511 has many more | ||
300 | * permutations, but the kernel doesn't. | ||
301 | */ | ||
302 | static void | ||
303 | ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | ||
304 | { | ||
305 | unsigned long flags; | ||
306 | |||
307 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | ||
308 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | ||
309 | 0x80 : BIN2BCD(pdata->alrm_mday) & 0x3f, | ||
310 | RTC_ALARM_DATE); | ||
311 | rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? | ||
312 | 0x80 : BIN2BCD(pdata->alrm_hour) & 0x3f, | ||
313 | RTC_ALARM_HOUR); | ||
314 | rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? | ||
315 | 0x80 : BIN2BCD(pdata->alrm_min) & 0x7f, | ||
316 | RTC_ALARM_MIN); | ||
317 | rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? | ||
318 | 0x80 : BIN2BCD(pdata->alrm_sec) & 0x7f, | ||
319 | RTC_ALARM_SEC); | ||
320 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); | ||
321 | rtc_read(RTC_CMD1); /* clear interrupts */ | ||
322 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | ||
323 | } | ||
324 | |||
325 | static int | ||
326 | ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
327 | { | ||
328 | struct platform_device *pdev = to_platform_device(dev); | ||
329 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
330 | |||
331 | if (pdata->irq < 0) { | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | pdata->alrm_mday = alrm->time.tm_mday; | ||
335 | pdata->alrm_hour = alrm->time.tm_hour; | ||
336 | pdata->alrm_min = alrm->time.tm_min; | ||
337 | pdata->alrm_sec = alrm->time.tm_sec; | ||
338 | if (alrm->enabled) { | ||
339 | pdata->irqen |= RTC_AF; | ||
340 | } | ||
341 | ds1511_rtc_update_alarm(pdata); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int | ||
346 | ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
347 | { | ||
348 | struct platform_device *pdev = to_platform_device(dev); | ||
349 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
350 | |||
351 | if (pdata->irq < 0) { | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday; | ||
355 | alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour; | ||
356 | alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min; | ||
357 | alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec; | ||
358 | alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static irqreturn_t | ||
363 | ds1511_interrupt(int irq, void *dev_id) | ||
364 | { | ||
365 | struct platform_device *pdev = dev_id; | ||
366 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
367 | unsigned long events = RTC_IRQF; | ||
368 | |||
369 | /* | ||
370 | * read and clear interrupt | ||
371 | */ | ||
372 | if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) { | ||
373 | return IRQ_NONE; | ||
374 | } | ||
375 | if (rtc_read(RTC_ALARM_SEC) & 0x80) { | ||
376 | events |= RTC_UF; | ||
377 | } else { | ||
378 | events |= RTC_AF; | ||
379 | } | ||
380 | rtc_update_irq(pdata->rtc, 1, events); | ||
381 | return IRQ_HANDLED; | ||
382 | } | ||
383 | |||
384 | static void | ||
385 | ds1511_rtc_release(struct device *dev) | ||
386 | { | ||
387 | struct platform_device *pdev = to_platform_device(dev); | ||
388 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
389 | |||
390 | if (pdata->irq >= 0) { | ||
391 | pdata->irqen = 0; | ||
392 | ds1511_rtc_update_alarm(pdata); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | static int | ||
397 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
398 | { | ||
399 | struct platform_device *pdev = to_platform_device(dev); | ||
400 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
401 | |||
402 | if (pdata->irq < 0) { | ||
403 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | ||
404 | } | ||
405 | switch (cmd) { | ||
406 | case RTC_AIE_OFF: | ||
407 | pdata->irqen &= ~RTC_AF; | ||
408 | ds1511_rtc_update_alarm(pdata); | ||
409 | break; | ||
410 | case RTC_AIE_ON: | ||
411 | pdata->irqen |= RTC_AF; | ||
412 | ds1511_rtc_update_alarm(pdata); | ||
413 | break; | ||
414 | case RTC_UIE_OFF: | ||
415 | pdata->irqen &= ~RTC_UF; | ||
416 | ds1511_rtc_update_alarm(pdata); | ||
417 | break; | ||
418 | case RTC_UIE_ON: | ||
419 | pdata->irqen |= RTC_UF; | ||
420 | ds1511_rtc_update_alarm(pdata); | ||
421 | break; | ||
422 | default: | ||
423 | return -ENOIOCTLCMD; | ||
424 | } | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static const struct rtc_class_ops ds1511_rtc_ops = { | ||
429 | .read_time = ds1511_rtc_read_time, | ||
430 | .set_time = ds1511_rtc_set_time, | ||
431 | .read_alarm = ds1511_rtc_read_alarm, | ||
432 | .set_alarm = ds1511_rtc_set_alarm, | ||
433 | .release = ds1511_rtc_release, | ||
434 | .ioctl = ds1511_rtc_ioctl, | ||
435 | }; | ||
436 | |||
437 | static ssize_t | ||
438 | ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | ||
439 | char *buf, loff_t pos, size_t size) | ||
440 | { | ||
441 | ssize_t count; | ||
442 | |||
443 | /* | ||
444 | * if count is more than one, turn on "burst" mode | ||
445 | * turn it off when you're done | ||
446 | */ | ||
447 | if (size > 1) { | ||
448 | rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD); | ||
449 | } | ||
450 | if (pos > DS1511_RAM_MAX) { | ||
451 | pos = DS1511_RAM_MAX; | ||
452 | } | ||
453 | if (size + pos > DS1511_RAM_MAX + 1) { | ||
454 | size = DS1511_RAM_MAX - pos + 1; | ||
455 | } | ||
456 | rtc_write(pos, DS1511_RAMADDR_LSB); | ||
457 | for (count = 0; size > 0; count++, size--) { | ||
458 | *buf++ = rtc_read(DS1511_RAMDATA); | ||
459 | } | ||
460 | if (count > 1) { | ||
461 | rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD); | ||
462 | } | ||
463 | return count; | ||
464 | } | ||
465 | |||
466 | static ssize_t | ||
467 | ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, | ||
468 | char *buf, loff_t pos, size_t size) | ||
469 | { | ||
470 | ssize_t count; | ||
471 | |||
472 | /* | ||
473 | * if count is more than one, turn on "burst" mode | ||
474 | * turn it off when you're done | ||
475 | */ | ||
476 | if (size > 1) { | ||
477 | rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD); | ||
478 | } | ||
479 | if (pos > DS1511_RAM_MAX) { | ||
480 | pos = DS1511_RAM_MAX; | ||
481 | } | ||
482 | if (size + pos > DS1511_RAM_MAX + 1) { | ||
483 | size = DS1511_RAM_MAX - pos + 1; | ||
484 | } | ||
485 | rtc_write(pos, DS1511_RAMADDR_LSB); | ||
486 | for (count = 0; size > 0; count++, size--) { | ||
487 | rtc_write(*buf++, DS1511_RAMDATA); | ||
488 | } | ||
489 | if (count > 1) { | ||
490 | rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD); | ||
491 | } | ||
492 | return count; | ||
493 | } | ||
494 | |||
495 | static struct bin_attribute ds1511_nvram_attr = { | ||
496 | .attr = { | ||
497 | .name = "nvram", | ||
498 | .mode = S_IRUGO | S_IWUGO, | ||
499 | .owner = THIS_MODULE, | ||
500 | }, | ||
501 | .size = DS1511_RAM_MAX, | ||
502 | .read = ds1511_nvram_read, | ||
503 | .write = ds1511_nvram_write, | ||
504 | }; | ||
505 | |||
506 | static int __devinit | ||
507 | ds1511_rtc_probe(struct platform_device *pdev) | ||
508 | { | ||
509 | struct rtc_device *rtc; | ||
510 | struct resource *res; | ||
511 | struct rtc_plat_data *pdata = NULL; | ||
512 | int ret = 0; | ||
513 | |||
514 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
515 | if (!res) { | ||
516 | return -ENODEV; | ||
517 | } | ||
518 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
519 | if (!pdata) { | ||
520 | return -ENOMEM; | ||
521 | } | ||
522 | pdata->irq = -1; | ||
523 | pdata->size = res->end - res->start + 1; | ||
524 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | ||
525 | ret = -EBUSY; | ||
526 | goto out; | ||
527 | } | ||
528 | pdata->baseaddr = res->start; | ||
529 | pdata->size = pdata->size; | ||
530 | ds1511_base = ioremap(pdata->baseaddr, pdata->size); | ||
531 | if (!ds1511_base) { | ||
532 | ret = -ENOMEM; | ||
533 | goto out; | ||
534 | } | ||
535 | pdata->ioaddr = ds1511_base; | ||
536 | pdata->irq = platform_get_irq(pdev, 0); | ||
537 | |||
538 | /* | ||
539 | * turn on the clock and the crystal, etc. | ||
540 | */ | ||
541 | rtc_write(0, RTC_CMD); | ||
542 | rtc_write(0, RTC_CMD1); | ||
543 | /* | ||
544 | * clear the wdog counter | ||
545 | */ | ||
546 | rtc_write(0, DS1511_WD_MSEC); | ||
547 | rtc_write(0, DS1511_WD_SEC); | ||
548 | /* | ||
549 | * start the clock | ||
550 | */ | ||
551 | rtc_enable_update(); | ||
552 | |||
553 | /* | ||
554 | * check for a dying bat-tree | ||
555 | */ | ||
556 | if (rtc_read(RTC_CMD1) & DS1511_BLF1) { | ||
557 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * if the platform has an interrupt in mind for this device, | ||
562 | * then by all means, set it | ||
563 | */ | ||
564 | if (pdata->irq >= 0) { | ||
565 | rtc_read(RTC_CMD1); | ||
566 | if (request_irq(pdata->irq, ds1511_interrupt, | ||
567 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { | ||
568 | |||
569 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
570 | pdata->irq = -1; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, | ||
575 | THIS_MODULE); | ||
576 | if (IS_ERR(rtc)) { | ||
577 | ret = PTR_ERR(rtc); | ||
578 | goto out; | ||
579 | } | ||
580 | pdata->rtc = rtc; | ||
581 | platform_set_drvdata(pdev, pdata); | ||
582 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | ||
583 | if (ret) { | ||
584 | goto out; | ||
585 | } | ||
586 | return 0; | ||
587 | out: | ||
588 | if (pdata->rtc) { | ||
589 | rtc_device_unregister(pdata->rtc); | ||
590 | } | ||
591 | if (pdata->irq >= 0) { | ||
592 | free_irq(pdata->irq, pdev); | ||
593 | } | ||
594 | if (ds1511_base) { | ||
595 | iounmap(ds1511_base); | ||
596 | ds1511_base = NULL; | ||
597 | } | ||
598 | if (pdata->baseaddr) { | ||
599 | release_mem_region(pdata->baseaddr, pdata->size); | ||
600 | } | ||
601 | |||
602 | kfree(pdata); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | static int __devexit | ||
607 | ds1511_rtc_remove(struct platform_device *pdev) | ||
608 | { | ||
609 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
610 | |||
611 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | ||
612 | rtc_device_unregister(pdata->rtc); | ||
613 | pdata->rtc = NULL; | ||
614 | if (pdata->irq >= 0) { | ||
615 | /* | ||
616 | * disable the alarm interrupt | ||
617 | */ | ||
618 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); | ||
619 | rtc_read(RTC_CMD1); | ||
620 | free_irq(pdata->irq, pdev); | ||
621 | } | ||
622 | iounmap(pdata->ioaddr); | ||
623 | ds1511_base = NULL; | ||
624 | release_mem_region(pdata->baseaddr, pdata->size); | ||
625 | kfree(pdata); | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | static struct platform_driver ds1511_rtc_driver = { | ||
630 | .probe = ds1511_rtc_probe, | ||
631 | .remove = __devexit_p(ds1511_rtc_remove), | ||
632 | .driver = { | ||
633 | .name = "ds1511", | ||
634 | .owner = THIS_MODULE, | ||
635 | }, | ||
636 | }; | ||
637 | |||
638 | static int __init | ||
639 | ds1511_rtc_init(void) | ||
640 | { | ||
641 | return platform_driver_register(&ds1511_rtc_driver); | ||
642 | } | ||
643 | |||
644 | static void __exit | ||
645 | ds1511_rtc_exit(void) | ||
646 | { | ||
647 | return platform_driver_unregister(&ds1511_rtc_driver); | ||
648 | } | ||
649 | |||
650 | module_init(ds1511_rtc_init); | ||
651 | module_exit(ds1511_rtc_exit); | ||
652 | |||
653 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@onstor.com>"); | ||
654 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); | ||
655 | MODULE_LICENSE("GPL"); | ||
656 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index c973ba94c422..8b3997007506 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
@@ -163,27 +163,17 @@ static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem) | |||
163 | 163 | ||
164 | static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) | 164 | static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) |
165 | { | 165 | { |
166 | unsigned char addr[1]; | 166 | unsigned char buf[9]; |
167 | struct i2c_msg msgs[2] = { | 167 | int ret; |
168 | { | ||
169 | .addr = client->addr, | ||
170 | .flags = 0, | ||
171 | .len = 1, | ||
172 | .buf = addr, | ||
173 | }, { | ||
174 | .addr = client->addr, | ||
175 | .flags = I2C_M_NOSTART, | ||
176 | .len = mem->nr, | ||
177 | .buf = mem->data, | ||
178 | } | ||
179 | }; | ||
180 | 168 | ||
181 | if (mem->loc < 8) | 169 | if (mem->loc < 8 || mem->nr > 8) |
182 | return -EINVAL; | 170 | return -EINVAL; |
183 | 171 | ||
184 | addr[0] = mem->loc; | 172 | buf[0] = mem->loc; |
173 | memcpy(buf + 1, mem->data, mem->nr); | ||
185 | 174 | ||
186 | return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; | 175 | ret = i2c_master_send(client, buf, mem->nr + 1); |
176 | return ret == mem->nr + 1 ? 0 : -EIO; | ||
187 | } | 177 | } |
188 | 178 | ||
189 | static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) | 179 | static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) |
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c new file mode 100644 index 000000000000..a64626a82d0b --- /dev/null +++ b/drivers/rtc/rtc-r9701.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * Driver for Epson RTC-9701JE | ||
3 | * | ||
4 | * Copyright (C) 2008 Magnus Damm | ||
5 | * | ||
6 | * Based on rtc-max6902.c | ||
7 | * | ||
8 | * Copyright (C) 2006 8D Technologies inc. | ||
9 | * Copyright (C) 2004 Compulab Ltd. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/version.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/bcd.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/bitops.h> | ||
27 | |||
28 | #define RSECCNT 0x00 /* Second Counter */ | ||
29 | #define RMINCNT 0x01 /* Minute Counter */ | ||
30 | #define RHRCNT 0x02 /* Hour Counter */ | ||
31 | #define RWKCNT 0x03 /* Week Counter */ | ||
32 | #define RDAYCNT 0x04 /* Day Counter */ | ||
33 | #define RMONCNT 0x05 /* Month Counter */ | ||
34 | #define RYRCNT 0x06 /* Year Counter */ | ||
35 | #define R100CNT 0x07 /* Y100 Counter */ | ||
36 | #define RMINAR 0x08 /* Minute Alarm */ | ||
37 | #define RHRAR 0x09 /* Hour Alarm */ | ||
38 | #define RWKAR 0x0a /* Week/Day Alarm */ | ||
39 | #define RTIMCNT 0x0c /* Interval Timer */ | ||
40 | #define REXT 0x0d /* Extension Register */ | ||
41 | #define RFLAG 0x0e /* RTC Flag Register */ | ||
42 | #define RCR 0x0f /* RTC Control Register */ | ||
43 | |||
44 | static int write_reg(struct device *dev, int address, unsigned char data) | ||
45 | { | ||
46 | struct spi_device *spi = to_spi_device(dev); | ||
47 | unsigned char buf[2]; | ||
48 | |||
49 | buf[0] = address & 0x7f; | ||
50 | buf[1] = data; | ||
51 | |||
52 | return spi_write(spi, buf, ARRAY_SIZE(buf)); | ||
53 | } | ||
54 | |||
55 | static int read_regs(struct device *dev, unsigned char *regs, int no_regs) | ||
56 | { | ||
57 | struct spi_device *spi = to_spi_device(dev); | ||
58 | u8 txbuf[1], rxbuf[1]; | ||
59 | int k, ret; | ||
60 | |||
61 | ret = 0; | ||
62 | |||
63 | for (k = 0; ret == 0 && k < no_regs; k++) { | ||
64 | txbuf[0] = 0x80 | regs[k]; | ||
65 | ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1); | ||
66 | regs[k] = rxbuf[0]; | ||
67 | } | ||
68 | |||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static int r9701_get_datetime(struct device *dev, struct rtc_time *dt) | ||
73 | { | ||
74 | unsigned long time; | ||
75 | int ret; | ||
76 | unsigned char buf[] = { RSECCNT, RMINCNT, RHRCNT, | ||
77 | RDAYCNT, RMONCNT, RYRCNT }; | ||
78 | |||
79 | ret = read_regs(dev, buf, ARRAY_SIZE(buf)); | ||
80 | if (ret) | ||
81 | return ret; | ||
82 | |||
83 | memset(dt, 0, sizeof(*dt)); | ||
84 | |||
85 | dt->tm_sec = BCD2BIN(buf[0]); /* RSECCNT */ | ||
86 | dt->tm_min = BCD2BIN(buf[1]); /* RMINCNT */ | ||
87 | dt->tm_hour = BCD2BIN(buf[2]); /* RHRCNT */ | ||
88 | |||
89 | dt->tm_mday = BCD2BIN(buf[3]); /* RDAYCNT */ | ||
90 | dt->tm_mon = BCD2BIN(buf[4]) - 1; /* RMONCNT */ | ||
91 | dt->tm_year = BCD2BIN(buf[5]) + 100; /* RYRCNT */ | ||
92 | |||
93 | /* the rtc device may contain illegal values on power up | ||
94 | * according to the data sheet. make sure they are valid. | ||
95 | */ | ||
96 | |||
97 | return rtc_valid_tm(dt); | ||
98 | } | ||
99 | |||
100 | static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) | ||
101 | { | ||
102 | int ret, year; | ||
103 | |||
104 | year = dt->tm_year + 1900; | ||
105 | if (year >= 2100 || year < 2000) | ||
106 | return -EINVAL; | ||
107 | |||
108 | ret = write_reg(dev, RHRCNT, BIN2BCD(dt->tm_hour)); | ||
109 | ret = ret ? ret : write_reg(dev, RMINCNT, BIN2BCD(dt->tm_min)); | ||
110 | ret = ret ? ret : write_reg(dev, RSECCNT, BIN2BCD(dt->tm_sec)); | ||
111 | ret = ret ? ret : write_reg(dev, RDAYCNT, BIN2BCD(dt->tm_mday)); | ||
112 | ret = ret ? ret : write_reg(dev, RMONCNT, BIN2BCD(dt->tm_mon + 1)); | ||
113 | ret = ret ? ret : write_reg(dev, RYRCNT, BIN2BCD(dt->tm_year - 100)); | ||
114 | ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static const struct rtc_class_ops r9701_rtc_ops = { | ||
120 | .read_time = r9701_get_datetime, | ||
121 | .set_time = r9701_set_datetime, | ||
122 | }; | ||
123 | |||
124 | static int __devinit r9701_probe(struct spi_device *spi) | ||
125 | { | ||
126 | struct rtc_device *rtc; | ||
127 | unsigned char tmp; | ||
128 | int res; | ||
129 | |||
130 | rtc = rtc_device_register("r9701", | ||
131 | &spi->dev, &r9701_rtc_ops, THIS_MODULE); | ||
132 | if (IS_ERR(rtc)) | ||
133 | return PTR_ERR(rtc); | ||
134 | |||
135 | dev_set_drvdata(&spi->dev, rtc); | ||
136 | |||
137 | tmp = R100CNT; | ||
138 | res = read_regs(&spi->dev, &tmp, 1); | ||
139 | if (res || tmp != 0x20) { | ||
140 | rtc_device_unregister(rtc); | ||
141 | return res; | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int __devexit r9701_remove(struct spi_device *spi) | ||
148 | { | ||
149 | struct rtc_device *rtc = dev_get_drvdata(&spi->dev); | ||
150 | |||
151 | rtc_device_unregister(rtc); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static struct spi_driver r9701_driver = { | ||
156 | .driver = { | ||
157 | .name = "rtc-r9701", | ||
158 | .owner = THIS_MODULE, | ||
159 | }, | ||
160 | .probe = r9701_probe, | ||
161 | .remove = __devexit_p(r9701_remove), | ||
162 | }; | ||
163 | |||
164 | static __init int r9701_init(void) | ||
165 | { | ||
166 | return spi_register_driver(&r9701_driver); | ||
167 | } | ||
168 | module_init(r9701_init); | ||
169 | |||
170 | static __exit void r9701_exit(void) | ||
171 | { | ||
172 | spi_unregister_driver(&r9701_driver); | ||
173 | } | ||
174 | module_exit(r9701_exit); | ||
175 | |||
176 | MODULE_DESCRIPTION("r9701 spi RTC driver"); | ||
177 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | ||
178 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index e2041b4d0c85..86766f1f2496 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/rtc.h> | 20 | #include <linux/rtc.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/log2.h> | ||
23 | 24 | ||
24 | #include <asm/hardware.h> | 25 | #include <asm/hardware.h> |
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
@@ -309,9 +310,7 @@ static int s3c_rtc_ioctl(struct device *dev, | |||
309 | break; | 310 | break; |
310 | 311 | ||
311 | case RTC_IRQP_SET: | 312 | case RTC_IRQP_SET: |
312 | /* check for power of 2 */ | 313 | if (!is_power_of_2(arg)) { |
313 | |||
314 | if ((arg & (arg-1)) != 0 || arg < 1) { | ||
315 | ret = -EINVAL; | 314 | ret = -EINVAL; |
316 | goto exit; | 315 | goto exit; |
317 | } | 316 | } |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 2eb38520f0c8..ee253cc45de1 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -357,23 +357,15 @@ static int sa1100_rtc_remove(struct platform_device *pdev) | |||
357 | #ifdef CONFIG_PM | 357 | #ifdef CONFIG_PM |
358 | static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 358 | static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
359 | { | 359 | { |
360 | if (pdev->dev.power.power_state.event != state.event) { | 360 | if (device_may_wakeup(&pdev->dev)) |
361 | if (state.event == PM_EVENT_SUSPEND && | 361 | enable_irq_wake(IRQ_RTCAlrm); |
362 | device_may_wakeup(&pdev->dev)) | ||
363 | enable_irq_wake(IRQ_RTCAlrm); | ||
364 | |||
365 | pdev->dev.power.power_state = state; | ||
366 | } | ||
367 | return 0; | 362 | return 0; |
368 | } | 363 | } |
369 | 364 | ||
370 | static int sa1100_rtc_resume(struct platform_device *pdev) | 365 | static int sa1100_rtc_resume(struct platform_device *pdev) |
371 | { | 366 | { |
372 | if (pdev->dev.power.power_state.event != PM_EVENT_ON) { | 367 | if (device_may_wakeup(&pdev->dev)) |
373 | if (device_may_wakeup(&pdev->dev)) | 368 | disable_irq_wake(IRQ_RTCAlrm); |
374 | disable_irq_wake(IRQ_RTCAlrm); | ||
375 | pdev->dev.power.power_state = PMSG_ON; | ||
376 | } | ||
377 | return 0; | 369 | return 0; |
378 | } | 370 | } |
379 | #else | 371 | #else |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 2ae0e8304d3a..4d27ccc4fc06 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
@@ -17,6 +17,13 @@ | |||
17 | 17 | ||
18 | /* device attributes */ | 18 | /* device attributes */ |
19 | 19 | ||
20 | /* | ||
21 | * NOTE: RTC times displayed in sysfs use the RTC's timezone. That's | ||
22 | * ideally UTC. However, PCs that also boot to MS-Windows normally use | ||
23 | * the local time and change to match daylight savings time. That affects | ||
24 | * attributes including date, time, since_epoch, and wakealarm. | ||
25 | */ | ||
26 | |||
20 | static ssize_t | 27 | static ssize_t |
21 | rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, | 28 | rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, |
22 | char *buf) | 29 | char *buf) |
@@ -113,13 +120,13 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, | |||
113 | unsigned long alarm; | 120 | unsigned long alarm; |
114 | struct rtc_wkalrm alm; | 121 | struct rtc_wkalrm alm; |
115 | 122 | ||
116 | /* Don't show disabled alarms; but the RTC could leave the | 123 | /* Don't show disabled alarms. For uniformity, RTC alarms are |
117 | * alarm enabled after it's already triggered. Alarms are | 124 | * conceptually one-shot, even though some common RTCs (on PCs) |
118 | * conceptually one-shot, even though some common hardware | 125 | * don't actually work that way. |
119 | * (PCs) doesn't actually work that way. | ||
120 | * | 126 | * |
121 | * REVISIT maybe we should require RTC implementations to | 127 | * NOTE: RTC implementations where the alarm doesn't match an |
122 | * disable the RTC alarm after it triggers, for uniformity. | 128 | * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC |
129 | * alarms after they trigger, to ensure one-shot semantics. | ||
123 | */ | 130 | */ |
124 | retval = rtc_read_alarm(to_rtc_device(dev), &alm); | 131 | retval = rtc_read_alarm(to_rtc_device(dev), &alm); |
125 | if (retval == 0 && alm.enabled) { | 132 | if (retval == 0 && alm.enabled) { |
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c index 19343f9675c3..291ff6235fe2 100644 --- a/drivers/s390/sysinfo.c +++ b/drivers/s390/sysinfo.c | |||
@@ -422,7 +422,7 @@ void s390_adjust_jiffies(void) | |||
422 | /* | 422 | /* |
423 | * calibrate the delay loop | 423 | * calibrate the delay loop |
424 | */ | 424 | */ |
425 | void __init calibrate_delay(void) | 425 | void __cpuinit calibrate_delay(void) |
426 | { | 426 | { |
427 | s390_adjust_jiffies(); | 427 | s390_adjust_jiffies(); |
428 | /* Print the good old Bogomips line .. */ | 428 | /* Print the good old Bogomips line .. */ |
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 23f27c9c9895..5ac3a3e8dfaf 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c | |||
@@ -46,8 +46,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
46 | struct Scsi_Host *instance = cmd->device->host; | 46 | struct Scsi_Host *instance = cmd->device->host; |
47 | 47 | ||
48 | /* don't allow DMA if the physical address is bad */ | 48 | /* don't allow DMA if the physical address is bad */ |
49 | if (addr & A2091_XFER_MASK || | 49 | if (addr & A2091_XFER_MASK) |
50 | (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) | ||
51 | { | 50 | { |
52 | HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511) | 51 | HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511) |
53 | & ~0x1ff; | 52 | & ~0x1ff; |
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index d7255c8bf281..3aeec963940b 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c | |||
@@ -54,8 +54,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
54 | * end of a physical memory chunk, then allocate a bounce | 54 | * end of a physical memory chunk, then allocate a bounce |
55 | * buffer | 55 | * buffer |
56 | */ | 56 | */ |
57 | if (addr & A3000_XFER_MASK || | 57 | if (addr & A3000_XFER_MASK) |
58 | (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) | ||
59 | { | 58 | { |
60 | HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511) | 59 | HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511) |
61 | & ~0x1ff; | 60 | & ~0x1ff; |
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 3bfd9296bbfa..93984c9dfe14 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c | |||
@@ -6472,7 +6472,7 @@ do_aic7xxx_isr(int irq, void *dev_id) | |||
6472 | unsigned long cpu_flags; | 6472 | unsigned long cpu_flags; |
6473 | struct aic7xxx_host *p; | 6473 | struct aic7xxx_host *p; |
6474 | 6474 | ||
6475 | p = (struct aic7xxx_host *)dev_id; | 6475 | p = dev_id; |
6476 | if(!p) | 6476 | if(!p) |
6477 | return IRQ_NONE; | 6477 | return IRQ_NONE; |
6478 | spin_lock_irqsave(p->host->host_lock, cpu_flags); | 6478 | spin_lock_irqsave(p->host->host_lock, cpu_flags); |
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 37741e9b5c3b..91f85226d08f 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c | |||
@@ -54,8 +54,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
54 | static int scsi_alloc_out_of_range = 0; | 54 | static int scsi_alloc_out_of_range = 0; |
55 | 55 | ||
56 | /* use bounce buffer if the physical address is bad */ | 56 | /* use bounce buffer if the physical address is bad */ |
57 | if (addr & HDATA(cmd->device->host)->dma_xfer_mask || | 57 | if (addr & HDATA(cmd->device->host)->dma_xfer_mask) |
58 | (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) | ||
59 | { | 58 | { |
60 | HDATA(cmd->device->host)->dma_bounce_len = (cmd->SCp.this_residual + 511) | 59 | HDATA(cmd->device->host)->dma_bounce_len = (cmd->SCp.this_residual + 511) |
61 | & ~0x1ff; | 60 | & ~0x1ff; |
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index d63f11e95abf..bd62131b97a1 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c | |||
@@ -539,9 +539,9 @@ out: | |||
539 | srp_iu_put(iue); | 539 | srp_iu_put(iue); |
540 | } | 540 | } |
541 | 541 | ||
542 | static irqreturn_t ibmvstgt_interrupt(int irq, void *data) | 542 | static irqreturn_t ibmvstgt_interrupt(int dummy, void *data) |
543 | { | 543 | { |
544 | struct srp_target *target = (struct srp_target *) data; | 544 | struct srp_target *target = data; |
545 | struct vio_port *vport = target_to_port(target); | 545 | struct vio_port *vport = target_to_port(target); |
546 | 546 | ||
547 | vio_disable_interrupts(vport->dma_dev); | 547 | vio_disable_interrupts(vport->dma_dev); |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 4fa7927997ad..6a44fb1dc167 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -877,15 +877,15 @@ config SERIAL_SUNHV | |||
877 | systems. Say Y if you want to be able to use this device. | 877 | systems. Say Y if you want to be able to use this device. |
878 | 878 | ||
879 | config SERIAL_IP22_ZILOG | 879 | config SERIAL_IP22_ZILOG |
880 | tristate "IP22 Zilog8530 serial support" | 880 | tristate "SGI Zilog8530 serial support" |
881 | depends on SGI_IP22 | 881 | depends on SGI_HAS_ZILOG |
882 | select SERIAL_CORE | 882 | select SERIAL_CORE |
883 | help | 883 | help |
884 | This driver supports the Zilog8530 serial ports found on SGI IP22 | 884 | This driver supports the Zilog8530 serial ports found on SGI |
885 | systems. Say Y or M if you want to be able to these serial ports. | 885 | systems. Say Y or M if you want to be able to these serial ports. |
886 | 886 | ||
887 | config SERIAL_IP22_ZILOG_CONSOLE | 887 | config SERIAL_IP22_ZILOG_CONSOLE |
888 | bool "Console on IP22 Zilog8530 serial port" | 888 | bool "Console on SGI Zilog8530 serial port" |
889 | depends on SERIAL_IP22_ZILOG=y | 889 | depends on SERIAL_IP22_ZILOG=y |
890 | select SERIAL_CORE_CONSOLE | 890 | select SERIAL_CORE_CONSOLE |
891 | 891 | ||
@@ -1318,4 +1318,19 @@ config SERIAL_QE | |||
1318 | This driver supports the QE serial ports on Freescale embedded | 1318 | This driver supports the QE serial ports on Freescale embedded |
1319 | PowerPC that contain a QUICC Engine. | 1319 | PowerPC that contain a QUICC Engine. |
1320 | 1320 | ||
1321 | config SERIAL_SC26XX | ||
1322 | tristate "SC2681/SC2692 serial port support" | ||
1323 | depends on SNI_RM | ||
1324 | select SERIAL_CORE | ||
1325 | help | ||
1326 | This is a driver for the onboard serial ports of | ||
1327 | older RM400 machines. | ||
1328 | |||
1329 | config SERIAL_SC26XX_CONSOLE | ||
1330 | bool "Console on SC2681/SC2692 serial port" | ||
1331 | depends on SERIAL_SC26XX | ||
1332 | select SERIAL_CORE_CONSOLE | ||
1333 | help | ||
1334 | Support for Console on SC2681/SC2692 serial ports. | ||
1335 | |||
1321 | endmenu | 1336 | endmenu |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 2dd41b4cc8db..640cfe44a56d 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -55,6 +55,7 @@ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o | |||
55 | obj-$(CONFIG_SERIAL_MPSC) += mpsc.o | 55 | obj-$(CONFIG_SERIAL_MPSC) += mpsc.o |
56 | obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o | 56 | obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o |
57 | obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o | 57 | obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o |
58 | obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o | ||
58 | obj-$(CONFIG_SERIAL_JSM) += jsm/ | 59 | obj-$(CONFIG_SERIAL_JSM) += jsm/ |
59 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o | 60 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o |
60 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o | 61 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index b5e4478de0e3..236af9d33851 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -380,7 +380,7 @@ static void cpm_uart_int_rx(struct uart_port *port) | |||
380 | static irqreturn_t cpm_uart_int(int irq, void *data) | 380 | static irqreturn_t cpm_uart_int(int irq, void *data) |
381 | { | 381 | { |
382 | u8 events; | 382 | u8 events; |
383 | struct uart_port *port = (struct uart_port *)data; | 383 | struct uart_port *port = data; |
384 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | 384 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; |
385 | smc_t __iomem *smcp = pinfo->smcp; | 385 | smc_t __iomem *smcp = pinfo->smcp; |
386 | scc_t __iomem *sccp = pinfo->sccp; | 386 | scc_t __iomem *sccp = pinfo->sccp; |
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index d31721f2744d..bbae5a220219 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -324,7 +324,7 @@ static inline void check_modem_status(struct dz_port *dport) | |||
324 | */ | 324 | */ |
325 | static irqreturn_t dz_interrupt(int irq, void *dev) | 325 | static irqreturn_t dz_interrupt(int irq, void *dev) |
326 | { | 326 | { |
327 | struct dz_port *dport = (struct dz_port *)dev; | 327 | struct dz_port *dport = dev; |
328 | unsigned short status; | 328 | unsigned short status; |
329 | 329 | ||
330 | /* get the reason why we just got an irq */ | 330 | /* get the reason why we just got an irq */ |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index dc1967176fe2..56af1f566a4c 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -308,7 +308,7 @@ static void imx_start_tx(struct uart_port *port) | |||
308 | 308 | ||
309 | static irqreturn_t imx_rtsint(int irq, void *dev_id) | 309 | static irqreturn_t imx_rtsint(int irq, void *dev_id) |
310 | { | 310 | { |
311 | struct imx_port *sport = (struct imx_port *)dev_id; | 311 | struct imx_port *sport = dev_id; |
312 | unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; | 312 | unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; |
313 | unsigned long flags; | 313 | unsigned long flags; |
314 | 314 | ||
@@ -324,7 +324,7 @@ static irqreturn_t imx_rtsint(int irq, void *dev_id) | |||
324 | 324 | ||
325 | static irqreturn_t imx_txint(int irq, void *dev_id) | 325 | static irqreturn_t imx_txint(int irq, void *dev_id) |
326 | { | 326 | { |
327 | struct imx_port *sport = (struct imx_port *)dev_id; | 327 | struct imx_port *sport = dev_id; |
328 | struct circ_buf *xmit = &sport->port.info->xmit; | 328 | struct circ_buf *xmit = &sport->port.info->xmit; |
329 | unsigned long flags; | 329 | unsigned long flags; |
330 | 330 | ||
diff --git a/drivers/serial/sc26xx.c b/drivers/serial/sc26xx.c new file mode 100644 index 000000000000..a350b6d2a181 --- /dev/null +++ b/drivers/serial/sc26xx.c | |||
@@ -0,0 +1,755 @@ | |||
1 | /* | ||
2 | * SC268xx.c: Serial driver for Philiphs SC2681/SC2692 devices. | ||
3 | * | ||
4 | * Copyright (C) 2006,2007 Thomas Bogendörfer (tsbogend@alpha.franken.de) | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/tty.h> | ||
11 | #include <linux/tty_flip.h> | ||
12 | #include <linux/major.h> | ||
13 | #include <linux/circ_buf.h> | ||
14 | #include <linux/serial.h> | ||
15 | #include <linux/sysrq.h> | ||
16 | #include <linux/console.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/irq.h> | ||
23 | |||
24 | #if defined(CONFIG_MAGIC_SYSRQ) | ||
25 | #define SUPPORT_SYSRQ | ||
26 | #endif | ||
27 | |||
28 | #include <linux/serial_core.h> | ||
29 | |||
30 | #define SC26XX_MAJOR 204 | ||
31 | #define SC26XX_MINOR_START 205 | ||
32 | #define SC26XX_NR 2 | ||
33 | |||
34 | struct uart_sc26xx_port { | ||
35 | struct uart_port port[2]; | ||
36 | u8 dsr_mask[2]; | ||
37 | u8 cts_mask[2]; | ||
38 | u8 dcd_mask[2]; | ||
39 | u8 ri_mask[2]; | ||
40 | u8 dtr_mask[2]; | ||
41 | u8 rts_mask[2]; | ||
42 | u8 imr; | ||
43 | }; | ||
44 | |||
45 | /* register common to both ports */ | ||
46 | #define RD_ISR 0x14 | ||
47 | #define RD_IPR 0x34 | ||
48 | |||
49 | #define WR_ACR 0x10 | ||
50 | #define WR_IMR 0x14 | ||
51 | #define WR_OPCR 0x34 | ||
52 | #define WR_OPR_SET 0x38 | ||
53 | #define WR_OPR_CLR 0x3C | ||
54 | |||
55 | /* access common register */ | ||
56 | #define READ_SC(p, r) readb((p)->membase + RD_##r) | ||
57 | #define WRITE_SC(p, r, v) writeb((v), (p)->membase + WR_##r) | ||
58 | |||
59 | /* register per port */ | ||
60 | #define RD_PORT_MRx 0x00 | ||
61 | #define RD_PORT_SR 0x04 | ||
62 | #define RD_PORT_RHR 0x0c | ||
63 | |||
64 | #define WR_PORT_MRx 0x00 | ||
65 | #define WR_PORT_CSR 0x04 | ||
66 | #define WR_PORT_CR 0x08 | ||
67 | #define WR_PORT_THR 0x0c | ||
68 | |||
69 | /* SR bits */ | ||
70 | #define SR_BREAK (1 << 7) | ||
71 | #define SR_FRAME (1 << 6) | ||
72 | #define SR_PARITY (1 << 5) | ||
73 | #define SR_OVERRUN (1 << 4) | ||
74 | #define SR_TXRDY (1 << 2) | ||
75 | #define SR_RXRDY (1 << 0) | ||
76 | |||
77 | #define CR_RES_MR (1 << 4) | ||
78 | #define CR_RES_RX (2 << 4) | ||
79 | #define CR_RES_TX (3 << 4) | ||
80 | #define CR_STRT_BRK (6 << 4) | ||
81 | #define CR_STOP_BRK (7 << 4) | ||
82 | #define CR_DIS_TX (1 << 3) | ||
83 | #define CR_ENA_TX (1 << 2) | ||
84 | #define CR_DIS_RX (1 << 1) | ||
85 | #define CR_ENA_RX (1 << 0) | ||
86 | |||
87 | /* ISR bits */ | ||
88 | #define ISR_RXRDYB (1 << 5) | ||
89 | #define ISR_TXRDYB (1 << 4) | ||
90 | #define ISR_RXRDYA (1 << 1) | ||
91 | #define ISR_TXRDYA (1 << 0) | ||
92 | |||
93 | /* IMR bits */ | ||
94 | #define IMR_RXRDY (1 << 1) | ||
95 | #define IMR_TXRDY (1 << 0) | ||
96 | |||
97 | /* access port register */ | ||
98 | static inline u8 read_sc_port(struct uart_port *p, u8 reg) | ||
99 | { | ||
100 | return readb(p->membase + p->line * 0x20 + reg); | ||
101 | } | ||
102 | |||
103 | static inline void write_sc_port(struct uart_port *p, u8 reg, u8 val) | ||
104 | { | ||
105 | writeb(val, p->membase + p->line * 0x20 + reg); | ||
106 | } | ||
107 | |||
108 | #define READ_SC_PORT(p, r) read_sc_port(p, RD_PORT_##r) | ||
109 | #define WRITE_SC_PORT(p, r, v) write_sc_port(p, WR_PORT_##r, v) | ||
110 | |||
111 | static void sc26xx_enable_irq(struct uart_port *port, int mask) | ||
112 | { | ||
113 | struct uart_sc26xx_port *up; | ||
114 | int line = port->line; | ||
115 | |||
116 | port -= line; | ||
117 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
118 | |||
119 | up->imr |= mask << (line * 4); | ||
120 | WRITE_SC(port, IMR, up->imr); | ||
121 | } | ||
122 | |||
123 | static void sc26xx_disable_irq(struct uart_port *port, int mask) | ||
124 | { | ||
125 | struct uart_sc26xx_port *up; | ||
126 | int line = port->line; | ||
127 | |||
128 | port -= line; | ||
129 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
130 | |||
131 | up->imr &= ~(mask << (line * 4)); | ||
132 | WRITE_SC(port, IMR, up->imr); | ||
133 | } | ||
134 | |||
135 | static struct tty_struct *receive_chars(struct uart_port *port) | ||
136 | { | ||
137 | struct tty_struct *tty = NULL; | ||
138 | int limit = 10000; | ||
139 | unsigned char ch; | ||
140 | char flag; | ||
141 | u8 status; | ||
142 | |||
143 | if (port->info != NULL) /* Unopened serial console */ | ||
144 | tty = port->info->tty; | ||
145 | |||
146 | while (limit-- > 0) { | ||
147 | status = READ_SC_PORT(port, SR); | ||
148 | if (!(status & SR_RXRDY)) | ||
149 | break; | ||
150 | ch = READ_SC_PORT(port, RHR); | ||
151 | |||
152 | flag = TTY_NORMAL; | ||
153 | port->icount.rx++; | ||
154 | |||
155 | if (unlikely(status & (SR_BREAK | SR_FRAME | | ||
156 | SR_PARITY | SR_OVERRUN))) { | ||
157 | if (status & SR_BREAK) { | ||
158 | status &= ~(SR_PARITY | SR_FRAME); | ||
159 | port->icount.brk++; | ||
160 | if (uart_handle_break(port)) | ||
161 | continue; | ||
162 | } else if (status & SR_PARITY) | ||
163 | port->icount.parity++; | ||
164 | else if (status & SR_FRAME) | ||
165 | port->icount.frame++; | ||
166 | if (status & SR_OVERRUN) | ||
167 | port->icount.overrun++; | ||
168 | |||
169 | status &= port->read_status_mask; | ||
170 | if (status & SR_BREAK) | ||
171 | flag = TTY_BREAK; | ||
172 | else if (status & SR_PARITY) | ||
173 | flag = TTY_PARITY; | ||
174 | else if (status & SR_FRAME) | ||
175 | flag = TTY_FRAME; | ||
176 | } | ||
177 | |||
178 | if (uart_handle_sysrq_char(port, ch)) | ||
179 | continue; | ||
180 | |||
181 | if (status & port->ignore_status_mask) | ||
182 | continue; | ||
183 | |||
184 | tty_insert_flip_char(tty, ch, flag); | ||
185 | } | ||
186 | return tty; | ||
187 | } | ||
188 | |||
189 | static void transmit_chars(struct uart_port *port) | ||
190 | { | ||
191 | struct circ_buf *xmit; | ||
192 | |||
193 | if (!port->info) | ||
194 | return; | ||
195 | |||
196 | xmit = &port->info->xmit; | ||
197 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
198 | sc26xx_disable_irq(port, IMR_TXRDY); | ||
199 | return; | ||
200 | } | ||
201 | while (!uart_circ_empty(xmit)) { | ||
202 | if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) | ||
203 | break; | ||
204 | |||
205 | WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); | ||
206 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
207 | port->icount.tx++; | ||
208 | } | ||
209 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
210 | uart_write_wakeup(port); | ||
211 | } | ||
212 | |||
213 | static irqreturn_t sc26xx_interrupt(int irq, void *dev_id) | ||
214 | { | ||
215 | struct uart_sc26xx_port *up = dev_id; | ||
216 | struct tty_struct *tty; | ||
217 | unsigned long flags; | ||
218 | u8 isr; | ||
219 | |||
220 | spin_lock_irqsave(&up->port[0].lock, flags); | ||
221 | |||
222 | tty = NULL; | ||
223 | isr = READ_SC(&up->port[0], ISR); | ||
224 | if (isr & ISR_TXRDYA) | ||
225 | transmit_chars(&up->port[0]); | ||
226 | if (isr & ISR_RXRDYA) | ||
227 | tty = receive_chars(&up->port[0]); | ||
228 | |||
229 | spin_unlock(&up->port[0].lock); | ||
230 | |||
231 | if (tty) | ||
232 | tty_flip_buffer_push(tty); | ||
233 | |||
234 | spin_lock(&up->port[1].lock); | ||
235 | |||
236 | tty = NULL; | ||
237 | if (isr & ISR_TXRDYB) | ||
238 | transmit_chars(&up->port[1]); | ||
239 | if (isr & ISR_RXRDYB) | ||
240 | tty = receive_chars(&up->port[1]); | ||
241 | |||
242 | spin_unlock_irqrestore(&up->port[1].lock, flags); | ||
243 | |||
244 | if (tty) | ||
245 | tty_flip_buffer_push(tty); | ||
246 | |||
247 | return IRQ_HANDLED; | ||
248 | } | ||
249 | |||
250 | /* port->lock is not held. */ | ||
251 | static unsigned int sc26xx_tx_empty(struct uart_port *port) | ||
252 | { | ||
253 | return (READ_SC_PORT(port, SR) & SR_TXRDY) ? TIOCSER_TEMT : 0; | ||
254 | } | ||
255 | |||
256 | /* port->lock held by caller. */ | ||
257 | static void sc26xx_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
258 | { | ||
259 | struct uart_sc26xx_port *up; | ||
260 | int line = port->line; | ||
261 | |||
262 | port -= line; | ||
263 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
264 | |||
265 | if (up->dtr_mask[line]) { | ||
266 | if (mctrl & TIOCM_DTR) | ||
267 | WRITE_SC(port, OPR_SET, up->dtr_mask[line]); | ||
268 | else | ||
269 | WRITE_SC(port, OPR_CLR, up->dtr_mask[line]); | ||
270 | } | ||
271 | if (up->rts_mask[line]) { | ||
272 | if (mctrl & TIOCM_RTS) | ||
273 | WRITE_SC(port, OPR_SET, up->rts_mask[line]); | ||
274 | else | ||
275 | WRITE_SC(port, OPR_CLR, up->rts_mask[line]); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | /* port->lock is held by caller and interrupts are disabled. */ | ||
280 | static unsigned int sc26xx_get_mctrl(struct uart_port *port) | ||
281 | { | ||
282 | struct uart_sc26xx_port *up; | ||
283 | int line = port->line; | ||
284 | unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; | ||
285 | u8 ipr; | ||
286 | |||
287 | port -= line; | ||
288 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
289 | ipr = READ_SC(port, IPR) ^ 0xff; | ||
290 | |||
291 | if (up->dsr_mask[line]) { | ||
292 | mctrl &= ~TIOCM_DSR; | ||
293 | mctrl |= ipr & up->dsr_mask[line] ? TIOCM_DSR : 0; | ||
294 | } | ||
295 | if (up->cts_mask[line]) { | ||
296 | mctrl &= ~TIOCM_CTS; | ||
297 | mctrl |= ipr & up->cts_mask[line] ? TIOCM_CTS : 0; | ||
298 | } | ||
299 | if (up->dcd_mask[line]) { | ||
300 | mctrl &= ~TIOCM_CAR; | ||
301 | mctrl |= ipr & up->dcd_mask[line] ? TIOCM_CAR : 0; | ||
302 | } | ||
303 | if (up->ri_mask[line]) { | ||
304 | mctrl &= ~TIOCM_RNG; | ||
305 | mctrl |= ipr & up->ri_mask[line] ? TIOCM_RNG : 0; | ||
306 | } | ||
307 | return mctrl; | ||
308 | } | ||
309 | |||
310 | /* port->lock held by caller. */ | ||
311 | static void sc26xx_stop_tx(struct uart_port *port) | ||
312 | { | ||
313 | return; | ||
314 | } | ||
315 | |||
316 | /* port->lock held by caller. */ | ||
317 | static void sc26xx_start_tx(struct uart_port *port) | ||
318 | { | ||
319 | struct circ_buf *xmit = &port->info->xmit; | ||
320 | |||
321 | while (!uart_circ_empty(xmit)) { | ||
322 | if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) { | ||
323 | sc26xx_enable_irq(port, IMR_TXRDY); | ||
324 | break; | ||
325 | } | ||
326 | WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); | ||
327 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
328 | port->icount.tx++; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /* port->lock held by caller. */ | ||
333 | static void sc26xx_stop_rx(struct uart_port *port) | ||
334 | { | ||
335 | } | ||
336 | |||
337 | /* port->lock held by caller. */ | ||
338 | static void sc26xx_enable_ms(struct uart_port *port) | ||
339 | { | ||
340 | } | ||
341 | |||
342 | /* port->lock is not held. */ | ||
343 | static void sc26xx_break_ctl(struct uart_port *port, int break_state) | ||
344 | { | ||
345 | if (break_state == -1) | ||
346 | WRITE_SC_PORT(port, CR, CR_STRT_BRK); | ||
347 | else | ||
348 | WRITE_SC_PORT(port, CR, CR_STOP_BRK); | ||
349 | } | ||
350 | |||
351 | /* port->lock is not held. */ | ||
352 | static int sc26xx_startup(struct uart_port *port) | ||
353 | { | ||
354 | sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY); | ||
355 | WRITE_SC(port, OPCR, 0); | ||
356 | |||
357 | /* reset tx and rx */ | ||
358 | WRITE_SC_PORT(port, CR, CR_RES_RX); | ||
359 | WRITE_SC_PORT(port, CR, CR_RES_TX); | ||
360 | |||
361 | /* start rx/tx */ | ||
362 | WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); | ||
363 | |||
364 | /* enable irqs */ | ||
365 | sc26xx_enable_irq(port, IMR_RXRDY); | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /* port->lock is not held. */ | ||
370 | static void sc26xx_shutdown(struct uart_port *port) | ||
371 | { | ||
372 | /* disable interrupst */ | ||
373 | sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY); | ||
374 | |||
375 | /* stop tx/rx */ | ||
376 | WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); | ||
377 | } | ||
378 | |||
379 | /* port->lock is not held. */ | ||
380 | static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios, | ||
381 | struct ktermios *old) | ||
382 | { | ||
383 | unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); | ||
384 | unsigned int quot = uart_get_divisor(port, baud); | ||
385 | unsigned int iflag, cflag; | ||
386 | unsigned long flags; | ||
387 | u8 mr1, mr2, csr; | ||
388 | |||
389 | spin_lock_irqsave(&port->lock, flags); | ||
390 | |||
391 | while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) | ||
392 | udelay(2); | ||
393 | |||
394 | WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); | ||
395 | |||
396 | iflag = termios->c_iflag; | ||
397 | cflag = termios->c_cflag; | ||
398 | |||
399 | port->read_status_mask = SR_OVERRUN; | ||
400 | if (iflag & INPCK) | ||
401 | port->read_status_mask |= SR_PARITY | SR_FRAME; | ||
402 | if (iflag & (BRKINT | PARMRK)) | ||
403 | port->read_status_mask |= SR_BREAK; | ||
404 | |||
405 | port->ignore_status_mask = 0; | ||
406 | if (iflag & IGNBRK) | ||
407 | port->ignore_status_mask |= SR_BREAK; | ||
408 | if ((cflag & CREAD) == 0) | ||
409 | port->ignore_status_mask |= SR_BREAK | SR_FRAME | | ||
410 | SR_PARITY | SR_OVERRUN; | ||
411 | |||
412 | switch (cflag & CSIZE) { | ||
413 | case CS5: | ||
414 | mr1 = 0x00; | ||
415 | break; | ||
416 | case CS6: | ||
417 | mr1 = 0x01; | ||
418 | break; | ||
419 | case CS7: | ||
420 | mr1 = 0x02; | ||
421 | break; | ||
422 | default: | ||
423 | case CS8: | ||
424 | mr1 = 0x03; | ||
425 | break; | ||
426 | } | ||
427 | mr2 = 0x07; | ||
428 | if (cflag & CSTOPB) | ||
429 | mr2 = 0x0f; | ||
430 | if (cflag & PARENB) { | ||
431 | if (cflag & PARODD) | ||
432 | mr1 |= (1 << 2); | ||
433 | } else | ||
434 | mr1 |= (2 << 3); | ||
435 | |||
436 | switch (baud) { | ||
437 | case 50: | ||
438 | csr = 0x00; | ||
439 | break; | ||
440 | case 110: | ||
441 | csr = 0x11; | ||
442 | break; | ||
443 | case 134: | ||
444 | csr = 0x22; | ||
445 | break; | ||
446 | case 200: | ||
447 | csr = 0x33; | ||
448 | break; | ||
449 | case 300: | ||
450 | csr = 0x44; | ||
451 | break; | ||
452 | case 600: | ||
453 | csr = 0x55; | ||
454 | break; | ||
455 | case 1200: | ||
456 | csr = 0x66; | ||
457 | break; | ||
458 | case 2400: | ||
459 | csr = 0x88; | ||
460 | break; | ||
461 | case 4800: | ||
462 | csr = 0x99; | ||
463 | break; | ||
464 | default: | ||
465 | case 9600: | ||
466 | csr = 0xbb; | ||
467 | break; | ||
468 | case 19200: | ||
469 | csr = 0xcc; | ||
470 | break; | ||
471 | } | ||
472 | |||
473 | WRITE_SC_PORT(port, CR, CR_RES_MR); | ||
474 | WRITE_SC_PORT(port, MRx, mr1); | ||
475 | WRITE_SC_PORT(port, MRx, mr2); | ||
476 | |||
477 | WRITE_SC(port, ACR, 0x80); | ||
478 | WRITE_SC_PORT(port, CSR, csr); | ||
479 | |||
480 | /* reset tx and rx */ | ||
481 | WRITE_SC_PORT(port, CR, CR_RES_RX); | ||
482 | WRITE_SC_PORT(port, CR, CR_RES_TX); | ||
483 | |||
484 | WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); | ||
485 | while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) | ||
486 | udelay(2); | ||
487 | |||
488 | /* XXX */ | ||
489 | uart_update_timeout(port, cflag, | ||
490 | (port->uartclk / (16 * quot))); | ||
491 | |||
492 | spin_unlock_irqrestore(&port->lock, flags); | ||
493 | } | ||
494 | |||
495 | static const char *sc26xx_type(struct uart_port *port) | ||
496 | { | ||
497 | return "SC26XX"; | ||
498 | } | ||
499 | |||
500 | static void sc26xx_release_port(struct uart_port *port) | ||
501 | { | ||
502 | } | ||
503 | |||
504 | static int sc26xx_request_port(struct uart_port *port) | ||
505 | { | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static void sc26xx_config_port(struct uart_port *port, int flags) | ||
510 | { | ||
511 | } | ||
512 | |||
513 | static int sc26xx_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
514 | { | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | |||
518 | static struct uart_ops sc26xx_ops = { | ||
519 | .tx_empty = sc26xx_tx_empty, | ||
520 | .set_mctrl = sc26xx_set_mctrl, | ||
521 | .get_mctrl = sc26xx_get_mctrl, | ||
522 | .stop_tx = sc26xx_stop_tx, | ||
523 | .start_tx = sc26xx_start_tx, | ||
524 | .stop_rx = sc26xx_stop_rx, | ||
525 | .enable_ms = sc26xx_enable_ms, | ||
526 | .break_ctl = sc26xx_break_ctl, | ||
527 | .startup = sc26xx_startup, | ||
528 | .shutdown = sc26xx_shutdown, | ||
529 | .set_termios = sc26xx_set_termios, | ||
530 | .type = sc26xx_type, | ||
531 | .release_port = sc26xx_release_port, | ||
532 | .request_port = sc26xx_request_port, | ||
533 | .config_port = sc26xx_config_port, | ||
534 | .verify_port = sc26xx_verify_port, | ||
535 | }; | ||
536 | |||
537 | static struct uart_port *sc26xx_port; | ||
538 | |||
539 | #ifdef CONFIG_SERIAL_SC26XX_CONSOLE | ||
540 | static void sc26xx_console_putchar(struct uart_port *port, char c) | ||
541 | { | ||
542 | unsigned long flags; | ||
543 | int limit = 1000000; | ||
544 | |||
545 | spin_lock_irqsave(&port->lock, flags); | ||
546 | |||
547 | while (limit-- > 0) { | ||
548 | if (READ_SC_PORT(port, SR) & SR_TXRDY) { | ||
549 | WRITE_SC_PORT(port, THR, c); | ||
550 | break; | ||
551 | } | ||
552 | udelay(2); | ||
553 | } | ||
554 | |||
555 | spin_unlock_irqrestore(&port->lock, flags); | ||
556 | } | ||
557 | |||
558 | static void sc26xx_console_write(struct console *con, const char *s, unsigned n) | ||
559 | { | ||
560 | struct uart_port *port = sc26xx_port; | ||
561 | int i; | ||
562 | |||
563 | for (i = 0; i < n; i++) { | ||
564 | if (*s == '\n') | ||
565 | sc26xx_console_putchar(port, '\r'); | ||
566 | sc26xx_console_putchar(port, *s++); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | static int __init sc26xx_console_setup(struct console *con, char *options) | ||
571 | { | ||
572 | struct uart_port *port = sc26xx_port; | ||
573 | int baud = 9600; | ||
574 | int bits = 8; | ||
575 | int parity = 'n'; | ||
576 | int flow = 'n'; | ||
577 | |||
578 | if (port->type != PORT_SC26XX) | ||
579 | return -1; | ||
580 | |||
581 | printk(KERN_INFO "Console: ttySC%d (SC26XX)\n", con->index); | ||
582 | if (options) | ||
583 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
584 | |||
585 | return uart_set_options(port, con, baud, parity, bits, flow); | ||
586 | } | ||
587 | |||
588 | static struct uart_driver sc26xx_reg; | ||
589 | static struct console sc26xx_console = { | ||
590 | .name = "ttySC", | ||
591 | .write = sc26xx_console_write, | ||
592 | .device = uart_console_device, | ||
593 | .setup = sc26xx_console_setup, | ||
594 | .flags = CON_PRINTBUFFER, | ||
595 | .index = -1, | ||
596 | .data = &sc26xx_reg, | ||
597 | }; | ||
598 | #define SC26XX_CONSOLE &sc26xx_console | ||
599 | #else | ||
600 | #define SC26XX_CONSOLE NULL | ||
601 | #endif | ||
602 | |||
603 | static struct uart_driver sc26xx_reg = { | ||
604 | .owner = THIS_MODULE, | ||
605 | .driver_name = "SC26xx", | ||
606 | .dev_name = "ttySC", | ||
607 | .major = SC26XX_MAJOR, | ||
608 | .minor = SC26XX_MINOR_START, | ||
609 | .nr = SC26XX_NR, | ||
610 | .cons = SC26XX_CONSOLE, | ||
611 | }; | ||
612 | |||
613 | static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos) | ||
614 | { | ||
615 | unsigned int bit = (flags >> bitpos) & 15; | ||
616 | |||
617 | return bit ? (1 << (bit - 1)) : 0; | ||
618 | } | ||
619 | |||
620 | static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up, | ||
621 | int line, unsigned int data) | ||
622 | { | ||
623 | up->dtr_mask[line] = sc26xx_flags2mask(data, 0); | ||
624 | up->rts_mask[line] = sc26xx_flags2mask(data, 4); | ||
625 | up->dsr_mask[line] = sc26xx_flags2mask(data, 8); | ||
626 | up->cts_mask[line] = sc26xx_flags2mask(data, 12); | ||
627 | up->dcd_mask[line] = sc26xx_flags2mask(data, 16); | ||
628 | up->ri_mask[line] = sc26xx_flags2mask(data, 20); | ||
629 | } | ||
630 | |||
631 | static int __devinit sc26xx_probe(struct platform_device *dev) | ||
632 | { | ||
633 | struct resource *res; | ||
634 | struct uart_sc26xx_port *up; | ||
635 | unsigned int *sc26xx_data = dev->dev.platform_data; | ||
636 | int err; | ||
637 | |||
638 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
639 | if (!res) | ||
640 | return -ENODEV; | ||
641 | |||
642 | up = kzalloc(sizeof *up, GFP_KERNEL); | ||
643 | if (unlikely(!up)) | ||
644 | return -ENOMEM; | ||
645 | |||
646 | up->port[0].line = 0; | ||
647 | up->port[0].ops = &sc26xx_ops; | ||
648 | up->port[0].type = PORT_SC26XX; | ||
649 | up->port[0].uartclk = (29491200 / 16); /* arbitrary */ | ||
650 | |||
651 | up->port[0].mapbase = res->start; | ||
652 | up->port[0].membase = ioremap_nocache(up->port[0].mapbase, 0x40); | ||
653 | up->port[0].iotype = UPIO_MEM; | ||
654 | up->port[0].irq = platform_get_irq(dev, 0); | ||
655 | |||
656 | up->port[0].dev = &dev->dev; | ||
657 | |||
658 | sc26xx_init_masks(up, 0, sc26xx_data[0]); | ||
659 | |||
660 | sc26xx_port = &up->port[0]; | ||
661 | |||
662 | up->port[1].line = 1; | ||
663 | up->port[1].ops = &sc26xx_ops; | ||
664 | up->port[1].type = PORT_SC26XX; | ||
665 | up->port[1].uartclk = (29491200 / 16); /* arbitrary */ | ||
666 | |||
667 | up->port[1].mapbase = up->port[0].mapbase; | ||
668 | up->port[1].membase = up->port[0].membase; | ||
669 | up->port[1].iotype = UPIO_MEM; | ||
670 | up->port[1].irq = up->port[0].irq; | ||
671 | |||
672 | up->port[1].dev = &dev->dev; | ||
673 | |||
674 | sc26xx_init_masks(up, 1, sc26xx_data[1]); | ||
675 | |||
676 | err = uart_register_driver(&sc26xx_reg); | ||
677 | if (err) | ||
678 | goto out_free_port; | ||
679 | |||
680 | sc26xx_reg.tty_driver->name_base = sc26xx_reg.minor; | ||
681 | |||
682 | err = uart_add_one_port(&sc26xx_reg, &up->port[0]); | ||
683 | if (err) | ||
684 | goto out_unregister_driver; | ||
685 | |||
686 | err = uart_add_one_port(&sc26xx_reg, &up->port[1]); | ||
687 | if (err) | ||
688 | goto out_remove_port0; | ||
689 | |||
690 | err = request_irq(up->port[0].irq, sc26xx_interrupt, 0, "sc26xx", up); | ||
691 | if (err) | ||
692 | goto out_remove_ports; | ||
693 | |||
694 | dev_set_drvdata(&dev->dev, up); | ||
695 | return 0; | ||
696 | |||
697 | out_remove_ports: | ||
698 | uart_remove_one_port(&sc26xx_reg, &up->port[1]); | ||
699 | out_remove_port0: | ||
700 | uart_remove_one_port(&sc26xx_reg, &up->port[0]); | ||
701 | |||
702 | out_unregister_driver: | ||
703 | uart_unregister_driver(&sc26xx_reg); | ||
704 | |||
705 | out_free_port: | ||
706 | kfree(up); | ||
707 | sc26xx_port = NULL; | ||
708 | return err; | ||
709 | } | ||
710 | |||
711 | |||
712 | static int __exit sc26xx_driver_remove(struct platform_device *dev) | ||
713 | { | ||
714 | struct uart_sc26xx_port *up = dev_get_drvdata(&dev->dev); | ||
715 | |||
716 | free_irq(up->port[0].irq, up); | ||
717 | |||
718 | uart_remove_one_port(&sc26xx_reg, &up->port[0]); | ||
719 | uart_remove_one_port(&sc26xx_reg, &up->port[1]); | ||
720 | |||
721 | uart_unregister_driver(&sc26xx_reg); | ||
722 | |||
723 | kfree(up); | ||
724 | sc26xx_port = NULL; | ||
725 | |||
726 | dev_set_drvdata(&dev->dev, NULL); | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static struct platform_driver sc26xx_driver = { | ||
731 | .probe = sc26xx_probe, | ||
732 | .remove = __devexit_p(sc26xx_driver_remove), | ||
733 | .driver = { | ||
734 | .name = "SC26xx", | ||
735 | }, | ||
736 | }; | ||
737 | |||
738 | static int __init sc26xx_init(void) | ||
739 | { | ||
740 | return platform_driver_register(&sc26xx_driver); | ||
741 | } | ||
742 | |||
743 | static void __exit sc26xx_exit(void) | ||
744 | { | ||
745 | platform_driver_unregister(&sc26xx_driver); | ||
746 | } | ||
747 | |||
748 | module_init(sc26xx_init); | ||
749 | module_exit(sc26xx_exit); | ||
750 | |||
751 | |||
752 | MODULE_AUTHOR("Thomas Bogendörfer"); | ||
753 | MODULE_DESCRIPTION("SC681/SC2692 serial driver"); | ||
754 | MODULE_VERSION("1.0"); | ||
755 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index 80943409edb0..bacf68dca01a 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c | |||
@@ -142,7 +142,7 @@ static int ulite_transmit(struct uart_port *port, int stat) | |||
142 | 142 | ||
143 | static irqreturn_t ulite_isr(int irq, void *dev_id) | 143 | static irqreturn_t ulite_isr(int irq, void *dev_id) |
144 | { | 144 | { |
145 | struct uart_port *port = (struct uart_port *)dev_id; | 145 | struct uart_port *port = dev_id; |
146 | int busy; | 146 | int busy; |
147 | 147 | ||
148 | do { | 148 | do { |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index aaaea81e412a..d8107890db15 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -144,10 +144,10 @@ config SPI_OMAP_UWIRE | |||
144 | This hooks up to the MicroWire controller on OMAP1 chips. | 144 | This hooks up to the MicroWire controller on OMAP1 chips. |
145 | 145 | ||
146 | config SPI_OMAP24XX | 146 | config SPI_OMAP24XX |
147 | tristate "McSPI driver for OMAP24xx" | 147 | tristate "McSPI driver for OMAP24xx/OMAP34xx" |
148 | depends on SPI_MASTER && ARCH_OMAP24XX | 148 | depends on SPI_MASTER && (ARCH_OMAP24XX || ARCH_OMAP34XX) |
149 | help | 149 | help |
150 | SPI master controller for OMAP24xx Multichannel SPI | 150 | SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI |
151 | (McSPI) modules. | 151 | (McSPI) modules. |
152 | 152 | ||
153 | config SPI_PXA2XX | 153 | config SPI_PXA2XX |
@@ -176,6 +176,13 @@ config SPI_S3C24XX_GPIO | |||
176 | the inbuilt hardware cannot provide the transfer mode, or | 176 | the inbuilt hardware cannot provide the transfer mode, or |
177 | where the board is using non hardware connected pins. | 177 | where the board is using non hardware connected pins. |
178 | 178 | ||
179 | config SPI_SH_SCI | ||
180 | tristate "SuperH SCI SPI controller" | ||
181 | depends on SPI_MASTER && SUPERH | ||
182 | select SPI_BITBANG | ||
183 | help | ||
184 | SPI driver for SuperH SCI blocks. | ||
185 | |||
179 | config SPI_TXX9 | 186 | config SPI_TXX9 |
180 | tristate "Toshiba TXx9 SPI controller" | 187 | tristate "Toshiba TXx9 SPI controller" |
181 | depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX | 188 | depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 41fbac45c323..7fca043ce723 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o | |||
27 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o | 27 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o |
28 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o | 28 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o |
29 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o | 29 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o |
30 | obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o | ||
30 | # ... add above this line ... | 31 | # ... add above this line ... |
31 | 32 | ||
32 | # SPI protocol drivers (device/link on bus) | 33 | # SPI protocol drivers (device/link on bus) |
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index ff10808183a3..293b7cab3e57 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
@@ -51,7 +51,9 @@ struct atmel_spi { | |||
51 | u8 stopping; | 51 | u8 stopping; |
52 | struct list_head queue; | 52 | struct list_head queue; |
53 | struct spi_transfer *current_transfer; | 53 | struct spi_transfer *current_transfer; |
54 | unsigned long remaining_bytes; | 54 | unsigned long current_remaining_bytes; |
55 | struct spi_transfer *next_transfer; | ||
56 | unsigned long next_remaining_bytes; | ||
55 | 57 | ||
56 | void *buffer; | 58 | void *buffer; |
57 | dma_addr_t buffer_dma; | 59 | dma_addr_t buffer_dma; |
@@ -121,6 +123,48 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) | |||
121 | gpio_set_value(gpio, !active); | 123 | gpio_set_value(gpio, !active); |
122 | } | 124 | } |
123 | 125 | ||
126 | static inline int atmel_spi_xfer_is_last(struct spi_message *msg, | ||
127 | struct spi_transfer *xfer) | ||
128 | { | ||
129 | return msg->transfers.prev == &xfer->transfer_list; | ||
130 | } | ||
131 | |||
132 | static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer) | ||
133 | { | ||
134 | return xfer->delay_usecs == 0 && !xfer->cs_change; | ||
135 | } | ||
136 | |||
137 | static void atmel_spi_next_xfer_data(struct spi_master *master, | ||
138 | struct spi_transfer *xfer, | ||
139 | dma_addr_t *tx_dma, | ||
140 | dma_addr_t *rx_dma, | ||
141 | u32 *plen) | ||
142 | { | ||
143 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
144 | u32 len = *plen; | ||
145 | |||
146 | /* use scratch buffer only when rx or tx data is unspecified */ | ||
147 | if (xfer->rx_buf) | ||
148 | *rx_dma = xfer->rx_dma + xfer->len - len; | ||
149 | else { | ||
150 | *rx_dma = as->buffer_dma; | ||
151 | if (len > BUFFER_SIZE) | ||
152 | len = BUFFER_SIZE; | ||
153 | } | ||
154 | if (xfer->tx_buf) | ||
155 | *tx_dma = xfer->tx_dma + xfer->len - len; | ||
156 | else { | ||
157 | *tx_dma = as->buffer_dma; | ||
158 | if (len > BUFFER_SIZE) | ||
159 | len = BUFFER_SIZE; | ||
160 | memset(as->buffer, 0, len); | ||
161 | dma_sync_single_for_device(&as->pdev->dev, | ||
162 | as->buffer_dma, len, DMA_TO_DEVICE); | ||
163 | } | ||
164 | |||
165 | *plen = len; | ||
166 | } | ||
167 | |||
124 | /* | 168 | /* |
125 | * Submit next transfer for DMA. | 169 | * Submit next transfer for DMA. |
126 | * lock is held, spi irq is blocked | 170 | * lock is held, spi irq is blocked |
@@ -130,53 +174,78 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
130 | { | 174 | { |
131 | struct atmel_spi *as = spi_master_get_devdata(master); | 175 | struct atmel_spi *as = spi_master_get_devdata(master); |
132 | struct spi_transfer *xfer; | 176 | struct spi_transfer *xfer; |
133 | u32 len; | 177 | u32 len, remaining, total; |
134 | dma_addr_t tx_dma, rx_dma; | 178 | dma_addr_t tx_dma, rx_dma; |
135 | 179 | ||
136 | xfer = as->current_transfer; | 180 | if (!as->current_transfer) |
137 | if (!xfer || as->remaining_bytes == 0) { | 181 | xfer = list_entry(msg->transfers.next, |
138 | if (xfer) | 182 | struct spi_transfer, transfer_list); |
139 | xfer = list_entry(xfer->transfer_list.next, | 183 | else if (!as->next_transfer) |
140 | struct spi_transfer, transfer_list); | 184 | xfer = list_entry(as->current_transfer->transfer_list.next, |
141 | else | 185 | struct spi_transfer, transfer_list); |
142 | xfer = list_entry(msg->transfers.next, | 186 | else |
143 | struct spi_transfer, transfer_list); | 187 | xfer = NULL; |
144 | as->remaining_bytes = xfer->len; | ||
145 | as->current_transfer = xfer; | ||
146 | } | ||
147 | 188 | ||
148 | len = as->remaining_bytes; | 189 | if (xfer) { |
190 | len = xfer->len; | ||
191 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); | ||
192 | remaining = xfer->len - len; | ||
149 | 193 | ||
150 | tx_dma = xfer->tx_dma + xfer->len - len; | 194 | spi_writel(as, RPR, rx_dma); |
151 | rx_dma = xfer->rx_dma + xfer->len - len; | 195 | spi_writel(as, TPR, tx_dma); |
152 | 196 | ||
153 | /* use scratch buffer only when rx or tx data is unspecified */ | 197 | if (msg->spi->bits_per_word > 8) |
154 | if (!xfer->rx_buf) { | 198 | len >>= 1; |
155 | rx_dma = as->buffer_dma; | 199 | spi_writel(as, RCR, len); |
156 | if (len > BUFFER_SIZE) | 200 | spi_writel(as, TCR, len); |
157 | len = BUFFER_SIZE; | 201 | |
158 | } | 202 | dev_dbg(&msg->spi->dev, |
159 | if (!xfer->tx_buf) { | 203 | " start xfer %p: len %u tx %p/%08x rx %p/%08x\n", |
160 | tx_dma = as->buffer_dma; | 204 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, |
161 | if (len > BUFFER_SIZE) | 205 | xfer->rx_buf, xfer->rx_dma); |
162 | len = BUFFER_SIZE; | 206 | } else { |
163 | memset(as->buffer, 0, len); | 207 | xfer = as->next_transfer; |
164 | dma_sync_single_for_device(&as->pdev->dev, | 208 | remaining = as->next_remaining_bytes; |
165 | as->buffer_dma, len, DMA_TO_DEVICE); | ||
166 | } | 209 | } |
167 | 210 | ||
168 | spi_writel(as, RPR, rx_dma); | 211 | as->current_transfer = xfer; |
169 | spi_writel(as, TPR, tx_dma); | 212 | as->current_remaining_bytes = remaining; |
170 | 213 | ||
171 | as->remaining_bytes -= len; | 214 | if (remaining > 0) |
172 | if (msg->spi->bits_per_word > 8) | 215 | len = remaining; |
173 | len >>= 1; | 216 | else if (!atmel_spi_xfer_is_last(msg, xfer) |
217 | && atmel_spi_xfer_can_be_chained(xfer)) { | ||
218 | xfer = list_entry(xfer->transfer_list.next, | ||
219 | struct spi_transfer, transfer_list); | ||
220 | len = xfer->len; | ||
221 | } else | ||
222 | xfer = NULL; | ||
174 | 223 | ||
175 | /* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer" | 224 | as->next_transfer = xfer; |
176 | * mechanism might help avoid the IRQ latency between transfers | 225 | |
177 | * (and improve the nCS0 errata handling on at91rm9200 chips) | 226 | if (xfer) { |
178 | * | 227 | total = len; |
179 | * We're also waiting for ENDRX before we start the next | 228 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); |
229 | as->next_remaining_bytes = total - len; | ||
230 | |||
231 | spi_writel(as, RNPR, rx_dma); | ||
232 | spi_writel(as, TNPR, tx_dma); | ||
233 | |||
234 | if (msg->spi->bits_per_word > 8) | ||
235 | len >>= 1; | ||
236 | spi_writel(as, RNCR, len); | ||
237 | spi_writel(as, TNCR, len); | ||
238 | |||
239 | dev_dbg(&msg->spi->dev, | ||
240 | " next xfer %p: len %u tx %p/%08x rx %p/%08x\n", | ||
241 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, | ||
242 | xfer->rx_buf, xfer->rx_dma); | ||
243 | } else { | ||
244 | spi_writel(as, RNCR, 0); | ||
245 | spi_writel(as, TNCR, 0); | ||
246 | } | ||
247 | |||
248 | /* REVISIT: We're waiting for ENDRX before we start the next | ||
180 | * transfer because we need to handle some difficult timing | 249 | * transfer because we need to handle some difficult timing |
181 | * issues otherwise. If we wait for ENDTX in one transfer and | 250 | * issues otherwise. If we wait for ENDTX in one transfer and |
182 | * then starts waiting for ENDRX in the next, it's difficult | 251 | * then starts waiting for ENDRX in the next, it's difficult |
@@ -186,17 +255,7 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
186 | * | 255 | * |
187 | * It should be doable, though. Just not now... | 256 | * It should be doable, though. Just not now... |
188 | */ | 257 | */ |
189 | spi_writel(as, TNCR, 0); | ||
190 | spi_writel(as, RNCR, 0); | ||
191 | spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); | 258 | spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); |
192 | |||
193 | dev_dbg(&msg->spi->dev, | ||
194 | " start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n", | ||
195 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, | ||
196 | xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR)); | ||
197 | |||
198 | spi_writel(as, RCR, len); | ||
199 | spi_writel(as, TCR, len); | ||
200 | spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); | 259 | spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); |
201 | } | 260 | } |
202 | 261 | ||
@@ -294,6 +353,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as, | |||
294 | spin_lock(&as->lock); | 353 | spin_lock(&as->lock); |
295 | 354 | ||
296 | as->current_transfer = NULL; | 355 | as->current_transfer = NULL; |
356 | as->next_transfer = NULL; | ||
297 | 357 | ||
298 | /* continue if needed */ | 358 | /* continue if needed */ |
299 | if (list_empty(&as->queue) || as->stopping) | 359 | if (list_empty(&as->queue) || as->stopping) |
@@ -377,7 +437,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
377 | 437 | ||
378 | spi_writel(as, IDR, pending); | 438 | spi_writel(as, IDR, pending); |
379 | 439 | ||
380 | if (as->remaining_bytes == 0) { | 440 | if (as->current_remaining_bytes == 0) { |
381 | msg->actual_length += xfer->len; | 441 | msg->actual_length += xfer->len; |
382 | 442 | ||
383 | if (!msg->is_dma_mapped) | 443 | if (!msg->is_dma_mapped) |
@@ -387,7 +447,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
387 | if (xfer->delay_usecs) | 447 | if (xfer->delay_usecs) |
388 | udelay(xfer->delay_usecs); | 448 | udelay(xfer->delay_usecs); |
389 | 449 | ||
390 | if (msg->transfers.prev == &xfer->transfer_list) { | 450 | if (atmel_spi_xfer_is_last(msg, xfer)) { |
391 | /* report completed message */ | 451 | /* report completed message */ |
392 | atmel_spi_msg_done(master, as, msg, 0, | 452 | atmel_spi_msg_done(master, as, msg, 0, |
393 | xfer->cs_change); | 453 | xfer->cs_change); |
@@ -490,9 +550,14 @@ static int atmel_spi_setup(struct spi_device *spi) | |||
490 | if (!(spi->mode & SPI_CPHA)) | 550 | if (!(spi->mode & SPI_CPHA)) |
491 | csr |= SPI_BIT(NCPHA); | 551 | csr |= SPI_BIT(NCPHA); |
492 | 552 | ||
493 | /* TODO: DLYBS and DLYBCT */ | 553 | /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. |
494 | csr |= SPI_BF(DLYBS, 10); | 554 | * |
495 | csr |= SPI_BF(DLYBCT, 10); | 555 | * DLYBCT would add delays between words, slowing down transfers. |
556 | * It could potentially be useful to cope with DMA bottlenecks, but | ||
557 | * in those cases it's probably best to just use a lower bitrate. | ||
558 | */ | ||
559 | csr |= SPI_BF(DLYBS, 0); | ||
560 | csr |= SPI_BF(DLYBCT, 0); | ||
496 | 561 | ||
497 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ | 562 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ |
498 | npcs_pin = (unsigned int)spi->controller_data; | 563 | npcs_pin = (unsigned int)spi->controller_data; |
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index ea61724ae225..a6ba11afb03f 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
@@ -915,6 +915,28 @@ static u8 __initdata spi2_txdma_id[] = { | |||
915 | OMAP24XX_DMA_SPI2_TX1, | 915 | OMAP24XX_DMA_SPI2_TX1, |
916 | }; | 916 | }; |
917 | 917 | ||
918 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | ||
919 | static u8 __initdata spi3_rxdma_id[] = { | ||
920 | OMAP24XX_DMA_SPI3_RX0, | ||
921 | OMAP24XX_DMA_SPI3_RX1, | ||
922 | }; | ||
923 | |||
924 | static u8 __initdata spi3_txdma_id[] = { | ||
925 | OMAP24XX_DMA_SPI3_TX0, | ||
926 | OMAP24XX_DMA_SPI3_TX1, | ||
927 | }; | ||
928 | #endif | ||
929 | |||
930 | #ifdef CONFIG_ARCH_OMAP3 | ||
931 | static u8 __initdata spi4_rxdma_id[] = { | ||
932 | OMAP34XX_DMA_SPI4_RX0, | ||
933 | }; | ||
934 | |||
935 | static u8 __initdata spi4_txdma_id[] = { | ||
936 | OMAP34XX_DMA_SPI4_TX0, | ||
937 | }; | ||
938 | #endif | ||
939 | |||
918 | static int __init omap2_mcspi_probe(struct platform_device *pdev) | 940 | static int __init omap2_mcspi_probe(struct platform_device *pdev) |
919 | { | 941 | { |
920 | struct spi_master *master; | 942 | struct spi_master *master; |
@@ -935,7 +957,20 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
935 | txdma_id = spi2_txdma_id; | 957 | txdma_id = spi2_txdma_id; |
936 | num_chipselect = 2; | 958 | num_chipselect = 2; |
937 | break; | 959 | break; |
938 | /* REVISIT omap2430 has a third McSPI ... */ | 960 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) |
961 | case 3: | ||
962 | rxdma_id = spi3_rxdma_id; | ||
963 | txdma_id = spi3_txdma_id; | ||
964 | num_chipselect = 2; | ||
965 | break; | ||
966 | #endif | ||
967 | #ifdef CONFIG_ARCH_OMAP3 | ||
968 | case 4: | ||
969 | rxdma_id = spi4_rxdma_id; | ||
970 | txdma_id = spi4_txdma_id; | ||
971 | num_chipselect = 1; | ||
972 | break; | ||
973 | #endif | ||
939 | default: | 974 | default: |
940 | return -EINVAL; | 975 | return -EINVAL; |
941 | } | 976 | } |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index eb817b8eb024..365e0e355aea 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -1526,17 +1526,6 @@ static void pxa2xx_spi_shutdown(struct platform_device *pdev) | |||
1526 | } | 1526 | } |
1527 | 1527 | ||
1528 | #ifdef CONFIG_PM | 1528 | #ifdef CONFIG_PM |
1529 | static int suspend_devices(struct device *dev, void *pm_message) | ||
1530 | { | ||
1531 | pm_message_t *state = pm_message; | ||
1532 | |||
1533 | if (dev->power.power_state.event != state->event) { | ||
1534 | dev_warn(dev, "pm state does not match request\n"); | ||
1535 | return -1; | ||
1536 | } | ||
1537 | |||
1538 | return 0; | ||
1539 | } | ||
1540 | 1529 | ||
1541 | static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) | 1530 | static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) |
1542 | { | 1531 | { |
@@ -1544,12 +1533,6 @@ static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) | |||
1544 | struct ssp_device *ssp = drv_data->ssp; | 1533 | struct ssp_device *ssp = drv_data->ssp; |
1545 | int status = 0; | 1534 | int status = 0; |
1546 | 1535 | ||
1547 | /* Check all childern for current power state */ | ||
1548 | if (device_for_each_child(&pdev->dev, &state, suspend_devices) != 0) { | ||
1549 | dev_warn(&pdev->dev, "suspend aborted\n"); | ||
1550 | return -1; | ||
1551 | } | ||
1552 | |||
1553 | status = stop_queue(drv_data); | 1536 | status = stop_queue(drv_data); |
1554 | if (status != 0) | 1537 | if (status != 0) |
1555 | return status; | 1538 | return status; |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 682a6a48fec3..1ad12afc6ba0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -18,7 +18,6 @@ | |||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/autoconf.h> | ||
22 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
24 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -77,39 +76,33 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
77 | 76 | ||
78 | #ifdef CONFIG_PM | 77 | #ifdef CONFIG_PM |
79 | 78 | ||
80 | /* | ||
81 | * NOTE: the suspend() method for an spi_master controller driver | ||
82 | * should verify that all its child devices are marked as suspended; | ||
83 | * suspend requests delivered through sysfs power/state files don't | ||
84 | * enforce such constraints. | ||
85 | */ | ||
86 | static int spi_suspend(struct device *dev, pm_message_t message) | 79 | static int spi_suspend(struct device *dev, pm_message_t message) |
87 | { | 80 | { |
88 | int value; | 81 | int value = 0; |
89 | struct spi_driver *drv = to_spi_driver(dev->driver); | 82 | struct spi_driver *drv = to_spi_driver(dev->driver); |
90 | 83 | ||
91 | if (!drv || !drv->suspend) | ||
92 | return 0; | ||
93 | |||
94 | /* suspend will stop irqs and dma; no more i/o */ | 84 | /* suspend will stop irqs and dma; no more i/o */ |
95 | value = drv->suspend(to_spi_device(dev), message); | 85 | if (drv) { |
96 | if (value == 0) | 86 | if (drv->suspend) |
97 | dev->power.power_state = message; | 87 | value = drv->suspend(to_spi_device(dev), message); |
88 | else | ||
89 | dev_dbg(dev, "... can't suspend\n"); | ||
90 | } | ||
98 | return value; | 91 | return value; |
99 | } | 92 | } |
100 | 93 | ||
101 | static int spi_resume(struct device *dev) | 94 | static int spi_resume(struct device *dev) |
102 | { | 95 | { |
103 | int value; | 96 | int value = 0; |
104 | struct spi_driver *drv = to_spi_driver(dev->driver); | 97 | struct spi_driver *drv = to_spi_driver(dev->driver); |
105 | 98 | ||
106 | if (!drv || !drv->resume) | ||
107 | return 0; | ||
108 | |||
109 | /* resume may restart the i/o queue */ | 99 | /* resume may restart the i/o queue */ |
110 | value = drv->resume(to_spi_device(dev)); | 100 | if (drv) { |
111 | if (value == 0) | 101 | if (drv->resume) |
112 | dev->power.power_state = PMSG_ON; | 102 | value = drv->resume(to_spi_device(dev)); |
103 | else | ||
104 | dev_dbg(dev, "... can't resume\n"); | ||
105 | } | ||
113 | return value; | 106 | return value; |
114 | } | 107 | } |
115 | 108 | ||
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 7ef39a6e8c06..d853fceb6bf0 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
@@ -1,37 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * File: drivers/spi/bfin5xx_spi.c | 2 | * Blackfin On-Chip SPI Driver |
3 | * Maintainer: | ||
4 | * Bryan Wu <bryan.wu@analog.com> | ||
5 | * Original Author: | ||
6 | * Luke Yang (Analog Devices Inc.) | ||
7 | * | ||
8 | * Created: March. 10th 2006 | ||
9 | * Description: SPI controller driver for Blackfin BF5xx | ||
10 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
11 | * | ||
12 | * Modified: | ||
13 | * March 10, 2006 bfin5xx_spi.c Created. (Luke Yang) | ||
14 | * August 7, 2006 added full duplex mode (Axel Weiss & Luke Yang) | ||
15 | * July 17, 2007 add support for BF54x SPI0 controller (Bryan Wu) | ||
16 | * July 30, 2007 add platfrom_resource interface to support multi-port | ||
17 | * SPI controller (Bryan Wu) | ||
18 | * | 3 | * |
19 | * Copyright 2004-2007 Analog Devices Inc. | 4 | * Copyright 2004-2007 Analog Devices Inc. |
20 | * | 5 | * |
21 | * This program is free software ; you can redistribute it and/or modify | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
22 | * it under the terms of the GNU General Public License as published by | ||
23 | * the Free Software Foundation ; either version 2, or (at your option) | ||
24 | * any later version. | ||
25 | * | ||
26 | * This program is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY ; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | 7 | * |
31 | * You should have received a copy of the GNU General Public License | 8 | * Licensed under the GPL-2 or later. |
32 | * along with this program ; see the file COPYING. | ||
33 | * If not, write to the Free Software Foundation, | ||
34 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
35 | */ | 9 | */ |
36 | 10 | ||
37 | #include <linux/init.h> | 11 | #include <linux/init.h> |
@@ -223,10 +197,9 @@ static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip) | |||
223 | #define MAX_SPI_SSEL 7 | 197 | #define MAX_SPI_SSEL 7 |
224 | 198 | ||
225 | /* stop controller and re-config current chip*/ | 199 | /* stop controller and re-config current chip*/ |
226 | static int restore_state(struct driver_data *drv_data) | 200 | static void restore_state(struct driver_data *drv_data) |
227 | { | 201 | { |
228 | struct chip_data *chip = drv_data->cur_chip; | 202 | struct chip_data *chip = drv_data->cur_chip; |
229 | int ret = 0; | ||
230 | 203 | ||
231 | /* Clear status and disable clock */ | 204 | /* Clear status and disable clock */ |
232 | write_STAT(drv_data, BIT_STAT_CLR); | 205 | write_STAT(drv_data, BIT_STAT_CLR); |
@@ -239,13 +212,6 @@ static int restore_state(struct driver_data *drv_data) | |||
239 | 212 | ||
240 | bfin_spi_enable(drv_data); | 213 | bfin_spi_enable(drv_data); |
241 | cs_active(drv_data, chip); | 214 | cs_active(drv_data, chip); |
242 | |||
243 | if (ret) | ||
244 | dev_dbg(&drv_data->pdev->dev, | ||
245 | ": request chip select number %d failed\n", | ||
246 | chip->chip_select_num); | ||
247 | |||
248 | return ret; | ||
249 | } | 215 | } |
250 | 216 | ||
251 | /* used to kick off transfer in rx mode */ | 217 | /* used to kick off transfer in rx mode */ |
@@ -286,32 +252,30 @@ static void u8_writer(struct driver_data *drv_data) | |||
286 | dev_dbg(&drv_data->pdev->dev, | 252 | dev_dbg(&drv_data->pdev->dev, |
287 | "cr8-s is 0x%x\n", read_STAT(drv_data)); | 253 | "cr8-s is 0x%x\n", read_STAT(drv_data)); |
288 | 254 | ||
289 | /* poll for SPI completion before start */ | ||
290 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
291 | cpu_relax(); | ||
292 | |||
293 | while (drv_data->tx < drv_data->tx_end) { | 255 | while (drv_data->tx < drv_data->tx_end) { |
294 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 256 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
295 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 257 | while (read_STAT(drv_data) & BIT_STAT_TXS) |
296 | cpu_relax(); | 258 | cpu_relax(); |
297 | ++drv_data->tx; | 259 | ++drv_data->tx; |
298 | } | 260 | } |
261 | |||
262 | /* poll for SPI completion before return */ | ||
263 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
264 | cpu_relax(); | ||
299 | } | 265 | } |
300 | 266 | ||
301 | static void u8_cs_chg_writer(struct driver_data *drv_data) | 267 | static void u8_cs_chg_writer(struct driver_data *drv_data) |
302 | { | 268 | { |
303 | struct chip_data *chip = drv_data->cur_chip; | 269 | struct chip_data *chip = drv_data->cur_chip; |
304 | 270 | ||
305 | /* poll for SPI completion before start */ | ||
306 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
307 | cpu_relax(); | ||
308 | |||
309 | while (drv_data->tx < drv_data->tx_end) { | 271 | while (drv_data->tx < drv_data->tx_end) { |
310 | cs_active(drv_data, chip); | 272 | cs_active(drv_data, chip); |
311 | 273 | ||
312 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 274 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
313 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 275 | while (read_STAT(drv_data) & BIT_STAT_TXS) |
314 | cpu_relax(); | 276 | cpu_relax(); |
277 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
278 | cpu_relax(); | ||
315 | 279 | ||
316 | cs_deactive(drv_data, chip); | 280 | cs_deactive(drv_data, chip); |
317 | 281 | ||
@@ -350,43 +314,28 @@ static void u8_cs_chg_reader(struct driver_data *drv_data) | |||
350 | { | 314 | { |
351 | struct chip_data *chip = drv_data->cur_chip; | 315 | struct chip_data *chip = drv_data->cur_chip; |
352 | 316 | ||
353 | /* poll for SPI completion before start */ | 317 | while (drv_data->rx < drv_data->rx_end) { |
354 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | 318 | cs_active(drv_data, chip); |
355 | cpu_relax(); | 319 | read_RDBR(drv_data); /* kick off */ |
356 | |||
357 | /* clear TDBR buffer before read(else it will be shifted out) */ | ||
358 | write_TDBR(drv_data, 0xFFFF); | ||
359 | 320 | ||
360 | cs_active(drv_data, chip); | 321 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
361 | dummy_read(drv_data); | 322 | cpu_relax(); |
323 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
324 | cpu_relax(); | ||
362 | 325 | ||
363 | while (drv_data->rx < drv_data->rx_end - 1) { | 326 | *(u8 *) (drv_data->rx) = read_SHAW(drv_data); |
364 | cs_deactive(drv_data, chip); | 327 | cs_deactive(drv_data, chip); |
365 | 328 | ||
366 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
367 | cpu_relax(); | ||
368 | cs_active(drv_data, chip); | ||
369 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | ||
370 | ++drv_data->rx; | 329 | ++drv_data->rx; |
371 | } | 330 | } |
372 | cs_deactive(drv_data, chip); | ||
373 | |||
374 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
375 | cpu_relax(); | ||
376 | *(u8 *) (drv_data->rx) = read_SHAW(drv_data); | ||
377 | ++drv_data->rx; | ||
378 | } | 331 | } |
379 | 332 | ||
380 | static void u8_duplex(struct driver_data *drv_data) | 333 | static void u8_duplex(struct driver_data *drv_data) |
381 | { | 334 | { |
382 | /* poll for SPI completion before start */ | ||
383 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
384 | cpu_relax(); | ||
385 | |||
386 | /* in duplex mode, clk is triggered by writing of TDBR */ | 335 | /* in duplex mode, clk is triggered by writing of TDBR */ |
387 | while (drv_data->rx < drv_data->rx_end) { | 336 | while (drv_data->rx < drv_data->rx_end) { |
388 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 337 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
389 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 338 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) |
390 | cpu_relax(); | 339 | cpu_relax(); |
391 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 340 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
392 | cpu_relax(); | 341 | cpu_relax(); |
@@ -400,15 +349,12 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data) | |||
400 | { | 349 | { |
401 | struct chip_data *chip = drv_data->cur_chip; | 350 | struct chip_data *chip = drv_data->cur_chip; |
402 | 351 | ||
403 | /* poll for SPI completion before start */ | ||
404 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
405 | cpu_relax(); | ||
406 | |||
407 | while (drv_data->rx < drv_data->rx_end) { | 352 | while (drv_data->rx < drv_data->rx_end) { |
408 | cs_active(drv_data, chip); | 353 | cs_active(drv_data, chip); |
409 | 354 | ||
410 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 355 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
411 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 356 | |
357 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
412 | cpu_relax(); | 358 | cpu_relax(); |
413 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 359 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
414 | cpu_relax(); | 360 | cpu_relax(); |
@@ -426,32 +372,30 @@ static void u16_writer(struct driver_data *drv_data) | |||
426 | dev_dbg(&drv_data->pdev->dev, | 372 | dev_dbg(&drv_data->pdev->dev, |
427 | "cr16 is 0x%x\n", read_STAT(drv_data)); | 373 | "cr16 is 0x%x\n", read_STAT(drv_data)); |
428 | 374 | ||
429 | /* poll for SPI completion before start */ | ||
430 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
431 | cpu_relax(); | ||
432 | |||
433 | while (drv_data->tx < drv_data->tx_end) { | 375 | while (drv_data->tx < drv_data->tx_end) { |
434 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 376 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
435 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) | 377 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) |
436 | cpu_relax(); | 378 | cpu_relax(); |
437 | drv_data->tx += 2; | 379 | drv_data->tx += 2; |
438 | } | 380 | } |
381 | |||
382 | /* poll for SPI completion before return */ | ||
383 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
384 | cpu_relax(); | ||
439 | } | 385 | } |
440 | 386 | ||
441 | static void u16_cs_chg_writer(struct driver_data *drv_data) | 387 | static void u16_cs_chg_writer(struct driver_data *drv_data) |
442 | { | 388 | { |
443 | struct chip_data *chip = drv_data->cur_chip; | 389 | struct chip_data *chip = drv_data->cur_chip; |
444 | 390 | ||
445 | /* poll for SPI completion before start */ | ||
446 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
447 | cpu_relax(); | ||
448 | |||
449 | while (drv_data->tx < drv_data->tx_end) { | 391 | while (drv_data->tx < drv_data->tx_end) { |
450 | cs_active(drv_data, chip); | 392 | cs_active(drv_data, chip); |
451 | 393 | ||
452 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 394 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
453 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) | 395 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) |
454 | cpu_relax(); | 396 | cpu_relax(); |
397 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
398 | cpu_relax(); | ||
455 | 399 | ||
456 | cs_deactive(drv_data, chip); | 400 | cs_deactive(drv_data, chip); |
457 | 401 | ||
@@ -519,14 +463,10 @@ static void u16_cs_chg_reader(struct driver_data *drv_data) | |||
519 | 463 | ||
520 | static void u16_duplex(struct driver_data *drv_data) | 464 | static void u16_duplex(struct driver_data *drv_data) |
521 | { | 465 | { |
522 | /* poll for SPI completion before start */ | ||
523 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
524 | cpu_relax(); | ||
525 | |||
526 | /* in duplex mode, clk is triggered by writing of TDBR */ | 466 | /* in duplex mode, clk is triggered by writing of TDBR */ |
527 | while (drv_data->tx < drv_data->tx_end) { | 467 | while (drv_data->tx < drv_data->tx_end) { |
528 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 468 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
529 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 469 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) |
530 | cpu_relax(); | 470 | cpu_relax(); |
531 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 471 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
532 | cpu_relax(); | 472 | cpu_relax(); |
@@ -540,15 +480,11 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data) | |||
540 | { | 480 | { |
541 | struct chip_data *chip = drv_data->cur_chip; | 481 | struct chip_data *chip = drv_data->cur_chip; |
542 | 482 | ||
543 | /* poll for SPI completion before start */ | ||
544 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
545 | cpu_relax(); | ||
546 | |||
547 | while (drv_data->tx < drv_data->tx_end) { | 483 | while (drv_data->tx < drv_data->tx_end) { |
548 | cs_active(drv_data, chip); | 484 | cs_active(drv_data, chip); |
549 | 485 | ||
550 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 486 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
551 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 487 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) |
552 | cpu_relax(); | 488 | cpu_relax(); |
553 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 489 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
554 | cpu_relax(); | 490 | cpu_relax(); |
@@ -616,7 +552,7 @@ static void giveback(struct driver_data *drv_data) | |||
616 | 552 | ||
617 | static irqreturn_t dma_irq_handler(int irq, void *dev_id) | 553 | static irqreturn_t dma_irq_handler(int irq, void *dev_id) |
618 | { | 554 | { |
619 | struct driver_data *drv_data = (struct driver_data *)dev_id; | 555 | struct driver_data *drv_data = dev_id; |
620 | struct chip_data *chip = drv_data->cur_chip; | 556 | struct chip_data *chip = drv_data->cur_chip; |
621 | struct spi_message *msg = drv_data->cur_msg; | 557 | struct spi_message *msg = drv_data->cur_msg; |
622 | 558 | ||
@@ -978,10 +914,7 @@ static void pump_messages(struct work_struct *work) | |||
978 | 914 | ||
979 | /* Setup the SSP using the per chip configuration */ | 915 | /* Setup the SSP using the per chip configuration */ |
980 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); | 916 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); |
981 | if (restore_state(drv_data)) { | 917 | restore_state(drv_data); |
982 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
983 | return; | ||
984 | }; | ||
985 | 918 | ||
986 | list_del_init(&drv_data->cur_msg->queue); | 919 | list_del_init(&drv_data->cur_msg->queue); |
987 | 920 | ||
@@ -1187,7 +1120,7 @@ static int setup(struct spi_device *spi) | |||
1187 | if ((chip->chip_select_num > 0) | 1120 | if ((chip->chip_select_num > 0) |
1188 | && (chip->chip_select_num <= spi->master->num_chipselect)) | 1121 | && (chip->chip_select_num <= spi->master->num_chipselect)) |
1189 | peripheral_request(ssel[spi->master->bus_num] | 1122 | peripheral_request(ssel[spi->master->bus_num] |
1190 | [chip->chip_select_num-1], DRV_NAME); | 1123 | [chip->chip_select_num-1], spi->modalias); |
1191 | 1124 | ||
1192 | cs_deactive(drv_data, chip); | 1125 | cs_deactive(drv_data, chip); |
1193 | 1126 | ||
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 639963eb1ac1..1b0647124933 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c | |||
@@ -1686,17 +1686,6 @@ static void spi_imx_shutdown(struct platform_device *pdev) | |||
1686 | } | 1686 | } |
1687 | 1687 | ||
1688 | #ifdef CONFIG_PM | 1688 | #ifdef CONFIG_PM |
1689 | static int suspend_devices(struct device *dev, void *pm_message) | ||
1690 | { | ||
1691 | pm_message_t *state = pm_message; | ||
1692 | |||
1693 | if (dev->power.power_state.event != state->event) { | ||
1694 | dev_warn(dev, "pm state does not match request\n"); | ||
1695 | return -1; | ||
1696 | } | ||
1697 | |||
1698 | return 0; | ||
1699 | } | ||
1700 | 1689 | ||
1701 | static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state) | 1690 | static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state) |
1702 | { | 1691 | { |
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 89d6685a5ca4..6e834b8b9d27 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
@@ -237,10 +237,8 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) | |||
237 | { | 237 | { |
238 | struct s3c24xx_spi *hw; | 238 | struct s3c24xx_spi *hw; |
239 | struct spi_master *master; | 239 | struct spi_master *master; |
240 | struct spi_board_info *bi; | ||
241 | struct resource *res; | 240 | struct resource *res; |
242 | int err = 0; | 241 | int err = 0; |
243 | int i; | ||
244 | 242 | ||
245 | master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); | 243 | master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); |
246 | if (master == NULL) { | 244 | if (master == NULL) { |
@@ -348,16 +346,6 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) | |||
348 | goto err_register; | 346 | goto err_register; |
349 | } | 347 | } |
350 | 348 | ||
351 | /* register all the devices associated */ | ||
352 | |||
353 | bi = &hw->pdata->board_info[0]; | ||
354 | for (i = 0; i < hw->pdata->board_size; i++, bi++) { | ||
355 | dev_info(hw->dev, "registering %s\n", bi->modalias); | ||
356 | |||
357 | bi->controller_data = hw; | ||
358 | spi_new_device(master, bi); | ||
359 | } | ||
360 | |||
361 | return 0; | 349 | return 0; |
362 | 350 | ||
363 | err_register: | 351 | err_register: |
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index 109d82c1abc0..82ae7d7eca38 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c | |||
@@ -100,7 +100,6 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) | |||
100 | struct spi_master *master; | 100 | struct spi_master *master; |
101 | struct s3c2410_spigpio *sp; | 101 | struct s3c2410_spigpio *sp; |
102 | int ret; | 102 | int ret; |
103 | int i; | ||
104 | 103 | ||
105 | master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio)); | 104 | master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio)); |
106 | if (master == NULL) { | 105 | if (master == NULL) { |
@@ -143,17 +142,6 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) | |||
143 | if (ret) | 142 | if (ret) |
144 | goto err_no_bitbang; | 143 | goto err_no_bitbang; |
145 | 144 | ||
146 | /* register the chips to go with the board */ | ||
147 | |||
148 | for (i = 0; i < sp->info->board_size; i++) { | ||
149 | dev_info(&dev->dev, "registering %p: %s\n", | ||
150 | &sp->info->board_info[i], | ||
151 | sp->info->board_info[i].modalias); | ||
152 | |||
153 | sp->info->board_info[i].controller_data = sp; | ||
154 | spi_new_device(master, sp->info->board_info + i); | ||
155 | } | ||
156 | |||
157 | return 0; | 145 | return 0; |
158 | 146 | ||
159 | err_no_bitbang: | 147 | err_no_bitbang: |
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c new file mode 100644 index 000000000000..3dbe71b16d60 --- /dev/null +++ b/drivers/spi/spi_sh_sci.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * SH SCI SPI interface | ||
3 | * | ||
4 | * Copyright (c) 2008 Magnus Damm | ||
5 | * | ||
6 | * Based on S3C24XX GPIO based SPI driver, which is: | ||
7 | * Copyright (c) 2006 Ben Dooks | ||
8 | * Copyright (c) 2006 Simtec Electronics | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/spi/spi_bitbang.h> | ||
25 | |||
26 | #include <asm/spi.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | struct sh_sci_spi { | ||
30 | struct spi_bitbang bitbang; | ||
31 | |||
32 | void __iomem *membase; | ||
33 | unsigned char val; | ||
34 | struct sh_spi_info *info; | ||
35 | struct platform_device *dev; | ||
36 | }; | ||
37 | |||
38 | #define SCSPTR(sp) (sp->membase + 0x1c) | ||
39 | #define PIN_SCK (1 << 2) | ||
40 | #define PIN_TXD (1 << 0) | ||
41 | #define PIN_RXD PIN_TXD | ||
42 | #define PIN_INIT ((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD) | ||
43 | |||
44 | static inline void setbits(struct sh_sci_spi *sp, int bits, int on) | ||
45 | { | ||
46 | /* | ||
47 | * We are the only user of SCSPTR so no locking is required. | ||
48 | * Reading bit 2 and 0 in SCSPTR gives pin state as input. | ||
49 | * Writing the same bits sets the output value. | ||
50 | * This makes regular read-modify-write difficult so we | ||
51 | * use sp->val to keep track of the latest register value. | ||
52 | */ | ||
53 | |||
54 | if (on) | ||
55 | sp->val |= bits; | ||
56 | else | ||
57 | sp->val &= ~bits; | ||
58 | |||
59 | iowrite8(sp->val, SCSPTR(sp)); | ||
60 | } | ||
61 | |||
62 | static inline void setsck(struct spi_device *dev, int on) | ||
63 | { | ||
64 | setbits(spi_master_get_devdata(dev->master), PIN_SCK, on); | ||
65 | } | ||
66 | |||
67 | static inline void setmosi(struct spi_device *dev, int on) | ||
68 | { | ||
69 | setbits(spi_master_get_devdata(dev->master), PIN_TXD, on); | ||
70 | } | ||
71 | |||
72 | static inline u32 getmiso(struct spi_device *dev) | ||
73 | { | ||
74 | struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); | ||
75 | |||
76 | return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0; | ||
77 | } | ||
78 | |||
79 | #define spidelay(x) ndelay(x) | ||
80 | |||
81 | #define EXPAND_BITBANG_TXRX | ||
82 | #include <linux/spi/spi_bitbang.h> | ||
83 | |||
84 | static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, | ||
85 | unsigned nsecs, u32 word, u8 bits) | ||
86 | { | ||
87 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | ||
88 | } | ||
89 | |||
90 | static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi, | ||
91 | unsigned nsecs, u32 word, u8 bits) | ||
92 | { | ||
93 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); | ||
94 | } | ||
95 | |||
96 | static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi, | ||
97 | unsigned nsecs, u32 word, u8 bits) | ||
98 | { | ||
99 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); | ||
100 | } | ||
101 | |||
102 | static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, | ||
103 | unsigned nsecs, u32 word, u8 bits) | ||
104 | { | ||
105 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); | ||
106 | } | ||
107 | |||
108 | static void sh_sci_spi_chipselect(struct spi_device *dev, int value) | ||
109 | { | ||
110 | struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); | ||
111 | |||
112 | if (sp->info && sp->info->chip_select) | ||
113 | (sp->info->chip_select)(sp->info, dev->chip_select, value); | ||
114 | } | ||
115 | |||
116 | static int sh_sci_spi_probe(struct platform_device *dev) | ||
117 | { | ||
118 | struct resource *r; | ||
119 | struct spi_master *master; | ||
120 | struct sh_sci_spi *sp; | ||
121 | int ret; | ||
122 | |||
123 | master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi)); | ||
124 | if (master == NULL) { | ||
125 | dev_err(&dev->dev, "failed to allocate spi master\n"); | ||
126 | ret = -ENOMEM; | ||
127 | goto err0; | ||
128 | } | ||
129 | |||
130 | sp = spi_master_get_devdata(master); | ||
131 | |||
132 | platform_set_drvdata(dev, sp); | ||
133 | sp->info = dev->dev.platform_data; | ||
134 | |||
135 | /* setup spi bitbang adaptor */ | ||
136 | sp->bitbang.master = spi_master_get(master); | ||
137 | sp->bitbang.master->bus_num = sp->info->bus_num; | ||
138 | sp->bitbang.master->num_chipselect = sp->info->num_chipselect; | ||
139 | sp->bitbang.chipselect = sh_sci_spi_chipselect; | ||
140 | |||
141 | sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0; | ||
142 | sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1; | ||
143 | sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2; | ||
144 | sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3; | ||
145 | |||
146 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
147 | if (r == NULL) { | ||
148 | ret = -ENOENT; | ||
149 | goto err1; | ||
150 | } | ||
151 | sp->membase = ioremap(r->start, r->end - r->start + 1); | ||
152 | if (!sp->membase) { | ||
153 | ret = -ENXIO; | ||
154 | goto err1; | ||
155 | } | ||
156 | sp->val = ioread8(SCSPTR(sp)); | ||
157 | setbits(sp, PIN_INIT, 1); | ||
158 | |||
159 | ret = spi_bitbang_start(&sp->bitbang); | ||
160 | if (!ret) | ||
161 | return 0; | ||
162 | |||
163 | setbits(sp, PIN_INIT, 0); | ||
164 | iounmap(sp->membase); | ||
165 | err1: | ||
166 | spi_master_put(sp->bitbang.master); | ||
167 | err0: | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static int sh_sci_spi_remove(struct platform_device *dev) | ||
172 | { | ||
173 | struct sh_sci_spi *sp = platform_get_drvdata(dev); | ||
174 | |||
175 | iounmap(sp->membase); | ||
176 | setbits(sp, PIN_INIT, 0); | ||
177 | spi_bitbang_stop(&sp->bitbang); | ||
178 | spi_master_put(sp->bitbang.master); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static struct platform_driver sh_sci_spi_drv = { | ||
183 | .probe = sh_sci_spi_probe, | ||
184 | .remove = sh_sci_spi_remove, | ||
185 | .driver = { | ||
186 | .name = "spi_sh_sci", | ||
187 | .owner = THIS_MODULE, | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | static int __init sh_sci_spi_init(void) | ||
192 | { | ||
193 | return platform_driver_register(&sh_sci_spi_drv); | ||
194 | } | ||
195 | module_init(sh_sci_spi_init); | ||
196 | |||
197 | static void __exit sh_sci_spi_exit(void) | ||
198 | { | ||
199 | platform_driver_unregister(&sh_sci_spi_drv); | ||
200 | } | ||
201 | module_exit(sh_sci_spi_exit); | ||
202 | |||
203 | MODULE_DESCRIPTION("SH SCI SPI Driver"); | ||
204 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | ||
205 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index cc246faa3590..2a77e9d42c68 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c | |||
@@ -417,30 +417,28 @@ static void uio_vma_close(struct vm_area_struct *vma) | |||
417 | idev->vma_count--; | 417 | idev->vma_count--; |
418 | } | 418 | } |
419 | 419 | ||
420 | static struct page *uio_vma_nopage(struct vm_area_struct *vma, | 420 | static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
421 | unsigned long address, int *type) | ||
422 | { | 421 | { |
423 | struct uio_device *idev = vma->vm_private_data; | 422 | struct uio_device *idev = vma->vm_private_data; |
424 | struct page* page = NOPAGE_SIGBUS; | 423 | struct page *page; |
425 | 424 | ||
426 | int mi = uio_find_mem_index(vma); | 425 | int mi = uio_find_mem_index(vma); |
427 | if (mi < 0) | 426 | if (mi < 0) |
428 | return page; | 427 | return VM_FAULT_SIGBUS; |
429 | 428 | ||
430 | if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL) | 429 | if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL) |
431 | page = virt_to_page(idev->info->mem[mi].addr); | 430 | page = virt_to_page(idev->info->mem[mi].addr); |
432 | else | 431 | else |
433 | page = vmalloc_to_page((void*)idev->info->mem[mi].addr); | 432 | page = vmalloc_to_page((void*)idev->info->mem[mi].addr); |
434 | get_page(page); | 433 | get_page(page); |
435 | if (type) | 434 | vmf->page = page; |
436 | *type = VM_FAULT_MINOR; | 435 | return 0; |
437 | return page; | ||
438 | } | 436 | } |
439 | 437 | ||
440 | static struct vm_operations_struct uio_vm_ops = { | 438 | static struct vm_operations_struct uio_vm_ops = { |
441 | .open = uio_vma_open, | 439 | .open = uio_vma_open, |
442 | .close = uio_vma_close, | 440 | .close = uio_vma_close, |
443 | .nopage = uio_vma_nopage, | 441 | .fault = uio_vma_fault, |
444 | }; | 442 | }; |
445 | 443 | ||
446 | static int uio_mmap_physical(struct vm_area_struct *vma) | 444 | static int uio_mmap_physical(struct vm_area_struct *vma) |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index f8e711147501..fc65c02306dd 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/backlight.h> | ||
19 | 20 | ||
20 | #include <asm/arch/board.h> | 21 | #include <asm/arch/board.h> |
21 | #include <asm/arch/cpu.h> | 22 | #include <asm/arch/cpu.h> |
@@ -69,6 +70,107 @@ static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | |||
69 | } | 70 | } |
70 | #endif | 71 | #endif |
71 | 72 | ||
73 | static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 | ||
74 | | ATMEL_LCDC_POL_POSITIVE | ||
75 | | ATMEL_LCDC_ENA_PWMENABLE; | ||
76 | |||
77 | #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC | ||
78 | |||
79 | /* some bl->props field just changed */ | ||
80 | static int atmel_bl_update_status(struct backlight_device *bl) | ||
81 | { | ||
82 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); | ||
83 | int power = sinfo->bl_power; | ||
84 | int brightness = bl->props.brightness; | ||
85 | |||
86 | /* REVISIT there may be a meaningful difference between | ||
87 | * fb_blank and power ... there seem to be some cases | ||
88 | * this doesn't handle correctly. | ||
89 | */ | ||
90 | if (bl->props.fb_blank != sinfo->bl_power) | ||
91 | power = bl->props.fb_blank; | ||
92 | else if (bl->props.power != sinfo->bl_power) | ||
93 | power = bl->props.power; | ||
94 | |||
95 | if (brightness < 0 && power == FB_BLANK_UNBLANK) | ||
96 | brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | ||
97 | else if (power != FB_BLANK_UNBLANK) | ||
98 | brightness = 0; | ||
99 | |||
100 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); | ||
101 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, | ||
102 | brightness ? contrast_ctr : 0); | ||
103 | |||
104 | bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int atmel_bl_get_brightness(struct backlight_device *bl) | ||
110 | { | ||
111 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); | ||
112 | |||
113 | return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | ||
114 | } | ||
115 | |||
116 | static struct backlight_ops atmel_lcdc_bl_ops = { | ||
117 | .update_status = atmel_bl_update_status, | ||
118 | .get_brightness = atmel_bl_get_brightness, | ||
119 | }; | ||
120 | |||
121 | static void init_backlight(struct atmel_lcdfb_info *sinfo) | ||
122 | { | ||
123 | struct backlight_device *bl; | ||
124 | |||
125 | sinfo->bl_power = FB_BLANK_UNBLANK; | ||
126 | |||
127 | if (sinfo->backlight) | ||
128 | return; | ||
129 | |||
130 | bl = backlight_device_register("backlight", &sinfo->pdev->dev, | ||
131 | sinfo, &atmel_lcdc_bl_ops); | ||
132 | if (IS_ERR(sinfo->backlight)) { | ||
133 | dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", | ||
134 | PTR_ERR(bl)); | ||
135 | return; | ||
136 | } | ||
137 | sinfo->backlight = bl; | ||
138 | |||
139 | bl->props.power = FB_BLANK_UNBLANK; | ||
140 | bl->props.fb_blank = FB_BLANK_UNBLANK; | ||
141 | bl->props.max_brightness = 0xff; | ||
142 | bl->props.brightness = atmel_bl_get_brightness(bl); | ||
143 | } | ||
144 | |||
145 | static void exit_backlight(struct atmel_lcdfb_info *sinfo) | ||
146 | { | ||
147 | if (sinfo->backlight) | ||
148 | backlight_device_unregister(sinfo->backlight); | ||
149 | } | ||
150 | |||
151 | #else | ||
152 | |||
153 | static void init_backlight(struct atmel_lcdfb_info *sinfo) | ||
154 | { | ||
155 | dev_warn(&sinfo->pdev->dev, "backlight control is not available\n"); | ||
156 | } | ||
157 | |||
158 | static void exit_backlight(struct atmel_lcdfb_info *sinfo) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | #endif | ||
163 | |||
164 | static void init_contrast(struct atmel_lcdfb_info *sinfo) | ||
165 | { | ||
166 | /* have some default contrast/backlight settings */ | ||
167 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); | ||
168 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); | ||
169 | |||
170 | if (sinfo->lcdcon_is_backlight) | ||
171 | init_backlight(sinfo); | ||
172 | } | ||
173 | |||
72 | 174 | ||
73 | static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { | 175 | static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { |
74 | .type = FB_TYPE_PACKED_PIXELS, | 176 | .type = FB_TYPE_PACKED_PIXELS, |
@@ -203,6 +305,26 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
203 | var->transp.offset = var->transp.length = 0; | 305 | var->transp.offset = var->transp.length = 0; |
204 | var->xoffset = var->yoffset = 0; | 306 | var->xoffset = var->yoffset = 0; |
205 | 307 | ||
308 | /* Saturate vertical and horizontal timings at maximum values */ | ||
309 | var->vsync_len = min_t(u32, var->vsync_len, | ||
310 | (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1); | ||
311 | var->upper_margin = min_t(u32, var->upper_margin, | ||
312 | ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET); | ||
313 | var->lower_margin = min_t(u32, var->lower_margin, | ||
314 | ATMEL_LCDC_VFP); | ||
315 | var->right_margin = min_t(u32, var->right_margin, | ||
316 | (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1); | ||
317 | var->hsync_len = min_t(u32, var->hsync_len, | ||
318 | (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1); | ||
319 | var->left_margin = min_t(u32, var->left_margin, | ||
320 | ATMEL_LCDC_HBP + 1); | ||
321 | |||
322 | /* Some parameters can't be zero */ | ||
323 | var->vsync_len = max_t(u32, var->vsync_len, 1); | ||
324 | var->right_margin = max_t(u32, var->right_margin, 1); | ||
325 | var->hsync_len = max_t(u32, var->hsync_len, 1); | ||
326 | var->left_margin = max_t(u32, var->left_margin, 1); | ||
327 | |||
206 | switch (var->bits_per_pixel) { | 328 | switch (var->bits_per_pixel) { |
207 | case 1: | 329 | case 1: |
208 | case 2: | 330 | case 2: |
@@ -370,10 +492,6 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
370 | /* Disable all interrupts */ | 492 | /* Disable all interrupts */ |
371 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | 493 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); |
372 | 494 | ||
373 | /* Set contrast */ | ||
374 | value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE; | ||
375 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value); | ||
376 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); | ||
377 | /* ...wait for DMA engine to become idle... */ | 495 | /* ...wait for DMA engine to become idle... */ |
378 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | 496 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) |
379 | msleep(10); | 497 | msleep(10); |
@@ -577,6 +695,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
577 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; | 695 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; |
578 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; | 696 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; |
579 | sinfo->guard_time = pdata_sinfo->guard_time; | 697 | sinfo->guard_time = pdata_sinfo->guard_time; |
698 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; | ||
580 | } else { | 699 | } else { |
581 | dev_err(dev, "cannot get default configuration\n"); | 700 | dev_err(dev, "cannot get default configuration\n"); |
582 | goto free_info; | 701 | goto free_info; |
@@ -670,6 +789,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
670 | goto release_mem; | 789 | goto release_mem; |
671 | } | 790 | } |
672 | 791 | ||
792 | /* Initialize PWM for contrast or backlight ("off") */ | ||
793 | init_contrast(sinfo); | ||
794 | |||
673 | /* interrupt */ | 795 | /* interrupt */ |
674 | ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); | 796 | ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); |
675 | if (ret) { | 797 | if (ret) { |
@@ -721,6 +843,7 @@ free_cmap: | |||
721 | unregister_irqs: | 843 | unregister_irqs: |
722 | free_irq(sinfo->irq_base, info); | 844 | free_irq(sinfo->irq_base, info); |
723 | unmap_mmio: | 845 | unmap_mmio: |
846 | exit_backlight(sinfo); | ||
724 | iounmap(sinfo->mmio); | 847 | iounmap(sinfo->mmio); |
725 | release_mem: | 848 | release_mem: |
726 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); | 849 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); |
@@ -755,6 +878,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
755 | if (!sinfo) | 878 | if (!sinfo) |
756 | return 0; | 879 | return 0; |
757 | 880 | ||
881 | exit_backlight(sinfo); | ||
758 | if (sinfo->atmel_lcdfb_power_control) | 882 | if (sinfo->atmel_lcdfb_power_control) |
759 | sinfo->atmel_lcdfb_power_control(0); | 883 | sinfo->atmel_lcdfb_power_control(0); |
760 | unregister_framebuffer(info); | 884 | unregister_framebuffer(info); |
@@ -781,6 +905,9 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
781 | 905 | ||
782 | static struct platform_driver atmel_lcdfb_driver = { | 906 | static struct platform_driver atmel_lcdfb_driver = { |
783 | .remove = __exit_p(atmel_lcdfb_remove), | 907 | .remove = __exit_p(atmel_lcdfb_remove), |
908 | |||
909 | // FIXME need suspend, resume | ||
910 | |||
784 | .driver = { | 911 | .driver = { |
785 | .name = "atmel_lcdfb", | 912 | .name = "atmel_lcdfb", |
786 | .owner = THIS_MODULE, | 913 | .owner = THIS_MODULE, |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 9609a6c676be..924e2551044a 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -50,6 +50,19 @@ config BACKLIGHT_CLASS_DEVICE | |||
50 | To have support for your specific LCD panel you will have to | 50 | To have support for your specific LCD panel you will have to |
51 | select the proper drivers which depend on this option. | 51 | select the proper drivers which depend on this option. |
52 | 52 | ||
53 | config BACKLIGHT_ATMEL_LCDC | ||
54 | bool "Atmel LCDC Contrast-as-Backlight control" | ||
55 | depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL | ||
56 | default y if MACH_SAM9261EK || MACH_SAM9263EK | ||
57 | help | ||
58 | This provides a backlight control internal to the Atmel LCDC | ||
59 | driver. If the LCD "contrast control" on your board is wired | ||
60 | so it controls the backlight brightness, select this option to | ||
61 | export this as a PWM-based backlight control. | ||
62 | |||
63 | If in doubt, it's safe to enable this option; it doesn't kick | ||
64 | in unless the board's description says it's wired that way. | ||
65 | |||
53 | config BACKLIGHT_CORGI | 66 | config BACKLIGHT_CORGI |
54 | tristate "Generic (aka Sharp Corgi) Backlight Driver" | 67 | tristate "Generic (aka Sharp Corgi) Backlight Driver" |
55 | depends on BACKLIGHT_CLASS_DEVICE | 68 | depends on BACKLIGHT_CLASS_DEVICE |
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index c8e7427a0bc8..0ce791e6f79c 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
@@ -498,8 +498,7 @@ static struct lcd_device *lcd_dev; | |||
498 | 498 | ||
499 | static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) | 499 | static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) |
500 | { | 500 | { |
501 | 501 | /*struct bfin_bf54xfb_info *info = dev_id;*/ | |
502 | /*struct bfin_bf54xfb_info *info = (struct bfin_bf54xfb_info *)dev_id;*/ | ||
503 | 502 | ||
504 | u16 status = bfin_read_EPPI0_STATUS(); | 503 | u16 status = bfin_read_EPPI0_STATUS(); |
505 | 504 | ||
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 308850df16fe..69864b1b3f9e 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c | |||
@@ -63,7 +63,7 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
63 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 63 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
64 | struct fb_fillrect region; | 64 | struct fb_fillrect region; |
65 | 65 | ||
66 | region.color = attr_bgcol_ec(bgshift, vc); | 66 | region.color = attr_bgcol_ec(bgshift, vc, info); |
67 | region.dx = sx * vc->vc_font.width; | 67 | region.dx = sx * vc->vc_font.width; |
68 | region.dy = sy * vc->vc_font.height; | 68 | region.dy = sy * vc->vc_font.height; |
69 | region.width = width * vc->vc_font.width; | 69 | region.width = width * vc->vc_font.width; |
@@ -213,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
213 | unsigned int bs = info->var.yres - bh; | 213 | unsigned int bs = info->var.yres - bh; |
214 | struct fb_fillrect region; | 214 | struct fb_fillrect region; |
215 | 215 | ||
216 | region.color = attr_bgcol_ec(bgshift, vc); | 216 | region.color = attr_bgcol_ec(bgshift, vc, info); |
217 | region.rop = ROP_COPY; | 217 | region.rop = ROP_COPY; |
218 | 218 | ||
219 | if (rw && !bottom_only) { | 219 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0f32f4a00b2d..022282494d3f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -84,7 +84,7 @@ | |||
84 | #ifdef CONFIG_MAC | 84 | #ifdef CONFIG_MAC |
85 | #include <asm/macints.h> | 85 | #include <asm/macints.h> |
86 | #endif | 86 | #endif |
87 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 87 | #if defined(__mc68000__) |
88 | #include <asm/machdep.h> | 88 | #include <asm/machdep.h> |
89 | #include <asm/setup.h> | 89 | #include <asm/setup.h> |
90 | #endif | 90 | #endif |
@@ -147,7 +147,7 @@ static char fontname[40]; | |||
147 | static int info_idx = -1; | 147 | static int info_idx = -1; |
148 | 148 | ||
149 | /* console rotation */ | 149 | /* console rotation */ |
150 | static int rotate; | 150 | static int initial_rotation; |
151 | static int fbcon_has_sysfs; | 151 | static int fbcon_has_sysfs; |
152 | 152 | ||
153 | static const struct consw fb_con; | 153 | static const struct consw fb_con; |
@@ -334,10 +334,7 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, | |||
334 | switch (depth) { | 334 | switch (depth) { |
335 | case 1: | 335 | case 1: |
336 | { | 336 | { |
337 | int col = ~(0xfff << (max(info->var.green.length, | 337 | int col = mono_col(info); |
338 | max(info->var.red.length, | ||
339 | info->var.blue.length)))) & 0xff; | ||
340 | |||
341 | /* 0 or 1 */ | 338 | /* 0 or 1 */ |
342 | int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; | 339 | int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; |
343 | int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; | 340 | int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; |
@@ -537,9 +534,9 @@ static int __init fb_console_setup(char *this_opt) | |||
537 | if (!strncmp(options, "rotate:", 7)) { | 534 | if (!strncmp(options, "rotate:", 7)) { |
538 | options += 7; | 535 | options += 7; |
539 | if (*options) | 536 | if (*options) |
540 | rotate = simple_strtoul(options, &options, 0); | 537 | initial_rotation = simple_strtoul(options, &options, 0); |
541 | if (rotate > 3) | 538 | if (initial_rotation > 3) |
542 | rotate = 0; | 539 | initial_rotation = 0; |
543 | } | 540 | } |
544 | } | 541 | } |
545 | return 1; | 542 | return 1; |
@@ -989,7 +986,7 @@ static const char *fbcon_startup(void) | |||
989 | ops->graphics = 1; | 986 | ops->graphics = 1; |
990 | ops->cur_rotate = -1; | 987 | ops->cur_rotate = -1; |
991 | info->fbcon_par = ops; | 988 | info->fbcon_par = ops; |
992 | p->con_rotate = rotate; | 989 | p->con_rotate = initial_rotation; |
993 | set_blitting_type(vc, info); | 990 | set_blitting_type(vc, info); |
994 | 991 | ||
995 | if (info->fix.type != FB_TYPE_TEXT) { | 992 | if (info->fix.type != FB_TYPE_TEXT) { |
@@ -1176,7 +1173,7 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
1176 | con_copy_unimap(vc, svc); | 1173 | con_copy_unimap(vc, svc); |
1177 | 1174 | ||
1178 | ops = info->fbcon_par; | 1175 | ops = info->fbcon_par; |
1179 | p->con_rotate = rotate; | 1176 | p->con_rotate = initial_rotation; |
1180 | set_blitting_type(vc, info); | 1177 | set_blitting_type(vc, info); |
1181 | 1178 | ||
1182 | cols = vc->vc_cols; | 1179 | cols = vc->vc_cols; |
@@ -2795,7 +2792,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2795 | { | 2792 | { |
2796 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; | 2793 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; |
2797 | struct fbcon_ops *ops = info->fbcon_par; | 2794 | struct fbcon_ops *ops = info->fbcon_par; |
2798 | struct display *p = &fb_display[fg_console]; | 2795 | struct display *disp = &fb_display[fg_console]; |
2799 | int offset, limit, scrollback_old; | 2796 | int offset, limit, scrollback_old; |
2800 | 2797 | ||
2801 | if (softback_top) { | 2798 | if (softback_top) { |
@@ -2833,7 +2830,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2833 | logo_shown = FBCON_LOGO_CANSHOW; | 2830 | logo_shown = FBCON_LOGO_CANSHOW; |
2834 | } | 2831 | } |
2835 | fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); | 2832 | fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); |
2836 | fbcon_redraw_softback(vc, p, lines); | 2833 | fbcon_redraw_softback(vc, disp, lines); |
2837 | fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); | 2834 | fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); |
2838 | return 0; | 2835 | return 0; |
2839 | } | 2836 | } |
@@ -2855,9 +2852,9 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2855 | 2852 | ||
2856 | fbcon_cursor(vc, CM_ERASE); | 2853 | fbcon_cursor(vc, CM_ERASE); |
2857 | 2854 | ||
2858 | offset = p->yscroll - scrollback_current; | 2855 | offset = disp->yscroll - scrollback_current; |
2859 | limit = p->vrows; | 2856 | limit = disp->vrows; |
2860 | switch (p->scrollmode) { | 2857 | switch (disp->scrollmode) { |
2861 | case SCROLL_WRAP_MOVE: | 2858 | case SCROLL_WRAP_MOVE: |
2862 | info->var.vmode |= FB_VMODE_YWRAP; | 2859 | info->var.vmode |= FB_VMODE_YWRAP; |
2863 | break; | 2860 | break; |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 8e6ef4bc7a5c..3706307e70ed 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -93,10 +93,6 @@ struct fbcon_ops { | |||
93 | (((s) >> (fgshift)) & 0x0f) | 93 | (((s) >> (fgshift)) & 0x0f) |
94 | #define attr_bgcol(bgshift,s) \ | 94 | #define attr_bgcol(bgshift,s) \ |
95 | (((s) >> (bgshift)) & 0x0f) | 95 | (((s) >> (bgshift)) & 0x0f) |
96 | #define attr_bgcol_ec(bgshift,vc) \ | ||
97 | ((vc) ? (((vc)->vc_video_erase_char >> (bgshift)) & 0x0f) : 0) | ||
98 | #define attr_fgcol_ec(fgshift,vc) \ | ||
99 | ((vc) ? (((vc)->vc_video_erase_char >> (fgshift)) & 0x0f) : 0) | ||
100 | 96 | ||
101 | /* Monochrome */ | 97 | /* Monochrome */ |
102 | #define attr_bold(s) \ | 98 | #define attr_bold(s) \ |
@@ -108,6 +104,49 @@ struct fbcon_ops { | |||
108 | #define attr_blink(s) \ | 104 | #define attr_blink(s) \ |
109 | ((s) & 0x8000) | 105 | ((s) & 0x8000) |
110 | 106 | ||
107 | #define mono_col(info) \ | ||
108 | (~(0xfff << (max((info)->var.green.length, \ | ||
109 | max((info)->var.red.length, \ | ||
110 | (info)->var.blue.length)))) & 0xff) | ||
111 | |||
112 | static inline int attr_col_ec(int shift, struct vc_data *vc, | ||
113 | struct fb_info *info, int is_fg) | ||
114 | { | ||
115 | int is_mono01; | ||
116 | int col; | ||
117 | int fg; | ||
118 | int bg; | ||
119 | |||
120 | if (!vc) | ||
121 | return 0; | ||
122 | |||
123 | if (vc->vc_can_do_color) | ||
124 | return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) | ||
125 | : attr_bgcol(shift,vc->vc_video_erase_char); | ||
126 | |||
127 | if (!info) | ||
128 | return 0; | ||
129 | |||
130 | col = mono_col(info); | ||
131 | is_mono01 = info->fix.visual == FB_VISUAL_MONO01; | ||
132 | |||
133 | if (attr_reverse(vc->vc_video_erase_char)) { | ||
134 | fg = is_mono01 ? col : 0; | ||
135 | bg = is_mono01 ? 0 : col; | ||
136 | } | ||
137 | else { | ||
138 | fg = is_mono01 ? 0 : col; | ||
139 | bg = is_mono01 ? col : 0; | ||
140 | } | ||
141 | |||
142 | return is_fg ? fg : bg; | ||
143 | } | ||
144 | |||
145 | #define attr_bgcol_ec(bgshift,vc,info) \ | ||
146 | attr_col_ec(bgshift,vc,info,0); | ||
147 | #define attr_fgcol_ec(fgshift,vc,info) \ | ||
148 | attr_col_ec(fgshift,vc,info,1); | ||
149 | |||
111 | /* Font */ | 150 | /* Font */ |
112 | #define REFCOUNT(fd) (((int *)(fd))[-1]) | 151 | #define REFCOUNT(fd) (((int *)(fd))[-1]) |
113 | #define FNTSIZE(fd) (((int *)(fd))[-2]) | 152 | #define FNTSIZE(fd) (((int *)(fd))[-2]) |
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 825e6d6972a7..bdf913ecf001 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c | |||
@@ -84,7 +84,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
84 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 84 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
85 | u32 vyres = GETVYRES(ops->p->scrollmode, info); | 85 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
86 | 86 | ||
87 | region.color = attr_bgcol_ec(bgshift,vc); | 87 | region.color = attr_bgcol_ec(bgshift,vc,info); |
88 | region.dx = sy * vc->vc_font.height; | 88 | region.dx = sy * vc->vc_font.height; |
89 | region.dy = vyres - ((sx + width) * vc->vc_font.width); | 89 | region.dy = vyres - ((sx + width) * vc->vc_font.width); |
90 | region.height = width * vc->vc_font.width; | 90 | region.height = width * vc->vc_font.width; |
@@ -198,7 +198,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
198 | struct fb_fillrect region; | 198 | struct fb_fillrect region; |
199 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 199 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
200 | 200 | ||
201 | region.color = attr_bgcol_ec(bgshift,vc); | 201 | region.color = attr_bgcol_ec(bgshift,vc,info); |
202 | region.rop = ROP_COPY; | 202 | region.rop = ROP_COPY; |
203 | 203 | ||
204 | if (rw && !bottom_only) { | 204 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index c637e6318803..a6819b9d1770 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c | |||
@@ -70,7 +70,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
70 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 70 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
71 | u32 vxres = GETVXRES(ops->p->scrollmode, info); | 71 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
72 | 72 | ||
73 | region.color = attr_bgcol_ec(bgshift,vc); | 73 | region.color = attr_bgcol_ec(bgshift,vc,info); |
74 | region.dx = vxres - ((sy + height) * vc->vc_font.height); | 74 | region.dx = vxres - ((sy + height) * vc->vc_font.height); |
75 | region.dy = sx * vc->vc_font.width; | 75 | region.dy = sx * vc->vc_font.width; |
76 | region.height = width * vc->vc_font.width; | 76 | region.height = width * vc->vc_font.width; |
@@ -182,7 +182,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
182 | struct fb_fillrect region; | 182 | struct fb_fillrect region; |
183 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 183 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
184 | 184 | ||
185 | region.color = attr_bgcol_ec(bgshift,vc); | 185 | region.color = attr_bgcol_ec(bgshift,vc,info); |
186 | region.rop = ROP_COPY; | 186 | region.rop = ROP_COPY; |
187 | 187 | ||
188 | if (rw && !bottom_only) { | 188 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 1473506df5d0..d9b5d6eb68a7 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c | |||
@@ -71,7 +71,7 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
71 | u32 vyres = GETVYRES(ops->p->scrollmode, info); | 71 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); | 72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
73 | 73 | ||
74 | region.color = attr_bgcol_ec(bgshift,vc); | 74 | region.color = attr_bgcol_ec(bgshift,vc,info); |
75 | region.dy = vyres - ((sy + height) * vc->vc_font.height); | 75 | region.dy = vyres - ((sy + height) * vc->vc_font.height); |
76 | region.dx = vxres - ((sx + width) * vc->vc_font.width); | 76 | region.dx = vxres - ((sx + width) * vc->vc_font.width); |
77 | region.width = width * vc->vc_font.width; | 77 | region.width = width * vc->vc_font.width; |
@@ -228,7 +228,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
228 | struct fb_fillrect region; | 228 | struct fb_fillrect region; |
229 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 229 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
230 | 230 | ||
231 | region.color = attr_bgcol_ec(bgshift,vc); | 231 | region.color = attr_bgcol_ec(bgshift,vc,info); |
232 | region.rop = ROP_COPY; | 232 | region.rop = ROP_COPY; |
233 | 233 | ||
234 | if (rw && !bottom_only) { | 234 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 96979c377518..d0c03fd70871 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 18 | #if defined(__mc68000__) |
19 | #include <asm/setup.h> | 19 | #include <asm/setup.h> |
20 | #endif | 20 | #endif |
21 | #include <linux/font.h> | 21 | #include <linux/font.h> |
@@ -120,7 +120,7 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w, | |||
120 | for(i=0; i<num_fonts; i++) { | 120 | for(i=0; i<num_fonts; i++) { |
121 | f = fonts[i]; | 121 | f = fonts[i]; |
122 | c = f->pref; | 122 | c = f->pref; |
123 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 123 | #if defined(__mc68000__) |
124 | #ifdef CONFIG_FONT_PEARL_8x8 | 124 | #ifdef CONFIG_FONT_PEARL_8x8 |
125 | if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) | 125 | if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) |
126 | c = 100; | 126 | c = 100; |
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index d981fe4d86c6..0056a41e5c35 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c | |||
@@ -40,8 +40,8 @@ static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
40 | 40 | ||
41 | rect.index = vc->vc_video_erase_char & | 41 | rect.index = vc->vc_video_erase_char & |
42 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); | 42 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); |
43 | rect.fg = attr_fgcol_ec(fgshift, vc); | 43 | rect.fg = attr_fgcol_ec(fgshift, vc, info); |
44 | rect.bg = attr_bgcol_ec(bgshift, vc); | 44 | rect.bg = attr_bgcol_ec(bgshift, vc, info); |
45 | rect.sx = sx; | 45 | rect.sx = sx; |
46 | rect.sy = sy; | 46 | rect.sy = sy; |
47 | rect.width = width; | 47 | rect.width = width; |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index f65bcd314d54..6df29a62d720 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1153,8 +1153,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1153 | 1153 | ||
1154 | /* if 512 char mode is already enabled don't re-enable it. */ | 1154 | /* if 512 char mode is already enabled don't re-enable it. */ |
1155 | if ((set) && (ch512 != vga_512_chars)) { | 1155 | if ((set) && (ch512 != vga_512_chars)) { |
1156 | int i; | ||
1157 | |||
1158 | /* attribute controller */ | 1156 | /* attribute controller */ |
1159 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 1157 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
1160 | struct vc_data *c = vc_cons[i].d; | 1158 | struct vc_data *c = vc_cons[i].d; |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index a0c5d9d90d74..0f8cfb988c90 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
26 | 26 | ||
27 | /* this is to find and return the vmalloc-ed fb pages */ | 27 | /* this is to find and return the vmalloc-ed fb pages */ |
28 | static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma, | 28 | static int fb_deferred_io_fault(struct vm_area_struct *vma, |
29 | unsigned long vaddr, int *type) | 29 | struct vm_fault *vmf) |
30 | { | 30 | { |
31 | unsigned long offset; | 31 | unsigned long offset; |
32 | struct page *page; | 32 | struct page *page; |
@@ -34,18 +34,17 @@ static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma, | |||
34 | /* info->screen_base is in System RAM */ | 34 | /* info->screen_base is in System RAM */ |
35 | void *screen_base = (void __force *) info->screen_base; | 35 | void *screen_base = (void __force *) info->screen_base; |
36 | 36 | ||
37 | offset = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); | 37 | offset = vmf->pgoff << PAGE_SHIFT; |
38 | if (offset >= info->fix.smem_len) | 38 | if (offset >= info->fix.smem_len) |
39 | return NOPAGE_SIGBUS; | 39 | return VM_FAULT_SIGBUS; |
40 | 40 | ||
41 | page = vmalloc_to_page(screen_base + offset); | 41 | page = vmalloc_to_page(screen_base + offset); |
42 | if (!page) | 42 | if (!page) |
43 | return NOPAGE_OOM; | 43 | return VM_FAULT_SIGBUS; |
44 | 44 | ||
45 | get_page(page); | 45 | get_page(page); |
46 | if (type) | 46 | vmf->page = page; |
47 | *type = VM_FAULT_MINOR; | 47 | return 0; |
48 | return page; | ||
49 | } | 48 | } |
50 | 49 | ||
51 | int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) | 50 | int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) |
@@ -84,7 +83,7 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
84 | } | 83 | } |
85 | 84 | ||
86 | static struct vm_operations_struct fb_deferred_io_vm_ops = { | 85 | static struct vm_operations_struct fb_deferred_io_vm_ops = { |
87 | .nopage = fb_deferred_io_nopage, | 86 | .fault = fb_deferred_io_fault, |
88 | .page_mkwrite = fb_deferred_io_mkwrite, | 87 | .page_mkwrite = fb_deferred_io_mkwrite, |
89 | }; | 88 | }; |
90 | 89 | ||
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h index cdafbe14ef1f..a2a0618d86a5 100644 --- a/drivers/video/fb_draw.h +++ b/drivers/video/fb_draw.h | |||
@@ -91,6 +91,7 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val, | |||
91 | val = comp(val >> 2, val << 2, REV_PIXELS_MASK2); | 91 | val = comp(val >> 2, val << 2, REV_PIXELS_MASK2); |
92 | if (bswapmask & 3) | 92 | if (bswapmask & 3) |
93 | val = comp(val >> 4, val << 4, REV_PIXELS_MASK4); | 93 | val = comp(val >> 4, val << 4, REV_PIXELS_MASK4); |
94 | return val; | ||
94 | } | 95 | } |
95 | 96 | ||
96 | static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) | 97 | static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) |
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 4ba9c0894416..052e18058498 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net> | 4 | * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net> |
5 | * | 5 | * |
6 | * Credits: | 6 | * Credits: |
7 | * | 7 | * |
8 | * The EDID Parser is a conglomeration from the following sources: | 8 | * The EDID Parser is a conglomeration from the following sources: |
9 | * | 9 | * |
10 | * 1. SciTech SNAP Graphics Architecture | 10 | * 1. SciTech SNAP Graphics Architecture |
@@ -12,13 +12,13 @@ | |||
12 | * | 12 | * |
13 | * 2. XFree86 4.3.0, interpret_edid.c | 13 | * 2. XFree86 4.3.0, interpret_edid.c |
14 | * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> | 14 | * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> |
15 | * | 15 | * |
16 | * 3. John Fremlin <vii@users.sourceforge.net> and | 16 | * 3. John Fremlin <vii@users.sourceforge.net> and |
17 | * Ani Joshi <ajoshi@unixbox.com> | 17 | * Ani Joshi <ajoshi@unixbox.com> |
18 | * | 18 | * |
19 | * Generalized Timing Formula is derived from: | 19 | * Generalized Timing Formula is derived from: |
20 | * | 20 | * |
21 | * GTF Spreadsheet by Andy Morrish (1/5/97) | 21 | * GTF Spreadsheet by Andy Morrish (1/5/97) |
22 | * available at http://www.vesa.org | 22 | * available at http://www.vesa.org |
23 | * | 23 | * |
24 | * This file is subject to the terms and conditions of the GNU General Public | 24 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -36,7 +36,7 @@ | |||
36 | #endif | 36 | #endif |
37 | #include "edid.h" | 37 | #include "edid.h" |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * EDID parser | 40 | * EDID parser |
41 | */ | 41 | */ |
42 | 42 | ||
@@ -160,8 +160,8 @@ static int check_edid(unsigned char *edid) | |||
160 | for (i = 0; i < ARRAY_SIZE(brokendb); i++) { | 160 | for (i = 0; i < ARRAY_SIZE(brokendb); i++) { |
161 | if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && | 161 | if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && |
162 | brokendb[i].model == model) { | 162 | brokendb[i].model == model) { |
163 | fix = brokendb[i].fix; | 163 | fix = brokendb[i].fix; |
164 | break; | 164 | break; |
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
@@ -323,7 +323,7 @@ static void get_dpms_capabilities(unsigned char flags, | |||
323 | (flags & DPMS_SUSPEND) ? "yes" : "no", | 323 | (flags & DPMS_SUSPEND) ? "yes" : "no", |
324 | (flags & DPMS_STANDBY) ? "yes" : "no"); | 324 | (flags & DPMS_STANDBY) ? "yes" : "no"); |
325 | } | 325 | } |
326 | 326 | ||
327 | static void get_chroma(unsigned char *block, struct fb_monspecs *specs) | 327 | static void get_chroma(unsigned char *block, struct fb_monspecs *specs) |
328 | { | 328 | { |
329 | int tmp; | 329 | int tmp; |
@@ -365,7 +365,7 @@ static void get_chroma(unsigned char *block, struct fb_monspecs *specs) | |||
365 | tmp += 512; | 365 | tmp += 512; |
366 | specs->chroma.bluey = tmp/1024; | 366 | specs->chroma.bluey = tmp/1024; |
367 | DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey); | 367 | DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey); |
368 | 368 | ||
369 | tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2); | 369 | tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2); |
370 | tmp *= 1000; | 370 | tmp *= 1000; |
371 | tmp += 512; | 371 | tmp += 512; |
@@ -383,7 +383,7 @@ static void calc_mode_timings(int xres, int yres, int refresh, | |||
383 | struct fb_videomode *mode) | 383 | struct fb_videomode *mode) |
384 | { | 384 | { |
385 | struct fb_var_screeninfo *var; | 385 | struct fb_var_screeninfo *var; |
386 | 386 | ||
387 | var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); | 387 | var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); |
388 | 388 | ||
389 | if (var) { | 389 | if (var) { |
@@ -451,11 +451,11 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
451 | 451 | ||
452 | c = block[1]; | 452 | c = block[1]; |
453 | if (c&0x80) { | 453 | if (c&0x80) { |
454 | mode[num++] = vesa_modes[9]; | 454 | mode[num++] = vesa_modes[9]; |
455 | DPRINTK(" 800x600@72Hz\n"); | 455 | DPRINTK(" 800x600@72Hz\n"); |
456 | } | 456 | } |
457 | if (c&0x40) { | 457 | if (c&0x40) { |
458 | mode[num++] = vesa_modes[10]; | 458 | mode[num++] = vesa_modes[10]; |
459 | DPRINTK(" 800x600@75Hz\n"); | 459 | DPRINTK(" 800x600@75Hz\n"); |
460 | } | 460 | } |
461 | if (c&0x20) { | 461 | if (c&0x20) { |
@@ -495,7 +495,7 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
495 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | 495 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) |
496 | { | 496 | { |
497 | int xres, yres = 0, refresh, ratio, i; | 497 | int xres, yres = 0, refresh, ratio, i; |
498 | 498 | ||
499 | xres = (block[0] + 31) * 8; | 499 | xres = (block[0] + 31) * 8; |
500 | if (xres <= 256) | 500 | if (xres <= 256) |
501 | return 0; | 501 | return 0; |
@@ -519,7 +519,7 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | |||
519 | 519 | ||
520 | DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); | 520 | DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); |
521 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { | 521 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { |
522 | if (vesa_modes[i].xres == xres && | 522 | if (vesa_modes[i].xres == xres && |
523 | vesa_modes[i].yres == yres && | 523 | vesa_modes[i].yres == yres && |
524 | vesa_modes[i].refresh == refresh) { | 524 | vesa_modes[i].refresh == refresh) { |
525 | *mode = vesa_modes[i]; | 525 | *mode = vesa_modes[i]; |
@@ -536,13 +536,13 @@ static int get_dst_timing(unsigned char *block, | |||
536 | { | 536 | { |
537 | int j, num = 0; | 537 | int j, num = 0; |
538 | 538 | ||
539 | for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE) | 539 | for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) |
540 | num += get_std_timing(block, &mode[num]); | 540 | num += get_std_timing(block, &mode[num]); |
541 | 541 | ||
542 | return num; | 542 | return num; |
543 | } | 543 | } |
544 | 544 | ||
545 | static void get_detailed_timing(unsigned char *block, | 545 | static void get_detailed_timing(unsigned char *block, |
546 | struct fb_videomode *mode) | 546 | struct fb_videomode *mode) |
547 | { | 547 | { |
548 | mode->xres = H_ACTIVE; | 548 | mode->xres = H_ACTIVE; |
@@ -553,7 +553,7 @@ static void get_detailed_timing(unsigned char *block, | |||
553 | mode->right_margin = H_SYNC_OFFSET; | 553 | mode->right_margin = H_SYNC_OFFSET; |
554 | mode->left_margin = (H_ACTIVE + H_BLANKING) - | 554 | mode->left_margin = (H_ACTIVE + H_BLANKING) - |
555 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); | 555 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); |
556 | mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - | 556 | mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - |
557 | V_SYNC_WIDTH; | 557 | V_SYNC_WIDTH; |
558 | mode->lower_margin = V_SYNC_OFFSET; | 558 | mode->lower_margin = V_SYNC_OFFSET; |
559 | mode->hsync_len = H_SYNC_WIDTH; | 559 | mode->hsync_len = H_SYNC_WIDTH; |
@@ -597,7 +597,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
597 | if (mode == NULL) | 597 | if (mode == NULL) |
598 | return NULL; | 598 | return NULL; |
599 | 599 | ||
600 | if (edid == NULL || !edid_checksum(edid) || | 600 | if (edid == NULL || !edid_checksum(edid) || |
601 | !edid_check_header(edid)) { | 601 | !edid_check_header(edid)) { |
602 | kfree(mode); | 602 | kfree(mode); |
603 | return NULL; | 603 | return NULL; |
@@ -632,7 +632,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
632 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) | 632 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) |
633 | num += get_dst_timing(block + 5, &mode[num]); | 633 | num += get_dst_timing(block + 5, &mode[num]); |
634 | } | 634 | } |
635 | 635 | ||
636 | /* Yikes, EDID data is totally useless */ | 636 | /* Yikes, EDID data is totally useless */ |
637 | if (!num) { | 637 | if (!num) { |
638 | kfree(mode); | 638 | kfree(mode); |
@@ -686,7 +686,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) | |||
686 | /* estimate monitor limits based on modes supported */ | 686 | /* estimate monitor limits based on modes supported */ |
687 | if (retval) { | 687 | if (retval) { |
688 | struct fb_videomode *modes, *mode; | 688 | struct fb_videomode *modes, *mode; |
689 | int num_modes, i, hz, hscan, pixclock; | 689 | int num_modes, hz, hscan, pixclock; |
690 | int vtotal, htotal; | 690 | int vtotal, htotal; |
691 | 691 | ||
692 | modes = fb_create_modedb(edid, &num_modes); | 692 | modes = fb_create_modedb(edid, &num_modes); |
@@ -713,7 +713,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) | |||
713 | hscan = (pixclock + htotal / 2) / htotal; | 713 | hscan = (pixclock + htotal / 2) / htotal; |
714 | hscan = (hscan + 500) / 1000 * 1000; | 714 | hscan = (hscan + 500) / 1000 * 1000; |
715 | hz = (hscan + vtotal / 2) / vtotal; | 715 | hz = (hscan + vtotal / 2) / vtotal; |
716 | 716 | ||
717 | if (specs->dclkmax == 0 || specs->dclkmax < pixclock) | 717 | if (specs->dclkmax == 0 || specs->dclkmax < pixclock) |
718 | specs->dclkmax = pixclock; | 718 | specs->dclkmax = pixclock; |
719 | 719 | ||
@@ -966,8 +966,8 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) | |||
966 | DPRINTK("========================================\n"); | 966 | DPRINTK("========================================\n"); |
967 | } | 967 | } |
968 | 968 | ||
969 | /* | 969 | /* |
970 | * VESA Generalized Timing Formula (GTF) | 970 | * VESA Generalized Timing Formula (GTF) |
971 | */ | 971 | */ |
972 | 972 | ||
973 | #define FLYBACK 550 | 973 | #define FLYBACK 550 |
@@ -996,7 +996,7 @@ struct __fb_timings { | |||
996 | * @hfreq: horizontal freq | 996 | * @hfreq: horizontal freq |
997 | * | 997 | * |
998 | * DESCRIPTION: | 998 | * DESCRIPTION: |
999 | * vblank = right_margin + vsync_len + left_margin | 999 | * vblank = right_margin + vsync_len + left_margin |
1000 | * | 1000 | * |
1001 | * given: right_margin = 1 (V_FRONTPORCH) | 1001 | * given: right_margin = 1 (V_FRONTPORCH) |
1002 | * vsync_len = 3 | 1002 | * vsync_len = 3 |
@@ -1010,12 +1010,12 @@ static u32 fb_get_vblank(u32 hfreq) | |||
1010 | { | 1010 | { |
1011 | u32 vblank; | 1011 | u32 vblank; |
1012 | 1012 | ||
1013 | vblank = (hfreq * FLYBACK)/1000; | 1013 | vblank = (hfreq * FLYBACK)/1000; |
1014 | vblank = (vblank + 500)/1000; | 1014 | vblank = (vblank + 500)/1000; |
1015 | return (vblank + V_FRONTPORCH); | 1015 | return (vblank + V_FRONTPORCH); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | /** | 1018 | /** |
1019 | * fb_get_hblank_by_freq - get horizontal blank time given hfreq | 1019 | * fb_get_hblank_by_freq - get horizontal blank time given hfreq |
1020 | * @hfreq: horizontal freq | 1020 | * @hfreq: horizontal freq |
1021 | * @xres: horizontal resolution in pixels | 1021 | * @xres: horizontal resolution in pixels |
@@ -1031,7 +1031,7 @@ static u32 fb_get_vblank(u32 hfreq) | |||
1031 | * | 1031 | * |
1032 | * where: C = ((offset - scale factor) * blank_scale) | 1032 | * where: C = ((offset - scale factor) * blank_scale) |
1033 | * -------------------------------------- + scale factor | 1033 | * -------------------------------------- + scale factor |
1034 | * 256 | 1034 | * 256 |
1035 | * M = blank_scale * gradient | 1035 | * M = blank_scale * gradient |
1036 | * | 1036 | * |
1037 | */ | 1037 | */ |
@@ -1039,7 +1039,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1039 | { | 1039 | { |
1040 | u32 c_val, m_val, duty_cycle, hblank; | 1040 | u32 c_val, m_val, duty_cycle, hblank; |
1041 | 1041 | ||
1042 | c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + | 1042 | c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + |
1043 | H_SCALEFACTOR) * 1000; | 1043 | H_SCALEFACTOR) * 1000; |
1044 | m_val = (H_BLANKSCALE * H_GRADIENT)/256; | 1044 | m_val = (H_BLANKSCALE * H_GRADIENT)/256; |
1045 | m_val = (m_val * 1000000)/hfreq; | 1045 | m_val = (m_val * 1000000)/hfreq; |
@@ -1048,7 +1048,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1048 | return (hblank); | 1048 | return (hblank); |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | /** | 1051 | /** |
1052 | * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock | 1052 | * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock |
1053 | * @dclk: pixelclock in Hz | 1053 | * @dclk: pixelclock in Hz |
1054 | * @xres: horizontal resolution in pixels | 1054 | * @xres: horizontal resolution in pixels |
@@ -1061,7 +1061,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1061 | * | 1061 | * |
1062 | * duty cycle = percent of htotal assigned to inactive display | 1062 | * duty cycle = percent of htotal assigned to inactive display |
1063 | * duty cycle = C - (M * h_period) | 1063 | * duty cycle = C - (M * h_period) |
1064 | * | 1064 | * |
1065 | * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 | 1065 | * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 |
1066 | * ----------------------------------------------- | 1066 | * ----------------------------------------------- |
1067 | * 2 * M | 1067 | * 2 * M |
@@ -1077,11 +1077,11 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1077 | h_period = 100 - C_VAL; | 1077 | h_period = 100 - C_VAL; |
1078 | h_period *= h_period; | 1078 | h_period *= h_period; |
1079 | h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk); | 1079 | h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk); |
1080 | h_period *=10000; | 1080 | h_period *= 10000; |
1081 | 1081 | ||
1082 | h_period = int_sqrt(h_period); | 1082 | h_period = int_sqrt(h_period); |
1083 | h_period -= (100 - C_VAL) * 100; | 1083 | h_period -= (100 - C_VAL) * 100; |
1084 | h_period *= 1000; | 1084 | h_period *= 1000; |
1085 | h_period /= 2 * M_VAL; | 1085 | h_period /= 2 * M_VAL; |
1086 | 1086 | ||
1087 | duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100; | 1087 | duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100; |
@@ -1089,7 +1089,7 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1089 | hblank &= ~15; | 1089 | hblank &= ~15; |
1090 | return (hblank); | 1090 | return (hblank); |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /** | 1093 | /** |
1094 | * fb_get_hfreq - estimate hsync | 1094 | * fb_get_hfreq - estimate hsync |
1095 | * @vfreq: vertical refresh rate | 1095 | * @vfreq: vertical refresh rate |
@@ -1100,13 +1100,13 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1100 | * (yres + front_port) * vfreq * 1000000 | 1100 | * (yres + front_port) * vfreq * 1000000 |
1101 | * hfreq = ------------------------------------- | 1101 | * hfreq = ------------------------------------- |
1102 | * (1000000 - (vfreq * FLYBACK) | 1102 | * (1000000 - (vfreq * FLYBACK) |
1103 | * | 1103 | * |
1104 | */ | 1104 | */ |
1105 | 1105 | ||
1106 | static u32 fb_get_hfreq(u32 vfreq, u32 yres) | 1106 | static u32 fb_get_hfreq(u32 vfreq, u32 yres) |
1107 | { | 1107 | { |
1108 | u32 divisor, hfreq; | 1108 | u32 divisor, hfreq; |
1109 | 1109 | ||
1110 | divisor = (1000000 - (vfreq * FLYBACK))/1000; | 1110 | divisor = (1000000 - (vfreq * FLYBACK))/1000; |
1111 | hfreq = (yres + V_FRONTPORCH) * vfreq * 1000; | 1111 | hfreq = (yres + V_FRONTPORCH) * vfreq * 1000; |
1112 | return (hfreq/divisor); | 1112 | return (hfreq/divisor); |
@@ -1117,7 +1117,7 @@ static void fb_timings_vfreq(struct __fb_timings *timings) | |||
1117 | timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive); | 1117 | timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive); |
1118 | timings->vblank = fb_get_vblank(timings->hfreq); | 1118 | timings->vblank = fb_get_vblank(timings->hfreq); |
1119 | timings->vtotal = timings->vactive + timings->vblank; | 1119 | timings->vtotal = timings->vactive + timings->vblank; |
1120 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, | 1120 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, |
1121 | timings->hactive); | 1121 | timings->hactive); |
1122 | timings->htotal = timings->hactive + timings->hblank; | 1122 | timings->htotal = timings->hactive + timings->hblank; |
1123 | timings->dclk = timings->htotal * timings->hfreq; | 1123 | timings->dclk = timings->htotal * timings->hfreq; |
@@ -1128,7 +1128,7 @@ static void fb_timings_hfreq(struct __fb_timings *timings) | |||
1128 | timings->vblank = fb_get_vblank(timings->hfreq); | 1128 | timings->vblank = fb_get_vblank(timings->hfreq); |
1129 | timings->vtotal = timings->vactive + timings->vblank; | 1129 | timings->vtotal = timings->vactive + timings->vblank; |
1130 | timings->vfreq = timings->hfreq/timings->vtotal; | 1130 | timings->vfreq = timings->hfreq/timings->vtotal; |
1131 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, | 1131 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, |
1132 | timings->hactive); | 1132 | timings->hactive); |
1133 | timings->htotal = timings->hactive + timings->hblank; | 1133 | timings->htotal = timings->hactive + timings->hblank; |
1134 | timings->dclk = timings->htotal * timings->hfreq; | 1134 | timings->dclk = timings->htotal * timings->hfreq; |
@@ -1136,7 +1136,7 @@ static void fb_timings_hfreq(struct __fb_timings *timings) | |||
1136 | 1136 | ||
1137 | static void fb_timings_dclk(struct __fb_timings *timings) | 1137 | static void fb_timings_dclk(struct __fb_timings *timings) |
1138 | { | 1138 | { |
1139 | timings->hblank = fb_get_hblank_by_dclk(timings->dclk, | 1139 | timings->hblank = fb_get_hblank_by_dclk(timings->dclk, |
1140 | timings->hactive); | 1140 | timings->hactive); |
1141 | timings->htotal = timings->hactive + timings->hblank; | 1141 | timings->htotal = timings->hactive + timings->hblank; |
1142 | timings->hfreq = timings->dclk/timings->htotal; | 1142 | timings->hfreq = timings->dclk/timings->htotal; |
@@ -1156,29 +1156,29 @@ static void fb_timings_dclk(struct __fb_timings *timings) | |||
1156 | * @info: pointer to fb_info | 1156 | * @info: pointer to fb_info |
1157 | * | 1157 | * |
1158 | * DESCRIPTION: | 1158 | * DESCRIPTION: |
1159 | * Calculates video mode based on monitor specs using VESA GTF. | 1159 | * Calculates video mode based on monitor specs using VESA GTF. |
1160 | * The GTF is best for VESA GTF compliant monitors but is | 1160 | * The GTF is best for VESA GTF compliant monitors but is |
1161 | * specifically formulated to work for older monitors as well. | 1161 | * specifically formulated to work for older monitors as well. |
1162 | * | 1162 | * |
1163 | * If @flag==0, the function will attempt to maximize the | 1163 | * If @flag==0, the function will attempt to maximize the |
1164 | * refresh rate. Otherwise, it will calculate timings based on | 1164 | * refresh rate. Otherwise, it will calculate timings based on |
1165 | * the flag and accompanying value. | 1165 | * the flag and accompanying value. |
1166 | * | 1166 | * |
1167 | * If FB_IGNOREMON bit is set in @flags, monitor specs will be | 1167 | * If FB_IGNOREMON bit is set in @flags, monitor specs will be |
1168 | * ignored and @var will be filled with the calculated timings. | 1168 | * ignored and @var will be filled with the calculated timings. |
1169 | * | 1169 | * |
1170 | * All calculations are based on the VESA GTF Spreadsheet | 1170 | * All calculations are based on the VESA GTF Spreadsheet |
1171 | * available at VESA's public ftp (http://www.vesa.org). | 1171 | * available at VESA's public ftp (http://www.vesa.org). |
1172 | * | 1172 | * |
1173 | * NOTES: | 1173 | * NOTES: |
1174 | * The timings generated by the GTF will be different from VESA | 1174 | * The timings generated by the GTF will be different from VESA |
1175 | * DMT. It might be a good idea to keep a table of standard | 1175 | * DMT. It might be a good idea to keep a table of standard |
1176 | * VESA modes as well. The GTF may also not work for some displays, | 1176 | * VESA modes as well. The GTF may also not work for some displays, |
1177 | * such as, and especially, analog TV. | 1177 | * such as, and especially, analog TV. |
1178 | * | 1178 | * |
1179 | * REQUIRES: | 1179 | * REQUIRES: |
1180 | * A valid info->monspecs, otherwise 'safe numbers' will be used. | 1180 | * A valid info->monspecs, otherwise 'safe numbers' will be used. |
1181 | */ | 1181 | */ |
1182 | int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) | 1182 | int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) |
1183 | { | 1183 | { |
1184 | struct __fb_timings *timings; | 1184 | struct __fb_timings *timings; |
@@ -1191,7 +1191,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1191 | if (!timings) | 1191 | if (!timings) |
1192 | return -ENOMEM; | 1192 | return -ENOMEM; |
1193 | 1193 | ||
1194 | /* | 1194 | /* |
1195 | * If monspecs are invalid, use values that are enough | 1195 | * If monspecs are invalid, use values that are enough |
1196 | * for 640x480@60 | 1196 | * for 640x480@60 |
1197 | */ | 1197 | */ |
@@ -1214,7 +1214,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1214 | 1214 | ||
1215 | timings->hactive = var->xres; | 1215 | timings->hactive = var->xres; |
1216 | timings->vactive = var->yres; | 1216 | timings->vactive = var->yres; |
1217 | if (var->vmode & FB_VMODE_INTERLACED) { | 1217 | if (var->vmode & FB_VMODE_INTERLACED) { |
1218 | timings->vactive /= 2; | 1218 | timings->vactive /= 2; |
1219 | interlace = 2; | 1219 | interlace = 2; |
1220 | } | 1220 | } |
@@ -1250,9 +1250,9 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1250 | break; | 1250 | break; |
1251 | default: | 1251 | default: |
1252 | err = -EINVAL; | 1252 | err = -EINVAL; |
1253 | 1253 | ||
1254 | } | 1254 | } |
1255 | 1255 | ||
1256 | if (err || (!(flags & FB_IGNOREMON) && | 1256 | if (err || (!(flags & FB_IGNOREMON) && |
1257 | (timings->vfreq < vfmin || timings->vfreq > vfmax || | 1257 | (timings->vfreq < vfmin || timings->vfreq > vfmax || |
1258 | timings->hfreq < hfmin || timings->hfreq > hfmax || | 1258 | timings->hfreq < hfmin || timings->hfreq > hfmax || |
@@ -1269,7 +1269,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1269 | var->upper_margin = (timings->vblank * interlace)/dscan - | 1269 | var->upper_margin = (timings->vblank * interlace)/dscan - |
1270 | (var->vsync_len + var->lower_margin); | 1270 | (var->vsync_len + var->lower_margin); |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | kfree(timings); | 1273 | kfree(timings); |
1274 | return err; | 1274 | return err; |
1275 | } | 1275 | } |
@@ -1291,7 +1291,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, | |||
1291 | return -EINVAL; | 1291 | return -EINVAL; |
1292 | } | 1292 | } |
1293 | #endif /* CONFIG_FB_MODE_HELPERS */ | 1293 | #endif /* CONFIG_FB_MODE_HELPERS */ |
1294 | 1294 | ||
1295 | /* | 1295 | /* |
1296 | * fb_validate_mode - validates var against monitor capabilities | 1296 | * fb_validate_mode - validates var against monitor capabilities |
1297 | * @var: pointer to fb_var_screeninfo | 1297 | * @var: pointer to fb_var_screeninfo |
@@ -1309,7 +1309,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1309 | u32 hfreq, vfreq, htotal, vtotal, pixclock; | 1309 | u32 hfreq, vfreq, htotal, vtotal, pixclock; |
1310 | u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; | 1310 | u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; |
1311 | 1311 | ||
1312 | /* | 1312 | /* |
1313 | * If monspecs are invalid, use values that are enough | 1313 | * If monspecs are invalid, use values that are enough |
1314 | * for 640x480@60 | 1314 | * for 640x480@60 |
1315 | */ | 1315 | */ |
@@ -1333,10 +1333,10 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1333 | if (!var->pixclock) | 1333 | if (!var->pixclock) |
1334 | return -EINVAL; | 1334 | return -EINVAL; |
1335 | pixclock = PICOS2KHZ(var->pixclock) * 1000; | 1335 | pixclock = PICOS2KHZ(var->pixclock) * 1000; |
1336 | 1336 | ||
1337 | htotal = var->xres + var->right_margin + var->hsync_len + | 1337 | htotal = var->xres + var->right_margin + var->hsync_len + |
1338 | var->left_margin; | 1338 | var->left_margin; |
1339 | vtotal = var->yres + var->lower_margin + var->vsync_len + | 1339 | vtotal = var->yres + var->lower_margin + var->vsync_len + |
1340 | var->upper_margin; | 1340 | var->upper_margin; |
1341 | 1341 | ||
1342 | if (var->vmode & FB_VMODE_INTERLACED) | 1342 | if (var->vmode & FB_VMODE_INTERLACED) |
@@ -1349,7 +1349,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1349 | 1349 | ||
1350 | vfreq = hfreq/vtotal; | 1350 | vfreq = hfreq/vtotal; |
1351 | 1351 | ||
1352 | return (vfreq < vfmin || vfreq > vfmax || | 1352 | return (vfreq < vfmin || vfreq > vfmax || |
1353 | hfreq < hfmin || hfreq > hfmax || | 1353 | hfreq < hfmin || hfreq > hfmax || |
1354 | pixclock < dclkmin || pixclock > dclkmax) ? | 1354 | pixclock < dclkmin || pixclock > dclkmax) ? |
1355 | -EINVAL : 0; | 1355 | -EINVAL : 0; |
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c index 583185fd7c94..eb6b88171538 100644 --- a/drivers/video/geode/lxfb_core.c +++ b/drivers/video/geode/lxfb_core.c | |||
@@ -34,7 +34,7 @@ static int fbsize; | |||
34 | * we try to make it something sane - 640x480-60 is sane | 34 | * we try to make it something sane - 640x480-60 is sane |
35 | */ | 35 | */ |
36 | 36 | ||
37 | const struct fb_videomode geode_modedb[] __initdata = { | 37 | static const struct fb_videomode geode_modedb[] __initdata = { |
38 | /* 640x480-60 */ | 38 | /* 640x480-60 */ |
39 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, | 39 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, |
40 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 40 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index b18486ad8e17..2eb4fb159084 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c | |||
@@ -207,7 +207,8 @@ static struct fb_ops hpfb_ops = { | |||
207 | #define HPFB_FBOMSB 0x5d /* Frame buffer offset */ | 207 | #define HPFB_FBOMSB 0x5d /* Frame buffer offset */ |
208 | #define HPFB_FBOLSB 0x5f | 208 | #define HPFB_FBOLSB 0x5f |
209 | 209 | ||
210 | static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base) | 210 | static int __devinit hpfb_init_one(unsigned long phys_base, |
211 | unsigned long virt_base) | ||
211 | { | 212 | { |
212 | unsigned long fboff, fb_width, fb_height, fb_start; | 213 | unsigned long fboff, fb_width, fb_height, fb_start; |
213 | 214 | ||
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 1a7d7789d877..1d13dd099af8 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -1476,7 +1476,7 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1476 | struct i810fb_par *par = info->par; | 1476 | struct i810fb_par *par = info->par; |
1477 | u8 __iomem *mmio = par->mmio_start_virtual; | 1477 | u8 __iomem *mmio = par->mmio_start_virtual; |
1478 | 1478 | ||
1479 | if (!par->dev_flags & LOCKUP) | 1479 | if (!(par->dev_flags & LOCKUP)) |
1480 | return -ENXIO; | 1480 | return -ENXIO; |
1481 | 1481 | ||
1482 | if (cursor->image.width > 64 || cursor->image.height > 64) | 1482 | if (cursor->image.width > 64 || cursor->image.height > 64) |
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index b87ea21d3d78..3a81060137a2 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c | |||
@@ -400,6 +400,7 @@ int __init igafb_init(void) | |||
400 | info = kzalloc(size, GFP_ATOMIC); | 400 | info = kzalloc(size, GFP_ATOMIC); |
401 | if (!info) { | 401 | if (!info) { |
402 | printk("igafb_init: can't alloc fb_info\n"); | 402 | printk("igafb_init: can't alloc fb_info\n"); |
403 | pci_dev_put(pdev); | ||
403 | return -ENOMEM; | 404 | return -ENOMEM; |
404 | } | 405 | } |
405 | 406 | ||
@@ -409,12 +410,14 @@ int __init igafb_init(void) | |||
409 | if ((addr = pdev->resource[0].start) == 0) { | 410 | if ((addr = pdev->resource[0].start) == 0) { |
410 | printk("igafb_init: no memory start\n"); | 411 | printk("igafb_init: no memory start\n"); |
411 | kfree(info); | 412 | kfree(info); |
413 | pci_dev_put(pdev); | ||
412 | return -ENXIO; | 414 | return -ENXIO; |
413 | } | 415 | } |
414 | 416 | ||
415 | if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { | 417 | if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { |
416 | printk("igafb_init: can't remap %lx[2M]\n", addr); | 418 | printk("igafb_init: can't remap %lx[2M]\n", addr); |
417 | kfree(info); | 419 | kfree(info); |
420 | pci_dev_put(pdev); | ||
418 | return -ENXIO; | 421 | return -ENXIO; |
419 | } | 422 | } |
420 | 423 | ||
@@ -449,6 +452,7 @@ int __init igafb_init(void) | |||
449 | printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); | 452 | printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); |
450 | iounmap((void *)info->screen_base); | 453 | iounmap((void *)info->screen_base); |
451 | kfree(info); | 454 | kfree(info); |
455 | pci_dev_put(pdev); | ||
452 | return -ENXIO; | 456 | return -ENXIO; |
453 | } | 457 | } |
454 | 458 | ||
@@ -466,6 +470,7 @@ int __init igafb_init(void) | |||
466 | iounmap((void *)par->io_base); | 470 | iounmap((void *)par->io_base); |
467 | iounmap(info->screen_base); | 471 | iounmap(info->screen_base); |
468 | kfree(info); | 472 | kfree(info); |
473 | pci_dev_put(pdev); | ||
469 | return -ENOMEM; | 474 | return -ENOMEM; |
470 | } | 475 | } |
471 | 476 | ||
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 5f6fb7d2c408..fa1fff553565 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -1971,7 +1971,7 @@ void intelfbhw_cursor_reset(struct intelfb_info *dinfo) | |||
1971 | static irqreturn_t intelfbhw_irq(int irq, void *dev_id) | 1971 | static irqreturn_t intelfbhw_irq(int irq, void *dev_id) |
1972 | { | 1972 | { |
1973 | u16 tmp; | 1973 | u16 tmp; |
1974 | struct intelfb_info *dinfo = (struct intelfb_info *)dev_id; | 1974 | struct intelfb_info *dinfo = dev_id; |
1975 | 1975 | ||
1976 | spin_lock(&dinfo->int_lock); | 1976 | spin_lock(&dinfo->int_lock); |
1977 | 1977 | ||
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 4b6a99b5be0d..5246b0402d76 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
@@ -2066,40 +2066,49 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st | |||
2066 | 2066 | ||
2067 | switch (info->fix.accel) { | 2067 | switch (info->fix.accel) { |
2068 | case FB_ACCEL_NEOMAGIC_NM2070: | 2068 | case FB_ACCEL_NEOMAGIC_NM2070: |
2069 | sprintf(info->fix.id, "MagicGraph 128"); | 2069 | snprintf(info->fix.id, sizeof(info->fix.id), |
2070 | "MagicGraph 128"); | ||
2070 | break; | 2071 | break; |
2071 | case FB_ACCEL_NEOMAGIC_NM2090: | 2072 | case FB_ACCEL_NEOMAGIC_NM2090: |
2072 | sprintf(info->fix.id, "MagicGraph 128V"); | 2073 | snprintf(info->fix.id, sizeof(info->fix.id), |
2074 | "MagicGraph 128V"); | ||
2073 | break; | 2075 | break; |
2074 | case FB_ACCEL_NEOMAGIC_NM2093: | 2076 | case FB_ACCEL_NEOMAGIC_NM2093: |
2075 | sprintf(info->fix.id, "MagicGraph 128ZV"); | 2077 | snprintf(info->fix.id, sizeof(info->fix.id), |
2078 | "MagicGraph 128ZV"); | ||
2076 | break; | 2079 | break; |
2077 | case FB_ACCEL_NEOMAGIC_NM2097: | 2080 | case FB_ACCEL_NEOMAGIC_NM2097: |
2078 | sprintf(info->fix.id, "MagicGraph 128ZV+"); | 2081 | snprintf(info->fix.id, sizeof(info->fix.id), |
2082 | "MagicGraph 128ZV+"); | ||
2079 | break; | 2083 | break; |
2080 | case FB_ACCEL_NEOMAGIC_NM2160: | 2084 | case FB_ACCEL_NEOMAGIC_NM2160: |
2081 | sprintf(info->fix.id, "MagicGraph 128XD"); | 2085 | snprintf(info->fix.id, sizeof(info->fix.id), |
2086 | "MagicGraph 128XD"); | ||
2082 | break; | 2087 | break; |
2083 | case FB_ACCEL_NEOMAGIC_NM2200: | 2088 | case FB_ACCEL_NEOMAGIC_NM2200: |
2084 | sprintf(info->fix.id, "MagicGraph 256AV"); | 2089 | snprintf(info->fix.id, sizeof(info->fix.id), |
2090 | "MagicGraph 256AV"); | ||
2085 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2091 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2086 | FBINFO_HWACCEL_COPYAREA | | 2092 | FBINFO_HWACCEL_COPYAREA | |
2087 | FBINFO_HWACCEL_FILLRECT; | 2093 | FBINFO_HWACCEL_FILLRECT; |
2088 | break; | 2094 | break; |
2089 | case FB_ACCEL_NEOMAGIC_NM2230: | 2095 | case FB_ACCEL_NEOMAGIC_NM2230: |
2090 | sprintf(info->fix.id, "MagicGraph 256AV+"); | 2096 | snprintf(info->fix.id, sizeof(info->fix.id), |
2097 | "MagicGraph 256AV+"); | ||
2091 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2098 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2092 | FBINFO_HWACCEL_COPYAREA | | 2099 | FBINFO_HWACCEL_COPYAREA | |
2093 | FBINFO_HWACCEL_FILLRECT; | 2100 | FBINFO_HWACCEL_FILLRECT; |
2094 | break; | 2101 | break; |
2095 | case FB_ACCEL_NEOMAGIC_NM2360: | 2102 | case FB_ACCEL_NEOMAGIC_NM2360: |
2096 | sprintf(info->fix.id, "MagicGraph 256ZX"); | 2103 | snprintf(info->fix.id, sizeof(info->fix.id), |
2104 | "MagicGraph 256ZX"); | ||
2097 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2105 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2098 | FBINFO_HWACCEL_COPYAREA | | 2106 | FBINFO_HWACCEL_COPYAREA | |
2099 | FBINFO_HWACCEL_FILLRECT; | 2107 | FBINFO_HWACCEL_FILLRECT; |
2100 | break; | 2108 | break; |
2101 | case FB_ACCEL_NEOMAGIC_NM2380: | 2109 | case FB_ACCEL_NEOMAGIC_NM2380: |
2102 | sprintf(info->fix.id, "MagicGraph 256XL+"); | 2110 | snprintf(info->fix.id, sizeof(info->fix.id), |
2111 | "MagicGraph 256XL+"); | ||
2103 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2112 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2104 | FBINFO_HWACCEL_COPYAREA | | 2113 | FBINFO_HWACCEL_COPYAREA | |
2105 | FBINFO_HWACCEL_FILLRECT; | 2114 | FBINFO_HWACCEL_FILLRECT; |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 30e14eb1f51e..74517b1b26a6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -849,9 +849,27 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var, | |||
849 | if (!mode_valid && info->monspecs.modedb_len) | 849 | if (!mode_valid && info->monspecs.modedb_len) |
850 | return -EINVAL; | 850 | return -EINVAL; |
851 | 851 | ||
852 | /* | ||
853 | * If we're on a flat panel, check if the mode is outside of the | ||
854 | * panel dimensions. If so, cap it and try for the next best mode | ||
855 | * before bailing out. | ||
856 | */ | ||
852 | if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres || | 857 | if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres || |
853 | par->fpHeight < var->yres)) | 858 | par->fpHeight < var->yres)) { |
854 | return -EINVAL; | 859 | const struct fb_videomode *mode; |
860 | |||
861 | var->xres = par->fpWidth; | ||
862 | var->yres = par->fpHeight; | ||
863 | |||
864 | mode = fb_find_best_mode(var, &info->modelist); | ||
865 | if (!mode) { | ||
866 | printk(KERN_ERR PFX "mode out of range of flat " | ||
867 | "panel dimensions\n"); | ||
868 | return -EINVAL; | ||
869 | } | ||
870 | |||
871 | fb_videomode_to_var(var, mode); | ||
872 | } | ||
855 | 873 | ||
856 | if (var->yres_virtual < var->yres) | 874 | if (var->yres_virtual < var->yres) |
857 | var->yres_virtual = var->yres; | 875 | var->yres_virtual = var->yres; |
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 5591dfb22b18..30181b593829 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -1159,6 +1159,11 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1159 | u32 fgx, bgx; | 1159 | u32 fgx, bgx; |
1160 | const u32 *src = (const u32 *)image->data; | 1160 | const u32 *src = (const u32 *)image->data; |
1161 | u32 xres = (info->var.xres + 31) & ~31; | 1161 | u32 xres = (info->var.xres + 31) & ~31; |
1162 | int raster_mode = 1; /* invert bits */ | ||
1163 | |||
1164 | #ifdef __LITTLE_ENDIAN | ||
1165 | raster_mode |= 3 << 7; /* reverse byte order */ | ||
1166 | #endif | ||
1162 | 1167 | ||
1163 | if (info->state != FBINFO_STATE_RUNNING) | 1168 | if (info->state != FBINFO_STATE_RUNNING) |
1164 | return; | 1169 | return; |
@@ -1208,9 +1213,8 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1208 | pm2_WR(par, PM2R_RENDER, | 1213 | pm2_WR(par, PM2R_RENDER, |
1209 | PM2F_RENDER_RECTANGLE | | 1214 | PM2F_RENDER_RECTANGLE | |
1210 | PM2F_INCREASE_X | PM2F_INCREASE_Y); | 1215 | PM2F_INCREASE_X | PM2F_INCREASE_Y); |
1211 | /* BitMapPackEachScanline & invert bits and byte order*/ | 1216 | /* BitMapPackEachScanline */ |
1212 | /* force background */ | 1217 | pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9)); |
1213 | pm2_WR(par, PM2R_RASTERIZER_MODE, (1 << 9) | 1 | (3 << 7)); | ||
1214 | pm2_WR(par, PM2R_CONSTANT_COLOR, fgx); | 1218 | pm2_WR(par, PM2R_CONSTANT_COLOR, fgx); |
1215 | pm2_WR(par, PM2R_RENDER, | 1219 | pm2_WR(par, PM2R_RENDER, |
1216 | PM2F_RENDER_RECTANGLE | | 1220 | PM2F_RENDER_RECTANGLE | |
@@ -1224,8 +1228,7 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1224 | PM2F_RENDER_RECTANGLE | | 1228 | PM2F_RENDER_RECTANGLE | |
1225 | PM2F_RENDER_FASTFILL | | 1229 | PM2F_RENDER_FASTFILL | |
1226 | PM2F_INCREASE_X | PM2F_INCREASE_Y); | 1230 | PM2F_INCREASE_X | PM2F_INCREASE_Y); |
1227 | /* invert bits and byte order*/ | 1231 | pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode); |
1228 | pm2_WR(par, PM2R_RASTERIZER_MODE, 1 | (3 << 7)); | ||
1229 | pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx); | 1232 | pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx); |
1230 | pm2_WR(par, PM2R_RENDER, | 1233 | pm2_WR(par, PM2R_RENDER, |
1231 | PM2F_RENDER_RECTANGLE | | 1234 | PM2F_RENDER_RECTANGLE | |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 070659992c18..5dba8cdd0517 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
@@ -1227,7 +1227,7 @@ static struct fb_ops pm3fb_ops = { | |||
1227 | 1227 | ||
1228 | /* mmio register are already mapped when this function is called */ | 1228 | /* mmio register are already mapped when this function is called */ |
1229 | /* the pm3fb_fix.smem_start is also set */ | 1229 | /* the pm3fb_fix.smem_start is also set */ |
1230 | static unsigned long pm3fb_size_memory(struct pm3_par *par) | 1230 | static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par) |
1231 | { | 1231 | { |
1232 | unsigned long memsize = 0; | 1232 | unsigned long memsize = 0; |
1233 | unsigned long tempBypass, i, temp1, temp2; | 1233 | unsigned long tempBypass, i, temp1, temp2; |
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c index a864438b6008..6515ec11c16b 100644 --- a/drivers/video/pmag-aa-fb.c +++ b/drivers/video/pmag-aa-fb.c | |||
@@ -150,7 +150,7 @@ static int aafbcon_set_font(struct display *disp, int width, int height) | |||
150 | { | 150 | { |
151 | struct aafb_info *info = (struct aafb_info *)disp->fb_info; | 151 | struct aafb_info *info = (struct aafb_info *)disp->fb_info; |
152 | struct aafb_cursor *c = &info->cursor; | 152 | struct aafb_cursor *c = &info->cursor; |
153 | u8 fgc = ~attr_bgcol_ec(disp, disp->conp); | 153 | u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info); |
154 | 154 | ||
155 | if (width > 64 || height > 64 || width < 0 || height < 0) | 155 | if (width > 64 || height > 64 || width < 0 || height < 0) |
156 | return -EINVAL; | 156 | return -EINVAL; |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 044a423a72cb..dc3af1c78c56 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -57,8 +57,6 @@ | |||
57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) | 57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) |
58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) | 58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) |
59 | 59 | ||
60 | #define PS3FB_FULL_MODE_BIT 0x80 | ||
61 | |||
62 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ | 60 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ |
63 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ | 61 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ |
64 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ | 62 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ |
@@ -118,8 +116,6 @@ struct ps3fb_priv { | |||
118 | unsigned int irq_no; | 116 | unsigned int irq_no; |
119 | 117 | ||
120 | u64 context_handle, memory_handle; | 118 | u64 context_handle, memory_handle; |
121 | void *xdr_ea; | ||
122 | size_t xdr_size; | ||
123 | struct gpu_driver_info *dinfo; | 119 | struct gpu_driver_info *dinfo; |
124 | 120 | ||
125 | u64 vblank_count; /* frame count */ | 121 | u64 vblank_count; /* frame count */ |
@@ -136,42 +132,19 @@ static struct ps3fb_priv ps3fb; | |||
136 | struct ps3fb_par { | 132 | struct ps3fb_par { |
137 | u32 pseudo_palette[16]; | 133 | u32 pseudo_palette[16]; |
138 | int mode_id, new_mode_id; | 134 | int mode_id, new_mode_id; |
139 | int res_index; | ||
140 | unsigned int num_frames; /* num of frame buffers */ | 135 | unsigned int num_frames; /* num of frame buffers */ |
141 | unsigned int width; | 136 | unsigned int width; |
142 | unsigned int height; | 137 | unsigned int height; |
143 | unsigned long full_offset; /* start of fullscreen DDR fb */ | 138 | unsigned int ddr_line_length; |
144 | unsigned long fb_offset; /* start of actual DDR fb */ | 139 | unsigned int ddr_frame_size; |
145 | unsigned long pan_offset; | 140 | unsigned int xdr_frame_size; |
141 | unsigned int full_offset; /* start of fullscreen DDR fb */ | ||
142 | unsigned int fb_offset; /* start of actual DDR fb */ | ||
143 | unsigned int pan_offset; | ||
146 | }; | 144 | }; |
147 | 145 | ||
148 | struct ps3fb_res_table { | 146 | |
149 | u32 xres; | 147 | #define FIRST_NATIVE_MODE_INDEX 10 |
150 | u32 yres; | ||
151 | u32 xoff; | ||
152 | u32 yoff; | ||
153 | u32 type; | ||
154 | }; | ||
155 | #define PS3FB_RES_FULL 1 | ||
156 | static const struct ps3fb_res_table ps3fb_res[] = { | ||
157 | /* res_x,y margin_x,y full */ | ||
158 | { 720, 480, 72, 48 , 0}, | ||
159 | { 720, 576, 72, 58 , 0}, | ||
160 | { 1280, 720, 78, 38 , 0}, | ||
161 | { 1920, 1080, 116, 58 , 0}, | ||
162 | /* full mode */ | ||
163 | { 720, 480, 0, 0 , PS3FB_RES_FULL}, | ||
164 | { 720, 576, 0, 0 , PS3FB_RES_FULL}, | ||
165 | { 1280, 720, 0, 0 , PS3FB_RES_FULL}, | ||
166 | { 1920, 1080, 0, 0 , PS3FB_RES_FULL}, | ||
167 | /* vesa: normally full mode */ | ||
168 | { 1280, 768, 0, 0 , 0}, | ||
169 | { 1280, 1024, 0, 0 , 0}, | ||
170 | { 1920, 1200, 0, 0 , 0}, | ||
171 | { 0, 0, 0, 0 , 0} }; | ||
172 | |||
173 | /* default resolution */ | ||
174 | #define GPU_RES_INDEX 0 /* 720 x 480 */ | ||
175 | 148 | ||
176 | static const struct fb_videomode ps3fb_modedb[] = { | 149 | static const struct fb_videomode ps3fb_modedb[] = { |
177 | /* 60 Hz broadcast modes (modes "1" to "5") */ | 150 | /* 60 Hz broadcast modes (modes "1" to "5") */ |
@@ -211,7 +184,7 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
211 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, | 184 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, |
212 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 185 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
213 | }, { | 186 | }, { |
214 | /* 1080 */ | 187 | /* 1080i */ |
215 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, | 188 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, |
216 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 189 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
217 | }, { | 190 | }, { |
@@ -220,24 +193,7 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
220 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 193 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
221 | }, | 194 | }, |
222 | 195 | ||
223 | /* VESA modes (modes "11" to "13") */ | 196 | [FIRST_NATIVE_MODE_INDEX] = |
224 | { | ||
225 | /* WXGA */ | ||
226 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, | ||
227 | 0, FB_VMODE_NONINTERLACED, | ||
228 | FB_MODE_IS_VESA | ||
229 | }, { | ||
230 | /* SXGA */ | ||
231 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||
232 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
233 | FB_MODE_IS_VESA | ||
234 | }, { | ||
235 | /* WUXGA */ | ||
236 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, | ||
237 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
238 | FB_MODE_IS_VESA | ||
239 | }, | ||
240 | |||
241 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ | 197 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ |
242 | { | 198 | { |
243 | /* 480if */ | 199 | /* 480if */ |
@@ -276,12 +232,30 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
276 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 232 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
277 | }, { | 233 | }, { |
278 | /* 1080if */ | 234 | /* 1080if */ |
279 | "1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, | 235 | "1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, |
280 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 236 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
281 | }, { | 237 | }, { |
282 | /* 1080pf */ | 238 | /* 1080pf */ |
283 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, | 239 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, |
284 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 240 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
241 | }, | ||
242 | |||
243 | /* VESA modes (modes "11" to "13") */ | ||
244 | { | ||
245 | /* WXGA */ | ||
246 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, | ||
247 | 0, FB_VMODE_NONINTERLACED, | ||
248 | FB_MODE_IS_VESA | ||
249 | }, { | ||
250 | /* SXGA */ | ||
251 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||
252 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
253 | FB_MODE_IS_VESA | ||
254 | }, { | ||
255 | /* WUXGA */ | ||
256 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, | ||
257 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
258 | FB_MODE_IS_VESA | ||
285 | } | 259 | } |
286 | }; | 260 | }; |
287 | 261 | ||
@@ -289,110 +263,188 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
289 | #define HEAD_A | 263 | #define HEAD_A |
290 | #define HEAD_B | 264 | #define HEAD_B |
291 | 265 | ||
292 | #define X_OFF(i) (ps3fb_res[i].xoff) /* left/right margin (pixel) */ | ||
293 | #define Y_OFF(i) (ps3fb_res[i].yoff) /* top/bottom margin (pixel) */ | ||
294 | #define WIDTH(i) (ps3fb_res[i].xres) /* width of FB */ | ||
295 | #define HEIGHT(i) (ps3fb_res[i].yres) /* height of FB */ | ||
296 | #define BPP 4 /* number of bytes per pixel */ | 266 | #define BPP 4 /* number of bytes per pixel */ |
297 | 267 | ||
298 | /* Start of the virtual frame buffer (relative to fullscreen ) */ | ||
299 | #define VP_OFF(i) ((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP) | ||
300 | |||
301 | 268 | ||
302 | static int ps3fb_mode; | 269 | static int ps3fb_mode; |
303 | module_param(ps3fb_mode, int, 0); | 270 | module_param(ps3fb_mode, int, 0); |
304 | 271 | ||
305 | static char *mode_option __devinitdata; | 272 | static char *mode_option __devinitdata; |
306 | 273 | ||
307 | static int ps3fb_get_res_table(u32 xres, u32 yres, int mode) | 274 | static int ps3fb_cmp_mode(const struct fb_videomode *vmode, |
275 | const struct fb_var_screeninfo *var) | ||
308 | { | 276 | { |
309 | int full_mode; | 277 | long xres, yres, left_margin, right_margin, upper_margin, lower_margin; |
310 | unsigned int i; | 278 | long dx, dy; |
311 | u32 x, y, f; | 279 | |
312 | 280 | /* maximum values */ | |
313 | full_mode = (mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0; | 281 | if (var->xres > vmode->xres || var->yres > vmode->yres || |
314 | for (i = 0;; i++) { | 282 | var->pixclock > vmode->pixclock || |
315 | x = ps3fb_res[i].xres; | 283 | var->hsync_len > vmode->hsync_len || |
316 | y = ps3fb_res[i].yres; | 284 | var->vsync_len > vmode->vsync_len) |
317 | f = ps3fb_res[i].type; | 285 | return -1; |
318 | |||
319 | if (!x) { | ||
320 | pr_debug("ERROR: ps3fb_get_res_table()\n"); | ||
321 | return -1; | ||
322 | } | ||
323 | 286 | ||
324 | if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL) | 287 | /* progressive/interlaced must match */ |
325 | continue; | 288 | if ((var->vmode & FB_VMODE_MASK) != vmode->vmode) |
289 | return -1; | ||
326 | 290 | ||
327 | if (x == xres && (yres == 0 || y == yres)) | 291 | /* minimum resolution */ |
328 | break; | 292 | xres = max(var->xres, 1U); |
293 | yres = max(var->yres, 1U); | ||
294 | |||
295 | /* minimum margins */ | ||
296 | left_margin = max(var->left_margin, vmode->left_margin); | ||
297 | right_margin = max(var->right_margin, vmode->right_margin); | ||
298 | upper_margin = max(var->upper_margin, vmode->upper_margin); | ||
299 | lower_margin = max(var->lower_margin, vmode->lower_margin); | ||
300 | |||
301 | /* resolution + margins may not exceed native parameters */ | ||
302 | dx = ((long)vmode->left_margin + (long)vmode->xres + | ||
303 | (long)vmode->right_margin) - | ||
304 | (left_margin + xres + right_margin); | ||
305 | if (dx < 0) | ||
306 | return -1; | ||
329 | 307 | ||
330 | x = x - 2 * ps3fb_res[i].xoff; | 308 | dy = ((long)vmode->upper_margin + (long)vmode->yres + |
331 | y = y - 2 * ps3fb_res[i].yoff; | 309 | (long)vmode->lower_margin) - |
332 | if (x == xres && (yres == 0 || y == yres)) | 310 | (upper_margin + yres + lower_margin); |
333 | break; | 311 | if (dy < 0) |
312 | return -1; | ||
313 | |||
314 | /* exact match */ | ||
315 | if (!dx && !dy) | ||
316 | return 0; | ||
317 | |||
318 | /* resolution difference */ | ||
319 | return (vmode->xres - xres) * (vmode->yres - yres); | ||
320 | } | ||
321 | |||
322 | static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id) | ||
323 | { | ||
324 | return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1]; | ||
325 | } | ||
326 | |||
327 | static const struct fb_videomode *ps3fb_vmode(int id) | ||
328 | { | ||
329 | u32 mode = id & PS3AV_MODE_MASK; | ||
330 | |||
331 | if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA) | ||
332 | return NULL; | ||
333 | |||
334 | if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) { | ||
335 | /* Non-fullscreen broadcast mode */ | ||
336 | return &ps3fb_modedb[mode - 1]; | ||
334 | } | 337 | } |
335 | return i; | 338 | |
339 | return ps3fb_native_vmode(mode); | ||
336 | } | 340 | } |
337 | 341 | ||
338 | static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var, | 342 | static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, |
339 | u32 *ddr_line_length, u32 *xdr_line_length) | 343 | u32 *ddr_line_length, u32 *xdr_line_length) |
340 | { | 344 | { |
341 | unsigned int i, mode; | 345 | unsigned int id, best_id; |
342 | 346 | int diff, best_diff; | |
343 | for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++) | 347 | const struct fb_videomode *vmode; |
344 | if (var->xres == ps3fb_modedb[i].xres && | 348 | long gap; |
345 | var->yres == ps3fb_modedb[i].yres && | 349 | |
346 | var->pixclock == ps3fb_modedb[i].pixclock && | 350 | best_id = 0; |
347 | var->hsync_len == ps3fb_modedb[i].hsync_len && | 351 | best_diff = INT_MAX; |
348 | var->vsync_len == ps3fb_modedb[i].vsync_len && | 352 | pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__, |
349 | var->left_margin == ps3fb_modedb[i].left_margin && | 353 | var->left_margin, var->xres, var->right_margin, |
350 | var->right_margin == ps3fb_modedb[i].right_margin && | 354 | var->upper_margin, var->yres, var->lower_margin); |
351 | var->upper_margin == ps3fb_modedb[i].upper_margin && | 355 | for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) { |
352 | var->lower_margin == ps3fb_modedb[i].lower_margin && | 356 | vmode = ps3fb_native_vmode(id); |
353 | var->sync == ps3fb_modedb[i].sync && | 357 | diff = ps3fb_cmp_mode(vmode, var); |
354 | (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) | 358 | pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n", |
355 | goto found; | 359 | __func__, id, vmode->left_margin, vmode->xres, |
356 | 360 | vmode->right_margin, vmode->upper_margin, | |
357 | pr_debug("ps3fb_find_mode: mode not found\n"); | 361 | vmode->yres, vmode->lower_margin, diff); |
358 | return 0; | 362 | if (diff < 0) |
363 | continue; | ||
364 | if (diff < best_diff) { | ||
365 | best_id = id; | ||
366 | if (!diff) | ||
367 | break; | ||
368 | best_diff = diff; | ||
369 | } | ||
370 | } | ||
359 | 371 | ||
360 | found: | 372 | if (!best_id) { |
361 | /* Cropped broadcast modes use the full line length */ | 373 | pr_debug("%s: no suitable mode found\n", __func__); |
362 | *ddr_line_length = ps3fb_modedb[i < 10 ? i + 13 : i].xres * BPP; | 374 | return 0; |
375 | } | ||
363 | 376 | ||
364 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { | 377 | id = best_id; |
365 | *xdr_line_length = GPU_ALIGN_UP(max(var->xres, | 378 | vmode = ps3fb_native_vmode(id); |
366 | var->xres_virtual) * BPP); | ||
367 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) | ||
368 | *xdr_line_length = GPU_MAX_LINE_LENGTH; | ||
369 | } else | ||
370 | *xdr_line_length = *ddr_line_length; | ||
371 | 379 | ||
372 | /* Full broadcast modes have the full mode bit set */ | 380 | *ddr_line_length = vmode->xres * BPP; |
373 | mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1; | ||
374 | 381 | ||
375 | pr_debug("ps3fb_find_mode: mode %u\n", mode); | 382 | /* minimum resolution */ |
383 | if (!var->xres) | ||
384 | var->xres = 1; | ||
385 | if (!var->yres) | ||
386 | var->yres = 1; | ||
376 | 387 | ||
377 | return mode; | 388 | /* minimum virtual resolution */ |
378 | } | 389 | if (var->xres_virtual < var->xres) |
390 | var->xres_virtual = var->xres; | ||
391 | if (var->yres_virtual < var->yres) | ||
392 | var->yres_virtual = var->yres; | ||
379 | 393 | ||
380 | static const struct fb_videomode *ps3fb_default_mode(int id) | 394 | /* minimum margins */ |
381 | { | 395 | if (var->left_margin < vmode->left_margin) |
382 | u32 mode = id & PS3AV_MODE_MASK; | 396 | var->left_margin = vmode->left_margin; |
383 | u32 flags; | 397 | if (var->right_margin < vmode->right_margin) |
398 | var->right_margin = vmode->right_margin; | ||
399 | if (var->upper_margin < vmode->upper_margin) | ||
400 | var->upper_margin = vmode->upper_margin; | ||
401 | if (var->lower_margin < vmode->lower_margin) | ||
402 | var->lower_margin = vmode->lower_margin; | ||
403 | |||
404 | /* extra margins */ | ||
405 | gap = ((long)vmode->left_margin + (long)vmode->xres + | ||
406 | (long)vmode->right_margin) - | ||
407 | ((long)var->left_margin + (long)var->xres + | ||
408 | (long)var->right_margin); | ||
409 | if (gap > 0) { | ||
410 | var->left_margin += gap/2; | ||
411 | var->right_margin += (gap+1)/2; | ||
412 | pr_debug("%s: rounded up H to %u [%u] %u\n", __func__, | ||
413 | var->left_margin, var->xres, var->right_margin); | ||
414 | } | ||
384 | 415 | ||
385 | if (mode < 1 || mode > 13) | 416 | gap = ((long)vmode->upper_margin + (long)vmode->yres + |
386 | return NULL; | 417 | (long)vmode->lower_margin) - |
418 | ((long)var->upper_margin + (long)var->yres + | ||
419 | (long)var->lower_margin); | ||
420 | if (gap > 0) { | ||
421 | var->upper_margin += gap/2; | ||
422 | var->lower_margin += (gap+1)/2; | ||
423 | pr_debug("%s: rounded up V to %u [%u] %u\n", __func__, | ||
424 | var->upper_margin, var->yres, var->lower_margin); | ||
425 | } | ||
426 | |||
427 | /* fixed fields */ | ||
428 | var->pixclock = vmode->pixclock; | ||
429 | var->hsync_len = vmode->hsync_len; | ||
430 | var->vsync_len = vmode->vsync_len; | ||
431 | var->sync = vmode->sync; | ||
387 | 432 | ||
388 | flags = id & ~PS3AV_MODE_MASK; | 433 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { |
434 | *xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP); | ||
435 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) | ||
436 | *xdr_line_length = GPU_MAX_LINE_LENGTH; | ||
437 | } else | ||
438 | *xdr_line_length = *ddr_line_length; | ||
389 | 439 | ||
390 | if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) { | 440 | if (vmode->sync & FB_SYNC_BROADCAST) { |
391 | /* Full broadcast mode */ | 441 | /* Full broadcast modes have the full mode bit set */ |
392 | return &ps3fb_modedb[mode + 12]; | 442 | if (vmode->xres == var->xres && vmode->yres == var->yres) |
443 | id |= PS3AV_MODE_FULL; | ||
393 | } | 444 | } |
394 | 445 | ||
395 | return &ps3fb_modedb[mode - 1]; | 446 | pr_debug("%s: mode %u\n", __func__, id); |
447 | return id; | ||
396 | } | 448 | } |
397 | 449 | ||
398 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | 450 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, |
@@ -439,8 +491,7 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | |||
439 | static int ps3fb_sync(struct fb_info *info, u32 frame) | 491 | static int ps3fb_sync(struct fb_info *info, u32 frame) |
440 | { | 492 | { |
441 | struct ps3fb_par *par = info->par; | 493 | struct ps3fb_par *par = info->par; |
442 | int i, error = 0; | 494 | int error = 0; |
443 | u32 ddr_line_length, xdr_line_length; | ||
444 | u64 ddr_base, xdr_base; | 495 | u64 ddr_base, xdr_base; |
445 | 496 | ||
446 | if (frame > par->num_frames - 1) { | 497 | if (frame > par->num_frames - 1) { |
@@ -450,16 +501,13 @@ static int ps3fb_sync(struct fb_info *info, u32 frame) | |||
450 | goto out; | 501 | goto out; |
451 | } | 502 | } |
452 | 503 | ||
453 | i = par->res_index; | 504 | xdr_base = frame * par->xdr_frame_size; |
454 | xdr_line_length = info->fix.line_length; | 505 | ddr_base = frame * par->ddr_frame_size; |
455 | ddr_line_length = ps3fb_res[i].xres * BPP; | ||
456 | xdr_base = frame * info->var.yres_virtual * xdr_line_length; | ||
457 | ddr_base = frame * ps3fb_res[i].yres * ddr_line_length; | ||
458 | 506 | ||
459 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, | 507 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, |
460 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, | 508 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, |
461 | par->width, par->height, ddr_line_length, | 509 | par->width, par->height, par->ddr_line_length, |
462 | xdr_line_length); | 510 | info->fix.line_length); |
463 | 511 | ||
464 | out: | 512 | out: |
465 | return error; | 513 | return error; |
@@ -498,22 +546,11 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
498 | u32 xdr_line_length, ddr_line_length; | 546 | u32 xdr_line_length, ddr_line_length; |
499 | int mode; | 547 | int mode; |
500 | 548 | ||
501 | dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres, | ||
502 | info->var.xres); | ||
503 | dev_dbg(info->device, "var->yres:%u info->var.yres:%u\n", var->yres, | ||
504 | info->var.yres); | ||
505 | |||
506 | /* FIXME For now we do exact matches only */ | ||
507 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); | 549 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); |
508 | if (!mode) | 550 | if (!mode) |
509 | return -EINVAL; | 551 | return -EINVAL; |
510 | 552 | ||
511 | /* Virtual screen */ | 553 | /* Virtual screen */ |
512 | if (var->xres_virtual < var->xres) | ||
513 | var->xres_virtual = var->xres; | ||
514 | if (var->yres_virtual < var->yres) | ||
515 | var->yres_virtual = var->yres; | ||
516 | |||
517 | if (var->xres_virtual > xdr_line_length / BPP) { | 554 | if (var->xres_virtual > xdr_line_length / BPP) { |
518 | dev_dbg(info->device, | 555 | dev_dbg(info->device, |
519 | "Horizontal virtual screen size too large\n"); | 556 | "Horizontal virtual screen size too large\n"); |
@@ -559,7 +596,7 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
559 | } | 596 | } |
560 | 597 | ||
561 | /* Memory limit */ | 598 | /* Memory limit */ |
562 | if (var->yres_virtual * xdr_line_length > ps3fb.xdr_size) { | 599 | if (var->yres_virtual * xdr_line_length > info->fix.smem_len) { |
563 | dev_dbg(info->device, "Not enough memory\n"); | 600 | dev_dbg(info->device, "Not enough memory\n"); |
564 | return -ENOMEM; | 601 | return -ENOMEM; |
565 | } | 602 | } |
@@ -578,39 +615,38 @@ static int ps3fb_set_par(struct fb_info *info) | |||
578 | { | 615 | { |
579 | struct ps3fb_par *par = info->par; | 616 | struct ps3fb_par *par = info->par; |
580 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; | 617 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; |
581 | int i; | 618 | unsigned int ddr_xoff, ddr_yoff, offset; |
582 | unsigned long offset; | 619 | const struct fb_videomode *vmode; |
583 | u64 dst; | 620 | u64 dst; |
584 | 621 | ||
585 | dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n", | ||
586 | info->var.xres, info->var.xres_virtual, | ||
587 | info->var.yres, info->var.yres_virtual, info->var.pixclock); | ||
588 | |||
589 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); | 622 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); |
590 | if (!mode) | 623 | if (!mode) |
591 | return -EINVAL; | 624 | return -EINVAL; |
592 | 625 | ||
593 | i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode); | 626 | vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK); |
594 | par->res_index = i; | ||
595 | 627 | ||
596 | info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); | ||
597 | info->fix.smem_len = ps3fb.xdr_size; | ||
598 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; | 628 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; |
599 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; | 629 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; |
600 | info->fix.line_length = xdr_line_length; | 630 | info->fix.line_length = xdr_line_length; |
601 | 631 | ||
602 | info->screen_base = (char __iomem *)ps3fb.xdr_ea; | 632 | par->ddr_line_length = ddr_line_length; |
633 | par->ddr_frame_size = vmode->yres * ddr_line_length; | ||
634 | par->xdr_frame_size = info->var.yres_virtual * xdr_line_length; | ||
603 | 635 | ||
604 | par->num_frames = ps3fb.xdr_size / | 636 | par->num_frames = info->fix.smem_len / |
605 | max(ps3fb_res[i].yres * ddr_line_length, | 637 | max(par->ddr_frame_size, par->xdr_frame_size); |
606 | info->var.yres_virtual * xdr_line_length); | ||
607 | 638 | ||
608 | /* Keep the special bits we cannot set using fb_var_screeninfo */ | 639 | /* Keep the special bits we cannot set using fb_var_screeninfo */ |
609 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; | 640 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; |
610 | 641 | ||
611 | par->width = info->var.xres; | 642 | par->width = info->var.xres; |
612 | par->height = info->var.yres; | 643 | par->height = info->var.yres; |
613 | offset = VP_OFF(i); | 644 | |
645 | /* Start of the virtual frame buffer (relative to fullscreen) */ | ||
646 | ddr_xoff = info->var.left_margin - vmode->left_margin; | ||
647 | ddr_yoff = info->var.upper_margin - vmode->upper_margin; | ||
648 | offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP; | ||
649 | |||
614 | par->fb_offset = GPU_ALIGN_UP(offset); | 650 | par->fb_offset = GPU_ALIGN_UP(offset); |
615 | par->full_offset = par->fb_offset - offset; | 651 | par->full_offset = par->fb_offset - offset; |
616 | par->pan_offset = info->var.yoffset * xdr_line_length + | 652 | par->pan_offset = info->var.yoffset * xdr_line_length + |
@@ -625,16 +661,16 @@ static int ps3fb_set_par(struct fb_info *info) | |||
625 | } | 661 | } |
626 | 662 | ||
627 | /* Clear XDR frame buffer memory */ | 663 | /* Clear XDR frame buffer memory */ |
628 | memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size); | 664 | memset((void __force *)info->screen_base, 0, info->fix.smem_len); |
629 | 665 | ||
630 | /* Clear DDR frame buffer memory */ | 666 | /* Clear DDR frame buffer memory */ |
631 | lines = ps3fb_res[i].yres * par->num_frames; | 667 | lines = vmode->yres * par->num_frames; |
632 | if (par->full_offset) | 668 | if (par->full_offset) |
633 | lines++; | 669 | lines++; |
634 | maxlines = ps3fb.xdr_size / ddr_line_length; | 670 | maxlines = info->fix.smem_len / ddr_line_length; |
635 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { | 671 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { |
636 | unsigned int l = min(lines, maxlines); | 672 | unsigned int l = min(lines, maxlines); |
637 | ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l, | 673 | ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l, |
638 | ddr_line_length, ddr_line_length); | 674 | ddr_line_length, ddr_line_length); |
639 | lines -= l; | 675 | lines -= l; |
640 | } | 676 | } |
@@ -797,7 +833,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
797 | case PS3FB_IOCTL_SETMODE: | 833 | case PS3FB_IOCTL_SETMODE: |
798 | { | 834 | { |
799 | struct ps3fb_par *par = info->par; | 835 | struct ps3fb_par *par = info->par; |
800 | const struct fb_videomode *mode; | 836 | const struct fb_videomode *vmode; |
801 | struct fb_var_screeninfo var; | 837 | struct fb_var_screeninfo var; |
802 | 838 | ||
803 | if (copy_from_user(&val, argp, sizeof(val))) | 839 | if (copy_from_user(&val, argp, sizeof(val))) |
@@ -810,10 +846,10 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
810 | } | 846 | } |
811 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); | 847 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); |
812 | retval = -EINVAL; | 848 | retval = -EINVAL; |
813 | mode = ps3fb_default_mode(val); | 849 | vmode = ps3fb_vmode(val); |
814 | if (mode) { | 850 | if (vmode) { |
815 | var = info->var; | 851 | var = info->var; |
816 | fb_videomode_to_var(&var, mode); | 852 | fb_videomode_to_var(&var, vmode); |
817 | acquire_console_sem(); | 853 | acquire_console_sem(); |
818 | info->flags |= FBINFO_MISC_USEREVENT; | 854 | info->flags |= FBINFO_MISC_USEREVENT; |
819 | /* Force, in case only special bits changed */ | 855 | /* Force, in case only special bits changed */ |
@@ -975,10 +1011,9 @@ static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev) | |||
975 | __func__, status); | 1011 | __func__, status); |
976 | return -ENXIO; | 1012 | return -ENXIO; |
977 | } | 1013 | } |
978 | dev_dbg(dev, | 1014 | dev_dbg(dev, "video:%p ioif:%lx lpar:%lx size:%lx\n", |
979 | "video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n", | 1015 | ps3fb_videomemory.address, GPU_IOIF, xdr_lpar, |
980 | ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar, | 1016 | ps3fb_videomemory.size); |
981 | virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size); | ||
982 | 1017 | ||
983 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 1018 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
984 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, | 1019 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, |
@@ -1055,14 +1090,14 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1055 | struct fb_info *info; | 1090 | struct fb_info *info; |
1056 | struct ps3fb_par *par; | 1091 | struct ps3fb_par *par; |
1057 | int retval = -ENOMEM; | 1092 | int retval = -ENOMEM; |
1058 | u32 xres, yres; | ||
1059 | u64 ddr_lpar = 0; | 1093 | u64 ddr_lpar = 0; |
1060 | u64 lpar_dma_control = 0; | 1094 | u64 lpar_dma_control = 0; |
1061 | u64 lpar_driver_info = 0; | 1095 | u64 lpar_driver_info = 0; |
1062 | u64 lpar_reports = 0; | 1096 | u64 lpar_reports = 0; |
1063 | u64 lpar_reports_size = 0; | 1097 | u64 lpar_reports_size = 0; |
1064 | u64 xdr_lpar; | 1098 | u64 xdr_lpar; |
1065 | int status, res_index; | 1099 | void *fb_start; |
1100 | int status; | ||
1066 | struct task_struct *task; | 1101 | struct task_struct *task; |
1067 | unsigned long max_ps3fb_size; | 1102 | unsigned long max_ps3fb_size; |
1068 | 1103 | ||
@@ -1080,14 +1115,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1080 | 1115 | ||
1081 | if (!ps3fb_mode) | 1116 | if (!ps3fb_mode) |
1082 | ps3fb_mode = ps3av_get_mode(); | 1117 | ps3fb_mode = ps3av_get_mode(); |
1083 | dev_dbg(&dev->core, "ps3av_mode:%d\n", ps3fb_mode); | 1118 | dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode); |
1084 | |||
1085 | if (ps3fb_mode > 0 && | ||
1086 | !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) { | ||
1087 | res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode); | ||
1088 | dev_dbg(&dev->core, "res_index:%d\n", res_index); | ||
1089 | } else | ||
1090 | res_index = GPU_RES_INDEX; | ||
1091 | 1119 | ||
1092 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ | 1120 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ |
1093 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | 1121 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ |
@@ -1124,7 +1152,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1124 | } | 1152 | } |
1125 | 1153 | ||
1126 | /* vsync interrupt */ | 1154 | /* vsync interrupt */ |
1127 | ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024); | 1155 | ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); |
1128 | if (!ps3fb.dinfo) { | 1156 | if (!ps3fb.dinfo) { |
1129 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); | 1157 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); |
1130 | goto err_gpu_context_free; | 1158 | goto err_gpu_context_free; |
@@ -1134,22 +1162,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1134 | if (retval) | 1162 | if (retval) |
1135 | goto err_iounmap_dinfo; | 1163 | goto err_iounmap_dinfo; |
1136 | 1164 | ||
1137 | /* XDR frame buffer */ | ||
1138 | ps3fb.xdr_ea = ps3fb_videomemory.address; | ||
1139 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea)); | ||
1140 | |||
1141 | /* Clear memory to prevent kernel info leakage into userspace */ | 1165 | /* Clear memory to prevent kernel info leakage into userspace */ |
1142 | memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size); | 1166 | memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); |
1143 | |||
1144 | /* | ||
1145 | * The GPU command buffer is at the start of video memory | ||
1146 | * As we don't use the full command buffer, we can put the actual | ||
1147 | * frame buffer at offset GPU_FB_START and save some precious XDR | ||
1148 | * memory | ||
1149 | */ | ||
1150 | ps3fb.xdr_ea += GPU_FB_START; | ||
1151 | ps3fb.xdr_size = ps3fb_videomemory.size - GPU_FB_START; | ||
1152 | 1167 | ||
1168 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); | ||
1153 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); | 1169 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); |
1154 | if (retval) | 1170 | if (retval) |
1155 | goto err_free_irq; | 1171 | goto err_free_irq; |
@@ -1161,15 +1177,22 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1161 | par = info->par; | 1177 | par = info->par; |
1162 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ | 1178 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ |
1163 | par->new_mode_id = ps3fb_mode; | 1179 | par->new_mode_id = ps3fb_mode; |
1164 | par->res_index = res_index; | ||
1165 | par->num_frames = 1; | 1180 | par->num_frames = 1; |
1166 | 1181 | ||
1167 | info->screen_base = (char __iomem *)ps3fb.xdr_ea; | ||
1168 | info->fbops = &ps3fb_ops; | 1182 | info->fbops = &ps3fb_ops; |
1169 | |||
1170 | info->fix = ps3fb_fix; | 1183 | info->fix = ps3fb_fix; |
1171 | info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); | 1184 | |
1172 | info->fix.smem_len = ps3fb.xdr_size; | 1185 | /* |
1186 | * The GPU command buffer is at the start of video memory | ||
1187 | * As we don't use the full command buffer, we can put the actual | ||
1188 | * frame buffer at offset GPU_FB_START and save some precious XDR | ||
1189 | * memory | ||
1190 | */ | ||
1191 | fb_start = ps3fb_videomemory.address + GPU_FB_START; | ||
1192 | info->screen_base = (char __force __iomem *)fb_start; | ||
1193 | info->fix.smem_start = virt_to_abs(fb_start); | ||
1194 | info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START; | ||
1195 | |||
1173 | info->pseudo_palette = par->pseudo_palette; | 1196 | info->pseudo_palette = par->pseudo_palette; |
1174 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | 1197 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | |
1175 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | 1198 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; |
@@ -1180,7 +1203,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1180 | 1203 | ||
1181 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, | 1204 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, |
1182 | ARRAY_SIZE(ps3fb_modedb), | 1205 | ARRAY_SIZE(ps3fb_modedb), |
1183 | ps3fb_default_mode(par->new_mode_id), 32)) { | 1206 | ps3fb_vmode(par->new_mode_id), 32)) { |
1184 | retval = -EINVAL; | 1207 | retval = -EINVAL; |
1185 | goto err_fb_dealloc; | 1208 | goto err_fb_dealloc; |
1186 | } | 1209 | } |
@@ -1194,9 +1217,9 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1194 | 1217 | ||
1195 | dev->core.driver_data = info; | 1218 | dev->core.driver_data = info; |
1196 | 1219 | ||
1197 | dev_info(info->device, "%s %s, using %lu KiB of video memory\n", | 1220 | dev_info(info->device, "%s %s, using %u KiB of video memory\n", |
1198 | dev_driver_string(info->dev), info->dev->bus_id, | 1221 | dev_driver_string(info->dev), info->dev->bus_id, |
1199 | ps3fb.xdr_size >> 10); | 1222 | info->fix.smem_len >> 10); |
1200 | 1223 | ||
1201 | task = kthread_run(ps3fbd, info, DEVICE_NAME); | 1224 | task = kthread_run(ps3fbd, info, DEVICE_NAME); |
1202 | if (IS_ERR(task)) { | 1225 | if (IS_ERR(task)) { |
@@ -1219,7 +1242,7 @@ err_free_irq: | |||
1219 | free_irq(ps3fb.irq_no, &dev->core); | 1242 | free_irq(ps3fb.irq_no, &dev->core); |
1220 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1243 | ps3_irq_plug_destroy(ps3fb.irq_no); |
1221 | err_iounmap_dinfo: | 1244 | err_iounmap_dinfo: |
1222 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1245 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1223 | err_gpu_context_free: | 1246 | err_gpu_context_free: |
1224 | lv1_gpu_context_free(ps3fb.context_handle); | 1247 | lv1_gpu_context_free(ps3fb.context_handle); |
1225 | err_gpu_memory_free: | 1248 | err_gpu_memory_free: |
@@ -1254,7 +1277,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | |||
1254 | framebuffer_release(info); | 1277 | framebuffer_release(info); |
1255 | info = dev->core.driver_data = NULL; | 1278 | info = dev->core.driver_data = NULL; |
1256 | } | 1279 | } |
1257 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1280 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1258 | 1281 | ||
1259 | status = lv1_gpu_context_free(ps3fb.context_handle); | 1282 | status = lv1_gpu_context_free(ps3fb.context_handle); |
1260 | if (status) | 1283 | if (status) |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index b3c31d9dc591..71fa6edb5c47 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -110,6 +110,11 @@ static int debug = 0; | |||
110 | 110 | ||
111 | /* useful functions */ | 111 | /* useful functions */ |
112 | 112 | ||
113 | static int is_s3c2412(struct s3c2410fb_info *fbi) | ||
114 | { | ||
115 | return (fbi->drv_type == DRV_S3C2412); | ||
116 | } | ||
117 | |||
113 | /* s3c2410fb_set_lcdaddr | 118 | /* s3c2410fb_set_lcdaddr |
114 | * | 119 | * |
115 | * initialise lcd controller address pointers | 120 | * initialise lcd controller address pointers |
@@ -501,7 +506,7 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
501 | { | 506 | { |
502 | unsigned long flags; | 507 | unsigned long flags; |
503 | unsigned long irqen; | 508 | unsigned long irqen; |
504 | void __iomem *regs = fbi->io; | 509 | void __iomem *irq_base = fbi->irq_base; |
505 | 510 | ||
506 | local_irq_save(flags); | 511 | local_irq_save(flags); |
507 | 512 | ||
@@ -511,9 +516,9 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
511 | fbi->palette_ready = 1; | 516 | fbi->palette_ready = 1; |
512 | 517 | ||
513 | /* enable IRQ */ | 518 | /* enable IRQ */ |
514 | irqen = readl(regs + S3C2410_LCDINTMSK); | 519 | irqen = readl(irq_base + S3C24XX_LCDINTMSK); |
515 | irqen &= ~S3C2410_LCDINT_FRSYNC; | 520 | irqen &= ~S3C2410_LCDINT_FRSYNC; |
516 | writel(irqen, regs + S3C2410_LCDINTMSK); | 521 | writel(irqen, irq_base + S3C24XX_LCDINTMSK); |
517 | } | 522 | } |
518 | 523 | ||
519 | local_irq_restore(flags); | 524 | local_irq_restore(flags); |
@@ -594,15 +599,17 @@ static int s3c2410fb_setcolreg(unsigned regno, | |||
594 | static int s3c2410fb_blank(int blank_mode, struct fb_info *info) | 599 | static int s3c2410fb_blank(int blank_mode, struct fb_info *info) |
595 | { | 600 | { |
596 | struct s3c2410fb_info *fbi = info->par; | 601 | struct s3c2410fb_info *fbi = info->par; |
597 | void __iomem *regs = fbi->io; | 602 | void __iomem *tpal_reg = fbi->io; |
598 | 603 | ||
599 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); | 604 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); |
600 | 605 | ||
606 | tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL; | ||
607 | |||
601 | if (blank_mode == FB_BLANK_UNBLANK) | 608 | if (blank_mode == FB_BLANK_UNBLANK) |
602 | writel(0x0, regs + S3C2410_TPAL); | 609 | writel(0x0, tpal_reg); |
603 | else { | 610 | else { |
604 | dprintk("setting TPAL to output 0x000000\n"); | 611 | dprintk("setting TPAL to output 0x000000\n"); |
605 | writel(S3C2410_TPAL_EN, regs + S3C2410_TPAL); | 612 | writel(S3C2410_TPAL_EN, tpal_reg); |
606 | } | 613 | } |
607 | 614 | ||
608 | return 0; | 615 | return 0; |
@@ -663,7 +670,7 @@ static int __init s3c2410fb_map_video_memory(struct fb_info *info) | |||
663 | dma_addr_t map_dma; | 670 | dma_addr_t map_dma; |
664 | unsigned map_size = PAGE_ALIGN(info->fix.smem_len); | 671 | unsigned map_size = PAGE_ALIGN(info->fix.smem_len); |
665 | 672 | ||
666 | dprintk("map_video_memory(fbi=%p)\n", fbi); | 673 | dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size); |
667 | 674 | ||
668 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, | 675 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, |
669 | &map_dma, GFP_KERNEL); | 676 | &map_dma, GFP_KERNEL); |
@@ -672,7 +679,7 @@ static int __init s3c2410fb_map_video_memory(struct fb_info *info) | |||
672 | /* prevent initial garbage on screen */ | 679 | /* prevent initial garbage on screen */ |
673 | dprintk("map_video_memory: clear %p:%08x\n", | 680 | dprintk("map_video_memory: clear %p:%08x\n", |
674 | info->screen_base, map_size); | 681 | info->screen_base, map_size); |
675 | memset(info->screen_base, 0xf0, map_size); | 682 | memset(info->screen_base, 0x00, map_size); |
676 | 683 | ||
677 | info->fix.smem_start = map_dma; | 684 | info->fix.smem_start = map_dma; |
678 | 685 | ||
@@ -709,6 +716,16 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
709 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; | 716 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; |
710 | unsigned long flags; | 717 | unsigned long flags; |
711 | void __iomem *regs = fbi->io; | 718 | void __iomem *regs = fbi->io; |
719 | void __iomem *tpal; | ||
720 | void __iomem *lpcsel; | ||
721 | |||
722 | if (is_s3c2412(fbi)) { | ||
723 | tpal = regs + S3C2412_TPAL; | ||
724 | lpcsel = regs + S3C2412_TCONSEL; | ||
725 | } else { | ||
726 | tpal = regs + S3C2410_TPAL; | ||
727 | lpcsel = regs + S3C2410_LPCSEL; | ||
728 | } | ||
712 | 729 | ||
713 | /* Initialise LCD with values from haret */ | 730 | /* Initialise LCD with values from haret */ |
714 | 731 | ||
@@ -724,12 +741,12 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
724 | local_irq_restore(flags); | 741 | local_irq_restore(flags); |
725 | 742 | ||
726 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); | 743 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); |
727 | writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); | 744 | writel(mach_info->lpcsel, lpcsel); |
728 | 745 | ||
729 | dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL)); | 746 | dprintk("replacing TPAL %08x\n", readl(tpal)); |
730 | 747 | ||
731 | /* ensure temporary palette disabled */ | 748 | /* ensure temporary palette disabled */ |
732 | writel(0x00, regs + S3C2410_TPAL); | 749 | writel(0x00, tpal); |
733 | 750 | ||
734 | return 0; | 751 | return 0; |
735 | } | 752 | } |
@@ -763,15 +780,15 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) | |||
763 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | 780 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) |
764 | { | 781 | { |
765 | struct s3c2410fb_info *fbi = dev_id; | 782 | struct s3c2410fb_info *fbi = dev_id; |
766 | void __iomem *regs = fbi->io; | 783 | void __iomem *irq_base = fbi->irq_base; |
767 | unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND); | 784 | unsigned long lcdirq = readl(irq_base + S3C24XX_LCDINTPND); |
768 | 785 | ||
769 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { | 786 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { |
770 | if (fbi->palette_ready) | 787 | if (fbi->palette_ready) |
771 | s3c2410fb_write_palette(fbi); | 788 | s3c2410fb_write_palette(fbi); |
772 | 789 | ||
773 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND); | 790 | writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND); |
774 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND); | 791 | writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND); |
775 | } | 792 | } |
776 | 793 | ||
777 | return IRQ_HANDLED; | 794 | return IRQ_HANDLED; |
@@ -779,7 +796,8 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | |||
779 | 796 | ||
780 | static char driver_name[] = "s3c2410fb"; | 797 | static char driver_name[] = "s3c2410fb"; |
781 | 798 | ||
782 | static int __init s3c2410fb_probe(struct platform_device *pdev) | 799 | static int __init s3c24xxfb_probe(struct platform_device *pdev, |
800 | enum s3c_drv_type drv_type) | ||
783 | { | 801 | { |
784 | struct s3c2410fb_info *info; | 802 | struct s3c2410fb_info *info; |
785 | struct s3c2410fb_display *display; | 803 | struct s3c2410fb_display *display; |
@@ -799,6 +817,12 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
799 | return -EINVAL; | 817 | return -EINVAL; |
800 | } | 818 | } |
801 | 819 | ||
820 | if (mach_info->default_display >= mach_info->num_displays) { | ||
821 | dev_err(&pdev->dev, "default is %d but only %d displays\n", | ||
822 | mach_info->default_display, mach_info->num_displays); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | |||
802 | display = mach_info->displays + mach_info->default_display; | 826 | display = mach_info->displays + mach_info->default_display; |
803 | 827 | ||
804 | irq = platform_get_irq(pdev, 0); | 828 | irq = platform_get_irq(pdev, 0); |
@@ -815,6 +839,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
815 | 839 | ||
816 | info = fbinfo->par; | 840 | info = fbinfo->par; |
817 | info->dev = &pdev->dev; | 841 | info->dev = &pdev->dev; |
842 | info->drv_type = drv_type; | ||
818 | 843 | ||
819 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 844 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
820 | if (res == NULL) { | 845 | if (res == NULL) { |
@@ -838,6 +863,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
838 | goto release_mem; | 863 | goto release_mem; |
839 | } | 864 | } |
840 | 865 | ||
866 | info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE); | ||
867 | |||
841 | dprintk("devinit\n"); | 868 | dprintk("devinit\n"); |
842 | 869 | ||
843 | strcpy(fbinfo->fix.id, driver_name); | 870 | strcpy(fbinfo->fix.id, driver_name); |
@@ -946,6 +973,16 @@ dealloc_fb: | |||
946 | return ret; | 973 | return ret; |
947 | } | 974 | } |
948 | 975 | ||
976 | static int __init s3c2410fb_probe(struct platform_device *pdev) | ||
977 | { | ||
978 | return s3c24xxfb_probe(pdev, DRV_S3C2410); | ||
979 | } | ||
980 | |||
981 | static int __init s3c2412fb_probe(struct platform_device *pdev) | ||
982 | { | ||
983 | return s3c24xxfb_probe(pdev, DRV_S3C2412); | ||
984 | } | ||
985 | |||
949 | /* s3c2410fb_stop_lcd | 986 | /* s3c2410fb_stop_lcd |
950 | * | 987 | * |
951 | * shutdown the lcd controller | 988 | * shutdown the lcd controller |
@@ -1047,14 +1084,31 @@ static struct platform_driver s3c2410fb_driver = { | |||
1047 | }, | 1084 | }, |
1048 | }; | 1085 | }; |
1049 | 1086 | ||
1087 | static struct platform_driver s3c2412fb_driver = { | ||
1088 | .probe = s3c2412fb_probe, | ||
1089 | .remove = s3c2410fb_remove, | ||
1090 | .suspend = s3c2410fb_suspend, | ||
1091 | .resume = s3c2410fb_resume, | ||
1092 | .driver = { | ||
1093 | .name = "s3c2412-lcd", | ||
1094 | .owner = THIS_MODULE, | ||
1095 | }, | ||
1096 | }; | ||
1097 | |||
1050 | int __init s3c2410fb_init(void) | 1098 | int __init s3c2410fb_init(void) |
1051 | { | 1099 | { |
1052 | return platform_driver_register(&s3c2410fb_driver); | 1100 | int ret = platform_driver_register(&s3c2410fb_driver); |
1101 | |||
1102 | if (ret == 0) | ||
1103 | ret = platform_driver_register(&s3c2412fb_driver);; | ||
1104 | |||
1105 | return ret; | ||
1053 | } | 1106 | } |
1054 | 1107 | ||
1055 | static void __exit s3c2410fb_cleanup(void) | 1108 | static void __exit s3c2410fb_cleanup(void) |
1056 | { | 1109 | { |
1057 | platform_driver_unregister(&s3c2410fb_driver); | 1110 | platform_driver_unregister(&s3c2410fb_driver); |
1111 | platform_driver_unregister(&s3c2412fb_driver); | ||
1058 | } | 1112 | } |
1059 | 1113 | ||
1060 | module_init(s3c2410fb_init); | 1114 | module_init(s3c2410fb_init); |
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index 6ce5dc26c5f7..dbb73b95e2ef 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h | |||
@@ -25,13 +25,20 @@ | |||
25 | #ifndef __S3C2410FB_H | 25 | #ifndef __S3C2410FB_H |
26 | #define __S3C2410FB_H | 26 | #define __S3C2410FB_H |
27 | 27 | ||
28 | enum s3c_drv_type { | ||
29 | DRV_S3C2410, | ||
30 | DRV_S3C2412, | ||
31 | }; | ||
32 | |||
28 | struct s3c2410fb_info { | 33 | struct s3c2410fb_info { |
29 | struct device *dev; | 34 | struct device *dev; |
30 | struct clk *clk; | 35 | struct clk *clk; |
31 | 36 | ||
32 | struct resource *mem; | 37 | struct resource *mem; |
33 | void __iomem *io; | 38 | void __iomem *io; |
39 | void __iomem *irq_base; | ||
34 | 40 | ||
41 | enum s3c_drv_type drv_type; | ||
35 | struct s3c2410fb_hw regs; | 42 | struct s3c2410fb_hw regs; |
36 | 43 | ||
37 | unsigned int palette_ready; | 44 | unsigned int palette_ready; |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 93ae747440cb..73803624c131 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -427,7 +427,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) | |||
427 | 427 | ||
428 | monitor->feature = buffer[0x18]; | 428 | monitor->feature = buffer[0x18]; |
429 | 429 | ||
430 | if(!buffer[0x14] & 0x80) { | 430 | if(!(buffer[0x14] & 0x80)) { |
431 | if(!(buffer[0x14] & 0x08)) { | 431 | if(!(buffer[0x14] & 0x08)) { |
432 | printk(KERN_INFO | 432 | printk(KERN_INFO |
433 | "sisfb: WARNING: Monitor does not support separate syncs\n"); | 433 | "sisfb: WARNING: Monitor does not support separate syncs\n"); |
@@ -4621,9 +4621,9 @@ sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev, | |||
4621 | 4621 | ||
4622 | while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { | 4622 | while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { |
4623 | temp = pdev->vendor; | 4623 | temp = pdev->vendor; |
4624 | pci_dev_put(pdev); | ||
4625 | if(temp == pcivendor) { | 4624 | if(temp == pcivendor) { |
4626 | ret = 1; | 4625 | ret = 1; |
4626 | pci_dev_put(pdev); | ||
4627 | break; | 4627 | break; |
4628 | } | 4628 | } |
4629 | } | 4629 | } |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 58f200c69be3..e83dfba7e636 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -641,6 +641,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
641 | { | 641 | { |
642 | unsigned long control; | 642 | unsigned long control; |
643 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; | 643 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; |
644 | struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; | ||
644 | 645 | ||
645 | control = readl(ctrl_reg); | 646 | control = readl(ctrl_reg); |
646 | 647 | ||
@@ -657,26 +658,34 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
657 | sm501fb_sync_regs(fbi); | 658 | sm501fb_sync_regs(fbi); |
658 | mdelay(10); | 659 | mdelay(10); |
659 | 660 | ||
660 | control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ | 661 | if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { |
661 | writel(control, ctrl_reg); | 662 | control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ |
662 | sm501fb_sync_regs(fbi); | 663 | writel(control, ctrl_reg); |
663 | mdelay(10); | 664 | sm501fb_sync_regs(fbi); |
664 | 665 | mdelay(10); | |
665 | control |= SM501_DC_PANEL_CONTROL_FPEN; | 666 | } |
666 | writel(control, ctrl_reg); | ||
667 | 667 | ||
668 | if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { | ||
669 | control |= SM501_DC_PANEL_CONTROL_FPEN; | ||
670 | writel(control, ctrl_reg); | ||
671 | sm501fb_sync_regs(fbi); | ||
672 | mdelay(10); | ||
673 | } | ||
668 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { | 674 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { |
669 | /* disable panel power */ | 675 | /* disable panel power */ |
676 | if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { | ||
677 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | ||
678 | writel(control, ctrl_reg); | ||
679 | sm501fb_sync_regs(fbi); | ||
680 | mdelay(10); | ||
681 | } | ||
670 | 682 | ||
671 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | 683 | if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { |
672 | writel(control, ctrl_reg); | 684 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; |
673 | sm501fb_sync_regs(fbi); | 685 | writel(control, ctrl_reg); |
674 | mdelay(10); | 686 | sm501fb_sync_regs(fbi); |
675 | 687 | mdelay(10); | |
676 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; | 688 | } |
677 | writel(control, ctrl_reg); | ||
678 | sm501fb_sync_regs(fbi); | ||
679 | mdelay(10); | ||
680 | 689 | ||
681 | control &= ~SM501_DC_PANEL_CONTROL_DATA; | 690 | control &= ~SM501_DC_PANEL_CONTROL_DATA; |
682 | writel(control, ctrl_reg); | 691 | writel(control, ctrl_reg); |
@@ -1267,6 +1276,7 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1267 | { | 1276 | { |
1268 | struct resource *res; | 1277 | struct resource *res; |
1269 | struct device *dev; | 1278 | struct device *dev; |
1279 | int k; | ||
1270 | int ret; | 1280 | int ret; |
1271 | 1281 | ||
1272 | info->dev = dev = &pdev->dev; | 1282 | info->dev = dev = &pdev->dev; |
@@ -1328,6 +1338,13 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1328 | 1338 | ||
1329 | info->fbmem_len = (res->end - res->start)+1; | 1339 | info->fbmem_len = (res->end - res->start)+1; |
1330 | 1340 | ||
1341 | /* clear framebuffer memory - avoids garbage data on unused fb */ | ||
1342 | memset(info->fbmem, 0, info->fbmem_len); | ||
1343 | |||
1344 | /* clear palette ram - undefined at power on */ | ||
1345 | for (k = 0; k < (256 * 3); k++) | ||
1346 | writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4)); | ||
1347 | |||
1331 | /* enable display controller */ | 1348 | /* enable display controller */ |
1332 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); | 1349 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); |
1333 | 1350 | ||
@@ -1681,6 +1698,15 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info, | |||
1681 | if (par->screen.size == 0) | 1698 | if (par->screen.size == 0) |
1682 | return 0; | 1699 | return 0; |
1683 | 1700 | ||
1701 | /* blank the relevant interface to ensure unit power minimised */ | ||
1702 | (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); | ||
1703 | |||
1704 | /* tell console/fb driver we are suspending */ | ||
1705 | |||
1706 | acquire_console_sem(); | ||
1707 | fb_set_suspend(fbi, 1); | ||
1708 | release_console_sem(); | ||
1709 | |||
1684 | /* backup copies in case chip is powered down over suspend */ | 1710 | /* backup copies in case chip is powered down over suspend */ |
1685 | 1711 | ||
1686 | par->store_fb = vmalloc(par->screen.size); | 1712 | par->store_fb = vmalloc(par->screen.size); |
@@ -1700,12 +1726,6 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info, | |||
1700 | 1726 | ||
1701 | memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); | 1727 | memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); |
1702 | memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); | 1728 | memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); |
1703 | /* blank the relevant interface to ensure unit power minimised */ | ||
1704 | (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); | ||
1705 | |||
1706 | acquire_console_sem(); | ||
1707 | fb_set_suspend(fbi, 1); | ||
1708 | release_console_sem(); | ||
1709 | 1729 | ||
1710 | return 0; | 1730 | return 0; |
1711 | 1731 | ||
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 057bdd593800..71e179ea5f95 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -1342,7 +1342,7 @@ out_err: | |||
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | #ifndef MODULE | 1344 | #ifndef MODULE |
1345 | static void tdfxfb_setup(char *options) | 1345 | static void __init tdfxfb_setup(char *options) |
1346 | { | 1346 | { |
1347 | char *this_opt; | 1347 | char *this_opt; |
1348 | 1348 | ||
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index a14ef894d571..be27b9c1ed72 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -2003,12 +2003,12 @@ static void __devexit uvesafb_exit(void) | |||
2003 | 2003 | ||
2004 | module_exit(uvesafb_exit); | 2004 | module_exit(uvesafb_exit); |
2005 | 2005 | ||
2006 | static inline int param_get_scroll(char *buffer, struct kernel_param *kp) | 2006 | static int param_get_scroll(char *buffer, struct kernel_param *kp) |
2007 | { | 2007 | { |
2008 | return 0; | 2008 | return 0; |
2009 | } | 2009 | } |
2010 | 2010 | ||
2011 | static inline int param_set_scroll(const char *val, struct kernel_param *kp) | 2011 | static int param_set_scroll(const char *val, struct kernel_param *kp) |
2012 | { | 2012 | { |
2013 | ypan = 0; | 2013 | ypan = 0; |
2014 | 2014 | ||
@@ -2022,11 +2022,11 @@ static inline int param_set_scroll(const char *val, struct kernel_param *kp) | |||
2022 | return 0; | 2022 | return 0; |
2023 | } | 2023 | } |
2024 | 2024 | ||
2025 | #define param_check_scroll(name, p) __param_check(name, p, void); | 2025 | #define param_check_scroll(name, p) __param_check(name, p, void) |
2026 | 2026 | ||
2027 | module_param_named(scroll, ypan, scroll, 0); | 2027 | module_param_named(scroll, ypan, scroll, 0); |
2028 | MODULE_PARM_DESC(scroll, | 2028 | MODULE_PARM_DESC(scroll, |
2029 | "Scrolling mode, set to 'redraw', ''ypan' or 'ywrap'"); | 2029 | "Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'"); |
2030 | module_param_named(vgapal, pmi_setpal, invbool, 0); | 2030 | module_param_named(vgapal, pmi_setpal, invbool, 0); |
2031 | MODULE_PARM_DESC(vgapal, "Set palette using VGA registers"); | 2031 | MODULE_PARM_DESC(vgapal, "Set palette using VGA registers"); |
2032 | module_param_named(pmipal, pmi_setpal, bool, 0); | 2032 | module_param_named(pmipal, pmi_setpal, bool, 0); |
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index 1c656667b937..2aa71eb67c2b 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c | |||
@@ -651,7 +651,7 @@ static int vmlfb_check_var_locked(struct fb_var_screeninfo *var, | |||
651 | return -EINVAL; | 651 | return -EINVAL; |
652 | } | 652 | } |
653 | 653 | ||
654 | pitch = __ALIGN_MASK((var->xres * var->bits_per_pixel) >> 3, 0x3F); | 654 | pitch = ALIGN((var->xres * var->bits_per_pixel) >> 3, 0x40); |
655 | mem = pitch * var->yres_virtual; | 655 | mem = pitch * var->yres_virtual; |
656 | if (mem > vinfo->vram_contig_size) { | 656 | if (mem > vinfo->vram_contig_size) { |
657 | return -ENOMEM; | 657 | return -ENOMEM; |
@@ -785,8 +785,7 @@ static int vmlfb_set_par_locked(struct vml_info *vinfo) | |||
785 | int clock; | 785 | int clock; |
786 | 786 | ||
787 | vinfo->bytes_per_pixel = var->bits_per_pixel >> 3; | 787 | vinfo->bytes_per_pixel = var->bits_per_pixel >> 3; |
788 | vinfo->stride = | 788 | vinfo->stride = ALIGN(var->xres_virtual * vinfo->bytes_per_pixel, 0x40); |
789 | __ALIGN_MASK(var->xres_virtual * vinfo->bytes_per_pixel, 0x3F); | ||
790 | info->fix.line_length = vinfo->stride; | 789 | info->fix.line_length = vinfo->stride; |
791 | 790 | ||
792 | if (!subsys) | 791 | if (!subsys) |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 622aece1acce..c8a4332d1132 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
26 | #include <linux/delay.h> | ||
26 | 27 | ||
27 | struct virtio_balloon | 28 | struct virtio_balloon |
28 | { | 29 | { |
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d447adf5..c4493091c655 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig | |||
@@ -42,5 +42,15 @@ config W1_MASTER_DS1WM | |||
42 | in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like | 42 | in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like |
43 | hx4700. | 43 | hx4700. |
44 | 44 | ||
45 | config W1_MASTER_GPIO | ||
46 | tristate "GPIO 1-wire busmaster" | ||
47 | depends on GENERIC_GPIO | ||
48 | help | ||
49 | Say Y here if you want to communicate with your 1-wire devices using | ||
50 | GPIO pins. This driver uses the GPIO API to control the wire. | ||
51 | |||
52 | This support is also available as a module. If so, the module | ||
53 | will be called w1-gpio.ko. | ||
54 | |||
45 | endmenu | 55 | endmenu |
46 | 56 | ||
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b328186..1420b5bbdda8 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile | |||
@@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o | |||
6 | obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o | 6 | obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o |
7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o | 7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o |
8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o | 8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o |
9 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o | ||
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000000000000..9e1138a75e8b --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * w1-gpio - GPIO w1 bus master driver | ||
3 | * | ||
4 | * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 | ||
8 | * as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/w1-gpio.h> | ||
15 | |||
16 | #include "../w1.h" | ||
17 | #include "../w1_int.h" | ||
18 | |||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | static void w1_gpio_write_bit_dir(void *data, u8 bit) | ||
22 | { | ||
23 | struct w1_gpio_platform_data *pdata = data; | ||
24 | |||
25 | if (bit) | ||
26 | gpio_direction_input(pdata->pin); | ||
27 | else | ||
28 | gpio_direction_output(pdata->pin, 0); | ||
29 | } | ||
30 | |||
31 | static void w1_gpio_write_bit_val(void *data, u8 bit) | ||
32 | { | ||
33 | struct w1_gpio_platform_data *pdata = data; | ||
34 | |||
35 | gpio_set_value(pdata->pin, bit); | ||
36 | } | ||
37 | |||
38 | static u8 w1_gpio_read_bit(void *data) | ||
39 | { | ||
40 | struct w1_gpio_platform_data *pdata = data; | ||
41 | |||
42 | return gpio_get_value(pdata->pin); | ||
43 | } | ||
44 | |||
45 | static int __init w1_gpio_probe(struct platform_device *pdev) | ||
46 | { | ||
47 | struct w1_bus_master *master; | ||
48 | struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; | ||
49 | int err; | ||
50 | |||
51 | if (!pdata) | ||
52 | return -ENXIO; | ||
53 | |||
54 | master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL); | ||
55 | if (!master) | ||
56 | return -ENOMEM; | ||
57 | |||
58 | err = gpio_request(pdata->pin, "w1"); | ||
59 | if (err) | ||
60 | goto free_master; | ||
61 | |||
62 | master->data = pdata; | ||
63 | master->read_bit = w1_gpio_read_bit; | ||
64 | |||
65 | if (pdata->is_open_drain) { | ||
66 | gpio_direction_output(pdata->pin, 1); | ||
67 | master->write_bit = w1_gpio_write_bit_val; | ||
68 | } else { | ||
69 | gpio_direction_input(pdata->pin); | ||
70 | master->write_bit = w1_gpio_write_bit_dir; | ||
71 | } | ||
72 | |||
73 | err = w1_add_master_device(master); | ||
74 | if (err) | ||
75 | goto free_gpio; | ||
76 | |||
77 | platform_set_drvdata(pdev, master); | ||
78 | |||
79 | return 0; | ||
80 | |||
81 | free_gpio: | ||
82 | gpio_free(pdata->pin); | ||
83 | free_master: | ||
84 | kfree(master); | ||
85 | |||
86 | return err; | ||
87 | } | ||
88 | |||
89 | static int __exit w1_gpio_remove(struct platform_device *pdev) | ||
90 | { | ||
91 | struct w1_bus_master *master = platform_get_drvdata(pdev); | ||
92 | struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; | ||
93 | |||
94 | w1_remove_master_device(master); | ||
95 | gpio_free(pdata->pin); | ||
96 | kfree(master); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static struct platform_driver w1_gpio_driver = { | ||
102 | .driver = { | ||
103 | .name = "w1-gpio", | ||
104 | .owner = THIS_MODULE, | ||
105 | }, | ||
106 | .remove = __exit_p(w1_gpio_remove), | ||
107 | }; | ||
108 | |||
109 | static int __init w1_gpio_init(void) | ||
110 | { | ||
111 | return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe); | ||
112 | } | ||
113 | |||
114 | static void __exit w1_gpio_exit(void) | ||
115 | { | ||
116 | platform_driver_unregister(&w1_gpio_driver); | ||
117 | } | ||
118 | |||
119 | module_init(w1_gpio_init); | ||
120 | module_exit(w1_gpio_exit); | ||
121 | |||
122 | MODULE_DESCRIPTION("GPIO w1 bus master driver"); | ||
123 | MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); | ||
124 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 112f4ec59035..fb28acaeed6c 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
@@ -92,6 +92,7 @@ struct w1_therm_family_converter | |||
92 | int (*convert)(u8 rom[9]); | 92 | int (*convert)(u8 rom[9]); |
93 | }; | 93 | }; |
94 | 94 | ||
95 | /* The return value is millidegrees Centigrade. */ | ||
95 | static inline int w1_DS18B20_convert_temp(u8 rom[9]); | 96 | static inline int w1_DS18B20_convert_temp(u8 rom[9]); |
96 | static inline int w1_DS18S20_convert_temp(u8 rom[9]); | 97 | static inline int w1_DS18S20_convert_temp(u8 rom[9]); |
97 | 98 | ||
@@ -113,7 +114,7 @@ static struct w1_therm_family_converter w1_therm_families[] = { | |||
113 | static inline int w1_DS18B20_convert_temp(u8 rom[9]) | 114 | static inline int w1_DS18B20_convert_temp(u8 rom[9]) |
114 | { | 115 | { |
115 | s16 t = (rom[1] << 8) | rom[0]; | 116 | s16 t = (rom[1] << 8) | rom[0]; |
116 | t /= 16; | 117 | t = t*1000/16; |
117 | return t; | 118 | return t; |
118 | } | 119 | } |
119 | 120 | ||
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 33e50310e9e0..7293c9b11f91 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -675,7 +675,6 @@ static void w1_slave_found(void *data, u64 rn) | |||
675 | struct w1_slave *sl; | 675 | struct w1_slave *sl; |
676 | struct list_head *ent; | 676 | struct list_head *ent; |
677 | struct w1_reg_num *tmp; | 677 | struct w1_reg_num *tmp; |
678 | int family_found = 0; | ||
679 | struct w1_master *dev; | 678 | struct w1_master *dev; |
680 | u64 rn_le = cpu_to_le64(rn); | 679 | u64 rn_le = cpu_to_le64(rn); |
681 | 680 | ||
@@ -698,9 +697,6 @@ static void w1_slave_found(void *data, u64 rn) | |||
698 | sl->reg_num.crc == tmp->crc) { | 697 | sl->reg_num.crc == tmp->crc) { |
699 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); | 698 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); |
700 | break; | 699 | break; |
701 | } else if (sl->reg_num.family == tmp->family) { | ||
702 | family_found = 1; | ||
703 | break; | ||
704 | } | 700 | } |
705 | 701 | ||
706 | slave_count++; | 702 | slave_count++; |