diff options
Diffstat (limited to 'drivers')
109 files changed, 6474 insertions, 1128 deletions
diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c index 4b65f74d66b1..ce074f6f3369 100644 --- a/drivers/acorn/block/mfmhd.c +++ b/drivers/acorn/block/mfmhd.c | |||
@@ -129,19 +129,6 @@ static DEFINE_SPINLOCK(mfm_lock); | |||
129 | #define MAJOR_NR MFM_ACORN_MAJOR | 129 | #define MAJOR_NR MFM_ACORN_MAJOR |
130 | #define QUEUE (mfm_queue) | 130 | #define QUEUE (mfm_queue) |
131 | #define CURRENT elv_next_request(mfm_queue) | 131 | #define CURRENT elv_next_request(mfm_queue) |
132 | /* | ||
133 | * This sort of stuff should be in a header file shared with ide.c, hd.c, xd.c etc | ||
134 | */ | ||
135 | #ifndef HDIO_GETGEO | ||
136 | #define HDIO_GETGEO 0x301 | ||
137 | struct hd_geometry { | ||
138 | unsigned char heads; | ||
139 | unsigned char sectors; | ||
140 | unsigned short cylinders; | ||
141 | unsigned long start; | ||
142 | }; | ||
143 | #endif | ||
144 | |||
145 | 132 | ||
146 | /* | 133 | /* |
147 | * Configuration section | 134 | * Configuration section |
@@ -1153,22 +1140,13 @@ static int mfm_initdrives(void) | |||
1153 | * The 'front' end of the mfm driver follows... | 1140 | * The 'front' end of the mfm driver follows... |
1154 | */ | 1141 | */ |
1155 | 1142 | ||
1156 | static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) | 1143 | static int mfm_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
1157 | { | 1144 | { |
1158 | struct mfm_info *p = inode->i_bdev->bd_disk->private_data; | 1145 | struct mfm_info *p = bdev->bd_disk->private_data; |
1159 | struct hd_geometry *geo = (struct hd_geometry *) arg; | 1146 | |
1160 | if (cmd != HDIO_GETGEO) | 1147 | geo->heads = p->heads; |
1161 | return -EINVAL; | 1148 | geo->sectors = p->sectors; |
1162 | if (!arg) | 1149 | geo->cylinders = p->cylinders; |
1163 | return -EINVAL; | ||
1164 | if (put_user (p->heads, &geo->heads)) | ||
1165 | return -EFAULT; | ||
1166 | if (put_user (p->sectors, &geo->sectors)) | ||
1167 | return -EFAULT; | ||
1168 | if (put_user (p->cylinders, &geo->cylinders)) | ||
1169 | return -EFAULT; | ||
1170 | if (put_user (get_start_sect(inode->i_bdev), &geo->start)) | ||
1171 | return -EFAULT; | ||
1172 | return 0; | 1150 | return 0; |
1173 | } | 1151 | } |
1174 | 1152 | ||
@@ -1219,7 +1197,7 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack, | |||
1219 | static struct block_device_operations mfm_fops = | 1197 | static struct block_device_operations mfm_fops = |
1220 | { | 1198 | { |
1221 | .owner = THIS_MODULE, | 1199 | .owner = THIS_MODULE, |
1222 | .ioctl = mfm_ioctl, | 1200 | .getgeo = mfm_getgeo, |
1223 | }; | 1201 | }; |
1224 | 1202 | ||
1225 | /* | 1203 | /* |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index e3cd0b16031a..20c9a37643c7 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -204,11 +204,13 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size, | |||
204 | 204 | ||
205 | return AE_OK; | 205 | return AE_OK; |
206 | } | 206 | } |
207 | EXPORT_SYMBOL_GPL(acpi_os_map_memory); | ||
207 | 208 | ||
208 | void acpi_os_unmap_memory(void __iomem * virt, acpi_size size) | 209 | void acpi_os_unmap_memory(void __iomem * virt, acpi_size size) |
209 | { | 210 | { |
210 | iounmap(virt); | 211 | iounmap(virt); |
211 | } | 212 | } |
213 | EXPORT_SYMBOL_GPL(acpi_os_unmap_memory); | ||
212 | 214 | ||
213 | #ifdef ACPI_FUTURE_USAGE | 215 | #ifdef ACPI_FUTURE_USAGE |
214 | acpi_status | 216 | acpi_status |
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index c57e20dcb0f8..074abc81ec3d 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c | |||
@@ -2126,8 +2126,7 @@ static void process_rsq(ns_dev *card) | |||
2126 | 2126 | ||
2127 | if (!ns_rsqe_valid(card->rsq.next)) | 2127 | if (!ns_rsqe_valid(card->rsq.next)) |
2128 | return; | 2128 | return; |
2129 | while (ns_rsqe_valid(card->rsq.next)) | 2129 | do { |
2130 | { | ||
2131 | dequeue_rx(card, card->rsq.next); | 2130 | dequeue_rx(card, card->rsq.next); |
2132 | ns_rsqe_init(card->rsq.next); | 2131 | ns_rsqe_init(card->rsq.next); |
2133 | previous = card->rsq.next; | 2132 | previous = card->rsq.next; |
@@ -2135,7 +2134,7 @@ static void process_rsq(ns_dev *card) | |||
2135 | card->rsq.next = card->rsq.base; | 2134 | card->rsq.next = card->rsq.base; |
2136 | else | 2135 | else |
2137 | card->rsq.next++; | 2136 | card->rsq.next++; |
2138 | } | 2137 | } while (ns_rsqe_valid(card->rsq.next)); |
2139 | writel((((u32) previous) - ((u32) card->rsq.base)), | 2138 | writel((((u32) previous) - ((u32) card->rsq.base)), |
2140 | card->membase + RSQH); | 2139 | card->membase + RSQH); |
2141 | } | 2140 | } |
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 21097a39a057..4a7bb7dfce85 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
@@ -92,34 +92,28 @@ static int DAC960_open(struct inode *inode, struct file *file) | |||
92 | return 0; | 92 | return 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | static int DAC960_ioctl(struct inode *inode, struct file *file, | 95 | static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
96 | unsigned int cmd, unsigned long arg) | ||
97 | { | 96 | { |
98 | struct gendisk *disk = inode->i_bdev->bd_disk; | 97 | struct gendisk *disk = bdev->bd_disk; |
99 | DAC960_Controller_T *p = disk->queue->queuedata; | 98 | DAC960_Controller_T *p = disk->queue->queuedata; |
100 | int drive_nr = (long)disk->private_data; | 99 | int drive_nr = (long)disk->private_data; |
101 | struct hd_geometry g; | ||
102 | struct hd_geometry __user *loc = (struct hd_geometry __user *)arg; | ||
103 | |||
104 | if (cmd != HDIO_GETGEO || !loc) | ||
105 | return -EINVAL; | ||
106 | 100 | ||
107 | if (p->FirmwareType == DAC960_V1_Controller) { | 101 | if (p->FirmwareType == DAC960_V1_Controller) { |
108 | g.heads = p->V1.GeometryTranslationHeads; | 102 | geo->heads = p->V1.GeometryTranslationHeads; |
109 | g.sectors = p->V1.GeometryTranslationSectors; | 103 | geo->sectors = p->V1.GeometryTranslationSectors; |
110 | g.cylinders = p->V1.LogicalDriveInformation[drive_nr]. | 104 | geo->cylinders = p->V1.LogicalDriveInformation[drive_nr]. |
111 | LogicalDriveSize / (g.heads * g.sectors); | 105 | LogicalDriveSize / (geo->heads * geo->sectors); |
112 | } else { | 106 | } else { |
113 | DAC960_V2_LogicalDeviceInfo_T *i = | 107 | DAC960_V2_LogicalDeviceInfo_T *i = |
114 | p->V2.LogicalDeviceInformation[drive_nr]; | 108 | p->V2.LogicalDeviceInformation[drive_nr]; |
115 | switch (i->DriveGeometry) { | 109 | switch (i->DriveGeometry) { |
116 | case DAC960_V2_Geometry_128_32: | 110 | case DAC960_V2_Geometry_128_32: |
117 | g.heads = 128; | 111 | geo->heads = 128; |
118 | g.sectors = 32; | 112 | geo->sectors = 32; |
119 | break; | 113 | break; |
120 | case DAC960_V2_Geometry_255_63: | 114 | case DAC960_V2_Geometry_255_63: |
121 | g.heads = 255; | 115 | geo->heads = 255; |
122 | g.sectors = 63; | 116 | geo->sectors = 63; |
123 | break; | 117 | break; |
124 | default: | 118 | default: |
125 | DAC960_Error("Illegal Logical Device Geometry %d\n", | 119 | DAC960_Error("Illegal Logical Device Geometry %d\n", |
@@ -127,12 +121,11 @@ static int DAC960_ioctl(struct inode *inode, struct file *file, | |||
127 | return -EINVAL; | 121 | return -EINVAL; |
128 | } | 122 | } |
129 | 123 | ||
130 | g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors); | 124 | geo->cylinders = i->ConfigurableDeviceSize / |
125 | (geo->heads * geo->sectors); | ||
131 | } | 126 | } |
132 | 127 | ||
133 | g.start = get_start_sect(inode->i_bdev); | 128 | return 0; |
134 | |||
135 | return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; | ||
136 | } | 129 | } |
137 | 130 | ||
138 | static int DAC960_media_changed(struct gendisk *disk) | 131 | static int DAC960_media_changed(struct gendisk *disk) |
@@ -157,7 +150,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk) | |||
157 | static struct block_device_operations DAC960_BlockDeviceOperations = { | 150 | static struct block_device_operations DAC960_BlockDeviceOperations = { |
158 | .owner = THIS_MODULE, | 151 | .owner = THIS_MODULE, |
159 | .open = DAC960_open, | 152 | .open = DAC960_open, |
160 | .ioctl = DAC960_ioctl, | 153 | .getgeo = DAC960_getgeo, |
161 | .media_changed = DAC960_media_changed, | 154 | .media_changed = DAC960_media_changed, |
162 | .revalidate_disk = DAC960_revalidate_disk, | 155 | .revalidate_disk = DAC960_revalidate_disk, |
163 | }; | 156 | }; |
@@ -3767,7 +3760,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command) | |||
3767 | if (SenseKey == DAC960_SenseKey_VendorSpecific && | 3760 | if (SenseKey == DAC960_SenseKey_VendorSpecific && |
3768 | AdditionalSenseCode == 0x80 && | 3761 | AdditionalSenseCode == 0x80 && |
3769 | AdditionalSenseCodeQualifier < | 3762 | AdditionalSenseCodeQualifier < |
3770 | sizeof(DAC960_EventMessages) / sizeof(char *)) | 3763 | ARRAY_SIZE(DAC960_EventMessages)) |
3771 | DAC960_Critical("Physical Device %d:%d %s\n", Controller, | 3764 | DAC960_Critical("Physical Device %d:%d %s\n", Controller, |
3772 | EventLogEntry->Channel, | 3765 | EventLogEntry->Channel, |
3773 | EventLogEntry->TargetID, | 3766 | EventLogEntry->TargetID, |
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c index 5d2d649f7e8d..196c0ec9cd54 100644 --- a/drivers/block/acsi.c +++ b/drivers/block/acsi.c | |||
@@ -1079,6 +1079,19 @@ static void redo_acsi_request( void ) | |||
1079 | * | 1079 | * |
1080 | ***********************************************************************/ | 1080 | ***********************************************************************/ |
1081 | 1081 | ||
1082 | static int acsi_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
1083 | { | ||
1084 | struct acsi_info_struct *aip = bdev->bd_disk->private_data; | ||
1085 | |||
1086 | /* | ||
1087 | * Just fake some geometry here, it's nonsense anyway | ||
1088 | * To make it easy, use Adaptec's usual 64/32 mapping | ||
1089 | */ | ||
1090 | geo->heads = 64; | ||
1091 | geo->sectors = 32; | ||
1092 | geo->cylinders = aip->size >> 11; | ||
1093 | return 0; | ||
1094 | } | ||
1082 | 1095 | ||
1083 | static int acsi_ioctl( struct inode *inode, struct file *file, | 1096 | static int acsi_ioctl( struct inode *inode, struct file *file, |
1084 | unsigned int cmd, unsigned long arg ) | 1097 | unsigned int cmd, unsigned long arg ) |
@@ -1086,18 +1099,6 @@ static int acsi_ioctl( struct inode *inode, struct file *file, | |||
1086 | struct gendisk *disk = inode->i_bdev->bd_disk; | 1099 | struct gendisk *disk = inode->i_bdev->bd_disk; |
1087 | struct acsi_info_struct *aip = disk->private_data; | 1100 | struct acsi_info_struct *aip = disk->private_data; |
1088 | switch (cmd) { | 1101 | switch (cmd) { |
1089 | case HDIO_GETGEO: | ||
1090 | /* HDIO_GETGEO is supported more for getting the partition's | ||
1091 | * start sector... */ | ||
1092 | { struct hd_geometry *geo = (struct hd_geometry *)arg; | ||
1093 | /* just fake some geometry here, it's nonsense anyway; to make it | ||
1094 | * easy, use Adaptec's usual 64/32 mapping */ | ||
1095 | put_user( 64, &geo->heads ); | ||
1096 | put_user( 32, &geo->sectors ); | ||
1097 | put_user( aip->size >> 11, &geo->cylinders ); | ||
1098 | put_user(get_start_sect(inode->i_bdev), &geo->start); | ||
1099 | return 0; | ||
1100 | } | ||
1101 | case SCSI_IOCTL_GET_IDLUN: | 1102 | case SCSI_IOCTL_GET_IDLUN: |
1102 | /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */ | 1103 | /* SCSI compatible GET_IDLUN call to get target's ID and LUN number */ |
1103 | put_user( aip->target | (aip->lun << 8), | 1104 | put_user( aip->target | (aip->lun << 8), |
@@ -1592,6 +1593,7 @@ static struct block_device_operations acsi_fops = { | |||
1592 | .open = acsi_open, | 1593 | .open = acsi_open, |
1593 | .release = acsi_release, | 1594 | .release = acsi_release, |
1594 | .ioctl = acsi_ioctl, | 1595 | .ioctl = acsi_ioctl, |
1596 | .getgeo = acsi_getgeo, | ||
1595 | .media_changed = acsi_media_change, | 1597 | .media_changed = acsi_media_change, |
1596 | .revalidate_disk= acsi_revalidate, | 1598 | .revalidate_disk= acsi_revalidate, |
1597 | }; | 1599 | }; |
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 0acbfff8ad28..3c679d30b698 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
@@ -131,7 +131,7 @@ static struct fd_drive_type drive_types[] = { | |||
131 | { FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2}, | 131 | { FD_DD_5, "DD 5.25", 40, 2, 14716, 13630, 1, 40, 81, 6, 30, 2}, |
132 | { FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} | 132 | { FD_NODRIVE, "No Drive", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} |
133 | }; | 133 | }; |
134 | static int num_dr_types = sizeof(drive_types) / sizeof(drive_types[0]); | 134 | static int num_dr_types = ARRAY_SIZE(drive_types); |
135 | 135 | ||
136 | static int amiga_read(int), dos_read(int); | 136 | static int amiga_read(int), dos_read(int); |
137 | static void amiga_write(int), dos_write(int); | 137 | static void amiga_write(int), dos_write(int); |
@@ -1424,6 +1424,16 @@ static void do_fd_request(request_queue_t * q) | |||
1424 | redo_fd_request(); | 1424 | redo_fd_request(); |
1425 | } | 1425 | } |
1426 | 1426 | ||
1427 | static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
1428 | { | ||
1429 | int drive = MINOR(bdev->bd_dev) & 3; | ||
1430 | |||
1431 | geo->heads = unit[drive].type->heads; | ||
1432 | geo->sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult; | ||
1433 | geo->cylinders = unit[drive].type->tracks; | ||
1434 | return 0; | ||
1435 | } | ||
1436 | |||
1427 | static int fd_ioctl(struct inode *inode, struct file *filp, | 1437 | static int fd_ioctl(struct inode *inode, struct file *filp, |
1428 | unsigned int cmd, unsigned long param) | 1438 | unsigned int cmd, unsigned long param) |
1429 | { | 1439 | { |
@@ -1431,18 +1441,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1431 | static struct floppy_struct getprm; | 1441 | static struct floppy_struct getprm; |
1432 | 1442 | ||
1433 | switch(cmd){ | 1443 | switch(cmd){ |
1434 | case HDIO_GETGEO: | ||
1435 | { | ||
1436 | struct hd_geometry loc; | ||
1437 | loc.heads = unit[drive].type->heads; | ||
1438 | loc.sectors = unit[drive].dtype->sects * unit[drive].type->sect_mult; | ||
1439 | loc.cylinders = unit[drive].type->tracks; | ||
1440 | loc.start = 0; | ||
1441 | if (copy_to_user((void *)param, (void *)&loc, | ||
1442 | sizeof(struct hd_geometry))) | ||
1443 | return -EFAULT; | ||
1444 | break; | ||
1445 | } | ||
1446 | case FDFMTBEG: | 1444 | case FDFMTBEG: |
1447 | get_fdc(drive); | 1445 | get_fdc(drive); |
1448 | if (fd_ref[drive] > 1) { | 1446 | if (fd_ref[drive] > 1) { |
@@ -1652,6 +1650,7 @@ static struct block_device_operations floppy_fops = { | |||
1652 | .open = floppy_open, | 1650 | .open = floppy_open, |
1653 | .release = floppy_release, | 1651 | .release = floppy_release, |
1654 | .ioctl = fd_ioctl, | 1652 | .ioctl = fd_ioctl, |
1653 | .getgeo = fd_getgeo, | ||
1655 | .media_changed = amiga_floppy_change, | 1654 | .media_changed = amiga_floppy_change, |
1656 | }; | 1655 | }; |
1657 | 1656 | ||
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 0e97fcb9f3a1..c05ee8bffd97 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c | |||
@@ -169,38 +169,26 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) | |||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
172 | /* This ioctl implementation expects userland to have the device node | ||
173 | * permissions set so that only priviledged users can open an aoe | ||
174 | * block device directly. | ||
175 | */ | ||
176 | static int | 172 | static int |
177 | aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg) | 173 | aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
178 | { | 174 | { |
179 | struct aoedev *d; | 175 | struct aoedev *d = bdev->bd_disk->private_data; |
180 | |||
181 | if (!arg) | ||
182 | return -EINVAL; | ||
183 | 176 | ||
184 | d = inode->i_bdev->bd_disk->private_data; | ||
185 | if ((d->flags & DEVFL_UP) == 0) { | 177 | if ((d->flags & DEVFL_UP) == 0) { |
186 | printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); | 178 | printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); |
187 | return -ENODEV; | 179 | return -ENODEV; |
188 | } | 180 | } |
189 | 181 | ||
190 | if (cmd == HDIO_GETGEO) { | 182 | geo->cylinders = d->geo.cylinders; |
191 | d->geo.start = get_start_sect(inode->i_bdev); | 183 | geo->heads = d->geo.heads; |
192 | if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo)) | 184 | geo->sectors = d->geo.sectors; |
193 | return 0; | 185 | return 0; |
194 | return -EFAULT; | ||
195 | } | ||
196 | printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd); | ||
197 | return -EINVAL; | ||
198 | } | 186 | } |
199 | 187 | ||
200 | static struct block_device_operations aoe_bdops = { | 188 | static struct block_device_operations aoe_bdops = { |
201 | .open = aoeblk_open, | 189 | .open = aoeblk_open, |
202 | .release = aoeblk_release, | 190 | .release = aoeblk_release, |
203 | .ioctl = aoeblk_ioctl, | 191 | .getgeo = aoeblk_getgeo, |
204 | .owner = THIS_MODULE, | 192 | .owner = THIS_MODULE, |
205 | }; | 193 | }; |
206 | 194 | ||
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 22bda05fc693..3aa68a5447d6 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
@@ -181,7 +181,7 @@ static struct { | |||
181 | { 6, TYPE_HD }, /* 31: H1640 <- was H1600 == h1600 for PC */ | 181 | { 6, TYPE_HD }, /* 31: H1640 <- was H1600 == h1600 for PC */ |
182 | }; | 182 | }; |
183 | 183 | ||
184 | #define NUM_DISK_MINORS (sizeof(minor2disktype)/sizeof(*minor2disktype)) | 184 | #define NUM_DISK_MINORS ARRAY_SIZE(minor2disktype) |
185 | 185 | ||
186 | /* | 186 | /* |
187 | * Maximum disk size (in kilobytes). This default is used whenever the | 187 | * Maximum disk size (in kilobytes). This default is used whenever the |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index d2815b7a9150..88452c79fb64 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Disk Array driver for HP SA 5xxx and 6xxx Controllers | 2 | * Disk Array driver for HP SA 5xxx and 6xxx Controllers |
3 | * Copyright 2000, 2005 Hewlett-Packard Development Company, L.P. | 3 | * Copyright 2000, 2006 Hewlett-Packard Development Company, L.P. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -47,12 +47,12 @@ | |||
47 | #include <linux/completion.h> | 47 | #include <linux/completion.h> |
48 | 48 | ||
49 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) | 49 | #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) |
50 | #define DRIVER_NAME "HP CISS Driver (v 2.6.8)" | 50 | #define DRIVER_NAME "HP CISS Driver (v 2.6.10)" |
51 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8) | 51 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,10) |
52 | 52 | ||
53 | /* Embedded module documentation macros - see modules.h */ | 53 | /* Embedded module documentation macros - see modules.h */ |
54 | MODULE_AUTHOR("Hewlett-Packard Company"); | 54 | MODULE_AUTHOR("Hewlett-Packard Company"); |
55 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8"); | 55 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.10"); |
56 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" | 56 | MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400" |
57 | " SA6i P600 P800 P400 P400i E200 E200i"); | 57 | " SA6i P600 P800 P400 P400i E200 E200i"); |
58 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
@@ -103,7 +103,7 @@ static const struct pci_device_id cciss_pci_device_id[] = { | |||
103 | }; | 103 | }; |
104 | MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); | 104 | MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); |
105 | 105 | ||
106 | #define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type)) | 106 | #define NR_PRODUCTS ARRAY_SIZE(products) |
107 | 107 | ||
108 | /* board_id = Subsystem Device ID & Vendor ID | 108 | /* board_id = Subsystem Device ID & Vendor ID |
109 | * product = Marketing Name for the board | 109 | * product = Marketing Name for the board |
@@ -153,6 +153,7 @@ static int cciss_open(struct inode *inode, struct file *filep); | |||
153 | static int cciss_release(struct inode *inode, struct file *filep); | 153 | static int cciss_release(struct inode *inode, struct file *filep); |
154 | static int cciss_ioctl(struct inode *inode, struct file *filep, | 154 | static int cciss_ioctl(struct inode *inode, struct file *filep, |
155 | unsigned int cmd, unsigned long arg); | 155 | unsigned int cmd, unsigned long arg); |
156 | static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); | ||
156 | 157 | ||
157 | static int revalidate_allvol(ctlr_info_t *host); | 158 | static int revalidate_allvol(ctlr_info_t *host); |
158 | static int cciss_revalidate(struct gendisk *disk); | 159 | static int cciss_revalidate(struct gendisk *disk); |
@@ -166,7 +167,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, | |||
166 | unsigned int block_size, InquiryData_struct *inq_buff, | 167 | unsigned int block_size, InquiryData_struct *inq_buff, |
167 | drive_info_struct *drv); | 168 | drive_info_struct *drv); |
168 | static void cciss_getgeometry(int cntl_num); | 169 | static void cciss_getgeometry(int cntl_num); |
169 | 170 | static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, __u32); | |
170 | static void start_io( ctlr_info_t *h); | 171 | static void start_io( ctlr_info_t *h); |
171 | static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, | 172 | static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, |
172 | unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, | 173 | unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, |
@@ -194,6 +195,7 @@ static struct block_device_operations cciss_fops = { | |||
194 | .open = cciss_open, | 195 | .open = cciss_open, |
195 | .release = cciss_release, | 196 | .release = cciss_release, |
196 | .ioctl = cciss_ioctl, | 197 | .ioctl = cciss_ioctl, |
198 | .getgeo = cciss_getgeo, | ||
197 | #ifdef CONFIG_COMPAT | 199 | #ifdef CONFIG_COMPAT |
198 | .compat_ioctl = cciss_compat_ioctl, | 200 | .compat_ioctl = cciss_compat_ioctl, |
199 | #endif | 201 | #endif |
@@ -282,7 +284,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, | |||
282 | h->product_name, | 284 | h->product_name, |
283 | (unsigned long)h->board_id, | 285 | (unsigned long)h->board_id, |
284 | h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3], | 286 | h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3], |
285 | (unsigned int)h->intr, | 287 | (unsigned int)h->intr[SIMPLE_MODE_INT], |
286 | h->num_luns, | 288 | h->num_luns, |
287 | h->Qdepth, h->commands_outstanding, | 289 | h->Qdepth, h->commands_outstanding, |
288 | h->maxQsinceinit, h->max_outstanding, h->maxSG); | 290 | h->maxQsinceinit, h->max_outstanding, h->maxSG); |
@@ -633,6 +635,20 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned | |||
633 | return err; | 635 | return err; |
634 | } | 636 | } |
635 | #endif | 637 | #endif |
638 | |||
639 | static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
640 | { | ||
641 | drive_info_struct *drv = get_drv(bdev->bd_disk); | ||
642 | |||
643 | if (!drv->cylinders) | ||
644 | return -ENXIO; | ||
645 | |||
646 | geo->heads = drv->heads; | ||
647 | geo->sectors = drv->sectors; | ||
648 | geo->cylinders = drv->cylinders; | ||
649 | return 0; | ||
650 | } | ||
651 | |||
636 | /* | 652 | /* |
637 | * ioctl | 653 | * ioctl |
638 | */ | 654 | */ |
@@ -651,21 +667,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, | |||
651 | #endif /* CCISS_DEBUG */ | 667 | #endif /* CCISS_DEBUG */ |
652 | 668 | ||
653 | switch(cmd) { | 669 | switch(cmd) { |
654 | case HDIO_GETGEO: | ||
655 | { | ||
656 | struct hd_geometry driver_geo; | ||
657 | if (drv->cylinders) { | ||
658 | driver_geo.heads = drv->heads; | ||
659 | driver_geo.sectors = drv->sectors; | ||
660 | driver_geo.cylinders = drv->cylinders; | ||
661 | } else | ||
662 | return -ENXIO; | ||
663 | driver_geo.start= get_start_sect(inode->i_bdev); | ||
664 | if (copy_to_user(argp, &driver_geo, sizeof(struct hd_geometry))) | ||
665 | return -EFAULT; | ||
666 | return(0); | ||
667 | } | ||
668 | |||
669 | case CCISS_GETPCIINFO: | 670 | case CCISS_GETPCIINFO: |
670 | { | 671 | { |
671 | cciss_pci_info_struct pciinfo; | 672 | cciss_pci_info_struct pciinfo; |
@@ -2661,6 +2662,60 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, | |||
2661 | return -1; | 2662 | return -1; |
2662 | } | 2663 | } |
2663 | 2664 | ||
2665 | /* If MSI/MSI-X is supported by the kernel we will try to enable it on | ||
2666 | * controllers that are capable. If not, we use IO-APIC mode. | ||
2667 | */ | ||
2668 | |||
2669 | static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, __u32 board_id) | ||
2670 | { | ||
2671 | #ifdef CONFIG_PCI_MSI | ||
2672 | int err; | ||
2673 | struct msix_entry cciss_msix_entries[4] = {{0,0}, {0,1}, | ||
2674 | {0,2}, {0,3}}; | ||
2675 | |||
2676 | /* Some boards advertise MSI but don't really support it */ | ||
2677 | if ((board_id == 0x40700E11) || | ||
2678 | (board_id == 0x40800E11) || | ||
2679 | (board_id == 0x40820E11) || | ||
2680 | (board_id == 0x40830E11)) | ||
2681 | goto default_int_mode; | ||
2682 | |||
2683 | if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) { | ||
2684 | err = pci_enable_msix(pdev, cciss_msix_entries, 4); | ||
2685 | if (!err) { | ||
2686 | c->intr[0] = cciss_msix_entries[0].vector; | ||
2687 | c->intr[1] = cciss_msix_entries[1].vector; | ||
2688 | c->intr[2] = cciss_msix_entries[2].vector; | ||
2689 | c->intr[3] = cciss_msix_entries[3].vector; | ||
2690 | c->msix_vector = 1; | ||
2691 | return; | ||
2692 | } | ||
2693 | if (err > 0) { | ||
2694 | printk(KERN_WARNING "cciss: only %d MSI-X vectors " | ||
2695 | "available\n", err); | ||
2696 | } else { | ||
2697 | printk(KERN_WARNING "cciss: MSI-X init failed %d\n", | ||
2698 | err); | ||
2699 | } | ||
2700 | } | ||
2701 | if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) { | ||
2702 | if (!pci_enable_msi(pdev)) { | ||
2703 | c->intr[SIMPLE_MODE_INT] = pdev->irq; | ||
2704 | c->msi_vector = 1; | ||
2705 | return; | ||
2706 | } else { | ||
2707 | printk(KERN_WARNING "cciss: MSI init failed\n"); | ||
2708 | c->intr[SIMPLE_MODE_INT] = pdev->irq; | ||
2709 | return; | ||
2710 | } | ||
2711 | } | ||
2712 | #endif /* CONFIG_PCI_MSI */ | ||
2713 | /* if we get here we're going to use the default interrupt mode */ | ||
2714 | default_int_mode: | ||
2715 | c->intr[SIMPLE_MODE_INT] = pdev->irq; | ||
2716 | return; | ||
2717 | } | ||
2718 | |||
2664 | static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | 2719 | static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) |
2665 | { | 2720 | { |
2666 | ushort subsystem_vendor_id, subsystem_device_id, command; | 2721 | ushort subsystem_vendor_id, subsystem_device_id, command; |
@@ -2721,7 +2776,10 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | |||
2721 | printk("board_id = %x\n", board_id); | 2776 | printk("board_id = %x\n", board_id); |
2722 | #endif /* CCISS_DEBUG */ | 2777 | #endif /* CCISS_DEBUG */ |
2723 | 2778 | ||
2724 | c->intr = pdev->irq; | 2779 | /* If the kernel supports MSI/MSI-X we will try to enable that functionality, |
2780 | * else we use the IO-APIC interrupt assigned to us by system ROM. | ||
2781 | */ | ||
2782 | cciss_interrupt_mode(c, pdev, board_id); | ||
2725 | 2783 | ||
2726 | /* | 2784 | /* |
2727 | * Memory base addr is first addr , the second points to the config | 2785 | * Memory base addr is first addr , the second points to the config |
@@ -2775,7 +2833,7 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev) | |||
2775 | c->board_id = board_id; | 2833 | c->board_id = board_id; |
2776 | 2834 | ||
2777 | #ifdef CCISS_DEBUG | 2835 | #ifdef CCISS_DEBUG |
2778 | print_cfg_table(c->cfgtable); | 2836 | print_cfg_table(c->cfgtable); |
2779 | #endif /* CCISS_DEBUG */ | 2837 | #endif /* CCISS_DEBUG */ |
2780 | 2838 | ||
2781 | for(i=0; i<NR_PRODUCTS; i++) { | 2839 | for(i=0; i<NR_PRODUCTS; i++) { |
@@ -3060,7 +3118,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3060 | * 8 controller support. | 3118 | * 8 controller support. |
3061 | */ | 3119 | */ |
3062 | if (i < MAX_CTLR_ORIG) | 3120 | if (i < MAX_CTLR_ORIG) |
3063 | hba[i]->major = MAJOR_NR + i; | 3121 | hba[i]->major = COMPAQ_CISS_MAJOR + i; |
3064 | rc = register_blkdev(hba[i]->major, hba[i]->devname); | 3122 | rc = register_blkdev(hba[i]->major, hba[i]->devname); |
3065 | if(rc == -EBUSY || rc == -EINVAL) { | 3123 | if(rc == -EBUSY || rc == -EINVAL) { |
3066 | printk(KERN_ERR | 3124 | printk(KERN_ERR |
@@ -3075,11 +3133,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3075 | 3133 | ||
3076 | /* make sure the board interrupts are off */ | 3134 | /* make sure the board interrupts are off */ |
3077 | hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); | 3135 | hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); |
3078 | if( request_irq(hba[i]->intr, do_cciss_intr, | 3136 | if( request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr, |
3079 | SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, | 3137 | SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, |
3080 | hba[i]->devname, hba[i])) { | 3138 | hba[i]->devname, hba[i])) { |
3081 | printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", | 3139 | printk(KERN_ERR "cciss: Unable to get irq %d for %s\n", |
3082 | hba[i]->intr, hba[i]->devname); | 3140 | hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname); |
3083 | goto clean2; | 3141 | goto clean2; |
3084 | } | 3142 | } |
3085 | hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL); | 3143 | hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL); |
@@ -3185,7 +3243,7 @@ clean4: | |||
3185 | NR_CMDS * sizeof( ErrorInfo_struct), | 3243 | NR_CMDS * sizeof( ErrorInfo_struct), |
3186 | hba[i]->errinfo_pool, | 3244 | hba[i]->errinfo_pool, |
3187 | hba[i]->errinfo_pool_dhandle); | 3245 | hba[i]->errinfo_pool_dhandle); |
3188 | free_irq(hba[i]->intr, hba[i]); | 3246 | free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]); |
3189 | clean2: | 3247 | clean2: |
3190 | unregister_blkdev(hba[i]->major, hba[i]->devname); | 3248 | unregister_blkdev(hba[i]->major, hba[i]->devname); |
3191 | clean1: | 3249 | clean1: |
@@ -3226,7 +3284,15 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) | |||
3226 | printk(KERN_WARNING "Error Flushing cache on controller %d\n", | 3284 | printk(KERN_WARNING "Error Flushing cache on controller %d\n", |
3227 | i); | 3285 | i); |
3228 | } | 3286 | } |
3229 | free_irq(hba[i]->intr, hba[i]); | 3287 | free_irq(hba[i]->intr[2], hba[i]); |
3288 | |||
3289 | #ifdef CONFIG_PCI_MSI | ||
3290 | if (hba[i]->msix_vector) | ||
3291 | pci_disable_msix(hba[i]->pdev); | ||
3292 | else if (hba[i]->msi_vector) | ||
3293 | pci_disable_msi(hba[i]->pdev); | ||
3294 | #endif /* CONFIG_PCI_MSI */ | ||
3295 | |||
3230 | pci_set_drvdata(pdev, NULL); | 3296 | pci_set_drvdata(pdev, NULL); |
3231 | iounmap(hba[i]->vaddr); | 3297 | iounmap(hba[i]->vaddr); |
3232 | cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ | 3298 | cciss_unregister_scsi(i); /* unhook from SCSI subsystem */ |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 3b0858c83897..b24fc0553ccf 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -13,8 +13,6 @@ | |||
13 | #define IO_OK 0 | 13 | #define IO_OK 0 |
14 | #define IO_ERROR 1 | 14 | #define IO_ERROR 1 |
15 | 15 | ||
16 | #define MAJOR_NR COMPAQ_CISS_MAJOR | ||
17 | |||
18 | struct ctlr_info; | 16 | struct ctlr_info; |
19 | typedef struct ctlr_info ctlr_info_t; | 17 | typedef struct ctlr_info ctlr_info_t; |
20 | 18 | ||
@@ -65,7 +63,6 @@ struct ctlr_info | |||
65 | unsigned long io_mem_addr; | 63 | unsigned long io_mem_addr; |
66 | unsigned long io_mem_length; | 64 | unsigned long io_mem_length; |
67 | CfgTable_struct __iomem *cfgtable; | 65 | CfgTable_struct __iomem *cfgtable; |
68 | unsigned int intr; | ||
69 | int interrupts_enabled; | 66 | int interrupts_enabled; |
70 | int major; | 67 | int major; |
71 | int max_commands; | 68 | int max_commands; |
@@ -74,6 +71,13 @@ struct ctlr_info | |||
74 | int num_luns; | 71 | int num_luns; |
75 | int highest_lun; | 72 | int highest_lun; |
76 | int usage_count; /* number of opens all all minor devices */ | 73 | int usage_count; /* number of opens all all minor devices */ |
74 | # define DOORBELL_INT 0 | ||
75 | # define PERF_MODE_INT 1 | ||
76 | # define SIMPLE_MODE_INT 2 | ||
77 | # define MEMQ_MODE_INT 3 | ||
78 | unsigned int intr[4]; | ||
79 | unsigned int msix_vector; | ||
80 | unsigned int msi_vector; | ||
77 | 81 | ||
78 | // information about each logical volume | 82 | // information about each logical volume |
79 | drive_info_struct drv[CISS_MAX_LUN]; | 83 | drive_info_struct drv[CISS_MAX_LUN]; |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 2942d32280a5..9e35de05d5c5 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -714,7 +714,7 @@ cciss_scsi_detect(int ctlr) | |||
714 | ((struct cciss_scsi_adapter_data_t *) | 714 | ((struct cciss_scsi_adapter_data_t *) |
715 | hba[ctlr]->scsi_ctlr)->scsi_host = (void *) sh; | 715 | hba[ctlr]->scsi_ctlr)->scsi_host = (void *) sh; |
716 | sh->hostdata[0] = (unsigned long) hba[ctlr]; | 716 | sh->hostdata[0] = (unsigned long) hba[ctlr]; |
717 | sh->irq = hba[ctlr]->intr; | 717 | sh->irq = hba[ctlr]->intr[SIMPLE_MODE_INT]; |
718 | sh->unique_id = sh->irq; | 718 | sh->unique_id = sh->irq; |
719 | error = scsi_add_host(sh, &hba[ctlr]->pdev->dev); | 719 | error = scsi_add_host(sh, &hba[ctlr]->pdev->dev); |
720 | if (error) | 720 | if (error) |
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 9bddb6874873..862b9abac0ae 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c | |||
@@ -72,11 +72,11 @@ static ctlr_info_t *hba[MAX_CTLR]; | |||
72 | 72 | ||
73 | static int eisa[8]; | 73 | static int eisa[8]; |
74 | 74 | ||
75 | #define NR_PRODUCTS (sizeof(products)/sizeof(struct board_type)) | 75 | #define NR_PRODUCTS ARRAY_SIZE(products) |
76 | 76 | ||
77 | /* board_id = Subsystem Device ID & Vendor ID | 77 | /* board_id = Subsystem Device ID & Vendor ID |
78 | * product = Marketing Name for the board | 78 | * product = Marketing Name for the board |
79 | * access = Address of the struct of function pointers | 79 | * access = Address of the struct of function pointers |
80 | */ | 80 | */ |
81 | static struct board_type products[] = { | 81 | static struct board_type products[] = { |
82 | { 0x0040110E, "IDA", &smart1_access }, | 82 | { 0x0040110E, "IDA", &smart1_access }, |
@@ -160,6 +160,7 @@ static int sendcmd( | |||
160 | static int ida_open(struct inode *inode, struct file *filep); | 160 | static int ida_open(struct inode *inode, struct file *filep); |
161 | static int ida_release(struct inode *inode, struct file *filep); | 161 | static int ida_release(struct inode *inode, struct file *filep); |
162 | static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); | 162 | static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); |
163 | static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo); | ||
163 | static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io); | 164 | static int ida_ctlr_ioctl(ctlr_info_t *h, int dsk, ida_ioctl_t *io); |
164 | 165 | ||
165 | static void do_ida_request(request_queue_t *q); | 166 | static void do_ida_request(request_queue_t *q); |
@@ -199,6 +200,7 @@ static struct block_device_operations ida_fops = { | |||
199 | .open = ida_open, | 200 | .open = ida_open, |
200 | .release = ida_release, | 201 | .release = ida_release, |
201 | .ioctl = ida_ioctl, | 202 | .ioctl = ida_ioctl, |
203 | .getgeo = ida_getgeo, | ||
202 | .revalidate_disk= ida_revalidate, | 204 | .revalidate_disk= ida_revalidate, |
203 | }; | 205 | }; |
204 | 206 | ||
@@ -1124,6 +1126,23 @@ static void ida_timer(unsigned long tdata) | |||
1124 | h->misc_tflags = 0; | 1126 | h->misc_tflags = 0; |
1125 | } | 1127 | } |
1126 | 1128 | ||
1129 | static int ida_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
1130 | { | ||
1131 | drv_info_t *drv = get_drv(bdev->bd_disk); | ||
1132 | |||
1133 | if (drv->cylinders) { | ||
1134 | geo->heads = drv->heads; | ||
1135 | geo->sectors = drv->sectors; | ||
1136 | geo->cylinders = drv->cylinders; | ||
1137 | } else { | ||
1138 | geo->heads = 0xff; | ||
1139 | geo->sectors = 0x3f; | ||
1140 | geo->cylinders = drv->nr_blks / (0xff*0x3f); | ||
1141 | } | ||
1142 | |||
1143 | return 0; | ||
1144 | } | ||
1145 | |||
1127 | /* | 1146 | /* |
1128 | * ida_ioctl does some miscellaneous stuff like reporting drive geometry, | 1147 | * ida_ioctl does some miscellaneous stuff like reporting drive geometry, |
1129 | * setting readahead and submitting commands from userspace to the controller. | 1148 | * setting readahead and submitting commands from userspace to the controller. |
@@ -1133,27 +1152,10 @@ static int ida_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, | |||
1133 | drv_info_t *drv = get_drv(inode->i_bdev->bd_disk); | 1152 | drv_info_t *drv = get_drv(inode->i_bdev->bd_disk); |
1134 | ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); | 1153 | ctlr_info_t *host = get_host(inode->i_bdev->bd_disk); |
1135 | int error; | 1154 | int error; |
1136 | int diskinfo[4]; | ||
1137 | struct hd_geometry __user *geo = (struct hd_geometry __user *)arg; | ||
1138 | ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg; | 1155 | ida_ioctl_t __user *io = (ida_ioctl_t __user *)arg; |
1139 | ida_ioctl_t *my_io; | 1156 | ida_ioctl_t *my_io; |
1140 | 1157 | ||
1141 | switch(cmd) { | 1158 | switch(cmd) { |
1142 | case HDIO_GETGEO: | ||
1143 | if (drv->cylinders) { | ||
1144 | diskinfo[0] = drv->heads; | ||
1145 | diskinfo[1] = drv->sectors; | ||
1146 | diskinfo[2] = drv->cylinders; | ||
1147 | } else { | ||
1148 | diskinfo[0] = 0xff; | ||
1149 | diskinfo[1] = 0x3f; | ||
1150 | diskinfo[2] = drv->nr_blks / (0xff*0x3f); | ||
1151 | } | ||
1152 | put_user(diskinfo[0], &geo->heads); | ||
1153 | put_user(diskinfo[1], &geo->sectors); | ||
1154 | put_user(diskinfo[2], &geo->cylinders); | ||
1155 | put_user(get_start_sect(inode->i_bdev), &geo->start); | ||
1156 | return 0; | ||
1157 | case IDAGETDRVINFO: | 1159 | case IDAGETDRVINFO: |
1158 | if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t))) | 1160 | if (copy_to_user(&io->c.drv, drv, sizeof(drv_info_t))) |
1159 | return -EFAULT; | 1161 | return -EFAULT; |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index a5b857c5c4b8..374621a512e0 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -479,7 +479,6 @@ static struct floppy_struct floppy_type[32] = { | |||
479 | { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ | 479 | { 3200,20,2,80,0,0x1C,0x00,0xCF,0x2C,"H1600" }, /* 31 1.6MB 3.5" */ |
480 | }; | 480 | }; |
481 | 481 | ||
482 | #define NUMBER(x) (sizeof(x) / sizeof(*(x))) | ||
483 | #define SECTSIZE (_FD_SECTSIZE(*floppy)) | 482 | #define SECTSIZE (_FD_SECTSIZE(*floppy)) |
484 | 483 | ||
485 | /* Auto-detection: Disk type used until the next media change occurs. */ | 484 | /* Auto-detection: Disk type used until the next media change occurs. */ |
@@ -3445,6 +3444,23 @@ static int get_floppy_geometry(int drive, int type, struct floppy_struct **g) | |||
3445 | return 0; | 3444 | return 0; |
3446 | } | 3445 | } |
3447 | 3446 | ||
3447 | static int fd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
3448 | { | ||
3449 | int drive = (long)bdev->bd_disk->private_data; | ||
3450 | int type = ITYPE(drive_state[drive].fd_device); | ||
3451 | struct floppy_struct *g; | ||
3452 | int ret; | ||
3453 | |||
3454 | ret = get_floppy_geometry(drive, type, &g); | ||
3455 | if (ret) | ||
3456 | return ret; | ||
3457 | |||
3458 | geo->heads = g->head; | ||
3459 | geo->sectors = g->sect; | ||
3460 | geo->cylinders = g->track; | ||
3461 | return 0; | ||
3462 | } | ||
3463 | |||
3448 | static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 3464 | static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, |
3449 | unsigned long param) | 3465 | unsigned long param) |
3450 | { | 3466 | { |
@@ -3474,23 +3490,6 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | |||
3474 | cmd = FDEJECT; | 3490 | cmd = FDEJECT; |
3475 | } | 3491 | } |
3476 | 3492 | ||
3477 | /* generic block device ioctls */ | ||
3478 | switch (cmd) { | ||
3479 | /* the following have been inspired by the corresponding | ||
3480 | * code for other block devices. */ | ||
3481 | struct floppy_struct *g; | ||
3482 | case HDIO_GETGEO: | ||
3483 | { | ||
3484 | struct hd_geometry loc; | ||
3485 | ECALL(get_floppy_geometry(drive, type, &g)); | ||
3486 | loc.heads = g->head; | ||
3487 | loc.sectors = g->sect; | ||
3488 | loc.cylinders = g->track; | ||
3489 | loc.start = 0; | ||
3490 | return _COPYOUT(loc); | ||
3491 | } | ||
3492 | } | ||
3493 | |||
3494 | /* convert the old style command into a new style command */ | 3493 | /* convert the old style command into a new style command */ |
3495 | if ((cmd & 0xff00) == 0x0200) { | 3494 | if ((cmd & 0xff00) == 0x0200) { |
3496 | ECALL(normalize_ioctl(&cmd, &size)); | 3495 | ECALL(normalize_ioctl(&cmd, &size)); |
@@ -3645,7 +3644,7 @@ static void __init config_types(void) | |||
3645 | const char *name = NULL; | 3644 | const char *name = NULL; |
3646 | static char temparea[32]; | 3645 | static char temparea[32]; |
3647 | 3646 | ||
3648 | if (type < NUMBER(default_drive_params)) { | 3647 | if (type < ARRAY_SIZE(default_drive_params)) { |
3649 | params = &default_drive_params[type].params; | 3648 | params = &default_drive_params[type].params; |
3650 | if (type) { | 3649 | if (type) { |
3651 | name = default_drive_params[type].name; | 3650 | name = default_drive_params[type].name; |
@@ -3938,6 +3937,7 @@ static struct block_device_operations floppy_fops = { | |||
3938 | .open = floppy_open, | 3937 | .open = floppy_open, |
3939 | .release = floppy_release, | 3938 | .release = floppy_release, |
3940 | .ioctl = fd_ioctl, | 3939 | .ioctl = fd_ioctl, |
3940 | .getgeo = fd_getgeo, | ||
3941 | .media_changed = check_floppy_change, | 3941 | .media_changed = check_floppy_change, |
3942 | .revalidate_disk = floppy_revalidate, | 3942 | .revalidate_disk = floppy_revalidate, |
3943 | }; | 3943 | }; |
@@ -3960,7 +3960,7 @@ static void __init register_devfs_entries(int drive) | |||
3960 | { | 3960 | { |
3961 | int base_minor = (drive < 4) ? drive : (124 + drive); | 3961 | int base_minor = (drive < 4) ? drive : (124 + drive); |
3962 | 3962 | ||
3963 | if (UDP->cmos < NUMBER(default_drive_params)) { | 3963 | if (UDP->cmos < ARRAY_SIZE(default_drive_params)) { |
3964 | int i = 0; | 3964 | int i = 0; |
3965 | do { | 3965 | do { |
3966 | int minor = base_minor + (table_sup[UDP->cmos][i] << 2); | 3966 | int minor = base_minor + (table_sup[UDP->cmos][i] << 2); |
@@ -4218,7 +4218,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) | |||
4218 | !(allowed_drive_mask & (1 << drive)) || | 4218 | !(allowed_drive_mask & (1 << drive)) || |
4219 | fdc_state[FDC(drive)].version == FDC_NONE) | 4219 | fdc_state[FDC(drive)].version == FDC_NONE) |
4220 | return NULL; | 4220 | return NULL; |
4221 | if (((*part >> 2) & 0x1f) >= NUMBER(floppy_type)) | 4221 | if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type)) |
4222 | return NULL; | 4222 | return NULL; |
4223 | *part = 0; | 4223 | *part = 0; |
4224 | return get_disk(disks[drive]); | 4224 | return get_disk(disks[drive]); |
@@ -4570,7 +4570,7 @@ static void unregister_devfs_entries(int drive) | |||
4570 | { | 4570 | { |
4571 | int i; | 4571 | int i; |
4572 | 4572 | ||
4573 | if (UDP->cmos < NUMBER(default_drive_params)) { | 4573 | if (UDP->cmos < ARRAY_SIZE(default_drive_params)) { |
4574 | i = 0; | 4574 | i = 0; |
4575 | do { | 4575 | do { |
4576 | devfs_remove("floppy/%d%s", drive, | 4576 | devfs_remove("floppy/%d%s", drive, |
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 33d6f237b2ed..6997d8e6bfb5 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -174,7 +174,6 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, | |||
174 | msg.msg_namelen = 0; | 174 | msg.msg_namelen = 0; |
175 | msg.msg_control = NULL; | 175 | msg.msg_control = NULL; |
176 | msg.msg_controllen = 0; | 176 | msg.msg_controllen = 0; |
177 | msg.msg_namelen = 0; | ||
178 | msg.msg_flags = msg_flags | MSG_NOSIGNAL; | 177 | msg.msg_flags = msg_flags | MSG_NOSIGNAL; |
179 | 178 | ||
180 | if (send) | 179 | if (send) |
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index fa49d62626ba..62d2464c12f2 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c | |||
@@ -747,32 +747,33 @@ static int pd_open(struct inode *inode, struct file *file) | |||
747 | return 0; | 747 | return 0; |
748 | } | 748 | } |
749 | 749 | ||
750 | static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
751 | { | ||
752 | struct pd_unit *disk = bdev->bd_disk->private_data; | ||
753 | |||
754 | if (disk->alt_geom) { | ||
755 | geo->heads = PD_LOG_HEADS; | ||
756 | geo->sectors = PD_LOG_SECTS; | ||
757 | geo->cylinders = disk->capacity / (geo->heads * geo->sectors); | ||
758 | } else { | ||
759 | geo->heads = disk->heads; | ||
760 | geo->sectors = disk->sectors; | ||
761 | geo->cylinders = disk->cylinders; | ||
762 | } | ||
763 | |||
764 | return 0; | ||
765 | } | ||
766 | |||
750 | static int pd_ioctl(struct inode *inode, struct file *file, | 767 | static int pd_ioctl(struct inode *inode, struct file *file, |
751 | unsigned int cmd, unsigned long arg) | 768 | unsigned int cmd, unsigned long arg) |
752 | { | 769 | { |
753 | struct pd_unit *disk = inode->i_bdev->bd_disk->private_data; | 770 | struct pd_unit *disk = inode->i_bdev->bd_disk->private_data; |
754 | struct hd_geometry __user *geo = (struct hd_geometry __user *) arg; | ||
755 | struct hd_geometry g; | ||
756 | 771 | ||
757 | switch (cmd) { | 772 | switch (cmd) { |
758 | case CDROMEJECT: | 773 | case CDROMEJECT: |
759 | if (disk->access == 1) | 774 | if (disk->access == 1) |
760 | pd_special_command(disk, pd_eject); | 775 | pd_special_command(disk, pd_eject); |
761 | return 0; | 776 | return 0; |
762 | case HDIO_GETGEO: | ||
763 | if (disk->alt_geom) { | ||
764 | g.heads = PD_LOG_HEADS; | ||
765 | g.sectors = PD_LOG_SECTS; | ||
766 | g.cylinders = disk->capacity / (g.heads * g.sectors); | ||
767 | } else { | ||
768 | g.heads = disk->heads; | ||
769 | g.sectors = disk->sectors; | ||
770 | g.cylinders = disk->cylinders; | ||
771 | } | ||
772 | g.start = get_start_sect(inode->i_bdev); | ||
773 | if (copy_to_user(geo, &g, sizeof(struct hd_geometry))) | ||
774 | return -EFAULT; | ||
775 | return 0; | ||
776 | default: | 777 | default: |
777 | return -EINVAL; | 778 | return -EINVAL; |
778 | } | 779 | } |
@@ -815,6 +816,7 @@ static struct block_device_operations pd_fops = { | |||
815 | .open = pd_open, | 816 | .open = pd_open, |
816 | .release = pd_release, | 817 | .release = pd_release, |
817 | .ioctl = pd_ioctl, | 818 | .ioctl = pd_ioctl, |
819 | .getgeo = pd_getgeo, | ||
818 | .media_changed = pd_check_media, | 820 | .media_changed = pd_check_media, |
819 | .revalidate_disk= pd_revalidate | 821 | .revalidate_disk= pd_revalidate |
820 | }; | 822 | }; |
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index e9746af29b9f..852b564e903a 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c | |||
@@ -205,6 +205,7 @@ static int pf_open(struct inode *inode, struct file *file); | |||
205 | static void do_pf_request(request_queue_t * q); | 205 | static void do_pf_request(request_queue_t * q); |
206 | static int pf_ioctl(struct inode *inode, struct file *file, | 206 | static int pf_ioctl(struct inode *inode, struct file *file, |
207 | unsigned int cmd, unsigned long arg); | 207 | unsigned int cmd, unsigned long arg); |
208 | static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo); | ||
208 | 209 | ||
209 | static int pf_release(struct inode *inode, struct file *file); | 210 | static int pf_release(struct inode *inode, struct file *file); |
210 | 211 | ||
@@ -266,6 +267,7 @@ static struct block_device_operations pf_fops = { | |||
266 | .open = pf_open, | 267 | .open = pf_open, |
267 | .release = pf_release, | 268 | .release = pf_release, |
268 | .ioctl = pf_ioctl, | 269 | .ioctl = pf_ioctl, |
270 | .getgeo = pf_getgeo, | ||
269 | .media_changed = pf_check_media, | 271 | .media_changed = pf_check_media, |
270 | }; | 272 | }; |
271 | 273 | ||
@@ -313,34 +315,34 @@ static int pf_open(struct inode *inode, struct file *file) | |||
313 | return 0; | 315 | return 0; |
314 | } | 316 | } |
315 | 317 | ||
316 | static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 318 | static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
317 | { | 319 | { |
318 | struct pf_unit *pf = inode->i_bdev->bd_disk->private_data; | 320 | struct pf_unit *pf = bdev->bd_disk->private_data; |
319 | struct hd_geometry __user *geo = (struct hd_geometry __user *) arg; | 321 | sector_t capacity = get_capacity(pf->disk); |
320 | struct hd_geometry g; | 322 | |
321 | sector_t capacity; | ||
322 | |||
323 | if (cmd == CDROMEJECT) { | ||
324 | if (pf->access == 1) { | ||
325 | pf_eject(pf); | ||
326 | return 0; | ||
327 | } | ||
328 | return -EBUSY; | ||
329 | } | ||
330 | if (cmd != HDIO_GETGEO) | ||
331 | return -EINVAL; | ||
332 | capacity = get_capacity(pf->disk); | ||
333 | if (capacity < PF_FD_MAX) { | 323 | if (capacity < PF_FD_MAX) { |
334 | g.cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT); | 324 | geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT); |
335 | g.heads = PF_FD_HDS; | 325 | geo->heads = PF_FD_HDS; |
336 | g.sectors = PF_FD_SPT; | 326 | geo->sectors = PF_FD_SPT; |
337 | } else { | 327 | } else { |
338 | g.cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT); | 328 | geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT); |
339 | g.heads = PF_HD_HDS; | 329 | geo->heads = PF_HD_HDS; |
340 | g.sectors = PF_HD_SPT; | 330 | geo->sectors = PF_HD_SPT; |
341 | } | 331 | } |
342 | if (copy_to_user(geo, &g, sizeof(g))) | 332 | |
343 | return -EFAULT; | 333 | return 0; |
334 | } | ||
335 | |||
336 | static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
337 | { | ||
338 | struct pf_unit *pf = inode->i_bdev->bd_disk->private_data; | ||
339 | |||
340 | if (cmd != CDROMEJECT) | ||
341 | return -EINVAL; | ||
342 | |||
343 | if (pf->access != 1) | ||
344 | return -EBUSY; | ||
345 | pf_eject(pf); | ||
344 | return 0; | 346 | return 0; |
345 | } | 347 | } |
346 | 348 | ||
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index c0233efabeba..51b7a5c5b77a 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -1955,9 +1955,12 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) | |||
1955 | if ((ret = blkdev_get(pd->bdev, FMODE_READ, O_RDONLY))) | 1955 | if ((ret = blkdev_get(pd->bdev, FMODE_READ, O_RDONLY))) |
1956 | goto out; | 1956 | goto out; |
1957 | 1957 | ||
1958 | if ((ret = bd_claim(pd->bdev, pd))) | ||
1959 | goto out_putdev; | ||
1960 | |||
1958 | if ((ret = pkt_get_last_written(pd, &lba))) { | 1961 | if ((ret = pkt_get_last_written(pd, &lba))) { |
1959 | printk("pktcdvd: pkt_get_last_written failed\n"); | 1962 | printk("pktcdvd: pkt_get_last_written failed\n"); |
1960 | goto out_putdev; | 1963 | goto out_unclaim; |
1961 | } | 1964 | } |
1962 | 1965 | ||
1963 | set_capacity(pd->disk, lba << 2); | 1966 | set_capacity(pd->disk, lba << 2); |
@@ -1967,7 +1970,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) | |||
1967 | q = bdev_get_queue(pd->bdev); | 1970 | q = bdev_get_queue(pd->bdev); |
1968 | if (write) { | 1971 | if (write) { |
1969 | if ((ret = pkt_open_write(pd))) | 1972 | if ((ret = pkt_open_write(pd))) |
1970 | goto out_putdev; | 1973 | goto out_unclaim; |
1971 | /* | 1974 | /* |
1972 | * Some CDRW drives can not handle writes larger than one packet, | 1975 | * Some CDRW drives can not handle writes larger than one packet, |
1973 | * even if the size is a multiple of the packet size. | 1976 | * even if the size is a multiple of the packet size. |
@@ -1982,13 +1985,15 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write) | |||
1982 | } | 1985 | } |
1983 | 1986 | ||
1984 | if ((ret = pkt_set_segment_merging(pd, q))) | 1987 | if ((ret = pkt_set_segment_merging(pd, q))) |
1985 | goto out_putdev; | 1988 | goto out_unclaim; |
1986 | 1989 | ||
1987 | if (write) | 1990 | if (write) |
1988 | printk("pktcdvd: %lukB available on disc\n", lba << 1); | 1991 | printk("pktcdvd: %lukB available on disc\n", lba << 1); |
1989 | 1992 | ||
1990 | return 0; | 1993 | return 0; |
1991 | 1994 | ||
1995 | out_unclaim: | ||
1996 | bd_release(pd->bdev); | ||
1992 | out_putdev: | 1997 | out_putdev: |
1993 | blkdev_put(pd->bdev); | 1998 | blkdev_put(pd->bdev); |
1994 | out: | 1999 | out: |
@@ -2007,6 +2012,7 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush) | |||
2007 | pkt_lock_door(pd, 0); | 2012 | pkt_lock_door(pd, 0); |
2008 | 2013 | ||
2009 | pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); | 2014 | pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); |
2015 | bd_release(pd->bdev); | ||
2010 | blkdev_put(pd->bdev); | 2016 | blkdev_put(pd->bdev); |
2011 | } | 2017 | } |
2012 | 2018 | ||
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c index 29d1518be72a..43415f69839f 100644 --- a/drivers/block/ps2esdi.c +++ b/drivers/block/ps2esdi.c | |||
@@ -81,8 +81,7 @@ static void (*current_int_handler) (u_int) = NULL; | |||
81 | static void ps2esdi_normal_interrupt_handler(u_int); | 81 | static void ps2esdi_normal_interrupt_handler(u_int); |
82 | static void ps2esdi_initial_reset_int_handler(u_int); | 82 | static void ps2esdi_initial_reset_int_handler(u_int); |
83 | static void ps2esdi_geometry_int_handler(u_int); | 83 | static void ps2esdi_geometry_int_handler(u_int); |
84 | static int ps2esdi_ioctl(struct inode *inode, struct file *file, | 84 | static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo); |
85 | u_int cmd, u_long arg); | ||
86 | 85 | ||
87 | static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); | 86 | static int ps2esdi_read_status_words(int num_words, int max_words, u_short * buffer); |
88 | 87 | ||
@@ -132,7 +131,7 @@ static struct ps2esdi_i_struct ps2esdi_info[MAX_HD] = | |||
132 | static struct block_device_operations ps2esdi_fops = | 131 | static struct block_device_operations ps2esdi_fops = |
133 | { | 132 | { |
134 | .owner = THIS_MODULE, | 133 | .owner = THIS_MODULE, |
135 | .ioctl = ps2esdi_ioctl, | 134 | .getgeo = ps2esdi_getgeo, |
136 | }; | 135 | }; |
137 | 136 | ||
138 | static struct gendisk *ps2esdi_gendisk[2]; | 137 | static struct gendisk *ps2esdi_gendisk[2]; |
@@ -1058,21 +1057,13 @@ static void dump_cmd_complete_status(u_int int_ret_code) | |||
1058 | 1057 | ||
1059 | } | 1058 | } |
1060 | 1059 | ||
1061 | static int ps2esdi_ioctl(struct inode *inode, | 1060 | static int ps2esdi_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
1062 | struct file *file, u_int cmd, u_long arg) | ||
1063 | { | 1061 | { |
1064 | struct ps2esdi_i_struct *p = inode->i_bdev->bd_disk->private_data; | 1062 | struct ps2esdi_i_struct *p = bdev->bd_disk->private_data; |
1065 | struct ps2esdi_geometry geom; | 1063 | |
1066 | 1064 | geo->heads = p->head; | |
1067 | if (cmd != HDIO_GETGEO) | 1065 | geo->sectors = p->sect; |
1068 | return -EINVAL; | 1066 | geo->cylinders = p->cyl; |
1069 | memset(&geom, 0, sizeof(geom)); | ||
1070 | geom.heads = p->head; | ||
1071 | geom.sectors = p->sect; | ||
1072 | geom.cylinders = p->cyl; | ||
1073 | geom.start = get_start_sect(inode->i_bdev); | ||
1074 | if (copy_to_user((void __user *)arg, &geom, sizeof(geom))) | ||
1075 | return -EFAULT; | ||
1076 | return 0; | 1067 | return 0; |
1077 | } | 1068 | } |
1078 | 1069 | ||
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 9251f4131b53..c0cdc182a8b0 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c | |||
@@ -407,8 +407,7 @@ struct carm_array_info { | |||
407 | 407 | ||
408 | static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); | 408 | static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); |
409 | static void carm_remove_one (struct pci_dev *pdev); | 409 | static void carm_remove_one (struct pci_dev *pdev); |
410 | static int carm_bdev_ioctl(struct inode *ino, struct file *fil, | 410 | static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo); |
411 | unsigned int cmd, unsigned long arg); | ||
412 | 411 | ||
413 | static struct pci_device_id carm_pci_tbl[] = { | 412 | static struct pci_device_id carm_pci_tbl[] = { |
414 | { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, | 413 | { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, |
@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = { | |||
426 | 425 | ||
427 | static struct block_device_operations carm_bd_ops = { | 426 | static struct block_device_operations carm_bd_ops = { |
428 | .owner = THIS_MODULE, | 427 | .owner = THIS_MODULE, |
429 | .ioctl = carm_bdev_ioctl, | 428 | .getgeo = carm_bdev_getgeo, |
430 | }; | 429 | }; |
431 | 430 | ||
432 | static unsigned int carm_host_id; | 431 | static unsigned int carm_host_id; |
@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc; | |||
434 | 433 | ||
435 | 434 | ||
436 | 435 | ||
437 | static int carm_bdev_ioctl(struct inode *ino, struct file *fil, | 436 | static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
438 | unsigned int cmd, unsigned long arg) | ||
439 | { | 437 | { |
440 | void __user *usermem = (void __user *) arg; | 438 | struct carm_port *port = bdev->bd_disk->private_data; |
441 | struct carm_port *port = ino->i_bdev->bd_disk->private_data; | ||
442 | struct hd_geometry geom; | ||
443 | 439 | ||
444 | switch (cmd) { | 440 | geo->heads = (u8) port->dev_geom_head; |
445 | case HDIO_GETGEO: | 441 | geo->sectors = (u8) port->dev_geom_sect; |
446 | if (!usermem) | 442 | geo->cylinders = port->dev_geom_cyl; |
447 | return -EINVAL; | 443 | return 0; |
448 | |||
449 | geom.heads = (u8) port->dev_geom_head; | ||
450 | geom.sectors = (u8) port->dev_geom_sect; | ||
451 | geom.cylinders = port->dev_geom_cyl; | ||
452 | geom.start = get_start_sect(ino->i_bdev); | ||
453 | |||
454 | if (copy_to_user(usermem, &geom, sizeof(geom))) | ||
455 | return -EFAULT; | ||
456 | return 0; | ||
457 | |||
458 | default: | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | return -EOPNOTSUPP; | ||
463 | } | 444 | } |
464 | 445 | ||
465 | static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE }; | 446 | static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE }; |
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 0f48301342da..15299e7a1ade 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
@@ -809,34 +809,23 @@ static int mm_revalidate(struct gendisk *disk) | |||
809 | set_capacity(disk, card->mm_size << 1); | 809 | set_capacity(disk, card->mm_size << 1); |
810 | return 0; | 810 | return 0; |
811 | } | 811 | } |
812 | /* | 812 | |
813 | ----------------------------------------------------------------------------------- | 813 | static int mm_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
814 | -- mm_ioctl | ||
815 | ----------------------------------------------------------------------------------- | ||
816 | */ | ||
817 | static int mm_ioctl(struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) | ||
818 | { | 814 | { |
819 | if (cmd == HDIO_GETGEO) { | 815 | struct cardinfo *card = bdev->bd_disk->private_data; |
820 | struct cardinfo *card = i->i_bdev->bd_disk->private_data; | 816 | int size = card->mm_size * (1024 / MM_HARDSECT); |
821 | int size = card->mm_size * (1024 / MM_HARDSECT); | ||
822 | struct hd_geometry geo; | ||
823 | /* | ||
824 | * get geometry: we have to fake one... trim the size to a | ||
825 | * multiple of 2048 (1M): tell we have 32 sectors, 64 heads, | ||
826 | * whatever cylinders. | ||
827 | */ | ||
828 | geo.heads = 64; | ||
829 | geo.sectors = 32; | ||
830 | geo.start = get_start_sect(i->i_bdev); | ||
831 | geo.cylinders = size / (geo.heads * geo.sectors); | ||
832 | |||
833 | if (copy_to_user((void __user *) arg, &geo, sizeof(geo))) | ||
834 | return -EFAULT; | ||
835 | return 0; | ||
836 | } | ||
837 | 817 | ||
838 | return -EINVAL; | 818 | /* |
819 | * get geometry: we have to fake one... trim the size to a | ||
820 | * multiple of 2048 (1M): tell we have 32 sectors, 64 heads, | ||
821 | * whatever cylinders. | ||
822 | */ | ||
823 | geo->heads = 64; | ||
824 | geo->sectors = 32; | ||
825 | geo->cylinders = size / (geo->heads * geo->sectors); | ||
826 | return 0; | ||
839 | } | 827 | } |
828 | |||
840 | /* | 829 | /* |
841 | ----------------------------------------------------------------------------------- | 830 | ----------------------------------------------------------------------------------- |
842 | -- mm_check_change | 831 | -- mm_check_change |
@@ -855,7 +844,7 @@ static int mm_check_change(struct gendisk *disk) | |||
855 | */ | 844 | */ |
856 | static struct block_device_operations mm_fops = { | 845 | static struct block_device_operations mm_fops = { |
857 | .owner = THIS_MODULE, | 846 | .owner = THIS_MODULE, |
858 | .ioctl = mm_ioctl, | 847 | .getgeo = mm_getgeo, |
859 | .revalidate_disk= mm_revalidate, | 848 | .revalidate_disk= mm_revalidate, |
860 | .media_changed = mm_check_change, | 849 | .media_changed = mm_check_change, |
861 | }; | 850 | }; |
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 063f0304a163..d1aaf31bd97e 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -247,43 +247,17 @@ static int viodasd_release(struct inode *ino, struct file *fil) | |||
247 | 247 | ||
248 | /* External ioctl entry point. | 248 | /* External ioctl entry point. |
249 | */ | 249 | */ |
250 | static int viodasd_ioctl(struct inode *ino, struct file *fil, | 250 | static int viodasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
251 | unsigned int cmd, unsigned long arg) | ||
252 | { | 251 | { |
253 | unsigned char sectors; | 252 | struct gendisk *disk = bdev->bd_disk; |
254 | unsigned char heads; | 253 | struct viodasd_device *d = disk->private_data; |
255 | unsigned short cylinders; | ||
256 | struct hd_geometry *geo; | ||
257 | struct gendisk *gendisk; | ||
258 | struct viodasd_device *d; | ||
259 | 254 | ||
260 | switch (cmd) { | 255 | geo->sectors = d->sectors ? d->sectors : 0; |
261 | case HDIO_GETGEO: | 256 | geo->heads = d->tracks ? d->tracks : 64; |
262 | geo = (struct hd_geometry *)arg; | 257 | geo->cylinders = d->cylinders ? d->cylinders : |
263 | if (geo == NULL) | 258 | get_capacity(disk) / (geo->cylinders * geo->heads); |
264 | return -EINVAL; | ||
265 | if (!access_ok(VERIFY_WRITE, geo, sizeof(*geo))) | ||
266 | return -EFAULT; | ||
267 | gendisk = ino->i_bdev->bd_disk; | ||
268 | d = gendisk->private_data; | ||
269 | sectors = d->sectors; | ||
270 | if (sectors == 0) | ||
271 | sectors = 32; | ||
272 | heads = d->tracks; | ||
273 | if (heads == 0) | ||
274 | heads = 64; | ||
275 | cylinders = d->cylinders; | ||
276 | if (cylinders == 0) | ||
277 | cylinders = get_capacity(gendisk) / (sectors * heads); | ||
278 | if (__put_user(sectors, &geo->sectors) || | ||
279 | __put_user(heads, &geo->heads) || | ||
280 | __put_user(cylinders, &geo->cylinders) || | ||
281 | __put_user(get_start_sect(ino->i_bdev), &geo->start)) | ||
282 | return -EFAULT; | ||
283 | return 0; | ||
284 | } | ||
285 | 259 | ||
286 | return -EINVAL; | 260 | return 0; |
287 | } | 261 | } |
288 | 262 | ||
289 | /* | 263 | /* |
@@ -293,7 +267,7 @@ static struct block_device_operations viodasd_fops = { | |||
293 | .owner = THIS_MODULE, | 267 | .owner = THIS_MODULE, |
294 | .open = viodasd_open, | 268 | .open = viodasd_open, |
295 | .release = viodasd_release, | 269 | .release = viodasd_release, |
296 | .ioctl = viodasd_ioctl, | 270 | .getgeo = viodasd_getgeo, |
297 | }; | 271 | }; |
298 | 272 | ||
299 | /* | 273 | /* |
diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 68b6d7b154cf..cbce7c5e9445 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c | |||
@@ -128,9 +128,12 @@ static DEFINE_SPINLOCK(xd_lock); | |||
128 | 128 | ||
129 | static struct gendisk *xd_gendisk[2]; | 129 | static struct gendisk *xd_gendisk[2]; |
130 | 130 | ||
131 | static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo); | ||
132 | |||
131 | static struct block_device_operations xd_fops = { | 133 | static struct block_device_operations xd_fops = { |
132 | .owner = THIS_MODULE, | 134 | .owner = THIS_MODULE, |
133 | .ioctl = xd_ioctl, | 135 | .ioctl = xd_ioctl, |
136 | .getgeo = xd_getgeo, | ||
134 | }; | 137 | }; |
135 | static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int); | 138 | static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int); |
136 | static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors; | 139 | static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors; |
@@ -276,11 +279,11 @@ static u_char __init xd_detect (u_char *controller, unsigned int *address) | |||
276 | return(1); | 279 | return(1); |
277 | } | 280 | } |
278 | 281 | ||
279 | for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])); i++) { | 282 | for (i = 0; i < ARRAY_SIZE(xd_bases); i++) { |
280 | void __iomem *p = ioremap(xd_bases[i], 0x2000); | 283 | void __iomem *p = ioremap(xd_bases[i], 0x2000); |
281 | if (!p) | 284 | if (!p) |
282 | continue; | 285 | continue; |
283 | for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])); j++) { | 286 | for (j = 1; j < ARRAY_SIZE(xd_sigs); j++) { |
284 | const char *s = xd_sigs[j].string; | 287 | const char *s = xd_sigs[j].string; |
285 | if (check_signature(p + xd_sigs[j].offset, s, strlen(s))) { | 288 | if (check_signature(p + xd_sigs[j].offset, s, strlen(s))) { |
286 | *controller = j; | 289 | *controller = j; |
@@ -330,22 +333,20 @@ static void do_xd_request (request_queue_t * q) | |||
330 | } | 333 | } |
331 | } | 334 | } |
332 | 335 | ||
336 | static int xd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
337 | { | ||
338 | XD_INFO *p = bdev->bd_disk->private_data; | ||
339 | |||
340 | geo->heads = p->heads; | ||
341 | geo->sectors = p->sectors; | ||
342 | geo->cylinders = p->cylinders; | ||
343 | return 0; | ||
344 | } | ||
345 | |||
333 | /* xd_ioctl: handle device ioctl's */ | 346 | /* xd_ioctl: handle device ioctl's */ |
334 | static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) | 347 | static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg) |
335 | { | 348 | { |
336 | XD_INFO *p = inode->i_bdev->bd_disk->private_data; | ||
337 | |||
338 | switch (cmd) { | 349 | switch (cmd) { |
339 | case HDIO_GETGEO: | ||
340 | { | ||
341 | struct hd_geometry g; | ||
342 | struct hd_geometry __user *geom= (void __user *)arg; | ||
343 | g.heads = p->heads; | ||
344 | g.sectors = p->sectors; | ||
345 | g.cylinders = p->cylinders; | ||
346 | g.start = get_start_sect(inode->i_bdev); | ||
347 | return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0; | ||
348 | } | ||
349 | case HDIO_SET_DMA: | 350 | case HDIO_SET_DMA: |
350 | if (!capable(CAP_SYS_ADMIN)) return -EACCES; | 351 | if (!capable(CAP_SYS_ADMIN)) return -EACCES; |
351 | if (xdc_busy) return -EBUSY; | 352 | if (xdc_busy) return -EBUSY; |
@@ -1017,7 +1018,7 @@ static void __init do_xd_setup (int *integers) | |||
1017 | case 2: if ((integers[2] > 0) && (integers[2] < 16)) | 1018 | case 2: if ((integers[2] > 0) && (integers[2] < 16)) |
1018 | xd_irq = integers[2]; | 1019 | xd_irq = integers[2]; |
1019 | case 1: xd_override = 1; | 1020 | case 1: xd_override = 1; |
1020 | if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0])))) | 1021 | if ((integers[1] >= 0) && (integers[1] < ARRAY_SIZE(xd_sigs))) |
1021 | xd_type = integers[1]; | 1022 | xd_type = integers[1]; |
1022 | case 0: break; | 1023 | case 0: break; |
1023 | default:printk("xd: too many parameters for xd\n"); | 1024 | default:printk("xd: too many parameters for xd\n"); |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 5ebd06b1b4ca..dd7e6901c575 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -220,6 +220,14 @@ config SYNCLINKMP | |||
220 | The module will be called synclinkmp. If you want to do that, say M | 220 | The module will be called synclinkmp. If you want to do that, say M |
221 | here. | 221 | here. |
222 | 222 | ||
223 | config SYNCLINK_GT | ||
224 | tristate "SyncLink GT/AC support" | ||
225 | depends on SERIAL_NONSTANDARD | ||
226 | help | ||
227 | Support for SyncLink GT and SyncLink AC families of | ||
228 | synchronous and asynchronous serial adapters | ||
229 | manufactured by Microgate Systems, Ltd. (www.microgate.com) | ||
230 | |||
223 | config N_HDLC | 231 | config N_HDLC |
224 | tristate "HDLC line discipline support" | 232 | tristate "HDLC line discipline support" |
225 | depends on SERIAL_NONSTANDARD | 233 | depends on SERIAL_NONSTANDARD |
@@ -687,7 +695,7 @@ config NVRAM | |||
687 | 695 | ||
688 | config RTC | 696 | config RTC |
689 | tristate "Enhanced Real Time Clock Support" | 697 | tristate "Enhanced Real Time Clock Support" |
690 | depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) | 698 | depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV |
691 | ---help--- | 699 | ---help--- |
692 | If you say Y here and create a character special file /dev/rtc with | 700 | If you say Y here and create a character special file /dev/rtc with |
693 | major number 10 and minor number 135 using mknod ("man mknod"), you | 701 | major number 10 and minor number 135 using mknod ("man mknod"), you |
@@ -735,7 +743,7 @@ config SGI_IP27_RTC | |||
735 | 743 | ||
736 | config GEN_RTC | 744 | config GEN_RTC |
737 | tristate "Generic /dev/rtc emulation" | 745 | tristate "Generic /dev/rtc emulation" |
738 | depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC | 746 | depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV |
739 | ---help--- | 747 | ---help--- |
740 | If you say Y here and create a character special file /dev/rtc with | 748 | If you say Y here and create a character special file /dev/rtc with |
741 | major number 10 and minor number 135 using mknod ("man mknod"), you | 749 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 4aeae687e88a..d973d14d8f7f 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_RISCOM8) += riscom8.o | |||
36 | obj-$(CONFIG_ISI) += isicom.o | 36 | obj-$(CONFIG_ISI) += isicom.o |
37 | obj-$(CONFIG_SYNCLINK) += synclink.o | 37 | obj-$(CONFIG_SYNCLINK) += synclink.o |
38 | obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o | 38 | obj-$(CONFIG_SYNCLINKMP) += synclinkmp.o |
39 | obj-$(CONFIG_SYNCLINK_GT) += synclink_gt.o | ||
39 | obj-$(CONFIG_N_HDLC) += n_hdlc.o | 40 | obj-$(CONFIG_N_HDLC) += n_hdlc.o |
40 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o | 41 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o |
41 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 42 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 3f8f7fa6b0ff..268f78d926d3 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/string.h> | 8 | #include <linux/string.h> |
9 | #include <linux/slab.h> | 9 | #include <linux/slab.h> |
10 | #include <linux/jiffies.h> | ||
10 | #include <linux/agp_backend.h> | 11 | #include <linux/agp_backend.h> |
11 | #include "agp.h" | 12 | #include "agp.h" |
12 | 13 | ||
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c index 49769f59ea1b..b3bc2e37e616 100644 --- a/drivers/char/hw_random.c +++ b/drivers/char/hw_random.c | |||
@@ -169,6 +169,7 @@ static struct pci_device_id rng_pci_tbl[] = { | |||
169 | 169 | ||
170 | { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, | 170 | { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, |
171 | { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, | 171 | { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, |
172 | { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, | ||
172 | { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, | 173 | { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, |
173 | { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, | 174 | { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, |
174 | { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, | 175 | { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 91dd669273e0..5b2d18035073 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -101,6 +101,11 @@ static inline int valid_phys_addr_range(unsigned long addr, size_t *count) | |||
101 | 101 | ||
102 | return 1; | 102 | return 1; |
103 | } | 103 | } |
104 | |||
105 | static inline int valid_mmap_phys_addr_range(unsigned long addr, size_t *size) | ||
106 | { | ||
107 | return 1; | ||
108 | } | ||
104 | #endif | 109 | #endif |
105 | 110 | ||
106 | /* | 111 | /* |
@@ -228,26 +233,36 @@ static ssize_t write_mem(struct file * file, const char __user * buf, | |||
228 | return written; | 233 | return written; |
229 | } | 234 | } |
230 | 235 | ||
236 | #ifndef __HAVE_PHYS_MEM_ACCESS_PROT | ||
237 | static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
238 | unsigned long size, pgprot_t vma_prot) | ||
239 | { | ||
240 | #ifdef pgprot_noncached | ||
241 | unsigned long offset = pfn << PAGE_SHIFT; | ||
242 | |||
243 | if (uncached_access(file, offset)) | ||
244 | return pgprot_noncached(vma_prot); | ||
245 | #endif | ||
246 | return vma_prot; | ||
247 | } | ||
248 | #endif | ||
249 | |||
231 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) | 250 | static int mmap_mem(struct file * file, struct vm_area_struct * vma) |
232 | { | 251 | { |
233 | #if defined(__HAVE_PHYS_MEM_ACCESS_PROT) | 252 | size_t size = vma->vm_end - vma->vm_start; |
253 | |||
254 | if (!valid_mmap_phys_addr_range(vma->vm_pgoff << PAGE_SHIFT, &size)) | ||
255 | return -EINVAL; | ||
256 | |||
234 | vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, | 257 | vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, |
235 | vma->vm_end - vma->vm_start, | 258 | size, |
236 | vma->vm_page_prot); | 259 | vma->vm_page_prot); |
237 | #elif defined(pgprot_noncached) | ||
238 | unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; | ||
239 | int uncached; | ||
240 | |||
241 | uncached = uncached_access(file, offset); | ||
242 | if (uncached) | ||
243 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
244 | #endif | ||
245 | 260 | ||
246 | /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ | 261 | /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ |
247 | if (remap_pfn_range(vma, | 262 | if (remap_pfn_range(vma, |
248 | vma->vm_start, | 263 | vma->vm_start, |
249 | vma->vm_pgoff, | 264 | vma->vm_pgoff, |
250 | vma->vm_end-vma->vm_start, | 265 | size, |
251 | vma->vm_page_prot)) | 266 | vma->vm_page_prot)) |
252 | return -EAGAIN; | 267 | return -EAGAIN; |
253 | return 0; | 268 | return 0; |
@@ -817,7 +832,7 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, | |||
817 | size_t count, loff_t *ppos) | 832 | size_t count, loff_t *ppos) |
818 | { | 833 | { |
819 | char *tmp; | 834 | char *tmp; |
820 | int ret; | 835 | ssize_t ret; |
821 | 836 | ||
822 | tmp = kmalloc(count + 1, GFP_KERNEL); | 837 | tmp = kmalloc(count + 1, GFP_KERNEL); |
823 | if (tmp == NULL) | 838 | if (tmp == NULL) |
@@ -826,6 +841,9 @@ static ssize_t kmsg_write(struct file * file, const char __user * buf, | |||
826 | if (!copy_from_user(tmp, buf, count)) { | 841 | if (!copy_from_user(tmp, buf, count)) { |
827 | tmp[count] = 0; | 842 | tmp[count] = 0; |
828 | ret = printk("%s", tmp); | 843 | ret = printk("%s", tmp); |
844 | if (ret > count) | ||
845 | /* printk can add a prefix */ | ||
846 | ret = count; | ||
829 | } | 847 | } |
830 | kfree(tmp); | 848 | kfree(tmp); |
831 | return ret; | 849 | return ret; |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 51a07370e636..f8dd8527c6aa 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -471,7 +471,6 @@ struct sonypi_keypress { | |||
471 | 471 | ||
472 | static struct sonypi_device { | 472 | static struct sonypi_device { |
473 | struct pci_dev *dev; | 473 | struct pci_dev *dev; |
474 | struct platform_device *pdev; | ||
475 | u16 irq; | 474 | u16 irq; |
476 | u16 bits; | 475 | u16 bits; |
477 | u16 ioport1; | 476 | u16 ioport1; |
@@ -511,6 +510,11 @@ static struct sonypi_device { | |||
511 | #define SONYPI_ACPI_ACTIVE 0 | 510 | #define SONYPI_ACPI_ACTIVE 0 |
512 | #endif /* CONFIG_ACPI */ | 511 | #endif /* CONFIG_ACPI */ |
513 | 512 | ||
513 | #ifdef CONFIG_ACPI | ||
514 | static struct acpi_device *sonypi_acpi_device; | ||
515 | static int acpi_enabled; | ||
516 | #endif | ||
517 | |||
514 | static int sonypi_ec_write(u8 addr, u8 value) | 518 | static int sonypi_ec_write(u8 addr, u8 value) |
515 | { | 519 | { |
516 | #ifdef CONFIG_ACPI_EC | 520 | #ifdef CONFIG_ACPI_EC |
@@ -864,6 +868,11 @@ found: | |||
864 | if (useinput) | 868 | if (useinput) |
865 | sonypi_report_input_event(event); | 869 | sonypi_report_input_event(event); |
866 | 870 | ||
871 | #ifdef CONFIG_ACPI | ||
872 | if (acpi_enabled) | ||
873 | acpi_bus_generate_event(sonypi_acpi_device, 1, event); | ||
874 | #endif | ||
875 | |||
867 | kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); | 876 | kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); |
868 | kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); | 877 | kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); |
869 | wake_up_interruptible(&sonypi_device.fifo_proc_list); | 878 | wake_up_interruptible(&sonypi_device.fifo_proc_list); |
@@ -1165,45 +1174,38 @@ static int sonypi_disable(void) | |||
1165 | return 0; | 1174 | return 0; |
1166 | } | 1175 | } |
1167 | 1176 | ||
1168 | #ifdef CONFIG_PM | 1177 | #ifdef CONFIG_ACPI |
1169 | static int old_camera_power; | 1178 | static int sonypi_acpi_add(struct acpi_device *device) |
1170 | |||
1171 | static int sonypi_suspend(struct platform_device *dev, pm_message_t state) | ||
1172 | { | 1179 | { |
1173 | old_camera_power = sonypi_device.camera_power; | 1180 | sonypi_acpi_device = device; |
1174 | sonypi_disable(); | 1181 | strcpy(acpi_device_name(device), "Sony laptop hotkeys"); |
1175 | 1182 | strcpy(acpi_device_class(device), "sony/hotkey"); | |
1176 | return 0; | 1183 | return 0; |
1177 | } | 1184 | } |
1178 | 1185 | ||
1179 | static int sonypi_resume(struct platform_device *dev) | 1186 | static int sonypi_acpi_remove(struct acpi_device *device, int type) |
1180 | { | 1187 | { |
1181 | sonypi_enable(old_camera_power); | 1188 | sonypi_acpi_device = NULL; |
1182 | return 0; | 1189 | return 0; |
1183 | } | 1190 | } |
1184 | #endif | ||
1185 | |||
1186 | static void sonypi_shutdown(struct platform_device *dev) | ||
1187 | { | ||
1188 | sonypi_disable(); | ||
1189 | } | ||
1190 | 1191 | ||
1191 | static struct platform_driver sonypi_driver = { | 1192 | static struct acpi_driver sonypi_acpi_driver = { |
1192 | #ifdef CONFIG_PM | 1193 | .name = "sonypi", |
1193 | .suspend = sonypi_suspend, | 1194 | .class = "hkey", |
1194 | .resume = sonypi_resume, | 1195 | .ids = "SNY6001", |
1195 | #endif | 1196 | .ops = { |
1196 | .shutdown = sonypi_shutdown, | 1197 | .add = sonypi_acpi_add, |
1197 | .driver = { | 1198 | .remove = sonypi_acpi_remove, |
1198 | .name = "sonypi", | ||
1199 | }, | 1199 | }, |
1200 | }; | 1200 | }; |
1201 | #endif | ||
1201 | 1202 | ||
1202 | static int __devinit sonypi_create_input_devices(void) | 1203 | static int __devinit sonypi_create_input_devices(void) |
1203 | { | 1204 | { |
1204 | struct input_dev *jog_dev; | 1205 | struct input_dev *jog_dev; |
1205 | struct input_dev *key_dev; | 1206 | struct input_dev *key_dev; |
1206 | int i; | 1207 | int i; |
1208 | int error; | ||
1207 | 1209 | ||
1208 | sonypi_device.input_jog_dev = jog_dev = input_allocate_device(); | 1210 | sonypi_device.input_jog_dev = jog_dev = input_allocate_device(); |
1209 | if (!jog_dev) | 1211 | if (!jog_dev) |
@@ -1219,9 +1221,8 @@ static int __devinit sonypi_create_input_devices(void) | |||
1219 | 1221 | ||
1220 | sonypi_device.input_key_dev = key_dev = input_allocate_device(); | 1222 | sonypi_device.input_key_dev = key_dev = input_allocate_device(); |
1221 | if (!key_dev) { | 1223 | if (!key_dev) { |
1222 | input_free_device(jog_dev); | 1224 | error = -ENOMEM; |
1223 | sonypi_device.input_jog_dev = NULL; | 1225 | goto err_free_jogdev; |
1224 | return -ENOMEM; | ||
1225 | } | 1226 | } |
1226 | 1227 | ||
1227 | key_dev->name = "Sony Vaio Keys"; | 1228 | key_dev->name = "Sony Vaio Keys"; |
@@ -1234,56 +1235,122 @@ static int __devinit sonypi_create_input_devices(void) | |||
1234 | if (sonypi_inputkeys[i].inputev) | 1235 | if (sonypi_inputkeys[i].inputev) |
1235 | set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit); | 1236 | set_bit(sonypi_inputkeys[i].inputev, key_dev->keybit); |
1236 | 1237 | ||
1237 | input_register_device(jog_dev); | 1238 | error = input_register_device(jog_dev); |
1238 | input_register_device(key_dev); | 1239 | if (error) |
1240 | goto err_free_keydev; | ||
1241 | |||
1242 | error = input_register_device(key_dev); | ||
1243 | if (error) | ||
1244 | goto err_unregister_jogdev; | ||
1239 | 1245 | ||
1240 | return 0; | 1246 | return 0; |
1247 | |||
1248 | err_unregister_jogdev: | ||
1249 | input_unregister_device(jog_dev); | ||
1250 | /* Set to NULL so we don't free it again below */ | ||
1251 | jog_dev = NULL; | ||
1252 | err_free_keydev: | ||
1253 | input_free_device(key_dev); | ||
1254 | sonypi_device.input_key_dev = NULL; | ||
1255 | err_free_jogdev: | ||
1256 | input_free_device(jog_dev); | ||
1257 | sonypi_device.input_jog_dev = NULL; | ||
1258 | |||
1259 | return error; | ||
1241 | } | 1260 | } |
1242 | 1261 | ||
1243 | static int __devinit sonypi_probe(void) | 1262 | static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, |
1263 | const struct sonypi_ioport_list *ioport_list) | ||
1244 | { | 1264 | { |
1245 | int i, ret; | 1265 | while (ioport_list->port1) { |
1246 | struct sonypi_ioport_list *ioport_list; | ||
1247 | struct sonypi_irq_list *irq_list; | ||
1248 | struct pci_dev *pcidev; | ||
1249 | 1266 | ||
1250 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1267 | if (request_region(ioport_list->port1, |
1251 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) | 1268 | sonypi_device.region_size, |
1252 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; | 1269 | "Sony Programable I/O Device")) { |
1253 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1270 | dev->ioport1 = ioport_list->port1; |
1254 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | 1271 | dev->ioport2 = ioport_list->port2; |
1255 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | 1272 | return 0; |
1256 | else | 1273 | } |
1257 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; | 1274 | ioport_list++; |
1275 | } | ||
1258 | 1276 | ||
1259 | sonypi_device.dev = pcidev; | 1277 | return -EBUSY; |
1278 | } | ||
1279 | |||
1280 | static int __devinit sonypi_setup_irq(struct sonypi_device *dev, | ||
1281 | const struct sonypi_irq_list *irq_list) | ||
1282 | { | ||
1283 | while (irq_list->irq) { | ||
1284 | |||
1285 | if (!request_irq(irq_list->irq, sonypi_irq, | ||
1286 | SA_SHIRQ, "sonypi", sonypi_irq)) { | ||
1287 | dev->irq = irq_list->irq; | ||
1288 | dev->bits = irq_list->bits; | ||
1289 | return 0; | ||
1290 | } | ||
1291 | irq_list++; | ||
1292 | } | ||
1293 | |||
1294 | return -EBUSY; | ||
1295 | } | ||
1296 | |||
1297 | static void __devinit sonypi_display_info(void) | ||
1298 | { | ||
1299 | printk(KERN_INFO "sonypi: detected type%d model, " | ||
1300 | "verbose = %d, fnkeyinit = %s, camera = %s, " | ||
1301 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", | ||
1302 | sonypi_device.model, | ||
1303 | verbose, | ||
1304 | fnkeyinit ? "on" : "off", | ||
1305 | camera ? "on" : "off", | ||
1306 | compat ? "on" : "off", | ||
1307 | mask, | ||
1308 | useinput ? "on" : "off", | ||
1309 | SONYPI_ACPI_ACTIVE ? "on" : "off"); | ||
1310 | printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", | ||
1311 | sonypi_device.irq, | ||
1312 | sonypi_device.ioport1, sonypi_device.ioport2); | ||
1313 | |||
1314 | if (minor == -1) | ||
1315 | printk(KERN_INFO "sonypi: device allocated minor is %d\n", | ||
1316 | sonypi_misc_device.minor); | ||
1317 | } | ||
1318 | |||
1319 | static int __devinit sonypi_probe(struct platform_device *dev) | ||
1320 | { | ||
1321 | const struct sonypi_ioport_list *ioport_list; | ||
1322 | const struct sonypi_irq_list *irq_list; | ||
1323 | struct pci_dev *pcidev; | ||
1324 | int error; | ||
1260 | 1325 | ||
1261 | spin_lock_init(&sonypi_device.fifo_lock); | 1326 | spin_lock_init(&sonypi_device.fifo_lock); |
1262 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, | 1327 | sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, |
1263 | &sonypi_device.fifo_lock); | 1328 | &sonypi_device.fifo_lock); |
1264 | if (IS_ERR(sonypi_device.fifo)) { | 1329 | if (IS_ERR(sonypi_device.fifo)) { |
1265 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); | 1330 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); |
1266 | ret = PTR_ERR(sonypi_device.fifo); | 1331 | return PTR_ERR(sonypi_device.fifo); |
1267 | goto out_fifo; | ||
1268 | } | 1332 | } |
1269 | 1333 | ||
1270 | init_waitqueue_head(&sonypi_device.fifo_proc_list); | 1334 | init_waitqueue_head(&sonypi_device.fifo_proc_list); |
1271 | init_MUTEX(&sonypi_device.lock); | 1335 | init_MUTEX(&sonypi_device.lock); |
1272 | sonypi_device.bluetooth_power = -1; | 1336 | sonypi_device.bluetooth_power = -1; |
1273 | 1337 | ||
1338 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1339 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) | ||
1340 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE1; | ||
1341 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1342 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | ||
1343 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3; | ||
1344 | else | ||
1345 | sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2; | ||
1346 | |||
1274 | if (pcidev && pci_enable_device(pcidev)) { | 1347 | if (pcidev && pci_enable_device(pcidev)) { |
1275 | printk(KERN_ERR "sonypi: pci_enable_device failed\n"); | 1348 | printk(KERN_ERR "sonypi: pci_enable_device failed\n"); |
1276 | ret = -EIO; | 1349 | error = -EIO; |
1277 | goto out_pcienable; | 1350 | goto err_put_pcidev; |
1278 | } | ||
1279 | |||
1280 | if (minor != -1) | ||
1281 | sonypi_misc_device.minor = minor; | ||
1282 | if ((ret = misc_register(&sonypi_misc_device))) { | ||
1283 | printk(KERN_ERR "sonypi: misc_register failed\n"); | ||
1284 | goto out_miscreg; | ||
1285 | } | 1351 | } |
1286 | 1352 | ||
1353 | sonypi_device.dev = pcidev; | ||
1287 | 1354 | ||
1288 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { | 1355 | if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE1) { |
1289 | ioport_list = sonypi_type1_ioport_list; | 1356 | ioport_list = sonypi_type1_ioport_list; |
@@ -1302,43 +1369,36 @@ static int __devinit sonypi_probe(void) | |||
1302 | irq_list = sonypi_type3_irq_list; | 1369 | irq_list = sonypi_type3_irq_list; |
1303 | } | 1370 | } |
1304 | 1371 | ||
1305 | for (i = 0; ioport_list[i].port1; i++) { | 1372 | error = sonypi_setup_ioports(&sonypi_device, ioport_list); |
1306 | if (request_region(ioport_list[i].port1, | 1373 | if (error) { |
1307 | sonypi_device.region_size, | 1374 | printk(KERN_ERR "sonypi: failed to request ioports\n"); |
1308 | "Sony Programable I/O Device")) { | 1375 | goto err_disable_pcidev; |
1309 | /* get the ioport */ | ||
1310 | sonypi_device.ioport1 = ioport_list[i].port1; | ||
1311 | sonypi_device.ioport2 = ioport_list[i].port2; | ||
1312 | break; | ||
1313 | } | ||
1314 | } | ||
1315 | if (!sonypi_device.ioport1) { | ||
1316 | printk(KERN_ERR "sonypi: request_region failed\n"); | ||
1317 | ret = -ENODEV; | ||
1318 | goto out_reqreg; | ||
1319 | } | 1376 | } |
1320 | 1377 | ||
1321 | for (i = 0; irq_list[i].irq; i++) { | 1378 | error = sonypi_setup_irq(&sonypi_device, irq_list); |
1322 | 1379 | if (error) { | |
1323 | sonypi_device.irq = irq_list[i].irq; | 1380 | printk(KERN_ERR "sonypi: request_irq failed\n"); |
1324 | sonypi_device.bits = irq_list[i].bits; | 1381 | goto err_free_ioports; |
1325 | |||
1326 | if (!request_irq(sonypi_device.irq, sonypi_irq, | ||
1327 | SA_SHIRQ, "sonypi", sonypi_irq)) | ||
1328 | break; | ||
1329 | } | 1382 | } |
1330 | 1383 | ||
1331 | if (!irq_list[i].irq) { | 1384 | if (minor != -1) |
1332 | printk(KERN_ERR "sonypi: request_irq failed\n"); | 1385 | sonypi_misc_device.minor = minor; |
1333 | ret = -ENODEV; | 1386 | error = misc_register(&sonypi_misc_device); |
1334 | goto out_reqirq; | 1387 | if (error) { |
1388 | printk(KERN_ERR "sonypi: misc_register failed\n"); | ||
1389 | goto err_free_irq; | ||
1335 | } | 1390 | } |
1336 | 1391 | ||
1392 | sonypi_display_info(); | ||
1393 | |||
1337 | if (useinput) { | 1394 | if (useinput) { |
1338 | 1395 | ||
1339 | ret = sonypi_create_input_devices(); | 1396 | error = sonypi_create_input_devices(); |
1340 | if (ret) | 1397 | if (error) { |
1341 | goto out_inputdevices; | 1398 | printk(KERN_ERR |
1399 | "sonypi: failed to create input devices\n"); | ||
1400 | goto err_miscdev_unregister; | ||
1401 | } | ||
1342 | 1402 | ||
1343 | spin_lock_init(&sonypi_device.input_fifo_lock); | 1403 | spin_lock_init(&sonypi_device.input_fifo_lock); |
1344 | sonypi_device.input_fifo = | 1404 | sonypi_device.input_fifo = |
@@ -1346,91 +1406,104 @@ static int __devinit sonypi_probe(void) | |||
1346 | &sonypi_device.input_fifo_lock); | 1406 | &sonypi_device.input_fifo_lock); |
1347 | if (IS_ERR(sonypi_device.input_fifo)) { | 1407 | if (IS_ERR(sonypi_device.input_fifo)) { |
1348 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); | 1408 | printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); |
1349 | ret = PTR_ERR(sonypi_device.input_fifo); | 1409 | error = PTR_ERR(sonypi_device.input_fifo); |
1350 | goto out_infifo; | 1410 | goto err_inpdev_unregister; |
1351 | } | 1411 | } |
1352 | 1412 | ||
1353 | INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); | 1413 | INIT_WORK(&sonypi_device.input_work, input_keyrelease, NULL); |
1354 | } | 1414 | } |
1355 | 1415 | ||
1356 | sonypi_device.pdev = platform_device_register_simple("sonypi", -1, | ||
1357 | NULL, 0); | ||
1358 | if (IS_ERR(sonypi_device.pdev)) { | ||
1359 | ret = PTR_ERR(sonypi_device.pdev); | ||
1360 | goto out_platformdev; | ||
1361 | } | ||
1362 | |||
1363 | sonypi_enable(0); | 1416 | sonypi_enable(0); |
1364 | 1417 | ||
1365 | printk(KERN_INFO "sonypi: Sony Programmable I/O Controller Driver" | ||
1366 | "v%s.\n", SONYPI_DRIVER_VERSION); | ||
1367 | printk(KERN_INFO "sonypi: detected type%d model, " | ||
1368 | "verbose = %d, fnkeyinit = %s, camera = %s, " | ||
1369 | "compat = %s, mask = 0x%08lx, useinput = %s, acpi = %s\n", | ||
1370 | sonypi_device.model, | ||
1371 | verbose, | ||
1372 | fnkeyinit ? "on" : "off", | ||
1373 | camera ? "on" : "off", | ||
1374 | compat ? "on" : "off", | ||
1375 | mask, | ||
1376 | useinput ? "on" : "off", | ||
1377 | SONYPI_ACPI_ACTIVE ? "on" : "off"); | ||
1378 | printk(KERN_INFO "sonypi: enabled at irq=%d, port1=0x%x, port2=0x%x\n", | ||
1379 | sonypi_device.irq, | ||
1380 | sonypi_device.ioport1, sonypi_device.ioport2); | ||
1381 | |||
1382 | if (minor == -1) | ||
1383 | printk(KERN_INFO "sonypi: device allocated minor is %d\n", | ||
1384 | sonypi_misc_device.minor); | ||
1385 | |||
1386 | return 0; | 1418 | return 0; |
1387 | 1419 | ||
1388 | out_platformdev: | 1420 | err_inpdev_unregister: |
1389 | kfifo_free(sonypi_device.input_fifo); | ||
1390 | out_infifo: | ||
1391 | input_unregister_device(sonypi_device.input_key_dev); | 1421 | input_unregister_device(sonypi_device.input_key_dev); |
1392 | input_unregister_device(sonypi_device.input_jog_dev); | 1422 | input_unregister_device(sonypi_device.input_jog_dev); |
1393 | out_inputdevices: | 1423 | err_miscdev_unregister: |
1424 | misc_deregister(&sonypi_misc_device); | ||
1425 | err_free_irq: | ||
1394 | free_irq(sonypi_device.irq, sonypi_irq); | 1426 | free_irq(sonypi_device.irq, sonypi_irq); |
1395 | out_reqirq: | 1427 | err_free_ioports: |
1396 | release_region(sonypi_device.ioport1, sonypi_device.region_size); | 1428 | release_region(sonypi_device.ioport1, sonypi_device.region_size); |
1397 | out_reqreg: | 1429 | err_disable_pcidev: |
1398 | misc_deregister(&sonypi_misc_device); | ||
1399 | out_miscreg: | ||
1400 | if (pcidev) | 1430 | if (pcidev) |
1401 | pci_disable_device(pcidev); | 1431 | pci_disable_device(pcidev); |
1402 | out_pcienable: | 1432 | err_put_pcidev: |
1433 | pci_dev_put(pcidev); | ||
1403 | kfifo_free(sonypi_device.fifo); | 1434 | kfifo_free(sonypi_device.fifo); |
1404 | out_fifo: | 1435 | |
1405 | pci_dev_put(sonypi_device.dev); | 1436 | return error; |
1406 | return ret; | ||
1407 | } | 1437 | } |
1408 | 1438 | ||
1409 | static void __devexit sonypi_remove(void) | 1439 | static int __devexit sonypi_remove(struct platform_device *dev) |
1410 | { | 1440 | { |
1411 | sonypi_disable(); | 1441 | sonypi_disable(); |
1412 | 1442 | ||
1413 | synchronize_sched(); /* Allow sonypi interrupt to complete. */ | 1443 | synchronize_sched(); /* Allow sonypi interrupt to complete. */ |
1414 | flush_scheduled_work(); | 1444 | flush_scheduled_work(); |
1415 | 1445 | ||
1416 | platform_device_unregister(sonypi_device.pdev); | ||
1417 | |||
1418 | if (useinput) { | 1446 | if (useinput) { |
1419 | input_unregister_device(sonypi_device.input_key_dev); | 1447 | input_unregister_device(sonypi_device.input_key_dev); |
1420 | input_unregister_device(sonypi_device.input_jog_dev); | 1448 | input_unregister_device(sonypi_device.input_jog_dev); |
1421 | kfifo_free(sonypi_device.input_fifo); | 1449 | kfifo_free(sonypi_device.input_fifo); |
1422 | } | 1450 | } |
1423 | 1451 | ||
1452 | misc_deregister(&sonypi_misc_device); | ||
1453 | |||
1424 | free_irq(sonypi_device.irq, sonypi_irq); | 1454 | free_irq(sonypi_device.irq, sonypi_irq); |
1425 | release_region(sonypi_device.ioport1, sonypi_device.region_size); | 1455 | release_region(sonypi_device.ioport1, sonypi_device.region_size); |
1426 | misc_deregister(&sonypi_misc_device); | 1456 | |
1427 | if (sonypi_device.dev) | 1457 | if (sonypi_device.dev) { |
1428 | pci_disable_device(sonypi_device.dev); | 1458 | pci_disable_device(sonypi_device.dev); |
1459 | pci_dev_put(sonypi_device.dev); | ||
1460 | } | ||
1461 | |||
1429 | kfifo_free(sonypi_device.fifo); | 1462 | kfifo_free(sonypi_device.fifo); |
1430 | pci_dev_put(sonypi_device.dev); | 1463 | |
1431 | printk(KERN_INFO "sonypi: removed.\n"); | 1464 | return 0; |
1432 | } | 1465 | } |
1433 | 1466 | ||
1467 | #ifdef CONFIG_PM | ||
1468 | static int old_camera_power; | ||
1469 | |||
1470 | static int sonypi_suspend(struct platform_device *dev, pm_message_t state) | ||
1471 | { | ||
1472 | old_camera_power = sonypi_device.camera_power; | ||
1473 | sonypi_disable(); | ||
1474 | |||
1475 | return 0; | ||
1476 | } | ||
1477 | |||
1478 | static int sonypi_resume(struct platform_device *dev) | ||
1479 | { | ||
1480 | sonypi_enable(old_camera_power); | ||
1481 | return 0; | ||
1482 | } | ||
1483 | #else | ||
1484 | #define sonypi_suspend NULL | ||
1485 | #define sonypi_resume NULL | ||
1486 | #endif | ||
1487 | |||
1488 | static void sonypi_shutdown(struct platform_device *dev) | ||
1489 | { | ||
1490 | sonypi_disable(); | ||
1491 | } | ||
1492 | |||
1493 | static struct platform_driver sonypi_driver = { | ||
1494 | .driver = { | ||
1495 | .name = "sonypi", | ||
1496 | .owner = THIS_MODULE, | ||
1497 | }, | ||
1498 | .probe = sonypi_probe, | ||
1499 | .remove = __devexit_p(sonypi_remove), | ||
1500 | .shutdown = sonypi_shutdown, | ||
1501 | .suspend = sonypi_suspend, | ||
1502 | .resume = sonypi_resume, | ||
1503 | }; | ||
1504 | |||
1505 | static struct platform_device *sonypi_platform_device; | ||
1506 | |||
1434 | static struct dmi_system_id __initdata sonypi_dmi_table[] = { | 1507 | static struct dmi_system_id __initdata sonypi_dmi_table[] = { |
1435 | { | 1508 | { |
1436 | .ident = "Sony Vaio", | 1509 | .ident = "Sony Vaio", |
@@ -1451,26 +1524,52 @@ static struct dmi_system_id __initdata sonypi_dmi_table[] = { | |||
1451 | 1524 | ||
1452 | static int __init sonypi_init(void) | 1525 | static int __init sonypi_init(void) |
1453 | { | 1526 | { |
1454 | int ret; | 1527 | int error; |
1528 | |||
1529 | printk(KERN_INFO | ||
1530 | "sonypi: Sony Programmable I/O Controller Driver v%s.\n", | ||
1531 | SONYPI_DRIVER_VERSION); | ||
1455 | 1532 | ||
1456 | if (!dmi_check_system(sonypi_dmi_table)) | 1533 | if (!dmi_check_system(sonypi_dmi_table)) |
1457 | return -ENODEV; | 1534 | return -ENODEV; |
1458 | 1535 | ||
1459 | ret = platform_driver_register(&sonypi_driver); | 1536 | error = platform_driver_register(&sonypi_driver); |
1460 | if (ret) | 1537 | if (error) |
1461 | return ret; | 1538 | return error; |
1462 | 1539 | ||
1463 | ret = sonypi_probe(); | 1540 | sonypi_platform_device = platform_device_alloc("sonypi", -1); |
1464 | if (ret) | 1541 | if (!sonypi_platform_device) { |
1465 | platform_driver_unregister(&sonypi_driver); | 1542 | error = -ENOMEM; |
1543 | goto err_driver_unregister; | ||
1544 | } | ||
1466 | 1545 | ||
1467 | return ret; | 1546 | error = platform_device_add(sonypi_platform_device); |
1547 | if (error) | ||
1548 | goto err_free_device; | ||
1549 | |||
1550 | #ifdef CONFIG_ACPI | ||
1551 | if (acpi_bus_register_driver(&sonypi_acpi_driver) > 0) | ||
1552 | acpi_enabled = 1; | ||
1553 | #endif | ||
1554 | |||
1555 | return 0; | ||
1556 | |||
1557 | err_free_device: | ||
1558 | platform_device_put(sonypi_platform_device); | ||
1559 | err_driver_unregister: | ||
1560 | platform_driver_unregister(&sonypi_driver); | ||
1561 | return error; | ||
1468 | } | 1562 | } |
1469 | 1563 | ||
1470 | static void __exit sonypi_exit(void) | 1564 | static void __exit sonypi_exit(void) |
1471 | { | 1565 | { |
1566 | #ifdef CONFIG_ACPI | ||
1567 | if (acpi_enabled) | ||
1568 | acpi_bus_unregister_driver(&sonypi_acpi_driver); | ||
1569 | #endif | ||
1570 | platform_device_unregister(sonypi_platform_device); | ||
1472 | platform_driver_unregister(&sonypi_driver); | 1571 | platform_driver_unregister(&sonypi_driver); |
1473 | sonypi_remove(); | 1572 | printk(KERN_INFO "sonypi: removed.\n"); |
1474 | } | 1573 | } |
1475 | 1574 | ||
1476 | module_init(sonypi_init); | 1575 | module_init(sonypi_init); |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c new file mode 100644 index 000000000000..2b9cde94e2f7 --- /dev/null +++ b/drivers/char/synclink_gt.c | |||
@@ -0,0 +1,4501 @@ | |||
1 | /* | ||
2 | * $Id: synclink_gt.c,v 4.20 2005/11/08 19:51:55 paulkf Exp $ | ||
3 | * | ||
4 | * Device driver for Microgate SyncLink GT serial adapters. | ||
5 | * | ||
6 | * written by Paul Fulghum for Microgate Corporation | ||
7 | * paulkf@microgate.com | ||
8 | * | ||
9 | * Microgate and SyncLink are trademarks of Microgate Corporation | ||
10 | * | ||
11 | * This code is released under the GNU General Public License (GPL) | ||
12 | * | ||
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | ||
14 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
15 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
16 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | ||
17 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
19 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
20 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
21 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
23 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | * DEBUG OUTPUT DEFINITIONS | ||
28 | * | ||
29 | * uncomment lines below to enable specific types of debug output | ||
30 | * | ||
31 | * DBGINFO information - most verbose output | ||
32 | * DBGERR serious errors | ||
33 | * DBGBH bottom half service routine debugging | ||
34 | * DBGISR interrupt service routine debugging | ||
35 | * DBGDATA output receive and transmit data | ||
36 | * DBGTBUF output transmit DMA buffers and registers | ||
37 | * DBGRBUF output receive DMA buffers and registers | ||
38 | */ | ||
39 | |||
40 | #define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt | ||
41 | #define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt | ||
42 | #define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt | ||
43 | #define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt | ||
44 | #define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label)) | ||
45 | //#define DBGTBUF(info) dump_tbufs(info) | ||
46 | //#define DBGRBUF(info) dump_rbufs(info) | ||
47 | |||
48 | |||
49 | #include <linux/config.h> | ||
50 | #include <linux/module.h> | ||
51 | #include <linux/version.h> | ||
52 | #include <linux/errno.h> | ||
53 | #include <linux/signal.h> | ||
54 | #include <linux/sched.h> | ||
55 | #include <linux/timer.h> | ||
56 | #include <linux/interrupt.h> | ||
57 | #include <linux/pci.h> | ||
58 | #include <linux/tty.h> | ||
59 | #include <linux/tty_flip.h> | ||
60 | #include <linux/serial.h> | ||
61 | #include <linux/major.h> | ||
62 | #include <linux/string.h> | ||
63 | #include <linux/fcntl.h> | ||
64 | #include <linux/ptrace.h> | ||
65 | #include <linux/ioport.h> | ||
66 | #include <linux/mm.h> | ||
67 | #include <linux/slab.h> | ||
68 | #include <linux/netdevice.h> | ||
69 | #include <linux/vmalloc.h> | ||
70 | #include <linux/init.h> | ||
71 | #include <linux/delay.h> | ||
72 | #include <linux/ioctl.h> | ||
73 | #include <linux/termios.h> | ||
74 | #include <linux/bitops.h> | ||
75 | #include <linux/workqueue.h> | ||
76 | #include <linux/hdlc.h> | ||
77 | |||
78 | #include <asm/serial.h> | ||
79 | #include <asm/system.h> | ||
80 | #include <asm/io.h> | ||
81 | #include <asm/irq.h> | ||
82 | #include <asm/dma.h> | ||
83 | #include <asm/types.h> | ||
84 | #include <asm/uaccess.h> | ||
85 | |||
86 | #include "linux/synclink.h" | ||
87 | |||
88 | #ifdef CONFIG_HDLC_MODULE | ||
89 | #define CONFIG_HDLC 1 | ||
90 | #endif | ||
91 | |||
92 | /* | ||
93 | * module identification | ||
94 | */ | ||
95 | static char *driver_name = "SyncLink GT"; | ||
96 | static char *driver_version = "$Revision: 4.20 $"; | ||
97 | static char *tty_driver_name = "synclink_gt"; | ||
98 | static char *tty_dev_prefix = "ttySLG"; | ||
99 | MODULE_LICENSE("GPL"); | ||
100 | #define MGSL_MAGIC 0x5401 | ||
101 | #define MAX_DEVICES 12 | ||
102 | |||
103 | static struct pci_device_id pci_table[] = { | ||
104 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | ||
105 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | ||
106 | {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, | ||
107 | {0,}, /* terminate list */ | ||
108 | }; | ||
109 | MODULE_DEVICE_TABLE(pci, pci_table); | ||
110 | |||
111 | static int init_one(struct pci_dev *dev,const struct pci_device_id *ent); | ||
112 | static void remove_one(struct pci_dev *dev); | ||
113 | static struct pci_driver pci_driver = { | ||
114 | .name = "synclink_gt", | ||
115 | .id_table = pci_table, | ||
116 | .probe = init_one, | ||
117 | .remove = __devexit_p(remove_one), | ||
118 | }; | ||
119 | |||
120 | static int pci_registered; | ||
121 | |||
122 | /* | ||
123 | * module configuration and status | ||
124 | */ | ||
125 | static struct slgt_info *slgt_device_list; | ||
126 | static int slgt_device_count; | ||
127 | |||
128 | static int ttymajor; | ||
129 | static int debug_level; | ||
130 | static int maxframe[MAX_DEVICES]; | ||
131 | static int dosyncppp[MAX_DEVICES]; | ||
132 | |||
133 | module_param(ttymajor, int, 0); | ||
134 | module_param(debug_level, int, 0); | ||
135 | module_param_array(maxframe, int, NULL, 0); | ||
136 | module_param_array(dosyncppp, int, NULL, 0); | ||
137 | |||
138 | MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned"); | ||
139 | MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail"); | ||
140 | MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)"); | ||
141 | MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable"); | ||
142 | |||
143 | /* | ||
144 | * tty support and callbacks | ||
145 | */ | ||
146 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
147 | |||
148 | static struct tty_driver *serial_driver; | ||
149 | |||
150 | static int open(struct tty_struct *tty, struct file * filp); | ||
151 | static void close(struct tty_struct *tty, struct file * filp); | ||
152 | static void hangup(struct tty_struct *tty); | ||
153 | static void set_termios(struct tty_struct *tty, struct termios *old_termios); | ||
154 | |||
155 | static int write(struct tty_struct *tty, const unsigned char *buf, int count); | ||
156 | static void put_char(struct tty_struct *tty, unsigned char ch); | ||
157 | static void send_xchar(struct tty_struct *tty, char ch); | ||
158 | static void wait_until_sent(struct tty_struct *tty, int timeout); | ||
159 | static int write_room(struct tty_struct *tty); | ||
160 | static void flush_chars(struct tty_struct *tty); | ||
161 | static void flush_buffer(struct tty_struct *tty); | ||
162 | static void tx_hold(struct tty_struct *tty); | ||
163 | static void tx_release(struct tty_struct *tty); | ||
164 | |||
165 | static int ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg); | ||
166 | static int read_proc(char *page, char **start, off_t off, int count,int *eof, void *data); | ||
167 | static int chars_in_buffer(struct tty_struct *tty); | ||
168 | static void throttle(struct tty_struct * tty); | ||
169 | static void unthrottle(struct tty_struct * tty); | ||
170 | static void set_break(struct tty_struct *tty, int break_state); | ||
171 | |||
172 | /* | ||
173 | * generic HDLC support and callbacks | ||
174 | */ | ||
175 | #ifdef CONFIG_HDLC | ||
176 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) | ||
177 | static void hdlcdev_tx_done(struct slgt_info *info); | ||
178 | static void hdlcdev_rx(struct slgt_info *info, char *buf, int size); | ||
179 | static int hdlcdev_init(struct slgt_info *info); | ||
180 | static void hdlcdev_exit(struct slgt_info *info); | ||
181 | #endif | ||
182 | |||
183 | |||
184 | /* | ||
185 | * device specific structures, macros and functions | ||
186 | */ | ||
187 | |||
188 | #define SLGT_MAX_PORTS 4 | ||
189 | #define SLGT_REG_SIZE 256 | ||
190 | |||
191 | /* | ||
192 | * DMA buffer descriptor and access macros | ||
193 | */ | ||
194 | struct slgt_desc | ||
195 | { | ||
196 | unsigned short count; | ||
197 | unsigned short status; | ||
198 | unsigned int pbuf; /* physical address of data buffer */ | ||
199 | unsigned int next; /* physical address of next descriptor */ | ||
200 | |||
201 | /* driver book keeping */ | ||
202 | char *buf; /* virtual address of data buffer */ | ||
203 | unsigned int pdesc; /* physical address of this descriptor */ | ||
204 | dma_addr_t buf_dma_addr; | ||
205 | }; | ||
206 | |||
207 | #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) | ||
208 | #define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) | ||
209 | #define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) | ||
210 | #define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) | ||
211 | #define desc_count(a) (le16_to_cpu((a).count)) | ||
212 | #define desc_status(a) (le16_to_cpu((a).status)) | ||
213 | #define desc_complete(a) (le16_to_cpu((a).status) & BIT15) | ||
214 | #define desc_eof(a) (le16_to_cpu((a).status) & BIT2) | ||
215 | #define desc_crc_error(a) (le16_to_cpu((a).status) & BIT1) | ||
216 | #define desc_abort(a) (le16_to_cpu((a).status) & BIT0) | ||
217 | #define desc_residue(a) ((le16_to_cpu((a).status) & 0x38) >> 3) | ||
218 | |||
219 | struct _input_signal_events { | ||
220 | int ri_up; | ||
221 | int ri_down; | ||
222 | int dsr_up; | ||
223 | int dsr_down; | ||
224 | int dcd_up; | ||
225 | int dcd_down; | ||
226 | int cts_up; | ||
227 | int cts_down; | ||
228 | }; | ||
229 | |||
230 | /* | ||
231 | * device instance data structure | ||
232 | */ | ||
233 | struct slgt_info { | ||
234 | void *if_ptr; /* General purpose pointer (used by SPPP) */ | ||
235 | |||
236 | struct slgt_info *next_device; /* device list link */ | ||
237 | |||
238 | int magic; | ||
239 | int flags; | ||
240 | |||
241 | char device_name[25]; | ||
242 | struct pci_dev *pdev; | ||
243 | |||
244 | int port_count; /* count of ports on adapter */ | ||
245 | int adapter_num; /* adapter instance number */ | ||
246 | int port_num; /* port instance number */ | ||
247 | |||
248 | /* array of pointers to port contexts on this adapter */ | ||
249 | struct slgt_info *port_array[SLGT_MAX_PORTS]; | ||
250 | |||
251 | int count; /* count of opens */ | ||
252 | int line; /* tty line instance number */ | ||
253 | unsigned short close_delay; | ||
254 | unsigned short closing_wait; /* time to wait before closing */ | ||
255 | |||
256 | struct mgsl_icount icount; | ||
257 | |||
258 | struct tty_struct *tty; | ||
259 | int timeout; | ||
260 | int x_char; /* xon/xoff character */ | ||
261 | int blocked_open; /* # of blocked opens */ | ||
262 | unsigned int read_status_mask; | ||
263 | unsigned int ignore_status_mask; | ||
264 | |||
265 | wait_queue_head_t open_wait; | ||
266 | wait_queue_head_t close_wait; | ||
267 | |||
268 | wait_queue_head_t status_event_wait_q; | ||
269 | wait_queue_head_t event_wait_q; | ||
270 | struct timer_list tx_timer; | ||
271 | struct timer_list rx_timer; | ||
272 | |||
273 | spinlock_t lock; /* spinlock for synchronizing with ISR */ | ||
274 | |||
275 | struct work_struct task; | ||
276 | u32 pending_bh; | ||
277 | int bh_requested; | ||
278 | int bh_running; | ||
279 | |||
280 | int isr_overflow; | ||
281 | int irq_requested; /* nonzero if IRQ requested */ | ||
282 | int irq_occurred; /* for diagnostics use */ | ||
283 | |||
284 | /* device configuration */ | ||
285 | |||
286 | unsigned int bus_type; | ||
287 | unsigned int irq_level; | ||
288 | unsigned long irq_flags; | ||
289 | |||
290 | unsigned char __iomem * reg_addr; /* memory mapped registers address */ | ||
291 | u32 phys_reg_addr; | ||
292 | u32 reg_offset; | ||
293 | int reg_addr_requested; | ||
294 | |||
295 | MGSL_PARAMS params; /* communications parameters */ | ||
296 | u32 idle_mode; | ||
297 | u32 max_frame_size; /* as set by device config */ | ||
298 | |||
299 | unsigned int raw_rx_size; | ||
300 | unsigned int if_mode; | ||
301 | |||
302 | /* device status */ | ||
303 | |||
304 | int rx_enabled; | ||
305 | int rx_restart; | ||
306 | |||
307 | int tx_enabled; | ||
308 | int tx_active; | ||
309 | |||
310 | unsigned char signals; /* serial signal states */ | ||
311 | unsigned int init_error; /* initialization error */ | ||
312 | |||
313 | unsigned char *tx_buf; | ||
314 | int tx_count; | ||
315 | |||
316 | char flag_buf[MAX_ASYNC_BUFFER_SIZE]; | ||
317 | char char_buf[MAX_ASYNC_BUFFER_SIZE]; | ||
318 | BOOLEAN drop_rts_on_tx_done; | ||
319 | struct _input_signal_events input_signal_events; | ||
320 | |||
321 | int dcd_chkcount; /* check counts to prevent */ | ||
322 | int cts_chkcount; /* too many IRQs if a signal */ | ||
323 | int dsr_chkcount; /* is floating */ | ||
324 | int ri_chkcount; | ||
325 | |||
326 | char *bufs; /* virtual address of DMA buffer lists */ | ||
327 | dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */ | ||
328 | |||
329 | unsigned int rbuf_count; | ||
330 | struct slgt_desc *rbufs; | ||
331 | unsigned int rbuf_current; | ||
332 | unsigned int rbuf_index; | ||
333 | |||
334 | unsigned int tbuf_count; | ||
335 | struct slgt_desc *tbufs; | ||
336 | unsigned int tbuf_current; | ||
337 | unsigned int tbuf_start; | ||
338 | |||
339 | unsigned char *tmp_rbuf; | ||
340 | unsigned int tmp_rbuf_count; | ||
341 | |||
342 | /* SPPP/Cisco HDLC device parts */ | ||
343 | |||
344 | int netcount; | ||
345 | int dosyncppp; | ||
346 | spinlock_t netlock; | ||
347 | #ifdef CONFIG_HDLC | ||
348 | struct net_device *netdev; | ||
349 | #endif | ||
350 | |||
351 | }; | ||
352 | |||
353 | static MGSL_PARAMS default_params = { | ||
354 | .mode = MGSL_MODE_HDLC, | ||
355 | .loopback = 0, | ||
356 | .flags = HDLC_FLAG_UNDERRUN_ABORT15, | ||
357 | .encoding = HDLC_ENCODING_NRZI_SPACE, | ||
358 | .clock_speed = 0, | ||
359 | .addr_filter = 0xff, | ||
360 | .crc_type = HDLC_CRC_16_CCITT, | ||
361 | .preamble_length = HDLC_PREAMBLE_LENGTH_8BITS, | ||
362 | .preamble = HDLC_PREAMBLE_PATTERN_NONE, | ||
363 | .data_rate = 9600, | ||
364 | .data_bits = 8, | ||
365 | .stop_bits = 1, | ||
366 | .parity = ASYNC_PARITY_NONE | ||
367 | }; | ||
368 | |||
369 | |||
370 | #define BH_RECEIVE 1 | ||
371 | #define BH_TRANSMIT 2 | ||
372 | #define BH_STATUS 4 | ||
373 | #define IO_PIN_SHUTDOWN_LIMIT 100 | ||
374 | |||
375 | #define DMABUFSIZE 256 | ||
376 | #define DESC_LIST_SIZE 4096 | ||
377 | |||
378 | #define MASK_PARITY BIT1 | ||
379 | #define MASK_FRAMING BIT2 | ||
380 | #define MASK_BREAK BIT3 | ||
381 | #define MASK_OVERRUN BIT4 | ||
382 | |||
383 | #define GSR 0x00 /* global status */ | ||
384 | #define TDR 0x80 /* tx data */ | ||
385 | #define RDR 0x80 /* rx data */ | ||
386 | #define TCR 0x82 /* tx control */ | ||
387 | #define TIR 0x84 /* tx idle */ | ||
388 | #define TPR 0x85 /* tx preamble */ | ||
389 | #define RCR 0x86 /* rx control */ | ||
390 | #define VCR 0x88 /* V.24 control */ | ||
391 | #define CCR 0x89 /* clock control */ | ||
392 | #define BDR 0x8a /* baud divisor */ | ||
393 | #define SCR 0x8c /* serial control */ | ||
394 | #define SSR 0x8e /* serial status */ | ||
395 | #define RDCSR 0x90 /* rx DMA control/status */ | ||
396 | #define TDCSR 0x94 /* tx DMA control/status */ | ||
397 | #define RDDAR 0x98 /* rx DMA descriptor address */ | ||
398 | #define TDDAR 0x9c /* tx DMA descriptor address */ | ||
399 | |||
400 | #define RXIDLE BIT14 | ||
401 | #define RXBREAK BIT14 | ||
402 | #define IRQ_TXDATA BIT13 | ||
403 | #define IRQ_TXIDLE BIT12 | ||
404 | #define IRQ_TXUNDER BIT11 /* HDLC */ | ||
405 | #define IRQ_RXDATA BIT10 | ||
406 | #define IRQ_RXIDLE BIT9 /* HDLC */ | ||
407 | #define IRQ_RXBREAK BIT9 /* async */ | ||
408 | #define IRQ_RXOVER BIT8 | ||
409 | #define IRQ_DSR BIT7 | ||
410 | #define IRQ_CTS BIT6 | ||
411 | #define IRQ_DCD BIT5 | ||
412 | #define IRQ_RI BIT4 | ||
413 | #define IRQ_ALL 0x3ff0 | ||
414 | #define IRQ_MASTER BIT0 | ||
415 | |||
416 | #define slgt_irq_on(info, mask) \ | ||
417 | wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask))) | ||
418 | #define slgt_irq_off(info, mask) \ | ||
419 | wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask))) | ||
420 | |||
421 | static __u8 rd_reg8(struct slgt_info *info, unsigned int addr); | ||
422 | static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value); | ||
423 | static __u16 rd_reg16(struct slgt_info *info, unsigned int addr); | ||
424 | static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value); | ||
425 | static __u32 rd_reg32(struct slgt_info *info, unsigned int addr); | ||
426 | static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value); | ||
427 | |||
428 | static void msc_set_vcr(struct slgt_info *info); | ||
429 | |||
430 | static int startup(struct slgt_info *info); | ||
431 | static int block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info); | ||
432 | static void shutdown(struct slgt_info *info); | ||
433 | static void program_hw(struct slgt_info *info); | ||
434 | static void change_params(struct slgt_info *info); | ||
435 | |||
436 | static int register_test(struct slgt_info *info); | ||
437 | static int irq_test(struct slgt_info *info); | ||
438 | static int loopback_test(struct slgt_info *info); | ||
439 | static int adapter_test(struct slgt_info *info); | ||
440 | |||
441 | static void reset_adapter(struct slgt_info *info); | ||
442 | static void reset_port(struct slgt_info *info); | ||
443 | static void async_mode(struct slgt_info *info); | ||
444 | static void hdlc_mode(struct slgt_info *info); | ||
445 | |||
446 | static void rx_stop(struct slgt_info *info); | ||
447 | static void rx_start(struct slgt_info *info); | ||
448 | static void reset_rbufs(struct slgt_info *info); | ||
449 | static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last); | ||
450 | static void rdma_reset(struct slgt_info *info); | ||
451 | static int rx_get_frame(struct slgt_info *info); | ||
452 | static int rx_get_buf(struct slgt_info *info); | ||
453 | |||
454 | static void tx_start(struct slgt_info *info); | ||
455 | static void tx_stop(struct slgt_info *info); | ||
456 | static void tx_set_idle(struct slgt_info *info); | ||
457 | static unsigned int free_tbuf_count(struct slgt_info *info); | ||
458 | static void reset_tbufs(struct slgt_info *info); | ||
459 | static void tdma_reset(struct slgt_info *info); | ||
460 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); | ||
461 | |||
462 | static void get_signals(struct slgt_info *info); | ||
463 | static void set_signals(struct slgt_info *info); | ||
464 | static void enable_loopback(struct slgt_info *info); | ||
465 | static void set_rate(struct slgt_info *info, u32 data_rate); | ||
466 | |||
467 | static int bh_action(struct slgt_info *info); | ||
468 | static void bh_handler(void* context); | ||
469 | static void bh_transmit(struct slgt_info *info); | ||
470 | static void isr_serial(struct slgt_info *info); | ||
471 | static void isr_rdma(struct slgt_info *info); | ||
472 | static void isr_txeom(struct slgt_info *info, unsigned short status); | ||
473 | static void isr_tdma(struct slgt_info *info); | ||
474 | static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs); | ||
475 | |||
476 | static int alloc_dma_bufs(struct slgt_info *info); | ||
477 | static void free_dma_bufs(struct slgt_info *info); | ||
478 | static int alloc_desc(struct slgt_info *info); | ||
479 | static void free_desc(struct slgt_info *info); | ||
480 | static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); | ||
481 | static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count); | ||
482 | |||
483 | static int alloc_tmp_rbuf(struct slgt_info *info); | ||
484 | static void free_tmp_rbuf(struct slgt_info *info); | ||
485 | |||
486 | static void tx_timeout(unsigned long context); | ||
487 | static void rx_timeout(unsigned long context); | ||
488 | |||
489 | /* | ||
490 | * ioctl handlers | ||
491 | */ | ||
492 | static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount); | ||
493 | static int get_params(struct slgt_info *info, MGSL_PARAMS __user *params); | ||
494 | static int set_params(struct slgt_info *info, MGSL_PARAMS __user *params); | ||
495 | static int get_txidle(struct slgt_info *info, int __user *idle_mode); | ||
496 | static int set_txidle(struct slgt_info *info, int idle_mode); | ||
497 | static int tx_enable(struct slgt_info *info, int enable); | ||
498 | static int tx_abort(struct slgt_info *info); | ||
499 | static int rx_enable(struct slgt_info *info, int enable); | ||
500 | static int modem_input_wait(struct slgt_info *info,int arg); | ||
501 | static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); | ||
502 | static int tiocmget(struct tty_struct *tty, struct file *file); | ||
503 | static int tiocmset(struct tty_struct *tty, struct file *file, | ||
504 | unsigned int set, unsigned int clear); | ||
505 | static void set_break(struct tty_struct *tty, int break_state); | ||
506 | static int get_interface(struct slgt_info *info, int __user *if_mode); | ||
507 | static int set_interface(struct slgt_info *info, int if_mode); | ||
508 | |||
509 | /* | ||
510 | * driver functions | ||
511 | */ | ||
512 | static void add_device(struct slgt_info *info); | ||
513 | static void device_init(int adapter_num, struct pci_dev *pdev); | ||
514 | static int claim_resources(struct slgt_info *info); | ||
515 | static void release_resources(struct slgt_info *info); | ||
516 | |||
517 | /* | ||
518 | * DEBUG OUTPUT CODE | ||
519 | */ | ||
520 | #ifndef DBGINFO | ||
521 | #define DBGINFO(fmt) | ||
522 | #endif | ||
523 | #ifndef DBGERR | ||
524 | #define DBGERR(fmt) | ||
525 | #endif | ||
526 | #ifndef DBGBH | ||
527 | #define DBGBH(fmt) | ||
528 | #endif | ||
529 | #ifndef DBGISR | ||
530 | #define DBGISR(fmt) | ||
531 | #endif | ||
532 | |||
533 | #ifdef DBGDATA | ||
534 | static void trace_block(struct slgt_info *info, const char *data, int count, const char *label) | ||
535 | { | ||
536 | int i; | ||
537 | int linecount; | ||
538 | printk("%s %s data:\n",info->device_name, label); | ||
539 | while(count) { | ||
540 | linecount = (count > 16) ? 16 : count; | ||
541 | for(i=0; i < linecount; i++) | ||
542 | printk("%02X ",(unsigned char)data[i]); | ||
543 | for(;i<17;i++) | ||
544 | printk(" "); | ||
545 | for(i=0;i<linecount;i++) { | ||
546 | if (data[i]>=040 && data[i]<=0176) | ||
547 | printk("%c",data[i]); | ||
548 | else | ||
549 | printk("."); | ||
550 | } | ||
551 | printk("\n"); | ||
552 | data += linecount; | ||
553 | count -= linecount; | ||
554 | } | ||
555 | } | ||
556 | #else | ||
557 | #define DBGDATA(info, buf, size, label) | ||
558 | #endif | ||
559 | |||
560 | #ifdef DBGTBUF | ||
561 | static void dump_tbufs(struct slgt_info *info) | ||
562 | { | ||
563 | int i; | ||
564 | printk("tbuf_current=%d\n", info->tbuf_current); | ||
565 | for (i=0 ; i < info->tbuf_count ; i++) { | ||
566 | printk("%d: count=%04X status=%04X\n", | ||
567 | i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status)); | ||
568 | } | ||
569 | } | ||
570 | #else | ||
571 | #define DBGTBUF(info) | ||
572 | #endif | ||
573 | |||
574 | #ifdef DBGRBUF | ||
575 | static void dump_rbufs(struct slgt_info *info) | ||
576 | { | ||
577 | int i; | ||
578 | printk("rbuf_current=%d\n", info->rbuf_current); | ||
579 | for (i=0 ; i < info->rbuf_count ; i++) { | ||
580 | printk("%d: count=%04X status=%04X\n", | ||
581 | i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status)); | ||
582 | } | ||
583 | } | ||
584 | #else | ||
585 | #define DBGRBUF(info) | ||
586 | #endif | ||
587 | |||
588 | static inline int sanity_check(struct slgt_info *info, char *devname, const char *name) | ||
589 | { | ||
590 | #ifdef SANITY_CHECK | ||
591 | if (!info) { | ||
592 | printk("null struct slgt_info for (%s) in %s\n", devname, name); | ||
593 | return 1; | ||
594 | } | ||
595 | if (info->magic != MGSL_MAGIC) { | ||
596 | printk("bad magic number struct slgt_info (%s) in %s\n", devname, name); | ||
597 | return 1; | ||
598 | } | ||
599 | #else | ||
600 | if (!info) | ||
601 | return 1; | ||
602 | #endif | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | /** | ||
607 | * line discipline callback wrappers | ||
608 | * | ||
609 | * The wrappers maintain line discipline references | ||
610 | * while calling into the line discipline. | ||
611 | * | ||
612 | * ldisc_receive_buf - pass receive data to line discipline | ||
613 | */ | ||
614 | static void ldisc_receive_buf(struct tty_struct *tty, | ||
615 | const __u8 *data, char *flags, int count) | ||
616 | { | ||
617 | struct tty_ldisc *ld; | ||
618 | if (!tty) | ||
619 | return; | ||
620 | ld = tty_ldisc_ref(tty); | ||
621 | if (ld) { | ||
622 | if (ld->receive_buf) | ||
623 | ld->receive_buf(tty, data, flags, count); | ||
624 | tty_ldisc_deref(ld); | ||
625 | } | ||
626 | } | ||
627 | |||
628 | /* tty callbacks */ | ||
629 | |||
630 | static int open(struct tty_struct *tty, struct file *filp) | ||
631 | { | ||
632 | struct slgt_info *info; | ||
633 | int retval, line; | ||
634 | unsigned long flags; | ||
635 | |||
636 | line = tty->index; | ||
637 | if ((line < 0) || (line >= slgt_device_count)) { | ||
638 | DBGERR(("%s: open with invalid line #%d.\n", driver_name, line)); | ||
639 | return -ENODEV; | ||
640 | } | ||
641 | |||
642 | info = slgt_device_list; | ||
643 | while(info && info->line != line) | ||
644 | info = info->next_device; | ||
645 | if (sanity_check(info, tty->name, "open")) | ||
646 | return -ENODEV; | ||
647 | if (info->init_error) { | ||
648 | DBGERR(("%s init error=%d\n", info->device_name, info->init_error)); | ||
649 | return -ENODEV; | ||
650 | } | ||
651 | |||
652 | tty->driver_data = info; | ||
653 | info->tty = tty; | ||
654 | |||
655 | DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->count)); | ||
656 | |||
657 | /* If port is closing, signal caller to try again */ | ||
658 | if (tty_hung_up_p(filp) || info->flags & ASYNC_CLOSING){ | ||
659 | if (info->flags & ASYNC_CLOSING) | ||
660 | interruptible_sleep_on(&info->close_wait); | ||
661 | retval = ((info->flags & ASYNC_HUP_NOTIFY) ? | ||
662 | -EAGAIN : -ERESTARTSYS); | ||
663 | goto cleanup; | ||
664 | } | ||
665 | |||
666 | info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
667 | |||
668 | spin_lock_irqsave(&info->netlock, flags); | ||
669 | if (info->netcount) { | ||
670 | retval = -EBUSY; | ||
671 | spin_unlock_irqrestore(&info->netlock, flags); | ||
672 | goto cleanup; | ||
673 | } | ||
674 | info->count++; | ||
675 | spin_unlock_irqrestore(&info->netlock, flags); | ||
676 | |||
677 | if (info->count == 1) { | ||
678 | /* 1st open on this device, init hardware */ | ||
679 | retval = startup(info); | ||
680 | if (retval < 0) | ||
681 | goto cleanup; | ||
682 | } | ||
683 | |||
684 | retval = block_til_ready(tty, filp, info); | ||
685 | if (retval) { | ||
686 | DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval)); | ||
687 | goto cleanup; | ||
688 | } | ||
689 | |||
690 | retval = 0; | ||
691 | |||
692 | cleanup: | ||
693 | if (retval) { | ||
694 | if (tty->count == 1) | ||
695 | info->tty = NULL; /* tty layer will release tty struct */ | ||
696 | if(info->count) | ||
697 | info->count--; | ||
698 | } | ||
699 | |||
700 | DBGINFO(("%s open rc=%d\n", info->device_name, retval)); | ||
701 | return retval; | ||
702 | } | ||
703 | |||
704 | static void close(struct tty_struct *tty, struct file *filp) | ||
705 | { | ||
706 | struct slgt_info *info = tty->driver_data; | ||
707 | |||
708 | if (sanity_check(info, tty->name, "close")) | ||
709 | return; | ||
710 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->count)); | ||
711 | |||
712 | if (!info->count) | ||
713 | return; | ||
714 | |||
715 | if (tty_hung_up_p(filp)) | ||
716 | goto cleanup; | ||
717 | |||
718 | if ((tty->count == 1) && (info->count != 1)) { | ||
719 | /* | ||
720 | * tty->count is 1 and the tty structure will be freed. | ||
721 | * info->count should be one in this case. | ||
722 | * if it's not, correct it so that the port is shutdown. | ||
723 | */ | ||
724 | DBGERR(("%s close: bad refcount; tty->count=1, " | ||
725 | "info->count=%d\n", info->device_name, info->count)); | ||
726 | info->count = 1; | ||
727 | } | ||
728 | |||
729 | info->count--; | ||
730 | |||
731 | /* if at least one open remaining, leave hardware active */ | ||
732 | if (info->count) | ||
733 | goto cleanup; | ||
734 | |||
735 | info->flags |= ASYNC_CLOSING; | ||
736 | |||
737 | /* set tty->closing to notify line discipline to | ||
738 | * only process XON/XOFF characters. Only the N_TTY | ||
739 | * discipline appears to use this (ppp does not). | ||
740 | */ | ||
741 | tty->closing = 1; | ||
742 | |||
743 | /* wait for transmit data to clear all layers */ | ||
744 | |||
745 | if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
746 | DBGINFO(("%s call tty_wait_until_sent\n", info->device_name)); | ||
747 | tty_wait_until_sent(tty, info->closing_wait); | ||
748 | } | ||
749 | |||
750 | if (info->flags & ASYNC_INITIALIZED) | ||
751 | wait_until_sent(tty, info->timeout); | ||
752 | if (tty->driver->flush_buffer) | ||
753 | tty->driver->flush_buffer(tty); | ||
754 | tty_ldisc_flush(tty); | ||
755 | |||
756 | shutdown(info); | ||
757 | |||
758 | tty->closing = 0; | ||
759 | info->tty = NULL; | ||
760 | |||
761 | if (info->blocked_open) { | ||
762 | if (info->close_delay) { | ||
763 | msleep_interruptible(jiffies_to_msecs(info->close_delay)); | ||
764 | } | ||
765 | wake_up_interruptible(&info->open_wait); | ||
766 | } | ||
767 | |||
768 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
769 | |||
770 | wake_up_interruptible(&info->close_wait); | ||
771 | |||
772 | cleanup: | ||
773 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->count)); | ||
774 | } | ||
775 | |||
776 | static void hangup(struct tty_struct *tty) | ||
777 | { | ||
778 | struct slgt_info *info = tty->driver_data; | ||
779 | |||
780 | if (sanity_check(info, tty->name, "hangup")) | ||
781 | return; | ||
782 | DBGINFO(("%s hangup\n", info->device_name)); | ||
783 | |||
784 | flush_buffer(tty); | ||
785 | shutdown(info); | ||
786 | |||
787 | info->count = 0; | ||
788 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
789 | info->tty = NULL; | ||
790 | |||
791 | wake_up_interruptible(&info->open_wait); | ||
792 | } | ||
793 | |||
794 | static void set_termios(struct tty_struct *tty, struct termios *old_termios) | ||
795 | { | ||
796 | struct slgt_info *info = tty->driver_data; | ||
797 | unsigned long flags; | ||
798 | |||
799 | DBGINFO(("%s set_termios\n", tty->driver->name)); | ||
800 | |||
801 | /* just return if nothing has changed */ | ||
802 | if ((tty->termios->c_cflag == old_termios->c_cflag) | ||
803 | && (RELEVANT_IFLAG(tty->termios->c_iflag) | ||
804 | == RELEVANT_IFLAG(old_termios->c_iflag))) | ||
805 | return; | ||
806 | |||
807 | change_params(info); | ||
808 | |||
809 | /* Handle transition to B0 status */ | ||
810 | if (old_termios->c_cflag & CBAUD && | ||
811 | !(tty->termios->c_cflag & CBAUD)) { | ||
812 | info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
813 | spin_lock_irqsave(&info->lock,flags); | ||
814 | set_signals(info); | ||
815 | spin_unlock_irqrestore(&info->lock,flags); | ||
816 | } | ||
817 | |||
818 | /* Handle transition away from B0 status */ | ||
819 | if (!(old_termios->c_cflag & CBAUD) && | ||
820 | tty->termios->c_cflag & CBAUD) { | ||
821 | info->signals |= SerialSignal_DTR; | ||
822 | if (!(tty->termios->c_cflag & CRTSCTS) || | ||
823 | !test_bit(TTY_THROTTLED, &tty->flags)) { | ||
824 | info->signals |= SerialSignal_RTS; | ||
825 | } | ||
826 | spin_lock_irqsave(&info->lock,flags); | ||
827 | set_signals(info); | ||
828 | spin_unlock_irqrestore(&info->lock,flags); | ||
829 | } | ||
830 | |||
831 | /* Handle turning off CRTSCTS */ | ||
832 | if (old_termios->c_cflag & CRTSCTS && | ||
833 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
834 | tty->hw_stopped = 0; | ||
835 | tx_release(tty); | ||
836 | } | ||
837 | } | ||
838 | |||
839 | static int write(struct tty_struct *tty, | ||
840 | const unsigned char *buf, int count) | ||
841 | { | ||
842 | int ret = 0; | ||
843 | struct slgt_info *info = tty->driver_data; | ||
844 | unsigned long flags; | ||
845 | |||
846 | if (sanity_check(info, tty->name, "write")) | ||
847 | goto cleanup; | ||
848 | DBGINFO(("%s write count=%d\n", info->device_name, count)); | ||
849 | |||
850 | if (!tty || !info->tx_buf) | ||
851 | goto cleanup; | ||
852 | |||
853 | if (count > info->max_frame_size) { | ||
854 | ret = -EIO; | ||
855 | goto cleanup; | ||
856 | } | ||
857 | |||
858 | if (!count) | ||
859 | goto cleanup; | ||
860 | |||
861 | if (info->params.mode == MGSL_MODE_RAW) { | ||
862 | unsigned int bufs_needed = (count/DMABUFSIZE); | ||
863 | unsigned int bufs_free = free_tbuf_count(info); | ||
864 | if (count % DMABUFSIZE) | ||
865 | ++bufs_needed; | ||
866 | if (bufs_needed > bufs_free) | ||
867 | goto cleanup; | ||
868 | } else { | ||
869 | if (info->tx_active) | ||
870 | goto cleanup; | ||
871 | if (info->tx_count) { | ||
872 | /* send accumulated data from send_char() calls */ | ||
873 | /* as frame and wait before accepting more data. */ | ||
874 | tx_load(info, info->tx_buf, info->tx_count); | ||
875 | goto start; | ||
876 | } | ||
877 | } | ||
878 | |||
879 | ret = info->tx_count = count; | ||
880 | tx_load(info, buf, count); | ||
881 | goto start; | ||
882 | |||
883 | start: | ||
884 | if (info->tx_count && !tty->stopped && !tty->hw_stopped) { | ||
885 | spin_lock_irqsave(&info->lock,flags); | ||
886 | if (!info->tx_active) | ||
887 | tx_start(info); | ||
888 | spin_unlock_irqrestore(&info->lock,flags); | ||
889 | } | ||
890 | |||
891 | cleanup: | ||
892 | DBGINFO(("%s write rc=%d\n", info->device_name, ret)); | ||
893 | return ret; | ||
894 | } | ||
895 | |||
896 | static void put_char(struct tty_struct *tty, unsigned char ch) | ||
897 | { | ||
898 | struct slgt_info *info = tty->driver_data; | ||
899 | unsigned long flags; | ||
900 | |||
901 | if (sanity_check(info, tty->name, "put_char")) | ||
902 | return; | ||
903 | DBGINFO(("%s put_char(%d)\n", info->device_name, ch)); | ||
904 | if (!tty || !info->tx_buf) | ||
905 | return; | ||
906 | spin_lock_irqsave(&info->lock,flags); | ||
907 | if (!info->tx_active && (info->tx_count < info->max_frame_size)) | ||
908 | info->tx_buf[info->tx_count++] = ch; | ||
909 | spin_unlock_irqrestore(&info->lock,flags); | ||
910 | } | ||
911 | |||
912 | static void send_xchar(struct tty_struct *tty, char ch) | ||
913 | { | ||
914 | struct slgt_info *info = tty->driver_data; | ||
915 | unsigned long flags; | ||
916 | |||
917 | if (sanity_check(info, tty->name, "send_xchar")) | ||
918 | return; | ||
919 | DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch)); | ||
920 | info->x_char = ch; | ||
921 | if (ch) { | ||
922 | spin_lock_irqsave(&info->lock,flags); | ||
923 | if (!info->tx_enabled) | ||
924 | tx_start(info); | ||
925 | spin_unlock_irqrestore(&info->lock,flags); | ||
926 | } | ||
927 | } | ||
928 | |||
929 | static void wait_until_sent(struct tty_struct *tty, int timeout) | ||
930 | { | ||
931 | struct slgt_info *info = tty->driver_data; | ||
932 | unsigned long orig_jiffies, char_time; | ||
933 | |||
934 | if (!info ) | ||
935 | return; | ||
936 | if (sanity_check(info, tty->name, "wait_until_sent")) | ||
937 | return; | ||
938 | DBGINFO(("%s wait_until_sent entry\n", info->device_name)); | ||
939 | if (!(info->flags & ASYNC_INITIALIZED)) | ||
940 | goto exit; | ||
941 | |||
942 | orig_jiffies = jiffies; | ||
943 | |||
944 | /* Set check interval to 1/5 of estimated time to | ||
945 | * send a character, and make it at least 1. The check | ||
946 | * interval should also be less than the timeout. | ||
947 | * Note: use tight timings here to satisfy the NIST-PCTS. | ||
948 | */ | ||
949 | |||
950 | if (info->params.data_rate) { | ||
951 | char_time = info->timeout/(32 * 5); | ||
952 | if (!char_time) | ||
953 | char_time++; | ||
954 | } else | ||
955 | char_time = 1; | ||
956 | |||
957 | if (timeout) | ||
958 | char_time = min_t(unsigned long, char_time, timeout); | ||
959 | |||
960 | while (info->tx_active) { | ||
961 | msleep_interruptible(jiffies_to_msecs(char_time)); | ||
962 | if (signal_pending(current)) | ||
963 | break; | ||
964 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | ||
965 | break; | ||
966 | } | ||
967 | |||
968 | exit: | ||
969 | DBGINFO(("%s wait_until_sent exit\n", info->device_name)); | ||
970 | } | ||
971 | |||
972 | static int write_room(struct tty_struct *tty) | ||
973 | { | ||
974 | struct slgt_info *info = tty->driver_data; | ||
975 | int ret; | ||
976 | |||
977 | if (sanity_check(info, tty->name, "write_room")) | ||
978 | return 0; | ||
979 | ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE; | ||
980 | DBGINFO(("%s write_room=%d\n", info->device_name, ret)); | ||
981 | return ret; | ||
982 | } | ||
983 | |||
984 | static void flush_chars(struct tty_struct *tty) | ||
985 | { | ||
986 | struct slgt_info *info = tty->driver_data; | ||
987 | unsigned long flags; | ||
988 | |||
989 | if (sanity_check(info, tty->name, "flush_chars")) | ||
990 | return; | ||
991 | DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count)); | ||
992 | |||
993 | if (info->tx_count <= 0 || tty->stopped || | ||
994 | tty->hw_stopped || !info->tx_buf) | ||
995 | return; | ||
996 | |||
997 | DBGINFO(("%s flush_chars start transmit\n", info->device_name)); | ||
998 | |||
999 | spin_lock_irqsave(&info->lock,flags); | ||
1000 | if (!info->tx_active && info->tx_count) { | ||
1001 | tx_load(info, info->tx_buf,info->tx_count); | ||
1002 | tx_start(info); | ||
1003 | } | ||
1004 | spin_unlock_irqrestore(&info->lock,flags); | ||
1005 | } | ||
1006 | |||
1007 | static void flush_buffer(struct tty_struct *tty) | ||
1008 | { | ||
1009 | struct slgt_info *info = tty->driver_data; | ||
1010 | unsigned long flags; | ||
1011 | |||
1012 | if (sanity_check(info, tty->name, "flush_buffer")) | ||
1013 | return; | ||
1014 | DBGINFO(("%s flush_buffer\n", info->device_name)); | ||
1015 | |||
1016 | spin_lock_irqsave(&info->lock,flags); | ||
1017 | if (!info->tx_active) | ||
1018 | info->tx_count = 0; | ||
1019 | spin_unlock_irqrestore(&info->lock,flags); | ||
1020 | |||
1021 | wake_up_interruptible(&tty->write_wait); | ||
1022 | tty_wakeup(tty); | ||
1023 | } | ||
1024 | |||
1025 | /* | ||
1026 | * throttle (stop) transmitter | ||
1027 | */ | ||
1028 | static void tx_hold(struct tty_struct *tty) | ||
1029 | { | ||
1030 | struct slgt_info *info = tty->driver_data; | ||
1031 | unsigned long flags; | ||
1032 | |||
1033 | if (sanity_check(info, tty->name, "tx_hold")) | ||
1034 | return; | ||
1035 | DBGINFO(("%s tx_hold\n", info->device_name)); | ||
1036 | spin_lock_irqsave(&info->lock,flags); | ||
1037 | if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC) | ||
1038 | tx_stop(info); | ||
1039 | spin_unlock_irqrestore(&info->lock,flags); | ||
1040 | } | ||
1041 | |||
1042 | /* | ||
1043 | * release (start) transmitter | ||
1044 | */ | ||
1045 | static void tx_release(struct tty_struct *tty) | ||
1046 | { | ||
1047 | struct slgt_info *info = tty->driver_data; | ||
1048 | unsigned long flags; | ||
1049 | |||
1050 | if (sanity_check(info, tty->name, "tx_release")) | ||
1051 | return; | ||
1052 | DBGINFO(("%s tx_release\n", info->device_name)); | ||
1053 | spin_lock_irqsave(&info->lock,flags); | ||
1054 | if (!info->tx_active && info->tx_count) { | ||
1055 | tx_load(info, info->tx_buf, info->tx_count); | ||
1056 | tx_start(info); | ||
1057 | } | ||
1058 | spin_unlock_irqrestore(&info->lock,flags); | ||
1059 | } | ||
1060 | |||
1061 | /* | ||
1062 | * Service an IOCTL request | ||
1063 | * | ||
1064 | * Arguments | ||
1065 | * | ||
1066 | * tty pointer to tty instance data | ||
1067 | * file pointer to associated file object for device | ||
1068 | * cmd IOCTL command code | ||
1069 | * arg command argument/context | ||
1070 | * | ||
1071 | * Return 0 if success, otherwise error code | ||
1072 | */ | ||
1073 | static int ioctl(struct tty_struct *tty, struct file *file, | ||
1074 | unsigned int cmd, unsigned long arg) | ||
1075 | { | ||
1076 | struct slgt_info *info = tty->driver_data; | ||
1077 | struct mgsl_icount cnow; /* kernel counter temps */ | ||
1078 | struct serial_icounter_struct __user *p_cuser; /* user space */ | ||
1079 | unsigned long flags; | ||
1080 | void __user *argp = (void __user *)arg; | ||
1081 | |||
1082 | if (sanity_check(info, tty->name, "ioctl")) | ||
1083 | return -ENODEV; | ||
1084 | DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); | ||
1085 | |||
1086 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && | ||
1087 | (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { | ||
1088 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
1089 | return -EIO; | ||
1090 | } | ||
1091 | |||
1092 | switch (cmd) { | ||
1093 | case MGSL_IOCGPARAMS: | ||
1094 | return get_params(info, argp); | ||
1095 | case MGSL_IOCSPARAMS: | ||
1096 | return set_params(info, argp); | ||
1097 | case MGSL_IOCGTXIDLE: | ||
1098 | return get_txidle(info, argp); | ||
1099 | case MGSL_IOCSTXIDLE: | ||
1100 | return set_txidle(info, (int)arg); | ||
1101 | case MGSL_IOCTXENABLE: | ||
1102 | return tx_enable(info, (int)arg); | ||
1103 | case MGSL_IOCRXENABLE: | ||
1104 | return rx_enable(info, (int)arg); | ||
1105 | case MGSL_IOCTXABORT: | ||
1106 | return tx_abort(info); | ||
1107 | case MGSL_IOCGSTATS: | ||
1108 | return get_stats(info, argp); | ||
1109 | case MGSL_IOCWAITEVENT: | ||
1110 | return wait_mgsl_event(info, argp); | ||
1111 | case TIOCMIWAIT: | ||
1112 | return modem_input_wait(info,(int)arg); | ||
1113 | case MGSL_IOCGIF: | ||
1114 | return get_interface(info, argp); | ||
1115 | case MGSL_IOCSIF: | ||
1116 | return set_interface(info,(int)arg); | ||
1117 | case TIOCGICOUNT: | ||
1118 | spin_lock_irqsave(&info->lock,flags); | ||
1119 | cnow = info->icount; | ||
1120 | spin_unlock_irqrestore(&info->lock,flags); | ||
1121 | p_cuser = argp; | ||
1122 | if (put_user(cnow.cts, &p_cuser->cts) || | ||
1123 | put_user(cnow.dsr, &p_cuser->dsr) || | ||
1124 | put_user(cnow.rng, &p_cuser->rng) || | ||
1125 | put_user(cnow.dcd, &p_cuser->dcd) || | ||
1126 | put_user(cnow.rx, &p_cuser->rx) || | ||
1127 | put_user(cnow.tx, &p_cuser->tx) || | ||
1128 | put_user(cnow.frame, &p_cuser->frame) || | ||
1129 | put_user(cnow.overrun, &p_cuser->overrun) || | ||
1130 | put_user(cnow.parity, &p_cuser->parity) || | ||
1131 | put_user(cnow.brk, &p_cuser->brk) || | ||
1132 | put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1133 | return -EFAULT; | ||
1134 | return 0; | ||
1135 | default: | ||
1136 | return -ENOIOCTLCMD; | ||
1137 | } | ||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | /* | ||
1142 | * proc fs support | ||
1143 | */ | ||
1144 | static inline int line_info(char *buf, struct slgt_info *info) | ||
1145 | { | ||
1146 | char stat_buf[30]; | ||
1147 | int ret; | ||
1148 | unsigned long flags; | ||
1149 | |||
1150 | ret = sprintf(buf, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n", | ||
1151 | info->device_name, info->phys_reg_addr, | ||
1152 | info->irq_level, info->max_frame_size); | ||
1153 | |||
1154 | /* output current serial signal states */ | ||
1155 | spin_lock_irqsave(&info->lock,flags); | ||
1156 | get_signals(info); | ||
1157 | spin_unlock_irqrestore(&info->lock,flags); | ||
1158 | |||
1159 | stat_buf[0] = 0; | ||
1160 | stat_buf[1] = 0; | ||
1161 | if (info->signals & SerialSignal_RTS) | ||
1162 | strcat(stat_buf, "|RTS"); | ||
1163 | if (info->signals & SerialSignal_CTS) | ||
1164 | strcat(stat_buf, "|CTS"); | ||
1165 | if (info->signals & SerialSignal_DTR) | ||
1166 | strcat(stat_buf, "|DTR"); | ||
1167 | if (info->signals & SerialSignal_DSR) | ||
1168 | strcat(stat_buf, "|DSR"); | ||
1169 | if (info->signals & SerialSignal_DCD) | ||
1170 | strcat(stat_buf, "|CD"); | ||
1171 | if (info->signals & SerialSignal_RI) | ||
1172 | strcat(stat_buf, "|RI"); | ||
1173 | |||
1174 | if (info->params.mode != MGSL_MODE_ASYNC) { | ||
1175 | ret += sprintf(buf+ret, "\tHDLC txok:%d rxok:%d", | ||
1176 | info->icount.txok, info->icount.rxok); | ||
1177 | if (info->icount.txunder) | ||
1178 | ret += sprintf(buf+ret, " txunder:%d", info->icount.txunder); | ||
1179 | if (info->icount.txabort) | ||
1180 | ret += sprintf(buf+ret, " txabort:%d", info->icount.txabort); | ||
1181 | if (info->icount.rxshort) | ||
1182 | ret += sprintf(buf+ret, " rxshort:%d", info->icount.rxshort); | ||
1183 | if (info->icount.rxlong) | ||
1184 | ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxlong); | ||
1185 | if (info->icount.rxover) | ||
1186 | ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); | ||
1187 | if (info->icount.rxcrc) | ||
1188 | ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); | ||
1189 | } else { | ||
1190 | ret += sprintf(buf+ret, "\tASYNC tx:%d rx:%d", | ||
1191 | info->icount.tx, info->icount.rx); | ||
1192 | if (info->icount.frame) | ||
1193 | ret += sprintf(buf+ret, " fe:%d", info->icount.frame); | ||
1194 | if (info->icount.parity) | ||
1195 | ret += sprintf(buf+ret, " pe:%d", info->icount.parity); | ||
1196 | if (info->icount.brk) | ||
1197 | ret += sprintf(buf+ret, " brk:%d", info->icount.brk); | ||
1198 | if (info->icount.overrun) | ||
1199 | ret += sprintf(buf+ret, " oe:%d", info->icount.overrun); | ||
1200 | } | ||
1201 | |||
1202 | /* Append serial signal status to end */ | ||
1203 | ret += sprintf(buf+ret, " %s\n", stat_buf+1); | ||
1204 | |||
1205 | ret += sprintf(buf+ret, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n", | ||
1206 | info->tx_active,info->bh_requested,info->bh_running, | ||
1207 | info->pending_bh); | ||
1208 | |||
1209 | return ret; | ||
1210 | } | ||
1211 | |||
1212 | /* Called to print information about devices | ||
1213 | */ | ||
1214 | static int read_proc(char *page, char **start, off_t off, int count, | ||
1215 | int *eof, void *data) | ||
1216 | { | ||
1217 | int len = 0, l; | ||
1218 | off_t begin = 0; | ||
1219 | struct slgt_info *info; | ||
1220 | |||
1221 | len += sprintf(page, "synclink_gt driver:%s\n", driver_version); | ||
1222 | |||
1223 | info = slgt_device_list; | ||
1224 | while( info ) { | ||
1225 | l = line_info(page + len, info); | ||
1226 | len += l; | ||
1227 | if (len+begin > off+count) | ||
1228 | goto done; | ||
1229 | if (len+begin < off) { | ||
1230 | begin += len; | ||
1231 | len = 0; | ||
1232 | } | ||
1233 | info = info->next_device; | ||
1234 | } | ||
1235 | |||
1236 | *eof = 1; | ||
1237 | done: | ||
1238 | if (off >= len+begin) | ||
1239 | return 0; | ||
1240 | *start = page + (off-begin); | ||
1241 | return ((count < begin+len-off) ? count : begin+len-off); | ||
1242 | } | ||
1243 | |||
1244 | /* | ||
1245 | * return count of bytes in transmit buffer | ||
1246 | */ | ||
1247 | static int chars_in_buffer(struct tty_struct *tty) | ||
1248 | { | ||
1249 | struct slgt_info *info = tty->driver_data; | ||
1250 | if (sanity_check(info, tty->name, "chars_in_buffer")) | ||
1251 | return 0; | ||
1252 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count)); | ||
1253 | return info->tx_count; | ||
1254 | } | ||
1255 | |||
1256 | /* | ||
1257 | * signal remote device to throttle send data (our receive data) | ||
1258 | */ | ||
1259 | static void throttle(struct tty_struct * tty) | ||
1260 | { | ||
1261 | struct slgt_info *info = tty->driver_data; | ||
1262 | unsigned long flags; | ||
1263 | |||
1264 | if (sanity_check(info, tty->name, "throttle")) | ||
1265 | return; | ||
1266 | DBGINFO(("%s throttle\n", info->device_name)); | ||
1267 | if (I_IXOFF(tty)) | ||
1268 | send_xchar(tty, STOP_CHAR(tty)); | ||
1269 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1270 | spin_lock_irqsave(&info->lock,flags); | ||
1271 | info->signals &= ~SerialSignal_RTS; | ||
1272 | set_signals(info); | ||
1273 | spin_unlock_irqrestore(&info->lock,flags); | ||
1274 | } | ||
1275 | } | ||
1276 | |||
1277 | /* | ||
1278 | * signal remote device to stop throttling send data (our receive data) | ||
1279 | */ | ||
1280 | static void unthrottle(struct tty_struct * tty) | ||
1281 | { | ||
1282 | struct slgt_info *info = tty->driver_data; | ||
1283 | unsigned long flags; | ||
1284 | |||
1285 | if (sanity_check(info, tty->name, "unthrottle")) | ||
1286 | return; | ||
1287 | DBGINFO(("%s unthrottle\n", info->device_name)); | ||
1288 | if (I_IXOFF(tty)) { | ||
1289 | if (info->x_char) | ||
1290 | info->x_char = 0; | ||
1291 | else | ||
1292 | send_xchar(tty, START_CHAR(tty)); | ||
1293 | } | ||
1294 | if (tty->termios->c_cflag & CRTSCTS) { | ||
1295 | spin_lock_irqsave(&info->lock,flags); | ||
1296 | info->signals |= SerialSignal_RTS; | ||
1297 | set_signals(info); | ||
1298 | spin_unlock_irqrestore(&info->lock,flags); | ||
1299 | } | ||
1300 | } | ||
1301 | |||
1302 | /* | ||
1303 | * set or clear transmit break condition | ||
1304 | * break_state -1=set break condition, 0=clear | ||
1305 | */ | ||
1306 | static void set_break(struct tty_struct *tty, int break_state) | ||
1307 | { | ||
1308 | struct slgt_info *info = tty->driver_data; | ||
1309 | unsigned short value; | ||
1310 | unsigned long flags; | ||
1311 | |||
1312 | if (sanity_check(info, tty->name, "set_break")) | ||
1313 | return; | ||
1314 | DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); | ||
1315 | |||
1316 | spin_lock_irqsave(&info->lock,flags); | ||
1317 | value = rd_reg16(info, TCR); | ||
1318 | if (break_state == -1) | ||
1319 | value |= BIT6; | ||
1320 | else | ||
1321 | value &= ~BIT6; | ||
1322 | wr_reg16(info, TCR, value); | ||
1323 | spin_unlock_irqrestore(&info->lock,flags); | ||
1324 | } | ||
1325 | |||
1326 | #ifdef CONFIG_HDLC | ||
1327 | |||
1328 | /** | ||
1329 | * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) | ||
1330 | * set encoding and frame check sequence (FCS) options | ||
1331 | * | ||
1332 | * dev pointer to network device structure | ||
1333 | * encoding serial encoding setting | ||
1334 | * parity FCS setting | ||
1335 | * | ||
1336 | * returns 0 if success, otherwise error code | ||
1337 | */ | ||
1338 | static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, | ||
1339 | unsigned short parity) | ||
1340 | { | ||
1341 | struct slgt_info *info = dev_to_port(dev); | ||
1342 | unsigned char new_encoding; | ||
1343 | unsigned short new_crctype; | ||
1344 | |||
1345 | /* return error if TTY interface open */ | ||
1346 | if (info->count) | ||
1347 | return -EBUSY; | ||
1348 | |||
1349 | DBGINFO(("%s hdlcdev_attach\n", info->device_name)); | ||
1350 | |||
1351 | switch (encoding) | ||
1352 | { | ||
1353 | case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; | ||
1354 | case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; | ||
1355 | case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; | ||
1356 | case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; | ||
1357 | case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; | ||
1358 | default: return -EINVAL; | ||
1359 | } | ||
1360 | |||
1361 | switch (parity) | ||
1362 | { | ||
1363 | case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; | ||
1364 | case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; | ||
1365 | case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; | ||
1366 | default: return -EINVAL; | ||
1367 | } | ||
1368 | |||
1369 | info->params.encoding = new_encoding; | ||
1370 | info->params.crc_type = new_crctype;; | ||
1371 | |||
1372 | /* if network interface up, reprogram hardware */ | ||
1373 | if (info->netcount) | ||
1374 | program_hw(info); | ||
1375 | |||
1376 | return 0; | ||
1377 | } | ||
1378 | |||
1379 | /** | ||
1380 | * called by generic HDLC layer to send frame | ||
1381 | * | ||
1382 | * skb socket buffer containing HDLC frame | ||
1383 | * dev pointer to network device structure | ||
1384 | * | ||
1385 | * returns 0 if success, otherwise error code | ||
1386 | */ | ||
1387 | static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) | ||
1388 | { | ||
1389 | struct slgt_info *info = dev_to_port(dev); | ||
1390 | struct net_device_stats *stats = hdlc_stats(dev); | ||
1391 | unsigned long flags; | ||
1392 | |||
1393 | DBGINFO(("%s hdlc_xmit\n", dev->name)); | ||
1394 | |||
1395 | /* stop sending until this frame completes */ | ||
1396 | netif_stop_queue(dev); | ||
1397 | |||
1398 | /* copy data to device buffers */ | ||
1399 | info->tx_count = skb->len; | ||
1400 | tx_load(info, skb->data, skb->len); | ||
1401 | |||
1402 | /* update network statistics */ | ||
1403 | stats->tx_packets++; | ||
1404 | stats->tx_bytes += skb->len; | ||
1405 | |||
1406 | /* done with socket buffer, so free it */ | ||
1407 | dev_kfree_skb(skb); | ||
1408 | |||
1409 | /* save start time for transmit timeout detection */ | ||
1410 | dev->trans_start = jiffies; | ||
1411 | |||
1412 | /* start hardware transmitter if necessary */ | ||
1413 | spin_lock_irqsave(&info->lock,flags); | ||
1414 | if (!info->tx_active) | ||
1415 | tx_start(info); | ||
1416 | spin_unlock_irqrestore(&info->lock,flags); | ||
1417 | |||
1418 | return 0; | ||
1419 | } | ||
1420 | |||
1421 | /** | ||
1422 | * called by network layer when interface enabled | ||
1423 | * claim resources and initialize hardware | ||
1424 | * | ||
1425 | * dev pointer to network device structure | ||
1426 | * | ||
1427 | * returns 0 if success, otherwise error code | ||
1428 | */ | ||
1429 | static int hdlcdev_open(struct net_device *dev) | ||
1430 | { | ||
1431 | struct slgt_info *info = dev_to_port(dev); | ||
1432 | int rc; | ||
1433 | unsigned long flags; | ||
1434 | |||
1435 | DBGINFO(("%s hdlcdev_open\n", dev->name)); | ||
1436 | |||
1437 | /* generic HDLC layer open processing */ | ||
1438 | if ((rc = hdlc_open(dev))) | ||
1439 | return rc; | ||
1440 | |||
1441 | /* arbitrate between network and tty opens */ | ||
1442 | spin_lock_irqsave(&info->netlock, flags); | ||
1443 | if (info->count != 0 || info->netcount != 0) { | ||
1444 | DBGINFO(("%s hdlc_open busy\n", dev->name)); | ||
1445 | spin_unlock_irqrestore(&info->netlock, flags); | ||
1446 | return -EBUSY; | ||
1447 | } | ||
1448 | info->netcount=1; | ||
1449 | spin_unlock_irqrestore(&info->netlock, flags); | ||
1450 | |||
1451 | /* claim resources and init adapter */ | ||
1452 | if ((rc = startup(info)) != 0) { | ||
1453 | spin_lock_irqsave(&info->netlock, flags); | ||
1454 | info->netcount=0; | ||
1455 | spin_unlock_irqrestore(&info->netlock, flags); | ||
1456 | return rc; | ||
1457 | } | ||
1458 | |||
1459 | /* assert DTR and RTS, apply hardware settings */ | ||
1460 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
1461 | program_hw(info); | ||
1462 | |||
1463 | /* enable network layer transmit */ | ||
1464 | dev->trans_start = jiffies; | ||
1465 | netif_start_queue(dev); | ||
1466 | |||
1467 | /* inform generic HDLC layer of current DCD status */ | ||
1468 | spin_lock_irqsave(&info->lock, flags); | ||
1469 | get_signals(info); | ||
1470 | spin_unlock_irqrestore(&info->lock, flags); | ||
1471 | hdlc_set_carrier(info->signals & SerialSignal_DCD, dev); | ||
1472 | |||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | /** | ||
1477 | * called by network layer when interface is disabled | ||
1478 | * shutdown hardware and release resources | ||
1479 | * | ||
1480 | * dev pointer to network device structure | ||
1481 | * | ||
1482 | * returns 0 if success, otherwise error code | ||
1483 | */ | ||
1484 | static int hdlcdev_close(struct net_device *dev) | ||
1485 | { | ||
1486 | struct slgt_info *info = dev_to_port(dev); | ||
1487 | unsigned long flags; | ||
1488 | |||
1489 | DBGINFO(("%s hdlcdev_close\n", dev->name)); | ||
1490 | |||
1491 | netif_stop_queue(dev); | ||
1492 | |||
1493 | /* shutdown adapter and release resources */ | ||
1494 | shutdown(info); | ||
1495 | |||
1496 | hdlc_close(dev); | ||
1497 | |||
1498 | spin_lock_irqsave(&info->netlock, flags); | ||
1499 | info->netcount=0; | ||
1500 | spin_unlock_irqrestore(&info->netlock, flags); | ||
1501 | |||
1502 | return 0; | ||
1503 | } | ||
1504 | |||
1505 | /** | ||
1506 | * called by network layer to process IOCTL call to network device | ||
1507 | * | ||
1508 | * dev pointer to network device structure | ||
1509 | * ifr pointer to network interface request structure | ||
1510 | * cmd IOCTL command code | ||
1511 | * | ||
1512 | * returns 0 if success, otherwise error code | ||
1513 | */ | ||
1514 | static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||
1515 | { | ||
1516 | const size_t size = sizeof(sync_serial_settings); | ||
1517 | sync_serial_settings new_line; | ||
1518 | sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; | ||
1519 | struct slgt_info *info = dev_to_port(dev); | ||
1520 | unsigned int flags; | ||
1521 | |||
1522 | DBGINFO(("%s hdlcdev_ioctl\n", dev->name)); | ||
1523 | |||
1524 | /* return error if TTY interface open */ | ||
1525 | if (info->count) | ||
1526 | return -EBUSY; | ||
1527 | |||
1528 | if (cmd != SIOCWANDEV) | ||
1529 | return hdlc_ioctl(dev, ifr, cmd); | ||
1530 | |||
1531 | switch(ifr->ifr_settings.type) { | ||
1532 | case IF_GET_IFACE: /* return current sync_serial_settings */ | ||
1533 | |||
1534 | ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; | ||
1535 | if (ifr->ifr_settings.size < size) { | ||
1536 | ifr->ifr_settings.size = size; /* data size wanted */ | ||
1537 | return -ENOBUFS; | ||
1538 | } | ||
1539 | |||
1540 | flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | | ||
1541 | HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | | ||
1542 | HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | | ||
1543 | HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); | ||
1544 | |||
1545 | switch (flags){ | ||
1546 | case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; | ||
1547 | case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; | ||
1548 | case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; | ||
1549 | case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; | ||
1550 | default: new_line.clock_type = CLOCK_DEFAULT; | ||
1551 | } | ||
1552 | |||
1553 | new_line.clock_rate = info->params.clock_speed; | ||
1554 | new_line.loopback = info->params.loopback ? 1:0; | ||
1555 | |||
1556 | if (copy_to_user(line, &new_line, size)) | ||
1557 | return -EFAULT; | ||
1558 | return 0; | ||
1559 | |||
1560 | case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ | ||
1561 | |||
1562 | if(!capable(CAP_NET_ADMIN)) | ||
1563 | return -EPERM; | ||
1564 | if (copy_from_user(&new_line, line, size)) | ||
1565 | return -EFAULT; | ||
1566 | |||
1567 | switch (new_line.clock_type) | ||
1568 | { | ||
1569 | case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; | ||
1570 | case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; | ||
1571 | case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; | ||
1572 | case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; | ||
1573 | case CLOCK_DEFAULT: flags = info->params.flags & | ||
1574 | (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | | ||
1575 | HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | | ||
1576 | HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | | ||
1577 | HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; | ||
1578 | default: return -EINVAL; | ||
1579 | } | ||
1580 | |||
1581 | if (new_line.loopback != 0 && new_line.loopback != 1) | ||
1582 | return -EINVAL; | ||
1583 | |||
1584 | info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | | ||
1585 | HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | | ||
1586 | HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | | ||
1587 | HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); | ||
1588 | info->params.flags |= flags; | ||
1589 | |||
1590 | info->params.loopback = new_line.loopback; | ||
1591 | |||
1592 | if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) | ||
1593 | info->params.clock_speed = new_line.clock_rate; | ||
1594 | else | ||
1595 | info->params.clock_speed = 0; | ||
1596 | |||
1597 | /* if network interface up, reprogram hardware */ | ||
1598 | if (info->netcount) | ||
1599 | program_hw(info); | ||
1600 | return 0; | ||
1601 | |||
1602 | default: | ||
1603 | return hdlc_ioctl(dev, ifr, cmd); | ||
1604 | } | ||
1605 | } | ||
1606 | |||
1607 | /** | ||
1608 | * called by network layer when transmit timeout is detected | ||
1609 | * | ||
1610 | * dev pointer to network device structure | ||
1611 | */ | ||
1612 | static void hdlcdev_tx_timeout(struct net_device *dev) | ||
1613 | { | ||
1614 | struct slgt_info *info = dev_to_port(dev); | ||
1615 | struct net_device_stats *stats = hdlc_stats(dev); | ||
1616 | unsigned long flags; | ||
1617 | |||
1618 | DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name)); | ||
1619 | |||
1620 | stats->tx_errors++; | ||
1621 | stats->tx_aborted_errors++; | ||
1622 | |||
1623 | spin_lock_irqsave(&info->lock,flags); | ||
1624 | tx_stop(info); | ||
1625 | spin_unlock_irqrestore(&info->lock,flags); | ||
1626 | |||
1627 | netif_wake_queue(dev); | ||
1628 | } | ||
1629 | |||
1630 | /** | ||
1631 | * called by device driver when transmit completes | ||
1632 | * reenable network layer transmit if stopped | ||
1633 | * | ||
1634 | * info pointer to device instance information | ||
1635 | */ | ||
1636 | static void hdlcdev_tx_done(struct slgt_info *info) | ||
1637 | { | ||
1638 | if (netif_queue_stopped(info->netdev)) | ||
1639 | netif_wake_queue(info->netdev); | ||
1640 | } | ||
1641 | |||
1642 | /** | ||
1643 | * called by device driver when frame received | ||
1644 | * pass frame to network layer | ||
1645 | * | ||
1646 | * info pointer to device instance information | ||
1647 | * buf pointer to buffer contianing frame data | ||
1648 | * size count of data bytes in buf | ||
1649 | */ | ||
1650 | static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) | ||
1651 | { | ||
1652 | struct sk_buff *skb = dev_alloc_skb(size); | ||
1653 | struct net_device *dev = info->netdev; | ||
1654 | struct net_device_stats *stats = hdlc_stats(dev); | ||
1655 | |||
1656 | DBGINFO(("%s hdlcdev_rx\n", dev->name)); | ||
1657 | |||
1658 | if (skb == NULL) { | ||
1659 | DBGERR(("%s: can't alloc skb, drop packet\n", dev->name)); | ||
1660 | stats->rx_dropped++; | ||
1661 | return; | ||
1662 | } | ||
1663 | |||
1664 | memcpy(skb_put(skb, size),buf,size); | ||
1665 | |||
1666 | skb->protocol = hdlc_type_trans(skb, info->netdev); | ||
1667 | |||
1668 | stats->rx_packets++; | ||
1669 | stats->rx_bytes += size; | ||
1670 | |||
1671 | netif_rx(skb); | ||
1672 | |||
1673 | info->netdev->last_rx = jiffies; | ||
1674 | } | ||
1675 | |||
1676 | /** | ||
1677 | * called by device driver when adding device instance | ||
1678 | * do generic HDLC initialization | ||
1679 | * | ||
1680 | * info pointer to device instance information | ||
1681 | * | ||
1682 | * returns 0 if success, otherwise error code | ||
1683 | */ | ||
1684 | static int hdlcdev_init(struct slgt_info *info) | ||
1685 | { | ||
1686 | int rc; | ||
1687 | struct net_device *dev; | ||
1688 | hdlc_device *hdlc; | ||
1689 | |||
1690 | /* allocate and initialize network and HDLC layer objects */ | ||
1691 | |||
1692 | if (!(dev = alloc_hdlcdev(info))) { | ||
1693 | printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name); | ||
1694 | return -ENOMEM; | ||
1695 | } | ||
1696 | |||
1697 | /* for network layer reporting purposes only */ | ||
1698 | dev->mem_start = info->phys_reg_addr; | ||
1699 | dev->mem_end = info->phys_reg_addr + SLGT_REG_SIZE - 1; | ||
1700 | dev->irq = info->irq_level; | ||
1701 | |||
1702 | /* network layer callbacks and settings */ | ||
1703 | dev->do_ioctl = hdlcdev_ioctl; | ||
1704 | dev->open = hdlcdev_open; | ||
1705 | dev->stop = hdlcdev_close; | ||
1706 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
1707 | dev->watchdog_timeo = 10*HZ; | ||
1708 | dev->tx_queue_len = 50; | ||
1709 | |||
1710 | /* generic HDLC layer callbacks and settings */ | ||
1711 | hdlc = dev_to_hdlc(dev); | ||
1712 | hdlc->attach = hdlcdev_attach; | ||
1713 | hdlc->xmit = hdlcdev_xmit; | ||
1714 | |||
1715 | /* register objects with HDLC layer */ | ||
1716 | if ((rc = register_hdlc_device(dev))) { | ||
1717 | printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); | ||
1718 | free_netdev(dev); | ||
1719 | return rc; | ||
1720 | } | ||
1721 | |||
1722 | info->netdev = dev; | ||
1723 | return 0; | ||
1724 | } | ||
1725 | |||
1726 | /** | ||
1727 | * called by device driver when removing device instance | ||
1728 | * do generic HDLC cleanup | ||
1729 | * | ||
1730 | * info pointer to device instance information | ||
1731 | */ | ||
1732 | static void hdlcdev_exit(struct slgt_info *info) | ||
1733 | { | ||
1734 | unregister_hdlc_device(info->netdev); | ||
1735 | free_netdev(info->netdev); | ||
1736 | info->netdev = NULL; | ||
1737 | } | ||
1738 | |||
1739 | #endif /* ifdef CONFIG_HDLC */ | ||
1740 | |||
1741 | /* | ||
1742 | * get async data from rx DMA buffers | ||
1743 | */ | ||
1744 | static void rx_async(struct slgt_info *info) | ||
1745 | { | ||
1746 | struct tty_struct *tty = info->tty; | ||
1747 | struct mgsl_icount *icount = &info->icount; | ||
1748 | unsigned int start, end; | ||
1749 | unsigned char *p; | ||
1750 | unsigned char status; | ||
1751 | struct slgt_desc *bufs = info->rbufs; | ||
1752 | int i, count; | ||
1753 | |||
1754 | start = end = info->rbuf_current; | ||
1755 | |||
1756 | while(desc_complete(bufs[end])) { | ||
1757 | count = desc_count(bufs[end]) - info->rbuf_index; | ||
1758 | p = bufs[end].buf + info->rbuf_index; | ||
1759 | |||
1760 | DBGISR(("%s rx_async count=%d\n", info->device_name, count)); | ||
1761 | DBGDATA(info, p, count, "rx"); | ||
1762 | |||
1763 | for(i=0 ; i < count; i+=2, p+=2) { | ||
1764 | if (tty) { | ||
1765 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) | ||
1766 | tty_flip_buffer_push(tty); | ||
1767 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) | ||
1768 | break; | ||
1769 | *tty->flip.char_buf_ptr = *p; | ||
1770 | *tty->flip.flag_buf_ptr = 0; | ||
1771 | } | ||
1772 | icount->rx++; | ||
1773 | |||
1774 | if ((status = *(p+1) & (BIT9 + BIT8))) { | ||
1775 | if (status & BIT9) | ||
1776 | icount->parity++; | ||
1777 | else if (status & BIT8) | ||
1778 | icount->frame++; | ||
1779 | /* discard char if tty control flags say so */ | ||
1780 | if (status & info->ignore_status_mask) | ||
1781 | continue; | ||
1782 | if (tty) { | ||
1783 | if (status & BIT9) | ||
1784 | *tty->flip.flag_buf_ptr = TTY_PARITY; | ||
1785 | else if (status & BIT8) | ||
1786 | *tty->flip.flag_buf_ptr = TTY_FRAME; | ||
1787 | } | ||
1788 | } | ||
1789 | if (tty) { | ||
1790 | tty->flip.flag_buf_ptr++; | ||
1791 | tty->flip.char_buf_ptr++; | ||
1792 | tty->flip.count++; | ||
1793 | } | ||
1794 | } | ||
1795 | |||
1796 | if (i < count) { | ||
1797 | /* receive buffer not completed */ | ||
1798 | info->rbuf_index += i; | ||
1799 | info->rx_timer.expires = jiffies + 1; | ||
1800 | add_timer(&info->rx_timer); | ||
1801 | break; | ||
1802 | } | ||
1803 | |||
1804 | info->rbuf_index = 0; | ||
1805 | free_rbufs(info, end, end); | ||
1806 | |||
1807 | if (++end == info->rbuf_count) | ||
1808 | end = 0; | ||
1809 | |||
1810 | /* if entire list searched then no frame available */ | ||
1811 | if (end == start) | ||
1812 | break; | ||
1813 | } | ||
1814 | |||
1815 | if (tty && tty->flip.count) | ||
1816 | tty_flip_buffer_push(tty); | ||
1817 | } | ||
1818 | |||
1819 | /* | ||
1820 | * return next bottom half action to perform | ||
1821 | */ | ||
1822 | static int bh_action(struct slgt_info *info) | ||
1823 | { | ||
1824 | unsigned long flags; | ||
1825 | int rc; | ||
1826 | |||
1827 | spin_lock_irqsave(&info->lock,flags); | ||
1828 | |||
1829 | if (info->pending_bh & BH_RECEIVE) { | ||
1830 | info->pending_bh &= ~BH_RECEIVE; | ||
1831 | rc = BH_RECEIVE; | ||
1832 | } else if (info->pending_bh & BH_TRANSMIT) { | ||
1833 | info->pending_bh &= ~BH_TRANSMIT; | ||
1834 | rc = BH_TRANSMIT; | ||
1835 | } else if (info->pending_bh & BH_STATUS) { | ||
1836 | info->pending_bh &= ~BH_STATUS; | ||
1837 | rc = BH_STATUS; | ||
1838 | } else { | ||
1839 | /* Mark BH routine as complete */ | ||
1840 | info->bh_running = 0; | ||
1841 | info->bh_requested = 0; | ||
1842 | rc = 0; | ||
1843 | } | ||
1844 | |||
1845 | spin_unlock_irqrestore(&info->lock,flags); | ||
1846 | |||
1847 | return rc; | ||
1848 | } | ||
1849 | |||
1850 | /* | ||
1851 | * perform bottom half processing | ||
1852 | */ | ||
1853 | static void bh_handler(void* context) | ||
1854 | { | ||
1855 | struct slgt_info *info = context; | ||
1856 | int action; | ||
1857 | |||
1858 | if (!info) | ||
1859 | return; | ||
1860 | info->bh_running = 1; | ||
1861 | |||
1862 | while((action = bh_action(info))) { | ||
1863 | switch (action) { | ||
1864 | case BH_RECEIVE: | ||
1865 | DBGBH(("%s bh receive\n", info->device_name)); | ||
1866 | switch(info->params.mode) { | ||
1867 | case MGSL_MODE_ASYNC: | ||
1868 | rx_async(info); | ||
1869 | break; | ||
1870 | case MGSL_MODE_HDLC: | ||
1871 | while(rx_get_frame(info)); | ||
1872 | break; | ||
1873 | case MGSL_MODE_RAW: | ||
1874 | while(rx_get_buf(info)); | ||
1875 | break; | ||
1876 | } | ||
1877 | /* restart receiver if rx DMA buffers exhausted */ | ||
1878 | if (info->rx_restart) | ||
1879 | rx_start(info); | ||
1880 | break; | ||
1881 | case BH_TRANSMIT: | ||
1882 | bh_transmit(info); | ||
1883 | break; | ||
1884 | case BH_STATUS: | ||
1885 | DBGBH(("%s bh status\n", info->device_name)); | ||
1886 | info->ri_chkcount = 0; | ||
1887 | info->dsr_chkcount = 0; | ||
1888 | info->dcd_chkcount = 0; | ||
1889 | info->cts_chkcount = 0; | ||
1890 | break; | ||
1891 | default: | ||
1892 | DBGBH(("%s unknown action\n", info->device_name)); | ||
1893 | break; | ||
1894 | } | ||
1895 | } | ||
1896 | DBGBH(("%s bh_handler exit\n", info->device_name)); | ||
1897 | } | ||
1898 | |||
1899 | static void bh_transmit(struct slgt_info *info) | ||
1900 | { | ||
1901 | struct tty_struct *tty = info->tty; | ||
1902 | |||
1903 | DBGBH(("%s bh_transmit\n", info->device_name)); | ||
1904 | if (tty) { | ||
1905 | tty_wakeup(tty); | ||
1906 | wake_up_interruptible(&tty->write_wait); | ||
1907 | } | ||
1908 | } | ||
1909 | |||
1910 | static void dsr_change(struct slgt_info *info) | ||
1911 | { | ||
1912 | get_signals(info); | ||
1913 | DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); | ||
1914 | if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | ||
1915 | slgt_irq_off(info, IRQ_DSR); | ||
1916 | return; | ||
1917 | } | ||
1918 | info->icount.dsr++; | ||
1919 | if (info->signals & SerialSignal_DSR) | ||
1920 | info->input_signal_events.dsr_up++; | ||
1921 | else | ||
1922 | info->input_signal_events.dsr_down++; | ||
1923 | wake_up_interruptible(&info->status_event_wait_q); | ||
1924 | wake_up_interruptible(&info->event_wait_q); | ||
1925 | info->pending_bh |= BH_STATUS; | ||
1926 | } | ||
1927 | |||
1928 | static void cts_change(struct slgt_info *info) | ||
1929 | { | ||
1930 | get_signals(info); | ||
1931 | DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); | ||
1932 | if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | ||
1933 | slgt_irq_off(info, IRQ_CTS); | ||
1934 | return; | ||
1935 | } | ||
1936 | info->icount.cts++; | ||
1937 | if (info->signals & SerialSignal_CTS) | ||
1938 | info->input_signal_events.cts_up++; | ||
1939 | else | ||
1940 | info->input_signal_events.cts_down++; | ||
1941 | wake_up_interruptible(&info->status_event_wait_q); | ||
1942 | wake_up_interruptible(&info->event_wait_q); | ||
1943 | info->pending_bh |= BH_STATUS; | ||
1944 | |||
1945 | if (info->flags & ASYNC_CTS_FLOW) { | ||
1946 | if (info->tty) { | ||
1947 | if (info->tty->hw_stopped) { | ||
1948 | if (info->signals & SerialSignal_CTS) { | ||
1949 | info->tty->hw_stopped = 0; | ||
1950 | info->pending_bh |= BH_TRANSMIT; | ||
1951 | return; | ||
1952 | } | ||
1953 | } else { | ||
1954 | if (!(info->signals & SerialSignal_CTS)) | ||
1955 | info->tty->hw_stopped = 1; | ||
1956 | } | ||
1957 | } | ||
1958 | } | ||
1959 | } | ||
1960 | |||
1961 | static void dcd_change(struct slgt_info *info) | ||
1962 | { | ||
1963 | get_signals(info); | ||
1964 | DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); | ||
1965 | if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | ||
1966 | slgt_irq_off(info, IRQ_DCD); | ||
1967 | return; | ||
1968 | } | ||
1969 | info->icount.dcd++; | ||
1970 | if (info->signals & SerialSignal_DCD) { | ||
1971 | info->input_signal_events.dcd_up++; | ||
1972 | } else { | ||
1973 | info->input_signal_events.dcd_down++; | ||
1974 | } | ||
1975 | #ifdef CONFIG_HDLC | ||
1976 | if (info->netcount) | ||
1977 | hdlc_set_carrier(info->signals & SerialSignal_DCD, info->netdev); | ||
1978 | #endif | ||
1979 | wake_up_interruptible(&info->status_event_wait_q); | ||
1980 | wake_up_interruptible(&info->event_wait_q); | ||
1981 | info->pending_bh |= BH_STATUS; | ||
1982 | |||
1983 | if (info->flags & ASYNC_CHECK_CD) { | ||
1984 | if (info->signals & SerialSignal_DCD) | ||
1985 | wake_up_interruptible(&info->open_wait); | ||
1986 | else { | ||
1987 | if (info->tty) | ||
1988 | tty_hangup(info->tty); | ||
1989 | } | ||
1990 | } | ||
1991 | } | ||
1992 | |||
1993 | static void ri_change(struct slgt_info *info) | ||
1994 | { | ||
1995 | get_signals(info); | ||
1996 | DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); | ||
1997 | if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | ||
1998 | slgt_irq_off(info, IRQ_RI); | ||
1999 | return; | ||
2000 | } | ||
2001 | info->icount.dcd++; | ||
2002 | if (info->signals & SerialSignal_RI) { | ||
2003 | info->input_signal_events.ri_up++; | ||
2004 | } else { | ||
2005 | info->input_signal_events.ri_down++; | ||
2006 | } | ||
2007 | wake_up_interruptible(&info->status_event_wait_q); | ||
2008 | wake_up_interruptible(&info->event_wait_q); | ||
2009 | info->pending_bh |= BH_STATUS; | ||
2010 | } | ||
2011 | |||
2012 | static void isr_serial(struct slgt_info *info) | ||
2013 | { | ||
2014 | unsigned short status = rd_reg16(info, SSR); | ||
2015 | |||
2016 | DBGISR(("%s isr_serial status=%04X\n", info->device_name, status)); | ||
2017 | |||
2018 | wr_reg16(info, SSR, status); /* clear pending */ | ||
2019 | |||
2020 | info->irq_occurred = 1; | ||
2021 | |||
2022 | if (info->params.mode == MGSL_MODE_ASYNC) { | ||
2023 | if (status & IRQ_TXIDLE) { | ||
2024 | if (info->tx_count) | ||
2025 | isr_txeom(info, status); | ||
2026 | } | ||
2027 | if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { | ||
2028 | info->icount.brk++; | ||
2029 | /* process break detection if tty control allows */ | ||
2030 | if (info->tty) { | ||
2031 | if (!(status & info->ignore_status_mask)) { | ||
2032 | if (info->read_status_mask & MASK_BREAK) { | ||
2033 | *info->tty->flip.flag_buf_ptr = TTY_BREAK; | ||
2034 | if (info->flags & ASYNC_SAK) | ||
2035 | do_SAK(info->tty); | ||
2036 | } | ||
2037 | } | ||
2038 | } | ||
2039 | } | ||
2040 | } else { | ||
2041 | if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) | ||
2042 | isr_txeom(info, status); | ||
2043 | |||
2044 | if (status & IRQ_RXIDLE) { | ||
2045 | if (status & RXIDLE) | ||
2046 | info->icount.rxidle++; | ||
2047 | else | ||
2048 | info->icount.exithunt++; | ||
2049 | wake_up_interruptible(&info->event_wait_q); | ||
2050 | } | ||
2051 | |||
2052 | if (status & IRQ_RXOVER) | ||
2053 | rx_start(info); | ||
2054 | } | ||
2055 | |||
2056 | if (status & IRQ_DSR) | ||
2057 | dsr_change(info); | ||
2058 | if (status & IRQ_CTS) | ||
2059 | cts_change(info); | ||
2060 | if (status & IRQ_DCD) | ||
2061 | dcd_change(info); | ||
2062 | if (status & IRQ_RI) | ||
2063 | ri_change(info); | ||
2064 | } | ||
2065 | |||
2066 | static void isr_rdma(struct slgt_info *info) | ||
2067 | { | ||
2068 | unsigned int status = rd_reg32(info, RDCSR); | ||
2069 | |||
2070 | DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status)); | ||
2071 | |||
2072 | /* RDCSR (rx DMA control/status) | ||
2073 | * | ||
2074 | * 31..07 reserved | ||
2075 | * 06 save status byte to DMA buffer | ||
2076 | * 05 error | ||
2077 | * 04 eol (end of list) | ||
2078 | * 03 eob (end of buffer) | ||
2079 | * 02 IRQ enable | ||
2080 | * 01 reset | ||
2081 | * 00 enable | ||
2082 | */ | ||
2083 | wr_reg32(info, RDCSR, status); /* clear pending */ | ||
2084 | |||
2085 | if (status & (BIT5 + BIT4)) { | ||
2086 | DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name)); | ||
2087 | info->rx_restart = 1; | ||
2088 | } | ||
2089 | info->pending_bh |= BH_RECEIVE; | ||
2090 | } | ||
2091 | |||
2092 | static void isr_tdma(struct slgt_info *info) | ||
2093 | { | ||
2094 | unsigned int status = rd_reg32(info, TDCSR); | ||
2095 | |||
2096 | DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status)); | ||
2097 | |||
2098 | /* TDCSR (tx DMA control/status) | ||
2099 | * | ||
2100 | * 31..06 reserved | ||
2101 | * 05 error | ||
2102 | * 04 eol (end of list) | ||
2103 | * 03 eob (end of buffer) | ||
2104 | * 02 IRQ enable | ||
2105 | * 01 reset | ||
2106 | * 00 enable | ||
2107 | */ | ||
2108 | wr_reg32(info, TDCSR, status); /* clear pending */ | ||
2109 | |||
2110 | if (status & (BIT5 + BIT4 + BIT3)) { | ||
2111 | // another transmit buffer has completed | ||
2112 | // run bottom half to get more send data from user | ||
2113 | info->pending_bh |= BH_TRANSMIT; | ||
2114 | } | ||
2115 | } | ||
2116 | |||
2117 | static void isr_txeom(struct slgt_info *info, unsigned short status) | ||
2118 | { | ||
2119 | DBGISR(("%s txeom status=%04x\n", info->device_name, status)); | ||
2120 | |||
2121 | slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); | ||
2122 | tdma_reset(info); | ||
2123 | reset_tbufs(info); | ||
2124 | if (status & IRQ_TXUNDER) { | ||
2125 | unsigned short val = rd_reg16(info, TCR); | ||
2126 | wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ | ||
2127 | wr_reg16(info, TCR, val); /* clear reset bit */ | ||
2128 | } | ||
2129 | |||
2130 | if (info->tx_active) { | ||
2131 | if (info->params.mode != MGSL_MODE_ASYNC) { | ||
2132 | if (status & IRQ_TXUNDER) | ||
2133 | info->icount.txunder++; | ||
2134 | else if (status & IRQ_TXIDLE) | ||
2135 | info->icount.txok++; | ||
2136 | } | ||
2137 | |||
2138 | info->tx_active = 0; | ||
2139 | info->tx_count = 0; | ||
2140 | |||
2141 | del_timer(&info->tx_timer); | ||
2142 | |||
2143 | if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) { | ||
2144 | info->signals &= ~SerialSignal_RTS; | ||
2145 | info->drop_rts_on_tx_done = 0; | ||
2146 | set_signals(info); | ||
2147 | } | ||
2148 | |||
2149 | #ifdef CONFIG_HDLC | ||
2150 | if (info->netcount) | ||
2151 | hdlcdev_tx_done(info); | ||
2152 | else | ||
2153 | #endif | ||
2154 | { | ||
2155 | if (info->tty && (info->tty->stopped || info->tty->hw_stopped)) { | ||
2156 | tx_stop(info); | ||
2157 | return; | ||
2158 | } | ||
2159 | info->pending_bh |= BH_TRANSMIT; | ||
2160 | } | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2164 | /* interrupt service routine | ||
2165 | * | ||
2166 | * irq interrupt number | ||
2167 | * dev_id device ID supplied during interrupt registration | ||
2168 | * regs interrupted processor context | ||
2169 | */ | ||
2170 | static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs) | ||
2171 | { | ||
2172 | struct slgt_info *info; | ||
2173 | unsigned int gsr; | ||
2174 | unsigned int i; | ||
2175 | |||
2176 | DBGISR(("slgt_interrupt irq=%d entry\n", irq)); | ||
2177 | |||
2178 | info = dev_id; | ||
2179 | if (!info) | ||
2180 | return IRQ_NONE; | ||
2181 | |||
2182 | spin_lock(&info->lock); | ||
2183 | |||
2184 | while((gsr = rd_reg32(info, GSR) & 0xffffff00)) { | ||
2185 | DBGISR(("%s gsr=%08x\n", info->device_name, gsr)); | ||
2186 | info->irq_occurred = 1; | ||
2187 | for(i=0; i < info->port_count ; i++) { | ||
2188 | if (info->port_array[i] == NULL) | ||
2189 | continue; | ||
2190 | if (gsr & (BIT8 << i)) | ||
2191 | isr_serial(info->port_array[i]); | ||
2192 | if (gsr & (BIT16 << (i*2))) | ||
2193 | isr_rdma(info->port_array[i]); | ||
2194 | if (gsr & (BIT17 << (i*2))) | ||
2195 | isr_tdma(info->port_array[i]); | ||
2196 | } | ||
2197 | } | ||
2198 | |||
2199 | for(i=0; i < info->port_count ; i++) { | ||
2200 | struct slgt_info *port = info->port_array[i]; | ||
2201 | |||
2202 | if (port && (port->count || port->netcount) && | ||
2203 | port->pending_bh && !port->bh_running && | ||
2204 | !port->bh_requested) { | ||
2205 | DBGISR(("%s bh queued\n", port->device_name)); | ||
2206 | schedule_work(&port->task); | ||
2207 | port->bh_requested = 1; | ||
2208 | } | ||
2209 | } | ||
2210 | |||
2211 | spin_unlock(&info->lock); | ||
2212 | |||
2213 | DBGISR(("slgt_interrupt irq=%d exit\n", irq)); | ||
2214 | return IRQ_HANDLED; | ||
2215 | } | ||
2216 | |||
2217 | static int startup(struct slgt_info *info) | ||
2218 | { | ||
2219 | DBGINFO(("%s startup\n", info->device_name)); | ||
2220 | |||
2221 | if (info->flags & ASYNC_INITIALIZED) | ||
2222 | return 0; | ||
2223 | |||
2224 | if (!info->tx_buf) { | ||
2225 | info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL); | ||
2226 | if (!info->tx_buf) { | ||
2227 | DBGERR(("%s can't allocate tx buffer\n", info->device_name)); | ||
2228 | return -ENOMEM; | ||
2229 | } | ||
2230 | } | ||
2231 | |||
2232 | info->pending_bh = 0; | ||
2233 | |||
2234 | memset(&info->icount, 0, sizeof(info->icount)); | ||
2235 | |||
2236 | /* program hardware for current parameters */ | ||
2237 | change_params(info); | ||
2238 | |||
2239 | if (info->tty) | ||
2240 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
2241 | |||
2242 | info->flags |= ASYNC_INITIALIZED; | ||
2243 | |||
2244 | return 0; | ||
2245 | } | ||
2246 | |||
2247 | /* | ||
2248 | * called by close() and hangup() to shutdown hardware | ||
2249 | */ | ||
2250 | static void shutdown(struct slgt_info *info) | ||
2251 | { | ||
2252 | unsigned long flags; | ||
2253 | |||
2254 | if (!(info->flags & ASYNC_INITIALIZED)) | ||
2255 | return; | ||
2256 | |||
2257 | DBGINFO(("%s shutdown\n", info->device_name)); | ||
2258 | |||
2259 | /* clear status wait queue because status changes */ | ||
2260 | /* can't happen after shutting down the hardware */ | ||
2261 | wake_up_interruptible(&info->status_event_wait_q); | ||
2262 | wake_up_interruptible(&info->event_wait_q); | ||
2263 | |||
2264 | del_timer_sync(&info->tx_timer); | ||
2265 | del_timer_sync(&info->rx_timer); | ||
2266 | |||
2267 | kfree(info->tx_buf); | ||
2268 | info->tx_buf = NULL; | ||
2269 | |||
2270 | spin_lock_irqsave(&info->lock,flags); | ||
2271 | |||
2272 | tx_stop(info); | ||
2273 | rx_stop(info); | ||
2274 | |||
2275 | slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); | ||
2276 | |||
2277 | if (!info->tty || info->tty->termios->c_cflag & HUPCL) { | ||
2278 | info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); | ||
2279 | set_signals(info); | ||
2280 | } | ||
2281 | |||
2282 | spin_unlock_irqrestore(&info->lock,flags); | ||
2283 | |||
2284 | if (info->tty) | ||
2285 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
2286 | |||
2287 | info->flags &= ~ASYNC_INITIALIZED; | ||
2288 | } | ||
2289 | |||
2290 | static void program_hw(struct slgt_info *info) | ||
2291 | { | ||
2292 | unsigned long flags; | ||
2293 | |||
2294 | spin_lock_irqsave(&info->lock,flags); | ||
2295 | |||
2296 | rx_stop(info); | ||
2297 | tx_stop(info); | ||
2298 | |||
2299 | if (info->params.mode == MGSL_MODE_HDLC || | ||
2300 | info->params.mode == MGSL_MODE_RAW || | ||
2301 | info->netcount) | ||
2302 | hdlc_mode(info); | ||
2303 | else | ||
2304 | async_mode(info); | ||
2305 | |||
2306 | set_signals(info); | ||
2307 | |||
2308 | info->dcd_chkcount = 0; | ||
2309 | info->cts_chkcount = 0; | ||
2310 | info->ri_chkcount = 0; | ||
2311 | info->dsr_chkcount = 0; | ||
2312 | |||
2313 | slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR); | ||
2314 | get_signals(info); | ||
2315 | |||
2316 | if (info->netcount || | ||
2317 | (info->tty && info->tty->termios->c_cflag & CREAD)) | ||
2318 | rx_start(info); | ||
2319 | |||
2320 | spin_unlock_irqrestore(&info->lock,flags); | ||
2321 | } | ||
2322 | |||
2323 | /* | ||
2324 | * reconfigure adapter based on new parameters | ||
2325 | */ | ||
2326 | static void change_params(struct slgt_info *info) | ||
2327 | { | ||
2328 | unsigned cflag; | ||
2329 | int bits_per_char; | ||
2330 | |||
2331 | if (!info->tty || !info->tty->termios) | ||
2332 | return; | ||
2333 | DBGINFO(("%s change_params\n", info->device_name)); | ||
2334 | |||
2335 | cflag = info->tty->termios->c_cflag; | ||
2336 | |||
2337 | /* if B0 rate (hangup) specified then negate DTR and RTS */ | ||
2338 | /* otherwise assert DTR and RTS */ | ||
2339 | if (cflag & CBAUD) | ||
2340 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
2341 | else | ||
2342 | info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
2343 | |||
2344 | /* byte size and parity */ | ||
2345 | |||
2346 | switch (cflag & CSIZE) { | ||
2347 | case CS5: info->params.data_bits = 5; break; | ||
2348 | case CS6: info->params.data_bits = 6; break; | ||
2349 | case CS7: info->params.data_bits = 7; break; | ||
2350 | case CS8: info->params.data_bits = 8; break; | ||
2351 | default: info->params.data_bits = 7; break; | ||
2352 | } | ||
2353 | |||
2354 | info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1; | ||
2355 | |||
2356 | if (cflag & PARENB) | ||
2357 | info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN; | ||
2358 | else | ||
2359 | info->params.parity = ASYNC_PARITY_NONE; | ||
2360 | |||
2361 | /* calculate number of jiffies to transmit a full | ||
2362 | * FIFO (32 bytes) at specified data rate | ||
2363 | */ | ||
2364 | bits_per_char = info->params.data_bits + | ||
2365 | info->params.stop_bits + 1; | ||
2366 | |||
2367 | info->params.data_rate = tty_get_baud_rate(info->tty); | ||
2368 | |||
2369 | if (info->params.data_rate) { | ||
2370 | info->timeout = (32*HZ*bits_per_char) / | ||
2371 | info->params.data_rate; | ||
2372 | } | ||
2373 | info->timeout += HZ/50; /* Add .02 seconds of slop */ | ||
2374 | |||
2375 | if (cflag & CRTSCTS) | ||
2376 | info->flags |= ASYNC_CTS_FLOW; | ||
2377 | else | ||
2378 | info->flags &= ~ASYNC_CTS_FLOW; | ||
2379 | |||
2380 | if (cflag & CLOCAL) | ||
2381 | info->flags &= ~ASYNC_CHECK_CD; | ||
2382 | else | ||
2383 | info->flags |= ASYNC_CHECK_CD; | ||
2384 | |||
2385 | /* process tty input control flags */ | ||
2386 | |||
2387 | info->read_status_mask = IRQ_RXOVER; | ||
2388 | if (I_INPCK(info->tty)) | ||
2389 | info->read_status_mask |= MASK_PARITY | MASK_FRAMING; | ||
2390 | if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) | ||
2391 | info->read_status_mask |= MASK_BREAK; | ||
2392 | if (I_IGNPAR(info->tty)) | ||
2393 | info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING; | ||
2394 | if (I_IGNBRK(info->tty)) { | ||
2395 | info->ignore_status_mask |= MASK_BREAK; | ||
2396 | /* If ignoring parity and break indicators, ignore | ||
2397 | * overruns too. (For real raw support). | ||
2398 | */ | ||
2399 | if (I_IGNPAR(info->tty)) | ||
2400 | info->ignore_status_mask |= MASK_OVERRUN; | ||
2401 | } | ||
2402 | |||
2403 | program_hw(info); | ||
2404 | } | ||
2405 | |||
2406 | static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount) | ||
2407 | { | ||
2408 | DBGINFO(("%s get_stats\n", info->device_name)); | ||
2409 | if (!user_icount) { | ||
2410 | memset(&info->icount, 0, sizeof(info->icount)); | ||
2411 | } else { | ||
2412 | if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount))) | ||
2413 | return -EFAULT; | ||
2414 | } | ||
2415 | return 0; | ||
2416 | } | ||
2417 | |||
2418 | static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params) | ||
2419 | { | ||
2420 | DBGINFO(("%s get_params\n", info->device_name)); | ||
2421 | if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS))) | ||
2422 | return -EFAULT; | ||
2423 | return 0; | ||
2424 | } | ||
2425 | |||
2426 | static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params) | ||
2427 | { | ||
2428 | unsigned long flags; | ||
2429 | MGSL_PARAMS tmp_params; | ||
2430 | |||
2431 | DBGINFO(("%s set_params\n", info->device_name)); | ||
2432 | if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS))) | ||
2433 | return -EFAULT; | ||
2434 | |||
2435 | spin_lock_irqsave(&info->lock, flags); | ||
2436 | memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS)); | ||
2437 | spin_unlock_irqrestore(&info->lock, flags); | ||
2438 | |||
2439 | change_params(info); | ||
2440 | |||
2441 | return 0; | ||
2442 | } | ||
2443 | |||
2444 | static int get_txidle(struct slgt_info *info, int __user *idle_mode) | ||
2445 | { | ||
2446 | DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode)); | ||
2447 | if (put_user(info->idle_mode, idle_mode)) | ||
2448 | return -EFAULT; | ||
2449 | return 0; | ||
2450 | } | ||
2451 | |||
2452 | static int set_txidle(struct slgt_info *info, int idle_mode) | ||
2453 | { | ||
2454 | unsigned long flags; | ||
2455 | DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode)); | ||
2456 | spin_lock_irqsave(&info->lock,flags); | ||
2457 | info->idle_mode = idle_mode; | ||
2458 | tx_set_idle(info); | ||
2459 | spin_unlock_irqrestore(&info->lock,flags); | ||
2460 | return 0; | ||
2461 | } | ||
2462 | |||
2463 | static int tx_enable(struct slgt_info *info, int enable) | ||
2464 | { | ||
2465 | unsigned long flags; | ||
2466 | DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable)); | ||
2467 | spin_lock_irqsave(&info->lock,flags); | ||
2468 | if (enable) { | ||
2469 | if (!info->tx_enabled) | ||
2470 | tx_start(info); | ||
2471 | } else { | ||
2472 | if (info->tx_enabled) | ||
2473 | tx_stop(info); | ||
2474 | } | ||
2475 | spin_unlock_irqrestore(&info->lock,flags); | ||
2476 | return 0; | ||
2477 | } | ||
2478 | |||
2479 | /* | ||
2480 | * abort transmit HDLC frame | ||
2481 | */ | ||
2482 | static int tx_abort(struct slgt_info *info) | ||
2483 | { | ||
2484 | unsigned long flags; | ||
2485 | DBGINFO(("%s tx_abort\n", info->device_name)); | ||
2486 | spin_lock_irqsave(&info->lock,flags); | ||
2487 | tdma_reset(info); | ||
2488 | spin_unlock_irqrestore(&info->lock,flags); | ||
2489 | return 0; | ||
2490 | } | ||
2491 | |||
2492 | static int rx_enable(struct slgt_info *info, int enable) | ||
2493 | { | ||
2494 | unsigned long flags; | ||
2495 | DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable)); | ||
2496 | spin_lock_irqsave(&info->lock,flags); | ||
2497 | if (enable) { | ||
2498 | if (!info->rx_enabled) | ||
2499 | rx_start(info); | ||
2500 | } else { | ||
2501 | if (info->rx_enabled) | ||
2502 | rx_stop(info); | ||
2503 | } | ||
2504 | spin_unlock_irqrestore(&info->lock,flags); | ||
2505 | return 0; | ||
2506 | } | ||
2507 | |||
2508 | /* | ||
2509 | * wait for specified event to occur | ||
2510 | */ | ||
2511 | static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr) | ||
2512 | { | ||
2513 | unsigned long flags; | ||
2514 | int s; | ||
2515 | int rc=0; | ||
2516 | struct mgsl_icount cprev, cnow; | ||
2517 | int events; | ||
2518 | int mask; | ||
2519 | struct _input_signal_events oldsigs, newsigs; | ||
2520 | DECLARE_WAITQUEUE(wait, current); | ||
2521 | |||
2522 | if (get_user(mask, mask_ptr)) | ||
2523 | return -EFAULT; | ||
2524 | |||
2525 | DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask)); | ||
2526 | |||
2527 | spin_lock_irqsave(&info->lock,flags); | ||
2528 | |||
2529 | /* return immediately if state matches requested events */ | ||
2530 | get_signals(info); | ||
2531 | s = info->signals; | ||
2532 | |||
2533 | events = mask & | ||
2534 | ( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) + | ||
2535 | ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) + | ||
2536 | ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) + | ||
2537 | ((s & SerialSignal_RI) ? MgslEvent_RiActive :MgslEvent_RiInactive) ); | ||
2538 | if (events) { | ||
2539 | spin_unlock_irqrestore(&info->lock,flags); | ||
2540 | goto exit; | ||
2541 | } | ||
2542 | |||
2543 | /* save current irq counts */ | ||
2544 | cprev = info->icount; | ||
2545 | oldsigs = info->input_signal_events; | ||
2546 | |||
2547 | /* enable hunt and idle irqs if needed */ | ||
2548 | if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) { | ||
2549 | unsigned short val = rd_reg16(info, SCR); | ||
2550 | if (!(val & IRQ_RXIDLE)) | ||
2551 | wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE)); | ||
2552 | } | ||
2553 | |||
2554 | set_current_state(TASK_INTERRUPTIBLE); | ||
2555 | add_wait_queue(&info->event_wait_q, &wait); | ||
2556 | |||
2557 | spin_unlock_irqrestore(&info->lock,flags); | ||
2558 | |||
2559 | for(;;) { | ||
2560 | schedule(); | ||
2561 | if (signal_pending(current)) { | ||
2562 | rc = -ERESTARTSYS; | ||
2563 | break; | ||
2564 | } | ||
2565 | |||
2566 | /* get current irq counts */ | ||
2567 | spin_lock_irqsave(&info->lock,flags); | ||
2568 | cnow = info->icount; | ||
2569 | newsigs = info->input_signal_events; | ||
2570 | set_current_state(TASK_INTERRUPTIBLE); | ||
2571 | spin_unlock_irqrestore(&info->lock,flags); | ||
2572 | |||
2573 | /* if no change, wait aborted for some reason */ | ||
2574 | if (newsigs.dsr_up == oldsigs.dsr_up && | ||
2575 | newsigs.dsr_down == oldsigs.dsr_down && | ||
2576 | newsigs.dcd_up == oldsigs.dcd_up && | ||
2577 | newsigs.dcd_down == oldsigs.dcd_down && | ||
2578 | newsigs.cts_up == oldsigs.cts_up && | ||
2579 | newsigs.cts_down == oldsigs.cts_down && | ||
2580 | newsigs.ri_up == oldsigs.ri_up && | ||
2581 | newsigs.ri_down == oldsigs.ri_down && | ||
2582 | cnow.exithunt == cprev.exithunt && | ||
2583 | cnow.rxidle == cprev.rxidle) { | ||
2584 | rc = -EIO; | ||
2585 | break; | ||
2586 | } | ||
2587 | |||
2588 | events = mask & | ||
2589 | ( (newsigs.dsr_up != oldsigs.dsr_up ? MgslEvent_DsrActive:0) + | ||
2590 | (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) + | ||
2591 | (newsigs.dcd_up != oldsigs.dcd_up ? MgslEvent_DcdActive:0) + | ||
2592 | (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) + | ||
2593 | (newsigs.cts_up != oldsigs.cts_up ? MgslEvent_CtsActive:0) + | ||
2594 | (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) + | ||
2595 | (newsigs.ri_up != oldsigs.ri_up ? MgslEvent_RiActive:0) + | ||
2596 | (newsigs.ri_down != oldsigs.ri_down ? MgslEvent_RiInactive:0) + | ||
2597 | (cnow.exithunt != cprev.exithunt ? MgslEvent_ExitHuntMode:0) + | ||
2598 | (cnow.rxidle != cprev.rxidle ? MgslEvent_IdleReceived:0) ); | ||
2599 | if (events) | ||
2600 | break; | ||
2601 | |||
2602 | cprev = cnow; | ||
2603 | oldsigs = newsigs; | ||
2604 | } | ||
2605 | |||
2606 | remove_wait_queue(&info->event_wait_q, &wait); | ||
2607 | set_current_state(TASK_RUNNING); | ||
2608 | |||
2609 | |||
2610 | if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) { | ||
2611 | spin_lock_irqsave(&info->lock,flags); | ||
2612 | if (!waitqueue_active(&info->event_wait_q)) { | ||
2613 | /* disable enable exit hunt mode/idle rcvd IRQs */ | ||
2614 | wr_reg16(info, SCR, | ||
2615 | (unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE)); | ||
2616 | } | ||
2617 | spin_unlock_irqrestore(&info->lock,flags); | ||
2618 | } | ||
2619 | exit: | ||
2620 | if (rc == 0) | ||
2621 | rc = put_user(events, mask_ptr); | ||
2622 | return rc; | ||
2623 | } | ||
2624 | |||
2625 | static int get_interface(struct slgt_info *info, int __user *if_mode) | ||
2626 | { | ||
2627 | DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode)); | ||
2628 | if (put_user(info->if_mode, if_mode)) | ||
2629 | return -EFAULT; | ||
2630 | return 0; | ||
2631 | } | ||
2632 | |||
2633 | static int set_interface(struct slgt_info *info, int if_mode) | ||
2634 | { | ||
2635 | unsigned long flags; | ||
2636 | unsigned char val; | ||
2637 | |||
2638 | DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode)); | ||
2639 | spin_lock_irqsave(&info->lock,flags); | ||
2640 | info->if_mode = if_mode; | ||
2641 | |||
2642 | msc_set_vcr(info); | ||
2643 | |||
2644 | /* TCR (tx control) 07 1=RTS driver control */ | ||
2645 | val = rd_reg16(info, TCR); | ||
2646 | if (info->if_mode & MGSL_INTERFACE_RTS_EN) | ||
2647 | val |= BIT7; | ||
2648 | else | ||
2649 | val &= ~BIT7; | ||
2650 | wr_reg16(info, TCR, val); | ||
2651 | |||
2652 | spin_unlock_irqrestore(&info->lock,flags); | ||
2653 | return 0; | ||
2654 | } | ||
2655 | |||
2656 | static int modem_input_wait(struct slgt_info *info,int arg) | ||
2657 | { | ||
2658 | unsigned long flags; | ||
2659 | int rc; | ||
2660 | struct mgsl_icount cprev, cnow; | ||
2661 | DECLARE_WAITQUEUE(wait, current); | ||
2662 | |||
2663 | /* save current irq counts */ | ||
2664 | spin_lock_irqsave(&info->lock,flags); | ||
2665 | cprev = info->icount; | ||
2666 | add_wait_queue(&info->status_event_wait_q, &wait); | ||
2667 | set_current_state(TASK_INTERRUPTIBLE); | ||
2668 | spin_unlock_irqrestore(&info->lock,flags); | ||
2669 | |||
2670 | for(;;) { | ||
2671 | schedule(); | ||
2672 | if (signal_pending(current)) { | ||
2673 | rc = -ERESTARTSYS; | ||
2674 | break; | ||
2675 | } | ||
2676 | |||
2677 | /* get new irq counts */ | ||
2678 | spin_lock_irqsave(&info->lock,flags); | ||
2679 | cnow = info->icount; | ||
2680 | set_current_state(TASK_INTERRUPTIBLE); | ||
2681 | spin_unlock_irqrestore(&info->lock,flags); | ||
2682 | |||
2683 | /* if no change, wait aborted for some reason */ | ||
2684 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | ||
2685 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { | ||
2686 | rc = -EIO; | ||
2687 | break; | ||
2688 | } | ||
2689 | |||
2690 | /* check for change in caller specified modem input */ | ||
2691 | if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) || | ||
2692 | (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) || | ||
2693 | (arg & TIOCM_CD && cnow.dcd != cprev.dcd) || | ||
2694 | (arg & TIOCM_CTS && cnow.cts != cprev.cts)) { | ||
2695 | rc = 0; | ||
2696 | break; | ||
2697 | } | ||
2698 | |||
2699 | cprev = cnow; | ||
2700 | } | ||
2701 | remove_wait_queue(&info->status_event_wait_q, &wait); | ||
2702 | set_current_state(TASK_RUNNING); | ||
2703 | return rc; | ||
2704 | } | ||
2705 | |||
2706 | /* | ||
2707 | * return state of serial control and status signals | ||
2708 | */ | ||
2709 | static int tiocmget(struct tty_struct *tty, struct file *file) | ||
2710 | { | ||
2711 | struct slgt_info *info = tty->driver_data; | ||
2712 | unsigned int result; | ||
2713 | unsigned long flags; | ||
2714 | |||
2715 | spin_lock_irqsave(&info->lock,flags); | ||
2716 | get_signals(info); | ||
2717 | spin_unlock_irqrestore(&info->lock,flags); | ||
2718 | |||
2719 | result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) + | ||
2720 | ((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) + | ||
2721 | ((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) + | ||
2722 | ((info->signals & SerialSignal_RI) ? TIOCM_RNG:0) + | ||
2723 | ((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) + | ||
2724 | ((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0); | ||
2725 | |||
2726 | DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result)); | ||
2727 | return result; | ||
2728 | } | ||
2729 | |||
2730 | /* | ||
2731 | * set modem control signals (DTR/RTS) | ||
2732 | * | ||
2733 | * cmd signal command: TIOCMBIS = set bit TIOCMBIC = clear bit | ||
2734 | * TIOCMSET = set/clear signal values | ||
2735 | * value bit mask for command | ||
2736 | */ | ||
2737 | static int tiocmset(struct tty_struct *tty, struct file *file, | ||
2738 | unsigned int set, unsigned int clear) | ||
2739 | { | ||
2740 | struct slgt_info *info = tty->driver_data; | ||
2741 | unsigned long flags; | ||
2742 | |||
2743 | DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear)); | ||
2744 | |||
2745 | if (set & TIOCM_RTS) | ||
2746 | info->signals |= SerialSignal_RTS; | ||
2747 | if (set & TIOCM_DTR) | ||
2748 | info->signals |= SerialSignal_DTR; | ||
2749 | if (clear & TIOCM_RTS) | ||
2750 | info->signals &= ~SerialSignal_RTS; | ||
2751 | if (clear & TIOCM_DTR) | ||
2752 | info->signals &= ~SerialSignal_DTR; | ||
2753 | |||
2754 | spin_lock_irqsave(&info->lock,flags); | ||
2755 | set_signals(info); | ||
2756 | spin_unlock_irqrestore(&info->lock,flags); | ||
2757 | return 0; | ||
2758 | } | ||
2759 | |||
2760 | /* | ||
2761 | * block current process until the device is ready to open | ||
2762 | */ | ||
2763 | static int block_til_ready(struct tty_struct *tty, struct file *filp, | ||
2764 | struct slgt_info *info) | ||
2765 | { | ||
2766 | DECLARE_WAITQUEUE(wait, current); | ||
2767 | int retval; | ||
2768 | int do_clocal = 0, extra_count = 0; | ||
2769 | unsigned long flags; | ||
2770 | |||
2771 | DBGINFO(("%s block_til_ready\n", tty->driver->name)); | ||
2772 | |||
2773 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | ||
2774 | /* nonblock mode is set or port is not enabled */ | ||
2775 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
2776 | return 0; | ||
2777 | } | ||
2778 | |||
2779 | if (tty->termios->c_cflag & CLOCAL) | ||
2780 | do_clocal = 1; | ||
2781 | |||
2782 | /* Wait for carrier detect and the line to become | ||
2783 | * free (i.e., not in use by the callout). While we are in | ||
2784 | * this loop, info->count is dropped by one, so that | ||
2785 | * close() knows when to free things. We restore it upon | ||
2786 | * exit, either normal or abnormal. | ||
2787 | */ | ||
2788 | |||
2789 | retval = 0; | ||
2790 | add_wait_queue(&info->open_wait, &wait); | ||
2791 | |||
2792 | spin_lock_irqsave(&info->lock, flags); | ||
2793 | if (!tty_hung_up_p(filp)) { | ||
2794 | extra_count = 1; | ||
2795 | info->count--; | ||
2796 | } | ||
2797 | spin_unlock_irqrestore(&info->lock, flags); | ||
2798 | info->blocked_open++; | ||
2799 | |||
2800 | while (1) { | ||
2801 | if ((tty->termios->c_cflag & CBAUD)) { | ||
2802 | spin_lock_irqsave(&info->lock,flags); | ||
2803 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
2804 | set_signals(info); | ||
2805 | spin_unlock_irqrestore(&info->lock,flags); | ||
2806 | } | ||
2807 | |||
2808 | set_current_state(TASK_INTERRUPTIBLE); | ||
2809 | |||
2810 | if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)){ | ||
2811 | retval = (info->flags & ASYNC_HUP_NOTIFY) ? | ||
2812 | -EAGAIN : -ERESTARTSYS; | ||
2813 | break; | ||
2814 | } | ||
2815 | |||
2816 | spin_lock_irqsave(&info->lock,flags); | ||
2817 | get_signals(info); | ||
2818 | spin_unlock_irqrestore(&info->lock,flags); | ||
2819 | |||
2820 | if (!(info->flags & ASYNC_CLOSING) && | ||
2821 | (do_clocal || (info->signals & SerialSignal_DCD)) ) { | ||
2822 | break; | ||
2823 | } | ||
2824 | |||
2825 | if (signal_pending(current)) { | ||
2826 | retval = -ERESTARTSYS; | ||
2827 | break; | ||
2828 | } | ||
2829 | |||
2830 | DBGINFO(("%s block_til_ready wait\n", tty->driver->name)); | ||
2831 | schedule(); | ||
2832 | } | ||
2833 | |||
2834 | set_current_state(TASK_RUNNING); | ||
2835 | remove_wait_queue(&info->open_wait, &wait); | ||
2836 | |||
2837 | if (extra_count) | ||
2838 | info->count++; | ||
2839 | info->blocked_open--; | ||
2840 | |||
2841 | if (!retval) | ||
2842 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
2843 | |||
2844 | DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); | ||
2845 | return retval; | ||
2846 | } | ||
2847 | |||
2848 | static int alloc_tmp_rbuf(struct slgt_info *info) | ||
2849 | { | ||
2850 | info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL); | ||
2851 | if (info->tmp_rbuf == NULL) | ||
2852 | return -ENOMEM; | ||
2853 | return 0; | ||
2854 | } | ||
2855 | |||
2856 | static void free_tmp_rbuf(struct slgt_info *info) | ||
2857 | { | ||
2858 | kfree(info->tmp_rbuf); | ||
2859 | info->tmp_rbuf = NULL; | ||
2860 | } | ||
2861 | |||
2862 | /* | ||
2863 | * allocate DMA descriptor lists. | ||
2864 | */ | ||
2865 | static int alloc_desc(struct slgt_info *info) | ||
2866 | { | ||
2867 | unsigned int i; | ||
2868 | unsigned int pbufs; | ||
2869 | |||
2870 | /* allocate memory to hold descriptor lists */ | ||
2871 | info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr); | ||
2872 | if (info->bufs == NULL) | ||
2873 | return -ENOMEM; | ||
2874 | |||
2875 | memset(info->bufs, 0, DESC_LIST_SIZE); | ||
2876 | |||
2877 | info->rbufs = (struct slgt_desc*)info->bufs; | ||
2878 | info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count; | ||
2879 | |||
2880 | pbufs = (unsigned int)info->bufs_dma_addr; | ||
2881 | |||
2882 | /* | ||
2883 | * Build circular lists of descriptors | ||
2884 | */ | ||
2885 | |||
2886 | for (i=0; i < info->rbuf_count; i++) { | ||
2887 | /* physical address of this descriptor */ | ||
2888 | info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc)); | ||
2889 | |||
2890 | /* physical address of next descriptor */ | ||
2891 | if (i == info->rbuf_count - 1) | ||
2892 | info->rbufs[i].next = cpu_to_le32(pbufs); | ||
2893 | else | ||
2894 | info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc))); | ||
2895 | set_desc_count(info->rbufs[i], DMABUFSIZE); | ||
2896 | } | ||
2897 | |||
2898 | for (i=0; i < info->tbuf_count; i++) { | ||
2899 | /* physical address of this descriptor */ | ||
2900 | info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc)); | ||
2901 | |||
2902 | /* physical address of next descriptor */ | ||
2903 | if (i == info->tbuf_count - 1) | ||
2904 | info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc)); | ||
2905 | else | ||
2906 | info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc))); | ||
2907 | } | ||
2908 | |||
2909 | return 0; | ||
2910 | } | ||
2911 | |||
2912 | static void free_desc(struct slgt_info *info) | ||
2913 | { | ||
2914 | if (info->bufs != NULL) { | ||
2915 | pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr); | ||
2916 | info->bufs = NULL; | ||
2917 | info->rbufs = NULL; | ||
2918 | info->tbufs = NULL; | ||
2919 | } | ||
2920 | } | ||
2921 | |||
2922 | static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) | ||
2923 | { | ||
2924 | int i; | ||
2925 | for (i=0; i < count; i++) { | ||
2926 | if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL) | ||
2927 | return -ENOMEM; | ||
2928 | bufs[i].pbuf = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr); | ||
2929 | } | ||
2930 | return 0; | ||
2931 | } | ||
2932 | |||
2933 | static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count) | ||
2934 | { | ||
2935 | int i; | ||
2936 | for (i=0; i < count; i++) { | ||
2937 | if (bufs[i].buf == NULL) | ||
2938 | continue; | ||
2939 | pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr); | ||
2940 | bufs[i].buf = NULL; | ||
2941 | } | ||
2942 | } | ||
2943 | |||
2944 | static int alloc_dma_bufs(struct slgt_info *info) | ||
2945 | { | ||
2946 | info->rbuf_count = 32; | ||
2947 | info->tbuf_count = 32; | ||
2948 | |||
2949 | if (alloc_desc(info) < 0 || | ||
2950 | alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 || | ||
2951 | alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 || | ||
2952 | alloc_tmp_rbuf(info) < 0) { | ||
2953 | DBGERR(("%s DMA buffer alloc fail\n", info->device_name)); | ||
2954 | return -ENOMEM; | ||
2955 | } | ||
2956 | reset_rbufs(info); | ||
2957 | return 0; | ||
2958 | } | ||
2959 | |||
2960 | static void free_dma_bufs(struct slgt_info *info) | ||
2961 | { | ||
2962 | if (info->bufs) { | ||
2963 | free_bufs(info, info->rbufs, info->rbuf_count); | ||
2964 | free_bufs(info, info->tbufs, info->tbuf_count); | ||
2965 | free_desc(info); | ||
2966 | } | ||
2967 | free_tmp_rbuf(info); | ||
2968 | } | ||
2969 | |||
2970 | static int claim_resources(struct slgt_info *info) | ||
2971 | { | ||
2972 | if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) { | ||
2973 | DBGERR(("%s reg addr conflict, addr=%08X\n", | ||
2974 | info->device_name, info->phys_reg_addr)); | ||
2975 | info->init_error = DiagStatus_AddressConflict; | ||
2976 | goto errout; | ||
2977 | } | ||
2978 | else | ||
2979 | info->reg_addr_requested = 1; | ||
2980 | |||
2981 | info->reg_addr = ioremap(info->phys_reg_addr, PAGE_SIZE); | ||
2982 | if (!info->reg_addr) { | ||
2983 | DBGERR(("%s cant map device registers, addr=%08X\n", | ||
2984 | info->device_name, info->phys_reg_addr)); | ||
2985 | info->init_error = DiagStatus_CantAssignPciResources; | ||
2986 | goto errout; | ||
2987 | } | ||
2988 | info->reg_addr += info->reg_offset; | ||
2989 | return 0; | ||
2990 | |||
2991 | errout: | ||
2992 | release_resources(info); | ||
2993 | return -ENODEV; | ||
2994 | } | ||
2995 | |||
2996 | static void release_resources(struct slgt_info *info) | ||
2997 | { | ||
2998 | if (info->irq_requested) { | ||
2999 | free_irq(info->irq_level, info); | ||
3000 | info->irq_requested = 0; | ||
3001 | } | ||
3002 | |||
3003 | if (info->reg_addr_requested) { | ||
3004 | release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE); | ||
3005 | info->reg_addr_requested = 0; | ||
3006 | } | ||
3007 | |||
3008 | if (info->reg_addr) { | ||
3009 | iounmap(info->reg_addr - info->reg_offset); | ||
3010 | info->reg_addr = NULL; | ||
3011 | } | ||
3012 | } | ||
3013 | |||
3014 | /* Add the specified device instance data structure to the | ||
3015 | * global linked list of devices and increment the device count. | ||
3016 | */ | ||
3017 | static void add_device(struct slgt_info *info) | ||
3018 | { | ||
3019 | char *devstr; | ||
3020 | |||
3021 | info->next_device = NULL; | ||
3022 | info->line = slgt_device_count; | ||
3023 | sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line); | ||
3024 | |||
3025 | if (info->line < MAX_DEVICES) { | ||
3026 | if (maxframe[info->line]) | ||
3027 | info->max_frame_size = maxframe[info->line]; | ||
3028 | info->dosyncppp = dosyncppp[info->line]; | ||
3029 | } | ||
3030 | |||
3031 | slgt_device_count++; | ||
3032 | |||
3033 | if (!slgt_device_list) | ||
3034 | slgt_device_list = info; | ||
3035 | else { | ||
3036 | struct slgt_info *current_dev = slgt_device_list; | ||
3037 | while(current_dev->next_device) | ||
3038 | current_dev = current_dev->next_device; | ||
3039 | current_dev->next_device = info; | ||
3040 | } | ||
3041 | |||
3042 | if (info->max_frame_size < 4096) | ||
3043 | info->max_frame_size = 4096; | ||
3044 | else if (info->max_frame_size > 65535) | ||
3045 | info->max_frame_size = 65535; | ||
3046 | |||
3047 | switch(info->pdev->device) { | ||
3048 | case SYNCLINK_GT_DEVICE_ID: | ||
3049 | devstr = "GT"; | ||
3050 | break; | ||
3051 | case SYNCLINK_GT4_DEVICE_ID: | ||
3052 | devstr = "GT4"; | ||
3053 | break; | ||
3054 | case SYNCLINK_AC_DEVICE_ID: | ||
3055 | devstr = "AC"; | ||
3056 | info->params.mode = MGSL_MODE_ASYNC; | ||
3057 | break; | ||
3058 | default: | ||
3059 | devstr = "(unknown model)"; | ||
3060 | } | ||
3061 | printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n", | ||
3062 | devstr, info->device_name, info->phys_reg_addr, | ||
3063 | info->irq_level, info->max_frame_size); | ||
3064 | |||
3065 | #ifdef CONFIG_HDLC | ||
3066 | hdlcdev_init(info); | ||
3067 | #endif | ||
3068 | } | ||
3069 | |||
3070 | /* | ||
3071 | * allocate device instance structure, return NULL on failure | ||
3072 | */ | ||
3073 | static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev) | ||
3074 | { | ||
3075 | struct slgt_info *info; | ||
3076 | |||
3077 | info = kmalloc(sizeof(struct slgt_info), GFP_KERNEL); | ||
3078 | |||
3079 | if (!info) { | ||
3080 | DBGERR(("%s device alloc failed adapter=%d port=%d\n", | ||
3081 | driver_name, adapter_num, port_num)); | ||
3082 | } else { | ||
3083 | memset(info, 0, sizeof(struct slgt_info)); | ||
3084 | info->magic = MGSL_MAGIC; | ||
3085 | INIT_WORK(&info->task, bh_handler, info); | ||
3086 | info->max_frame_size = 4096; | ||
3087 | info->raw_rx_size = DMABUFSIZE; | ||
3088 | info->close_delay = 5*HZ/10; | ||
3089 | info->closing_wait = 30*HZ; | ||
3090 | init_waitqueue_head(&info->open_wait); | ||
3091 | init_waitqueue_head(&info->close_wait); | ||
3092 | init_waitqueue_head(&info->status_event_wait_q); | ||
3093 | init_waitqueue_head(&info->event_wait_q); | ||
3094 | spin_lock_init(&info->netlock); | ||
3095 | memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS)); | ||
3096 | info->idle_mode = HDLC_TXIDLE_FLAGS; | ||
3097 | info->adapter_num = adapter_num; | ||
3098 | info->port_num = port_num; | ||
3099 | |||
3100 | init_timer(&info->tx_timer); | ||
3101 | info->tx_timer.data = (unsigned long)info; | ||
3102 | info->tx_timer.function = tx_timeout; | ||
3103 | |||
3104 | init_timer(&info->rx_timer); | ||
3105 | info->rx_timer.data = (unsigned long)info; | ||
3106 | info->rx_timer.function = rx_timeout; | ||
3107 | |||
3108 | /* Copy configuration info to device instance data */ | ||
3109 | info->pdev = pdev; | ||
3110 | info->irq_level = pdev->irq; | ||
3111 | info->phys_reg_addr = pci_resource_start(pdev,0); | ||
3112 | |||
3113 | /* veremap works on page boundaries | ||
3114 | * map full page starting at the page boundary | ||
3115 | */ | ||
3116 | info->reg_offset = info->phys_reg_addr & (PAGE_SIZE-1); | ||
3117 | info->phys_reg_addr &= ~(PAGE_SIZE-1); | ||
3118 | |||
3119 | info->bus_type = MGSL_BUS_TYPE_PCI; | ||
3120 | info->irq_flags = SA_SHIRQ; | ||
3121 | |||
3122 | info->init_error = -1; /* assume error, set to 0 on successful init */ | ||
3123 | } | ||
3124 | |||
3125 | return info; | ||
3126 | } | ||
3127 | |||
3128 | static void device_init(int adapter_num, struct pci_dev *pdev) | ||
3129 | { | ||
3130 | struct slgt_info *port_array[SLGT_MAX_PORTS]; | ||
3131 | int i; | ||
3132 | int port_count = 1; | ||
3133 | |||
3134 | if (pdev->device == SYNCLINK_GT4_DEVICE_ID) | ||
3135 | port_count = 4; | ||
3136 | |||
3137 | /* allocate device instances for all ports */ | ||
3138 | for (i=0; i < port_count; ++i) { | ||
3139 | port_array[i] = alloc_dev(adapter_num, i, pdev); | ||
3140 | if (port_array[i] == NULL) { | ||
3141 | for (--i; i >= 0; --i) | ||
3142 | kfree(port_array[i]); | ||
3143 | return; | ||
3144 | } | ||
3145 | } | ||
3146 | |||
3147 | /* give copy of port_array to all ports and add to device list */ | ||
3148 | for (i=0; i < port_count; ++i) { | ||
3149 | memcpy(port_array[i]->port_array, port_array, sizeof(port_array)); | ||
3150 | add_device(port_array[i]); | ||
3151 | port_array[i]->port_count = port_count; | ||
3152 | spin_lock_init(&port_array[i]->lock); | ||
3153 | } | ||
3154 | |||
3155 | /* Allocate and claim adapter resources */ | ||
3156 | if (!claim_resources(port_array[0])) { | ||
3157 | |||
3158 | alloc_dma_bufs(port_array[0]); | ||
3159 | |||
3160 | /* copy resource information from first port to others */ | ||
3161 | for (i = 1; i < port_count; ++i) { | ||
3162 | port_array[i]->lock = port_array[0]->lock; | ||
3163 | port_array[i]->irq_level = port_array[0]->irq_level; | ||
3164 | port_array[i]->reg_addr = port_array[0]->reg_addr; | ||
3165 | alloc_dma_bufs(port_array[i]); | ||
3166 | } | ||
3167 | |||
3168 | if (request_irq(port_array[0]->irq_level, | ||
3169 | slgt_interrupt, | ||
3170 | port_array[0]->irq_flags, | ||
3171 | port_array[0]->device_name, | ||
3172 | port_array[0]) < 0) { | ||
3173 | DBGERR(("%s request_irq failed IRQ=%d\n", | ||
3174 | port_array[0]->device_name, | ||
3175 | port_array[0]->irq_level)); | ||
3176 | } else { | ||
3177 | port_array[0]->irq_requested = 1; | ||
3178 | adapter_test(port_array[0]); | ||
3179 | for (i=1 ; i < port_count ; i++) | ||
3180 | port_array[i]->init_error = port_array[0]->init_error; | ||
3181 | } | ||
3182 | } | ||
3183 | } | ||
3184 | |||
3185 | static int __devinit init_one(struct pci_dev *dev, | ||
3186 | const struct pci_device_id *ent) | ||
3187 | { | ||
3188 | if (pci_enable_device(dev)) { | ||
3189 | printk("error enabling pci device %p\n", dev); | ||
3190 | return -EIO; | ||
3191 | } | ||
3192 | pci_set_master(dev); | ||
3193 | device_init(slgt_device_count, dev); | ||
3194 | return 0; | ||
3195 | } | ||
3196 | |||
3197 | static void __devexit remove_one(struct pci_dev *dev) | ||
3198 | { | ||
3199 | } | ||
3200 | |||
3201 | static struct tty_operations ops = { | ||
3202 | .open = open, | ||
3203 | .close = close, | ||
3204 | .write = write, | ||
3205 | .put_char = put_char, | ||
3206 | .flush_chars = flush_chars, | ||
3207 | .write_room = write_room, | ||
3208 | .chars_in_buffer = chars_in_buffer, | ||
3209 | .flush_buffer = flush_buffer, | ||
3210 | .ioctl = ioctl, | ||
3211 | .throttle = throttle, | ||
3212 | .unthrottle = unthrottle, | ||
3213 | .send_xchar = send_xchar, | ||
3214 | .break_ctl = set_break, | ||
3215 | .wait_until_sent = wait_until_sent, | ||
3216 | .read_proc = read_proc, | ||
3217 | .set_termios = set_termios, | ||
3218 | .stop = tx_hold, | ||
3219 | .start = tx_release, | ||
3220 | .hangup = hangup, | ||
3221 | .tiocmget = tiocmget, | ||
3222 | .tiocmset = tiocmset, | ||
3223 | }; | ||
3224 | |||
3225 | static void slgt_cleanup(void) | ||
3226 | { | ||
3227 | int rc; | ||
3228 | struct slgt_info *info; | ||
3229 | struct slgt_info *tmp; | ||
3230 | |||
3231 | printk("unload %s %s\n", driver_name, driver_version); | ||
3232 | |||
3233 | if (serial_driver) { | ||
3234 | if ((rc = tty_unregister_driver(serial_driver))) | ||
3235 | DBGERR(("tty_unregister_driver error=%d\n", rc)); | ||
3236 | put_tty_driver(serial_driver); | ||
3237 | } | ||
3238 | |||
3239 | /* reset devices */ | ||
3240 | info = slgt_device_list; | ||
3241 | while(info) { | ||
3242 | reset_port(info); | ||
3243 | info = info->next_device; | ||
3244 | } | ||
3245 | |||
3246 | /* release devices */ | ||
3247 | info = slgt_device_list; | ||
3248 | while(info) { | ||
3249 | #ifdef CONFIG_HDLC | ||
3250 | hdlcdev_exit(info); | ||
3251 | #endif | ||
3252 | free_dma_bufs(info); | ||
3253 | free_tmp_rbuf(info); | ||
3254 | if (info->port_num == 0) | ||
3255 | release_resources(info); | ||
3256 | tmp = info; | ||
3257 | info = info->next_device; | ||
3258 | kfree(tmp); | ||
3259 | } | ||
3260 | |||
3261 | if (pci_registered) | ||
3262 | pci_unregister_driver(&pci_driver); | ||
3263 | } | ||
3264 | |||
3265 | /* | ||
3266 | * Driver initialization entry point. | ||
3267 | */ | ||
3268 | static int __init slgt_init(void) | ||
3269 | { | ||
3270 | int rc; | ||
3271 | |||
3272 | printk("%s %s\n", driver_name, driver_version); | ||
3273 | |||
3274 | slgt_device_count = 0; | ||
3275 | if ((rc = pci_register_driver(&pci_driver)) < 0) { | ||
3276 | printk("%s pci_register_driver error=%d\n", driver_name, rc); | ||
3277 | return rc; | ||
3278 | } | ||
3279 | pci_registered = 1; | ||
3280 | |||
3281 | if (!slgt_device_list) { | ||
3282 | printk("%s no devices found\n",driver_name); | ||
3283 | return -ENODEV; | ||
3284 | } | ||
3285 | |||
3286 | serial_driver = alloc_tty_driver(MAX_DEVICES); | ||
3287 | if (!serial_driver) { | ||
3288 | rc = -ENOMEM; | ||
3289 | goto error; | ||
3290 | } | ||
3291 | |||
3292 | /* Initialize the tty_driver structure */ | ||
3293 | |||
3294 | serial_driver->owner = THIS_MODULE; | ||
3295 | serial_driver->driver_name = tty_driver_name; | ||
3296 | serial_driver->name = tty_dev_prefix; | ||
3297 | serial_driver->major = ttymajor; | ||
3298 | serial_driver->minor_start = 64; | ||
3299 | serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
3300 | serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
3301 | serial_driver->init_termios = tty_std_termios; | ||
3302 | serial_driver->init_termios.c_cflag = | ||
3303 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
3304 | serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
3305 | tty_set_operations(serial_driver, &ops); | ||
3306 | if ((rc = tty_register_driver(serial_driver)) < 0) { | ||
3307 | DBGERR(("%s can't register serial driver\n", driver_name)); | ||
3308 | put_tty_driver(serial_driver); | ||
3309 | serial_driver = NULL; | ||
3310 | goto error; | ||
3311 | } | ||
3312 | |||
3313 | printk("%s %s, tty major#%d\n", | ||
3314 | driver_name, driver_version, | ||
3315 | serial_driver->major); | ||
3316 | |||
3317 | return 0; | ||
3318 | |||
3319 | error: | ||
3320 | slgt_cleanup(); | ||
3321 | return rc; | ||
3322 | } | ||
3323 | |||
3324 | static void __exit slgt_exit(void) | ||
3325 | { | ||
3326 | slgt_cleanup(); | ||
3327 | } | ||
3328 | |||
3329 | module_init(slgt_init); | ||
3330 | module_exit(slgt_exit); | ||
3331 | |||
3332 | /* | ||
3333 | * register access routines | ||
3334 | */ | ||
3335 | |||
3336 | #define CALC_REGADDR() \ | ||
3337 | unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \ | ||
3338 | if (addr >= 0x80) \ | ||
3339 | reg_addr += (info->port_num) * 32; | ||
3340 | |||
3341 | static __u8 rd_reg8(struct slgt_info *info, unsigned int addr) | ||
3342 | { | ||
3343 | CALC_REGADDR(); | ||
3344 | return readb((void __iomem *)reg_addr); | ||
3345 | } | ||
3346 | |||
3347 | static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value) | ||
3348 | { | ||
3349 | CALC_REGADDR(); | ||
3350 | writeb(value, (void __iomem *)reg_addr); | ||
3351 | } | ||
3352 | |||
3353 | static __u16 rd_reg16(struct slgt_info *info, unsigned int addr) | ||
3354 | { | ||
3355 | CALC_REGADDR(); | ||
3356 | return readw((void __iomem *)reg_addr); | ||
3357 | } | ||
3358 | |||
3359 | static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value) | ||
3360 | { | ||
3361 | CALC_REGADDR(); | ||
3362 | writew(value, (void __iomem *)reg_addr); | ||
3363 | } | ||
3364 | |||
3365 | static __u32 rd_reg32(struct slgt_info *info, unsigned int addr) | ||
3366 | { | ||
3367 | CALC_REGADDR(); | ||
3368 | return readl((void __iomem *)reg_addr); | ||
3369 | } | ||
3370 | |||
3371 | static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value) | ||
3372 | { | ||
3373 | CALC_REGADDR(); | ||
3374 | writel(value, (void __iomem *)reg_addr); | ||
3375 | } | ||
3376 | |||
3377 | static void rdma_reset(struct slgt_info *info) | ||
3378 | { | ||
3379 | unsigned int i; | ||
3380 | |||
3381 | /* set reset bit */ | ||
3382 | wr_reg32(info, RDCSR, BIT1); | ||
3383 | |||
3384 | /* wait for enable bit cleared */ | ||
3385 | for(i=0 ; i < 1000 ; i++) | ||
3386 | if (!(rd_reg32(info, RDCSR) & BIT0)) | ||
3387 | break; | ||
3388 | } | ||
3389 | |||
3390 | static void tdma_reset(struct slgt_info *info) | ||
3391 | { | ||
3392 | unsigned int i; | ||
3393 | |||
3394 | /* set reset bit */ | ||
3395 | wr_reg32(info, TDCSR, BIT1); | ||
3396 | |||
3397 | /* wait for enable bit cleared */ | ||
3398 | for(i=0 ; i < 1000 ; i++) | ||
3399 | if (!(rd_reg32(info, TDCSR) & BIT0)) | ||
3400 | break; | ||
3401 | } | ||
3402 | |||
3403 | /* | ||
3404 | * enable internal loopback | ||
3405 | * TxCLK and RxCLK are generated from BRG | ||
3406 | * and TxD is looped back to RxD internally. | ||
3407 | */ | ||
3408 | static void enable_loopback(struct slgt_info *info) | ||
3409 | { | ||
3410 | /* SCR (serial control) BIT2=looopback enable */ | ||
3411 | wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2)); | ||
3412 | |||
3413 | if (info->params.mode != MGSL_MODE_ASYNC) { | ||
3414 | /* CCR (clock control) | ||
3415 | * 07..05 tx clock source (010 = BRG) | ||
3416 | * 04..02 rx clock source (010 = BRG) | ||
3417 | * 01 auxclk enable (0 = disable) | ||
3418 | * 00 BRG enable (1 = enable) | ||
3419 | * | ||
3420 | * 0100 1001 | ||
3421 | */ | ||
3422 | wr_reg8(info, CCR, 0x49); | ||
3423 | |||
3424 | /* set speed if available, otherwise use default */ | ||
3425 | if (info->params.clock_speed) | ||
3426 | set_rate(info, info->params.clock_speed); | ||
3427 | else | ||
3428 | set_rate(info, 3686400); | ||
3429 | } | ||
3430 | } | ||
3431 | |||
3432 | /* | ||
3433 | * set baud rate generator to specified rate | ||
3434 | */ | ||
3435 | static void set_rate(struct slgt_info *info, u32 rate) | ||
3436 | { | ||
3437 | unsigned int div; | ||
3438 | static unsigned int osc = 14745600; | ||
3439 | |||
3440 | /* div = osc/rate - 1 | ||
3441 | * | ||
3442 | * Round div up if osc/rate is not integer to | ||
3443 | * force to next slowest rate. | ||
3444 | */ | ||
3445 | |||
3446 | if (rate) { | ||
3447 | div = osc/rate; | ||
3448 | if (!(osc % rate) && div) | ||
3449 | div--; | ||
3450 | wr_reg16(info, BDR, (unsigned short)div); | ||
3451 | } | ||
3452 | } | ||
3453 | |||
3454 | static void rx_stop(struct slgt_info *info) | ||
3455 | { | ||
3456 | unsigned short val; | ||
3457 | |||
3458 | /* disable and reset receiver */ | ||
3459 | val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ | ||
3460 | wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ | ||
3461 | wr_reg16(info, RCR, val); /* clear reset bit */ | ||
3462 | |||
3463 | slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE); | ||
3464 | |||
3465 | /* clear pending rx interrupts */ | ||
3466 | wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER); | ||
3467 | |||
3468 | rdma_reset(info); | ||
3469 | |||
3470 | info->rx_enabled = 0; | ||
3471 | info->rx_restart = 0; | ||
3472 | } | ||
3473 | |||
3474 | static void rx_start(struct slgt_info *info) | ||
3475 | { | ||
3476 | unsigned short val; | ||
3477 | |||
3478 | slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA); | ||
3479 | |||
3480 | /* clear pending rx overrun IRQ */ | ||
3481 | wr_reg16(info, SSR, IRQ_RXOVER); | ||
3482 | |||
3483 | /* reset and disable receiver */ | ||
3484 | val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */ | ||
3485 | wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */ | ||
3486 | wr_reg16(info, RCR, val); /* clear reset bit */ | ||
3487 | |||
3488 | rdma_reset(info); | ||
3489 | reset_rbufs(info); | ||
3490 | |||
3491 | /* set 1st descriptor address */ | ||
3492 | wr_reg32(info, RDDAR, info->rbufs[0].pdesc); | ||
3493 | |||
3494 | if (info->params.mode != MGSL_MODE_ASYNC) { | ||
3495 | /* enable rx DMA and DMA interrupt */ | ||
3496 | wr_reg32(info, RDCSR, (BIT2 + BIT0)); | ||
3497 | } else { | ||
3498 | /* enable saving of rx status, rx DMA and DMA interrupt */ | ||
3499 | wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); | ||
3500 | } | ||
3501 | |||
3502 | slgt_irq_on(info, IRQ_RXOVER); | ||
3503 | |||
3504 | /* enable receiver */ | ||
3505 | wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1)); | ||
3506 | |||
3507 | info->rx_restart = 0; | ||
3508 | info->rx_enabled = 1; | ||
3509 | } | ||
3510 | |||
3511 | static void tx_start(struct slgt_info *info) | ||
3512 | { | ||
3513 | if (!info->tx_enabled) { | ||
3514 | wr_reg16(info, TCR, | ||
3515 | (unsigned short)(rd_reg16(info, TCR) | BIT1)); | ||
3516 | info->tx_enabled = TRUE; | ||
3517 | } | ||
3518 | |||
3519 | if (info->tx_count) { | ||
3520 | info->drop_rts_on_tx_done = 0; | ||
3521 | |||
3522 | if (info->params.mode != MGSL_MODE_ASYNC) { | ||
3523 | if (info->params.flags & HDLC_FLAG_AUTO_RTS) { | ||
3524 | get_signals(info); | ||
3525 | if (!(info->signals & SerialSignal_RTS)) { | ||
3526 | info->signals |= SerialSignal_RTS; | ||
3527 | set_signals(info); | ||
3528 | info->drop_rts_on_tx_done = 1; | ||
3529 | } | ||
3530 | } | ||
3531 | |||
3532 | slgt_irq_off(info, IRQ_TXDATA); | ||
3533 | slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); | ||
3534 | /* clear tx idle and underrun status bits */ | ||
3535 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); | ||
3536 | |||
3537 | if (!(rd_reg32(info, TDCSR) & BIT0)) { | ||
3538 | /* tx DMA stopped, restart tx DMA */ | ||
3539 | tdma_reset(info); | ||
3540 | /* set 1st descriptor address */ | ||
3541 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
3542 | if (info->params.mode == MGSL_MODE_RAW) | ||
3543 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
3544 | else | ||
3545 | wr_reg32(info, TDCSR, BIT0); /* DMA enable */ | ||
3546 | } | ||
3547 | |||
3548 | if (info->params.mode != MGSL_MODE_RAW) { | ||
3549 | info->tx_timer.expires = jiffies + msecs_to_jiffies(5000); | ||
3550 | add_timer(&info->tx_timer); | ||
3551 | } | ||
3552 | } else { | ||
3553 | tdma_reset(info); | ||
3554 | /* set 1st descriptor address */ | ||
3555 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
3556 | |||
3557 | slgt_irq_off(info, IRQ_TXDATA); | ||
3558 | slgt_irq_on(info, IRQ_TXIDLE); | ||
3559 | /* clear tx idle status bit */ | ||
3560 | wr_reg16(info, SSR, IRQ_TXIDLE); | ||
3561 | |||
3562 | /* enable tx DMA */ | ||
3563 | wr_reg32(info, TDCSR, BIT0); | ||
3564 | } | ||
3565 | |||
3566 | info->tx_active = 1; | ||
3567 | } | ||
3568 | } | ||
3569 | |||
3570 | static void tx_stop(struct slgt_info *info) | ||
3571 | { | ||
3572 | unsigned short val; | ||
3573 | |||
3574 | del_timer(&info->tx_timer); | ||
3575 | |||
3576 | tdma_reset(info); | ||
3577 | |||
3578 | /* reset and disable transmitter */ | ||
3579 | val = rd_reg16(info, TCR) & ~BIT1; /* clear enable bit */ | ||
3580 | wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */ | ||
3581 | wr_reg16(info, TCR, val); /* clear reset */ | ||
3582 | |||
3583 | slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER); | ||
3584 | |||
3585 | /* clear tx idle and underrun status bit */ | ||
3586 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); | ||
3587 | |||
3588 | reset_tbufs(info); | ||
3589 | |||
3590 | info->tx_enabled = 0; | ||
3591 | info->tx_active = 0; | ||
3592 | } | ||
3593 | |||
3594 | static void reset_port(struct slgt_info *info) | ||
3595 | { | ||
3596 | if (!info->reg_addr) | ||
3597 | return; | ||
3598 | |||
3599 | tx_stop(info); | ||
3600 | rx_stop(info); | ||
3601 | |||
3602 | info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS); | ||
3603 | set_signals(info); | ||
3604 | |||
3605 | slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); | ||
3606 | } | ||
3607 | |||
3608 | static void reset_adapter(struct slgt_info *info) | ||
3609 | { | ||
3610 | int i; | ||
3611 | for (i=0; i < info->port_count; ++i) { | ||
3612 | if (info->port_array[i]) | ||
3613 | reset_port(info->port_array[i]); | ||
3614 | } | ||
3615 | } | ||
3616 | |||
3617 | static void async_mode(struct slgt_info *info) | ||
3618 | { | ||
3619 | unsigned short val; | ||
3620 | |||
3621 | slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); | ||
3622 | tx_stop(info); | ||
3623 | rx_stop(info); | ||
3624 | |||
3625 | /* TCR (tx control) | ||
3626 | * | ||
3627 | * 15..13 mode, 010=async | ||
3628 | * 12..10 encoding, 000=NRZ | ||
3629 | * 09 parity enable | ||
3630 | * 08 1=odd parity, 0=even parity | ||
3631 | * 07 1=RTS driver control | ||
3632 | * 06 1=break enable | ||
3633 | * 05..04 character length | ||
3634 | * 00=5 bits | ||
3635 | * 01=6 bits | ||
3636 | * 10=7 bits | ||
3637 | * 11=8 bits | ||
3638 | * 03 0=1 stop bit, 1=2 stop bits | ||
3639 | * 02 reset | ||
3640 | * 01 enable | ||
3641 | * 00 auto-CTS enable | ||
3642 | */ | ||
3643 | val = 0x4000; | ||
3644 | |||
3645 | if (info->if_mode & MGSL_INTERFACE_RTS_EN) | ||
3646 | val |= BIT7; | ||
3647 | |||
3648 | if (info->params.parity != ASYNC_PARITY_NONE) { | ||
3649 | val |= BIT9; | ||
3650 | if (info->params.parity == ASYNC_PARITY_ODD) | ||
3651 | val |= BIT8; | ||
3652 | } | ||
3653 | |||
3654 | switch (info->params.data_bits) | ||
3655 | { | ||
3656 | case 6: val |= BIT4; break; | ||
3657 | case 7: val |= BIT5; break; | ||
3658 | case 8: val |= BIT5 + BIT4; break; | ||
3659 | } | ||
3660 | |||
3661 | if (info->params.stop_bits != 1) | ||
3662 | val |= BIT3; | ||
3663 | |||
3664 | if (info->params.flags & HDLC_FLAG_AUTO_CTS) | ||
3665 | val |= BIT0; | ||
3666 | |||
3667 | wr_reg16(info, TCR, val); | ||
3668 | |||
3669 | /* RCR (rx control) | ||
3670 | * | ||
3671 | * 15..13 mode, 010=async | ||
3672 | * 12..10 encoding, 000=NRZ | ||
3673 | * 09 parity enable | ||
3674 | * 08 1=odd parity, 0=even parity | ||
3675 | * 07..06 reserved, must be 0 | ||
3676 | * 05..04 character length | ||
3677 | * 00=5 bits | ||
3678 | * 01=6 bits | ||
3679 | * 10=7 bits | ||
3680 | * 11=8 bits | ||
3681 | * 03 reserved, must be zero | ||
3682 | * 02 reset | ||
3683 | * 01 enable | ||
3684 | * 00 auto-DCD enable | ||
3685 | */ | ||
3686 | val = 0x4000; | ||
3687 | |||
3688 | if (info->params.parity != ASYNC_PARITY_NONE) { | ||
3689 | val |= BIT9; | ||
3690 | if (info->params.parity == ASYNC_PARITY_ODD) | ||
3691 | val |= BIT8; | ||
3692 | } | ||
3693 | |||
3694 | switch (info->params.data_bits) | ||
3695 | { | ||
3696 | case 6: val |= BIT4; break; | ||
3697 | case 7: val |= BIT5; break; | ||
3698 | case 8: val |= BIT5 + BIT4; break; | ||
3699 | } | ||
3700 | |||
3701 | if (info->params.flags & HDLC_FLAG_AUTO_DCD) | ||
3702 | val |= BIT0; | ||
3703 | |||
3704 | wr_reg16(info, RCR, val); | ||
3705 | |||
3706 | /* CCR (clock control) | ||
3707 | * | ||
3708 | * 07..05 011 = tx clock source is BRG/16 | ||
3709 | * 04..02 010 = rx clock source is BRG | ||
3710 | * 01 0 = auxclk disabled | ||
3711 | * 00 1 = BRG enabled | ||
3712 | * | ||
3713 | * 0110 1001 | ||
3714 | */ | ||
3715 | wr_reg8(info, CCR, 0x69); | ||
3716 | |||
3717 | msc_set_vcr(info); | ||
3718 | |||
3719 | tx_set_idle(info); | ||
3720 | |||
3721 | /* SCR (serial control) | ||
3722 | * | ||
3723 | * 15 1=tx req on FIFO half empty | ||
3724 | * 14 1=rx req on FIFO half full | ||
3725 | * 13 tx data IRQ enable | ||
3726 | * 12 tx idle IRQ enable | ||
3727 | * 11 rx break on IRQ enable | ||
3728 | * 10 rx data IRQ enable | ||
3729 | * 09 rx break off IRQ enable | ||
3730 | * 08 overrun IRQ enable | ||
3731 | * 07 DSR IRQ enable | ||
3732 | * 06 CTS IRQ enable | ||
3733 | * 05 DCD IRQ enable | ||
3734 | * 04 RI IRQ enable | ||
3735 | * 03 reserved, must be zero | ||
3736 | * 02 1=txd->rxd internal loopback enable | ||
3737 | * 01 reserved, must be zero | ||
3738 | * 00 1=master IRQ enable | ||
3739 | */ | ||
3740 | val = BIT15 + BIT14 + BIT0; | ||
3741 | wr_reg16(info, SCR, val); | ||
3742 | |||
3743 | slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER); | ||
3744 | |||
3745 | set_rate(info, info->params.data_rate * 16); | ||
3746 | |||
3747 | if (info->params.loopback) | ||
3748 | enable_loopback(info); | ||
3749 | } | ||
3750 | |||
3751 | static void hdlc_mode(struct slgt_info *info) | ||
3752 | { | ||
3753 | unsigned short val; | ||
3754 | |||
3755 | slgt_irq_off(info, IRQ_ALL | IRQ_MASTER); | ||
3756 | tx_stop(info); | ||
3757 | rx_stop(info); | ||
3758 | |||
3759 | /* TCR (tx control) | ||
3760 | * | ||
3761 | * 15..13 mode, 000=HDLC 001=raw sync | ||
3762 | * 12..10 encoding | ||
3763 | * 09 CRC enable | ||
3764 | * 08 CRC32 | ||
3765 | * 07 1=RTS driver control | ||
3766 | * 06 preamble enable | ||
3767 | * 05..04 preamble length | ||
3768 | * 03 share open/close flag | ||
3769 | * 02 reset | ||
3770 | * 01 enable | ||
3771 | * 00 auto-CTS enable | ||
3772 | */ | ||
3773 | val = 0; | ||
3774 | |||
3775 | if (info->params.mode == MGSL_MODE_RAW) | ||
3776 | val |= BIT13; | ||
3777 | if (info->if_mode & MGSL_INTERFACE_RTS_EN) | ||
3778 | val |= BIT7; | ||
3779 | |||
3780 | switch(info->params.encoding) | ||
3781 | { | ||
3782 | case HDLC_ENCODING_NRZB: val |= BIT10; break; | ||
3783 | case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; | ||
3784 | case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; | ||
3785 | case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; | ||
3786 | case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; | ||
3787 | case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; | ||
3788 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; | ||
3789 | } | ||
3790 | |||
3791 | switch (info->params.crc_type) | ||
3792 | { | ||
3793 | case HDLC_CRC_16_CCITT: val |= BIT9; break; | ||
3794 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; | ||
3795 | } | ||
3796 | |||
3797 | if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE) | ||
3798 | val |= BIT6; | ||
3799 | |||
3800 | switch (info->params.preamble_length) | ||
3801 | { | ||
3802 | case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break; | ||
3803 | case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break; | ||
3804 | case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break; | ||
3805 | } | ||
3806 | |||
3807 | if (info->params.flags & HDLC_FLAG_AUTO_CTS) | ||
3808 | val |= BIT0; | ||
3809 | |||
3810 | wr_reg16(info, TCR, val); | ||
3811 | |||
3812 | /* TPR (transmit preamble) */ | ||
3813 | |||
3814 | switch (info->params.preamble) | ||
3815 | { | ||
3816 | case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break; | ||
3817 | case HDLC_PREAMBLE_PATTERN_ONES: val = 0xff; break; | ||
3818 | case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break; | ||
3819 | case HDLC_PREAMBLE_PATTERN_10: val = 0x55; break; | ||
3820 | case HDLC_PREAMBLE_PATTERN_01: val = 0xaa; break; | ||
3821 | default: val = 0x7e; break; | ||
3822 | } | ||
3823 | wr_reg8(info, TPR, (unsigned char)val); | ||
3824 | |||
3825 | /* RCR (rx control) | ||
3826 | * | ||
3827 | * 15..13 mode, 000=HDLC 001=raw sync | ||
3828 | * 12..10 encoding | ||
3829 | * 09 CRC enable | ||
3830 | * 08 CRC32 | ||
3831 | * 07..03 reserved, must be 0 | ||
3832 | * 02 reset | ||
3833 | * 01 enable | ||
3834 | * 00 auto-DCD enable | ||
3835 | */ | ||
3836 | val = 0; | ||
3837 | |||
3838 | if (info->params.mode == MGSL_MODE_RAW) | ||
3839 | val |= BIT13; | ||
3840 | |||
3841 | switch(info->params.encoding) | ||
3842 | { | ||
3843 | case HDLC_ENCODING_NRZB: val |= BIT10; break; | ||
3844 | case HDLC_ENCODING_NRZI_MARK: val |= BIT11; break; | ||
3845 | case HDLC_ENCODING_NRZI: val |= BIT11 + BIT10; break; | ||
3846 | case HDLC_ENCODING_BIPHASE_MARK: val |= BIT12; break; | ||
3847 | case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break; | ||
3848 | case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break; | ||
3849 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; | ||
3850 | } | ||
3851 | |||
3852 | switch (info->params.crc_type) | ||
3853 | { | ||
3854 | case HDLC_CRC_16_CCITT: val |= BIT9; break; | ||
3855 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; | ||
3856 | } | ||
3857 | |||
3858 | if (info->params.flags & HDLC_FLAG_AUTO_DCD) | ||
3859 | val |= BIT0; | ||
3860 | |||
3861 | wr_reg16(info, RCR, val); | ||
3862 | |||
3863 | /* CCR (clock control) | ||
3864 | * | ||
3865 | * 07..05 tx clock source | ||
3866 | * 04..02 rx clock source | ||
3867 | * 01 auxclk enable | ||
3868 | * 00 BRG enable | ||
3869 | */ | ||
3870 | val = 0; | ||
3871 | |||
3872 | if (info->params.flags & HDLC_FLAG_TXC_BRG) | ||
3873 | { | ||
3874 | // when RxC source is DPLL, BRG generates 16X DPLL | ||
3875 | // reference clock, so take TxC from BRG/16 to get | ||
3876 | // transmit clock at actual data rate | ||
3877 | if (info->params.flags & HDLC_FLAG_RXC_DPLL) | ||
3878 | val |= BIT6 + BIT5; /* 011, txclk = BRG/16 */ | ||
3879 | else | ||
3880 | val |= BIT6; /* 010, txclk = BRG */ | ||
3881 | } | ||
3882 | else if (info->params.flags & HDLC_FLAG_TXC_DPLL) | ||
3883 | val |= BIT7; /* 100, txclk = DPLL Input */ | ||
3884 | else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN) | ||
3885 | val |= BIT5; /* 001, txclk = RXC Input */ | ||
3886 | |||
3887 | if (info->params.flags & HDLC_FLAG_RXC_BRG) | ||
3888 | val |= BIT3; /* 010, rxclk = BRG */ | ||
3889 | else if (info->params.flags & HDLC_FLAG_RXC_DPLL) | ||
3890 | val |= BIT4; /* 100, rxclk = DPLL */ | ||
3891 | else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN) | ||
3892 | val |= BIT2; /* 001, rxclk = TXC Input */ | ||
3893 | |||
3894 | if (info->params.clock_speed) | ||
3895 | val |= BIT1 + BIT0; | ||
3896 | |||
3897 | wr_reg8(info, CCR, (unsigned char)val); | ||
3898 | |||
3899 | if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL)) | ||
3900 | { | ||
3901 | // program DPLL mode | ||
3902 | switch(info->params.encoding) | ||
3903 | { | ||
3904 | case HDLC_ENCODING_BIPHASE_MARK: | ||
3905 | case HDLC_ENCODING_BIPHASE_SPACE: | ||
3906 | val = BIT7; break; | ||
3907 | case HDLC_ENCODING_BIPHASE_LEVEL: | ||
3908 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: | ||
3909 | val = BIT7 + BIT6; break; | ||
3910 | default: val = BIT6; // NRZ encodings | ||
3911 | } | ||
3912 | wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val)); | ||
3913 | |||
3914 | // DPLL requires a 16X reference clock from BRG | ||
3915 | set_rate(info, info->params.clock_speed * 16); | ||
3916 | } | ||
3917 | else | ||
3918 | set_rate(info, info->params.clock_speed); | ||
3919 | |||
3920 | tx_set_idle(info); | ||
3921 | |||
3922 | msc_set_vcr(info); | ||
3923 | |||
3924 | /* SCR (serial control) | ||
3925 | * | ||
3926 | * 15 1=tx req on FIFO half empty | ||
3927 | * 14 1=rx req on FIFO half full | ||
3928 | * 13 tx data IRQ enable | ||
3929 | * 12 tx idle IRQ enable | ||
3930 | * 11 underrun IRQ enable | ||
3931 | * 10 rx data IRQ enable | ||
3932 | * 09 rx idle IRQ enable | ||
3933 | * 08 overrun IRQ enable | ||
3934 | * 07 DSR IRQ enable | ||
3935 | * 06 CTS IRQ enable | ||
3936 | * 05 DCD IRQ enable | ||
3937 | * 04 RI IRQ enable | ||
3938 | * 03 reserved, must be zero | ||
3939 | * 02 1=txd->rxd internal loopback enable | ||
3940 | * 01 reserved, must be zero | ||
3941 | * 00 1=master IRQ enable | ||
3942 | */ | ||
3943 | wr_reg16(info, SCR, BIT15 + BIT14 + BIT0); | ||
3944 | |||
3945 | if (info->params.loopback) | ||
3946 | enable_loopback(info); | ||
3947 | } | ||
3948 | |||
3949 | /* | ||
3950 | * set transmit idle mode | ||
3951 | */ | ||
3952 | static void tx_set_idle(struct slgt_info *info) | ||
3953 | { | ||
3954 | unsigned char val = 0xff; | ||
3955 | |||
3956 | switch(info->idle_mode) | ||
3957 | { | ||
3958 | case HDLC_TXIDLE_FLAGS: val = 0x7e; break; | ||
3959 | case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break; | ||
3960 | case HDLC_TXIDLE_ZEROS: val = 0x00; break; | ||
3961 | case HDLC_TXIDLE_ONES: val = 0xff; break; | ||
3962 | case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break; | ||
3963 | case HDLC_TXIDLE_SPACE: val = 0x00; break; | ||
3964 | case HDLC_TXIDLE_MARK: val = 0xff; break; | ||
3965 | } | ||
3966 | |||
3967 | wr_reg8(info, TIR, val); | ||
3968 | } | ||
3969 | |||
3970 | /* | ||
3971 | * get state of V24 status (input) signals | ||
3972 | */ | ||
3973 | static void get_signals(struct slgt_info *info) | ||
3974 | { | ||
3975 | unsigned short status = rd_reg16(info, SSR); | ||
3976 | |||
3977 | /* clear all serial signals except DTR and RTS */ | ||
3978 | info->signals &= SerialSignal_DTR + SerialSignal_RTS; | ||
3979 | |||
3980 | if (status & BIT3) | ||
3981 | info->signals |= SerialSignal_DSR; | ||
3982 | if (status & BIT2) | ||
3983 | info->signals |= SerialSignal_CTS; | ||
3984 | if (status & BIT1) | ||
3985 | info->signals |= SerialSignal_DCD; | ||
3986 | if (status & BIT0) | ||
3987 | info->signals |= SerialSignal_RI; | ||
3988 | } | ||
3989 | |||
3990 | /* | ||
3991 | * set V.24 Control Register based on current configuration | ||
3992 | */ | ||
3993 | static void msc_set_vcr(struct slgt_info *info) | ||
3994 | { | ||
3995 | unsigned char val = 0; | ||
3996 | |||
3997 | /* VCR (V.24 control) | ||
3998 | * | ||
3999 | * 07..04 serial IF select | ||
4000 | * 03 DTR | ||
4001 | * 02 RTS | ||
4002 | * 01 LL | ||
4003 | * 00 RL | ||
4004 | */ | ||
4005 | |||
4006 | switch(info->if_mode & MGSL_INTERFACE_MASK) | ||
4007 | { | ||
4008 | case MGSL_INTERFACE_RS232: | ||
4009 | val |= BIT5; /* 0010 */ | ||
4010 | break; | ||
4011 | case MGSL_INTERFACE_V35: | ||
4012 | val |= BIT7 + BIT6 + BIT5; /* 1110 */ | ||
4013 | break; | ||
4014 | case MGSL_INTERFACE_RS422: | ||
4015 | val |= BIT6; /* 0100 */ | ||
4016 | break; | ||
4017 | } | ||
4018 | |||
4019 | if (info->signals & SerialSignal_DTR) | ||
4020 | val |= BIT3; | ||
4021 | if (info->signals & SerialSignal_RTS) | ||
4022 | val |= BIT2; | ||
4023 | if (info->if_mode & MGSL_INTERFACE_LL) | ||
4024 | val |= BIT1; | ||
4025 | if (info->if_mode & MGSL_INTERFACE_RL) | ||
4026 | val |= BIT0; | ||
4027 | wr_reg8(info, VCR, val); | ||
4028 | } | ||
4029 | |||
4030 | /* | ||
4031 | * set state of V24 control (output) signals | ||
4032 | */ | ||
4033 | static void set_signals(struct slgt_info *info) | ||
4034 | { | ||
4035 | unsigned char val = rd_reg8(info, VCR); | ||
4036 | if (info->signals & SerialSignal_DTR) | ||
4037 | val |= BIT3; | ||
4038 | else | ||
4039 | val &= ~BIT3; | ||
4040 | if (info->signals & SerialSignal_RTS) | ||
4041 | val |= BIT2; | ||
4042 | else | ||
4043 | val &= ~BIT2; | ||
4044 | wr_reg8(info, VCR, val); | ||
4045 | } | ||
4046 | |||
4047 | /* | ||
4048 | * free range of receive DMA buffers (i to last) | ||
4049 | */ | ||
4050 | static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last) | ||
4051 | { | ||
4052 | int done = 0; | ||
4053 | |||
4054 | while(!done) { | ||
4055 | /* reset current buffer for reuse */ | ||
4056 | info->rbufs[i].status = 0; | ||
4057 | if (info->params.mode == MGSL_MODE_RAW) | ||
4058 | set_desc_count(info->rbufs[i], info->raw_rx_size); | ||
4059 | else | ||
4060 | set_desc_count(info->rbufs[i], DMABUFSIZE); | ||
4061 | |||
4062 | if (i == last) | ||
4063 | done = 1; | ||
4064 | if (++i == info->rbuf_count) | ||
4065 | i = 0; | ||
4066 | } | ||
4067 | info->rbuf_current = i; | ||
4068 | } | ||
4069 | |||
4070 | /* | ||
4071 | * mark all receive DMA buffers as free | ||
4072 | */ | ||
4073 | static void reset_rbufs(struct slgt_info *info) | ||
4074 | { | ||
4075 | free_rbufs(info, 0, info->rbuf_count - 1); | ||
4076 | } | ||
4077 | |||
4078 | /* | ||
4079 | * pass receive HDLC frame to upper layer | ||
4080 | * | ||
4081 | * return 1 if frame available, otherwise 0 | ||
4082 | */ | ||
4083 | static int rx_get_frame(struct slgt_info *info) | ||
4084 | { | ||
4085 | unsigned int start, end; | ||
4086 | unsigned short status; | ||
4087 | unsigned int framesize = 0; | ||
4088 | int rc = 0; | ||
4089 | unsigned long flags; | ||
4090 | struct tty_struct *tty = info->tty; | ||
4091 | unsigned char addr_field = 0xff; | ||
4092 | |||
4093 | check_again: | ||
4094 | |||
4095 | framesize = 0; | ||
4096 | addr_field = 0xff; | ||
4097 | start = end = info->rbuf_current; | ||
4098 | |||
4099 | for (;;) { | ||
4100 | if (!desc_complete(info->rbufs[end])) | ||
4101 | goto cleanup; | ||
4102 | |||
4103 | if (framesize == 0 && info->params.addr_filter != 0xff) | ||
4104 | addr_field = info->rbufs[end].buf[0]; | ||
4105 | |||
4106 | framesize += desc_count(info->rbufs[end]); | ||
4107 | |||
4108 | if (desc_eof(info->rbufs[end])) | ||
4109 | break; | ||
4110 | |||
4111 | if (++end == info->rbuf_count) | ||
4112 | end = 0; | ||
4113 | |||
4114 | if (end == info->rbuf_current) { | ||
4115 | if (info->rx_enabled){ | ||
4116 | spin_lock_irqsave(&info->lock,flags); | ||
4117 | rx_start(info); | ||
4118 | spin_unlock_irqrestore(&info->lock,flags); | ||
4119 | } | ||
4120 | goto cleanup; | ||
4121 | } | ||
4122 | } | ||
4123 | |||
4124 | /* status | ||
4125 | * | ||
4126 | * 15 buffer complete | ||
4127 | * 14..06 reserved | ||
4128 | * 05..04 residue | ||
4129 | * 02 eof (end of frame) | ||
4130 | * 01 CRC error | ||
4131 | * 00 abort | ||
4132 | */ | ||
4133 | status = desc_status(info->rbufs[end]); | ||
4134 | |||
4135 | /* ignore CRC bit if not using CRC (bit is undefined) */ | ||
4136 | if (info->params.crc_type == HDLC_CRC_NONE) | ||
4137 | status &= ~BIT1; | ||
4138 | |||
4139 | if (framesize == 0 || | ||
4140 | (addr_field != 0xff && addr_field != info->params.addr_filter)) { | ||
4141 | free_rbufs(info, start, end); | ||
4142 | goto check_again; | ||
4143 | } | ||
4144 | |||
4145 | if (framesize < 2 || status & (BIT1+BIT0)) { | ||
4146 | if (framesize < 2 || (status & BIT0)) | ||
4147 | info->icount.rxshort++; | ||
4148 | else | ||
4149 | info->icount.rxcrc++; | ||
4150 | framesize = 0; | ||
4151 | |||
4152 | #ifdef CONFIG_HDLC | ||
4153 | { | ||
4154 | struct net_device_stats *stats = hdlc_stats(info->netdev); | ||
4155 | stats->rx_errors++; | ||
4156 | stats->rx_frame_errors++; | ||
4157 | } | ||
4158 | #endif | ||
4159 | } else { | ||
4160 | /* adjust frame size for CRC, if any */ | ||
4161 | if (info->params.crc_type == HDLC_CRC_16_CCITT) | ||
4162 | framesize -= 2; | ||
4163 | else if (info->params.crc_type == HDLC_CRC_32_CCITT) | ||
4164 | framesize -= 4; | ||
4165 | } | ||
4166 | |||
4167 | DBGBH(("%s rx frame status=%04X size=%d\n", | ||
4168 | info->device_name, status, framesize)); | ||
4169 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); | ||
4170 | |||
4171 | if (framesize) { | ||
4172 | if (framesize > info->max_frame_size) | ||
4173 | info->icount.rxlong++; | ||
4174 | else { | ||
4175 | /* copy dma buffer(s) to contiguous temp buffer */ | ||
4176 | int copy_count = framesize; | ||
4177 | int i = start; | ||
4178 | unsigned char *p = info->tmp_rbuf; | ||
4179 | info->tmp_rbuf_count = framesize; | ||
4180 | |||
4181 | info->icount.rxok++; | ||
4182 | |||
4183 | while(copy_count) { | ||
4184 | int partial_count = min(copy_count, DMABUFSIZE); | ||
4185 | memcpy(p, info->rbufs[i].buf, partial_count); | ||
4186 | p += partial_count; | ||
4187 | copy_count -= partial_count; | ||
4188 | if (++i == info->rbuf_count) | ||
4189 | i = 0; | ||
4190 | } | ||
4191 | |||
4192 | #ifdef CONFIG_HDLC | ||
4193 | if (info->netcount) | ||
4194 | hdlcdev_rx(info,info->tmp_rbuf, framesize); | ||
4195 | else | ||
4196 | #endif | ||
4197 | ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize); | ||
4198 | } | ||
4199 | } | ||
4200 | free_rbufs(info, start, end); | ||
4201 | rc = 1; | ||
4202 | |||
4203 | cleanup: | ||
4204 | return rc; | ||
4205 | } | ||
4206 | |||
4207 | /* | ||
4208 | * pass receive buffer (RAW synchronous mode) to tty layer | ||
4209 | * return 1 if buffer available, otherwise 0 | ||
4210 | */ | ||
4211 | static int rx_get_buf(struct slgt_info *info) | ||
4212 | { | ||
4213 | unsigned int i = info->rbuf_current; | ||
4214 | |||
4215 | if (!desc_complete(info->rbufs[i])) | ||
4216 | return 0; | ||
4217 | DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx"); | ||
4218 | DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i]))); | ||
4219 | ldisc_receive_buf(info->tty, info->rbufs[i].buf, | ||
4220 | info->flag_buf, desc_count(info->rbufs[i])); | ||
4221 | free_rbufs(info, i, i); | ||
4222 | return 1; | ||
4223 | } | ||
4224 | |||
4225 | static void reset_tbufs(struct slgt_info *info) | ||
4226 | { | ||
4227 | unsigned int i; | ||
4228 | info->tbuf_current = 0; | ||
4229 | for (i=0 ; i < info->tbuf_count ; i++) { | ||
4230 | info->tbufs[i].status = 0; | ||
4231 | info->tbufs[i].count = 0; | ||
4232 | } | ||
4233 | } | ||
4234 | |||
4235 | /* | ||
4236 | * return number of free transmit DMA buffers | ||
4237 | */ | ||
4238 | static unsigned int free_tbuf_count(struct slgt_info *info) | ||
4239 | { | ||
4240 | unsigned int count = 0; | ||
4241 | unsigned int i = info->tbuf_current; | ||
4242 | |||
4243 | do | ||
4244 | { | ||
4245 | if (desc_count(info->tbufs[i])) | ||
4246 | break; /* buffer in use */ | ||
4247 | ++count; | ||
4248 | if (++i == info->tbuf_count) | ||
4249 | i=0; | ||
4250 | } while (i != info->tbuf_current); | ||
4251 | |||
4252 | /* last buffer with zero count may be in use, assume it is */ | ||
4253 | if (count) | ||
4254 | --count; | ||
4255 | |||
4256 | return count; | ||
4257 | } | ||
4258 | |||
4259 | /* | ||
4260 | * load transmit DMA buffer(s) with data | ||
4261 | */ | ||
4262 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | ||
4263 | { | ||
4264 | unsigned short count; | ||
4265 | unsigned int i; | ||
4266 | struct slgt_desc *d; | ||
4267 | |||
4268 | if (size == 0) | ||
4269 | return; | ||
4270 | |||
4271 | DBGDATA(info, buf, size, "tx"); | ||
4272 | |||
4273 | info->tbuf_start = i = info->tbuf_current; | ||
4274 | |||
4275 | while (size) { | ||
4276 | d = &info->tbufs[i]; | ||
4277 | if (++i == info->tbuf_count) | ||
4278 | i = 0; | ||
4279 | |||
4280 | count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size); | ||
4281 | memcpy(d->buf, buf, count); | ||
4282 | |||
4283 | size -= count; | ||
4284 | buf += count; | ||
4285 | |||
4286 | if (!size && info->params.mode != MGSL_MODE_RAW) | ||
4287 | set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */ | ||
4288 | else | ||
4289 | set_desc_eof(*d, 0); | ||
4290 | |||
4291 | set_desc_count(*d, count); | ||
4292 | } | ||
4293 | |||
4294 | info->tbuf_current = i; | ||
4295 | } | ||
4296 | |||
4297 | static int register_test(struct slgt_info *info) | ||
4298 | { | ||
4299 | static unsigned short patterns[] = | ||
4300 | {0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696}; | ||
4301 | static unsigned int count = sizeof(patterns)/sizeof(patterns[0]); | ||
4302 | unsigned int i; | ||
4303 | int rc = 0; | ||
4304 | |||
4305 | for (i=0 ; i < count ; i++) { | ||
4306 | wr_reg16(info, TIR, patterns[i]); | ||
4307 | wr_reg16(info, BDR, patterns[(i+1)%count]); | ||
4308 | if ((rd_reg16(info, TIR) != patterns[i]) || | ||
4309 | (rd_reg16(info, BDR) != patterns[(i+1)%count])) { | ||
4310 | rc = -ENODEV; | ||
4311 | break; | ||
4312 | } | ||
4313 | } | ||
4314 | |||
4315 | info->init_error = rc ? 0 : DiagStatus_AddressFailure; | ||
4316 | return rc; | ||
4317 | } | ||
4318 | |||
4319 | static int irq_test(struct slgt_info *info) | ||
4320 | { | ||
4321 | unsigned long timeout; | ||
4322 | unsigned long flags; | ||
4323 | struct tty_struct *oldtty = info->tty; | ||
4324 | u32 speed = info->params.data_rate; | ||
4325 | |||
4326 | info->params.data_rate = 921600; | ||
4327 | info->tty = NULL; | ||
4328 | |||
4329 | spin_lock_irqsave(&info->lock, flags); | ||
4330 | async_mode(info); | ||
4331 | slgt_irq_on(info, IRQ_TXIDLE); | ||
4332 | |||
4333 | /* enable transmitter */ | ||
4334 | wr_reg16(info, TCR, | ||
4335 | (unsigned short)(rd_reg16(info, TCR) | BIT1)); | ||
4336 | |||
4337 | /* write one byte and wait for tx idle */ | ||
4338 | wr_reg16(info, TDR, 0); | ||
4339 | |||
4340 | /* assume failure */ | ||
4341 | info->init_error = DiagStatus_IrqFailure; | ||
4342 | info->irq_occurred = FALSE; | ||
4343 | |||
4344 | spin_unlock_irqrestore(&info->lock, flags); | ||
4345 | |||
4346 | timeout=100; | ||
4347 | while(timeout-- && !info->irq_occurred) | ||
4348 | msleep_interruptible(10); | ||
4349 | |||
4350 | spin_lock_irqsave(&info->lock,flags); | ||
4351 | reset_port(info); | ||
4352 | spin_unlock_irqrestore(&info->lock,flags); | ||
4353 | |||
4354 | info->params.data_rate = speed; | ||
4355 | info->tty = oldtty; | ||
4356 | |||
4357 | info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure; | ||
4358 | return info->irq_occurred ? 0 : -ENODEV; | ||
4359 | } | ||
4360 | |||
4361 | static int loopback_test_rx(struct slgt_info *info) | ||
4362 | { | ||
4363 | unsigned char *src, *dest; | ||
4364 | int count; | ||
4365 | |||
4366 | if (desc_complete(info->rbufs[0])) { | ||
4367 | count = desc_count(info->rbufs[0]); | ||
4368 | src = info->rbufs[0].buf; | ||
4369 | dest = info->tmp_rbuf; | ||
4370 | |||
4371 | for( ; count ; count-=2, src+=2) { | ||
4372 | /* src=data byte (src+1)=status byte */ | ||
4373 | if (!(*(src+1) & (BIT9 + BIT8))) { | ||
4374 | *dest = *src; | ||
4375 | dest++; | ||
4376 | info->tmp_rbuf_count++; | ||
4377 | } | ||
4378 | } | ||
4379 | DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx"); | ||
4380 | return 1; | ||
4381 | } | ||
4382 | return 0; | ||
4383 | } | ||
4384 | |||
4385 | static int loopback_test(struct slgt_info *info) | ||
4386 | { | ||
4387 | #define TESTFRAMESIZE 20 | ||
4388 | |||
4389 | unsigned long timeout; | ||
4390 | u16 count = TESTFRAMESIZE; | ||
4391 | unsigned char buf[TESTFRAMESIZE]; | ||
4392 | int rc = -ENODEV; | ||
4393 | unsigned long flags; | ||
4394 | |||
4395 | struct tty_struct *oldtty = info->tty; | ||
4396 | MGSL_PARAMS params; | ||
4397 | |||
4398 | memcpy(¶ms, &info->params, sizeof(params)); | ||
4399 | |||
4400 | info->params.mode = MGSL_MODE_ASYNC; | ||
4401 | info->params.data_rate = 921600; | ||
4402 | info->params.loopback = 1; | ||
4403 | info->tty = NULL; | ||
4404 | |||
4405 | /* build and send transmit frame */ | ||
4406 | for (count = 0; count < TESTFRAMESIZE; ++count) | ||
4407 | buf[count] = (unsigned char)count; | ||
4408 | |||
4409 | info->tmp_rbuf_count = 0; | ||
4410 | memset(info->tmp_rbuf, 0, TESTFRAMESIZE); | ||
4411 | |||
4412 | /* program hardware for HDLC and enabled receiver */ | ||
4413 | spin_lock_irqsave(&info->lock,flags); | ||
4414 | async_mode(info); | ||
4415 | rx_start(info); | ||
4416 | info->tx_count = count; | ||
4417 | tx_load(info, buf, count); | ||
4418 | tx_start(info); | ||
4419 | spin_unlock_irqrestore(&info->lock, flags); | ||
4420 | |||
4421 | /* wait for receive complete */ | ||
4422 | for (timeout = 100; timeout; --timeout) { | ||
4423 | msleep_interruptible(10); | ||
4424 | if (loopback_test_rx(info)) { | ||
4425 | rc = 0; | ||
4426 | break; | ||
4427 | } | ||
4428 | } | ||
4429 | |||
4430 | /* verify received frame length and contents */ | ||
4431 | if (!rc && (info->tmp_rbuf_count != count || | ||
4432 | memcmp(buf, info->tmp_rbuf, count))) { | ||
4433 | rc = -ENODEV; | ||
4434 | } | ||
4435 | |||
4436 | spin_lock_irqsave(&info->lock,flags); | ||
4437 | reset_adapter(info); | ||
4438 | spin_unlock_irqrestore(&info->lock,flags); | ||
4439 | |||
4440 | memcpy(&info->params, ¶ms, sizeof(info->params)); | ||
4441 | info->tty = oldtty; | ||
4442 | |||
4443 | info->init_error = rc ? DiagStatus_DmaFailure : 0; | ||
4444 | return rc; | ||
4445 | } | ||
4446 | |||
4447 | static int adapter_test(struct slgt_info *info) | ||
4448 | { | ||
4449 | DBGINFO(("testing %s\n", info->device_name)); | ||
4450 | if ((info->init_error = register_test(info)) < 0) { | ||
4451 | printk("register test failure %s addr=%08X\n", | ||
4452 | info->device_name, info->phys_reg_addr); | ||
4453 | } else if ((info->init_error = irq_test(info)) < 0) { | ||
4454 | printk("IRQ test failure %s IRQ=%d\n", | ||
4455 | info->device_name, info->irq_level); | ||
4456 | } else if ((info->init_error = loopback_test(info)) < 0) { | ||
4457 | printk("loopback test failure %s\n", info->device_name); | ||
4458 | } | ||
4459 | return info->init_error; | ||
4460 | } | ||
4461 | |||
4462 | /* | ||
4463 | * transmit timeout handler | ||
4464 | */ | ||
4465 | static void tx_timeout(unsigned long context) | ||
4466 | { | ||
4467 | struct slgt_info *info = (struct slgt_info*)context; | ||
4468 | unsigned long flags; | ||
4469 | |||
4470 | DBGINFO(("%s tx_timeout\n", info->device_name)); | ||
4471 | if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) { | ||
4472 | info->icount.txtimeout++; | ||
4473 | } | ||
4474 | spin_lock_irqsave(&info->lock,flags); | ||
4475 | info->tx_active = 0; | ||
4476 | info->tx_count = 0; | ||
4477 | spin_unlock_irqrestore(&info->lock,flags); | ||
4478 | |||
4479 | #ifdef CONFIG_HDLC | ||
4480 | if (info->netcount) | ||
4481 | hdlcdev_tx_done(info); | ||
4482 | else | ||
4483 | #endif | ||
4484 | bh_transmit(info); | ||
4485 | } | ||
4486 | |||
4487 | /* | ||
4488 | * receive buffer polling timer | ||
4489 | */ | ||
4490 | static void rx_timeout(unsigned long context) | ||
4491 | { | ||
4492 | struct slgt_info *info = (struct slgt_info*)context; | ||
4493 | unsigned long flags; | ||
4494 | |||
4495 | DBGINFO(("%s rx_timeout\n", info->device_name)); | ||
4496 | spin_lock_irqsave(&info->lock, flags); | ||
4497 | info->pending_bh |= BH_RECEIVE; | ||
4498 | spin_unlock_irqrestore(&info->lock, flags); | ||
4499 | bh_handler(info); | ||
4500 | } | ||
4501 | |||
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 2392e404e8d1..ba4582d160fd 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile | |||
@@ -2,6 +2,9 @@ | |||
2 | # Makefile for the kernel tpm device drivers. | 2 | # Makefile for the kernel tpm device drivers. |
3 | # | 3 | # |
4 | obj-$(CONFIG_TCG_TPM) += tpm.o | 4 | obj-$(CONFIG_TCG_TPM) += tpm.o |
5 | ifdef CONFIG_ACPI | ||
6 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o | ||
7 | endif | ||
5 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o | 8 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o |
6 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o | 9 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o |
7 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o | 10 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index a9be0e8eaea5..5a3870477ef1 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -466,6 +466,7 @@ void tpm_remove_hardware(struct device *dev) | |||
466 | kfree(chip->vendor->miscdev.name); | 466 | kfree(chip->vendor->miscdev.name); |
467 | 467 | ||
468 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); | 468 | sysfs_remove_group(&dev->kobj, chip->vendor->attr_group); |
469 | tpm_bios_log_teardown(chip->bios_dir); | ||
469 | 470 | ||
470 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= | 471 | dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= |
471 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); | 472 | ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES)); |
@@ -593,6 +594,8 @@ dev_num_search_complete: | |||
593 | 594 | ||
594 | sysfs_create_group(&dev->kobj, chip->vendor->attr_group); | 595 | sysfs_create_group(&dev->kobj, chip->vendor->attr_group); |
595 | 596 | ||
597 | chip->bios_dir = tpm_bios_log_setup(devname); | ||
598 | |||
596 | return 0; | 599 | return 0; |
597 | } | 600 | } |
598 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 601 | EXPORT_SYMBOL_GPL(tpm_register_hardware); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 159882ca69dd..fd3a4beaa53d 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -82,6 +82,8 @@ struct tpm_chip { | |||
82 | 82 | ||
83 | struct tpm_vendor_specific *vendor; | 83 | struct tpm_vendor_specific *vendor; |
84 | 84 | ||
85 | struct dentry **bios_dir; | ||
86 | |||
85 | struct list_head list; | 87 | struct list_head list; |
86 | }; | 88 | }; |
87 | 89 | ||
@@ -107,3 +109,16 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); | |||
107 | extern void tpm_remove_hardware(struct device *); | 109 | extern void tpm_remove_hardware(struct device *); |
108 | extern int tpm_pm_suspend(struct device *, pm_message_t); | 110 | extern int tpm_pm_suspend(struct device *, pm_message_t); |
109 | extern int tpm_pm_resume(struct device *); | 111 | extern int tpm_pm_resume(struct device *); |
112 | |||
113 | #ifdef CONFIG_ACPI | ||
114 | extern struct dentry ** tpm_bios_log_setup(char *); | ||
115 | extern void tpm_bios_log_teardown(struct dentry **); | ||
116 | #else | ||
117 | static inline struct dentry* tpm_bios_log_setup(char *name) | ||
118 | { | ||
119 | return NULL; | ||
120 | } | ||
121 | static inline void tpm_bios_log_teardown(struct dentry **dir) | ||
122 | { | ||
123 | } | ||
124 | #endif | ||
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c new file mode 100644 index 000000000000..aedf7a8e6da7 --- /dev/null +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -0,0 +1,540 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 IBM Corporation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Seiji Munetoh <munetoh@jp.ibm.com> | ||
6 | * Stefan Berger <stefanb@us.ibm.com> | ||
7 | * Reiner Sailer <sailer@watson.ibm.com> | ||
8 | * Kylene Hall <kjhall@us.ibm.com> | ||
9 | * | ||
10 | * Access to the eventlog extended by the TCG BIOS of PC platform | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/fs.h> | ||
21 | #include <linux/security.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <acpi/acpi.h> | ||
24 | #include <acpi/actypes.h> | ||
25 | #include <acpi/actbl.h> | ||
26 | #include "tpm.h" | ||
27 | |||
28 | #define TCG_EVENT_NAME_LEN_MAX 255 | ||
29 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | ||
30 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | ||
31 | |||
32 | struct tpm_bios_log { | ||
33 | void *bios_event_log; | ||
34 | void *bios_event_log_end; | ||
35 | }; | ||
36 | |||
37 | struct acpi_tcpa { | ||
38 | struct acpi_table_header hdr; | ||
39 | u16 reserved; | ||
40 | u32 log_max_len __attribute__ ((packed)); | ||
41 | u32 log_start_addr __attribute__ ((packed)); | ||
42 | }; | ||
43 | |||
44 | struct tcpa_event { | ||
45 | u32 pcr_index; | ||
46 | u32 event_type; | ||
47 | u8 pcr_value[20]; /* SHA1 */ | ||
48 | u32 event_size; | ||
49 | u8 event_data[0]; | ||
50 | }; | ||
51 | |||
52 | enum tcpa_event_types { | ||
53 | PREBOOT = 0, | ||
54 | POST_CODE, | ||
55 | UNUSED, | ||
56 | NO_ACTION, | ||
57 | SEPARATOR, | ||
58 | ACTION, | ||
59 | EVENT_TAG, | ||
60 | SCRTM_CONTENTS, | ||
61 | SCRTM_VERSION, | ||
62 | CPU_MICROCODE, | ||
63 | PLATFORM_CONFIG_FLAGS, | ||
64 | TABLE_OF_DEVICES, | ||
65 | COMPACT_HASH, | ||
66 | IPL, | ||
67 | IPL_PARTITION_DATA, | ||
68 | NONHOST_CODE, | ||
69 | NONHOST_CONFIG, | ||
70 | NONHOST_INFO, | ||
71 | }; | ||
72 | |||
73 | static const char* tcpa_event_type_strings[] = { | ||
74 | "PREBOOT", | ||
75 | "POST CODE", | ||
76 | "", | ||
77 | "NO ACTION", | ||
78 | "SEPARATOR", | ||
79 | "ACTION", | ||
80 | "EVENT TAG", | ||
81 | "S-CRTM Contents", | ||
82 | "S-CRTM Version", | ||
83 | "CPU Microcode", | ||
84 | "Platform Config Flags", | ||
85 | "Table of Devices", | ||
86 | "Compact Hash", | ||
87 | "IPL", | ||
88 | "IPL Partition Data", | ||
89 | "Non-Host Code", | ||
90 | "Non-Host Config", | ||
91 | "Non-Host Info" | ||
92 | }; | ||
93 | |||
94 | enum tcpa_pc_event_ids { | ||
95 | SMBIOS = 1, | ||
96 | BIS_CERT, | ||
97 | POST_BIOS_ROM, | ||
98 | ESCD, | ||
99 | CMOS, | ||
100 | NVRAM, | ||
101 | OPTION_ROM_EXEC, | ||
102 | OPTION_ROM_CONFIG, | ||
103 | OPTION_ROM_MICROCODE, | ||
104 | S_CRTM_VERSION, | ||
105 | S_CRTM_CONTENTS, | ||
106 | POST_CONTENTS, | ||
107 | }; | ||
108 | |||
109 | static const char* tcpa_pc_event_id_strings[] = { | ||
110 | "" | ||
111 | "SMBIOS", | ||
112 | "BIS Certificate", | ||
113 | "POST BIOS ", | ||
114 | "ESCD ", | ||
115 | "CMOS", | ||
116 | "NVRAM", | ||
117 | "Option ROM", | ||
118 | "Option ROM config", | ||
119 | "Option ROM microcode", | ||
120 | "S-CRTM Version", | ||
121 | "S-CRTM Contents", | ||
122 | "S-CRTM POST Contents", | ||
123 | }; | ||
124 | |||
125 | /* returns pointer to start of pos. entry of tcg log */ | ||
126 | static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) | ||
127 | { | ||
128 | loff_t i; | ||
129 | struct tpm_bios_log *log = m->private; | ||
130 | void *addr = log->bios_event_log; | ||
131 | void *limit = log->bios_event_log_end; | ||
132 | struct tcpa_event *event; | ||
133 | |||
134 | /* read over *pos measurements */ | ||
135 | for (i = 0; i < *pos; i++) { | ||
136 | event = addr; | ||
137 | |||
138 | if ((addr + sizeof(struct tcpa_event)) < limit) { | ||
139 | if (event->event_type == 0 && event->event_size == 0) | ||
140 | return NULL; | ||
141 | addr += sizeof(struct tcpa_event) + event->event_size; | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* now check if current entry is valid */ | ||
146 | if ((addr + sizeof(struct tcpa_event)) >= limit) | ||
147 | return NULL; | ||
148 | |||
149 | event = addr; | ||
150 | |||
151 | if ((event->event_type == 0 && event->event_size == 0) || | ||
152 | ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit)) | ||
153 | return NULL; | ||
154 | |||
155 | return addr; | ||
156 | } | ||
157 | |||
158 | static void *tpm_bios_measurements_next(struct seq_file *m, void *v, | ||
159 | loff_t *pos) | ||
160 | { | ||
161 | struct tcpa_event *event = v; | ||
162 | struct tpm_bios_log *log = m->private; | ||
163 | void *limit = log->bios_event_log_end; | ||
164 | |||
165 | v += sizeof(struct tcpa_event) + event->event_size; | ||
166 | |||
167 | /* now check if current entry is valid */ | ||
168 | if ((v + sizeof(struct tcpa_event)) >= limit) | ||
169 | return NULL; | ||
170 | |||
171 | event = v; | ||
172 | |||
173 | if (event->event_type == 0 && event->event_size == 0) | ||
174 | return NULL; | ||
175 | |||
176 | if ((event->event_type == 0 && event->event_size == 0) || | ||
177 | ((v + sizeof(struct tcpa_event) + event->event_size) >= limit)) | ||
178 | return NULL; | ||
179 | |||
180 | (*pos)++; | ||
181 | return v; | ||
182 | } | ||
183 | |||
184 | static void tpm_bios_measurements_stop(struct seq_file *m, void *v) | ||
185 | { | ||
186 | } | ||
187 | |||
188 | static int get_event_name(char *dest, struct tcpa_event *event, | ||
189 | unsigned char * event_entry) | ||
190 | { | ||
191 | const char *name = ""; | ||
192 | char data[40] = ""; | ||
193 | int i, n_len = 0, d_len = 0; | ||
194 | u32 event_id, event_data_size; | ||
195 | |||
196 | switch(event->event_type) { | ||
197 | case PREBOOT: | ||
198 | case POST_CODE: | ||
199 | case UNUSED: | ||
200 | case NO_ACTION: | ||
201 | case SCRTM_CONTENTS: | ||
202 | case SCRTM_VERSION: | ||
203 | case CPU_MICROCODE: | ||
204 | case PLATFORM_CONFIG_FLAGS: | ||
205 | case TABLE_OF_DEVICES: | ||
206 | case COMPACT_HASH: | ||
207 | case IPL: | ||
208 | case IPL_PARTITION_DATA: | ||
209 | case NONHOST_CODE: | ||
210 | case NONHOST_CONFIG: | ||
211 | case NONHOST_INFO: | ||
212 | name = tcpa_event_type_strings[event->event_type]; | ||
213 | n_len = strlen(name); | ||
214 | break; | ||
215 | case SEPARATOR: | ||
216 | case ACTION: | ||
217 | if (MAX_TEXT_EVENT > event->event_size) { | ||
218 | name = event_entry; | ||
219 | n_len = event->event_size; | ||
220 | } | ||
221 | break; | ||
222 | case EVENT_TAG: | ||
223 | event_id = be32_to_cpu(event_entry); | ||
224 | event_data_size = be32_to_cpu(&event_entry[4]); | ||
225 | |||
226 | /* ToDo Row data -> Base64 */ | ||
227 | |||
228 | switch (event_id) { | ||
229 | case SMBIOS: | ||
230 | case BIS_CERT: | ||
231 | case CMOS: | ||
232 | case NVRAM: | ||
233 | case OPTION_ROM_EXEC: | ||
234 | case OPTION_ROM_CONFIG: | ||
235 | case OPTION_ROM_MICROCODE: | ||
236 | case S_CRTM_VERSION: | ||
237 | case S_CRTM_CONTENTS: | ||
238 | case POST_CONTENTS: | ||
239 | name = tcpa_pc_event_id_strings[event_id]; | ||
240 | n_len = strlen(name); | ||
241 | break; | ||
242 | case POST_BIOS_ROM: | ||
243 | case ESCD: | ||
244 | name = tcpa_pc_event_id_strings[event_id]; | ||
245 | n_len = strlen(name); | ||
246 | for (i = 0; i < 20; i++) | ||
247 | d_len += sprintf(data, "%02x", | ||
248 | event_entry[8 + i]); | ||
249 | break; | ||
250 | default: | ||
251 | break; | ||
252 | } | ||
253 | default: | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]", | ||
258 | n_len, name, d_len, data); | ||
259 | |||
260 | } | ||
261 | |||
262 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) | ||
263 | { | ||
264 | |||
265 | char *eventname; | ||
266 | char data[4]; | ||
267 | u32 help; | ||
268 | int i, len; | ||
269 | struct tcpa_event *event = (struct tcpa_event *) v; | ||
270 | unsigned char *event_entry = | ||
271 | (unsigned char *) (v + sizeof(struct tcpa_event)); | ||
272 | |||
273 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | ||
274 | if (!eventname) { | ||
275 | printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", | ||
276 | __func__); | ||
277 | return -ENOMEM; | ||
278 | } | ||
279 | |||
280 | /* 1st: PCR used is in little-endian format (4 bytes) */ | ||
281 | help = le32_to_cpu(event->pcr_index); | ||
282 | memcpy(data, &help, 4); | ||
283 | for (i = 0; i < 4; i++) | ||
284 | seq_putc(m, data[i]); | ||
285 | |||
286 | /* 2nd: SHA1 (20 bytes) */ | ||
287 | for (i = 0; i < 20; i++) | ||
288 | seq_putc(m, event->pcr_value[i]); | ||
289 | |||
290 | /* 3rd: event type identifier (4 bytes) */ | ||
291 | help = le32_to_cpu(event->event_type); | ||
292 | memcpy(data, &help, 4); | ||
293 | for (i = 0; i < 4; i++) | ||
294 | seq_putc(m, data[i]); | ||
295 | |||
296 | len = 0; | ||
297 | |||
298 | len += get_event_name(eventname, event, event_entry); | ||
299 | |||
300 | /* 4th: filename <= 255 + \'0' delimiter */ | ||
301 | if (len > TCG_EVENT_NAME_LEN_MAX) | ||
302 | len = TCG_EVENT_NAME_LEN_MAX; | ||
303 | |||
304 | for (i = 0; i < len; i++) | ||
305 | seq_putc(m, eventname[i]); | ||
306 | |||
307 | /* 5th: delimiter */ | ||
308 | seq_putc(m, '\0'); | ||
309 | |||
310 | return 0; | ||
311 | } | ||
312 | |||
313 | static int tpm_bios_measurements_release(struct inode *inode, | ||
314 | struct file *file) | ||
315 | { | ||
316 | struct seq_file *seq = file->private_data; | ||
317 | struct tpm_bios_log *log = seq->private; | ||
318 | |||
319 | if (log) { | ||
320 | kfree(log->bios_event_log); | ||
321 | kfree(log); | ||
322 | } | ||
323 | |||
324 | return seq_release(inode, file); | ||
325 | } | ||
326 | |||
327 | static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | ||
328 | { | ||
329 | int len = 0; | ||
330 | int i; | ||
331 | char *eventname; | ||
332 | struct tcpa_event *event = v; | ||
333 | unsigned char *event_entry = | ||
334 | (unsigned char *) (v + sizeof(struct tcpa_event)); | ||
335 | |||
336 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | ||
337 | if (!eventname) { | ||
338 | printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", | ||
339 | __func__); | ||
340 | return -EFAULT; | ||
341 | } | ||
342 | |||
343 | seq_printf(m, "%2d ", event->pcr_index); | ||
344 | |||
345 | /* 2nd: SHA1 */ | ||
346 | for (i = 0; i < 20; i++) | ||
347 | seq_printf(m, "%02x", event->pcr_value[i]); | ||
348 | |||
349 | /* 3rd: event type identifier */ | ||
350 | seq_printf(m, " %02x", event->event_type); | ||
351 | |||
352 | len += get_event_name(eventname, event, event_entry); | ||
353 | |||
354 | /* 4th: eventname <= max + \'0' delimiter */ | ||
355 | seq_printf(m, " %s\n", eventname); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static struct seq_operations tpm_ascii_b_measurments_seqops = { | ||
361 | .start = tpm_bios_measurements_start, | ||
362 | .next = tpm_bios_measurements_next, | ||
363 | .stop = tpm_bios_measurements_stop, | ||
364 | .show = tpm_ascii_bios_measurements_show, | ||
365 | }; | ||
366 | |||
367 | static struct seq_operations tpm_binary_b_measurments_seqops = { | ||
368 | .start = tpm_bios_measurements_start, | ||
369 | .next = tpm_bios_measurements_next, | ||
370 | .stop = tpm_bios_measurements_stop, | ||
371 | .show = tpm_binary_bios_measurements_show, | ||
372 | }; | ||
373 | |||
374 | /* read binary bios log */ | ||
375 | static int read_log(struct tpm_bios_log *log) | ||
376 | { | ||
377 | struct acpi_tcpa *buff; | ||
378 | acpi_status status; | ||
379 | void *virt; | ||
380 | |||
381 | if (log->bios_event_log != NULL) { | ||
382 | printk(KERN_ERR | ||
383 | "%s: ERROR - Eventlog already initialized\n", | ||
384 | __func__); | ||
385 | return -EFAULT; | ||
386 | } | ||
387 | |||
388 | /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ | ||
389 | status = acpi_get_firmware_table(ACPI_TCPA_SIG, 1, | ||
390 | ACPI_LOGICAL_ADDRESSING, | ||
391 | (struct acpi_table_header **) | ||
392 | &buff); | ||
393 | |||
394 | if (ACPI_FAILURE(status)) { | ||
395 | printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", | ||
396 | __func__); | ||
397 | return -EIO; | ||
398 | } | ||
399 | |||
400 | if (buff->log_max_len == 0) { | ||
401 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); | ||
402 | return -EIO; | ||
403 | } | ||
404 | |||
405 | /* malloc EventLog space */ | ||
406 | log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL); | ||
407 | if (!log->bios_event_log) { | ||
408 | printk | ||
409 | ("%s: ERROR - Not enough Memory for BIOS measurements\n", | ||
410 | __func__); | ||
411 | return -ENOMEM; | ||
412 | } | ||
413 | |||
414 | log->bios_event_log_end = log->bios_event_log + buff->log_max_len; | ||
415 | |||
416 | acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt); | ||
417 | |||
418 | memcpy(log->bios_event_log, virt, buff->log_max_len); | ||
419 | |||
420 | acpi_os_unmap_memory(virt, buff->log_max_len); | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int tpm_ascii_bios_measurements_open(struct inode *inode, | ||
425 | struct file *file) | ||
426 | { | ||
427 | int err; | ||
428 | struct tpm_bios_log *log; | ||
429 | struct seq_file *seq; | ||
430 | |||
431 | log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL); | ||
432 | if (!log) | ||
433 | return -ENOMEM; | ||
434 | |||
435 | if ((err = read_log(log))) | ||
436 | return err; | ||
437 | |||
438 | /* now register seq file */ | ||
439 | err = seq_open(file, &tpm_ascii_b_measurments_seqops); | ||
440 | if (!err) { | ||
441 | seq = file->private_data; | ||
442 | seq->private = log; | ||
443 | } else { | ||
444 | kfree(log->bios_event_log); | ||
445 | kfree(log); | ||
446 | } | ||
447 | return err; | ||
448 | } | ||
449 | |||
450 | struct file_operations tpm_ascii_bios_measurements_ops = { | ||
451 | .open = tpm_ascii_bios_measurements_open, | ||
452 | .read = seq_read, | ||
453 | .llseek = seq_lseek, | ||
454 | .release = tpm_bios_measurements_release, | ||
455 | }; | ||
456 | |||
457 | static int tpm_binary_bios_measurements_open(struct inode *inode, | ||
458 | struct file *file) | ||
459 | { | ||
460 | int err; | ||
461 | struct tpm_bios_log *log; | ||
462 | struct seq_file *seq; | ||
463 | |||
464 | log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL); | ||
465 | if (!log) | ||
466 | return -ENOMEM; | ||
467 | |||
468 | if ((err = read_log(log))) | ||
469 | return err; | ||
470 | |||
471 | /* now register seq file */ | ||
472 | err = seq_open(file, &tpm_binary_b_measurments_seqops); | ||
473 | if (!err) { | ||
474 | seq = file->private_data; | ||
475 | seq->private = log; | ||
476 | } else { | ||
477 | kfree(log->bios_event_log); | ||
478 | kfree(log); | ||
479 | } | ||
480 | return err; | ||
481 | } | ||
482 | |||
483 | struct file_operations tpm_binary_bios_measurements_ops = { | ||
484 | .open = tpm_binary_bios_measurements_open, | ||
485 | .read = seq_read, | ||
486 | .llseek = seq_lseek, | ||
487 | .release = tpm_bios_measurements_release, | ||
488 | }; | ||
489 | |||
490 | struct dentry **tpm_bios_log_setup(char *name) | ||
491 | { | ||
492 | struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file; | ||
493 | |||
494 | tpm_dir = securityfs_create_dir(name, NULL); | ||
495 | if (!tpm_dir) | ||
496 | goto out; | ||
497 | |||
498 | bin_file = | ||
499 | securityfs_create_file("binary_bios_measurements", | ||
500 | S_IRUSR | S_IRGRP, tpm_dir, NULL, | ||
501 | &tpm_binary_bios_measurements_ops); | ||
502 | if (!bin_file) | ||
503 | goto out_tpm; | ||
504 | |||
505 | ascii_file = | ||
506 | securityfs_create_file("ascii_bios_measurements", | ||
507 | S_IRUSR | S_IRGRP, tpm_dir, NULL, | ||
508 | &tpm_ascii_bios_measurements_ops); | ||
509 | if (!ascii_file) | ||
510 | goto out_bin; | ||
511 | |||
512 | ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL); | ||
513 | if (!ret) | ||
514 | goto out_ascii; | ||
515 | |||
516 | ret[0] = ascii_file; | ||
517 | ret[1] = bin_file; | ||
518 | ret[2] = tpm_dir; | ||
519 | |||
520 | return ret; | ||
521 | |||
522 | out_ascii: | ||
523 | securityfs_remove(ascii_file); | ||
524 | out_bin: | ||
525 | securityfs_remove(bin_file); | ||
526 | out_tpm: | ||
527 | securityfs_remove(tpm_dir); | ||
528 | out: | ||
529 | return NULL; | ||
530 | } | ||
531 | EXPORT_SYMBOL_GPL(tpm_bios_log_setup); | ||
532 | |||
533 | void tpm_bios_log_teardown(struct dentry **lst) | ||
534 | { | ||
535 | int i; | ||
536 | |||
537 | for (i = 0; i < 3; i++) | ||
538 | securityfs_remove(lst[i]); | ||
539 | } | ||
540 | EXPORT_SYMBOL_GPL(tpm_bios_log_teardown); | ||
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index 9ac6d43437b3..a5b18e086a94 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
@@ -718,7 +718,7 @@ static struct platform_driver giu_device_driver = { | |||
718 | }, | 718 | }, |
719 | }; | 719 | }; |
720 | 720 | ||
721 | static int __devinit vr41xx_giu_init(void) | 721 | static int __init vr41xx_giu_init(void) |
722 | { | 722 | { |
723 | int retval; | 723 | int retval; |
724 | 724 | ||
@@ -733,7 +733,7 @@ static int __devinit vr41xx_giu_init(void) | |||
733 | return retval; | 733 | return retval; |
734 | } | 734 | } |
735 | 735 | ||
736 | static void __devexit vr41xx_giu_exit(void) | 736 | static void __exit vr41xx_giu_exit(void) |
737 | { | 737 | { |
738 | platform_driver_unregister(&giu_device_driver); | 738 | platform_driver_unregister(&giu_device_driver); |
739 | 739 | ||
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c index 44d49dfacbb3..3843900e94c4 100644 --- a/drivers/char/watchdog/wdt977.c +++ b/drivers/char/watchdog/wdt977.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Wdt977 0.03: A Watchdog Device for Netwinder W83977AF chip | 2 | * Wdt977 0.04: A Watchdog Device for Netwinder W83977AF chip |
3 | * | 3 | * |
4 | * (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>) | 4 | * (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>) |
5 | * | 5 | * |
@@ -18,6 +18,8 @@ | |||
18 | * from minutes to seconds. | 18 | * from minutes to seconds. |
19 | * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in | 19 | * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in |
20 | * nwwatchdog_init. | 20 | * nwwatchdog_init. |
21 | * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks | ||
22 | * remove limitiation to be used on Netwinders only | ||
21 | */ | 23 | */ |
22 | 24 | ||
23 | #include <linux/module.h> | 25 | #include <linux/module.h> |
@@ -28,6 +30,7 @@ | |||
28 | #include <linux/fs.h> | 30 | #include <linux/fs.h> |
29 | #include <linux/miscdevice.h> | 31 | #include <linux/miscdevice.h> |
30 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/ioport.h> | ||
31 | #include <linux/watchdog.h> | 34 | #include <linux/watchdog.h> |
32 | #include <linux/notifier.h> | 35 | #include <linux/notifier.h> |
33 | #include <linux/reboot.h> | 36 | #include <linux/reboot.h> |
@@ -37,8 +40,18 @@ | |||
37 | #include <asm/mach-types.h> | 40 | #include <asm/mach-types.h> |
38 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
39 | 42 | ||
40 | #define PFX "Wdt977: " | 43 | #define WATCHDOG_VERSION "0.04" |
41 | #define WATCHDOG_MINOR 130 | 44 | #define WATCHDOG_NAME "Wdt977" |
45 | #define PFX WATCHDOG_NAME ": " | ||
46 | #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" | ||
47 | |||
48 | #define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */ | ||
49 | #define IO_DATA_PORT (IO_INDEX_PORT+1) | ||
50 | |||
51 | #define UNLOCK_DATA 0x87 | ||
52 | #define LOCK_DATA 0xAA | ||
53 | #define DEVICE_REGISTER 0x07 | ||
54 | |||
42 | 55 | ||
43 | #define DEFAULT_TIMEOUT 60 /* default timeout in seconds */ | 56 | #define DEFAULT_TIMEOUT 60 /* default timeout in seconds */ |
44 | 57 | ||
@@ -47,6 +60,7 @@ static int timeoutM; /* timeout in minutes */ | |||
47 | static unsigned long timer_alive; | 60 | static unsigned long timer_alive; |
48 | static int testmode; | 61 | static int testmode; |
49 | static char expect_close; | 62 | static char expect_close; |
63 | static spinlock_t spinlock; | ||
50 | 64 | ||
51 | module_param(timeout, int, 0); | 65 | module_param(timeout, int, 0); |
52 | MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); | 66 | MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); |
@@ -63,9 +77,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON | |||
63 | 77 | ||
64 | static int wdt977_start(void) | 78 | static int wdt977_start(void) |
65 | { | 79 | { |
80 | unsigned long flags; | ||
81 | |||
82 | spin_lock_irqsave(&spinlock, flags); | ||
83 | |||
66 | /* unlock the SuperIO chip */ | 84 | /* unlock the SuperIO chip */ |
67 | outb(0x87,0x370); | 85 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
68 | outb(0x87,0x370); | 86 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
69 | 87 | ||
70 | /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4 | 88 | /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4 |
71 | * F2 has the timeout in minutes | 89 | * F2 has the timeout in minutes |
@@ -73,28 +91,29 @@ static int wdt977_start(void) | |||
73 | * at timeout, and to reset timer on kbd/mouse activity (not impl.) | 91 | * at timeout, and to reset timer on kbd/mouse activity (not impl.) |
74 | * F4 is used to just clear the TIMEOUT'ed state (bit 0) | 92 | * F4 is used to just clear the TIMEOUT'ed state (bit 0) |
75 | */ | 93 | */ |
76 | outb(0x07,0x370); | 94 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
77 | outb(0x08,0x371); | 95 | outb_p(0x08, IO_DATA_PORT); |
78 | outb(0xF2,0x370); | 96 | outb_p(0xF2, IO_INDEX_PORT); |
79 | outb(timeoutM,0x371); | 97 | outb_p(timeoutM, IO_DATA_PORT); |
80 | outb(0xF3,0x370); | 98 | outb_p(0xF3, IO_INDEX_PORT); |
81 | outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */ | 99 | outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for kbd/mouse/LED */ |
82 | outb(0xF4,0x370); | 100 | outb_p(0xF4, IO_INDEX_PORT); |
83 | outb(0x00,0x371); | 101 | outb_p(0x00, IO_DATA_PORT); |
84 | 102 | ||
85 | /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ | 103 | /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ |
86 | /* in test mode watch the bit 1 on F4 to indicate "triggered" */ | 104 | /* in test mode watch the bit 1 on F4 to indicate "triggered" */ |
87 | if (!testmode) | 105 | if (!testmode) |
88 | { | 106 | { |
89 | outb(0x07,0x370); | 107 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
90 | outb(0x07,0x371); | 108 | outb_p(0x07, IO_DATA_PORT); |
91 | outb(0xE6,0x370); | 109 | outb_p(0xE6, IO_INDEX_PORT); |
92 | outb(0x08,0x371); | 110 | outb_p(0x08, IO_DATA_PORT); |
93 | } | 111 | } |
94 | 112 | ||
95 | /* lock the SuperIO chip */ | 113 | /* lock the SuperIO chip */ |
96 | outb(0xAA,0x370); | 114 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
97 | 115 | ||
116 | spin_unlock_irqrestore(&spinlock, flags); | ||
98 | printk(KERN_INFO PFX "activated.\n"); | 117 | printk(KERN_INFO PFX "activated.\n"); |
99 | 118 | ||
100 | return 0; | 119 | return 0; |
@@ -106,35 +125,39 @@ static int wdt977_start(void) | |||
106 | 125 | ||
107 | static int wdt977_stop(void) | 126 | static int wdt977_stop(void) |
108 | { | 127 | { |
128 | unsigned long flags; | ||
129 | spin_lock_irqsave(&spinlock, flags); | ||
130 | |||
109 | /* unlock the SuperIO chip */ | 131 | /* unlock the SuperIO chip */ |
110 | outb(0x87,0x370); | 132 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
111 | outb(0x87,0x370); | 133 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
112 | 134 | ||
113 | /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4 | 135 | /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4 |
114 | * F3 is reset to its default state | 136 | * F3 is reset to its default state |
115 | * F4 can clear the TIMEOUT'ed state (bit 0) - back to default | 137 | * F4 can clear the TIMEOUT'ed state (bit 0) - back to default |
116 | * We can not use GP17 as a PowerLed, as we use its usage as a RedLed | 138 | * We can not use GP17 as a PowerLed, as we use its usage as a RedLed |
117 | */ | 139 | */ |
118 | outb(0x07,0x370); | 140 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
119 | outb(0x08,0x371); | 141 | outb_p(0x08, IO_DATA_PORT); |
120 | outb(0xF2,0x370); | 142 | outb_p(0xF2, IO_INDEX_PORT); |
121 | outb(0xFF,0x371); | 143 | outb_p(0xFF, IO_DATA_PORT); |
122 | outb(0xF3,0x370); | 144 | outb_p(0xF3, IO_INDEX_PORT); |
123 | outb(0x00,0x371); | 145 | outb_p(0x00, IO_DATA_PORT); |
124 | outb(0xF4,0x370); | 146 | outb_p(0xF4, IO_INDEX_PORT); |
125 | outb(0x00,0x371); | 147 | outb_p(0x00, IO_DATA_PORT); |
126 | outb(0xF2,0x370); | 148 | outb_p(0xF2, IO_INDEX_PORT); |
127 | outb(0x00,0x371); | 149 | outb_p(0x00, IO_DATA_PORT); |
128 | 150 | ||
129 | /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ | 151 | /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ |
130 | outb(0x07,0x370); | 152 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
131 | outb(0x07,0x371); | 153 | outb_p(0x07, IO_DATA_PORT); |
132 | outb(0xE6,0x370); | 154 | outb_p(0xE6, IO_INDEX_PORT); |
133 | outb(0x08,0x371); | 155 | outb_p(0x08, IO_DATA_PORT); |
134 | 156 | ||
135 | /* lock the SuperIO chip */ | 157 | /* lock the SuperIO chip */ |
136 | outb(0xAA,0x370); | 158 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
137 | 159 | ||
160 | spin_unlock_irqrestore(&spinlock, flags); | ||
138 | printk(KERN_INFO PFX "shutdown.\n"); | 161 | printk(KERN_INFO PFX "shutdown.\n"); |
139 | 162 | ||
140 | return 0; | 163 | return 0; |
@@ -147,19 +170,23 @@ static int wdt977_stop(void) | |||
147 | 170 | ||
148 | static int wdt977_keepalive(void) | 171 | static int wdt977_keepalive(void) |
149 | { | 172 | { |
173 | unsigned long flags; | ||
174 | spin_lock_irqsave(&spinlock, flags); | ||
175 | |||
150 | /* unlock the SuperIO chip */ | 176 | /* unlock the SuperIO chip */ |
151 | outb(0x87,0x370); | 177 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
152 | outb(0x87,0x370); | 178 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
153 | 179 | ||
154 | /* select device Aux2 (device=8) and kicks watchdog reg F2 */ | 180 | /* select device Aux2 (device=8) and kicks watchdog reg F2 */ |
155 | /* F2 has the timeout in minutes */ | 181 | /* F2 has the timeout in minutes */ |
156 | outb(0x07,0x370); | 182 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
157 | outb(0x08,0x371); | 183 | outb_p(0x08, IO_DATA_PORT); |
158 | outb(0xF2,0x370); | 184 | outb_p(0xF2, IO_INDEX_PORT); |
159 | outb(timeoutM,0x371); | 185 | outb_p(timeoutM, IO_DATA_PORT); |
160 | 186 | ||
161 | /* lock the SuperIO chip */ | 187 | /* lock the SuperIO chip */ |
162 | outb(0xAA,0x370); | 188 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
189 | spin_unlock_irqrestore(&spinlock, flags); | ||
163 | 190 | ||
164 | return 0; | 191 | return 0; |
165 | } | 192 | } |
@@ -198,22 +225,26 @@ static int wdt977_set_timeout(int t) | |||
198 | static int wdt977_get_status(int *status) | 225 | static int wdt977_get_status(int *status) |
199 | { | 226 | { |
200 | int new_status; | 227 | int new_status; |
228 | unsigned long flags; | ||
201 | 229 | ||
202 | *status=0; | 230 | spin_lock_irqsave(&spinlock, flags); |
203 | 231 | ||
204 | /* unlock the SuperIO chip */ | 232 | /* unlock the SuperIO chip */ |
205 | outb(0x87,0x370); | 233 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
206 | outb(0x87,0x370); | 234 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
207 | 235 | ||
208 | /* select device Aux2 (device=8) and read watchdog reg F4 */ | 236 | /* select device Aux2 (device=8) and read watchdog reg F4 */ |
209 | outb(0x07,0x370); | 237 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
210 | outb(0x08,0x371); | 238 | outb_p(0x08, IO_DATA_PORT); |
211 | outb(0xF4,0x370); | 239 | outb_p(0xF4, IO_INDEX_PORT); |
212 | new_status = inb(0x371); | 240 | new_status = inb_p(IO_DATA_PORT); |
213 | 241 | ||
214 | /* lock the SuperIO chip */ | 242 | /* lock the SuperIO chip */ |
215 | outb(0xAA,0x370); | 243 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
216 | 244 | ||
245 | spin_unlock_irqrestore(&spinlock, flags); | ||
246 | |||
247 | *status=0; | ||
217 | if (new_status & 1) | 248 | if (new_status & 1) |
218 | *status |= WDIOF_CARDRESET; | 249 | *status |= WDIOF_CARDRESET; |
219 | 250 | ||
@@ -249,8 +280,8 @@ static int wdt977_release(struct inode *inode, struct file *file) | |||
249 | wdt977_stop(); | 280 | wdt977_stop(); |
250 | clear_bit(0,&timer_alive); | 281 | clear_bit(0,&timer_alive); |
251 | } else { | 282 | } else { |
252 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | ||
253 | wdt977_keepalive(); | 283 | wdt977_keepalive(); |
284 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | ||
254 | } | 285 | } |
255 | expect_close = 0; | 286 | expect_close = 0; |
256 | return 0; | 287 | return 0; |
@@ -271,14 +302,17 @@ static int wdt977_release(struct inode *inode, struct file *file) | |||
271 | static ssize_t wdt977_write(struct file *file, const char __user *buf, | 302 | static ssize_t wdt977_write(struct file *file, const char __user *buf, |
272 | size_t count, loff_t *ppos) | 303 | size_t count, loff_t *ppos) |
273 | { | 304 | { |
274 | if (count) { | 305 | if (count) |
275 | if (!nowayout) { | 306 | { |
307 | if (!nowayout) | ||
308 | { | ||
276 | size_t i; | 309 | size_t i; |
277 | 310 | ||
278 | /* In case it was set long ago */ | 311 | /* In case it was set long ago */ |
279 | expect_close = 0; | 312 | expect_close = 0; |
280 | 313 | ||
281 | for (i = 0; i != count; i++) { | 314 | for (i = 0; i != count; i++) |
315 | { | ||
282 | char c; | 316 | char c; |
283 | if (get_user(c, buf + i)) | 317 | if (get_user(c, buf + i)) |
284 | return -EFAULT; | 318 | return -EFAULT; |
@@ -287,6 +321,7 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf, | |||
287 | } | 321 | } |
288 | } | 322 | } |
289 | 323 | ||
324 | /* someone wrote to us, we should restart timer */ | ||
290 | wdt977_keepalive(); | 325 | wdt977_keepalive(); |
291 | } | 326 | } |
292 | return count; | 327 | return count; |
@@ -308,7 +343,7 @@ static struct watchdog_info ident = { | |||
308 | WDIOF_MAGICCLOSE | | 343 | WDIOF_MAGICCLOSE | |
309 | WDIOF_KEEPALIVEPING, | 344 | WDIOF_KEEPALIVEPING, |
310 | .firmware_version = 1, | 345 | .firmware_version = 1, |
311 | .identity = "Winbond 83977", | 346 | .identity = WATCHDOG_NAME, |
312 | }; | 347 | }; |
313 | 348 | ||
314 | static int wdt977_ioctl(struct inode *inode, struct file *file, | 349 | static int wdt977_ioctl(struct inode *inode, struct file *file, |
@@ -405,50 +440,81 @@ static struct notifier_block wdt977_notifier = { | |||
405 | .notifier_call = wdt977_notify_sys, | 440 | .notifier_call = wdt977_notify_sys, |
406 | }; | 441 | }; |
407 | 442 | ||
408 | static int __init nwwatchdog_init(void) | 443 | static int __init wd977_init(void) |
409 | { | 444 | { |
410 | int retval; | 445 | int rc; |
411 | if (!machine_is_netwinder()) | 446 | |
412 | return -ENODEV; | 447 | //if (!machine_is_netwinder()) |
448 | // return -ENODEV; | ||
449 | |||
450 | printk(KERN_INFO PFX DRIVER_VERSION); | ||
451 | |||
452 | spin_lock_init(&spinlock); | ||
413 | 453 | ||
414 | /* Check that the timeout value is within it's range ; if not reset to the default */ | 454 | /* Check that the timeout value is within it's range ; if not reset to the default */ |
415 | if (wdt977_set_timeout(timeout)) { | 455 | if (wdt977_set_timeout(timeout)) |
456 | { | ||
416 | wdt977_set_timeout(DEFAULT_TIMEOUT); | 457 | wdt977_set_timeout(DEFAULT_TIMEOUT); |
417 | printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n", | 458 | printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n", |
418 | DEFAULT_TIMEOUT); | 459 | DEFAULT_TIMEOUT); |
419 | } | 460 | } |
420 | 461 | ||
421 | retval = register_reboot_notifier(&wdt977_notifier); | 462 | /* on Netwinder the IOports are already reserved by |
422 | if (retval) { | 463 | * arch/arm/mach-footbridge/netwinder-hw.c |
423 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 464 | */ |
424 | retval); | 465 | if (!machine_is_netwinder()) |
425 | return retval; | 466 | { |
467 | if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) | ||
468 | { | ||
469 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | ||
470 | IO_INDEX_PORT); | ||
471 | rc = -EIO; | ||
472 | goto err_out; | ||
473 | } | ||
426 | } | 474 | } |
427 | 475 | ||
428 | retval = misc_register(&wdt977_miscdev); | 476 | rc = misc_register(&wdt977_miscdev); |
429 | if (retval) { | 477 | if (rc) |
478 | { | ||
430 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 479 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", |
431 | WATCHDOG_MINOR, retval); | 480 | wdt977_miscdev.minor, rc); |
432 | unregister_reboot_notifier(&wdt977_notifier); | 481 | goto err_out_region; |
433 | return retval; | 482 | } |
483 | |||
484 | rc = register_reboot_notifier(&wdt977_notifier); | ||
485 | if (rc) | ||
486 | { | ||
487 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | ||
488 | rc); | ||
489 | goto err_out_miscdev; | ||
434 | } | 490 | } |
435 | 491 | ||
436 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode = %i)\n", | 492 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n", |
437 | timeout, nowayout, testmode); | 493 | timeout, nowayout, testmode); |
438 | 494 | ||
439 | return 0; | 495 | return 0; |
496 | |||
497 | err_out_miscdev: | ||
498 | misc_deregister(&wdt977_miscdev); | ||
499 | err_out_region: | ||
500 | if (!machine_is_netwinder()) | ||
501 | release_region(IO_INDEX_PORT,2); | ||
502 | err_out: | ||
503 | return rc; | ||
440 | } | 504 | } |
441 | 505 | ||
442 | static void __exit nwwatchdog_exit(void) | 506 | static void __exit wd977_exit(void) |
443 | { | 507 | { |
508 | wdt977_stop(); | ||
444 | misc_deregister(&wdt977_miscdev); | 509 | misc_deregister(&wdt977_miscdev); |
445 | unregister_reboot_notifier(&wdt977_notifier); | 510 | unregister_reboot_notifier(&wdt977_notifier); |
511 | release_region(IO_INDEX_PORT,2); | ||
446 | } | 512 | } |
447 | 513 | ||
448 | module_init(nwwatchdog_init); | 514 | module_init(wd977_init); |
449 | module_exit(nwwatchdog_exit); | 515 | module_exit(wd977_exit); |
450 | 516 | ||
451 | MODULE_AUTHOR("Woody Suwalski <woody@netwinder.org>"); | 517 | MODULE_AUTHOR("Woody Suwalski <woodys@xandros.com>"); |
452 | MODULE_DESCRIPTION("W83977AF Watchdog driver"); | 518 | MODULE_DESCRIPTION("W83977AF Watchdog driver"); |
453 | MODULE_LICENSE("GPL"); | 519 | MODULE_LICENSE("GPL"); |
454 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 520 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 969d2b4aaec0..385e52930c02 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c | |||
@@ -34,14 +34,14 @@ | |||
34 | static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); | 34 | static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); |
35 | static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; | 35 | static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; |
36 | 36 | ||
37 | /* proc_counts is used as the sequence number of the netlink message */ | 37 | /* proc_event_counts is used as the sequence number of the netlink message */ |
38 | static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; | 38 | static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; |
39 | 39 | ||
40 | static inline void get_seq(__u32 *ts, int *cpu) | 40 | static inline void get_seq(__u32 *ts, int *cpu) |
41 | { | 41 | { |
42 | *ts = get_cpu_var(proc_event_counts)++; | 42 | *ts = get_cpu_var(proc_event_counts)++; |
43 | *cpu = smp_processor_id(); | 43 | *cpu = smp_processor_id(); |
44 | put_cpu_var(proc_counts); | 44 | put_cpu_var(proc_event_counts); |
45 | } | 45 | } |
46 | 46 | ||
47 | void proc_fork_connector(struct task_struct *task) | 47 | void proc_fork_connector(struct task_struct *task) |
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c index e70b3db69edd..1af3dfbb8086 100644 --- a/drivers/i2c/chips/tps65010.c +++ b/drivers/i2c/chips/tps65010.c | |||
@@ -494,6 +494,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
494 | { | 494 | { |
495 | struct tps65010 *tps; | 495 | struct tps65010 *tps; |
496 | int status; | 496 | int status; |
497 | unsigned long irqflags; | ||
497 | 498 | ||
498 | if (the_tps) { | 499 | if (the_tps) { |
499 | dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME); | 500 | dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME); |
@@ -520,13 +521,14 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
520 | } | 521 | } |
521 | 522 | ||
522 | #ifdef CONFIG_ARM | 523 | #ifdef CONFIG_ARM |
524 | irqflags = SA_SAMPLE_RANDOM | SA_TRIGGER_LOW; | ||
523 | if (machine_is_omap_h2()) { | 525 | if (machine_is_omap_h2()) { |
524 | tps->model = TPS65010; | 526 | tps->model = TPS65010; |
525 | omap_cfg_reg(W4_GPIO58); | 527 | omap_cfg_reg(W4_GPIO58); |
526 | tps->irq = OMAP_GPIO_IRQ(58); | 528 | tps->irq = OMAP_GPIO_IRQ(58); |
527 | omap_request_gpio(58); | 529 | omap_request_gpio(58); |
528 | omap_set_gpio_direction(58, 1); | 530 | omap_set_gpio_direction(58, 1); |
529 | set_irq_type(tps->irq, IRQT_FALLING); | 531 | irqflags |= SA_TRIGGER_FALLING; |
530 | } | 532 | } |
531 | if (machine_is_omap_osk()) { | 533 | if (machine_is_omap_osk()) { |
532 | tps->model = TPS65010; | 534 | tps->model = TPS65010; |
@@ -534,7 +536,7 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
534 | tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)); | 536 | tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)); |
535 | omap_request_gpio(OMAP_MPUIO(1)); | 537 | omap_request_gpio(OMAP_MPUIO(1)); |
536 | omap_set_gpio_direction(OMAP_MPUIO(1), 1); | 538 | omap_set_gpio_direction(OMAP_MPUIO(1), 1); |
537 | set_irq_type(tps->irq, IRQT_FALLING); | 539 | irqflags |= SA_TRIGGER_FALLING; |
538 | } | 540 | } |
539 | if (machine_is_omap_h3()) { | 541 | if (machine_is_omap_h3()) { |
540 | tps->model = TPS65013; | 542 | tps->model = TPS65013; |
@@ -542,13 +544,12 @@ tps65010_probe(struct i2c_adapter *bus, int address, int kind) | |||
542 | // FIXME set up this board's IRQ ... | 544 | // FIXME set up this board's IRQ ... |
543 | } | 545 | } |
544 | #else | 546 | #else |
545 | #define set_irq_type(num,trigger) do{}while(0) | 547 | irqflags = SA_SAMPLE_RANDOM; |
546 | #endif | 548 | #endif |
547 | 549 | ||
548 | if (tps->irq > 0) { | 550 | if (tps->irq > 0) { |
549 | set_irq_type(tps->irq, IRQT_LOW); | ||
550 | status = request_irq(tps->irq, tps65010_irq, | 551 | status = request_irq(tps->irq, tps65010_irq, |
551 | SA_SAMPLE_RANDOM, DRIVER_NAME, tps); | 552 | irqflags, DRIVER_NAME, tps); |
552 | if (status < 0) { | 553 | if (status < 0) { |
553 | dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n", | 554 | dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n", |
554 | tps->irq, status); | 555 | tps->irq, status); |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 4b441720b6ba..cab362ea0336 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -1130,6 +1130,17 @@ static int idedisk_release(struct inode *inode, struct file *filp) | |||
1130 | return 0; | 1130 | return 0; |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
1134 | { | ||
1135 | struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); | ||
1136 | ide_drive_t *drive = idkp->drive; | ||
1137 | |||
1138 | geo->heads = drive->bios_head; | ||
1139 | geo->sectors = drive->bios_sect; | ||
1140 | geo->cylinders = (u16)drive->bios_cyl; /* truncate */ | ||
1141 | return 0; | ||
1142 | } | ||
1143 | |||
1133 | static int idedisk_ioctl(struct inode *inode, struct file *file, | 1144 | static int idedisk_ioctl(struct inode *inode, struct file *file, |
1134 | unsigned int cmd, unsigned long arg) | 1145 | unsigned int cmd, unsigned long arg) |
1135 | { | 1146 | { |
@@ -1164,6 +1175,7 @@ static struct block_device_operations idedisk_ops = { | |||
1164 | .open = idedisk_open, | 1175 | .open = idedisk_open, |
1165 | .release = idedisk_release, | 1176 | .release = idedisk_release, |
1166 | .ioctl = idedisk_ioctl, | 1177 | .ioctl = idedisk_ioctl, |
1178 | .getgeo = idedisk_getgeo, | ||
1167 | .media_changed = idedisk_media_changed, | 1179 | .media_changed = idedisk_media_changed, |
1168 | .revalidate_disk= idedisk_revalidate_disk | 1180 | .revalidate_disk= idedisk_revalidate_disk |
1169 | }; | 1181 | }; |
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index fba3fffc2d66..5945f551aaaa 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -2031,6 +2031,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp) | |||
2031 | return 0; | 2031 | return 0; |
2032 | } | 2032 | } |
2033 | 2033 | ||
2034 | static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
2035 | { | ||
2036 | struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk); | ||
2037 | ide_drive_t *drive = floppy->drive; | ||
2038 | |||
2039 | geo->heads = drive->bios_head; | ||
2040 | geo->sectors = drive->bios_sect; | ||
2041 | geo->cylinders = (u16)drive->bios_cyl; /* truncate */ | ||
2042 | return 0; | ||
2043 | } | ||
2044 | |||
2034 | static int idefloppy_ioctl(struct inode *inode, struct file *file, | 2045 | static int idefloppy_ioctl(struct inode *inode, struct file *file, |
2035 | unsigned int cmd, unsigned long arg) | 2046 | unsigned int cmd, unsigned long arg) |
2036 | { | 2047 | { |
@@ -2120,6 +2131,7 @@ static struct block_device_operations idefloppy_ops = { | |||
2120 | .open = idefloppy_open, | 2131 | .open = idefloppy_open, |
2121 | .release = idefloppy_release, | 2132 | .release = idefloppy_release, |
2122 | .ioctl = idefloppy_ioctl, | 2133 | .ioctl = idefloppy_ioctl, |
2134 | .getgeo = idefloppy_getgeo, | ||
2123 | .media_changed = idefloppy_media_changed, | 2135 | .media_changed = idefloppy_media_changed, |
2124 | .revalidate_disk= idefloppy_revalidate_disk | 2136 | .revalidate_disk= idefloppy_revalidate_disk |
2125 | }; | 2137 | }; |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 4b524f6b3ecd..b069b13b75a7 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -1278,19 +1278,6 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device | |||
1278 | up(&ide_setting_sem); | 1278 | up(&ide_setting_sem); |
1279 | 1279 | ||
1280 | switch (cmd) { | 1280 | switch (cmd) { |
1281 | case HDIO_GETGEO: | ||
1282 | { | ||
1283 | struct hd_geometry geom; | ||
1284 | if (!p || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL; | ||
1285 | geom.heads = drive->bios_head; | ||
1286 | geom.sectors = drive->bios_sect; | ||
1287 | geom.cylinders = (u16)drive->bios_cyl; /* truncate */ | ||
1288 | geom.start = get_start_sect(bdev); | ||
1289 | if (copy_to_user(p, &geom, sizeof(struct hd_geometry))) | ||
1290 | return -EFAULT; | ||
1291 | return 0; | ||
1292 | } | ||
1293 | |||
1294 | case HDIO_OBSOLETE_IDENTITY: | 1281 | case HDIO_OBSOLETE_IDENTITY: |
1295 | case HDIO_GET_IDENTITY: | 1282 | case HDIO_GET_IDENTITY: |
1296 | if (bdev != bdev->bd_contains) | 1283 | if (bdev != bdev->bd_contains) |
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index 242029c9c0ca..6439dec66881 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c | |||
@@ -658,22 +658,14 @@ static void do_hd_request (request_queue_t * q) | |||
658 | enable_irq(HD_IRQ); | 658 | enable_irq(HD_IRQ); |
659 | } | 659 | } |
660 | 660 | ||
661 | static int hd_ioctl(struct inode * inode, struct file * file, | 661 | static int hd_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
662 | unsigned int cmd, unsigned long arg) | ||
663 | { | 662 | { |
664 | struct hd_i_struct *disk = inode->i_bdev->bd_disk->private_data; | 663 | struct hd_i_struct *disk = bdev->bd_disk->private_data; |
665 | struct hd_geometry __user *loc = (struct hd_geometry __user *) arg; | 664 | |
666 | struct hd_geometry g; | 665 | geo->heads = disk->head; |
667 | 666 | geo->sectors = disk->sect; | |
668 | if (cmd != HDIO_GETGEO) | 667 | geo->cylinders = disk->cyl; |
669 | return -EINVAL; | 668 | return 0; |
670 | if (!loc) | ||
671 | return -EINVAL; | ||
672 | g.heads = disk->head; | ||
673 | g.sectors = disk->sect; | ||
674 | g.cylinders = disk->cyl; | ||
675 | g.start = get_start_sect(inode->i_bdev); | ||
676 | return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; | ||
677 | } | 669 | } |
678 | 670 | ||
679 | /* | 671 | /* |
@@ -695,7 +687,7 @@ static irqreturn_t hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
695 | } | 687 | } |
696 | 688 | ||
697 | static struct block_device_operations hd_fops = { | 689 | static struct block_device_operations hd_fops = { |
698 | .ioctl = hd_ioctl, | 690 | .getgeo = hd_getgeo, |
699 | }; | 691 | }; |
700 | 692 | ||
701 | /* | 693 | /* |
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c index ff2e217a8c84..0d3073f4eab4 100644 --- a/drivers/ide/pci/serverworks.c +++ b/drivers/ide/pci/serverworks.c | |||
@@ -69,7 +69,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list) | |||
69 | static u8 svwks_ratemask (ide_drive_t *drive) | 69 | static u8 svwks_ratemask (ide_drive_t *drive) |
70 | { | 70 | { |
71 | struct pci_dev *dev = HWIF(drive)->pci_dev; | 71 | struct pci_dev *dev = HWIF(drive)->pci_dev; |
72 | u8 mode; | 72 | u8 mode = 0; |
73 | 73 | ||
74 | if (!svwks_revision) | 74 | if (!svwks_revision) |
75 | pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); | 75 | pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 02110e00d145..3a611fe5497e 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -308,10 +308,11 @@ static int cm_alloc_id(struct cm_id_private *cm_id_priv) | |||
308 | { | 308 | { |
309 | unsigned long flags; | 309 | unsigned long flags; |
310 | int ret; | 310 | int ret; |
311 | static int next_id; | ||
311 | 312 | ||
312 | do { | 313 | do { |
313 | spin_lock_irqsave(&cm.lock, flags); | 314 | spin_lock_irqsave(&cm.lock, flags); |
314 | ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, 1, | 315 | ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, next_id++, |
315 | (__force int *) &cm_id_priv->id.local_id); | 316 | (__force int *) &cm_id_priv->id.local_id); |
316 | spin_unlock_irqrestore(&cm.lock, flags); | 317 | spin_unlock_irqrestore(&cm.lock, flags); |
317 | } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); | 318 | } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); |
@@ -684,6 +685,13 @@ retest: | |||
684 | cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT); | 685 | cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT); |
685 | break; | 686 | break; |
686 | case IB_CM_REQ_SENT: | 687 | case IB_CM_REQ_SENT: |
688 | ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); | ||
689 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | ||
690 | ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT, | ||
691 | &cm_id_priv->av.port->cm_dev->ca_guid, | ||
692 | sizeof cm_id_priv->av.port->cm_dev->ca_guid, | ||
693 | NULL, 0); | ||
694 | break; | ||
687 | case IB_CM_MRA_REQ_RCVD: | 695 | case IB_CM_MRA_REQ_RCVD: |
688 | case IB_CM_REP_SENT: | 696 | case IB_CM_REP_SENT: |
689 | case IB_CM_MRA_REP_RCVD: | 697 | case IB_CM_MRA_REP_RCVD: |
@@ -694,10 +702,8 @@ retest: | |||
694 | case IB_CM_REP_RCVD: | 702 | case IB_CM_REP_RCVD: |
695 | case IB_CM_MRA_REP_SENT: | 703 | case IB_CM_MRA_REP_SENT: |
696 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | 704 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); |
697 | ib_send_cm_rej(cm_id, IB_CM_REJ_TIMEOUT, | 705 | ib_send_cm_rej(cm_id, IB_CM_REJ_CONSUMER_DEFINED, |
698 | &cm_id_priv->av.port->cm_dev->ca_guid, | 706 | NULL, 0, NULL, 0); |
699 | sizeof cm_id_priv->av.port->cm_dev->ca_guid, | ||
700 | NULL, 0); | ||
701 | break; | 707 | break; |
702 | case IB_CM_ESTABLISHED: | 708 | case IB_CM_ESTABLISHED: |
703 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); | 709 | spin_unlock_irqrestore(&cm_id_priv->lock, flags); |
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index eb7f52537ccc..c908de8db5a9 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c | |||
@@ -197,8 +197,8 @@ static void send_handler(struct ib_mad_agent *agent, | |||
197 | memcpy(timeout->mad.data, packet->mad.data, | 197 | memcpy(timeout->mad.data, packet->mad.data, |
198 | sizeof (struct ib_mad_hdr)); | 198 | sizeof (struct ib_mad_hdr)); |
199 | 199 | ||
200 | if (!queue_packet(file, agent, timeout)) | 200 | if (queue_packet(file, agent, timeout)) |
201 | return; | 201 | kfree(timeout); |
202 | } | 202 | } |
203 | out: | 203 | out: |
204 | kfree(packet); | 204 | kfree(packet); |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a57d021d435a..a02c5a05c984 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -489,6 +489,7 @@ err_idr: | |||
489 | 489 | ||
490 | err_unreg: | 490 | err_unreg: |
491 | ib_dereg_mr(mr); | 491 | ib_dereg_mr(mr); |
492 | atomic_dec(&pd->usecnt); | ||
492 | 493 | ||
493 | err_up: | 494 | err_up: |
494 | up(&ib_uverbs_idr_mutex); | 495 | up(&ib_uverbs_idr_mutex); |
@@ -593,13 +594,18 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
593 | if (cmd.comp_vector >= file->device->num_comp_vectors) | 594 | if (cmd.comp_vector >= file->device->num_comp_vectors) |
594 | return -EINVAL; | 595 | return -EINVAL; |
595 | 596 | ||
596 | if (cmd.comp_channel >= 0) | ||
597 | ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); | ||
598 | |||
599 | uobj = kmalloc(sizeof *uobj, GFP_KERNEL); | 597 | uobj = kmalloc(sizeof *uobj, GFP_KERNEL); |
600 | if (!uobj) | 598 | if (!uobj) |
601 | return -ENOMEM; | 599 | return -ENOMEM; |
602 | 600 | ||
601 | if (cmd.comp_channel >= 0) { | ||
602 | ev_file = ib_uverbs_lookup_comp_file(cmd.comp_channel); | ||
603 | if (!ev_file) { | ||
604 | ret = -EINVAL; | ||
605 | goto err; | ||
606 | } | ||
607 | } | ||
608 | |||
603 | uobj->uobject.user_handle = cmd.user_handle; | 609 | uobj->uobject.user_handle = cmd.user_handle; |
604 | uobj->uobject.context = file->ucontext; | 610 | uobj->uobject.context = file->ucontext; |
605 | uobj->uverbs_file = file; | 611 | uobj->uverbs_file = file; |
@@ -663,6 +669,8 @@ err_up: | |||
663 | ib_destroy_cq(cq); | 669 | ib_destroy_cq(cq); |
664 | 670 | ||
665 | err: | 671 | err: |
672 | if (ev_file) | ||
673 | ib_uverbs_release_ucq(file, ev_file, uobj); | ||
666 | kfree(uobj); | 674 | kfree(uobj); |
667 | return ret; | 675 | return ret; |
668 | } | 676 | } |
@@ -935,6 +943,11 @@ err_idr: | |||
935 | 943 | ||
936 | err_destroy: | 944 | err_destroy: |
937 | ib_destroy_qp(qp); | 945 | ib_destroy_qp(qp); |
946 | atomic_dec(&pd->usecnt); | ||
947 | atomic_dec(&attr.send_cq->usecnt); | ||
948 | atomic_dec(&attr.recv_cq->usecnt); | ||
949 | if (attr.srq) | ||
950 | atomic_dec(&attr.srq->usecnt); | ||
938 | 951 | ||
939 | err_up: | 952 | err_up: |
940 | up(&ib_uverbs_idr_mutex); | 953 | up(&ib_uverbs_idr_mutex); |
@@ -1448,6 +1461,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, | |||
1448 | attr.sl = cmd.attr.sl; | 1461 | attr.sl = cmd.attr.sl; |
1449 | attr.src_path_bits = cmd.attr.src_path_bits; | 1462 | attr.src_path_bits = cmd.attr.src_path_bits; |
1450 | attr.static_rate = cmd.attr.static_rate; | 1463 | attr.static_rate = cmd.attr.static_rate; |
1464 | attr.ah_flags = cmd.attr.is_global ? IB_AH_GRH : 0; | ||
1451 | attr.port_num = cmd.attr.port_num; | 1465 | attr.port_num = cmd.attr.port_num; |
1452 | attr.grh.flow_label = cmd.attr.grh.flow_label; | 1466 | attr.grh.flow_label = cmd.attr.grh.flow_label; |
1453 | attr.grh.sgid_index = cmd.attr.grh.sgid_index; | 1467 | attr.grh.sgid_index = cmd.attr.grh.sgid_index; |
@@ -1729,6 +1743,7 @@ err_idr: | |||
1729 | 1743 | ||
1730 | err_destroy: | 1744 | err_destroy: |
1731 | ib_destroy_srq(srq); | 1745 | ib_destroy_srq(srq); |
1746 | atomic_dec(&pd->usecnt); | ||
1732 | 1747 | ||
1733 | err_up: | 1748 | err_up: |
1734 | up(&ib_uverbs_idr_mutex); | 1749 | up(&ib_uverbs_idr_mutex); |
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 4c15e112736c..c857361be449 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c | |||
@@ -107,9 +107,9 @@ struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, struct ib_wc *wc, | |||
107 | 107 | ||
108 | if (wc->wc_flags & IB_WC_GRH) { | 108 | if (wc->wc_flags & IB_WC_GRH) { |
109 | ah_attr.ah_flags = IB_AH_GRH; | 109 | ah_attr.ah_flags = IB_AH_GRH; |
110 | ah_attr.grh.dgid = grh->dgid; | 110 | ah_attr.grh.dgid = grh->sgid; |
111 | 111 | ||
112 | ret = ib_find_cached_gid(pd->device, &grh->sgid, &port_num, | 112 | ret = ib_find_cached_gid(pd->device, &grh->dgid, &port_num, |
113 | &gid_index); | 113 | &gid_index); |
114 | if (ret) | 114 | if (ret) |
115 | return ERR_PTR(ret); | 115 | return ERR_PTR(ret); |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 9ed34587fc5c..22ac72bc20c3 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -937,10 +937,6 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
937 | if (err) | 937 | if (err) |
938 | goto out; | 938 | goto out; |
939 | 939 | ||
940 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); | ||
941 | dev_lim->max_srq_sz = (1 << field) - 1; | ||
942 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); | ||
943 | dev_lim->max_qp_sz = (1 << field) - 1; | ||
944 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET); | 940 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSVD_QP_OFFSET); |
945 | dev_lim->reserved_qps = 1 << (field & 0xf); | 941 | dev_lim->reserved_qps = 1 << (field & 0xf); |
946 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET); | 942 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_OFFSET); |
@@ -1056,6 +1052,10 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
1056 | mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); | 1052 | mthca_dbg(dev, "Flags: %08x\n", dev_lim->flags); |
1057 | 1053 | ||
1058 | if (mthca_is_memfree(dev)) { | 1054 | if (mthca_is_memfree(dev)) { |
1055 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); | ||
1056 | dev_lim->max_srq_sz = 1 << field; | ||
1057 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); | ||
1058 | dev_lim->max_qp_sz = 1 << field; | ||
1059 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSZ_SRQ_OFFSET); | 1059 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_RSZ_SRQ_OFFSET); |
1060 | dev_lim->hca.arbel.resize_srq = field & 1; | 1060 | dev_lim->hca.arbel.resize_srq = field & 1; |
1061 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); | 1061 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET); |
@@ -1087,6 +1087,10 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev, | |||
1087 | mthca_dbg(dev, "Max ICM size %lld MB\n", | 1087 | mthca_dbg(dev, "Max ICM size %lld MB\n", |
1088 | (unsigned long long) dev_lim->hca.arbel.max_icm_sz >> 20); | 1088 | (unsigned long long) dev_lim->hca.arbel.max_icm_sz >> 20); |
1089 | } else { | 1089 | } else { |
1090 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SRQ_SZ_OFFSET); | ||
1091 | dev_lim->max_srq_sz = (1 << field) - 1; | ||
1092 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_QP_SZ_OFFSET); | ||
1093 | dev_lim->max_qp_sz = (1 << field) - 1; | ||
1090 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_AV_OFFSET); | 1094 | MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_AV_OFFSET); |
1091 | dev_lim->hca.tavor.max_avs = 1 << (field & 0x3f); | 1095 | dev_lim->hca.tavor.max_avs = 1 << (field & 0x3f); |
1092 | dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE; | 1096 | dev_lim->mpt_entry_sz = MTHCA_MPT_ENTRY_SIZE; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 4a8adcef2079..96f1a86bf049 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c | |||
@@ -128,12 +128,12 @@ struct mthca_err_cqe { | |||
128 | __be32 my_qpn; | 128 | __be32 my_qpn; |
129 | u32 reserved1[3]; | 129 | u32 reserved1[3]; |
130 | u8 syndrome; | 130 | u8 syndrome; |
131 | u8 reserved2; | 131 | u8 vendor_err; |
132 | __be16 db_cnt; | 132 | __be16 db_cnt; |
133 | u32 reserved3; | 133 | u32 reserved2; |
134 | __be32 wqe; | 134 | __be32 wqe; |
135 | u8 opcode; | 135 | u8 opcode; |
136 | u8 reserved4[2]; | 136 | u8 reserved3[2]; |
137 | u8 owner; | 137 | u8 owner; |
138 | }; | 138 | }; |
139 | 139 | ||
@@ -253,6 +253,15 @@ void mthca_cq_event(struct mthca_dev *dev, u32 cqn, | |||
253 | wake_up(&cq->wait); | 253 | wake_up(&cq->wait); |
254 | } | 254 | } |
255 | 255 | ||
256 | static inline int is_recv_cqe(struct mthca_cqe *cqe) | ||
257 | { | ||
258 | if ((cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) == | ||
259 | MTHCA_ERROR_CQE_OPCODE_MASK) | ||
260 | return !(cqe->opcode & 0x01); | ||
261 | else | ||
262 | return !(cqe->is_send & 0x80); | ||
263 | } | ||
264 | |||
256 | void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, | 265 | void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, |
257 | struct mthca_srq *srq) | 266 | struct mthca_srq *srq) |
258 | { | 267 | { |
@@ -296,7 +305,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn, | |||
296 | while ((int) --prod_index - (int) cq->cons_index >= 0) { | 305 | while ((int) --prod_index - (int) cq->cons_index >= 0) { |
297 | cqe = get_cqe(cq, prod_index & cq->ibcq.cqe); | 306 | cqe = get_cqe(cq, prod_index & cq->ibcq.cqe); |
298 | if (cqe->my_qpn == cpu_to_be32(qpn)) { | 307 | if (cqe->my_qpn == cpu_to_be32(qpn)) { |
299 | if (srq) | 308 | if (srq && is_recv_cqe(cqe)) |
300 | mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe)); | 309 | mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe)); |
301 | ++nfreed; | 310 | ++nfreed; |
302 | } else if (nfreed) | 311 | } else if (nfreed) |
@@ -333,8 +342,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, | |||
333 | } | 342 | } |
334 | 343 | ||
335 | /* | 344 | /* |
336 | * For completions in error, only work request ID, status (and | 345 | * For completions in error, only work request ID, status, vendor error |
337 | * freed resource count for RD) have to be set. | 346 | * (and freed resource count for RD) have to be set. |
338 | */ | 347 | */ |
339 | switch (cqe->syndrome) { | 348 | switch (cqe->syndrome) { |
340 | case SYNDROME_LOCAL_LENGTH_ERR: | 349 | case SYNDROME_LOCAL_LENGTH_ERR: |
@@ -396,6 +405,8 @@ static int handle_error_cqe(struct mthca_dev *dev, struct mthca_cq *cq, | |||
396 | break; | 405 | break; |
397 | } | 406 | } |
398 | 407 | ||
408 | entry->vendor_err = cqe->vendor_err; | ||
409 | |||
399 | /* | 410 | /* |
400 | * Mem-free HCAs always generate one CQE per WQE, even in the | 411 | * Mem-free HCAs always generate one CQE per WQE, even in the |
401 | * error case, so we don't have to check the doorbell count, etc. | 412 | * error case, so we don't have to check the doorbell count, etc. |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 497ff794ef6a..795b379260bf 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/kernel.h> | 43 | #include <linux/kernel.h> |
44 | #include <linux/pci.h> | 44 | #include <linux/pci.h> |
45 | #include <linux/dma-mapping.h> | 45 | #include <linux/dma-mapping.h> |
46 | #include <linux/timer.h> | ||
46 | #include <asm/semaphore.h> | 47 | #include <asm/semaphore.h> |
47 | 48 | ||
48 | #include "mthca_provider.h" | 49 | #include "mthca_provider.h" |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 34d68e5a72d8..e8a948f087c0 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
@@ -484,8 +484,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
484 | u8 intr, | 484 | u8 intr, |
485 | struct mthca_eq *eq) | 485 | struct mthca_eq *eq) |
486 | { | 486 | { |
487 | int npages = (nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) / | 487 | int npages; |
488 | PAGE_SIZE; | ||
489 | u64 *dma_list = NULL; | 488 | u64 *dma_list = NULL; |
490 | dma_addr_t t; | 489 | dma_addr_t t; |
491 | struct mthca_mailbox *mailbox; | 490 | struct mthca_mailbox *mailbox; |
@@ -496,6 +495,7 @@ static int __devinit mthca_create_eq(struct mthca_dev *dev, | |||
496 | 495 | ||
497 | eq->dev = dev; | 496 | eq->dev = dev; |
498 | eq->nent = roundup_pow_of_two(max(nent, 2)); | 497 | eq->nent = roundup_pow_of_two(max(nent, 2)); |
498 | npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE; | ||
499 | 499 | ||
500 | eq->page_list = kmalloc(npages * sizeof *eq->page_list, | 500 | eq->page_list = kmalloc(npages * sizeof *eq->page_list, |
501 | GFP_KERNEL); | 501 | GFP_KERNEL); |
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 6f94b25f3acd..8b00d9a0f6f4 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c | |||
@@ -261,6 +261,10 @@ static int __devinit mthca_init_tavor(struct mthca_dev *mdev) | |||
261 | } | 261 | } |
262 | 262 | ||
263 | err = mthca_dev_lim(mdev, &dev_lim); | 263 | err = mthca_dev_lim(mdev, &dev_lim); |
264 | if (err) { | ||
265 | mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n"); | ||
266 | goto err_disable; | ||
267 | } | ||
264 | 268 | ||
265 | profile = default_profile; | 269 | profile = default_profile; |
266 | profile.num_uar = dev_lim.uar_size / PAGE_SIZE; | 270 | profile.num_uar = dev_lim.uar_size / PAGE_SIZE; |
diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 2fc449da418d..77bc6c746f43 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c | |||
@@ -111,7 +111,8 @@ static int find_mgm(struct mthca_dev *dev, | |||
111 | goto out; | 111 | goto out; |
112 | if (status) { | 112 | if (status) { |
113 | mthca_err(dev, "READ_MGM returned status %02x\n", status); | 113 | mthca_err(dev, "READ_MGM returned status %02x\n", status); |
114 | return -EINVAL; | 114 | err = -EINVAL; |
115 | goto out; | ||
115 | } | 116 | } |
116 | 117 | ||
117 | if (!memcmp(mgm->gid, zero_gid, 16)) { | 118 | if (!memcmp(mgm->gid, zero_gid, 16)) { |
@@ -126,7 +127,7 @@ static int find_mgm(struct mthca_dev *dev, | |||
126 | goto out; | 127 | goto out; |
127 | 128 | ||
128 | *prev = *index; | 129 | *prev = *index; |
129 | *index = be32_to_cpu(mgm->next_gid_index) >> 5; | 130 | *index = be32_to_cpu(mgm->next_gid_index) >> 6; |
130 | } while (*index); | 131 | } while (*index); |
131 | 132 | ||
132 | *index = -1; | 133 | *index = -1; |
@@ -153,8 +154,10 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
153 | return PTR_ERR(mailbox); | 154 | return PTR_ERR(mailbox); |
154 | mgm = mailbox->buf; | 155 | mgm = mailbox->buf; |
155 | 156 | ||
156 | if (down_interruptible(&dev->mcg_table.sem)) | 157 | if (down_interruptible(&dev->mcg_table.sem)) { |
157 | return -EINTR; | 158 | err = -EINTR; |
159 | goto err_sem; | ||
160 | } | ||
158 | 161 | ||
159 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); | 162 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); |
160 | if (err) | 163 | if (err) |
@@ -181,9 +184,8 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
181 | err = -EINVAL; | 184 | err = -EINVAL; |
182 | goto out; | 185 | goto out; |
183 | } | 186 | } |
184 | 187 | memset(mgm, 0, sizeof *mgm); | |
185 | memcpy(mgm->gid, gid->raw, 16); | 188 | memcpy(mgm->gid, gid->raw, 16); |
186 | mgm->next_gid_index = 0; | ||
187 | } | 189 | } |
188 | 190 | ||
189 | for (i = 0; i < MTHCA_QP_PER_MGM; ++i) | 191 | for (i = 0; i < MTHCA_QP_PER_MGM; ++i) |
@@ -209,6 +211,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
209 | if (status) { | 211 | if (status) { |
210 | mthca_err(dev, "WRITE_MGM returned status %02x\n", status); | 212 | mthca_err(dev, "WRITE_MGM returned status %02x\n", status); |
211 | err = -EINVAL; | 213 | err = -EINVAL; |
214 | goto out; | ||
212 | } | 215 | } |
213 | 216 | ||
214 | if (!link) | 217 | if (!link) |
@@ -223,7 +226,7 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
223 | goto out; | 226 | goto out; |
224 | } | 227 | } |
225 | 228 | ||
226 | mgm->next_gid_index = cpu_to_be32(index << 5); | 229 | mgm->next_gid_index = cpu_to_be32(index << 6); |
227 | 230 | ||
228 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); | 231 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); |
229 | if (err) | 232 | if (err) |
@@ -234,7 +237,12 @@ int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
234 | } | 237 | } |
235 | 238 | ||
236 | out: | 239 | out: |
240 | if (err && link && index != -1) { | ||
241 | BUG_ON(index < dev->limits.num_mgms); | ||
242 | mthca_free(&dev->mcg_table.alloc, index); | ||
243 | } | ||
237 | up(&dev->mcg_table.sem); | 244 | up(&dev->mcg_table.sem); |
245 | err_sem: | ||
238 | mthca_free_mailbox(dev, mailbox); | 246 | mthca_free_mailbox(dev, mailbox); |
239 | return err; | 247 | return err; |
240 | } | 248 | } |
@@ -255,8 +263,10 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
255 | return PTR_ERR(mailbox); | 263 | return PTR_ERR(mailbox); |
256 | mgm = mailbox->buf; | 264 | mgm = mailbox->buf; |
257 | 265 | ||
258 | if (down_interruptible(&dev->mcg_table.sem)) | 266 | if (down_interruptible(&dev->mcg_table.sem)) { |
259 | return -EINTR; | 267 | err = -EINTR; |
268 | goto err_sem; | ||
269 | } | ||
260 | 270 | ||
261 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); | 271 | err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index); |
262 | if (err) | 272 | if (err) |
@@ -305,13 +315,11 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
305 | if (i != 1) | 315 | if (i != 1) |
306 | goto out; | 316 | goto out; |
307 | 317 | ||
308 | goto out; | ||
309 | |||
310 | if (prev == -1) { | 318 | if (prev == -1) { |
311 | /* Remove entry from MGM */ | 319 | /* Remove entry from MGM */ |
312 | if (be32_to_cpu(mgm->next_gid_index) >> 5) { | 320 | int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6; |
313 | err = mthca_READ_MGM(dev, | 321 | if (amgm_index_to_free) { |
314 | be32_to_cpu(mgm->next_gid_index) >> 5, | 322 | err = mthca_READ_MGM(dev, amgm_index_to_free, |
315 | mailbox, &status); | 323 | mailbox, &status); |
316 | if (err) | 324 | if (err) |
317 | goto out; | 325 | goto out; |
@@ -332,9 +340,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
332 | err = -EINVAL; | 340 | err = -EINVAL; |
333 | goto out; | 341 | goto out; |
334 | } | 342 | } |
343 | if (amgm_index_to_free) { | ||
344 | BUG_ON(amgm_index_to_free < dev->limits.num_mgms); | ||
345 | mthca_free(&dev->mcg_table.alloc, amgm_index_to_free); | ||
346 | } | ||
335 | } else { | 347 | } else { |
336 | /* Remove entry from AMGM */ | 348 | /* Remove entry from AMGM */ |
337 | index = be32_to_cpu(mgm->next_gid_index) >> 5; | 349 | int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6; |
338 | err = mthca_READ_MGM(dev, prev, mailbox, &status); | 350 | err = mthca_READ_MGM(dev, prev, mailbox, &status); |
339 | if (err) | 351 | if (err) |
340 | goto out; | 352 | goto out; |
@@ -344,7 +356,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
344 | goto out; | 356 | goto out; |
345 | } | 357 | } |
346 | 358 | ||
347 | mgm->next_gid_index = cpu_to_be32(index << 5); | 359 | mgm->next_gid_index = cpu_to_be32(curr_next_index << 6); |
348 | 360 | ||
349 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); | 361 | err = mthca_WRITE_MGM(dev, prev, mailbox, &status); |
350 | if (err) | 362 | if (err) |
@@ -354,10 +366,13 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
354 | err = -EINVAL; | 366 | err = -EINVAL; |
355 | goto out; | 367 | goto out; |
356 | } | 368 | } |
369 | BUG_ON(index < dev->limits.num_mgms); | ||
370 | mthca_free(&dev->mcg_table.alloc, index); | ||
357 | } | 371 | } |
358 | 372 | ||
359 | out: | 373 | out: |
360 | up(&dev->mcg_table.sem); | 374 | up(&dev->mcg_table.sem); |
375 | err_sem: | ||
361 | mthca_free_mailbox(dev, mailbox); | 376 | mthca_free_mailbox(dev, mailbox); |
362 | return err; | 377 | return err; |
363 | } | 378 | } |
@@ -365,11 +380,12 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) | |||
365 | int __devinit mthca_init_mcg_table(struct mthca_dev *dev) | 380 | int __devinit mthca_init_mcg_table(struct mthca_dev *dev) |
366 | { | 381 | { |
367 | int err; | 382 | int err; |
383 | int table_size = dev->limits.num_mgms + dev->limits.num_amgms; | ||
368 | 384 | ||
369 | err = mthca_alloc_init(&dev->mcg_table.alloc, | 385 | err = mthca_alloc_init(&dev->mcg_table.alloc, |
370 | dev->limits.num_amgms, | 386 | table_size, |
371 | dev->limits.num_amgms - 1, | 387 | table_size - 1, |
372 | 0); | 388 | dev->limits.num_mgms); |
373 | if (err) | 389 | if (err) |
374 | return err; | 390 | return err; |
375 | 391 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index d72fe95cba08..9fb985a016e9 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c | |||
@@ -233,7 +233,7 @@ void *mthca_table_find(struct mthca_icm_table *table, int obj) | |||
233 | for (i = 0; i < chunk->npages; ++i) { | 233 | for (i = 0; i < chunk->npages; ++i) { |
234 | if (chunk->mem[i].length >= offset) { | 234 | if (chunk->mem[i].length >= offset) { |
235 | page = chunk->mem[i].page; | 235 | page = chunk->mem[i].page; |
236 | break; | 236 | goto out; |
237 | } | 237 | } |
238 | offset -= chunk->mem[i].length; | 238 | offset -= chunk->mem[i].length; |
239 | } | 239 | } |
@@ -485,6 +485,8 @@ void mthca_cleanup_user_db_tab(struct mthca_dev *dev, struct mthca_uar *uar, | |||
485 | put_page(db_tab->page[i].mem.page); | 485 | put_page(db_tab->page[i].mem.page); |
486 | } | 486 | } |
487 | } | 487 | } |
488 | |||
489 | kfree(db_tab); | ||
488 | } | 490 | } |
489 | 491 | ||
490 | int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type, | 492 | int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type, |
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 7450550db736..564b6d51c394 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -383,12 +383,10 @@ static const struct { | |||
383 | [UC] = (IB_QP_CUR_STATE | | 383 | [UC] = (IB_QP_CUR_STATE | |
384 | IB_QP_ALT_PATH | | 384 | IB_QP_ALT_PATH | |
385 | IB_QP_ACCESS_FLAGS | | 385 | IB_QP_ACCESS_FLAGS | |
386 | IB_QP_PKEY_INDEX | | ||
387 | IB_QP_PATH_MIG_STATE), | 386 | IB_QP_PATH_MIG_STATE), |
388 | [RC] = (IB_QP_CUR_STATE | | 387 | [RC] = (IB_QP_CUR_STATE | |
389 | IB_QP_ALT_PATH | | 388 | IB_QP_ALT_PATH | |
390 | IB_QP_ACCESS_FLAGS | | 389 | IB_QP_ACCESS_FLAGS | |
391 | IB_QP_PKEY_INDEX | | ||
392 | IB_QP_MIN_RNR_TIMER | | 390 | IB_QP_MIN_RNR_TIMER | |
393 | IB_QP_PATH_MIG_STATE), | 391 | IB_QP_PATH_MIG_STATE), |
394 | [MLX] = (IB_QP_CUR_STATE | | 392 | [MLX] = (IB_QP_CUR_STATE | |
@@ -476,9 +474,8 @@ static const struct { | |||
476 | .opt_param = { | 474 | .opt_param = { |
477 | [UD] = (IB_QP_CUR_STATE | | 475 | [UD] = (IB_QP_CUR_STATE | |
478 | IB_QP_QKEY), | 476 | IB_QP_QKEY), |
479 | [UC] = IB_QP_CUR_STATE, | 477 | [UC] = (IB_QP_CUR_STATE | |
480 | [RC] = (IB_QP_CUR_STATE | | 478 | IB_QP_ACCESS_FLAGS), |
481 | IB_QP_MIN_RNR_TIMER), | ||
482 | [MLX] = (IB_QP_CUR_STATE | | 479 | [MLX] = (IB_QP_CUR_STATE | |
483 | IB_QP_QKEY), | 480 | IB_QP_QKEY), |
484 | } | 481 | } |
@@ -522,6 +519,55 @@ static void init_port(struct mthca_dev *dev, int port) | |||
522 | mthca_warn(dev, "INIT_IB returned status %02x.\n", status); | 519 | mthca_warn(dev, "INIT_IB returned status %02x.\n", status); |
523 | } | 520 | } |
524 | 521 | ||
522 | static __be32 get_hw_access_flags(struct mthca_qp *qp, struct ib_qp_attr *attr, | ||
523 | int attr_mask) | ||
524 | { | ||
525 | u8 dest_rd_atomic; | ||
526 | u32 access_flags; | ||
527 | u32 hw_access_flags = 0; | ||
528 | |||
529 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) | ||
530 | dest_rd_atomic = attr->max_dest_rd_atomic; | ||
531 | else | ||
532 | dest_rd_atomic = qp->resp_depth; | ||
533 | |||
534 | if (attr_mask & IB_QP_ACCESS_FLAGS) | ||
535 | access_flags = attr->qp_access_flags; | ||
536 | else | ||
537 | access_flags = qp->atomic_rd_en; | ||
538 | |||
539 | if (!dest_rd_atomic) | ||
540 | access_flags &= IB_ACCESS_REMOTE_WRITE; | ||
541 | |||
542 | if (access_flags & IB_ACCESS_REMOTE_READ) | ||
543 | hw_access_flags |= MTHCA_QP_BIT_RRE; | ||
544 | if (access_flags & IB_ACCESS_REMOTE_ATOMIC) | ||
545 | hw_access_flags |= MTHCA_QP_BIT_RAE; | ||
546 | if (access_flags & IB_ACCESS_REMOTE_WRITE) | ||
547 | hw_access_flags |= MTHCA_QP_BIT_RWE; | ||
548 | |||
549 | return cpu_to_be32(hw_access_flags); | ||
550 | } | ||
551 | |||
552 | static void mthca_path_set(struct ib_ah_attr *ah, struct mthca_qp_path *path) | ||
553 | { | ||
554 | path->g_mylmc = ah->src_path_bits & 0x7f; | ||
555 | path->rlid = cpu_to_be16(ah->dlid); | ||
556 | path->static_rate = !!ah->static_rate; | ||
557 | |||
558 | if (ah->ah_flags & IB_AH_GRH) { | ||
559 | path->g_mylmc |= 1 << 7; | ||
560 | path->mgid_index = ah->grh.sgid_index; | ||
561 | path->hop_limit = ah->grh.hop_limit; | ||
562 | path->sl_tclass_flowlabel = | ||
563 | cpu_to_be32((ah->sl << 28) | | ||
564 | (ah->grh.traffic_class << 20) | | ||
565 | (ah->grh.flow_label)); | ||
566 | memcpy(path->rgid, ah->grh.dgid.raw, 16); | ||
567 | } else | ||
568 | path->sl_tclass_flowlabel = cpu_to_be32(ah->sl << 28); | ||
569 | } | ||
570 | |||
525 | int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | 571 | int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) |
526 | { | 572 | { |
527 | struct mthca_dev *dev = to_mdev(ibqp->device); | 573 | struct mthca_dev *dev = to_mdev(ibqp->device); |
@@ -591,6 +637,26 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
591 | return -EINVAL; | 637 | return -EINVAL; |
592 | } | 638 | } |
593 | 639 | ||
640 | if ((attr_mask & IB_QP_PORT) && | ||
641 | (attr->port_num == 0 || attr->port_num > dev->limits.num_ports)) { | ||
642 | mthca_dbg(dev, "Port number (%u) is invalid\n", attr->port_num); | ||
643 | return -EINVAL; | ||
644 | } | ||
645 | |||
646 | if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && | ||
647 | attr->max_rd_atomic > dev->limits.max_qp_init_rdma) { | ||
648 | mthca_dbg(dev, "Max rdma_atomic as initiator %u too large (max is %d)\n", | ||
649 | attr->max_rd_atomic, dev->limits.max_qp_init_rdma); | ||
650 | return -EINVAL; | ||
651 | } | ||
652 | |||
653 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && | ||
654 | attr->max_dest_rd_atomic > 1 << dev->qp_table.rdb_shift) { | ||
655 | mthca_dbg(dev, "Max rdma_atomic as responder %u too large (max %d)\n", | ||
656 | attr->max_dest_rd_atomic, 1 << dev->qp_table.rdb_shift); | ||
657 | return -EINVAL; | ||
658 | } | ||
659 | |||
594 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); | 660 | mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); |
595 | if (IS_ERR(mailbox)) | 661 | if (IS_ERR(mailbox)) |
596 | return PTR_ERR(mailbox); | 662 | return PTR_ERR(mailbox); |
@@ -665,28 +731,14 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
665 | } | 731 | } |
666 | 732 | ||
667 | if (attr_mask & IB_QP_RNR_RETRY) { | 733 | if (attr_mask & IB_QP_RNR_RETRY) { |
668 | qp_context->pri_path.rnr_retry = attr->rnr_retry << 5; | 734 | qp_context->alt_path.rnr_retry = qp_context->pri_path.rnr_retry = |
669 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY); | 735 | attr->rnr_retry << 5; |
736 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_RETRY | | ||
737 | MTHCA_QP_OPTPAR_ALT_RNR_RETRY); | ||
670 | } | 738 | } |
671 | 739 | ||
672 | if (attr_mask & IB_QP_AV) { | 740 | if (attr_mask & IB_QP_AV) { |
673 | qp_context->pri_path.g_mylmc = attr->ah_attr.src_path_bits & 0x7f; | 741 | mthca_path_set(&attr->ah_attr, &qp_context->pri_path); |
674 | qp_context->pri_path.rlid = cpu_to_be16(attr->ah_attr.dlid); | ||
675 | qp_context->pri_path.static_rate = !!attr->ah_attr.static_rate; | ||
676 | if (attr->ah_attr.ah_flags & IB_AH_GRH) { | ||
677 | qp_context->pri_path.g_mylmc |= 1 << 7; | ||
678 | qp_context->pri_path.mgid_index = attr->ah_attr.grh.sgid_index; | ||
679 | qp_context->pri_path.hop_limit = attr->ah_attr.grh.hop_limit; | ||
680 | qp_context->pri_path.sl_tclass_flowlabel = | ||
681 | cpu_to_be32((attr->ah_attr.sl << 28) | | ||
682 | (attr->ah_attr.grh.traffic_class << 20) | | ||
683 | (attr->ah_attr.grh.flow_label)); | ||
684 | memcpy(qp_context->pri_path.rgid, | ||
685 | attr->ah_attr.grh.dgid.raw, 16); | ||
686 | } else { | ||
687 | qp_context->pri_path.sl_tclass_flowlabel = | ||
688 | cpu_to_be32(attr->ah_attr.sl << 28); | ||
689 | } | ||
690 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH); | 742 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_PRIMARY_ADDR_PATH); |
691 | } | 743 | } |
692 | 744 | ||
@@ -695,7 +747,19 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
695 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT); | 747 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ACK_TIMEOUT); |
696 | } | 748 | } |
697 | 749 | ||
698 | /* XXX alt_path */ | 750 | if (attr_mask & IB_QP_ALT_PATH) { |
751 | if (attr->alt_port_num == 0 || attr->alt_port_num > dev->limits.num_ports) { | ||
752 | mthca_dbg(dev, "Alternate port number (%u) is invalid\n", | ||
753 | attr->alt_port_num); | ||
754 | return -EINVAL; | ||
755 | } | ||
756 | |||
757 | mthca_path_set(&attr->alt_ah_attr, &qp_context->alt_path); | ||
758 | qp_context->alt_path.port_pkey |= cpu_to_be32(attr->alt_pkey_index | | ||
759 | attr->alt_port_num << 24); | ||
760 | qp_context->alt_path.ackto = attr->alt_timeout << 3; | ||
761 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_ALT_ADDR_PATH); | ||
762 | } | ||
699 | 763 | ||
700 | /* leave rdd as 0 */ | 764 | /* leave rdd as 0 */ |
701 | qp_context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pd_num); | 765 | qp_context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pd_num); |
@@ -703,9 +767,7 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
703 | qp_context->wqe_lkey = cpu_to_be32(qp->mr.ibmr.lkey); | 767 | qp_context->wqe_lkey = cpu_to_be32(qp->mr.ibmr.lkey); |
704 | qp_context->params1 = cpu_to_be32((MTHCA_ACK_REQ_FREQ << 28) | | 768 | qp_context->params1 = cpu_to_be32((MTHCA_ACK_REQ_FREQ << 28) | |
705 | (MTHCA_FLIGHT_LIMIT << 24) | | 769 | (MTHCA_FLIGHT_LIMIT << 24) | |
706 | MTHCA_QP_BIT_SRE | | 770 | MTHCA_QP_BIT_SWE); |
707 | MTHCA_QP_BIT_SWE | | ||
708 | MTHCA_QP_BIT_SAE); | ||
709 | if (qp->sq_policy == IB_SIGNAL_ALL_WR) | 771 | if (qp->sq_policy == IB_SIGNAL_ALL_WR) |
710 | qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC); | 772 | qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC); |
711 | if (attr_mask & IB_QP_RETRY_CNT) { | 773 | if (attr_mask & IB_QP_RETRY_CNT) { |
@@ -714,9 +776,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
714 | } | 776 | } |
715 | 777 | ||
716 | if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { | 778 | if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) { |
717 | qp_context->params1 |= cpu_to_be32(min(attr->max_rd_atomic ? | 779 | if (attr->max_rd_atomic) { |
718 | ffs(attr->max_rd_atomic) - 1 : 0, | 780 | qp_context->params1 |= |
719 | 7) << 21); | 781 | cpu_to_be32(MTHCA_QP_BIT_SRE | |
782 | MTHCA_QP_BIT_SAE); | ||
783 | qp_context->params1 |= | ||
784 | cpu_to_be32(fls(attr->max_rd_atomic - 1) << 21); | ||
785 | } | ||
720 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX); | 786 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_SRA_MAX); |
721 | } | 787 | } |
722 | 788 | ||
@@ -729,71 +795,19 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
729 | qp_context->snd_db_index = cpu_to_be32(qp->sq.db_index); | 795 | qp_context->snd_db_index = cpu_to_be32(qp->sq.db_index); |
730 | } | 796 | } |
731 | 797 | ||
732 | if (attr_mask & IB_QP_ACCESS_FLAGS) { | ||
733 | qp_context->params2 |= | ||
734 | cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE ? | ||
735 | MTHCA_QP_BIT_RWE : 0); | ||
736 | |||
737 | /* | ||
738 | * Only enable RDMA reads and atomics if we have | ||
739 | * responder resources set to a non-zero value. | ||
740 | */ | ||
741 | if (qp->resp_depth) { | ||
742 | qp_context->params2 |= | ||
743 | cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_READ ? | ||
744 | MTHCA_QP_BIT_RRE : 0); | ||
745 | qp_context->params2 |= | ||
746 | cpu_to_be32(attr->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC ? | ||
747 | MTHCA_QP_BIT_RAE : 0); | ||
748 | } | ||
749 | |||
750 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE | | ||
751 | MTHCA_QP_OPTPAR_RRE | | ||
752 | MTHCA_QP_OPTPAR_RAE); | ||
753 | |||
754 | qp->atomic_rd_en = attr->qp_access_flags; | ||
755 | } | ||
756 | |||
757 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { | 798 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) { |
758 | u8 rra_max; | 799 | if (attr->max_dest_rd_atomic) |
759 | |||
760 | if (qp->resp_depth && !attr->max_dest_rd_atomic) { | ||
761 | /* | ||
762 | * Lowering our responder resources to zero. | ||
763 | * Turn off reads RDMA and atomics as responder. | ||
764 | * (RRE/RAE in params2 already zero) | ||
765 | */ | ||
766 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE | | ||
767 | MTHCA_QP_OPTPAR_RAE); | ||
768 | } | ||
769 | |||
770 | if (!qp->resp_depth && attr->max_dest_rd_atomic) { | ||
771 | /* | ||
772 | * Increasing our responder resources from | ||
773 | * zero. Turn on RDMA reads and atomics as | ||
774 | * appropriate. | ||
775 | */ | ||
776 | qp_context->params2 |= | 800 | qp_context->params2 |= |
777 | cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_READ ? | 801 | cpu_to_be32(fls(attr->max_dest_rd_atomic - 1) << 21); |
778 | MTHCA_QP_BIT_RRE : 0); | ||
779 | qp_context->params2 |= | ||
780 | cpu_to_be32(qp->atomic_rd_en & IB_ACCESS_REMOTE_ATOMIC ? | ||
781 | MTHCA_QP_BIT_RAE : 0); | ||
782 | |||
783 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRE | | ||
784 | MTHCA_QP_OPTPAR_RAE); | ||
785 | } | ||
786 | 802 | ||
787 | for (rra_max = 0; | ||
788 | 1 << rra_max < attr->max_dest_rd_atomic && | ||
789 | rra_max < dev->qp_table.rdb_shift; | ||
790 | ++rra_max) | ||
791 | ; /* nothing */ | ||
792 | |||
793 | qp_context->params2 |= cpu_to_be32(rra_max << 21); | ||
794 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX); | 803 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RRA_MAX); |
804 | } | ||
795 | 805 | ||
796 | qp->resp_depth = attr->max_dest_rd_atomic; | 806 | if (attr_mask & (IB_QP_ACCESS_FLAGS | IB_QP_MAX_DEST_RD_ATOMIC)) { |
807 | qp_context->params2 |= get_hw_access_flags(qp, attr, attr_mask); | ||
808 | qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RWE | | ||
809 | MTHCA_QP_OPTPAR_RRE | | ||
810 | MTHCA_QP_OPTPAR_RAE); | ||
797 | } | 811 | } |
798 | 812 | ||
799 | qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC); | 813 | qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC); |
@@ -835,8 +849,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
835 | err = -EINVAL; | 849 | err = -EINVAL; |
836 | } | 850 | } |
837 | 851 | ||
838 | if (!err) | 852 | if (!err) { |
839 | qp->state = new_state; | 853 | qp->state = new_state; |
854 | if (attr_mask & IB_QP_ACCESS_FLAGS) | ||
855 | qp->atomic_rd_en = attr->qp_access_flags; | ||
856 | if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC) | ||
857 | qp->resp_depth = attr->max_dest_rd_atomic; | ||
858 | } | ||
840 | 859 | ||
841 | mthca_free_mailbox(dev, mailbox); | 860 | mthca_free_mailbox(dev, mailbox); |
842 | 861 | ||
@@ -885,18 +904,13 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) | |||
885 | return err; | 904 | return err; |
886 | } | 905 | } |
887 | 906 | ||
888 | static void mthca_adjust_qp_caps(struct mthca_dev *dev, | 907 | static int mthca_max_data_size(struct mthca_dev *dev, struct mthca_qp *qp, int desc_sz) |
889 | struct mthca_pd *pd, | ||
890 | struct mthca_qp *qp) | ||
891 | { | 908 | { |
892 | int max_data_size; | ||
893 | |||
894 | /* | 909 | /* |
895 | * Calculate the maximum size of WQE s/g segments, excluding | 910 | * Calculate the maximum size of WQE s/g segments, excluding |
896 | * the next segment and other non-data segments. | 911 | * the next segment and other non-data segments. |
897 | */ | 912 | */ |
898 | max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) - | 913 | int max_data_size = desc_sz - sizeof (struct mthca_next_seg); |
899 | sizeof (struct mthca_next_seg); | ||
900 | 914 | ||
901 | switch (qp->transport) { | 915 | switch (qp->transport) { |
902 | case MLX: | 916 | case MLX: |
@@ -915,11 +929,24 @@ static void mthca_adjust_qp_caps(struct mthca_dev *dev, | |||
915 | break; | 929 | break; |
916 | } | 930 | } |
917 | 931 | ||
932 | return max_data_size; | ||
933 | } | ||
934 | |||
935 | static inline int mthca_max_inline_data(struct mthca_pd *pd, int max_data_size) | ||
936 | { | ||
918 | /* We don't support inline data for kernel QPs (yet). */ | 937 | /* We don't support inline data for kernel QPs (yet). */ |
919 | if (!pd->ibpd.uobject) | 938 | return pd->ibpd.uobject ? max_data_size - MTHCA_INLINE_HEADER_SIZE : 0; |
920 | qp->max_inline_data = 0; | 939 | } |
921 | else | 940 | |
922 | qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE; | 941 | static void mthca_adjust_qp_caps(struct mthca_dev *dev, |
942 | struct mthca_pd *pd, | ||
943 | struct mthca_qp *qp) | ||
944 | { | ||
945 | int max_data_size = mthca_max_data_size(dev, qp, | ||
946 | min(dev->limits.max_desc_sz, | ||
947 | 1 << qp->sq.wqe_shift)); | ||
948 | |||
949 | qp->max_inline_data = mthca_max_inline_data(pd, max_data_size); | ||
923 | 950 | ||
924 | qp->sq.max_gs = min_t(int, dev->limits.max_sg, | 951 | qp->sq.max_gs = min_t(int, dev->limits.max_sg, |
925 | max_data_size / sizeof (struct mthca_data_seg)); | 952 | max_data_size / sizeof (struct mthca_data_seg)); |
@@ -1186,13 +1213,23 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev, | |||
1186 | } | 1213 | } |
1187 | 1214 | ||
1188 | static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, | 1215 | static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, |
1189 | struct mthca_qp *qp) | 1216 | struct mthca_pd *pd, struct mthca_qp *qp) |
1190 | { | 1217 | { |
1218 | int max_data_size = mthca_max_data_size(dev, qp, dev->limits.max_desc_sz); | ||
1219 | |||
1191 | /* Sanity check QP size before proceeding */ | 1220 | /* Sanity check QP size before proceeding */ |
1192 | if (cap->max_send_wr > dev->limits.max_wqes || | 1221 | if (cap->max_send_wr > dev->limits.max_wqes || |
1193 | cap->max_recv_wr > dev->limits.max_wqes || | 1222 | cap->max_recv_wr > dev->limits.max_wqes || |
1194 | cap->max_send_sge > dev->limits.max_sg || | 1223 | cap->max_send_sge > dev->limits.max_sg || |
1195 | cap->max_recv_sge > dev->limits.max_sg) | 1224 | cap->max_recv_sge > dev->limits.max_sg || |
1225 | cap->max_inline_data > mthca_max_inline_data(pd, max_data_size)) | ||
1226 | return -EINVAL; | ||
1227 | |||
1228 | /* | ||
1229 | * For MLX transport we need 2 extra S/G entries: | ||
1230 | * one for the header and one for the checksum at the end | ||
1231 | */ | ||
1232 | if (qp->transport == MLX && cap->max_recv_sge + 2 > dev->limits.max_sg) | ||
1196 | return -EINVAL; | 1233 | return -EINVAL; |
1197 | 1234 | ||
1198 | if (mthca_is_memfree(dev)) { | 1235 | if (mthca_is_memfree(dev)) { |
@@ -1211,14 +1248,6 @@ static int mthca_set_qp_size(struct mthca_dev *dev, struct ib_qp_cap *cap, | |||
1211 | MTHCA_INLINE_CHUNK_SIZE) / | 1248 | MTHCA_INLINE_CHUNK_SIZE) / |
1212 | sizeof (struct mthca_data_seg)); | 1249 | sizeof (struct mthca_data_seg)); |
1213 | 1250 | ||
1214 | /* | ||
1215 | * For MLX transport we need 2 extra S/G entries: | ||
1216 | * one for the header and one for the checksum at the end | ||
1217 | */ | ||
1218 | if ((qp->transport == MLX && qp->sq.max_gs + 2 > dev->limits.max_sg) || | ||
1219 | qp->sq.max_gs > dev->limits.max_sg || qp->rq.max_gs > dev->limits.max_sg) | ||
1220 | return -EINVAL; | ||
1221 | |||
1222 | return 0; | 1251 | return 0; |
1223 | } | 1252 | } |
1224 | 1253 | ||
@@ -1233,7 +1262,7 @@ int mthca_alloc_qp(struct mthca_dev *dev, | |||
1233 | { | 1262 | { |
1234 | int err; | 1263 | int err; |
1235 | 1264 | ||
1236 | err = mthca_set_qp_size(dev, cap, qp); | 1265 | err = mthca_set_qp_size(dev, cap, pd, qp); |
1237 | if (err) | 1266 | if (err) |
1238 | return err; | 1267 | return err; |
1239 | 1268 | ||
@@ -1276,7 +1305,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev, | |||
1276 | u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1; | 1305 | u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1; |
1277 | int err; | 1306 | int err; |
1278 | 1307 | ||
1279 | err = mthca_set_qp_size(dev, cap, &sqp->qp); | 1308 | err = mthca_set_qp_size(dev, cap, pd, &sqp->qp); |
1280 | if (err) | 1309 | if (err) |
1281 | return err; | 1310 | return err; |
1282 | 1311 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index f7d234295efe..e7e153d9c4c6 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c | |||
@@ -201,7 +201,7 @@ int mthca_alloc_srq(struct mthca_dev *dev, struct mthca_pd *pd, | |||
201 | if (mthca_is_memfree(dev)) | 201 | if (mthca_is_memfree(dev)) |
202 | srq->max = roundup_pow_of_two(srq->max + 1); | 202 | srq->max = roundup_pow_of_two(srq->max + 1); |
203 | 203 | ||
204 | ds = min(64UL, | 204 | ds = max(64UL, |
205 | roundup_pow_of_two(sizeof (struct mthca_next_seg) + | 205 | roundup_pow_of_two(sizeof (struct mthca_next_seg) + |
206 | srq->max_gs * sizeof (struct mthca_data_seg))); | 206 | srq->max_gs * sizeof (struct mthca_data_seg))); |
207 | srq->wqe_shift = long_log2(ds); | 207 | srq->wqe_shift = long_log2(ds); |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index ee9fe226ae99..dd488d3cffa9 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/string.h> | 39 | #include <linux/string.h> |
40 | #include <linux/parser.h> | 40 | #include <linux/parser.h> |
41 | #include <linux/random.h> | 41 | #include <linux/random.h> |
42 | #include <linux/jiffies.h> | ||
42 | 43 | ||
43 | #include <asm/atomic.h> | 44 | #include <asm/atomic.h> |
44 | 45 | ||
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index 64672d491222..e301ee4ca264 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <asm/irq.h> | ||
23 | 22 | ||
24 | #include <asm/arch/corgi.h> | 23 | #include <asm/arch/corgi.h> |
25 | #include <asm/arch/hardware.h> | 24 | #include <asm/arch/hardware.h> |
@@ -343,10 +342,9 @@ static int __init corgikbd_probe(struct platform_device *pdev) | |||
343 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { | 342 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { |
344 | pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); | 343 | pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); |
345 | if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, | 344 | if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, |
346 | SA_INTERRUPT, "corgikbd", corgikbd)) | 345 | SA_INTERRUPT | SA_TRIGGER_RISING, |
346 | "corgikbd", corgikbd)) | ||
347 | printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); | 347 | printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); |
348 | else | ||
349 | set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING); | ||
350 | } | 348 | } |
351 | 349 | ||
352 | /* Set Strobe lines as outputs - set high */ | 350 | /* Set Strobe lines as outputs - set high */ |
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index 6a15fe3bc527..83999d583122 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <asm/irq.h> | ||
23 | 22 | ||
24 | #include <asm/arch/spitz.h> | 23 | #include <asm/arch/spitz.h> |
25 | #include <asm/arch/hardware.h> | 24 | #include <asm/arch/hardware.h> |
@@ -407,10 +406,9 @@ static int __init spitzkbd_probe(struct platform_device *dev) | |||
407 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { | 406 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { |
408 | pxa_gpio_mode(spitz_senses[i] | GPIO_IN); | 407 | pxa_gpio_mode(spitz_senses[i] | GPIO_IN); |
409 | if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, | 408 | if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, |
410 | SA_INTERRUPT, "Spitzkbd Sense", spitzkbd)) | 409 | SA_INTERRUPT|SA_TRIGGER_RISING, |
410 | "Spitzkbd Sense", spitzkbd)) | ||
411 | printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); | 411 | printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); |
412 | else | ||
413 | set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING); | ||
414 | } | 412 | } |
415 | 413 | ||
416 | /* Set Strobe lines as outputs - set high */ | 414 | /* Set Strobe lines as outputs - set high */ |
@@ -422,15 +420,18 @@ static int __init spitzkbd_probe(struct platform_device *dev) | |||
422 | pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); | 420 | pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); |
423 | pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); | 421 | pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); |
424 | 422 | ||
425 | request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd); | 423 | request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, |
426 | request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd); | 424 | SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, |
427 | request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd); | 425 | "Spitzkbd Sync", spitzkbd); |
428 | request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd); | 426 | request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, |
429 | 427 | SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, | |
430 | set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE); | 428 | "Spitzkbd PwrOn", spitzkbd); |
431 | set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE); | 429 | request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, |
432 | set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE); | 430 | SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, |
433 | set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE); | 431 | "Spitzkbd SWA", spitzkbd); |
432 | request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, | ||
433 | SA_INTERRUPT | SA_TRIGGER_RISING | SA_TRIGGER_FALLING, | ||
434 | "Spitzkbd SWB", spitzkbd); | ||
434 | 435 | ||
435 | printk(KERN_INFO "input: Spitz Keyboard Registered\n"); | 436 | printk(KERN_INFO "input: Spitz Keyboard Registered\n"); |
436 | 437 | ||
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index 1cd7657f7e42..1be963961c15 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c | |||
@@ -60,8 +60,6 @@ static struct fasync_struct *hp_sdc_rtc_async_queue; | |||
60 | 60 | ||
61 | static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); | 61 | static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait); |
62 | 62 | ||
63 | static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin); | ||
64 | |||
65 | static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, | 63 | static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, |
66 | size_t count, loff_t *ppos); | 64 | size_t count, loff_t *ppos); |
67 | 65 | ||
@@ -387,11 +385,6 @@ static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd) | |||
387 | return 0; | 385 | return 0; |
388 | } | 386 | } |
389 | 387 | ||
390 | static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin) | ||
391 | { | ||
392 | return -ESPIPE; | ||
393 | } | ||
394 | |||
395 | static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, | 388 | static ssize_t hp_sdc_rtc_read(struct file *file, char *buf, |
396 | size_t count, loff_t *ppos) { | 389 | size_t count, loff_t *ppos) { |
397 | ssize_t retval; | 390 | ssize_t retval; |
@@ -679,7 +672,7 @@ static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, | |||
679 | 672 | ||
680 | static struct file_operations hp_sdc_rtc_fops = { | 673 | static struct file_operations hp_sdc_rtc_fops = { |
681 | .owner = THIS_MODULE, | 674 | .owner = THIS_MODULE, |
682 | .llseek = hp_sdc_rtc_llseek, | 675 | .llseek = no_llseek, |
683 | .read = hp_sdc_rtc_read, | 676 | .read = hp_sdc_rtc_read, |
684 | .poll = hp_sdc_rtc_poll, | 677 | .poll = hp_sdc_rtc_poll, |
685 | .ioctl = hp_sdc_rtc_ioctl, | 678 | .ioctl = hp_sdc_rtc_ioctl, |
diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h index b091d1a54125..d4c50512a1ff 100644 --- a/drivers/isdn/act2000/act2000.h +++ b/drivers/isdn/act2000/act2000.h | |||
@@ -181,17 +181,17 @@ typedef struct act2000_card { | |||
181 | char regname[35]; /* Name used for request_region */ | 181 | char regname[35]; /* Name used for request_region */ |
182 | } act2000_card; | 182 | } act2000_card; |
183 | 183 | ||
184 | extern __inline__ void act2000_schedule_tx(act2000_card *card) | 184 | static inline void act2000_schedule_tx(act2000_card *card) |
185 | { | 185 | { |
186 | schedule_work(&card->snd_tq); | 186 | schedule_work(&card->snd_tq); |
187 | } | 187 | } |
188 | 188 | ||
189 | extern __inline__ void act2000_schedule_rx(act2000_card *card) | 189 | static inline void act2000_schedule_rx(act2000_card *card) |
190 | { | 190 | { |
191 | schedule_work(&card->rcv_tq); | 191 | schedule_work(&card->rcv_tq); |
192 | } | 192 | } |
193 | 193 | ||
194 | extern __inline__ void act2000_schedule_poll(act2000_card *card) | 194 | static inline void act2000_schedule_poll(act2000_card *card) |
195 | { | 195 | { |
196 | schedule_work(&card->poll_tq); | 196 | schedule_work(&card->poll_tq); |
197 | } | 197 | } |
diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h index f6d5f530b86b..49f453c53c64 100644 --- a/drivers/isdn/act2000/capi.h +++ b/drivers/isdn/act2000/capi.h | |||
@@ -78,29 +78,29 @@ typedef union actcapi_infoel { /* info element */ | |||
78 | typedef struct actcapi_msn { | 78 | typedef struct actcapi_msn { |
79 | __u8 eaz; | 79 | __u8 eaz; |
80 | __u8 len; /* Length of MSN */ | 80 | __u8 len; /* Length of MSN */ |
81 | __u8 msn[15] __attribute__ ((packed)); | 81 | __u8 msn[15]; |
82 | } actcapi_msn; | 82 | } __attribute__((packed)) actcapi_msn; |
83 | 83 | ||
84 | typedef struct actcapi_dlpd { | 84 | typedef struct actcapi_dlpd { |
85 | __u8 len; /* Length of structure */ | 85 | __u8 len; /* Length of structure */ |
86 | __u16 dlen __attribute__ ((packed)); /* Data Length */ | 86 | __u16 dlen; /* Data Length */ |
87 | __u8 laa __attribute__ ((packed)); /* Link Address A */ | 87 | __u8 laa; /* Link Address A */ |
88 | __u8 lab; /* Link Address B */ | 88 | __u8 lab; /* Link Address B */ |
89 | __u8 modulo; /* Modulo Mode */ | 89 | __u8 modulo; /* Modulo Mode */ |
90 | __u8 win; /* Window size */ | 90 | __u8 win; /* Window size */ |
91 | __u8 xid[100]; /* XID Information */ | 91 | __u8 xid[100]; /* XID Information */ |
92 | } actcapi_dlpd; | 92 | } __attribute__((packed)) actcapi_dlpd; |
93 | 93 | ||
94 | typedef struct actcapi_ncpd { | 94 | typedef struct actcapi_ncpd { |
95 | __u8 len; /* Length of structure */ | 95 | __u8 len; /* Length of structure */ |
96 | __u16 lic __attribute__ ((packed)); | 96 | __u16 lic; |
97 | __u16 hic __attribute__ ((packed)); | 97 | __u16 hic; |
98 | __u16 ltc __attribute__ ((packed)); | 98 | __u16 ltc; |
99 | __u16 htc __attribute__ ((packed)); | 99 | __u16 htc; |
100 | __u16 loc __attribute__ ((packed)); | 100 | __u16 loc; |
101 | __u16 hoc __attribute__ ((packed)); | 101 | __u16 hoc; |
102 | __u8 modulo __attribute__ ((packed)); | 102 | __u8 modulo; |
103 | } actcapi_ncpd; | 103 | } __attribute__((packed)) actcapi_ncpd; |
104 | #define actcapi_ncpi actcapi_ncpd | 104 | #define actcapi_ncpi actcapi_ncpd |
105 | 105 | ||
106 | /* | 106 | /* |
@@ -168,19 +168,19 @@ typedef struct actcapi_msg { | |||
168 | __u16 manuf_msg; | 168 | __u16 manuf_msg; |
169 | __u16 controller; | 169 | __u16 controller; |
170 | actcapi_msn msnmap; | 170 | actcapi_msn msnmap; |
171 | } manufacturer_req_msn; | 171 | } __attribute ((packed)) manufacturer_req_msn; |
172 | /* TODO: TraceInit-req/conf/ind/resp and | 172 | /* TODO: TraceInit-req/conf/ind/resp and |
173 | * TraceDump-req/conf/ind/resp | 173 | * TraceDump-req/conf/ind/resp |
174 | */ | 174 | */ |
175 | struct connect_req { | 175 | struct connect_req { |
176 | __u8 controller; | 176 | __u8 controller; |
177 | __u8 bchan; | 177 | __u8 bchan; |
178 | __u32 infomask __attribute__ ((packed)); | 178 | __u32 infomask; |
179 | __u8 si1; | 179 | __u8 si1; |
180 | __u8 si2; | 180 | __u8 si2; |
181 | __u8 eaz; | 181 | __u8 eaz; |
182 | actcapi_addr addr; | 182 | actcapi_addr addr; |
183 | } connect_req; | 183 | } __attribute__ ((packed)) connect_req; |
184 | struct connect_conf { | 184 | struct connect_conf { |
185 | __u16 plci; | 185 | __u16 plci; |
186 | __u16 info; | 186 | __u16 info; |
@@ -192,7 +192,7 @@ typedef struct actcapi_msg { | |||
192 | __u8 si2; | 192 | __u8 si2; |
193 | __u8 eaz; | 193 | __u8 eaz; |
194 | actcapi_addr addr; | 194 | actcapi_addr addr; |
195 | } connect_ind; | 195 | } __attribute__ ((packed)) connect_ind; |
196 | struct connect_resp { | 196 | struct connect_resp { |
197 | __u16 plci; | 197 | __u16 plci; |
198 | __u8 rejectcause; | 198 | __u8 rejectcause; |
@@ -200,14 +200,14 @@ typedef struct actcapi_msg { | |||
200 | struct connect_active_ind { | 200 | struct connect_active_ind { |
201 | __u16 plci; | 201 | __u16 plci; |
202 | actcapi_addr addr; | 202 | actcapi_addr addr; |
203 | } connect_active_ind; | 203 | } __attribute__ ((packed)) connect_active_ind; |
204 | struct connect_active_resp { | 204 | struct connect_active_resp { |
205 | __u16 plci; | 205 | __u16 plci; |
206 | } connect_active_resp; | 206 | } connect_active_resp; |
207 | struct connect_b3_req { | 207 | struct connect_b3_req { |
208 | __u16 plci; | 208 | __u16 plci; |
209 | actcapi_ncpi ncpi; | 209 | actcapi_ncpi ncpi; |
210 | } connect_b3_req; | 210 | } __attribute__ ((packed)) connect_b3_req; |
211 | struct connect_b3_conf { | 211 | struct connect_b3_conf { |
212 | __u16 plci; | 212 | __u16 plci; |
213 | __u16 ncci; | 213 | __u16 ncci; |
@@ -217,12 +217,12 @@ typedef struct actcapi_msg { | |||
217 | __u16 ncci; | 217 | __u16 ncci; |
218 | __u16 plci; | 218 | __u16 plci; |
219 | actcapi_ncpi ncpi; | 219 | actcapi_ncpi ncpi; |
220 | } connect_b3_ind; | 220 | } __attribute__ ((packed)) connect_b3_ind; |
221 | struct connect_b3_resp { | 221 | struct connect_b3_resp { |
222 | __u16 ncci; | 222 | __u16 ncci; |
223 | __u8 rejectcause; | 223 | __u8 rejectcause; |
224 | actcapi_ncpi ncpi __attribute__ ((packed)); | 224 | actcapi_ncpi ncpi; |
225 | } connect_b3_resp; | 225 | } __attribute__ ((packed)) connect_b3_resp; |
226 | struct disconnect_req { | 226 | struct disconnect_req { |
227 | __u16 plci; | 227 | __u16 plci; |
228 | __u8 cause; | 228 | __u8 cause; |
@@ -241,14 +241,14 @@ typedef struct actcapi_msg { | |||
241 | struct connect_b3_active_ind { | 241 | struct connect_b3_active_ind { |
242 | __u16 ncci; | 242 | __u16 ncci; |
243 | actcapi_ncpi ncpi; | 243 | actcapi_ncpi ncpi; |
244 | } connect_b3_active_ind; | 244 | } __attribute__ ((packed)) connect_b3_active_ind; |
245 | struct connect_b3_active_resp { | 245 | struct connect_b3_active_resp { |
246 | __u16 ncci; | 246 | __u16 ncci; |
247 | } connect_b3_active_resp; | 247 | } connect_b3_active_resp; |
248 | struct disconnect_b3_req { | 248 | struct disconnect_b3_req { |
249 | __u16 ncci; | 249 | __u16 ncci; |
250 | actcapi_ncpi ncpi; | 250 | actcapi_ncpi ncpi; |
251 | } disconnect_b3_req; | 251 | } __attribute__ ((packed)) disconnect_b3_req; |
252 | struct disconnect_b3_conf { | 252 | struct disconnect_b3_conf { |
253 | __u16 ncci; | 253 | __u16 ncci; |
254 | __u16 info; | 254 | __u16 info; |
@@ -257,7 +257,7 @@ typedef struct actcapi_msg { | |||
257 | __u16 ncci; | 257 | __u16 ncci; |
258 | __u16 info; | 258 | __u16 info; |
259 | actcapi_ncpi ncpi; | 259 | actcapi_ncpi ncpi; |
260 | } disconnect_b3_ind; | 260 | } __attribute__ ((packed)) disconnect_b3_ind; |
261 | struct disconnect_b3_resp { | 261 | struct disconnect_b3_resp { |
262 | __u16 ncci; | 262 | __u16 ncci; |
263 | } disconnect_b3_resp; | 263 | } disconnect_b3_resp; |
@@ -265,7 +265,7 @@ typedef struct actcapi_msg { | |||
265 | __u16 plci; | 265 | __u16 plci; |
266 | actcapi_infonr nr; | 266 | actcapi_infonr nr; |
267 | actcapi_infoel el; | 267 | actcapi_infoel el; |
268 | } info_ind; | 268 | } __attribute__ ((packed)) info_ind; |
269 | struct info_resp { | 269 | struct info_resp { |
270 | __u16 plci; | 270 | __u16 plci; |
271 | } info_resp; | 271 | } info_resp; |
@@ -279,8 +279,8 @@ typedef struct actcapi_msg { | |||
279 | struct select_b2_protocol_req { | 279 | struct select_b2_protocol_req { |
280 | __u16 plci; | 280 | __u16 plci; |
281 | __u8 protocol; | 281 | __u8 protocol; |
282 | actcapi_dlpd dlpd __attribute__ ((packed)); | 282 | actcapi_dlpd dlpd; |
283 | } select_b2_protocol_req; | 283 | } __attribute__ ((packed)) select_b2_protocol_req; |
284 | struct select_b2_protocol_conf { | 284 | struct select_b2_protocol_conf { |
285 | __u16 plci; | 285 | __u16 plci; |
286 | __u16 info; | 286 | __u16 info; |
@@ -288,49 +288,49 @@ typedef struct actcapi_msg { | |||
288 | struct select_b3_protocol_req { | 288 | struct select_b3_protocol_req { |
289 | __u16 plci; | 289 | __u16 plci; |
290 | __u8 protocol; | 290 | __u8 protocol; |
291 | actcapi_ncpd ncpd __attribute__ ((packed)); | 291 | actcapi_ncpd ncpd; |
292 | } select_b3_protocol_req; | 292 | } __attribute__ ((packed)) select_b3_protocol_req; |
293 | struct select_b3_protocol_conf { | 293 | struct select_b3_protocol_conf { |
294 | __u16 plci; | 294 | __u16 plci; |
295 | __u16 info; | 295 | __u16 info; |
296 | } select_b3_protocol_conf; | 296 | } select_b3_protocol_conf; |
297 | struct listen_req { | 297 | struct listen_req { |
298 | __u8 controller; | 298 | __u8 controller; |
299 | __u32 infomask __attribute__ ((packed)); | 299 | __u32 infomask; |
300 | __u16 eazmask __attribute__ ((packed)); | 300 | __u16 eazmask; |
301 | __u16 simask __attribute__ ((packed)); | 301 | __u16 simask; |
302 | } listen_req; | 302 | } __attribute__ ((packed)) listen_req; |
303 | struct listen_conf { | 303 | struct listen_conf { |
304 | __u8 controller; | 304 | __u8 controller; |
305 | __u16 info __attribute__ ((packed)); | 305 | __u16 info; |
306 | } listen_conf; | 306 | } __attribute__ ((packed)) listen_conf; |
307 | struct data_b3_req { | 307 | struct data_b3_req { |
308 | __u16 fakencci; | 308 | __u16 fakencci; |
309 | __u16 datalen; | 309 | __u16 datalen; |
310 | __u32 unused; | 310 | __u32 unused; |
311 | __u8 blocknr; | 311 | __u8 blocknr; |
312 | __u16 flags __attribute__ ((packed)); | 312 | __u16 flags; |
313 | } data_b3_req; | 313 | } __attribute ((packed)) data_b3_req; |
314 | struct data_b3_ind { | 314 | struct data_b3_ind { |
315 | __u16 fakencci; | 315 | __u16 fakencci; |
316 | __u16 datalen; | 316 | __u16 datalen; |
317 | __u32 unused; | 317 | __u32 unused; |
318 | __u8 blocknr; | 318 | __u8 blocknr; |
319 | __u16 flags __attribute__ ((packed)); | 319 | __u16 flags; |
320 | } data_b3_ind; | 320 | } __attribute__ ((packed)) data_b3_ind; |
321 | struct data_b3_resp { | 321 | struct data_b3_resp { |
322 | __u16 ncci; | 322 | __u16 ncci; |
323 | __u8 blocknr; | 323 | __u8 blocknr; |
324 | } data_b3_resp; | 324 | } __attribute__ ((packed)) data_b3_resp; |
325 | struct data_b3_conf { | 325 | struct data_b3_conf { |
326 | __u16 ncci; | 326 | __u16 ncci; |
327 | __u8 blocknr; | 327 | __u8 blocknr; |
328 | __u16 info __attribute__ ((packed)); | 328 | __u16 info; |
329 | } data_b3_conf; | 329 | } __attribute__ ((packed)) data_b3_conf; |
330 | } msg; | 330 | } msg; |
331 | } actcapi_msg; | 331 | } __attribute__ ((packed)) actcapi_msg; |
332 | 332 | ||
333 | extern __inline__ unsigned short | 333 | static inline unsigned short |
334 | actcapi_nextsmsg(act2000_card *card) | 334 | actcapi_nextsmsg(act2000_card *card) |
335 | { | 335 | { |
336 | unsigned long flags; | 336 | unsigned long flags; |
diff --git a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c index 7b564c0dd996..207cae366256 100644 --- a/drivers/isdn/capi/capifs.c +++ b/drivers/isdn/capi/capifs.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
18 | #include <linux/sched.h> /* current */ | 18 | #include <linux/sched.h> /* current */ |
19 | 19 | ||
20 | #include "capifs.h" | ||
21 | |||
20 | MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem"); | 22 | MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem"); |
21 | MODULE_AUTHOR("Carsten Paeth"); | 23 | MODULE_AUTHOR("Carsten Paeth"); |
22 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c index cccfabc1117d..11e6f937c1e4 100644 --- a/drivers/isdn/hardware/eicon/os_4bri.c +++ b/drivers/isdn/hardware/eicon/os_4bri.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "diva_pci.h" | 16 | #include "diva_pci.h" |
17 | #include "mi_pc.h" | 17 | #include "mi_pc.h" |
18 | #include "dsrv4bri.h" | 18 | #include "dsrv4bri.h" |
19 | #include "helpers.h" | ||
19 | 20 | ||
20 | static void *diva_xdiLoadFileFile = NULL; | 21 | static void *diva_xdiLoadFileFile = NULL; |
21 | static dword diva_xdiLoadFileLength = 0; | 22 | static dword diva_xdiLoadFileLength = 0; |
@@ -815,7 +816,7 @@ diva_4bri_cmd_card_proc(struct _diva_os_xdi_adapter *a, | |||
815 | return (ret); | 816 | return (ret); |
816 | } | 817 | } |
817 | 818 | ||
818 | void *xdiLoadFile(char *FileName, unsigned long *FileLength, | 819 | void *xdiLoadFile(char *FileName, dword *FileLength, |
819 | unsigned long lim) | 820 | unsigned long lim) |
820 | { | 821 | { |
821 | void *ret = diva_xdiLoadFileFile; | 822 | void *ret = diva_xdiLoadFileFile; |
diff --git a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c index 4cc44a5dd1db..f31bba5b16ff 100644 --- a/drivers/isdn/hardware/eicon/os_bri.c +++ b/drivers/isdn/hardware/eicon/os_bri.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include "diva_pci.h" | 16 | #include "diva_pci.h" |
17 | #include "mi_pc.h" | 17 | #include "mi_pc.h" |
18 | #include "pc_maint.h" | 18 | #include "pc_maint.h" |
19 | #include "dsrv_bri.h" | ||
19 | 20 | ||
20 | /* | 21 | /* |
21 | ** IMPORTS | 22 | ** IMPORTS |
diff --git a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c index 8ac207f75e54..a296a846f296 100644 --- a/drivers/isdn/hardware/eicon/os_pri.c +++ b/drivers/isdn/hardware/eicon/os_pri.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "pc_maint.h" | 18 | #include "pc_maint.h" |
19 | #include "dsp_tst.h" | 19 | #include "dsp_tst.h" |
20 | #include "diva_dma.h" | 20 | #include "diva_dma.h" |
21 | #include "dsrv_pri.h" | ||
21 | 22 | ||
22 | /* -------------------------------------------------------------------------- | 23 | /* -------------------------------------------------------------------------- |
23 | OS Dependent part of XDI driver for DIVA PRI Adapter | 24 | OS Dependent part of XDI driver for DIVA PRI Adapter |
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index c82105920d71..0ef560144be3 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig | |||
@@ -110,7 +110,7 @@ config HISAX_16_3 | |||
110 | 110 | ||
111 | config HISAX_TELESPCI | 111 | config HISAX_TELESPCI |
112 | bool "Teles PCI" | 112 | bool "Teles PCI" |
113 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) | 113 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) |
114 | help | 114 | help |
115 | This enables HiSax support for the Teles PCI. | 115 | This enables HiSax support for the Teles PCI. |
116 | See <file:Documentation/isdn/README.HiSax> on how to configure it. | 116 | See <file:Documentation/isdn/README.HiSax> on how to configure it. |
@@ -238,7 +238,7 @@ config HISAX_MIC | |||
238 | 238 | ||
239 | config HISAX_NETJET | 239 | config HISAX_NETJET |
240 | bool "NETjet card" | 240 | bool "NETjet card" |
241 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) | 241 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) |
242 | help | 242 | help |
243 | This enables HiSax support for the NetJet from Traverse | 243 | This enables HiSax support for the NetJet from Traverse |
244 | Technologies. | 244 | Technologies. |
@@ -249,7 +249,7 @@ config HISAX_NETJET | |||
249 | 249 | ||
250 | config HISAX_NETJET_U | 250 | config HISAX_NETJET_U |
251 | bool "NETspider U card" | 251 | bool "NETspider U card" |
252 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) | 252 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) |
253 | help | 253 | help |
254 | This enables HiSax support for the Netspider U interface ISDN card | 254 | This enables HiSax support for the Netspider U interface ISDN card |
255 | from Traverse Technologies. | 255 | from Traverse Technologies. |
@@ -317,7 +317,7 @@ config HISAX_GAZEL | |||
317 | 317 | ||
318 | config HISAX_HFC_PCI | 318 | config HISAX_HFC_PCI |
319 | bool "HFC PCI-Bus cards" | 319 | bool "HFC PCI-Bus cards" |
320 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) | 320 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) |
321 | help | 321 | help |
322 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. | 322 | This enables HiSax support for the HFC-S PCI 2BDS0 based cards. |
323 | 323 | ||
@@ -344,7 +344,7 @@ config HISAX_HFC_SX | |||
344 | 344 | ||
345 | config HISAX_ENTERNOW_PCI | 345 | config HISAX_ENTERNOW_PCI |
346 | bool "Formula-n enter:now PCI card" | 346 | bool "Formula-n enter:now PCI card" |
347 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K)) | 347 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) |
348 | help | 348 | help |
349 | This enables HiSax support for the Formula-n enter:now PCI | 349 | This enables HiSax support for the Formula-n enter:now PCI |
350 | ISDN card. | 350 | ISDN card. |
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h index 26c545fa223b..1b85ce166af8 100644 --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h | |||
@@ -396,17 +396,17 @@ struct isar_hw { | |||
396 | 396 | ||
397 | struct hdlc_stat_reg { | 397 | struct hdlc_stat_reg { |
398 | #ifdef __BIG_ENDIAN | 398 | #ifdef __BIG_ENDIAN |
399 | u_char fill __attribute__((packed)); | 399 | u_char fill; |
400 | u_char mode __attribute__((packed)); | 400 | u_char mode; |
401 | u_char xml __attribute__((packed)); | 401 | u_char xml; |
402 | u_char cmd __attribute__((packed)); | 402 | u_char cmd; |
403 | #else | 403 | #else |
404 | u_char cmd __attribute__((packed)); | 404 | u_char cmd; |
405 | u_char xml __attribute__((packed)); | 405 | u_char xml; |
406 | u_char mode __attribute__((packed)); | 406 | u_char mode; |
407 | u_char fill __attribute__((packed)); | 407 | u_char fill; |
408 | #endif | 408 | #endif |
409 | }; | 409 | } __attribute__((packed)); |
410 | 410 | ||
411 | struct hdlc_hw { | 411 | struct hdlc_hw { |
412 | union { | 412 | union { |
diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.h b/drivers/isdn/hisax/hisax_fcpcipnp.h index bd8a22e4d6a2..21fbcedf3a94 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.h +++ b/drivers/isdn/hisax/hisax_fcpcipnp.h | |||
@@ -12,17 +12,17 @@ enum { | |||
12 | 12 | ||
13 | struct hdlc_stat_reg { | 13 | struct hdlc_stat_reg { |
14 | #ifdef __BIG_ENDIAN | 14 | #ifdef __BIG_ENDIAN |
15 | u_char fill __attribute__((packed)); | 15 | u_char fill; |
16 | u_char mode __attribute__((packed)); | 16 | u_char mode; |
17 | u_char xml __attribute__((packed)); | 17 | u_char xml; |
18 | u_char cmd __attribute__((packed)); | 18 | u_char cmd; |
19 | #else | 19 | #else |
20 | u_char cmd __attribute__((packed)); | 20 | u_char cmd; |
21 | u_char xml __attribute__((packed)); | 21 | u_char xml; |
22 | u_char mode __attribute__((packed)); | 22 | u_char mode; |
23 | u_char fill __attribute__((packed)); | 23 | u_char fill; |
24 | #endif | 24 | #endif |
25 | }; | 25 | } __attribute__((packed)); |
26 | 26 | ||
27 | struct fritz_bcs { | 27 | struct fritz_bcs { |
28 | struct hisax_b_if b_if; | 28 | struct hisax_b_if b_if; |
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c index 19f2fcf0ae4a..b4b24335f716 100644 --- a/drivers/isdn/sc/command.c +++ b/drivers/isdn/sc/command.c | |||
@@ -43,7 +43,6 @@ extern int send_and_receive(int, unsigned int, unsigned char, unsigned char, | |||
43 | RspMessage *, int); | 43 | RspMessage *, int); |
44 | extern int sendmessage(int, unsigned int, unsigned int, unsigned int, | 44 | extern int sendmessage(int, unsigned int, unsigned int, unsigned int, |
45 | unsigned int, unsigned int, unsigned int, unsigned int *); | 45 | unsigned int, unsigned int, unsigned int, unsigned int *); |
46 | extern inline void pullphone(char *, char *); | ||
47 | 46 | ||
48 | #ifdef DEBUG | 47 | #ifdef DEBUG |
49 | /* | 48 | /* |
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c index 2c3158c81ff2..4d811600bdab 100644 --- a/drivers/macintosh/windfarm_smu_controls.c +++ b/drivers/macintosh/windfarm_smu_controls.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/wait.h> | 16 | #include <linux/wait.h> |
17 | #include <linux/completion.h> | ||
17 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
18 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
diff --git a/drivers/macintosh/windfarm_smu_sensors.c b/drivers/macintosh/windfarm_smu_sensors.c index b558cc209d49..1a00d9c75a23 100644 --- a/drivers/macintosh/windfarm_smu_sensors.c +++ b/drivers/macintosh/windfarm_smu_sensors.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/wait.h> | 16 | #include <linux/wait.h> |
17 | #include <linux/completion.h> | ||
17 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
18 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 1b76fb29fb70..e423a16ba3c9 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3598,12 +3598,21 @@ static int set_disk_faulty(mddev_t *mddev, dev_t dev) | |||
3598 | return 0; | 3598 | return 0; |
3599 | } | 3599 | } |
3600 | 3600 | ||
3601 | static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
3602 | { | ||
3603 | mddev_t *mddev = bdev->bd_disk->private_data; | ||
3604 | |||
3605 | geo->heads = 2; | ||
3606 | geo->sectors = 4; | ||
3607 | geo->cylinders = get_capacity(mddev->gendisk) / 8; | ||
3608 | return 0; | ||
3609 | } | ||
3610 | |||
3601 | static int md_ioctl(struct inode *inode, struct file *file, | 3611 | static int md_ioctl(struct inode *inode, struct file *file, |
3602 | unsigned int cmd, unsigned long arg) | 3612 | unsigned int cmd, unsigned long arg) |
3603 | { | 3613 | { |
3604 | int err = 0; | 3614 | int err = 0; |
3605 | void __user *argp = (void __user *)arg; | 3615 | void __user *argp = (void __user *)arg; |
3606 | struct hd_geometry __user *loc = argp; | ||
3607 | mddev_t *mddev = NULL; | 3616 | mddev_t *mddev = NULL; |
3608 | 3617 | ||
3609 | if (!capable(CAP_SYS_ADMIN)) | 3618 | if (!capable(CAP_SYS_ADMIN)) |
@@ -3765,24 +3774,6 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
3765 | * 4 sectors (with a BIG number of cylinders...). This drives | 3774 | * 4 sectors (with a BIG number of cylinders...). This drives |
3766 | * dosfs just mad... ;-) | 3775 | * dosfs just mad... ;-) |
3767 | */ | 3776 | */ |
3768 | case HDIO_GETGEO: | ||
3769 | if (!loc) { | ||
3770 | err = -EINVAL; | ||
3771 | goto abort_unlock; | ||
3772 | } | ||
3773 | err = put_user (2, (char __user *) &loc->heads); | ||
3774 | if (err) | ||
3775 | goto abort_unlock; | ||
3776 | err = put_user (4, (char __user *) &loc->sectors); | ||
3777 | if (err) | ||
3778 | goto abort_unlock; | ||
3779 | err = put_user(get_capacity(mddev->gendisk)/8, | ||
3780 | (short __user *) &loc->cylinders); | ||
3781 | if (err) | ||
3782 | goto abort_unlock; | ||
3783 | err = put_user (get_start_sect(inode->i_bdev), | ||
3784 | (long __user *) &loc->start); | ||
3785 | goto done_unlock; | ||
3786 | } | 3777 | } |
3787 | 3778 | ||
3788 | /* | 3779 | /* |
@@ -3911,6 +3902,7 @@ static struct block_device_operations md_fops = | |||
3911 | .open = md_open, | 3902 | .open = md_open, |
3912 | .release = md_release, | 3903 | .release = md_release, |
3913 | .ioctl = md_ioctl, | 3904 | .ioctl = md_ioctl, |
3905 | .getgeo = md_getgeo, | ||
3914 | .media_changed = md_media_changed, | 3906 | .media_changed = md_media_changed, |
3915 | .revalidate_disk= md_revalidate, | 3907 | .revalidate_disk= md_revalidate, |
3916 | }; | 3908 | }; |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index abbca150202b..d03f99cf4b7d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -306,9 +306,6 @@ static int raid0_run (mddev_t *mddev) | |||
306 | printk("raid0 : conf->hash_spacing is %llu blocks.\n", | 306 | printk("raid0 : conf->hash_spacing is %llu blocks.\n", |
307 | (unsigned long long)conf->hash_spacing); | 307 | (unsigned long long)conf->hash_spacing); |
308 | { | 308 | { |
309 | #if __GNUC__ < 3 | ||
310 | volatile | ||
311 | #endif | ||
312 | sector_t s = mddev->array_size; | 309 | sector_t s = mddev->array_size; |
313 | sector_t space = conf->hash_spacing; | 310 | sector_t space = conf->hash_spacing; |
314 | int round; | 311 | int round; |
@@ -439,9 +436,6 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio) | |||
439 | 436 | ||
440 | 437 | ||
441 | { | 438 | { |
442 | #if __GNUC__ < 3 | ||
443 | volatile | ||
444 | #endif | ||
445 | sector_t x = block >> conf->preshift; | 439 | sector_t x = block >> conf->preshift; |
446 | sector_div(x, (u32)conf->hash_spacing); | 440 | sector_div(x, (u32)conf->hash_spacing); |
447 | zone = conf->hash_table[x]; | 441 | zone = conf->hash_table[x]; |
diff --git a/drivers/media/video/v4l2-common.c b/drivers/media/video/v4l2-common.c index 597b8db35a13..62a7d636ef11 100644 --- a/drivers/media/video/v4l2-common.c +++ b/drivers/media/video/v4l2-common.c | |||
@@ -191,9 +191,7 @@ char *v4l2_type_names[] = { | |||
191 | }; | 191 | }; |
192 | 192 | ||
193 | char *v4l2_ioctl_names[256] = { | 193 | char *v4l2_ioctl_names[256] = { |
194 | #if __GNUC__ >= 3 | ||
195 | [0 ... 255] = "UNKNOWN", | 194 | [0 ... 255] = "UNKNOWN", |
196 | #endif | ||
197 | [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", | 195 | [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", |
198 | [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", | 196 | [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", |
199 | [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", | 197 | [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", |
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 5b1febed3133..b09fb6307153 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c | |||
@@ -662,6 +662,13 @@ static int i2o_block_release(struct inode *inode, struct file *file) | |||
662 | return 0; | 662 | return 0; |
663 | } | 663 | } |
664 | 664 | ||
665 | static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
666 | { | ||
667 | i2o_block_biosparam(get_capacity(bdev->bd_disk), | ||
668 | &geo->cylinders, &geo->heads, &geo->sectors); | ||
669 | return 0; | ||
670 | } | ||
671 | |||
665 | /** | 672 | /** |
666 | * i2o_block_ioctl - Issue device specific ioctl calls. | 673 | * i2o_block_ioctl - Issue device specific ioctl calls. |
667 | * @cmd: ioctl command | 674 | * @cmd: ioctl command |
@@ -676,7 +683,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, | |||
676 | { | 683 | { |
677 | struct gendisk *disk = inode->i_bdev->bd_disk; | 684 | struct gendisk *disk = inode->i_bdev->bd_disk; |
678 | struct i2o_block_device *dev = disk->private_data; | 685 | struct i2o_block_device *dev = disk->private_data; |
679 | void __user *argp = (void __user *)arg; | ||
680 | 686 | ||
681 | /* Anyone capable of this syscall can do *real bad* things */ | 687 | /* Anyone capable of this syscall can do *real bad* things */ |
682 | 688 | ||
@@ -684,15 +690,6 @@ static int i2o_block_ioctl(struct inode *inode, struct file *file, | |||
684 | return -EPERM; | 690 | return -EPERM; |
685 | 691 | ||
686 | switch (cmd) { | 692 | switch (cmd) { |
687 | case HDIO_GETGEO: | ||
688 | { | ||
689 | struct hd_geometry g; | ||
690 | i2o_block_biosparam(get_capacity(disk), | ||
691 | &g.cylinders, &g.heads, &g.sectors); | ||
692 | g.start = get_start_sect(inode->i_bdev); | ||
693 | return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0; | ||
694 | } | ||
695 | |||
696 | case BLKI2OGRSTRAT: | 693 | case BLKI2OGRSTRAT: |
697 | return put_user(dev->rcache, (int __user *)arg); | 694 | return put_user(dev->rcache, (int __user *)arg); |
698 | case BLKI2OGWSTRAT: | 695 | case BLKI2OGWSTRAT: |
@@ -962,6 +959,7 @@ static struct block_device_operations i2o_block_fops = { | |||
962 | .open = i2o_block_open, | 959 | .open = i2o_block_open, |
963 | .release = i2o_block_release, | 960 | .release = i2o_block_release, |
964 | .ioctl = i2o_block_ioctl, | 961 | .ioctl = i2o_block_ioctl, |
962 | .getgeo = i2o_block_getgeo, | ||
965 | .media_changed = i2o_block_media_changed | 963 | .media_changed = i2o_block_media_changed |
966 | }; | 964 | }; |
967 | 965 | ||
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index e335d54c4659..b42e0fbab59b 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c | |||
@@ -27,7 +27,6 @@ | |||
27 | 27 | ||
28 | #include <asm/dma.h> | 28 | #include <asm/dma.h> |
29 | #include <asm/hardware.h> | 29 | #include <asm/hardware.h> |
30 | #include <asm/irq.h> | ||
31 | 30 | ||
32 | #include "ucb1x00.h" | 31 | #include "ucb1x00.h" |
33 | 32 | ||
@@ -507,14 +506,14 @@ static int ucb1x00_probe(struct mcp *mcp) | |||
507 | goto err_free; | 506 | goto err_free; |
508 | } | 507 | } |
509 | 508 | ||
510 | ret = request_irq(ucb->irq, ucb1x00_irq, 0, "UCB1x00", ucb); | 509 | ret = request_irq(ucb->irq, ucb1x00_irq, SA_TRIGGER_RISING, |
510 | "UCB1x00", ucb); | ||
511 | if (ret) { | 511 | if (ret) { |
512 | printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", | 512 | printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n", |
513 | ucb->irq, ret); | 513 | ucb->irq, ret); |
514 | goto err_free; | 514 | goto err_free; |
515 | } | 515 | } |
516 | 516 | ||
517 | set_irq_type(ucb->irq, IRQT_RISING); | ||
518 | mcp_set_drvdata(mcp, ucb); | 517 | mcp_set_drvdata(mcp, ucb); |
519 | 518 | ||
520 | ret = class_device_register(&ucb->cdev); | 519 | ret = class_device_register(&ucb->cdev); |
diff --git a/drivers/mfd/ucb1x00-ts.c b/drivers/mfd/ucb1x00-ts.c index 551061c2eadf..79fd062ccb34 100644 --- a/drivers/mfd/ucb1x00-ts.c +++ b/drivers/mfd/ucb1x00-ts.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include <linux/suspend.h> | 32 | #include <linux/suspend.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/kthread.h> | 34 | #include <linux/kthread.h> |
35 | #include <linux/delay.h> | ||
36 | 35 | ||
37 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
38 | #include <asm/semaphore.h> | 37 | #include <asm/semaphore.h> |
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 198561d21710..d5f28981596b 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -113,31 +113,18 @@ static int mmc_blk_release(struct inode *inode, struct file *filp) | |||
113 | } | 113 | } |
114 | 114 | ||
115 | static int | 115 | static int |
116 | mmc_blk_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) | 116 | mmc_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
117 | { | 117 | { |
118 | struct block_device *bdev = inode->i_bdev; | 118 | geo->cylinders = get_capacity(bdev->bd_disk) / (4 * 16); |
119 | 119 | geo->heads = 4; | |
120 | if (cmd == HDIO_GETGEO) { | 120 | geo->sectors = 16; |
121 | struct hd_geometry geo; | 121 | return 0; |
122 | |||
123 | memset(&geo, 0, sizeof(struct hd_geometry)); | ||
124 | |||
125 | geo.cylinders = get_capacity(bdev->bd_disk) / (4 * 16); | ||
126 | geo.heads = 4; | ||
127 | geo.sectors = 16; | ||
128 | geo.start = get_start_sect(bdev); | ||
129 | |||
130 | return copy_to_user((void __user *)arg, &geo, sizeof(geo)) | ||
131 | ? -EFAULT : 0; | ||
132 | } | ||
133 | |||
134 | return -ENOTTY; | ||
135 | } | 122 | } |
136 | 123 | ||
137 | static struct block_device_operations mmc_bdops = { | 124 | static struct block_device_operations mmc_bdops = { |
138 | .open = mmc_blk_open, | 125 | .open = mmc_blk_open, |
139 | .release = mmc_blk_release, | 126 | .release = mmc_blk_release, |
140 | .ioctl = mmc_blk_ioctl, | 127 | .getgeo = mmc_blk_getgeo, |
141 | .owner = THIS_MODULE, | 128 | .owner = THIS_MODULE, |
142 | }; | 129 | }; |
143 | 130 | ||
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 339cb1218eaa..7f3ff500b68e 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -194,6 +194,14 @@ static int blktrans_release(struct inode *i, struct file *f) | |||
194 | return ret; | 194 | return ret; |
195 | } | 195 | } |
196 | 196 | ||
197 | static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
198 | { | ||
199 | struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; | ||
200 | |||
201 | if (dev->tr->getgeo) | ||
202 | return dev->tr->getgeo(dev, geo); | ||
203 | return -ENOTTY; | ||
204 | } | ||
197 | 205 | ||
198 | static int blktrans_ioctl(struct inode *inode, struct file *file, | 206 | static int blktrans_ioctl(struct inode *inode, struct file *file, |
199 | unsigned int cmd, unsigned long arg) | 207 | unsigned int cmd, unsigned long arg) |
@@ -207,22 +215,6 @@ static int blktrans_ioctl(struct inode *inode, struct file *file, | |||
207 | return tr->flush(dev); | 215 | return tr->flush(dev); |
208 | /* The core code did the work, we had nothing to do. */ | 216 | /* The core code did the work, we had nothing to do. */ |
209 | return 0; | 217 | return 0; |
210 | |||
211 | case HDIO_GETGEO: | ||
212 | if (tr->getgeo) { | ||
213 | struct hd_geometry g; | ||
214 | int ret; | ||
215 | |||
216 | memset(&g, 0, sizeof(g)); | ||
217 | ret = tr->getgeo(dev, &g); | ||
218 | if (ret) | ||
219 | return ret; | ||
220 | |||
221 | g.start = get_start_sect(inode->i_bdev); | ||
222 | if (copy_to_user((void __user *)arg, &g, sizeof(g))) | ||
223 | return -EFAULT; | ||
224 | return 0; | ||
225 | } /* else */ | ||
226 | default: | 218 | default: |
227 | return -ENOTTY; | 219 | return -ENOTTY; |
228 | } | 220 | } |
@@ -233,6 +225,7 @@ struct block_device_operations mtd_blktrans_ops = { | |||
233 | .open = blktrans_open, | 225 | .open = blktrans_open, |
234 | .release = blktrans_release, | 226 | .release = blktrans_release, |
235 | .ioctl = blktrans_ioctl, | 227 | .ioctl = blktrans_ioctl, |
228 | .getgeo = blktrans_getgeo, | ||
236 | }; | 229 | }; |
237 | 230 | ||
238 | int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | 231 | int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) |
diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 45c077d0f063..af06a80f44de 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/slab.h> | ||
17 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
18 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
19 | #include <linux/mtd/onenand.h> | 20 | #include <linux/mtd/onenand.h> |
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 20ce212638fc..a3e00a4635a5 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/mtd/blktrans.h> | 18 | #include <linux/mtd/blktrans.h> |
19 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/slab.h> | ||
21 | #include <linux/jiffies.h> | 22 | #include <linux/jiffies.h> |
22 | 23 | ||
23 | #include <asm/types.h> | 24 | #include <asm/types.h> |
diff --git a/drivers/net/3c527.h b/drivers/net/3c527.h index c10f009ce9b6..53b5b071df08 100644 --- a/drivers/net/3c527.h +++ b/drivers/net/3c527.h | |||
@@ -32,43 +32,43 @@ | |||
32 | 32 | ||
33 | struct mc32_mailbox | 33 | struct mc32_mailbox |
34 | { | 34 | { |
35 | u16 mbox __attribute((packed)); | 35 | u16 mbox; |
36 | u16 data[1] __attribute((packed)); | 36 | u16 data[1]; |
37 | }; | 37 | } __attribute((packed)); |
38 | 38 | ||
39 | struct skb_header | 39 | struct skb_header |
40 | { | 40 | { |
41 | u8 status __attribute((packed)); | 41 | u8 status; |
42 | u8 control __attribute((packed)); | 42 | u8 control; |
43 | u16 next __attribute((packed)); /* Do not change! */ | 43 | u16 next; /* Do not change! */ |
44 | u16 length __attribute((packed)); | 44 | u16 length; |
45 | u32 data __attribute((packed)); | 45 | u32 data; |
46 | }; | 46 | } __attribute((packed)); |
47 | 47 | ||
48 | struct mc32_stats | 48 | struct mc32_stats |
49 | { | 49 | { |
50 | /* RX Errors */ | 50 | /* RX Errors */ |
51 | u32 rx_crc_errors __attribute((packed)); | 51 | u32 rx_crc_errors; |
52 | u32 rx_alignment_errors __attribute((packed)); | 52 | u32 rx_alignment_errors; |
53 | u32 rx_overrun_errors __attribute((packed)); | 53 | u32 rx_overrun_errors; |
54 | u32 rx_tooshort_errors __attribute((packed)); | 54 | u32 rx_tooshort_errors; |
55 | u32 rx_toolong_errors __attribute((packed)); | 55 | u32 rx_toolong_errors; |
56 | u32 rx_outofresource_errors __attribute((packed)); | 56 | u32 rx_outofresource_errors; |
57 | 57 | ||
58 | u32 rx_discarded __attribute((packed)); /* via card pattern match filter */ | 58 | u32 rx_discarded; /* via card pattern match filter */ |
59 | 59 | ||
60 | /* TX Errors */ | 60 | /* TX Errors */ |
61 | u32 tx_max_collisions __attribute((packed)); | 61 | u32 tx_max_collisions; |
62 | u32 tx_carrier_errors __attribute((packed)); | 62 | u32 tx_carrier_errors; |
63 | u32 tx_underrun_errors __attribute((packed)); | 63 | u32 tx_underrun_errors; |
64 | u32 tx_cts_errors __attribute((packed)); | 64 | u32 tx_cts_errors; |
65 | u32 tx_timeout_errors __attribute((packed)) ; | 65 | u32 tx_timeout_errors; |
66 | 66 | ||
67 | /* various cruft */ | 67 | /* various cruft */ |
68 | u32 dataA[6] __attribute((packed)); | 68 | u32 dataA[6]; |
69 | u16 dataB[5] __attribute((packed)); | 69 | u16 dataB[5]; |
70 | u32 dataC[14] __attribute((packed)); | 70 | u32 dataC[14]; |
71 | }; | 71 | } __attribute((packed)); |
72 | 72 | ||
73 | #define STATUS_MASK 0x0F | 73 | #define STATUS_MASK 0x0F |
74 | #define COMPLETED (1<<7) | 74 | #define COMPLETED (1<<7) |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e2fa29b612cd..1960961bf28e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1374,7 +1374,7 @@ config FORCEDETH | |||
1374 | 1374 | ||
1375 | config CS89x0 | 1375 | config CS89x0 |
1376 | tristate "CS89x0 support" | 1376 | tristate "CS89x0 support" |
1377 | depends on (NET_PCI && (ISA || ARCH_IXDP2X01)) || ARCH_PNX0105 | 1377 | depends on NET_PCI && (ISA || ARCH_IXDP2X01 || ARCH_PNX010X) |
1378 | ---help--- | 1378 | ---help--- |
1379 | Support for CS89x0 chipset based Ethernet cards. If you have a | 1379 | Support for CS89x0 chipset based Ethernet cards. If you have a |
1380 | network (Ethernet) card of this type, say Y and read the | 1380 | network (Ethernet) card of this type, say Y and read the |
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index a6078ad9b654..907c01009746 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c | |||
@@ -175,7 +175,7 @@ static unsigned int cs8900_irq_map[] = {1,0,0,0}; | |||
175 | #include <asm/irq.h> | 175 | #include <asm/irq.h> |
176 | static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; | 176 | static unsigned int netcard_portlist[] __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0}; |
177 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; | 177 | static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0}; |
178 | #elif defined(CONFIG_ARCH_PNX0105) | 178 | #elif defined(CONFIG_ARCH_PNX010X) |
179 | #include <asm/irq.h> | 179 | #include <asm/irq.h> |
180 | #include <asm/arch/gpio.h> | 180 | #include <asm/arch/gpio.h> |
181 | #define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ | 181 | #define CIRRUS_DEFAULT_BASE IO_ADDRESS(EXT_STATIC2_s0_BASE + 0x200000) /* = Physical address 0x48200000 */ |
@@ -338,30 +338,86 @@ out: | |||
338 | } | 338 | } |
339 | #endif | 339 | #endif |
340 | 340 | ||
341 | #if defined(CONFIG_ARCH_IXDP2X01) | ||
341 | static int | 342 | static int |
342 | readreg(struct net_device *dev, int portno) | 343 | readword(unsigned long base_addr, int portno) |
343 | { | 344 | { |
344 | outw(portno, dev->base_addr + ADD_PORT); | 345 | return (u16)__raw_readl(base_addr + (portno << 1)); |
345 | return inw(dev->base_addr + DATA_PORT); | ||
346 | } | 346 | } |
347 | 347 | ||
348 | static void | 348 | static void |
349 | writereg(struct net_device *dev, int portno, int value) | 349 | writeword(unsigned long base_addr, int portno, int value) |
350 | { | 350 | { |
351 | outw(portno, dev->base_addr + ADD_PORT); | 351 | __raw_writel((u16)value, base_addr + (portno << 1)); |
352 | outw(value, dev->base_addr + DATA_PORT); | 352 | } |
353 | #else | ||
354 | #if defined(CONFIG_ARCH_PNX010X) | ||
355 | static int | ||
356 | readword(unsigned long base_addr, int portno) | ||
357 | { | ||
358 | return inw(base_addr + (portno << 1)); | ||
359 | } | ||
360 | |||
361 | static void | ||
362 | writeword(unsigned long base_addr, int portno, int value) | ||
363 | { | ||
364 | outw(value, base_addr + (portno << 1)); | ||
365 | } | ||
366 | #else | ||
367 | static int | ||
368 | readword(unsigned long base_addr, int portno) | ||
369 | { | ||
370 | return inw(base_addr + portno); | ||
371 | } | ||
372 | |||
373 | static void | ||
374 | writeword(unsigned long base_addr, int portno, int value) | ||
375 | { | ||
376 | outw(value, base_addr + portno); | ||
377 | } | ||
378 | #endif | ||
379 | #endif | ||
380 | |||
381 | static void | ||
382 | readwords(unsigned long base_addr, int portno, void *buf, int length) | ||
383 | { | ||
384 | u8 *buf8 = (u8 *)buf; | ||
385 | |||
386 | do { | ||
387 | u32 tmp32; | ||
388 | |||
389 | tmp32 = readword(base_addr, portno); | ||
390 | *buf8++ = (u8)tmp32; | ||
391 | *buf8++ = (u8)(tmp32 >> 8); | ||
392 | } while (--length); | ||
393 | } | ||
394 | |||
395 | static void | ||
396 | writewords(unsigned long base_addr, int portno, void *buf, int length) | ||
397 | { | ||
398 | u8 *buf8 = (u8 *)buf; | ||
399 | |||
400 | do { | ||
401 | u32 tmp32; | ||
402 | |||
403 | tmp32 = *buf8++; | ||
404 | tmp32 |= (*buf8++) << 8; | ||
405 | writeword(base_addr, portno, tmp32); | ||
406 | } while (--length); | ||
353 | } | 407 | } |
354 | 408 | ||
355 | static int | 409 | static int |
356 | readword(struct net_device *dev, int portno) | 410 | readreg(struct net_device *dev, int regno) |
357 | { | 411 | { |
358 | return inw(dev->base_addr + portno); | 412 | writeword(dev->base_addr, ADD_PORT, regno); |
413 | return readword(dev->base_addr, DATA_PORT); | ||
359 | } | 414 | } |
360 | 415 | ||
361 | static void | 416 | static void |
362 | writeword(struct net_device *dev, int portno, int value) | 417 | writereg(struct net_device *dev, int regno, int value) |
363 | { | 418 | { |
364 | outw(value, dev->base_addr + portno); | 419 | writeword(dev->base_addr, ADD_PORT, regno); |
420 | writeword(dev->base_addr, DATA_PORT, value); | ||
365 | } | 421 | } |
366 | 422 | ||
367 | static int __init | 423 | static int __init |
@@ -456,7 +512,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
456 | #endif | 512 | #endif |
457 | } | 513 | } |
458 | 514 | ||
459 | #ifdef CONFIG_ARCH_PNX0105 | 515 | #ifdef CONFIG_ARCH_PNX010X |
460 | initialize_ebi(); | 516 | initialize_ebi(); |
461 | 517 | ||
462 | /* Map GPIO registers for the pins connected to the CS8900a. */ | 518 | /* Map GPIO registers for the pins connected to the CS8900a. */ |
@@ -491,8 +547,8 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
491 | 547 | ||
492 | #ifdef CONFIG_SH_HICOSH4 | 548 | #ifdef CONFIG_SH_HICOSH4 |
493 | /* truely reset the chip */ | 549 | /* truely reset the chip */ |
494 | outw(0x0114, ioaddr + ADD_PORT); | 550 | writeword(ioaddr, ADD_PORT, 0x0114); |
495 | outw(0x0040, ioaddr + DATA_PORT); | 551 | writeword(ioaddr, DATA_PORT, 0x0040); |
496 | #endif | 552 | #endif |
497 | 553 | ||
498 | /* if they give us an odd I/O address, then do ONE write to | 554 | /* if they give us an odd I/O address, then do ONE write to |
@@ -503,24 +559,24 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
503 | if (net_debug > 1) | 559 | if (net_debug > 1) |
504 | printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr); | 560 | printk(KERN_INFO "%s: odd ioaddr 0x%x\n", dev->name, ioaddr); |
505 | if ((ioaddr & 2) != 2) | 561 | if ((ioaddr & 2) != 2) |
506 | if ((inw((ioaddr & ~3)+ ADD_PORT) & ADD_MASK) != ADD_SIG) { | 562 | if ((readword(ioaddr & ~3, ADD_PORT) & ADD_MASK) != ADD_SIG) { |
507 | printk(KERN_ERR "%s: bad signature 0x%x\n", | 563 | printk(KERN_ERR "%s: bad signature 0x%x\n", |
508 | dev->name, inw((ioaddr & ~3)+ ADD_PORT)); | 564 | dev->name, readword(ioaddr & ~3, ADD_PORT)); |
509 | retval = -ENODEV; | 565 | retval = -ENODEV; |
510 | goto out2; | 566 | goto out2; |
511 | } | 567 | } |
512 | } | 568 | } |
513 | printk(KERN_DEBUG "PP_addr at %x: 0x%x\n", | 569 | printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", |
514 | ioaddr + ADD_PORT, inw(ioaddr + ADD_PORT)); | 570 | ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); |
515 | 571 | ||
516 | ioaddr &= ~3; | 572 | ioaddr &= ~3; |
517 | outw(PP_ChipID, ioaddr + ADD_PORT); | 573 | writeword(ioaddr, ADD_PORT, PP_ChipID); |
518 | 574 | ||
519 | tmp = inw(ioaddr + DATA_PORT); | 575 | tmp = readword(ioaddr, DATA_PORT); |
520 | if (tmp != CHIP_EISA_ID_SIG) { | 576 | if (tmp != CHIP_EISA_ID_SIG) { |
521 | printk(KERN_DEBUG "%s: incorrect signature at %x: 0x%x!=" | 577 | printk(KERN_DEBUG "%s: incorrect signature at %x[%x]: 0x%x!=" |
522 | CHIP_EISA_ID_SIG_STR "\n", | 578 | CHIP_EISA_ID_SIG_STR "\n", |
523 | dev->name, ioaddr + DATA_PORT, tmp); | 579 | dev->name, ioaddr, DATA_PORT, tmp); |
524 | retval = -ENODEV; | 580 | retval = -ENODEV; |
525 | goto out2; | 581 | goto out2; |
526 | } | 582 | } |
@@ -724,7 +780,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
724 | } else { | 780 | } else { |
725 | i = lp->isa_config & INT_NO_MASK; | 781 | i = lp->isa_config & INT_NO_MASK; |
726 | if (lp->chip_type == CS8900) { | 782 | if (lp->chip_type == CS8900) { |
727 | #if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) | 783 | #if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX010X) |
728 | i = cs8900_irq_map[0]; | 784 | i = cs8900_irq_map[0]; |
729 | #else | 785 | #else |
730 | /* Translate the IRQ using the IRQ mapping table. */ | 786 | /* Translate the IRQ using the IRQ mapping table. */ |
@@ -790,7 +846,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) | |||
790 | goto out3; | 846 | goto out3; |
791 | return 0; | 847 | return 0; |
792 | out3: | 848 | out3: |
793 | outw(PP_ChipID, dev->base_addr + ADD_PORT); | 849 | writeword(dev->base_addr, ADD_PORT, PP_ChipID); |
794 | out2: | 850 | out2: |
795 | release_region(ioaddr & ~3, NETCARD_IO_EXTENT); | 851 | release_region(ioaddr & ~3, NETCARD_IO_EXTENT); |
796 | out1: | 852 | out1: |
@@ -970,11 +1026,11 @@ void __init reset_chip(struct net_device *dev) | |||
970 | #ifndef CONFIG_ARCH_IXDP2X01 | 1026 | #ifndef CONFIG_ARCH_IXDP2X01 |
971 | if (lp->chip_type != CS8900) { | 1027 | if (lp->chip_type != CS8900) { |
972 | /* Hardware problem requires PNP registers to be reconfigured after a reset */ | 1028 | /* Hardware problem requires PNP registers to be reconfigured after a reset */ |
973 | outw(PP_CS8920_ISAINT, ioaddr + ADD_PORT); | 1029 | writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT); |
974 | outb(dev->irq, ioaddr + DATA_PORT); | 1030 | outb(dev->irq, ioaddr + DATA_PORT); |
975 | outb(0, ioaddr + DATA_PORT + 1); | 1031 | outb(0, ioaddr + DATA_PORT + 1); |
976 | 1032 | ||
977 | outw(PP_CS8920_ISAMemB, ioaddr + ADD_PORT); | 1033 | writeword(ioaddr, ADD_PORT, PP_CS8920_ISAMemB); |
978 | outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT); | 1034 | outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT); |
979 | outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1); | 1035 | outb((dev->mem_start >> 8) & 0xff, ioaddr + DATA_PORT + 1); |
980 | } | 1036 | } |
@@ -1104,8 +1160,8 @@ send_test_pkt(struct net_device *dev) | |||
1104 | memcpy(test_packet, dev->dev_addr, ETH_ALEN); | 1160 | memcpy(test_packet, dev->dev_addr, ETH_ALEN); |
1105 | memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN); | 1161 | memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN); |
1106 | 1162 | ||
1107 | writeword(dev, TX_CMD_PORT, TX_AFTER_ALL); | 1163 | writeword(dev->base_addr, TX_CMD_PORT, TX_AFTER_ALL); |
1108 | writeword(dev, TX_LEN_PORT, ETH_ZLEN); | 1164 | writeword(dev->base_addr, TX_LEN_PORT, ETH_ZLEN); |
1109 | 1165 | ||
1110 | /* Test to see if the chip has allocated memory for the packet */ | 1166 | /* Test to see if the chip has allocated memory for the packet */ |
1111 | while (jiffies - timenow < 5) | 1167 | while (jiffies - timenow < 5) |
@@ -1115,7 +1171,7 @@ send_test_pkt(struct net_device *dev) | |||
1115 | return 0; /* this shouldn't happen */ | 1171 | return 0; /* this shouldn't happen */ |
1116 | 1172 | ||
1117 | /* Write the contents of the packet */ | 1173 | /* Write the contents of the packet */ |
1118 | outsw(dev->base_addr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); | 1174 | writewords(dev->base_addr, TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1); |
1119 | 1175 | ||
1120 | if (net_debug > 1) printk("Sending test packet "); | 1176 | if (net_debug > 1) printk("Sending test packet "); |
1121 | /* wait a couple of jiffies for packet to be received */ | 1177 | /* wait a couple of jiffies for packet to be received */ |
@@ -1200,7 +1256,7 @@ net_open(struct net_device *dev) | |||
1200 | int i; | 1256 | int i; |
1201 | int ret; | 1257 | int ret; |
1202 | 1258 | ||
1203 | #if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX0105) /* uses irq#1, so this won't work */ | 1259 | #if !defined(CONFIG_SH_HICOSH4) && !defined(CONFIG_ARCH_PNX010X) /* uses irq#1, so this won't work */ |
1204 | if (dev->irq < 2) { | 1260 | if (dev->irq < 2) { |
1205 | /* Allow interrupts to be generated by the chip */ | 1261 | /* Allow interrupts to be generated by the chip */ |
1206 | /* Cirrus' release had this: */ | 1262 | /* Cirrus' release had this: */ |
@@ -1231,7 +1287,7 @@ net_open(struct net_device *dev) | |||
1231 | else | 1287 | else |
1232 | #endif | 1288 | #endif |
1233 | { | 1289 | { |
1234 | #if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX0105) | 1290 | #if !defined(CONFIG_ARCH_IXDP2X01) && !defined(CONFIG_ARCH_PNX010X) |
1235 | if (((1 << dev->irq) & lp->irq_map) == 0) { | 1291 | if (((1 << dev->irq) & lp->irq_map) == 0) { |
1236 | printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", | 1292 | printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n", |
1237 | dev->name, dev->irq, lp->irq_map); | 1293 | dev->name, dev->irq, lp->irq_map); |
@@ -1316,7 +1372,7 @@ net_open(struct net_device *dev) | |||
1316 | case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; | 1372 | case A_CNF_MEDIA_10B_2: result = lp->adapter_cnf & A_CNF_10B_2; break; |
1317 | default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); | 1373 | default: result = lp->adapter_cnf & (A_CNF_10B_T | A_CNF_AUI | A_CNF_10B_2); |
1318 | } | 1374 | } |
1319 | #ifdef CONFIG_ARCH_PNX0105 | 1375 | #ifdef CONFIG_ARCH_PNX010X |
1320 | result = A_CNF_10B_T; | 1376 | result = A_CNF_10B_T; |
1321 | #endif | 1377 | #endif |
1322 | if (!result) { | 1378 | if (!result) { |
@@ -1457,8 +1513,8 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) | |||
1457 | netif_stop_queue(dev); | 1513 | netif_stop_queue(dev); |
1458 | 1514 | ||
1459 | /* initiate a transmit sequence */ | 1515 | /* initiate a transmit sequence */ |
1460 | writeword(dev, TX_CMD_PORT, lp->send_cmd); | 1516 | writeword(dev->base_addr, TX_CMD_PORT, lp->send_cmd); |
1461 | writeword(dev, TX_LEN_PORT, skb->len); | 1517 | writeword(dev->base_addr, TX_LEN_PORT, skb->len); |
1462 | 1518 | ||
1463 | /* Test to see if the chip has allocated memory for the packet */ | 1519 | /* Test to see if the chip has allocated memory for the packet */ |
1464 | if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { | 1520 | if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) { |
@@ -1472,7 +1528,7 @@ static int net_send_packet(struct sk_buff *skb, struct net_device *dev) | |||
1472 | return 1; | 1528 | return 1; |
1473 | } | 1529 | } |
1474 | /* Write the contents of the packet */ | 1530 | /* Write the contents of the packet */ |
1475 | outsw(dev->base_addr + TX_FRAME_PORT,skb->data,(skb->len+1) >>1); | 1531 | writewords(dev->base_addr, TX_FRAME_PORT,skb->data,(skb->len+1) >>1); |
1476 | spin_unlock_irq(&lp->lock); | 1532 | spin_unlock_irq(&lp->lock); |
1477 | lp->stats.tx_bytes += skb->len; | 1533 | lp->stats.tx_bytes += skb->len; |
1478 | dev->trans_start = jiffies; | 1534 | dev->trans_start = jiffies; |
@@ -1512,7 +1568,7 @@ static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
1512 | course, if you're on a slow machine, and packets are arriving | 1568 | course, if you're on a slow machine, and packets are arriving |
1513 | faster than you can read them off, you're screwed. Hasta la | 1569 | faster than you can read them off, you're screwed. Hasta la |
1514 | vista, baby! */ | 1570 | vista, baby! */ |
1515 | while ((status = readword(dev, ISQ_PORT))) { | 1571 | while ((status = readword(dev->base_addr, ISQ_PORT))) { |
1516 | if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status); | 1572 | if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status); |
1517 | handled = 1; | 1573 | handled = 1; |
1518 | switch(status & ISQ_EVENT_MASK) { | 1574 | switch(status & ISQ_EVENT_MASK) { |
@@ -1606,8 +1662,8 @@ net_rx(struct net_device *dev) | |||
1606 | int status, length; | 1662 | int status, length; |
1607 | 1663 | ||
1608 | int ioaddr = dev->base_addr; | 1664 | int ioaddr = dev->base_addr; |
1609 | status = inw(ioaddr + RX_FRAME_PORT); | 1665 | status = readword(ioaddr, RX_FRAME_PORT); |
1610 | length = inw(ioaddr + RX_FRAME_PORT); | 1666 | length = readword(ioaddr, RX_FRAME_PORT); |
1611 | 1667 | ||
1612 | if ((status & RX_OK) == 0) { | 1668 | if ((status & RX_OK) == 0) { |
1613 | count_rx_errors(status, lp); | 1669 | count_rx_errors(status, lp); |
@@ -1626,9 +1682,9 @@ net_rx(struct net_device *dev) | |||
1626 | skb_reserve(skb, 2); /* longword align L3 header */ | 1682 | skb_reserve(skb, 2); /* longword align L3 header */ |
1627 | skb->dev = dev; | 1683 | skb->dev = dev; |
1628 | 1684 | ||
1629 | insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1); | 1685 | readwords(ioaddr, RX_FRAME_PORT, skb_put(skb, length), length >> 1); |
1630 | if (length & 1) | 1686 | if (length & 1) |
1631 | skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT); | 1687 | skb->data[length-1] = readword(ioaddr, RX_FRAME_PORT); |
1632 | 1688 | ||
1633 | if (net_debug > 3) { | 1689 | if (net_debug > 3) { |
1634 | printk( "%s: received %d byte packet of type %x\n", | 1690 | printk( "%s: received %d byte packet of type %x\n", |
@@ -1901,7 +1957,7 @@ void | |||
1901 | cleanup_module(void) | 1957 | cleanup_module(void) |
1902 | { | 1958 | { |
1903 | unregister_netdev(dev_cs89x0); | 1959 | unregister_netdev(dev_cs89x0); |
1904 | outw(PP_ChipID, dev_cs89x0->base_addr + ADD_PORT); | 1960 | writeword(dev_cs89x0->base_addr, ADD_PORT, PP_ChipID); |
1905 | release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT); | 1961 | release_region(dev_cs89x0->base_addr, NETCARD_IO_EXTENT); |
1906 | free_netdev(dev_cs89x0); | 1962 | free_netdev(dev_cs89x0); |
1907 | } | 1963 | } |
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h index decea264f121..bd954aaa636f 100644 --- a/drivers/net/cs89x0.h +++ b/drivers/net/cs89x0.h | |||
@@ -16,13 +16,6 @@ | |||
16 | 16 | ||
17 | #include <linux/config.h> | 17 | #include <linux/config.h> |
18 | 18 | ||
19 | #if defined(CONFIG_ARCH_IXDP2X01) || defined(CONFIG_ARCH_PNX0105) | ||
20 | /* IXDP2401/IXDP2801 uses dword-aligned register addressing */ | ||
21 | #define CS89x0_PORT(reg) ((reg) * 2) | ||
22 | #else | ||
23 | #define CS89x0_PORT(reg) (reg) | ||
24 | #endif | ||
25 | |||
26 | #define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */ | 19 | #define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */ |
27 | /* offset 2h -> Model/Product Number */ | 20 | /* offset 2h -> Model/Product Number */ |
28 | /* offset 3h -> Chip Revision Number */ | 21 | /* offset 3h -> Chip Revision Number */ |
@@ -332,16 +325,16 @@ | |||
332 | #define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */ | 325 | #define RAM_SIZE 0x1000 /* The card has 4k bytes or RAM */ |
333 | #define PKT_START PP_TxFrame /* Start of packet RAM */ | 326 | #define PKT_START PP_TxFrame /* Start of packet RAM */ |
334 | 327 | ||
335 | #define RX_FRAME_PORT CS89x0_PORT(0x0000) | 328 | #define RX_FRAME_PORT 0x0000 |
336 | #define TX_FRAME_PORT RX_FRAME_PORT | 329 | #define TX_FRAME_PORT RX_FRAME_PORT |
337 | #define TX_CMD_PORT CS89x0_PORT(0x0004) | 330 | #define TX_CMD_PORT 0x0004 |
338 | #define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */ | 331 | #define TX_NOW 0x0000 /* Tx packet after 5 bytes copied */ |
339 | #define TX_AFTER_381 0x0040 /* Tx packet after 381 bytes copied */ | 332 | #define TX_AFTER_381 0x0040 /* Tx packet after 381 bytes copied */ |
340 | #define TX_AFTER_ALL 0x00c0 /* Tx packet after all bytes copied */ | 333 | #define TX_AFTER_ALL 0x00c0 /* Tx packet after all bytes copied */ |
341 | #define TX_LEN_PORT CS89x0_PORT(0x0006) | 334 | #define TX_LEN_PORT 0x0006 |
342 | #define ISQ_PORT CS89x0_PORT(0x0008) | 335 | #define ISQ_PORT 0x0008 |
343 | #define ADD_PORT CS89x0_PORT(0x000A) | 336 | #define ADD_PORT 0x000A |
344 | #define DATA_PORT CS89x0_PORT(0x000C) | 337 | #define DATA_PORT 0x000C |
345 | 338 | ||
346 | #define EEPROM_WRITE_EN 0x00F0 | 339 | #define EEPROM_WRITE_EN 0x00F0 |
347 | #define EEPROM_WRITE_DIS 0x0000 | 340 | #define EEPROM_WRITE_DIS 0x0000 |
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 3e9accf137e7..41b3d83c2ab8 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c | |||
@@ -524,6 +524,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) | |||
524 | ax->dev->trans_start = jiffies; | 524 | ax->dev->trans_start = jiffies; |
525 | ax->xleft = count - actual; | 525 | ax->xleft = count - actual; |
526 | ax->xhead = ax->xbuff + actual; | 526 | ax->xhead = ax->xbuff + actual; |
527 | spin_unlock_bh(&ax->buflock); | ||
527 | } | 528 | } |
528 | 529 | ||
529 | /* Encapsulate an AX.25 packet and kick it into a TTY queue. */ | 530 | /* Encapsulate an AX.25 packet and kick it into a TTY queue. */ |
diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h index 741aecc655df..a82a4ba8de4f 100644 --- a/drivers/net/irda/vlsi_ir.h +++ b/drivers/net/irda/vlsi_ir.h | |||
@@ -577,8 +577,8 @@ struct ring_descr_hw { | |||
577 | struct { | 577 | struct { |
578 | u8 addr_res[3]; | 578 | u8 addr_res[3]; |
579 | volatile u8 status; /* descriptor status */ | 579 | volatile u8 status; /* descriptor status */ |
580 | } rd_s __attribute__((packed)); | 580 | } __attribute__((packed)) rd_s; |
581 | } rd_u __attribute((packed)); | 581 | } __attribute((packed)) rd_u; |
582 | } __attribute__ ((packed)); | 582 | } __attribute__ ((packed)); |
583 | 583 | ||
584 | #define rd_addr rd_u.addr | 584 | #define rd_addr rd_u.addr |
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 28bf2e69eb5e..7ec08127c9d6 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c | |||
@@ -88,7 +88,6 @@ static const char version[] = | |||
88 | #include <linux/skbuff.h> | 88 | #include <linux/skbuff.h> |
89 | 89 | ||
90 | #include <asm/io.h> | 90 | #include <asm/io.h> |
91 | #include <asm/irq.h> | ||
92 | 91 | ||
93 | #include "smc91x.h" | 92 | #include "smc91x.h" |
94 | 93 | ||
@@ -2007,12 +2006,10 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr) | |||
2007 | } | 2006 | } |
2008 | 2007 | ||
2009 | /* Grab the IRQ */ | 2008 | /* Grab the IRQ */ |
2010 | retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); | 2009 | retval = request_irq(dev->irq, &smc_interrupt, SMC_IRQ_FLAGS, dev->name, dev); |
2011 | if (retval) | 2010 | if (retval) |
2012 | goto err_out; | 2011 | goto err_out; |
2013 | 2012 | ||
2014 | set_irq_type(dev->irq, SMC_IRQ_TRIGGER_TYPE); | ||
2015 | |||
2016 | #ifdef SMC_USE_PXA_DMA | 2013 | #ifdef SMC_USE_PXA_DMA |
2017 | { | 2014 | { |
2018 | int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, | 2015 | int dma = pxa_request_dma(dev->name, DMA_PRIO_LOW, |
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 5c2824be4ee6..e0efd1964e72 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h | |||
@@ -90,7 +90,7 @@ | |||
90 | __l--; \ | 90 | __l--; \ |
91 | } \ | 91 | } \ |
92 | } while (0) | 92 | } while (0) |
93 | #define set_irq_type(irq, type) | 93 | #define SMC_IRQ_FLAGS (0) |
94 | 94 | ||
95 | #elif defined(CONFIG_SA1100_PLEB) | 95 | #elif defined(CONFIG_SA1100_PLEB) |
96 | /* We can only do 16-bit reads and writes in the static memory space. */ | 96 | /* We can only do 16-bit reads and writes in the static memory space. */ |
@@ -109,7 +109,7 @@ | |||
109 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) | 109 | #define SMC_outw(v, a, r) writew(v, (a) + (r)) |
110 | #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) | 110 | #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) |
111 | 111 | ||
112 | #define set_irq_type(irq, type) do {} while (0) | 112 | #define SMC_IRQ_FLAGS (0) |
113 | 113 | ||
114 | #elif defined(CONFIG_SA1100_ASSABET) | 114 | #elif defined(CONFIG_SA1100_ASSABET) |
115 | 115 | ||
@@ -185,11 +185,11 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) | |||
185 | #include <asm/mach-types.h> | 185 | #include <asm/mach-types.h> |
186 | #include <asm/arch/cpu.h> | 186 | #include <asm/arch/cpu.h> |
187 | 187 | ||
188 | #define SMC_IRQ_TRIGGER_TYPE (( \ | 188 | #define SMC_IRQ_FLAGS (( \ |
189 | machine_is_omap_h2() \ | 189 | machine_is_omap_h2() \ |
190 | || machine_is_omap_h3() \ | 190 | || machine_is_omap_h3() \ |
191 | || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ | 191 | || (machine_is_omap_innovator() && !cpu_is_omap1510()) \ |
192 | ) ? IRQT_FALLING : IRQT_RISING) | 192 | ) ? SA_TRIGGER_FALLING : SA_TRIGGER_RISING) |
193 | 193 | ||
194 | 194 | ||
195 | #elif defined(CONFIG_SH_SH4202_MICRODEV) | 195 | #elif defined(CONFIG_SH_SH4202_MICRODEV) |
@@ -209,7 +209,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) | |||
209 | #define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l) | 209 | #define SMC_insw(a, r, p, l) insw((a) + (r) - 0xa0000000, p, l) |
210 | #define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l) | 210 | #define SMC_outsw(a, r, p, l) outsw((a) + (r) - 0xa0000000, p, l) |
211 | 211 | ||
212 | #define set_irq_type(irq, type) do {} while(0) | 212 | #define SMC_IRQ_FLAGS (0) |
213 | 213 | ||
214 | #elif defined(CONFIG_ISA) | 214 | #elif defined(CONFIG_ISA) |
215 | 215 | ||
@@ -237,7 +237,7 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg) | |||
237 | #define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l) | 237 | #define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l) |
238 | #define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l) | 238 | #define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l) |
239 | 239 | ||
240 | #define set_irq_type(irq, type) do {} while(0) | 240 | #define SMC_IRQ_FLAGS (0) |
241 | 241 | ||
242 | #define RPC_LSA_DEFAULT RPC_LED_TX_RX | 242 | #define RPC_LSA_DEFAULT RPC_LED_TX_RX |
243 | #define RPC_LSB_DEFAULT RPC_LED_100_10 | 243 | #define RPC_LSB_DEFAULT RPC_LED_100_10 |
@@ -319,7 +319,7 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) | |||
319 | au_writew(*_p++ , _a); \ | 319 | au_writew(*_p++ , _a); \ |
320 | } while(0) | 320 | } while(0) |
321 | 321 | ||
322 | #define set_irq_type(irq, type) do {} while (0) | 322 | #define SMC_IRQ_FLAGS (0) |
323 | 323 | ||
324 | #else | 324 | #else |
325 | 325 | ||
@@ -342,8 +342,8 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l) | |||
342 | 342 | ||
343 | #endif | 343 | #endif |
344 | 344 | ||
345 | #ifndef SMC_IRQ_TRIGGER_TYPE | 345 | #ifndef SMC_IRQ_FLAGS |
346 | #define SMC_IRQ_TRIGGER_TYPE IRQT_RISING | 346 | #define SMC_IRQ_FLAGS SA_TRIGGER_RISING |
347 | #endif | 347 | #endif |
348 | 348 | ||
349 | #ifdef SMC_USE_PXA_DMA | 349 | #ifdef SMC_USE_PXA_DMA |
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 036adc4f8ba7..22e794071cf4 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c | |||
@@ -329,9 +329,9 @@ static int sdla_cpuspeed(struct net_device *dev, struct ifreq *ifr) | |||
329 | 329 | ||
330 | struct _dlci_stat | 330 | struct _dlci_stat |
331 | { | 331 | { |
332 | short dlci __attribute__((packed)); | 332 | short dlci; |
333 | char flags __attribute__((packed)); | 333 | char flags; |
334 | }; | 334 | } __attribute__((packed)); |
335 | 335 | ||
336 | struct _frad_stat | 336 | struct _frad_stat |
337 | { | 337 | { |
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c index 531b07313141..b2e8e49c8659 100644 --- a/drivers/oprofile/buffer_sync.c +++ b/drivers/oprofile/buffer_sync.c | |||
@@ -43,13 +43,16 @@ static void process_task_mortuary(void); | |||
43 | * list for processing. Only after two full buffer syncs | 43 | * list for processing. Only after two full buffer syncs |
44 | * does the task eventually get freed, because by then | 44 | * does the task eventually get freed, because by then |
45 | * we are sure we will not reference it again. | 45 | * we are sure we will not reference it again. |
46 | * Can be invoked from softirq via RCU callback due to | ||
47 | * call_rcu() of the task struct, hence the _irqsave. | ||
46 | */ | 48 | */ |
47 | static int task_free_notify(struct notifier_block * self, unsigned long val, void * data) | 49 | static int task_free_notify(struct notifier_block * self, unsigned long val, void * data) |
48 | { | 50 | { |
51 | unsigned long flags; | ||
49 | struct task_struct * task = data; | 52 | struct task_struct * task = data; |
50 | spin_lock(&task_mortuary); | 53 | spin_lock_irqsave(&task_mortuary, flags); |
51 | list_add(&task->tasks, &dying_tasks); | 54 | list_add(&task->tasks, &dying_tasks); |
52 | spin_unlock(&task_mortuary); | 55 | spin_unlock_irqrestore(&task_mortuary, flags); |
53 | return NOTIFY_OK; | 56 | return NOTIFY_OK; |
54 | } | 57 | } |
55 | 58 | ||
@@ -431,25 +434,22 @@ static void increment_tail(struct oprofile_cpu_buffer * b) | |||
431 | */ | 434 | */ |
432 | static void process_task_mortuary(void) | 435 | static void process_task_mortuary(void) |
433 | { | 436 | { |
434 | struct list_head * pos; | 437 | unsigned long flags; |
435 | struct list_head * pos2; | 438 | LIST_HEAD(local_dead_tasks); |
436 | struct task_struct * task; | 439 | struct task_struct * task; |
440 | struct task_struct * ttask; | ||
437 | 441 | ||
438 | spin_lock(&task_mortuary); | 442 | spin_lock_irqsave(&task_mortuary, flags); |
439 | 443 | ||
440 | list_for_each_safe(pos, pos2, &dead_tasks) { | 444 | list_splice_init(&dead_tasks, &local_dead_tasks); |
441 | task = list_entry(pos, struct task_struct, tasks); | 445 | list_splice_init(&dying_tasks, &dead_tasks); |
442 | list_del(&task->tasks); | ||
443 | free_task(task); | ||
444 | } | ||
445 | 446 | ||
446 | list_for_each_safe(pos, pos2, &dying_tasks) { | 447 | spin_unlock_irqrestore(&task_mortuary, flags); |
447 | task = list_entry(pos, struct task_struct, tasks); | 448 | |
449 | list_for_each_entry_safe(task, ttask, &local_dead_tasks, tasks) { | ||
448 | list_del(&task->tasks); | 450 | list_del(&task->tasks); |
449 | list_add_tail(&task->tasks, &dead_tasks); | 451 | free_task(task); |
450 | } | 452 | } |
451 | |||
452 | spin_unlock(&task_mortuary); | ||
453 | } | 453 | } |
454 | 454 | ||
455 | 455 | ||
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 026f671ea558..78193e4bbdb5 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c | |||
@@ -52,7 +52,8 @@ int alloc_cpu_buffers(void) | |||
52 | for_each_online_cpu(i) { | 52 | for_each_online_cpu(i) { |
53 | struct oprofile_cpu_buffer * b = &cpu_buffer[i]; | 53 | struct oprofile_cpu_buffer * b = &cpu_buffer[i]; |
54 | 54 | ||
55 | b->buffer = vmalloc(sizeof(struct op_sample) * buffer_size); | 55 | b->buffer = vmalloc_node(sizeof(struct op_sample) * buffer_size, |
56 | cpu_to_node(i)); | ||
56 | if (!b->buffer) | 57 | if (!b->buffer) |
57 | goto fail; | 58 | goto fail; |
58 | 59 | ||
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index b8241561da45..a665951b1586 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig | |||
@@ -34,7 +34,7 @@ config PARPORT | |||
34 | 34 | ||
35 | config PARPORT_PC | 35 | config PARPORT_PC |
36 | tristate "PC-style hardware" | 36 | tristate "PC-style hardware" |
37 | depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R | 37 | depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV |
38 | ---help--- | 38 | ---help--- |
39 | You should say Y here if you have a PC-style parallel port. All | 39 | You should say Y here if you have a PC-style parallel port. All |
40 | IBM PC compatible computers and some Alphas have PC-style | 40 | IBM PC compatible computers and some Alphas have PC-style |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 18e85ccdae67..9302b8fd7461 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2371,8 +2371,10 @@ void parport_pc_unregister_port (struct parport *p) | |||
2371 | spin_lock(&ports_lock); | 2371 | spin_lock(&ports_lock); |
2372 | list_del_init(&priv->list); | 2372 | list_del_init(&priv->list); |
2373 | spin_unlock(&ports_lock); | 2373 | spin_unlock(&ports_lock); |
2374 | #if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA) | ||
2374 | if (p->dma != PARPORT_DMA_NONE) | 2375 | if (p->dma != PARPORT_DMA_NONE) |
2375 | free_dma(p->dma); | 2376 | free_dma(p->dma); |
2377 | #endif | ||
2376 | if (p->irq != PARPORT_IRQ_NONE) | 2378 | if (p->irq != PARPORT_IRQ_NONE) |
2377 | free_irq(p->irq, p); | 2379 | free_irq(p->irq, p); |
2378 | release_region(p->base, 3); | 2380 | release_region(p->base, 3); |
@@ -2380,14 +2382,12 @@ void parport_pc_unregister_port (struct parport *p) | |||
2380 | release_region(p->base + 3, p->size - 3); | 2382 | release_region(p->base + 3, p->size - 3); |
2381 | if (p->modes & PARPORT_MODE_ECP) | 2383 | if (p->modes & PARPORT_MODE_ECP) |
2382 | release_region(p->base_hi, 3); | 2384 | release_region(p->base_hi, 3); |
2383 | #ifdef CONFIG_PARPORT_PC_FIFO | 2385 | #if defined(CONFIG_PARPORT_PC_FIFO) && defined(HAS_DMA) |
2384 | #ifdef HAS_DMA | ||
2385 | if (priv->dma_buf) | 2386 | if (priv->dma_buf) |
2386 | pci_free_consistent(priv->dev, PAGE_SIZE, | 2387 | pci_free_consistent(priv->dev, PAGE_SIZE, |
2387 | priv->dma_buf, | 2388 | priv->dma_buf, |
2388 | priv->dma_handle); | 2389 | priv->dma_handle); |
2389 | #endif | 2390 | #endif |
2390 | #endif | ||
2391 | kfree (p->private_data); | 2391 | kfree (p->private_data); |
2392 | parport_put_port(p); | 2392 | parport_put_port(p); |
2393 | kfree (ops); /* hope no-one cached it */ | 2393 | kfree (ops); /* hope no-one cached it */ |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 6a61b9f286e1..0aac6a61337d 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/sched.h> /* signal_pending() */ | ||
35 | #include <linux/pcieport_if.h> | 36 | #include <linux/pcieport_if.h> |
36 | #include "pci_hotplug.h" | 37 | #include "pci_hotplug.h" |
37 | 38 | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 0b8b26beb163..ac1e495c314e 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/types.h> | 32 | #include <linux/types.h> |
33 | #include <linux/signal.h> | ||
34 | #include <linux/jiffies.h> | ||
35 | #include <linux/timer.h> | ||
33 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
34 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
35 | 38 | ||
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 4f7ed4bd3be9..94e30fe4b8f3 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <linux/timer.h> | 26 | #include <linux/timer.h> |
27 | #include <linux/jiffies.h> | ||
28 | #include <linux/slab.h> | ||
27 | 29 | ||
28 | #include "rio.h" | 30 | #include "rio.h" |
29 | 31 | ||
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 30a11436e241..bef9316e95df 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/rio.h> | 15 | #include <linux/rio.h> |
16 | #include <linux/rio_drv.h> | 16 | #include <linux/rio_drv.h> |
17 | #include <linux/stat.h> | 17 | #include <linux/stat.h> |
18 | #include <linux/sched.h> /* for capable() */ | ||
18 | 19 | ||
19 | #include "rio.h" | 20 | #include "rio.h" |
20 | 21 | ||
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 3ca1011ceaac..5e382470faa2 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/rio_regs.h> | 23 | #include <linux/rio_regs.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
26 | #include <linux/slab.h> | ||
26 | 27 | ||
27 | #include "rio.h" | 28 | #include "rio.h" |
28 | 29 | ||
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index f779f674dfa0..2472fa1a1be1 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/major.h> | 18 | #include <linux/major.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
21 | #include <linux/hdreg.h> | ||
21 | 22 | ||
22 | #include <asm/ccwdev.h> | 23 | #include <asm/ccwdev.h> |
23 | #include <asm/ebcdic.h> | 24 | #include <asm/ebcdic.h> |
@@ -1723,12 +1724,34 @@ dasd_release(struct inode *inp, struct file *filp) | |||
1723 | return 0; | 1724 | return 0; |
1724 | } | 1725 | } |
1725 | 1726 | ||
1727 | /* | ||
1728 | * Return disk geometry. | ||
1729 | */ | ||
1730 | static int | ||
1731 | dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
1732 | { | ||
1733 | struct dasd_device *device; | ||
1734 | |||
1735 | device = bdev->bd_disk->private_data; | ||
1736 | if (!device) | ||
1737 | return -ENODEV; | ||
1738 | |||
1739 | if (!device->discipline || | ||
1740 | !device->discipline->fill_geometry) | ||
1741 | return -EINVAL; | ||
1742 | |||
1743 | device->discipline->fill_geometry(device, geo); | ||
1744 | geo->start = get_start_sect(bdev) >> device->s2b_shift; | ||
1745 | return 0; | ||
1746 | } | ||
1747 | |||
1726 | struct block_device_operations | 1748 | struct block_device_operations |
1727 | dasd_device_operations = { | 1749 | dasd_device_operations = { |
1728 | .owner = THIS_MODULE, | 1750 | .owner = THIS_MODULE, |
1729 | .open = dasd_open, | 1751 | .open = dasd_open, |
1730 | .release = dasd_release, | 1752 | .release = dasd_release, |
1731 | .ioctl = dasd_ioctl, | 1753 | .ioctl = dasd_ioctl, |
1754 | .getgeo = dasd_getgeo, | ||
1732 | }; | 1755 | }; |
1733 | 1756 | ||
1734 | 1757 | ||
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index 044b75371990..8e4dcd58599e 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
@@ -486,33 +486,6 @@ dasd_ioctl_set_ro(struct block_device *bdev, int no, long args) | |||
486 | } | 486 | } |
487 | 487 | ||
488 | /* | 488 | /* |
489 | * Return disk geometry. | ||
490 | */ | ||
491 | static int | ||
492 | dasd_ioctl_getgeo(struct block_device *bdev, int no, long args) | ||
493 | { | ||
494 | struct hd_geometry geo = { 0, }; | ||
495 | struct dasd_device *device; | ||
496 | |||
497 | device = bdev->bd_disk->private_data; | ||
498 | if (device == NULL) | ||
499 | return -ENODEV; | ||
500 | |||
501 | if (device == NULL || device->discipline == NULL || | ||
502 | device->discipline->fill_geometry == NULL) | ||
503 | return -EINVAL; | ||
504 | |||
505 | geo = (struct hd_geometry) {}; | ||
506 | device->discipline->fill_geometry(device, &geo); | ||
507 | geo.start = get_start_sect(bdev) >> device->s2b_shift; | ||
508 | if (copy_to_user((struct hd_geometry __user *) args, &geo, | ||
509 | sizeof (struct hd_geometry))) | ||
510 | return -EFAULT; | ||
511 | |||
512 | return 0; | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * List of static ioctls. | 489 | * List of static ioctls. |
517 | */ | 490 | */ |
518 | static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] = | 491 | static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] = |
@@ -528,7 +501,6 @@ static struct { int no; dasd_ioctl_fn_t fn; } dasd_ioctls[] = | |||
528 | { BIODASDPRRST, dasd_ioctl_reset_profile }, | 501 | { BIODASDPRRST, dasd_ioctl_reset_profile }, |
529 | { BLKROSET, dasd_ioctl_set_ro }, | 502 | { BLKROSET, dasd_ioctl_set_ro }, |
530 | { DASDAPIVER, dasd_ioctl_api_version }, | 503 | { DASDAPIVER, dasd_ioctl_api_version }, |
531 | { HDIO_GETGEO, dasd_ioctl_getgeo }, | ||
532 | { -1, NULL } | 504 | { -1, NULL } |
533 | }; | 505 | }; |
534 | 506 | ||
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index bf3a67c3cc5e..54ecd548c318 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
@@ -328,31 +328,27 @@ fail: | |||
328 | return 0; | 328 | return 0; |
329 | } | 329 | } |
330 | 330 | ||
331 | static int xpram_ioctl (struct inode *inode, struct file *filp, | 331 | static int xpram_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
332 | unsigned int cmd, unsigned long arg) | ||
333 | { | 332 | { |
334 | struct hd_geometry __user *geo; | ||
335 | unsigned long size; | 333 | unsigned long size; |
336 | if (cmd != HDIO_GETGEO) | 334 | |
337 | return -EINVAL; | ||
338 | /* | 335 | /* |
339 | * get geometry: we have to fake one... trim the size to a | 336 | * get geometry: we have to fake one... trim the size to a |
340 | * multiple of 64 (32k): tell we have 16 sectors, 4 heads, | 337 | * multiple of 64 (32k): tell we have 16 sectors, 4 heads, |
341 | * whatever cylinders. Tell also that data starts at sector. 4. | 338 | * whatever cylinders. Tell also that data starts at sector. 4. |
342 | */ | 339 | */ |
343 | geo = (struct hd_geometry __user *) arg; | ||
344 | size = (xpram_pages * 8) & ~0x3f; | 340 | size = (xpram_pages * 8) & ~0x3f; |
345 | put_user(size >> 6, &geo->cylinders); | 341 | geo->cylinders = size >> 6; |
346 | put_user(4, &geo->heads); | 342 | geo->heads = 4; |
347 | put_user(16, &geo->sectors); | 343 | geo->sectors = 16; |
348 | put_user(4, &geo->start); | 344 | geo->start = 4; |
349 | return 0; | 345 | return 0; |
350 | } | 346 | } |
351 | 347 | ||
352 | static struct block_device_operations xpram_devops = | 348 | static struct block_device_operations xpram_devops = |
353 | { | 349 | { |
354 | .owner = THIS_MODULE, | 350 | .owner = THIS_MODULE, |
355 | .ioctl = xpram_ioctl, | 351 | .getgeo = xpram_getgeo, |
356 | }; | 352 | }; |
357 | 353 | ||
358 | /* | 354 | /* |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 32d4d8d7b9f3..4c5127ed379c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -527,7 +527,7 @@ static int sd_release(struct inode *inode, struct file *filp) | |||
527 | return 0; | 527 | return 0; |
528 | } | 528 | } |
529 | 529 | ||
530 | static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user *loc) | 530 | static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
531 | { | 531 | { |
532 | struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); | 532 | struct scsi_disk *sdkp = scsi_disk(bdev->bd_disk); |
533 | struct scsi_device *sdp = sdkp->device; | 533 | struct scsi_device *sdp = sdkp->device; |
@@ -545,15 +545,9 @@ static int sd_hdio_getgeo(struct block_device *bdev, struct hd_geometry __user * | |||
545 | else | 545 | else |
546 | scsicam_bios_param(bdev, sdkp->capacity, diskinfo); | 546 | scsicam_bios_param(bdev, sdkp->capacity, diskinfo); |
547 | 547 | ||
548 | if (put_user(diskinfo[0], &loc->heads)) | 548 | geo->heads = diskinfo[0]; |
549 | return -EFAULT; | 549 | geo->sectors = diskinfo[1]; |
550 | if (put_user(diskinfo[1], &loc->sectors)) | 550 | geo->cylinders = diskinfo[2]; |
551 | return -EFAULT; | ||
552 | if (put_user(diskinfo[2], &loc->cylinders)) | ||
553 | return -EFAULT; | ||
554 | if (put_user((unsigned)get_start_sect(bdev), | ||
555 | (unsigned long __user *)&loc->start)) | ||
556 | return -EFAULT; | ||
557 | return 0; | 551 | return 0; |
558 | } | 552 | } |
559 | 553 | ||
@@ -593,12 +587,6 @@ static int sd_ioctl(struct inode * inode, struct file * filp, | |||
593 | if (!scsi_block_when_processing_errors(sdp) || !error) | 587 | if (!scsi_block_when_processing_errors(sdp) || !error) |
594 | return error; | 588 | return error; |
595 | 589 | ||
596 | if (cmd == HDIO_GETGEO) { | ||
597 | if (!arg) | ||
598 | return -EINVAL; | ||
599 | return sd_hdio_getgeo(bdev, p); | ||
600 | } | ||
601 | |||
602 | /* | 590 | /* |
603 | * Send SCSI addressing ioctls directly to mid level, send other | 591 | * Send SCSI addressing ioctls directly to mid level, send other |
604 | * ioctls to block level and then onto mid level if they can't be | 592 | * ioctls to block level and then onto mid level if they can't be |
@@ -800,6 +788,7 @@ static struct block_device_operations sd_fops = { | |||
800 | .open = sd_open, | 788 | .open = sd_open, |
801 | .release = sd_release, | 789 | .release = sd_release, |
802 | .ioctl = sd_ioctl, | 790 | .ioctl = sd_ioctl, |
791 | .getgeo = sd_getgeo, | ||
803 | #ifdef CONFIG_COMPAT | 792 | #ifdef CONFIG_COMPAT |
804 | .compat_ioctl = sd_compat_ioctl, | 793 | .compat_ioctl = sd_compat_ioctl, |
805 | #endif | 794 | #endif |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index c44bbedec817..4ddc453023a2 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -186,7 +186,7 @@ static void update_bus(struct dentry *bus) | |||
186 | 186 | ||
187 | down(&bus->d_inode->i_sem); | 187 | down(&bus->d_inode->i_sem); |
188 | 188 | ||
189 | list_for_each_entry(dev, &bus->d_subdirs, d_child) | 189 | list_for_each_entry(dev, &bus->d_subdirs, d_u.d_child) |
190 | if (dev->d_inode) | 190 | if (dev->d_inode) |
191 | update_dev(dev); | 191 | update_dev(dev); |
192 | 192 | ||
@@ -203,7 +203,7 @@ static void update_sb(struct super_block *sb) | |||
203 | 203 | ||
204 | down(&root->d_inode->i_sem); | 204 | down(&root->d_inode->i_sem); |
205 | 205 | ||
206 | list_for_each_entry(bus, &root->d_subdirs, d_child) { | 206 | list_for_each_entry(bus, &root->d_subdirs, d_u.d_child) { |
207 | if (bus->d_inode) { | 207 | if (bus->d_inode) { |
208 | switch (S_IFMT & bus->d_inode->i_mode) { | 208 | switch (S_IFMT & bus->d_inode->i_mode) { |
209 | case S_IFDIR: | 209 | case S_IFDIR: |
@@ -319,7 +319,7 @@ static int usbfs_empty (struct dentry *dentry) | |||
319 | spin_lock(&dcache_lock); | 319 | spin_lock(&dcache_lock); |
320 | 320 | ||
321 | list_for_each(list, &dentry->d_subdirs) { | 321 | list_for_each(list, &dentry->d_subdirs) { |
322 | struct dentry *de = list_entry(list, struct dentry, d_child); | 322 | struct dentry *de = list_entry(list, struct dentry, d_u.d_child); |
323 | if (usbfs_positive(de)) { | 323 | if (usbfs_positive(de)) { |
324 | spin_unlock(&dcache_lock); | 324 | spin_unlock(&dcache_lock); |
325 | return 0; | 325 | return 0; |
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index d9cf3b327d96..77cd6ac07e3c 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/signal.h> | ||
22 | 23 | ||
23 | #include <asm/mach-au1x00/au1000.h> | 24 | #include <asm/mach-au1x00/au1000.h> |
24 | 25 | ||
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 3959ccc88332..0020ed7a39d0 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/signal.h> | ||
20 | 21 | ||
21 | #include <asm/hardware.h> | 22 | #include <asm/hardware.h> |
22 | 23 | ||
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 2ec6a78bd65e..b2a8dfa48870 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/signal.h> | ||
18 | 19 | ||
19 | /* configure so an HC device and id are always provided */ | 20 | /* configure so an HC device and id are always provided */ |
20 | /* always called with process context; sleeping is OK */ | 21 | /* always called with process context; sleeping is OK */ |
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index a5d09e159cd1..6ee449858a5c 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig | |||
@@ -6,7 +6,7 @@ menu "Console display driver support" | |||
6 | 6 | ||
7 | config VGA_CONSOLE | 7 | config VGA_CONSOLE |
8 | bool "VGA text console" if EMBEDDED || !X86 | 8 | bool "VGA text console" if EMBEDDED || !X86 |
9 | depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !ARCH_VERSATILE | 9 | depends on !ARCH_ACORN && !ARCH_EBSA110 && !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !ARCH_VERSATILE |
10 | default y | 10 | default y |
11 | help | 11 | help |
12 | Saying Y here will allow you to use Linux in text mode through a | 12 | Saying Y here will allow you to use Linux in text mode through a |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 167de397e4b4..12d9329d1408 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -56,6 +56,8 @@ | |||
56 | static DEFINE_SPINLOCK(vga_lock); | 56 | static DEFINE_SPINLOCK(vga_lock); |
57 | static int cursor_size_lastfrom; | 57 | static int cursor_size_lastfrom; |
58 | static int cursor_size_lastto; | 58 | static int cursor_size_lastto; |
59 | static u32 vgacon_xres; | ||
60 | static u32 vgacon_yres; | ||
59 | static struct vgastate state; | 61 | static struct vgastate state; |
60 | 62 | ||
61 | #define BLANK 0x0020 | 63 | #define BLANK 0x0020 |
@@ -69,7 +71,7 @@ static struct vgastate state; | |||
69 | * appear. | 71 | * appear. |
70 | */ | 72 | */ |
71 | #undef TRIDENT_GLITCH | 73 | #undef TRIDENT_GLITCH |
72 | 74 | #define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */ | |
73 | /* | 75 | /* |
74 | * Interface used by the world | 76 | * Interface used by the world |
75 | */ | 77 | */ |
@@ -325,6 +327,10 @@ static const char __init *vgacon_startup(void) | |||
325 | vga_scan_lines = | 327 | vga_scan_lines = |
326 | vga_video_font_height * vga_video_num_lines; | 328 | vga_video_font_height * vga_video_num_lines; |
327 | } | 329 | } |
330 | |||
331 | vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; | ||
332 | vgacon_yres = vga_scan_lines; | ||
333 | |||
328 | return display_desc; | 334 | return display_desc; |
329 | } | 335 | } |
330 | 336 | ||
@@ -503,10 +509,18 @@ static int vgacon_doresize(struct vc_data *c, | |||
503 | { | 509 | { |
504 | unsigned long flags; | 510 | unsigned long flags; |
505 | unsigned int scanlines = height * c->vc_font.height; | 511 | unsigned int scanlines = height * c->vc_font.height; |
506 | u8 scanlines_lo, r7, vsync_end, mode; | 512 | u8 scanlines_lo, r7, vsync_end, mode, max_scan; |
507 | 513 | ||
508 | spin_lock_irqsave(&vga_lock, flags); | 514 | spin_lock_irqsave(&vga_lock, flags); |
509 | 515 | ||
516 | outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg); | ||
517 | max_scan = inb_p(vga_video_port_val); | ||
518 | |||
519 | if (max_scan & 0x80) | ||
520 | scanlines <<= 1; | ||
521 | |||
522 | vgacon_xres = width * VGA_FONTWIDTH; | ||
523 | vgacon_yres = height * c->vc_font.height; | ||
510 | outb_p(VGA_CRTC_MODE, vga_video_port_reg); | 524 | outb_p(VGA_CRTC_MODE, vga_video_port_reg); |
511 | mode = inb_p(vga_video_port_val); | 525 | mode = inb_p(vga_video_port_val); |
512 | 526 | ||
@@ -551,6 +565,10 @@ static int vgacon_doresize(struct vc_data *c, | |||
551 | 565 | ||
552 | static int vgacon_switch(struct vc_data *c) | 566 | static int vgacon_switch(struct vc_data *c) |
553 | { | 567 | { |
568 | int x = c->vc_cols * VGA_FONTWIDTH; | ||
569 | int y = c->vc_rows * c->vc_font.height; | ||
570 | int rows = ORIG_VIDEO_LINES * vga_default_font_height/ | ||
571 | c->vc_font.height; | ||
554 | /* | 572 | /* |
555 | * We need to save screen size here as it's the only way | 573 | * We need to save screen size here as it's the only way |
556 | * we can spot the screen has been resized and we need to | 574 | * we can spot the screen has been resized and we need to |
@@ -566,10 +584,11 @@ static int vgacon_switch(struct vc_data *c) | |||
566 | scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, | 584 | scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, |
567 | c->vc_screenbuf_size > vga_vram_size ? | 585 | c->vc_screenbuf_size > vga_vram_size ? |
568 | vga_vram_size : c->vc_screenbuf_size); | 586 | vga_vram_size : c->vc_screenbuf_size); |
569 | if (!(vga_video_num_columns % 2) && | 587 | |
570 | vga_video_num_columns <= ORIG_VIDEO_COLS && | 588 | if ((vgacon_xres != x || vgacon_yres != y) && |
571 | vga_video_num_lines <= (ORIG_VIDEO_LINES * | 589 | (!(vga_video_num_columns % 2) && |
572 | vga_default_font_height) / c->vc_font.height) | 590 | vga_video_num_columns <= ORIG_VIDEO_COLS && |
591 | vga_video_num_lines <= rows)) | ||
573 | vgacon_doresize(c, c->vc_cols, c->vc_rows); | 592 | vgacon_doresize(c, c->vc_cols, c->vc_rows); |
574 | } | 593 | } |
575 | 594 | ||
@@ -993,7 +1012,8 @@ static int vgacon_font_set(struct vc_data *c, struct console_font *font, unsigne | |||
993 | if (vga_video_type < VIDEO_TYPE_EGAM) | 1012 | if (vga_video_type < VIDEO_TYPE_EGAM) |
994 | return -EINVAL; | 1013 | return -EINVAL; |
995 | 1014 | ||
996 | if (font->width != 8 || (charcount != 256 && charcount != 512)) | 1015 | if (font->width != VGA_FONTWIDTH || |
1016 | (charcount != 256 && charcount != 512)) | ||
997 | return -EINVAL; | 1017 | return -EINVAL; |
998 | 1018 | ||
999 | rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512); | 1019 | rc = vgacon_do_font_op(&state, font->data, 1, charcount == 512); |
@@ -1010,7 +1030,7 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) | |||
1010 | if (vga_video_type < VIDEO_TYPE_EGAM) | 1030 | if (vga_video_type < VIDEO_TYPE_EGAM) |
1011 | return -EINVAL; | 1031 | return -EINVAL; |
1012 | 1032 | ||
1013 | font->width = 8; | 1033 | font->width = VGA_FONTWIDTH; |
1014 | font->height = c->vc_font.height; | 1034 | font->height = c->vc_font.height; |
1015 | font->charcount = vga_512_chars ? 512 : 256; | 1035 | font->charcount = vga_512_chars ? 512 : 256; |
1016 | if (!font->data) | 1036 | if (!font->data) |