diff options
Diffstat (limited to 'drivers')
133 files changed, 4290 insertions, 1258 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c index 373e7b728fa7..6b2eb6f39b4d 100644 --- a/drivers/base/attribute_container.c +++ b/drivers/base/attribute_container.c | |||
@@ -152,12 +152,13 @@ attribute_container_add_device(struct device *dev, | |||
152 | 152 | ||
153 | if (!cont->match(cont, dev)) | 153 | if (!cont->match(cont, dev)) |
154 | continue; | 154 | continue; |
155 | ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL); | 155 | |
156 | ic = kzalloc(sizeof(*ic), GFP_KERNEL); | ||
156 | if (!ic) { | 157 | if (!ic) { |
157 | dev_printk(KERN_ERR, dev, "failed to allocate class container\n"); | 158 | dev_printk(KERN_ERR, dev, "failed to allocate class container\n"); |
158 | continue; | 159 | continue; |
159 | } | 160 | } |
160 | memset(ic, 0, sizeof(struct internal_container)); | 161 | |
161 | ic->cont = cont; | 162 | ic->cont = cont; |
162 | class_device_initialize(&ic->classdev); | 163 | class_device_initialize(&ic->classdev); |
163 | ic->classdev.dev = get_device(dev); | 164 | ic->classdev.dev = get_device(dev); |
diff --git a/drivers/base/class.c b/drivers/base/class.c index d164c32a97ad..3b112e3542f8 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -189,12 +189,11 @@ struct class *class_create(struct module *owner, char *name) | |||
189 | struct class *cls; | 189 | struct class *cls; |
190 | int retval; | 190 | int retval; |
191 | 191 | ||
192 | cls = kmalloc(sizeof(struct class), GFP_KERNEL); | 192 | cls = kzalloc(sizeof(*cls), GFP_KERNEL); |
193 | if (!cls) { | 193 | if (!cls) { |
194 | retval = -ENOMEM; | 194 | retval = -ENOMEM; |
195 | goto error; | 195 | goto error; |
196 | } | 196 | } |
197 | memset(cls, 0x00, sizeof(struct class)); | ||
198 | 197 | ||
199 | cls->name = name; | 198 | cls->name = name; |
200 | cls->owner = owner; | 199 | cls->owner = owner; |
@@ -500,13 +499,13 @@ int class_device_add(struct class_device *class_dev) | |||
500 | /* add the needed attributes to this device */ | 499 | /* add the needed attributes to this device */ |
501 | if (MAJOR(class_dev->devt)) { | 500 | if (MAJOR(class_dev->devt)) { |
502 | struct class_device_attribute *attr; | 501 | struct class_device_attribute *attr; |
503 | attr = kmalloc(sizeof(*attr), GFP_KERNEL); | 502 | attr = kzalloc(sizeof(*attr), GFP_KERNEL); |
504 | if (!attr) { | 503 | if (!attr) { |
505 | error = -ENOMEM; | 504 | error = -ENOMEM; |
506 | kobject_del(&class_dev->kobj); | 505 | kobject_del(&class_dev->kobj); |
507 | goto register_done; | 506 | goto register_done; |
508 | } | 507 | } |
509 | memset(attr, sizeof(*attr), 0x00); | 508 | |
510 | attr->attr.name = "dev"; | 509 | attr->attr.name = "dev"; |
511 | attr->attr.mode = S_IRUGO; | 510 | attr->attr.mode = S_IRUGO; |
512 | attr->attr.owner = parent->owner; | 511 | attr->attr.owner = parent->owner; |
@@ -577,12 +576,11 @@ struct class_device *class_device_create(struct class *cls, dev_t devt, | |||
577 | if (cls == NULL || IS_ERR(cls)) | 576 | if (cls == NULL || IS_ERR(cls)) |
578 | goto error; | 577 | goto error; |
579 | 578 | ||
580 | class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL); | 579 | class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL); |
581 | if (!class_dev) { | 580 | if (!class_dev) { |
582 | retval = -ENOMEM; | 581 | retval = -ENOMEM; |
583 | goto error; | 582 | goto error; |
584 | } | 583 | } |
585 | memset(class_dev, 0x00, sizeof(struct class_device)); | ||
586 | 584 | ||
587 | class_dev->devt = devt; | 585 | class_dev->devt = devt; |
588 | class_dev->dev = device; | 586 | class_dev->dev = device; |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 5bfa2e9a7c26..4acb2c5733c3 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -301,9 +301,9 @@ fw_register_class_device(struct class_device **class_dev_p, | |||
301 | const char *fw_name, struct device *device) | 301 | const char *fw_name, struct device *device) |
302 | { | 302 | { |
303 | int retval; | 303 | int retval; |
304 | struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv), | 304 | struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv), |
305 | GFP_KERNEL); | 305 | GFP_KERNEL); |
306 | struct class_device *class_dev = kmalloc(sizeof (struct class_device), | 306 | struct class_device *class_dev = kzalloc(sizeof(*class_dev), |
307 | GFP_KERNEL); | 307 | GFP_KERNEL); |
308 | 308 | ||
309 | *class_dev_p = NULL; | 309 | *class_dev_p = NULL; |
@@ -313,8 +313,6 @@ fw_register_class_device(struct class_device **class_dev_p, | |||
313 | retval = -ENOMEM; | 313 | retval = -ENOMEM; |
314 | goto error_kfree; | 314 | goto error_kfree; |
315 | } | 315 | } |
316 | memset(fw_priv, 0, sizeof (*fw_priv)); | ||
317 | memset(class_dev, 0, sizeof (*class_dev)); | ||
318 | 316 | ||
319 | init_completion(&fw_priv->completion); | 317 | init_completion(&fw_priv->completion); |
320 | fw_priv->attr_data = firmware_attr_data_tmpl; | 318 | fw_priv->attr_data = firmware_attr_data_tmpl; |
@@ -402,14 +400,13 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
402 | if (!firmware_p) | 400 | if (!firmware_p) |
403 | return -EINVAL; | 401 | return -EINVAL; |
404 | 402 | ||
405 | *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL); | 403 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); |
406 | if (!firmware) { | 404 | if (!firmware) { |
407 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", | 405 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", |
408 | __FUNCTION__); | 406 | __FUNCTION__); |
409 | retval = -ENOMEM; | 407 | retval = -ENOMEM; |
410 | goto out; | 408 | goto out; |
411 | } | 409 | } |
412 | memset(firmware, 0, sizeof (*firmware)); | ||
413 | 410 | ||
414 | retval = fw_setup_class_device(firmware, &class_dev, name, device, | 411 | retval = fw_setup_class_device(firmware, &class_dev, name, device, |
415 | hotplug); | 412 | hotplug); |
diff --git a/drivers/base/map.c b/drivers/base/map.c index 2f455d86793c..b449dae6f0d3 100644 --- a/drivers/base/map.c +++ b/drivers/base/map.c | |||
@@ -135,7 +135,7 @@ retry: | |||
135 | struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) | 135 | struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) |
136 | { | 136 | { |
137 | struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); | 137 | struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL); |
138 | struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL); | 138 | struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL); |
139 | int i; | 139 | int i; |
140 | 140 | ||
141 | if ((p == NULL) || (base == NULL)) { | 141 | if ((p == NULL) || (base == NULL)) { |
@@ -144,7 +144,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem) | |||
144 | return NULL; | 144 | return NULL; |
145 | } | 145 | } |
146 | 146 | ||
147 | memset(base, 0, sizeof(struct probe)); | ||
148 | base->dev = 1; | 147 | base->dev = 1; |
149 | base->range = ~0; | 148 | base->range = ~0; |
150 | base->get = base_probe; | 149 | base->get = base_probe; |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 3a5f4c991797..361e204209eb 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -225,13 +225,12 @@ struct platform_device *platform_device_register_simple(char *name, unsigned int | |||
225 | struct platform_object *pobj; | 225 | struct platform_object *pobj; |
226 | int retval; | 226 | int retval; |
227 | 227 | ||
228 | pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL); | 228 | pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL); |
229 | if (!pobj) { | 229 | if (!pobj) { |
230 | retval = -ENOMEM; | 230 | retval = -ENOMEM; |
231 | goto error; | 231 | goto error; |
232 | } | 232 | } |
233 | 233 | ||
234 | memset(pobj, 0, sizeof(*pobj)); | ||
235 | pobj->pdev.name = name; | 234 | pobj->pdev.name = name; |
236 | pobj->pdev.id = id; | 235 | pobj->pdev.id = id; |
237 | pobj->pdev.dev.release = platform_device_release_simple; | 236 | pobj->pdev.dev.release = platform_device_release_simple; |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 28f2c177a541..c56f995aadad 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -47,14 +47,14 @@ | |||
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.6)" | 50 | #define DRIVER_NAME "HP CISS Driver (v 2.6.8)" |
51 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6) | 51 | #define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8) |
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.6"); | 55 | MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8"); |
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 E400 E300"); | 57 | " SA6i P600 P800 P400 P400i E200 E200i"); |
58 | MODULE_LICENSE("GPL"); | 58 | MODULE_LICENSE("GPL"); |
59 | 59 | ||
60 | #include "cciss_cmd.h" | 60 | #include "cciss_cmd.h" |
@@ -83,12 +83,22 @@ static const struct pci_device_id cciss_pci_device_id[] = { | |||
83 | 0x0E11, 0x4091, 0, 0, 0}, | 83 | 0x0E11, 0x4091, 0, 0, 0}, |
84 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, | 84 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, |
85 | 0x103C, 0x3225, 0, 0, 0}, | 85 | 0x103C, 0x3225, 0, 0, 0}, |
86 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB, | 86 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, |
87 | 0x103c, 0x3223, 0, 0, 0}, | 87 | 0x103c, 0x3223, 0, 0, 0}, |
88 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, | 88 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, |
89 | 0x103c, 0x3231, 0, 0, 0}, | 89 | 0x103c, 0x3234, 0, 0, 0}, |
90 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, | 90 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, |
91 | 0x103c, 0x3233, 0, 0, 0}, | 91 | 0x103c, 0x3235, 0, 0, 0}, |
92 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, | ||
93 | 0x103c, 0x3211, 0, 0, 0}, | ||
94 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, | ||
95 | 0x103c, 0x3212, 0, 0, 0}, | ||
96 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, | ||
97 | 0x103c, 0x3213, 0, 0, 0}, | ||
98 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, | ||
99 | 0x103c, 0x3214, 0, 0, 0}, | ||
100 | { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, | ||
101 | 0x103c, 0x3215, 0, 0, 0}, | ||
92 | {0,} | 102 | {0,} |
93 | }; | 103 | }; |
94 | MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); | 104 | MODULE_DEVICE_TABLE(pci, cciss_pci_device_id); |
@@ -111,8 +121,13 @@ static struct board_type products[] = { | |||
111 | { 0x40910E11, "Smart Array 6i", &SA5_access}, | 121 | { 0x40910E11, "Smart Array 6i", &SA5_access}, |
112 | { 0x3225103C, "Smart Array P600", &SA5_access}, | 122 | { 0x3225103C, "Smart Array P600", &SA5_access}, |
113 | { 0x3223103C, "Smart Array P800", &SA5_access}, | 123 | { 0x3223103C, "Smart Array P800", &SA5_access}, |
114 | { 0x3231103C, "Smart Array E400", &SA5_access}, | 124 | { 0x3234103C, "Smart Array P400", &SA5_access}, |
115 | { 0x3233103C, "Smart Array E300", &SA5_access}, | 125 | { 0x3235103C, "Smart Array P400i", &SA5_access}, |
126 | { 0x3211103C, "Smart Array E200i", &SA5_access}, | ||
127 | { 0x3212103C, "Smart Array E200", &SA5_access}, | ||
128 | { 0x3213103C, "Smart Array E200i", &SA5_access}, | ||
129 | { 0x3214103C, "Smart Array E200i", &SA5_access}, | ||
130 | { 0x3215103C, "Smart Array E200i", &SA5_access}, | ||
116 | }; | 131 | }; |
117 | 132 | ||
118 | /* How long to wait (in millesconds) for board to go into simple mode */ | 133 | /* How long to wait (in millesconds) for board to go into simple mode */ |
@@ -140,15 +155,26 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, | |||
140 | 155 | ||
141 | static int revalidate_allvol(ctlr_info_t *host); | 156 | static int revalidate_allvol(ctlr_info_t *host); |
142 | static int cciss_revalidate(struct gendisk *disk); | 157 | static int cciss_revalidate(struct gendisk *disk); |
143 | static int deregister_disk(struct gendisk *disk); | 158 | static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk); |
144 | static int register_new_disk(ctlr_info_t *h); | 159 | static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all); |
145 | 160 | ||
161 | static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, | ||
162 | int withirq, unsigned int *total_size, unsigned int *block_size); | ||
163 | static void cciss_geometry_inquiry(int ctlr, int logvol, | ||
164 | int withirq, unsigned int total_size, | ||
165 | unsigned int block_size, InquiryData_struct *inq_buff, | ||
166 | drive_info_struct *drv); | ||
146 | static void cciss_getgeometry(int cntl_num); | 167 | static void cciss_getgeometry(int cntl_num); |
147 | 168 | ||
148 | static void start_io( ctlr_info_t *h); | 169 | static void start_io( ctlr_info_t *h); |
149 | static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, | 170 | static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size, |
150 | unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, | 171 | unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, |
151 | unsigned char *scsi3addr, int cmd_type); | 172 | unsigned char *scsi3addr, int cmd_type); |
173 | static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, | ||
174 | unsigned int use_unit_num, unsigned int log_unit, __u8 page_code, | ||
175 | int cmd_type); | ||
176 | |||
177 | static void fail_all_cmds(unsigned long ctlr); | ||
152 | 178 | ||
153 | #ifdef CONFIG_PROC_FS | 179 | #ifdef CONFIG_PROC_FS |
154 | static int cciss_proc_get_info(char *buffer, char **start, off_t offset, | 180 | static int cciss_proc_get_info(char *buffer, char **start, off_t offset, |
@@ -265,7 +291,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset, | |||
265 | for(i=0; i<=h->highest_lun; i++) { | 291 | for(i=0; i<=h->highest_lun; i++) { |
266 | 292 | ||
267 | drv = &h->drv[i]; | 293 | drv = &h->drv[i]; |
268 | if (drv->block_size == 0) | 294 | if (drv->heads == 0) |
269 | continue; | 295 | continue; |
270 | 296 | ||
271 | vol_sz = drv->nr_blocks; | 297 | vol_sz = drv->nr_blocks; |
@@ -363,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) | |||
363 | return NULL; | 389 | return NULL; |
364 | memset(c, 0, sizeof(CommandList_struct)); | 390 | memset(c, 0, sizeof(CommandList_struct)); |
365 | 391 | ||
392 | c->cmdindex = -1; | ||
393 | |||
366 | c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( | 394 | c->err_info = (ErrorInfo_struct *)pci_alloc_consistent( |
367 | h->pdev, sizeof(ErrorInfo_struct), | 395 | h->pdev, sizeof(ErrorInfo_struct), |
368 | &err_dma_handle); | 396 | &err_dma_handle); |
@@ -393,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool) | |||
393 | err_dma_handle = h->errinfo_pool_dhandle | 421 | err_dma_handle = h->errinfo_pool_dhandle |
394 | + i*sizeof(ErrorInfo_struct); | 422 | + i*sizeof(ErrorInfo_struct); |
395 | h->nr_allocs++; | 423 | h->nr_allocs++; |
424 | |||
425 | c->cmdindex = i; | ||
396 | } | 426 | } |
397 | 427 | ||
398 | c->busaddr = (__u32) cmd_dma_handle; | 428 | c->busaddr = (__u32) cmd_dma_handle; |
@@ -453,6 +483,11 @@ static int cciss_open(struct inode *inode, struct file *filep) | |||
453 | printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); | 483 | printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name); |
454 | #endif /* CCISS_DEBUG */ | 484 | #endif /* CCISS_DEBUG */ |
455 | 485 | ||
486 | if (host->busy_initializing) | ||
487 | return -EBUSY; | ||
488 | |||
489 | if (host->busy_initializing || drv->busy_configuring) | ||
490 | return -EBUSY; | ||
456 | /* | 491 | /* |
457 | * Root is allowed to open raw volume zero even if it's not configured | 492 | * Root is allowed to open raw volume zero even if it's not configured |
458 | * so array config can still work. Root is also allowed to open any | 493 | * so array config can still work. Root is also allowed to open any |
@@ -796,10 +831,10 @@ static int cciss_ioctl(struct inode *inode, struct file *filep, | |||
796 | return(0); | 831 | return(0); |
797 | } | 832 | } |
798 | case CCISS_DEREGDISK: | 833 | case CCISS_DEREGDISK: |
799 | return deregister_disk(disk); | 834 | return rebuild_lun_table(host, disk); |
800 | 835 | ||
801 | case CCISS_REGNEWD: | 836 | case CCISS_REGNEWD: |
802 | return register_new_disk(host); | 837 | return rebuild_lun_table(host, NULL); |
803 | 838 | ||
804 | case CCISS_PASSTHRU: | 839 | case CCISS_PASSTHRU: |
805 | { | 840 | { |
@@ -1143,48 +1178,323 @@ static int revalidate_allvol(ctlr_info_t *host) | |||
1143 | return 0; | 1178 | return 0; |
1144 | } | 1179 | } |
1145 | 1180 | ||
1146 | static int deregister_disk(struct gendisk *disk) | 1181 | /* This function will check the usage_count of the drive to be updated/added. |
1182 | * If the usage_count is zero then the drive information will be updated and | ||
1183 | * the disk will be re-registered with the kernel. If not then it will be | ||
1184 | * left alone for the next reboot. The exception to this is disk 0 which | ||
1185 | * will always be left registered with the kernel since it is also the | ||
1186 | * controller node. Any changes to disk 0 will show up on the next | ||
1187 | * reboot. | ||
1188 | */ | ||
1189 | static void cciss_update_drive_info(int ctlr, int drv_index) | ||
1190 | { | ||
1191 | ctlr_info_t *h = hba[ctlr]; | ||
1192 | struct gendisk *disk; | ||
1193 | ReadCapdata_struct *size_buff = NULL; | ||
1194 | InquiryData_struct *inq_buff = NULL; | ||
1195 | unsigned int block_size; | ||
1196 | unsigned int total_size; | ||
1197 | unsigned long flags = 0; | ||
1198 | int ret = 0; | ||
1199 | |||
1200 | /* if the disk already exists then deregister it before proceeding*/ | ||
1201 | if (h->drv[drv_index].raid_level != -1){ | ||
1202 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
1203 | h->drv[drv_index].busy_configuring = 1; | ||
1204 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1205 | ret = deregister_disk(h->gendisk[drv_index], | ||
1206 | &h->drv[drv_index], 0); | ||
1207 | h->drv[drv_index].busy_configuring = 0; | ||
1208 | } | ||
1209 | |||
1210 | /* If the disk is in use return */ | ||
1211 | if (ret) | ||
1212 | return; | ||
1213 | |||
1214 | |||
1215 | /* Get information about the disk and modify the driver sturcture */ | ||
1216 | size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); | ||
1217 | if (size_buff == NULL) | ||
1218 | goto mem_msg; | ||
1219 | inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); | ||
1220 | if (inq_buff == NULL) | ||
1221 | goto mem_msg; | ||
1222 | |||
1223 | cciss_read_capacity(ctlr, drv_index, size_buff, 1, | ||
1224 | &total_size, &block_size); | ||
1225 | cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size, | ||
1226 | inq_buff, &h->drv[drv_index]); | ||
1227 | |||
1228 | ++h->num_luns; | ||
1229 | disk = h->gendisk[drv_index]; | ||
1230 | set_capacity(disk, h->drv[drv_index].nr_blocks); | ||
1231 | |||
1232 | |||
1233 | /* if it's the controller it's already added */ | ||
1234 | if (drv_index){ | ||
1235 | disk->queue = blk_init_queue(do_cciss_request, &h->lock); | ||
1236 | |||
1237 | /* Set up queue information */ | ||
1238 | disk->queue->backing_dev_info.ra_pages = READ_AHEAD; | ||
1239 | blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask); | ||
1240 | |||
1241 | /* This is a hardware imposed limit. */ | ||
1242 | blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES); | ||
1243 | |||
1244 | /* This is a limit in the driver and could be eliminated. */ | ||
1245 | blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES); | ||
1246 | |||
1247 | blk_queue_max_sectors(disk->queue, 512); | ||
1248 | |||
1249 | disk->queue->queuedata = hba[ctlr]; | ||
1250 | |||
1251 | blk_queue_hardsect_size(disk->queue, | ||
1252 | hba[ctlr]->drv[drv_index].block_size); | ||
1253 | |||
1254 | h->drv[drv_index].queue = disk->queue; | ||
1255 | add_disk(disk); | ||
1256 | } | ||
1257 | |||
1258 | freeret: | ||
1259 | kfree(size_buff); | ||
1260 | kfree(inq_buff); | ||
1261 | return; | ||
1262 | mem_msg: | ||
1263 | printk(KERN_ERR "cciss: out of memory\n"); | ||
1264 | goto freeret; | ||
1265 | } | ||
1266 | |||
1267 | /* This function will find the first index of the controllers drive array | ||
1268 | * that has a -1 for the raid_level and will return that index. This is | ||
1269 | * where new drives will be added. If the index to be returned is greater | ||
1270 | * than the highest_lun index for the controller then highest_lun is set | ||
1271 | * to this new index. If there are no available indexes then -1 is returned. | ||
1272 | */ | ||
1273 | static int cciss_find_free_drive_index(int ctlr) | ||
1147 | { | 1274 | { |
1275 | int i; | ||
1276 | |||
1277 | for (i=0; i < CISS_MAX_LUN; i++){ | ||
1278 | if (hba[ctlr]->drv[i].raid_level == -1){ | ||
1279 | if (i > hba[ctlr]->highest_lun) | ||
1280 | hba[ctlr]->highest_lun = i; | ||
1281 | return i; | ||
1282 | } | ||
1283 | } | ||
1284 | return -1; | ||
1285 | } | ||
1286 | |||
1287 | /* This function will add and remove logical drives from the Logical | ||
1288 | * drive array of the controller and maintain persistancy of ordering | ||
1289 | * so that mount points are preserved until the next reboot. This allows | ||
1290 | * for the removal of logical drives in the middle of the drive array | ||
1291 | * without a re-ordering of those drives. | ||
1292 | * INPUT | ||
1293 | * h = The controller to perform the operations on | ||
1294 | * del_disk = The disk to remove if specified. If the value given | ||
1295 | * is NULL then no disk is removed. | ||
1296 | */ | ||
1297 | static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk) | ||
1298 | { | ||
1299 | int ctlr = h->ctlr; | ||
1300 | int num_luns; | ||
1301 | ReportLunData_struct *ld_buff = NULL; | ||
1302 | drive_info_struct *drv = NULL; | ||
1303 | int return_code; | ||
1304 | int listlength = 0; | ||
1305 | int i; | ||
1306 | int drv_found; | ||
1307 | int drv_index = 0; | ||
1308 | __u32 lunid = 0; | ||
1148 | unsigned long flags; | 1309 | unsigned long flags; |
1310 | |||
1311 | /* Set busy_configuring flag for this operation */ | ||
1312 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
1313 | if (h->num_luns >= CISS_MAX_LUN){ | ||
1314 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1315 | return -EINVAL; | ||
1316 | } | ||
1317 | |||
1318 | if (h->busy_configuring){ | ||
1319 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1320 | return -EBUSY; | ||
1321 | } | ||
1322 | h->busy_configuring = 1; | ||
1323 | |||
1324 | /* if del_disk is NULL then we are being called to add a new disk | ||
1325 | * and update the logical drive table. If it is not NULL then | ||
1326 | * we will check if the disk is in use or not. | ||
1327 | */ | ||
1328 | if (del_disk != NULL){ | ||
1329 | drv = get_drv(del_disk); | ||
1330 | drv->busy_configuring = 1; | ||
1331 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1332 | return_code = deregister_disk(del_disk, drv, 1); | ||
1333 | drv->busy_configuring = 0; | ||
1334 | h->busy_configuring = 0; | ||
1335 | return return_code; | ||
1336 | } else { | ||
1337 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
1338 | if (!capable(CAP_SYS_RAWIO)) | ||
1339 | return -EPERM; | ||
1340 | |||
1341 | ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL); | ||
1342 | if (ld_buff == NULL) | ||
1343 | goto mem_msg; | ||
1344 | |||
1345 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, | ||
1346 | sizeof(ReportLunData_struct), 0, 0, 0, | ||
1347 | TYPE_CMD); | ||
1348 | |||
1349 | if (return_code == IO_OK){ | ||
1350 | listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24; | ||
1351 | listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16; | ||
1352 | listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8; | ||
1353 | listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]); | ||
1354 | } else{ /* reading number of logical volumes failed */ | ||
1355 | printk(KERN_WARNING "cciss: report logical volume" | ||
1356 | " command failed\n"); | ||
1357 | listlength = 0; | ||
1358 | goto freeret; | ||
1359 | } | ||
1360 | |||
1361 | num_luns = listlength / 8; /* 8 bytes per entry */ | ||
1362 | if (num_luns > CISS_MAX_LUN){ | ||
1363 | num_luns = CISS_MAX_LUN; | ||
1364 | printk(KERN_WARNING "cciss: more luns configured" | ||
1365 | " on controller than can be handled by" | ||
1366 | " this driver.\n"); | ||
1367 | } | ||
1368 | |||
1369 | /* Compare controller drive array to drivers drive array. | ||
1370 | * Check for updates in the drive information and any new drives | ||
1371 | * on the controller. | ||
1372 | */ | ||
1373 | for (i=0; i < num_luns; i++){ | ||
1374 | int j; | ||
1375 | |||
1376 | drv_found = 0; | ||
1377 | |||
1378 | lunid = (0xff & | ||
1379 | (unsigned int)(ld_buff->LUN[i][3])) << 24; | ||
1380 | lunid |= (0xff & | ||
1381 | (unsigned int)(ld_buff->LUN[i][2])) << 16; | ||
1382 | lunid |= (0xff & | ||
1383 | (unsigned int)(ld_buff->LUN[i][1])) << 8; | ||
1384 | lunid |= 0xff & | ||
1385 | (unsigned int)(ld_buff->LUN[i][0]); | ||
1386 | |||
1387 | /* Find if the LUN is already in the drive array | ||
1388 | * of the controller. If so then update its info | ||
1389 | * if not is use. If it does not exist then find | ||
1390 | * the first free index and add it. | ||
1391 | */ | ||
1392 | for (j=0; j <= h->highest_lun; j++){ | ||
1393 | if (h->drv[j].LunID == lunid){ | ||
1394 | drv_index = j; | ||
1395 | drv_found = 1; | ||
1396 | } | ||
1397 | } | ||
1398 | |||
1399 | /* check if the drive was found already in the array */ | ||
1400 | if (!drv_found){ | ||
1401 | drv_index = cciss_find_free_drive_index(ctlr); | ||
1402 | if (drv_index == -1) | ||
1403 | goto freeret; | ||
1404 | |||
1405 | } | ||
1406 | h->drv[drv_index].LunID = lunid; | ||
1407 | cciss_update_drive_info(ctlr, drv_index); | ||
1408 | } /* end for */ | ||
1409 | } /* end else */ | ||
1410 | |||
1411 | freeret: | ||
1412 | kfree(ld_buff); | ||
1413 | h->busy_configuring = 0; | ||
1414 | /* We return -1 here to tell the ACU that we have registered/updated | ||
1415 | * all of the drives that we can and to keep it from calling us | ||
1416 | * additional times. | ||
1417 | */ | ||
1418 | return -1; | ||
1419 | mem_msg: | ||
1420 | printk(KERN_ERR "cciss: out of memory\n"); | ||
1421 | goto freeret; | ||
1422 | } | ||
1423 | |||
1424 | /* This function will deregister the disk and it's queue from the | ||
1425 | * kernel. It must be called with the controller lock held and the | ||
1426 | * drv structures busy_configuring flag set. It's parameters are: | ||
1427 | * | ||
1428 | * disk = This is the disk to be deregistered | ||
1429 | * drv = This is the drive_info_struct associated with the disk to be | ||
1430 | * deregistered. It contains information about the disk used | ||
1431 | * by the driver. | ||
1432 | * clear_all = This flag determines whether or not the disk information | ||
1433 | * is going to be completely cleared out and the highest_lun | ||
1434 | * reset. Sometimes we want to clear out information about | ||
1435 | * the disk in preperation for re-adding it. In this case | ||
1436 | * the highest_lun should be left unchanged and the LunID | ||
1437 | * should not be cleared. | ||
1438 | */ | ||
1439 | static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, | ||
1440 | int clear_all) | ||
1441 | { | ||
1149 | ctlr_info_t *h = get_host(disk); | 1442 | ctlr_info_t *h = get_host(disk); |
1150 | drive_info_struct *drv = get_drv(disk); | ||
1151 | int ctlr = h->ctlr; | ||
1152 | 1443 | ||
1153 | if (!capable(CAP_SYS_RAWIO)) | 1444 | if (!capable(CAP_SYS_RAWIO)) |
1154 | return -EPERM; | 1445 | return -EPERM; |
1155 | 1446 | ||
1156 | spin_lock_irqsave(CCISS_LOCK(ctlr), flags); | ||
1157 | /* make sure logical volume is NOT is use */ | 1447 | /* make sure logical volume is NOT is use */ |
1158 | if( drv->usage_count > 1) { | 1448 | if(clear_all || (h->gendisk[0] == disk)) { |
1159 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | 1449 | if (drv->usage_count > 1) |
1160 | return -EBUSY; | 1450 | return -EBUSY; |
1161 | } | 1451 | } |
1162 | drv->usage_count++; | 1452 | else |
1163 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | 1453 | if( drv->usage_count > 0 ) |
1454 | return -EBUSY; | ||
1164 | 1455 | ||
1165 | /* invalidate the devices and deregister the disk */ | 1456 | /* invalidate the devices and deregister the disk. If it is disk |
1166 | if (disk->flags & GENHD_FL_UP) | 1457 | * zero do not deregister it but just zero out it's values. This |
1458 | * allows us to delete disk zero but keep the controller registered. | ||
1459 | */ | ||
1460 | if (h->gendisk[0] != disk){ | ||
1461 | if (disk->flags & GENHD_FL_UP){ | ||
1462 | blk_cleanup_queue(disk->queue); | ||
1167 | del_gendisk(disk); | 1463 | del_gendisk(disk); |
1464 | drv->queue = NULL; | ||
1465 | } | ||
1466 | } | ||
1467 | |||
1468 | --h->num_luns; | ||
1469 | /* zero out the disk size info */ | ||
1470 | drv->nr_blocks = 0; | ||
1471 | drv->block_size = 0; | ||
1472 | drv->heads = 0; | ||
1473 | drv->sectors = 0; | ||
1474 | drv->cylinders = 0; | ||
1475 | drv->raid_level = -1; /* This can be used as a flag variable to | ||
1476 | * indicate that this element of the drive | ||
1477 | * array is free. | ||
1478 | */ | ||
1479 | |||
1480 | if (clear_all){ | ||
1168 | /* check to see if it was the last disk */ | 1481 | /* check to see if it was the last disk */ |
1169 | if (drv == h->drv + h->highest_lun) { | 1482 | if (drv == h->drv + h->highest_lun) { |
1170 | /* if so, find the new hightest lun */ | 1483 | /* if so, find the new hightest lun */ |
1171 | int i, newhighest =-1; | 1484 | int i, newhighest =-1; |
1172 | for(i=0; i<h->highest_lun; i++) { | 1485 | for(i=0; i<h->highest_lun; i++) { |
1173 | /* if the disk has size > 0, it is available */ | 1486 | /* if the disk has size > 0, it is available */ |
1174 | if (h->drv[i].nr_blocks) | 1487 | if (h->drv[i].heads) |
1175 | newhighest = i; | 1488 | newhighest = i; |
1176 | } | 1489 | } |
1177 | h->highest_lun = newhighest; | 1490 | h->highest_lun = newhighest; |
1178 | |||
1179 | } | 1491 | } |
1180 | --h->num_luns; | 1492 | |
1181 | /* zero out the disk size info */ | ||
1182 | drv->nr_blocks = 0; | ||
1183 | drv->block_size = 0; | ||
1184 | drv->cylinders = 0; | ||
1185 | drv->LunID = 0; | 1493 | drv->LunID = 0; |
1494 | } | ||
1186 | return(0); | 1495 | return(0); |
1187 | } | 1496 | } |
1497 | |||
1188 | static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, | 1498 | static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, |
1189 | size_t size, | 1499 | size_t size, |
1190 | unsigned int use_unit_num, /* 0: address the controller, | 1500 | unsigned int use_unit_num, /* 0: address the controller, |
@@ -1420,8 +1730,10 @@ case CMD_HARDWARE_ERR: | |||
1420 | } | 1730 | } |
1421 | } | 1731 | } |
1422 | /* unlock the buffers from DMA */ | 1732 | /* unlock the buffers from DMA */ |
1733 | buff_dma_handle.val32.lower = c->SG[0].Addr.lower; | ||
1734 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; | ||
1423 | pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val, | 1735 | pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val, |
1424 | size, PCI_DMA_BIDIRECTIONAL); | 1736 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); |
1425 | cmd_free(h, c, 0); | 1737 | cmd_free(h, c, 0); |
1426 | return(return_status); | 1738 | return(return_status); |
1427 | 1739 | ||
@@ -1495,164 +1807,6 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf, | |||
1495 | return; | 1807 | return; |
1496 | } | 1808 | } |
1497 | 1809 | ||
1498 | static int register_new_disk(ctlr_info_t *h) | ||
1499 | { | ||
1500 | struct gendisk *disk; | ||
1501 | int ctlr = h->ctlr; | ||
1502 | int i; | ||
1503 | int num_luns; | ||
1504 | int logvol; | ||
1505 | int new_lun_found = 0; | ||
1506 | int new_lun_index = 0; | ||
1507 | int free_index_found = 0; | ||
1508 | int free_index = 0; | ||
1509 | ReportLunData_struct *ld_buff = NULL; | ||
1510 | ReadCapdata_struct *size_buff = NULL; | ||
1511 | InquiryData_struct *inq_buff = NULL; | ||
1512 | int return_code; | ||
1513 | int listlength = 0; | ||
1514 | __u32 lunid = 0; | ||
1515 | unsigned int block_size; | ||
1516 | unsigned int total_size; | ||
1517 | |||
1518 | if (!capable(CAP_SYS_RAWIO)) | ||
1519 | return -EPERM; | ||
1520 | /* if we have no space in our disk array left to add anything */ | ||
1521 | if( h->num_luns >= CISS_MAX_LUN) | ||
1522 | return -EINVAL; | ||
1523 | |||
1524 | ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL); | ||
1525 | if (ld_buff == NULL) | ||
1526 | goto mem_msg; | ||
1527 | memset(ld_buff, 0, sizeof(ReportLunData_struct)); | ||
1528 | size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL); | ||
1529 | if (size_buff == NULL) | ||
1530 | goto mem_msg; | ||
1531 | inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); | ||
1532 | if (inq_buff == NULL) | ||
1533 | goto mem_msg; | ||
1534 | |||
1535 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, | ||
1536 | sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD); | ||
1537 | |||
1538 | if( return_code == IO_OK) | ||
1539 | { | ||
1540 | |||
1541 | // printk("LUN Data\n--------------------------\n"); | ||
1542 | |||
1543 | listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24; | ||
1544 | listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16; | ||
1545 | listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8; | ||
1546 | listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]); | ||
1547 | } else /* reading number of logical volumes failed */ | ||
1548 | { | ||
1549 | printk(KERN_WARNING "cciss: report logical volume" | ||
1550 | " command failed\n"); | ||
1551 | listlength = 0; | ||
1552 | goto free_err; | ||
1553 | } | ||
1554 | num_luns = listlength / 8; // 8 bytes pre entry | ||
1555 | if (num_luns > CISS_MAX_LUN) | ||
1556 | { | ||
1557 | num_luns = CISS_MAX_LUN; | ||
1558 | } | ||
1559 | #ifdef CCISS_DEBUG | ||
1560 | printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0], | ||
1561 | ld_buff->LUNListLength[1], ld_buff->LUNListLength[2], | ||
1562 | ld_buff->LUNListLength[3], num_luns); | ||
1563 | #endif | ||
1564 | for(i=0; i< num_luns; i++) | ||
1565 | { | ||
1566 | int j; | ||
1567 | int lunID_found = 0; | ||
1568 | |||
1569 | lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24; | ||
1570 | lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16; | ||
1571 | lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8; | ||
1572 | lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); | ||
1573 | |||
1574 | /* check to see if this is a new lun */ | ||
1575 | for(j=0; j <= h->highest_lun; j++) | ||
1576 | { | ||
1577 | #ifdef CCISS_DEBUG | ||
1578 | printk("Checking %d %x against %x\n", j,h->drv[j].LunID, | ||
1579 | lunid); | ||
1580 | #endif /* CCISS_DEBUG */ | ||
1581 | if (h->drv[j].LunID == lunid) | ||
1582 | { | ||
1583 | lunID_found = 1; | ||
1584 | break; | ||
1585 | } | ||
1586 | |||
1587 | } | ||
1588 | if( lunID_found == 1) | ||
1589 | continue; | ||
1590 | else | ||
1591 | { /* It is the new lun we have been looking for */ | ||
1592 | #ifdef CCISS_DEBUG | ||
1593 | printk("new lun found at %d\n", i); | ||
1594 | #endif /* CCISS_DEBUG */ | ||
1595 | new_lun_index = i; | ||
1596 | new_lun_found = 1; | ||
1597 | break; | ||
1598 | } | ||
1599 | } | ||
1600 | if (!new_lun_found) | ||
1601 | { | ||
1602 | printk(KERN_WARNING "cciss: New Logical Volume not found\n"); | ||
1603 | goto free_err; | ||
1604 | } | ||
1605 | /* Now find the free index */ | ||
1606 | for(i=0; i <CISS_MAX_LUN; i++) | ||
1607 | { | ||
1608 | #ifdef CCISS_DEBUG | ||
1609 | printk("Checking Index %d\n", i); | ||
1610 | #endif /* CCISS_DEBUG */ | ||
1611 | if(h->drv[i].LunID == 0) | ||
1612 | { | ||
1613 | #ifdef CCISS_DEBUG | ||
1614 | printk("free index found at %d\n", i); | ||
1615 | #endif /* CCISS_DEBUG */ | ||
1616 | free_index_found = 1; | ||
1617 | free_index = i; | ||
1618 | break; | ||
1619 | } | ||
1620 | } | ||
1621 | if (!free_index_found) | ||
1622 | { | ||
1623 | printk(KERN_WARNING "cciss: unable to find free slot for disk\n"); | ||
1624 | goto free_err; | ||
1625 | } | ||
1626 | |||
1627 | logvol = free_index; | ||
1628 | h->drv[logvol].LunID = lunid; | ||
1629 | /* there could be gaps in lun numbers, track hightest */ | ||
1630 | if(h->highest_lun < lunid) | ||
1631 | h->highest_lun = logvol; | ||
1632 | cciss_read_capacity(ctlr, logvol, size_buff, 1, | ||
1633 | &total_size, &block_size); | ||
1634 | cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size, | ||
1635 | inq_buff, &h->drv[logvol]); | ||
1636 | h->drv[logvol].usage_count = 0; | ||
1637 | ++h->num_luns; | ||
1638 | /* setup partitions per disk */ | ||
1639 | disk = h->gendisk[logvol]; | ||
1640 | set_capacity(disk, h->drv[logvol].nr_blocks); | ||
1641 | /* if it's the controller it's already added */ | ||
1642 | if(logvol) | ||
1643 | add_disk(disk); | ||
1644 | freeret: | ||
1645 | kfree(ld_buff); | ||
1646 | kfree(size_buff); | ||
1647 | kfree(inq_buff); | ||
1648 | return (logvol); | ||
1649 | mem_msg: | ||
1650 | printk(KERN_ERR "cciss: out of memory\n"); | ||
1651 | free_err: | ||
1652 | logvol = -1; | ||
1653 | goto freeret; | ||
1654 | } | ||
1655 | |||
1656 | static int cciss_revalidate(struct gendisk *disk) | 1810 | static int cciss_revalidate(struct gendisk *disk) |
1657 | { | 1811 | { |
1658 | ctlr_info_t *h = get_host(disk); | 1812 | ctlr_info_t *h = get_host(disk); |
@@ -1859,8 +2013,10 @@ resend_cmd1: | |||
1859 | 2013 | ||
1860 | cleanup1: | 2014 | cleanup1: |
1861 | /* unlock the data buffer from DMA */ | 2015 | /* unlock the data buffer from DMA */ |
2016 | buff_dma_handle.val32.lower = c->SG[0].Addr.lower; | ||
2017 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; | ||
1862 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, | 2018 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, |
1863 | size, PCI_DMA_BIDIRECTIONAL); | 2019 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); |
1864 | cmd_free(info_p, c, 1); | 2020 | cmd_free(info_p, c, 1); |
1865 | return (status); | 2021 | return (status); |
1866 | } | 2022 | } |
@@ -2111,7 +2267,11 @@ queue: | |||
2111 | /* fill in the request */ | 2267 | /* fill in the request */ |
2112 | drv = creq->rq_disk->private_data; | 2268 | drv = creq->rq_disk->private_data; |
2113 | c->Header.ReplyQueue = 0; // unused in simple mode | 2269 | c->Header.ReplyQueue = 0; // unused in simple mode |
2114 | c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag | 2270 | /* got command from pool, so use the command block index instead */ |
2271 | /* for direct lookups. */ | ||
2272 | /* The first 2 bits are reserved for controller error reporting. */ | ||
2273 | c->Header.Tag.lower = (c->cmdindex << 3); | ||
2274 | c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ | ||
2115 | c->Header.LUN.LogDev.VolId= drv->LunID; | 2275 | c->Header.LUN.LogDev.VolId= drv->LunID; |
2116 | c->Header.LUN.LogDev.Mode = 1; | 2276 | c->Header.LUN.LogDev.Mode = 1; |
2117 | c->Request.CDBLen = 10; // 12 byte commands not in FW yet; | 2277 | c->Request.CDBLen = 10; // 12 byte commands not in FW yet; |
@@ -2186,7 +2346,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2186 | ctlr_info_t *h = dev_id; | 2346 | ctlr_info_t *h = dev_id; |
2187 | CommandList_struct *c; | 2347 | CommandList_struct *c; |
2188 | unsigned long flags; | 2348 | unsigned long flags; |
2189 | __u32 a, a1; | 2349 | __u32 a, a1, a2; |
2190 | int j; | 2350 | int j; |
2191 | int start_queue = h->next_to_run; | 2351 | int start_queue = h->next_to_run; |
2192 | 2352 | ||
@@ -2204,10 +2364,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2204 | while((a = h->access.command_completed(h)) != FIFO_EMPTY) | 2364 | while((a = h->access.command_completed(h)) != FIFO_EMPTY) |
2205 | { | 2365 | { |
2206 | a1 = a; | 2366 | a1 = a; |
2367 | if ((a & 0x04)) { | ||
2368 | a2 = (a >> 3); | ||
2369 | if (a2 >= NR_CMDS) { | ||
2370 | printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr); | ||
2371 | fail_all_cmds(h->ctlr); | ||
2372 | return IRQ_HANDLED; | ||
2373 | } | ||
2374 | |||
2375 | c = h->cmd_pool + a2; | ||
2376 | a = c->busaddr; | ||
2377 | |||
2378 | } else { | ||
2207 | a &= ~3; | 2379 | a &= ~3; |
2208 | if ((c = h->cmpQ) == NULL) | 2380 | if ((c = h->cmpQ) == NULL) { |
2209 | { | 2381 | printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1); |
2210 | printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1); | ||
2211 | continue; | 2382 | continue; |
2212 | } | 2383 | } |
2213 | while(c->busaddr != a) { | 2384 | while(c->busaddr != a) { |
@@ -2215,6 +2386,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2215 | if (c == h->cmpQ) | 2386 | if (c == h->cmpQ) |
2216 | break; | 2387 | break; |
2217 | } | 2388 | } |
2389 | } | ||
2218 | /* | 2390 | /* |
2219 | * If we've found the command, take it off the | 2391 | * If we've found the command, take it off the |
2220 | * completion Q and free it | 2392 | * completion Q and free it |
@@ -2634,12 +2806,16 @@ static void cciss_getgeometry(int cntl_num) | |||
2634 | #endif /* CCISS_DEBUG */ | 2806 | #endif /* CCISS_DEBUG */ |
2635 | 2807 | ||
2636 | hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1; | 2808 | hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1; |
2637 | for(i=0; i< hba[cntl_num]->num_luns; i++) | 2809 | // for(i=0; i< hba[cntl_num]->num_luns; i++) |
2810 | for(i=0; i < CISS_MAX_LUN; i++) | ||
2638 | { | 2811 | { |
2639 | 2812 | if (i < hba[cntl_num]->num_luns){ | |
2640 | lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24; | 2813 | lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) |
2641 | lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16; | 2814 | << 24; |
2642 | lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8; | 2815 | lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) |
2816 | << 16; | ||
2817 | lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) | ||
2818 | << 8; | ||
2643 | lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); | 2819 | lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]); |
2644 | 2820 | ||
2645 | hba[cntl_num]->drv[i].LunID = lunid; | 2821 | hba[cntl_num]->drv[i].LunID = lunid; |
@@ -2647,13 +2823,18 @@ static void cciss_getgeometry(int cntl_num) | |||
2647 | 2823 | ||
2648 | #ifdef CCISS_DEBUG | 2824 | #ifdef CCISS_DEBUG |
2649 | printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i, | 2825 | printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i, |
2650 | ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], | 2826 | ld_buff->LUN[i][0], ld_buff->LUN[i][1], |
2651 | ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID); | 2827 | ld_buff->LUN[i][2], ld_buff->LUN[i][3], |
2828 | hba[cntl_num]->drv[i].LunID); | ||
2652 | #endif /* CCISS_DEBUG */ | 2829 | #endif /* CCISS_DEBUG */ |
2653 | cciss_read_capacity(cntl_num, i, size_buff, 0, | 2830 | cciss_read_capacity(cntl_num, i, size_buff, 0, |
2654 | &total_size, &block_size); | 2831 | &total_size, &block_size); |
2655 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size, | 2832 | cciss_geometry_inquiry(cntl_num, i, 0, total_size, |
2656 | inq_buff, &hba[cntl_num]->drv[i]); | 2833 | block_size, inq_buff, &hba[cntl_num]->drv[i]); |
2834 | } else { | ||
2835 | /* initialize raid_level to indicate a free space */ | ||
2836 | hba[cntl_num]->drv[i].raid_level = -1; | ||
2837 | } | ||
2657 | } | 2838 | } |
2658 | kfree(ld_buff); | 2839 | kfree(ld_buff); |
2659 | kfree(size_buff); | 2840 | kfree(size_buff); |
@@ -2727,6 +2908,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
2727 | i = alloc_cciss_hba(); | 2908 | i = alloc_cciss_hba(); |
2728 | if(i < 0) | 2909 | if(i < 0) |
2729 | return (-1); | 2910 | return (-1); |
2911 | |||
2912 | hba[i]->busy_initializing = 1; | ||
2913 | |||
2730 | if (cciss_pci_init(hba[i], pdev) != 0) | 2914 | if (cciss_pci_init(hba[i], pdev) != 0) |
2731 | goto clean1; | 2915 | goto clean1; |
2732 | 2916 | ||
@@ -2849,6 +3033,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
2849 | add_disk(disk); | 3033 | add_disk(disk); |
2850 | } | 3034 | } |
2851 | 3035 | ||
3036 | hba[i]->busy_initializing = 0; | ||
2852 | return(1); | 3037 | return(1); |
2853 | 3038 | ||
2854 | clean4: | 3039 | clean4: |
@@ -2869,6 +3054,7 @@ clean2: | |||
2869 | clean1: | 3054 | clean1: |
2870 | release_io_mem(hba[i]); | 3055 | release_io_mem(hba[i]); |
2871 | free_hba(i); | 3056 | free_hba(i); |
3057 | hba[i]->busy_initializing = 0; | ||
2872 | return(-1); | 3058 | return(-1); |
2873 | } | 3059 | } |
2874 | 3060 | ||
@@ -2913,9 +3099,10 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev) | |||
2913 | /* remove it from the disk list */ | 3099 | /* remove it from the disk list */ |
2914 | for (j = 0; j < NWD; j++) { | 3100 | for (j = 0; j < NWD; j++) { |
2915 | struct gendisk *disk = hba[i]->gendisk[j]; | 3101 | struct gendisk *disk = hba[i]->gendisk[j]; |
2916 | if (disk->flags & GENHD_FL_UP) | 3102 | if (disk->flags & GENHD_FL_UP) { |
2917 | blk_cleanup_queue(disk->queue); | ||
2918 | del_gendisk(disk); | 3103 | del_gendisk(disk); |
3104 | blk_cleanup_queue(disk->queue); | ||
3105 | } | ||
2919 | } | 3106 | } |
2920 | 3107 | ||
2921 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), | 3108 | pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), |
@@ -2964,5 +3151,43 @@ static void __exit cciss_cleanup(void) | |||
2964 | remove_proc_entry("cciss", proc_root_driver); | 3151 | remove_proc_entry("cciss", proc_root_driver); |
2965 | } | 3152 | } |
2966 | 3153 | ||
3154 | static void fail_all_cmds(unsigned long ctlr) | ||
3155 | { | ||
3156 | /* If we get here, the board is apparently dead. */ | ||
3157 | ctlr_info_t *h = hba[ctlr]; | ||
3158 | CommandList_struct *c; | ||
3159 | unsigned long flags; | ||
3160 | |||
3161 | printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr); | ||
3162 | h->alive = 0; /* the controller apparently died... */ | ||
3163 | |||
3164 | spin_lock_irqsave(CCISS_LOCK(ctlr), flags); | ||
3165 | |||
3166 | pci_disable_device(h->pdev); /* Make sure it is really dead. */ | ||
3167 | |||
3168 | /* move everything off the request queue onto the completed queue */ | ||
3169 | while( (c = h->reqQ) != NULL ) { | ||
3170 | removeQ(&(h->reqQ), c); | ||
3171 | h->Qdepth--; | ||
3172 | addQ (&(h->cmpQ), c); | ||
3173 | } | ||
3174 | |||
3175 | /* Now, fail everything on the completed queue with a HW error */ | ||
3176 | while( (c = h->cmpQ) != NULL ) { | ||
3177 | removeQ(&h->cmpQ, c); | ||
3178 | c->err_info->CommandStatus = CMD_HARDWARE_ERR; | ||
3179 | if (c->cmd_type == CMD_RWREQ) { | ||
3180 | complete_command(h, c, 0); | ||
3181 | } else if (c->cmd_type == CMD_IOCTL_PEND) | ||
3182 | complete(c->waiting); | ||
3183 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
3184 | else if (c->cmd_type == CMD_SCSI) | ||
3185 | complete_scsi_command(c, 0, 0); | ||
3186 | #endif | ||
3187 | } | ||
3188 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | ||
3189 | return; | ||
3190 | } | ||
3191 | |||
2967 | module_init(cciss_init); | 3192 | module_init(cciss_init); |
2968 | module_exit(cciss_cleanup); | 3193 | module_exit(cciss_cleanup); |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 566587d0a500..ef277baee9fd 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
@@ -35,7 +35,13 @@ typedef struct _drive_info_struct | |||
35 | int heads; | 35 | int heads; |
36 | int sectors; | 36 | int sectors; |
37 | int cylinders; | 37 | int cylinders; |
38 | int raid_level; | 38 | int raid_level; /* set to -1 to indicate that |
39 | * the drive is not in use/configured | ||
40 | */ | ||
41 | int busy_configuring; /*This is set when the drive is being removed | ||
42 | *to prevent it from being opened or it's queue | ||
43 | *from being started. | ||
44 | */ | ||
39 | } drive_info_struct; | 45 | } drive_info_struct; |
40 | 46 | ||
41 | struct ctlr_info | 47 | struct ctlr_info |
@@ -83,6 +89,7 @@ struct ctlr_info | |||
83 | int nr_allocs; | 89 | int nr_allocs; |
84 | int nr_frees; | 90 | int nr_frees; |
85 | int busy_configuring; | 91 | int busy_configuring; |
92 | int busy_initializing; | ||
86 | 93 | ||
87 | /* This element holds the zero based queue number of the last | 94 | /* This element holds the zero based queue number of the last |
88 | * queue to be started. It is used for fairness. | 95 | * queue to be started. It is used for fairness. |
@@ -94,6 +101,7 @@ struct ctlr_info | |||
94 | #ifdef CONFIG_CISS_SCSI_TAPE | 101 | #ifdef CONFIG_CISS_SCSI_TAPE |
95 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ | 102 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ |
96 | #endif | 103 | #endif |
104 | unsigned char alive; | ||
97 | }; | 105 | }; |
98 | 106 | ||
99 | /* Defining the diffent access_menthods */ | 107 | /* Defining the diffent access_menthods */ |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index a88a88817623..53fea549ba8b 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct { | |||
226 | #define CMD_MSG_DONE 0x04 | 226 | #define CMD_MSG_DONE 0x04 |
227 | #define CMD_MSG_TIMEOUT 0x05 | 227 | #define CMD_MSG_TIMEOUT 0x05 |
228 | 228 | ||
229 | /* This structure needs to be divisible by 8 for new | ||
230 | * indexing method. | ||
231 | */ | ||
232 | #define PADSIZE (sizeof(long) - 4) | ||
229 | typedef struct _CommandList_struct { | 233 | typedef struct _CommandList_struct { |
230 | CommandListHeader_struct Header; | 234 | CommandListHeader_struct Header; |
231 | RequestBlock_struct Request; | 235 | RequestBlock_struct Request; |
@@ -236,14 +240,14 @@ typedef struct _CommandList_struct { | |||
236 | ErrorInfo_struct * err_info; /* pointer to the allocated mem */ | 240 | ErrorInfo_struct * err_info; /* pointer to the allocated mem */ |
237 | int ctlr; | 241 | int ctlr; |
238 | int cmd_type; | 242 | int cmd_type; |
243 | long cmdindex; | ||
239 | struct _CommandList_struct *prev; | 244 | struct _CommandList_struct *prev; |
240 | struct _CommandList_struct *next; | 245 | struct _CommandList_struct *next; |
241 | struct request * rq; | 246 | struct request * rq; |
242 | struct completion *waiting; | 247 | struct completion *waiting; |
243 | int retry_count; | 248 | int retry_count; |
244 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
245 | void * scsi_cmd; | 249 | void * scsi_cmd; |
246 | #endif | 250 | char pad[PADSIZE]; |
247 | } CommandList_struct; | 251 | } CommandList_struct; |
248 | 252 | ||
249 | //Configuration Table Structure | 253 | //Configuration Table Structure |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index f16e3caed58a..e183a3ef7839 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t { | |||
93 | CommandList_struct cmd; | 93 | CommandList_struct cmd; |
94 | ErrorInfo_struct Err; | 94 | ErrorInfo_struct Err; |
95 | __u32 busaddr; | 95 | __u32 busaddr; |
96 | __u32 pad; | ||
96 | }; | 97 | }; |
97 | 98 | ||
98 | #pragma pack() | 99 | #pragma pack() |
@@ -877,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp) | |||
877 | 878 | ||
878 | static int | 879 | static int |
879 | cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, | 880 | cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, |
880 | InquiryData_struct *buf) | 881 | unsigned char *buf, unsigned char bufsize) |
881 | { | 882 | { |
882 | int rc; | 883 | int rc; |
883 | CommandList_struct *cp; | 884 | CommandList_struct *cp; |
@@ -900,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr, | |||
900 | cdb[1] = 0; | 901 | cdb[1] = 0; |
901 | cdb[2] = 0; | 902 | cdb[2] = 0; |
902 | cdb[3] = 0; | 903 | cdb[3] = 0; |
903 | cdb[4] = sizeof(*buf) & 0xff; | 904 | cdb[4] = bufsize; |
904 | cdb[5] = 0; | 905 | cdb[5] = 0; |
905 | rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, | 906 | rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb, |
906 | 6, (unsigned char *) buf, | 907 | 6, buf, bufsize, XFER_READ); |
907 | sizeof(*buf), XFER_READ); | ||
908 | 908 | ||
909 | if (rc != 0) return rc; /* something went wrong */ | 909 | if (rc != 0) return rc; /* something went wrong */ |
910 | 910 | ||
@@ -1000,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
1000 | that though. | 1000 | that though. |
1001 | 1001 | ||
1002 | */ | 1002 | */ |
1003 | 1003 | #define OBDR_TAPE_INQ_SIZE 49 | |
1004 | #define OBDR_TAPE_SIG "$DR-10" | ||
1004 | ReportLunData_struct *ld_buff; | 1005 | ReportLunData_struct *ld_buff; |
1005 | InquiryData_struct *inq_buff; | 1006 | unsigned char *inq_buff; |
1006 | unsigned char scsi3addr[8]; | 1007 | unsigned char scsi3addr[8]; |
1007 | ctlr_info_t *c; | 1008 | ctlr_info_t *c; |
1008 | __u32 num_luns=0; | 1009 | __u32 num_luns=0; |
@@ -1020,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
1020 | return; | 1021 | return; |
1021 | } | 1022 | } |
1022 | memset(ld_buff, 0, reportlunsize); | 1023 | memset(ld_buff, 0, reportlunsize); |
1023 | inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL); | 1024 | inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL); |
1024 | if (inq_buff == NULL) { | 1025 | if (inq_buff == NULL) { |
1025 | printk(KERN_ERR "cciss: out of memory\n"); | 1026 | printk(KERN_ERR "cciss: out of memory\n"); |
1026 | kfree(ld_buff); | 1027 | kfree(ld_buff); |
@@ -1051,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) | |||
1051 | 1052 | ||
1052 | /* for each physical lun, do an inquiry */ | 1053 | /* for each physical lun, do an inquiry */ |
1053 | if (ld_buff->LUN[i][3] & 0xC0) continue; | 1054 | if (ld_buff->LUN[i][3] & 0xC0) continue; |
1054 | memset(inq_buff, 0, sizeof(InquiryData_struct)); | 1055 | memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE); |
1055 | memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); | 1056 | memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8); |
1056 | 1057 | ||
1057 | if (cciss_scsi_do_inquiry(hba[cntl_num], | 1058 | if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff, |
1058 | scsi3addr, inq_buff) != 0) | 1059 | (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) { |
1059 | { | ||
1060 | /* Inquiry failed (msg printed already) */ | 1060 | /* Inquiry failed (msg printed already) */ |
1061 | devtype = 0; /* so we will skip this device. */ | 1061 | devtype = 0; /* so we will skip this device. */ |
1062 | } else /* what kind of device is this? */ | 1062 | } else /* what kind of device is this? */ |
1063 | devtype = (inq_buff->data_byte[0] & 0x1f); | 1063 | devtype = (inq_buff[0] & 0x1f); |
1064 | 1064 | ||
1065 | switch (devtype) | 1065 | switch (devtype) |
1066 | { | 1066 | { |
1067 | case 0x05: /* CD-ROM */ { | ||
1068 | |||
1069 | /* We don't *really* support actual CD-ROM devices, | ||
1070 | * just this "One Button Disaster Recovery" tape drive | ||
1071 | * which temporarily pretends to be a CD-ROM drive. | ||
1072 | * So we check that the device is really an OBDR tape | ||
1073 | * device by checking for "$DR-10" in bytes 43-48 of | ||
1074 | * the inquiry data. | ||
1075 | */ | ||
1076 | char obdr_sig[7]; | ||
1077 | |||
1078 | strncpy(obdr_sig, &inq_buff[43], 6); | ||
1079 | obdr_sig[6] = '\0'; | ||
1080 | if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0) | ||
1081 | /* Not OBDR device, ignore it. */ | ||
1082 | break; | ||
1083 | } | ||
1084 | /* fall through . . . */ | ||
1067 | case 0x01: /* sequential access, (tape) */ | 1085 | case 0x01: /* sequential access, (tape) */ |
1068 | case 0x08: /* medium changer */ | 1086 | case 0x08: /* medium changer */ |
1069 | if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { | 1087 | if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) { |
@@ -1126,6 +1144,7 @@ cciss_scsi_proc_info(struct Scsi_Host *sh, | |||
1126 | 1144 | ||
1127 | int buflen, datalen; | 1145 | int buflen, datalen; |
1128 | ctlr_info_t *ci; | 1146 | ctlr_info_t *ci; |
1147 | int i; | ||
1129 | int cntl_num; | 1148 | int cntl_num; |
1130 | 1149 | ||
1131 | 1150 | ||
@@ -1136,8 +1155,28 @@ cciss_scsi_proc_info(struct Scsi_Host *sh, | |||
1136 | cntl_num = ci->ctlr; /* Get our index into the hba[] array */ | 1155 | cntl_num = ci->ctlr; /* Get our index into the hba[] array */ |
1137 | 1156 | ||
1138 | if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */ | 1157 | if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */ |
1139 | buflen = sprintf(buffer, "hostnum=%d\n", sh->host_no); | 1158 | buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n", |
1140 | 1159 | cntl_num, sh->host_no); | |
1160 | |||
1161 | /* this information is needed by apps to know which cciss | ||
1162 | device corresponds to which scsi host number without | ||
1163 | having to open a scsi target device node. The device | ||
1164 | information is not a duplicate of /proc/scsi/scsi because | ||
1165 | the two may be out of sync due to scsi hotplug, rather | ||
1166 | this info is for an app to be able to use to know how to | ||
1167 | get them back in sync. */ | ||
1168 | |||
1169 | for (i=0;i<ccissscsi[cntl_num].ndevices;i++) { | ||
1170 | struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i]; | ||
1171 | buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d " | ||
1172 | "0x%02x%02x%02x%02x%02x%02x%02x%02x\n", | ||
1173 | sh->host_no, sd->bus, sd->target, sd->lun, | ||
1174 | sd->devtype, | ||
1175 | sd->scsi3addr[0], sd->scsi3addr[1], | ||
1176 | sd->scsi3addr[2], sd->scsi3addr[3], | ||
1177 | sd->scsi3addr[4], sd->scsi3addr[5], | ||
1178 | sd->scsi3addr[6], sd->scsi3addr[7]); | ||
1179 | } | ||
1141 | datalen = buflen - offset; | 1180 | datalen = buflen - offset; |
1142 | if (datalen < 0) { /* they're reading past EOF. */ | 1181 | if (datalen < 0) { /* they're reading past EOF. */ |
1143 | datalen = 0; | 1182 | datalen = 0; |
@@ -1399,7 +1438,7 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) | |||
1399 | 1438 | ||
1400 | CPQ_TAPE_LOCK(ctlr, flags); | 1439 | CPQ_TAPE_LOCK(ctlr, flags); |
1401 | size = sprintf(buffer + *len, | 1440 | size = sprintf(buffer + *len, |
1402 | " Sequential access devices: %d\n\n", | 1441 | "Sequential access devices: %d\n\n", |
1403 | ccissscsi[ctlr].ndevices); | 1442 | ccissscsi[ctlr].ndevices); |
1404 | CPQ_TAPE_UNLOCK(ctlr, flags); | 1443 | CPQ_TAPE_UNLOCK(ctlr, flags); |
1405 | *pos += size; *len += size; | 1444 | *pos += size; *len += size; |
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 711d2f314ac3..94af920465b5 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c | |||
@@ -750,6 +750,14 @@ static int pf_ready(void) | |||
750 | 750 | ||
751 | static struct request_queue *pf_queue; | 751 | static struct request_queue *pf_queue; |
752 | 752 | ||
753 | static void pf_end_request(int uptodate) | ||
754 | { | ||
755 | if (pf_req) { | ||
756 | end_request(pf_req, uptodate); | ||
757 | pf_req = NULL; | ||
758 | } | ||
759 | } | ||
760 | |||
753 | static void do_pf_request(request_queue_t * q) | 761 | static void do_pf_request(request_queue_t * q) |
754 | { | 762 | { |
755 | if (pf_busy) | 763 | if (pf_busy) |
@@ -765,7 +773,7 @@ repeat: | |||
765 | pf_count = pf_req->current_nr_sectors; | 773 | pf_count = pf_req->current_nr_sectors; |
766 | 774 | ||
767 | if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { | 775 | if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { |
768 | end_request(pf_req, 0); | 776 | pf_end_request(0); |
769 | goto repeat; | 777 | goto repeat; |
770 | } | 778 | } |
771 | 779 | ||
@@ -780,7 +788,7 @@ repeat: | |||
780 | pi_do_claimed(pf_current->pi, do_pf_write); | 788 | pi_do_claimed(pf_current->pi, do_pf_write); |
781 | else { | 789 | else { |
782 | pf_busy = 0; | 790 | pf_busy = 0; |
783 | end_request(pf_req, 0); | 791 | pf_end_request(0); |
784 | goto repeat; | 792 | goto repeat; |
785 | } | 793 | } |
786 | } | 794 | } |
@@ -798,9 +806,11 @@ static int pf_next_buf(void) | |||
798 | if (!pf_count) | 806 | if (!pf_count) |
799 | return 1; | 807 | return 1; |
800 | spin_lock_irqsave(&pf_spin_lock, saved_flags); | 808 | spin_lock_irqsave(&pf_spin_lock, saved_flags); |
801 | end_request(pf_req, 1); | 809 | pf_end_request(1); |
802 | pf_count = pf_req->current_nr_sectors; | 810 | if (pf_req) { |
803 | pf_buf = pf_req->buffer; | 811 | pf_count = pf_req->current_nr_sectors; |
812 | pf_buf = pf_req->buffer; | ||
813 | } | ||
804 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); | 814 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); |
805 | return 1; | 815 | return 1; |
806 | } | 816 | } |
@@ -810,7 +820,7 @@ static inline void next_request(int success) | |||
810 | unsigned long saved_flags; | 820 | unsigned long saved_flags; |
811 | 821 | ||
812 | spin_lock_irqsave(&pf_spin_lock, saved_flags); | 822 | spin_lock_irqsave(&pf_spin_lock, saved_flags); |
813 | end_request(pf_req, success); | 823 | pf_end_request(success); |
814 | pf_busy = 0; | 824 | pf_busy = 0; |
815 | do_pf_request(pf_queue); | 825 | do_pf_request(pf_queue); |
816 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); | 826 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 7b838342f0a3..7e22a58926b8 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -5,29 +5,41 @@ | |||
5 | * May be copied or modified under the terms of the GNU General Public | 5 | * May be copied or modified under the terms of the GNU General Public |
6 | * License. See linux/COPYING for more information. | 6 | * License. See linux/COPYING for more information. |
7 | * | 7 | * |
8 | * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and | 8 | * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and |
9 | * DVD-RW devices (aka an exercise in block layer masturbation) | 9 | * DVD-RAM devices. |
10 | * | 10 | * |
11 | * Theory of operation: | ||
11 | * | 12 | * |
12 | * TODO: (circa order of when I will fix it) | 13 | * At the lowest level, there is the standard driver for the CD/DVD device, |
13 | * - Only able to write on CD-RW media right now. | 14 | * typically ide-cd.c or sr.c. This driver can handle read and write requests, |
14 | * - check host application code on media and set it in write page | 15 | * but it doesn't know anything about the special restrictions that apply to |
15 | * - interface for UDF <-> packet to negotiate a new location when a write | 16 | * packet writing. One restriction is that write requests must be aligned to |
16 | * fails. | 17 | * packet boundaries on the physical media, and the size of a write request |
17 | * - handle OPC, especially for -RW media | 18 | * must be equal to the packet size. Another restriction is that a |
19 | * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read | ||
20 | * command, if the previous command was a write. | ||
18 | * | 21 | * |
19 | * Theory of operation: | 22 | * The purpose of the packet writing driver is to hide these restrictions from |
23 | * higher layers, such as file systems, and present a block device that can be | ||
24 | * randomly read and written using 2kB-sized blocks. | ||
25 | * | ||
26 | * The lowest layer in the packet writing driver is the packet I/O scheduler. | ||
27 | * Its data is defined by the struct packet_iosched and includes two bio | ||
28 | * queues with pending read and write requests. These queues are processed | ||
29 | * by the pkt_iosched_process_queue() function. The write requests in this | ||
30 | * queue are already properly aligned and sized. This layer is responsible for | ||
31 | * issuing the flush cache commands and scheduling the I/O in a good order. | ||
20 | * | 32 | * |
21 | * We use a custom make_request_fn function that forwards reads directly to | 33 | * The next layer transforms unaligned write requests to aligned writes. This |
22 | * the underlying CD device. Write requests are either attached directly to | 34 | * transformation requires reading missing pieces of data from the underlying |
23 | * a live packet_data object, or simply stored sequentially in a list for | 35 | * block device, assembling the pieces to full packets and queuing them to the |
24 | * later processing by the kcdrwd kernel thread. This driver doesn't use | 36 | * packet I/O scheduler. |
25 | * any elevator functionally as defined by the elevator_s struct, but the | ||
26 | * underlying CD device uses a standard elevator. | ||
27 | * | 37 | * |
28 | * This strategy makes it possible to do very late merging of IO requests. | 38 | * At the top layer there is a custom make_request_fn function that forwards |
29 | * A new bio sent to pkt_make_request can be merged with a live packet_data | 39 | * read requests directly to the iosched queue and puts write requests in the |
30 | * object even if the object is in the data gathering state. | 40 | * unaligned write queue. A kernel thread performs the necessary read |
41 | * gathering to convert the unaligned writes to aligned writes and then feeds | ||
42 | * them to the packet I/O scheduler. | ||
31 | * | 43 | * |
32 | *************************************************************************/ | 44 | *************************************************************************/ |
33 | 45 | ||
@@ -100,10 +112,9 @@ static struct bio *pkt_bio_alloc(int nr_iovecs) | |||
100 | goto no_bio; | 112 | goto no_bio; |
101 | bio_init(bio); | 113 | bio_init(bio); |
102 | 114 | ||
103 | bvl = kmalloc(nr_iovecs * sizeof(struct bio_vec), GFP_KERNEL); | 115 | bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL); |
104 | if (!bvl) | 116 | if (!bvl) |
105 | goto no_bvl; | 117 | goto no_bvl; |
106 | memset(bvl, 0, nr_iovecs * sizeof(struct bio_vec)); | ||
107 | 118 | ||
108 | bio->bi_max_vecs = nr_iovecs; | 119 | bio->bi_max_vecs = nr_iovecs; |
109 | bio->bi_io_vec = bvl; | 120 | bio->bi_io_vec = bvl; |
@@ -125,10 +136,9 @@ static struct packet_data *pkt_alloc_packet_data(void) | |||
125 | int i; | 136 | int i; |
126 | struct packet_data *pkt; | 137 | struct packet_data *pkt; |
127 | 138 | ||
128 | pkt = kmalloc(sizeof(struct packet_data), GFP_KERNEL); | 139 | pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL); |
129 | if (!pkt) | 140 | if (!pkt) |
130 | goto no_pkt; | 141 | goto no_pkt; |
131 | memset(pkt, 0, sizeof(struct packet_data)); | ||
132 | 142 | ||
133 | pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE); | 143 | pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE); |
134 | if (!pkt->w_bio) | 144 | if (!pkt->w_bio) |
@@ -659,7 +669,6 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in | |||
659 | } | 669 | } |
660 | offs += CD_FRAMESIZE; | 670 | offs += CD_FRAMESIZE; |
661 | if (offs >= PAGE_SIZE) { | 671 | if (offs >= PAGE_SIZE) { |
662 | BUG_ON(offs > PAGE_SIZE); | ||
663 | offs = 0; | 672 | offs = 0; |
664 | p++; | 673 | p++; |
665 | } | 674 | } |
@@ -724,12 +733,6 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
724 | atomic_set(&pkt->io_wait, 0); | 733 | atomic_set(&pkt->io_wait, 0); |
725 | atomic_set(&pkt->io_errors, 0); | 734 | atomic_set(&pkt->io_errors, 0); |
726 | 735 | ||
727 | if (pkt->cache_valid) { | ||
728 | VPRINTK("pkt_gather_data: zone %llx cached\n", | ||
729 | (unsigned long long)pkt->sector); | ||
730 | goto out_account; | ||
731 | } | ||
732 | |||
733 | /* | 736 | /* |
734 | * Figure out which frames we need to read before we can write. | 737 | * Figure out which frames we need to read before we can write. |
735 | */ | 738 | */ |
@@ -738,6 +741,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
738 | for (bio = pkt->orig_bios; bio; bio = bio->bi_next) { | 741 | for (bio = pkt->orig_bios; bio; bio = bio->bi_next) { |
739 | int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9); | 742 | int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9); |
740 | int num_frames = bio->bi_size / CD_FRAMESIZE; | 743 | int num_frames = bio->bi_size / CD_FRAMESIZE; |
744 | pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9); | ||
741 | BUG_ON(first_frame < 0); | 745 | BUG_ON(first_frame < 0); |
742 | BUG_ON(first_frame + num_frames > pkt->frames); | 746 | BUG_ON(first_frame + num_frames > pkt->frames); |
743 | for (f = first_frame; f < first_frame + num_frames; f++) | 747 | for (f = first_frame; f < first_frame + num_frames; f++) |
@@ -745,6 +749,12 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
745 | } | 749 | } |
746 | spin_unlock(&pkt->lock); | 750 | spin_unlock(&pkt->lock); |
747 | 751 | ||
752 | if (pkt->cache_valid) { | ||
753 | VPRINTK("pkt_gather_data: zone %llx cached\n", | ||
754 | (unsigned long long)pkt->sector); | ||
755 | goto out_account; | ||
756 | } | ||
757 | |||
748 | /* | 758 | /* |
749 | * Schedule reads for missing parts of the packet. | 759 | * Schedule reads for missing parts of the packet. |
750 | */ | 760 | */ |
@@ -778,7 +788,6 @@ out_account: | |||
778 | frames_read, (unsigned long long)pkt->sector); | 788 | frames_read, (unsigned long long)pkt->sector); |
779 | pd->stats.pkt_started++; | 789 | pd->stats.pkt_started++; |
780 | pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9); | 790 | pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9); |
781 | pd->stats.secs_w += pd->settings.size; | ||
782 | } | 791 | } |
783 | 792 | ||
784 | /* | 793 | /* |
@@ -794,10 +803,11 @@ static struct packet_data *pkt_get_packet_data(struct pktcdvd_device *pd, int zo | |||
794 | list_del_init(&pkt->list); | 803 | list_del_init(&pkt->list); |
795 | if (pkt->sector != zone) | 804 | if (pkt->sector != zone) |
796 | pkt->cache_valid = 0; | 805 | pkt->cache_valid = 0; |
797 | break; | 806 | return pkt; |
798 | } | 807 | } |
799 | } | 808 | } |
800 | return pkt; | 809 | BUG(); |
810 | return NULL; | ||
801 | } | 811 | } |
802 | 812 | ||
803 | static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt) | 813 | static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt) |
@@ -941,12 +951,10 @@ try_next_bio: | |||
941 | } | 951 | } |
942 | 952 | ||
943 | pkt = pkt_get_packet_data(pd, zone); | 953 | pkt = pkt_get_packet_data(pd, zone); |
944 | BUG_ON(!pkt); | ||
945 | 954 | ||
946 | pd->current_sector = zone + pd->settings.size; | 955 | pd->current_sector = zone + pd->settings.size; |
947 | pkt->sector = zone; | 956 | pkt->sector = zone; |
948 | pkt->frames = pd->settings.size >> 2; | 957 | pkt->frames = pd->settings.size >> 2; |
949 | BUG_ON(pkt->frames > PACKET_MAX_SIZE); | ||
950 | pkt->write_size = 0; | 958 | pkt->write_size = 0; |
951 | 959 | ||
952 | /* | 960 | /* |
@@ -1636,6 +1644,10 @@ static int pkt_probe_settings(struct pktcdvd_device *pd) | |||
1636 | printk("pktcdvd: detected zero packet size!\n"); | 1644 | printk("pktcdvd: detected zero packet size!\n"); |
1637 | pd->settings.size = 128; | 1645 | pd->settings.size = 128; |
1638 | } | 1646 | } |
1647 | if (pd->settings.size > PACKET_MAX_SECTORS) { | ||
1648 | printk("pktcdvd: packet size is too big\n"); | ||
1649 | return -ENXIO; | ||
1650 | } | ||
1639 | pd->settings.fp = ti.fp; | 1651 | pd->settings.fp = ti.fp; |
1640 | pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1); | 1652 | pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1); |
1641 | 1653 | ||
@@ -2198,7 +2210,6 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio) | |||
2198 | * No matching packet found. Store the bio in the work queue. | 2210 | * No matching packet found. Store the bio in the work queue. |
2199 | */ | 2211 | */ |
2200 | node = mempool_alloc(pd->rb_pool, GFP_NOIO); | 2212 | node = mempool_alloc(pd->rb_pool, GFP_NOIO); |
2201 | BUG_ON(!node); | ||
2202 | node->bio = bio; | 2213 | node->bio = bio; |
2203 | spin_lock(&pd->lock); | 2214 | spin_lock(&pd->lock); |
2204 | BUG_ON(pd->bio_queue_size < 0); | 2215 | BUG_ON(pd->bio_queue_size < 0); |
@@ -2406,7 +2417,6 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u | |||
2406 | struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data; | 2417 | struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data; |
2407 | 2418 | ||
2408 | VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode)); | 2419 | VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode)); |
2409 | BUG_ON(!pd); | ||
2410 | 2420 | ||
2411 | switch (cmd) { | 2421 | switch (cmd) { |
2412 | /* | 2422 | /* |
@@ -2477,10 +2487,9 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd) | |||
2477 | return -EBUSY; | 2487 | return -EBUSY; |
2478 | } | 2488 | } |
2479 | 2489 | ||
2480 | pd = kmalloc(sizeof(struct pktcdvd_device), GFP_KERNEL); | 2490 | pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL); |
2481 | if (!pd) | 2491 | if (!pd) |
2482 | return ret; | 2492 | return ret; |
2483 | memset(pd, 0, sizeof(struct pktcdvd_device)); | ||
2484 | 2493 | ||
2485 | pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL); | 2494 | pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL); |
2486 | if (!pd->rb_pool) | 2495 | if (!pd->rb_pool) |
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 856c2278e9d0..079ec344eb47 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c | |||
@@ -168,6 +168,7 @@ static int verify_command(struct file *file, unsigned char *cmd) | |||
168 | safe_for_write(WRITE_VERIFY_12), | 168 | safe_for_write(WRITE_VERIFY_12), |
169 | safe_for_write(WRITE_16), | 169 | safe_for_write(WRITE_16), |
170 | safe_for_write(WRITE_LONG), | 170 | safe_for_write(WRITE_LONG), |
171 | safe_for_write(WRITE_LONG_2), | ||
171 | safe_for_write(ERASE), | 172 | safe_for_write(ERASE), |
172 | safe_for_write(GPCMD_MODE_SELECT_10), | 173 | safe_for_write(GPCMD_MODE_SELECT_10), |
173 | safe_for_write(MODE_SELECT), | 174 | safe_for_write(MODE_SELECT), |
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 67d96b5cbb96..57c48bbf6fe6 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c | |||
@@ -65,13 +65,15 @@ | |||
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | static int ignore = 0; | 67 | static int ignore = 0; |
68 | static int ignore_csr = 0; | ||
69 | static int ignore_sniffer = 0; | ||
68 | static int reset = 0; | 70 | static int reset = 0; |
69 | 71 | ||
70 | #ifdef CONFIG_BT_HCIUSB_SCO | 72 | #ifdef CONFIG_BT_HCIUSB_SCO |
71 | static int isoc = 2; | 73 | static int isoc = 2; |
72 | #endif | 74 | #endif |
73 | 75 | ||
74 | #define VERSION "2.8" | 76 | #define VERSION "2.9" |
75 | 77 | ||
76 | static struct usb_driver hci_usb_driver; | 78 | static struct usb_driver hci_usb_driver; |
77 | 79 | ||
@@ -98,6 +100,9 @@ static struct usb_device_id bluetooth_ids[] = { | |||
98 | MODULE_DEVICE_TABLE (usb, bluetooth_ids); | 100 | MODULE_DEVICE_TABLE (usb, bluetooth_ids); |
99 | 101 | ||
100 | static struct usb_device_id blacklist_ids[] = { | 102 | static struct usb_device_id blacklist_ids[] = { |
103 | /* CSR BlueCore devices */ | ||
104 | { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR }, | ||
105 | |||
101 | /* Broadcom BCM2033 without firmware */ | 106 | /* Broadcom BCM2033 without firmware */ |
102 | { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, | 107 | { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, |
103 | 108 | ||
@@ -836,6 +841,12 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id | |||
836 | if (ignore || id->driver_info & HCI_IGNORE) | 841 | if (ignore || id->driver_info & HCI_IGNORE) |
837 | return -ENODEV; | 842 | return -ENODEV; |
838 | 843 | ||
844 | if (ignore_csr && id->driver_info & HCI_CSR) | ||
845 | return -ENODEV; | ||
846 | |||
847 | if (ignore_sniffer && id->driver_info & HCI_SNIFFER) | ||
848 | return -ENODEV; | ||
849 | |||
839 | if (intf->cur_altsetting->desc.bInterfaceNumber > 0) | 850 | if (intf->cur_altsetting->desc.bInterfaceNumber > 0) |
840 | return -ENODEV; | 851 | return -ENODEV; |
841 | 852 | ||
@@ -1061,6 +1072,12 @@ module_exit(hci_usb_exit); | |||
1061 | module_param(ignore, bool, 0644); | 1072 | module_param(ignore, bool, 0644); |
1062 | MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); | 1073 | MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); |
1063 | 1074 | ||
1075 | module_param(ignore_csr, bool, 0644); | ||
1076 | MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001"); | ||
1077 | |||
1078 | module_param(ignore_sniffer, bool, 0644); | ||
1079 | MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002"); | ||
1080 | |||
1064 | module_param(reset, bool, 0644); | 1081 | module_param(reset, bool, 0644); |
1065 | MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); | 1082 | MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); |
1066 | 1083 | ||
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h index 29936b43d4f8..37100a6ea1a8 100644 --- a/drivers/bluetooth/hci_usb.h +++ b/drivers/bluetooth/hci_usb.h | |||
@@ -31,9 +31,10 @@ | |||
31 | #define HCI_IGNORE 0x01 | 31 | #define HCI_IGNORE 0x01 |
32 | #define HCI_RESET 0x02 | 32 | #define HCI_RESET 0x02 |
33 | #define HCI_DIGIANSWER 0x04 | 33 | #define HCI_DIGIANSWER 0x04 |
34 | #define HCI_SNIFFER 0x08 | 34 | #define HCI_CSR 0x08 |
35 | #define HCI_BROKEN_ISOC 0x10 | 35 | #define HCI_SNIFFER 0x10 |
36 | #define HCI_BCM92035 0x20 | 36 | #define HCI_BCM92035 0x20 |
37 | #define HCI_BROKEN_ISOC 0x40 | ||
37 | 38 | ||
38 | #define HCI_MAX_IFACE_NUM 3 | 39 | #define HCI_MAX_IFACE_NUM 3 |
39 | 40 | ||
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 99762b6c19ae..de5d6d212674 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c | |||
@@ -252,7 +252,7 @@ hp_zx1_configure (void) | |||
252 | readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); | 252 | readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); |
253 | writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); | 253 | writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); |
254 | readl(hp->ioc_regs+HP_ZX1_TCNFG); | 254 | readl(hp->ioc_regs+HP_ZX1_TCNFG); |
255 | writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK); | 255 | writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK); |
256 | readl(hp->ioc_regs+HP_ZX1_IMASK); | 256 | readl(hp->ioc_regs+HP_ZX1_IMASK); |
257 | writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); | 257 | writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE); |
258 | readl(hp->ioc_regs+HP_ZX1_IBASE); | 258 | readl(hp->ioc_regs+HP_ZX1_IBASE); |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 2a36561eec68..a124f8c5d062 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -2053,10 +2053,6 @@ static int __init rs_init(void) | |||
2053 | state->icount.rx = state->icount.tx = 0; | 2053 | state->icount.rx = state->icount.tx = 0; |
2054 | state->icount.frame = state->icount.parity = 0; | 2054 | state->icount.frame = state->icount.parity = 0; |
2055 | state->icount.overrun = state->icount.brk = 0; | 2055 | state->icount.overrun = state->icount.brk = 0; |
2056 | /* | ||
2057 | if(state->port && check_region(state->port,REGION_LENGTH(state))) | ||
2058 | continue; | ||
2059 | */ | ||
2060 | 2056 | ||
2061 | printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", | 2057 | printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", |
2062 | state->line); | 2058 | state->line); |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 58d3738a2b7f..407708a001e4 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -534,7 +534,7 @@ static void shutdown(struct channel *ch) | |||
534 | 534 | ||
535 | unsigned long flags; | 535 | unsigned long flags; |
536 | struct tty_struct *tty; | 536 | struct tty_struct *tty; |
537 | struct board_chan *bc; | 537 | struct board_chan __iomem *bc; |
538 | 538 | ||
539 | if (!(ch->asyncflags & ASYNC_INITIALIZED)) | 539 | if (!(ch->asyncflags & ASYNC_INITIALIZED)) |
540 | return; | 540 | return; |
@@ -618,7 +618,7 @@ static int pc_write(struct tty_struct * tty, | |||
618 | struct channel *ch; | 618 | struct channel *ch; |
619 | unsigned long flags; | 619 | unsigned long flags; |
620 | int remain; | 620 | int remain; |
621 | struct board_chan *bc; | 621 | struct board_chan __iomem *bc; |
622 | 622 | ||
623 | /* ---------------------------------------------------------------- | 623 | /* ---------------------------------------------------------------- |
624 | pc_write is primarily called directly by the kernel routine | 624 | pc_write is primarily called directly by the kernel routine |
@@ -685,7 +685,7 @@ static int pc_write(struct tty_struct * tty, | |||
685 | ------------------------------------------------------------------- */ | 685 | ------------------------------------------------------------------- */ |
686 | 686 | ||
687 | dataLen = min(bytesAvailable, dataLen); | 687 | dataLen = min(bytesAvailable, dataLen); |
688 | memcpy(ch->txptr + head, buf, dataLen); | 688 | memcpy_toio(ch->txptr + head, buf, dataLen); |
689 | buf += dataLen; | 689 | buf += dataLen; |
690 | head += dataLen; | 690 | head += dataLen; |
691 | amountCopied += dataLen; | 691 | amountCopied += dataLen; |
@@ -726,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty) | |||
726 | struct channel *ch; | 726 | struct channel *ch; |
727 | unsigned long flags; | 727 | unsigned long flags; |
728 | unsigned int head, tail; | 728 | unsigned int head, tail; |
729 | struct board_chan *bc; | 729 | struct board_chan __iomem *bc; |
730 | 730 | ||
731 | remain = 0; | 731 | remain = 0; |
732 | 732 | ||
@@ -773,7 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty) | |||
773 | int remain; | 773 | int remain; |
774 | unsigned long flags; | 774 | unsigned long flags; |
775 | struct channel *ch; | 775 | struct channel *ch; |
776 | struct board_chan *bc; | 776 | struct board_chan __iomem *bc; |
777 | 777 | ||
778 | /* --------------------------------------------------------- | 778 | /* --------------------------------------------------------- |
779 | verifyChannel returns the channel from the tty struct | 779 | verifyChannel returns the channel from the tty struct |
@@ -830,7 +830,7 @@ static void pc_flush_buffer(struct tty_struct *tty) | |||
830 | unsigned int tail; | 830 | unsigned int tail; |
831 | unsigned long flags; | 831 | unsigned long flags; |
832 | struct channel *ch; | 832 | struct channel *ch; |
833 | struct board_chan *bc; | 833 | struct board_chan __iomem *bc; |
834 | /* --------------------------------------------------------- | 834 | /* --------------------------------------------------------- |
835 | verifyChannel returns the channel from the tty struct | 835 | verifyChannel returns the channel from the tty struct |
836 | if it is valid. This serves as a sanity check. | 836 | if it is valid. This serves as a sanity check. |
@@ -976,7 +976,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
976 | struct channel *ch; | 976 | struct channel *ch; |
977 | unsigned long flags; | 977 | unsigned long flags; |
978 | int line, retval, boardnum; | 978 | int line, retval, boardnum; |
979 | struct board_chan *bc; | 979 | struct board_chan __iomem *bc; |
980 | unsigned int head; | 980 | unsigned int head; |
981 | 981 | ||
982 | line = tty->index; | 982 | line = tty->index; |
@@ -1041,7 +1041,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp) | |||
1041 | ch->statusflags = 0; | 1041 | ch->statusflags = 0; |
1042 | 1042 | ||
1043 | /* Save boards current modem status */ | 1043 | /* Save boards current modem status */ |
1044 | ch->imodem = bc->mstat; | 1044 | ch->imodem = readb(&bc->mstat); |
1045 | 1045 | ||
1046 | /* ---------------------------------------------------------------- | 1046 | /* ---------------------------------------------------------------- |
1047 | Set receive head and tail ptrs to each other. This indicates | 1047 | Set receive head and tail ptrs to each other. This indicates |
@@ -1399,10 +1399,10 @@ static void post_fep_init(unsigned int crd) | |||
1399 | { /* Begin post_fep_init */ | 1399 | { /* Begin post_fep_init */ |
1400 | 1400 | ||
1401 | int i; | 1401 | int i; |
1402 | unsigned char *memaddr; | 1402 | void __iomem *memaddr; |
1403 | struct global_data *gd; | 1403 | struct global_data __iomem *gd; |
1404 | struct board_info *bd; | 1404 | struct board_info *bd; |
1405 | struct board_chan *bc; | 1405 | struct board_chan __iomem *bc; |
1406 | struct channel *ch; | 1406 | struct channel *ch; |
1407 | int shrinkmem = 0, lowwater ; | 1407 | int shrinkmem = 0, lowwater ; |
1408 | 1408 | ||
@@ -1461,7 +1461,7 @@ static void post_fep_init(unsigned int crd) | |||
1461 | 8 and 64 of these structures. | 1461 | 8 and 64 of these structures. |
1462 | -------------------------------------------------------------------- */ | 1462 | -------------------------------------------------------------------- */ |
1463 | 1463 | ||
1464 | bc = (struct board_chan *)(memaddr + CHANSTRUCT); | 1464 | bc = memaddr + CHANSTRUCT; |
1465 | 1465 | ||
1466 | /* ------------------------------------------------------------------- | 1466 | /* ------------------------------------------------------------------- |
1467 | The below assignment will set gd to point at the BEGINING of | 1467 | The below assignment will set gd to point at the BEGINING of |
@@ -1470,7 +1470,7 @@ static void post_fep_init(unsigned int crd) | |||
1470 | pointer begins at 0xd10. | 1470 | pointer begins at 0xd10. |
1471 | ---------------------------------------------------------------------- */ | 1471 | ---------------------------------------------------------------------- */ |
1472 | 1472 | ||
1473 | gd = (struct global_data *)(memaddr + GLOBAL); | 1473 | gd = memaddr + GLOBAL; |
1474 | 1474 | ||
1475 | /* -------------------------------------------------------------------- | 1475 | /* -------------------------------------------------------------------- |
1476 | XEPORTS (address 0xc22) points at the number of channels the | 1476 | XEPORTS (address 0xc22) points at the number of channels the |
@@ -1493,6 +1493,7 @@ static void post_fep_init(unsigned int crd) | |||
1493 | 1493 | ||
1494 | for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ | 1494 | for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */ |
1495 | unsigned long flags; | 1495 | unsigned long flags; |
1496 | u16 tseg, rseg; | ||
1496 | 1497 | ||
1497 | ch->brdchan = bc; | 1498 | ch->brdchan = bc; |
1498 | ch->mailbox = gd; | 1499 | ch->mailbox = gd; |
@@ -1553,50 +1554,53 @@ static void post_fep_init(unsigned int crd) | |||
1553 | shrinkmem = 0; | 1554 | shrinkmem = 0; |
1554 | } | 1555 | } |
1555 | 1556 | ||
1557 | tseg = readw(&bc->tseg); | ||
1558 | rseg = readw(&bc->rseg); | ||
1559 | |||
1556 | switch (bd->type) { | 1560 | switch (bd->type) { |
1557 | 1561 | ||
1558 | case PCIXEM: | 1562 | case PCIXEM: |
1559 | case PCIXRJ: | 1563 | case PCIXRJ: |
1560 | case PCIXR: | 1564 | case PCIXR: |
1561 | /* Cover all the 2MEG cards */ | 1565 | /* Cover all the 2MEG cards */ |
1562 | ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff); | 1566 | ch->txptr = memaddr + ((tseg << 4) & 0x1fffff); |
1563 | ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff); | 1567 | ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff); |
1564 | ch->txwin = FEPWIN | ((bc->tseg) >> 11); | 1568 | ch->txwin = FEPWIN | (tseg >> 11); |
1565 | ch->rxwin = FEPWIN | ((bc->rseg) >> 11); | 1569 | ch->rxwin = FEPWIN | (rseg >> 11); |
1566 | break; | 1570 | break; |
1567 | 1571 | ||
1568 | case PCXEM: | 1572 | case PCXEM: |
1569 | case EISAXEM: | 1573 | case EISAXEM: |
1570 | /* Cover all the 32K windowed cards */ | 1574 | /* Cover all the 32K windowed cards */ |
1571 | /* Mask equal to window size - 1 */ | 1575 | /* Mask equal to window size - 1 */ |
1572 | ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff); | 1576 | ch->txptr = memaddr + ((tseg << 4) & 0x7fff); |
1573 | ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff); | 1577 | ch->rxptr = memaddr + ((rseg << 4) & 0x7fff); |
1574 | ch->txwin = FEPWIN | ((bc->tseg) >> 11); | 1578 | ch->txwin = FEPWIN | (tseg >> 11); |
1575 | ch->rxwin = FEPWIN | ((bc->rseg) >> 11); | 1579 | ch->rxwin = FEPWIN | (rseg >> 11); |
1576 | break; | 1580 | break; |
1577 | 1581 | ||
1578 | case PCXEVE: | 1582 | case PCXEVE: |
1579 | case PCXE: | 1583 | case PCXE: |
1580 | ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff); | 1584 | ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff); |
1581 | ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9); | 1585 | ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9); |
1582 | ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff); | 1586 | ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff); |
1583 | ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 ); | 1587 | ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 ); |
1584 | break; | 1588 | break; |
1585 | 1589 | ||
1586 | case PCXI: | 1590 | case PCXI: |
1587 | case PC64XE: | 1591 | case PC64XE: |
1588 | ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4); | 1592 | ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4); |
1589 | ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4); | 1593 | ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4); |
1590 | ch->txwin = ch->rxwin = 0; | 1594 | ch->txwin = ch->rxwin = 0; |
1591 | break; | 1595 | break; |
1592 | 1596 | ||
1593 | } /* End switch bd->type */ | 1597 | } /* End switch bd->type */ |
1594 | 1598 | ||
1595 | ch->txbufhead = 0; | 1599 | ch->txbufhead = 0; |
1596 | ch->txbufsize = bc->tmax + 1; | 1600 | ch->txbufsize = readw(&bc->tmax) + 1; |
1597 | 1601 | ||
1598 | ch->rxbufhead = 0; | 1602 | ch->rxbufhead = 0; |
1599 | ch->rxbufsize = bc->rmax + 1; | 1603 | ch->rxbufsize = readw(&bc->rmax) + 1; |
1600 | 1604 | ||
1601 | lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); | 1605 | lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2); |
1602 | 1606 | ||
@@ -1718,11 +1722,11 @@ static void epcapoll(unsigned long ignored) | |||
1718 | static void doevent(int crd) | 1722 | static void doevent(int crd) |
1719 | { /* Begin doevent */ | 1723 | { /* Begin doevent */ |
1720 | 1724 | ||
1721 | void *eventbuf; | 1725 | void __iomem *eventbuf; |
1722 | struct channel *ch, *chan0; | 1726 | struct channel *ch, *chan0; |
1723 | static struct tty_struct *tty; | 1727 | static struct tty_struct *tty; |
1724 | struct board_info *bd; | 1728 | struct board_info *bd; |
1725 | struct board_chan *bc; | 1729 | struct board_chan __iomem *bc; |
1726 | unsigned int tail, head; | 1730 | unsigned int tail, head; |
1727 | int event, channel; | 1731 | int event, channel; |
1728 | int mstat, lstat; | 1732 | int mstat, lstat; |
@@ -1817,7 +1821,7 @@ static void doevent(int crd) | |||
1817 | static void fepcmd(struct channel *ch, int cmd, int word_or_byte, | 1821 | static void fepcmd(struct channel *ch, int cmd, int word_or_byte, |
1818 | int byte2, int ncmds, int bytecmd) | 1822 | int byte2, int ncmds, int bytecmd) |
1819 | { /* Begin fepcmd */ | 1823 | { /* Begin fepcmd */ |
1820 | unchar *memaddr; | 1824 | unchar __iomem *memaddr; |
1821 | unsigned int head, cmdTail, cmdStart, cmdMax; | 1825 | unsigned int head, cmdTail, cmdStart, cmdMax; |
1822 | long count; | 1826 | long count; |
1823 | int n; | 1827 | int n; |
@@ -2000,7 +2004,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
2000 | 2004 | ||
2001 | unsigned int cmdHead; | 2005 | unsigned int cmdHead; |
2002 | struct termios *ts; | 2006 | struct termios *ts; |
2003 | struct board_chan *bc; | 2007 | struct board_chan __iomem *bc; |
2004 | unsigned mval, hflow, cflag, iflag; | 2008 | unsigned mval, hflow, cflag, iflag; |
2005 | 2009 | ||
2006 | bc = ch->brdchan; | 2010 | bc = ch->brdchan; |
@@ -2010,7 +2014,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
2010 | ts = tty->termios; | 2014 | ts = tty->termios; |
2011 | if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ | 2015 | if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */ |
2012 | cmdHead = readw(&bc->rin); | 2016 | cmdHead = readw(&bc->rin); |
2013 | bc->rout = cmdHead; | 2017 | writew(cmdHead, &bc->rout); |
2014 | cmdHead = readw(&bc->tin); | 2018 | cmdHead = readw(&bc->tin); |
2015 | /* Changing baud in mid-stream transmission can be wonderful */ | 2019 | /* Changing baud in mid-stream transmission can be wonderful */ |
2016 | /* --------------------------------------------------------------- | 2020 | /* --------------------------------------------------------------- |
@@ -2116,7 +2120,7 @@ static void receive_data(struct channel *ch) | |||
2116 | unchar *rptr; | 2120 | unchar *rptr; |
2117 | struct termios *ts = NULL; | 2121 | struct termios *ts = NULL; |
2118 | struct tty_struct *tty; | 2122 | struct tty_struct *tty; |
2119 | struct board_chan *bc; | 2123 | struct board_chan __iomem *bc; |
2120 | int dataToRead, wrapgap, bytesAvailable; | 2124 | int dataToRead, wrapgap, bytesAvailable; |
2121 | unsigned int tail, head; | 2125 | unsigned int tail, head; |
2122 | unsigned int wrapmask; | 2126 | unsigned int wrapmask; |
@@ -2154,7 +2158,7 @@ static void receive_data(struct channel *ch) | |||
2154 | --------------------------------------------------------------------- */ | 2158 | --------------------------------------------------------------------- */ |
2155 | 2159 | ||
2156 | if (!tty || !ts || !(ts->c_cflag & CREAD)) { | 2160 | if (!tty || !ts || !(ts->c_cflag & CREAD)) { |
2157 | bc->rout = head; | 2161 | writew(head, &bc->rout); |
2158 | return; | 2162 | return; |
2159 | } | 2163 | } |
2160 | 2164 | ||
@@ -2270,7 +2274,7 @@ static int info_ioctl(struct tty_struct *tty, struct file * file, | |||
2270 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) | 2274 | static int pc_tiocmget(struct tty_struct *tty, struct file *file) |
2271 | { | 2275 | { |
2272 | struct channel *ch = (struct channel *) tty->driver_data; | 2276 | struct channel *ch = (struct channel *) tty->driver_data; |
2273 | struct board_chan *bc; | 2277 | struct board_chan __iomem *bc; |
2274 | unsigned int mstat, mflag = 0; | 2278 | unsigned int mstat, mflag = 0; |
2275 | unsigned long flags; | 2279 | unsigned long flags; |
2276 | 2280 | ||
@@ -2351,7 +2355,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file, | |||
2351 | unsigned long flags; | 2355 | unsigned long flags; |
2352 | unsigned int mflag, mstat; | 2356 | unsigned int mflag, mstat; |
2353 | unsigned char startc, stopc; | 2357 | unsigned char startc, stopc; |
2354 | struct board_chan *bc; | 2358 | struct board_chan __iomem *bc; |
2355 | struct channel *ch = (struct channel *) tty->driver_data; | 2359 | struct channel *ch = (struct channel *) tty->driver_data; |
2356 | void __user *argp = (void __user *)arg; | 2360 | void __user *argp = (void __user *)arg; |
2357 | 2361 | ||
@@ -2633,7 +2637,7 @@ static void pc_start(struct tty_struct *tty) | |||
2633 | spin_lock_irqsave(&epca_lock, flags); | 2637 | spin_lock_irqsave(&epca_lock, flags); |
2634 | /* Just in case output was resumed because of a change in Digi-flow */ | 2638 | /* Just in case output was resumed because of a change in Digi-flow */ |
2635 | if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ | 2639 | if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */ |
2636 | struct board_chan *bc; | 2640 | struct board_chan __iomem *bc; |
2637 | globalwinon(ch); | 2641 | globalwinon(ch); |
2638 | bc = ch->brdchan; | 2642 | bc = ch->brdchan; |
2639 | if (ch->statusflags & LOWWAIT) | 2643 | if (ch->statusflags & LOWWAIT) |
@@ -2727,7 +2731,7 @@ void digi_send_break(struct channel *ch, int msec) | |||
2727 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch) | 2731 | static void setup_empty_event(struct tty_struct *tty, struct channel *ch) |
2728 | { /* Begin setup_empty_event */ | 2732 | { /* Begin setup_empty_event */ |
2729 | 2733 | ||
2730 | struct board_chan *bc = ch->brdchan; | 2734 | struct board_chan __iomem *bc = ch->brdchan; |
2731 | 2735 | ||
2732 | globalwinon(ch); | 2736 | globalwinon(ch); |
2733 | ch->statusflags |= EMPTYWAIT; | 2737 | ch->statusflags |= EMPTYWAIT; |
diff --git a/drivers/char/epca.h b/drivers/char/epca.h index 20eeb5a70e1a..456d6c8f94a8 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h | |||
@@ -128,17 +128,17 @@ struct channel | |||
128 | unsigned long c_cflag; | 128 | unsigned long c_cflag; |
129 | unsigned long c_lflag; | 129 | unsigned long c_lflag; |
130 | unsigned long c_oflag; | 130 | unsigned long c_oflag; |
131 | unsigned char *txptr; | 131 | unsigned char __iomem *txptr; |
132 | unsigned char *rxptr; | 132 | unsigned char __iomem *rxptr; |
133 | unsigned char *tmp_buf; | 133 | unsigned char *tmp_buf; |
134 | struct board_info *board; | 134 | struct board_info *board; |
135 | struct board_chan *brdchan; | 135 | struct board_chan __iomem *brdchan; |
136 | struct digi_struct digiext; | 136 | struct digi_struct digiext; |
137 | struct tty_struct *tty; | 137 | struct tty_struct *tty; |
138 | wait_queue_head_t open_wait; | 138 | wait_queue_head_t open_wait; |
139 | wait_queue_head_t close_wait; | 139 | wait_queue_head_t close_wait; |
140 | struct work_struct tqueue; | 140 | struct work_struct tqueue; |
141 | struct global_data *mailbox; | 141 | struct global_data __iomem *mailbox; |
142 | }; | 142 | }; |
143 | 143 | ||
144 | struct board_info | 144 | struct board_info |
@@ -149,8 +149,8 @@ struct board_info | |||
149 | unsigned short numports; | 149 | unsigned short numports; |
150 | unsigned long port; | 150 | unsigned long port; |
151 | unsigned long membase; | 151 | unsigned long membase; |
152 | unsigned char __iomem *re_map_port; | 152 | void __iomem *re_map_port; |
153 | unsigned char *re_map_membase; | 153 | void __iomem *re_map_membase; |
154 | unsigned long memory_seg; | 154 | unsigned long memory_seg; |
155 | void ( * memwinon ) (struct board_info *, unsigned int) ; | 155 | void ( * memwinon ) (struct board_info *, unsigned int) ; |
156 | void ( * memwinoff ) (struct board_info *, unsigned int) ; | 156 | void ( * memwinoff ) (struct board_info *, unsigned int) ; |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index cddb789902db..f92177634677 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -839,9 +839,6 @@ int __init hvc_init(void) | |||
839 | hvc_driver->flags = TTY_DRIVER_REAL_RAW; | 839 | hvc_driver->flags = TTY_DRIVER_REAL_RAW; |
840 | tty_set_operations(hvc_driver, &hvc_ops); | 840 | tty_set_operations(hvc_driver, &hvc_ops); |
841 | 841 | ||
842 | if (tty_register_driver(hvc_driver)) | ||
843 | panic("Couldn't register hvc console driver\n"); | ||
844 | |||
845 | /* Always start the kthread because there can be hotplug vty adapters | 842 | /* Always start the kthread because there can be hotplug vty adapters |
846 | * added later. */ | 843 | * added later. */ |
847 | hvc_task = kthread_run(khvcd, NULL, "khvcd"); | 844 | hvc_task = kthread_run(khvcd, NULL, "khvcd"); |
@@ -851,6 +848,9 @@ int __init hvc_init(void) | |||
851 | return -EIO; | 848 | return -EIO; |
852 | } | 849 | } |
853 | 850 | ||
851 | if (tty_register_driver(hvc_driver)) | ||
852 | panic("Couldn't register hvc console driver\n"); | ||
853 | |||
854 | return 0; | 854 | return 0; |
855 | } | 855 | } |
856 | module_init(hvc_init); | 856 | module_init(hvc_init); |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1e33cb032e07..e91268e86833 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -810,13 +810,14 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) | |||
810 | * from the top and bottom of cursor position | 810 | * from the top and bottom of cursor position |
811 | */ | 811 | */ |
812 | old_origin += (vc->vc_y - new_rows/2) * old_row_size; | 812 | old_origin += (vc->vc_y - new_rows/2) * old_row_size; |
813 | end = old_origin + new_screen_size; | 813 | end = old_origin + (old_row_size * new_rows); |
814 | } | 814 | } |
815 | } else | 815 | } else |
816 | /* | 816 | /* |
817 | * Cursor near the top, copy contents from the top of buffer | 817 | * Cursor near the top, copy contents from the top of buffer |
818 | */ | 818 | */ |
819 | end = (old_rows > new_rows) ? old_origin + new_screen_size : | 819 | end = (old_rows > new_rows) ? old_origin + |
820 | (old_row_size * new_rows) : | ||
820 | vc->vc_scr_end; | 821 | vc->vc_scr_end; |
821 | 822 | ||
822 | update_attr(vc); | 823 | update_attr(vc); |
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index fa789ea36bbe..344001b45af9 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig | |||
@@ -84,6 +84,17 @@ config 977_WATCHDOG | |||
84 | 84 | ||
85 | Not sure? It's safe to say N. | 85 | Not sure? It's safe to say N. |
86 | 86 | ||
87 | config IXP2000_WATCHDOG | ||
88 | tristate "IXP2000 Watchdog" | ||
89 | depends on WATCHDOG && ARCH_IXP2000 | ||
90 | help | ||
91 | Say Y here if to include support for the watchdog timer | ||
92 | in the Intel IXP2000(2400, 2800, 2850) network processors. | ||
93 | This driver can be built as a module by choosing M. The module | ||
94 | will be called ixp2000_wdt. | ||
95 | |||
96 | Say N if you are unsure. | ||
97 | |||
87 | config IXP4XX_WATCHDOG | 98 | config IXP4XX_WATCHDOG |
88 | tristate "IXP4xx Watchdog" | 99 | tristate "IXP4xx Watchdog" |
89 | depends on WATCHDOG && ARCH_IXP4XX | 100 | depends on WATCHDOG && ARCH_IXP4XX |
@@ -100,17 +111,6 @@ config IXP4XX_WATCHDOG | |||
100 | 111 | ||
101 | Say N if you are unsure. | 112 | Say N if you are unsure. |
102 | 113 | ||
103 | config IXP2000_WATCHDOG | ||
104 | tristate "IXP2000 Watchdog" | ||
105 | depends on WATCHDOG && ARCH_IXP2000 | ||
106 | help | ||
107 | Say Y here if to include support for the watchdog timer | ||
108 | in the Intel IXP2000(2400, 2800, 2850) network processors. | ||
109 | This driver can be built as a module by choosing M. The module | ||
110 | will be called ixp2000_wdt. | ||
111 | |||
112 | Say N if you are unsure. | ||
113 | |||
114 | config S3C2410_WATCHDOG | 114 | config S3C2410_WATCHDOG |
115 | tristate "S3C2410 Watchdog" | 115 | tristate "S3C2410 Watchdog" |
116 | depends on WATCHDOG && ARCH_S3C2410 | 116 | depends on WATCHDOG && ARCH_S3C2410 |
@@ -233,6 +233,16 @@ config IB700_WDT | |||
233 | 233 | ||
234 | Most people will say N. | 234 | Most people will say N. |
235 | 235 | ||
236 | config IBMASR | ||
237 | tristate "IBM Automatic Server Restart" | ||
238 | depends on WATCHDOG && X86 | ||
239 | help | ||
240 | This is the driver for the IBM Automatic Server Restart watchdog | ||
241 | timer builtin into some eServer xSeries machines. | ||
242 | |||
243 | To compile this driver as a module, choose M here: the | ||
244 | module will be called ibmasr. | ||
245 | |||
236 | config WAFER_WDT | 246 | config WAFER_WDT |
237 | tristate "ICP Wafer 5823 Single Board Computer Watchdog" | 247 | tristate "ICP Wafer 5823 Single Board Computer Watchdog" |
238 | depends on WATCHDOG && X86 | 248 | depends on WATCHDOG && X86 |
@@ -243,6 +253,16 @@ config WAFER_WDT | |||
243 | To compile this driver as a module, choose M here: the | 253 | To compile this driver as a module, choose M here: the |
244 | module will be called wafer5823wdt. | 254 | module will be called wafer5823wdt. |
245 | 255 | ||
256 | config I6300ESB_WDT | ||
257 | tristate "Intel 6300ESB Timer/Watchdog" | ||
258 | depends on WATCHDOG && X86 && PCI | ||
259 | ---help--- | ||
260 | Hardware driver for the watchdog timer built into the Intel | ||
261 | 6300ESB controller hub. | ||
262 | |||
263 | To compile this driver as a module, choose M here: the | ||
264 | module will be called i6300esb. | ||
265 | |||
246 | config I8XX_TCO | 266 | config I8XX_TCO |
247 | tristate "Intel i8xx TCO Timer/Watchdog" | 267 | tristate "Intel i8xx TCO Timer/Watchdog" |
248 | depends on WATCHDOG && (X86 || IA64) && PCI | 268 | depends on WATCHDOG && (X86 || IA64) && PCI |
@@ -298,6 +318,19 @@ config 60XX_WDT | |||
298 | You can compile this driver directly into the kernel, or use | 318 | You can compile this driver directly into the kernel, or use |
299 | it as a module. The module will be called sbc60xxwdt. | 319 | it as a module. The module will be called sbc60xxwdt. |
300 | 320 | ||
321 | config SBC8360_WDT | ||
322 | tristate "SBC8360 Watchdog Timer" | ||
323 | depends on WATCHDOG && X86 | ||
324 | ---help--- | ||
325 | |||
326 | This is the driver for the hardware watchdog on the SBC8360 Single | ||
327 | Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com). | ||
328 | |||
329 | To compile this driver as a module, choose M here: the | ||
330 | module will be called sbc8360.ko. | ||
331 | |||
332 | Most people will say N. | ||
333 | |||
301 | config CPU5_WDT | 334 | config CPU5_WDT |
302 | tristate "SMA CPU5 Watchdog" | 335 | tristate "SMA CPU5 Watchdog" |
303 | depends on WATCHDOG && X86 | 336 | depends on WATCHDOG && X86 |
@@ -336,6 +369,19 @@ config W83877F_WDT | |||
336 | 369 | ||
337 | Most people will say N. | 370 | Most people will say N. |
338 | 371 | ||
372 | config W83977F_WDT | ||
373 | tristate "W83977F (PCM-5335) Watchdog Timer" | ||
374 | depends on WATCHDOG && X86 | ||
375 | ---help--- | ||
376 | This is the driver for the hardware watchdog on the W83977F I/O chip | ||
377 | as used in AAEON's PCM-5335 SBC (and likely others). This | ||
378 | watchdog simply watches your kernel to make sure it doesn't freeze, | ||
379 | and if it does, it reboots your computer after a certain amount of | ||
380 | time. | ||
381 | |||
382 | To compile this driver as a module, choose M here: the | ||
383 | module will be called w83977f_wdt. | ||
384 | |||
339 | config MACHZ_WDT | 385 | config MACHZ_WDT |
340 | tristate "ZF MachZ Watchdog" | 386 | tristate "ZF MachZ Watchdog" |
341 | depends on WATCHDOG && X86 | 387 | depends on WATCHDOG && X86 |
@@ -355,6 +401,10 @@ config 8xx_WDT | |||
355 | tristate "MPC8xx Watchdog Timer" | 401 | tristate "MPC8xx Watchdog Timer" |
356 | depends on WATCHDOG && 8xx | 402 | depends on WATCHDOG && 8xx |
357 | 403 | ||
404 | config MV64X60_WDT | ||
405 | tristate "MV64X60 (Marvell Discovery) Watchdog Timer" | ||
406 | depends on WATCHDOG && MV64X60 | ||
407 | |||
358 | config BOOKE_WDT | 408 | config BOOKE_WDT |
359 | tristate "PowerPC Book-E Watchdog Timer" | 409 | tristate "PowerPC Book-E Watchdog Timer" |
360 | depends on WATCHDOG && (BOOKE || 4xx) | 410 | depends on WATCHDOG && (BOOKE || 4xx) |
@@ -362,6 +412,17 @@ config BOOKE_WDT | |||
362 | Please see Documentation/watchdog/watchdog-api.txt for | 412 | Please see Documentation/watchdog/watchdog-api.txt for |
363 | more information. | 413 | more information. |
364 | 414 | ||
415 | # PPC64 Architecture | ||
416 | |||
417 | config WATCHDOG_RTAS | ||
418 | tristate "RTAS watchdog" | ||
419 | depends on WATCHDOG && PPC_RTAS | ||
420 | help | ||
421 | This driver adds watchdog support for the RTAS watchdog. | ||
422 | |||
423 | To compile this driver as a module, choose M here. The module | ||
424 | will be called wdrtas. | ||
425 | |||
365 | # MIPS Architecture | 426 | # MIPS Architecture |
366 | 427 | ||
367 | config INDYDOG | 428 | config INDYDOG |
@@ -430,16 +491,6 @@ config WATCHDOG_RIO | |||
430 | machines. The watchdog timeout period is normally one minute but | 491 | machines. The watchdog timeout period is normally one minute but |
431 | can be changed with a boot-time parameter. | 492 | can be changed with a boot-time parameter. |
432 | 493 | ||
433 | # ppc64 RTAS watchdog | ||
434 | config WATCHDOG_RTAS | ||
435 | tristate "RTAS watchdog" | ||
436 | depends on WATCHDOG && PPC_RTAS | ||
437 | help | ||
438 | This driver adds watchdog support for the RTAS watchdog. | ||
439 | |||
440 | To compile this driver as a module, choose M here. The module | ||
441 | will be called wdrtas. | ||
442 | |||
443 | # | 494 | # |
444 | # ISA-based Watchdog Cards | 495 | # ISA-based Watchdog Cards |
445 | # | 496 | # |
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index bc6f5fe88c8c..cfd0a3987710 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile | |||
@@ -39,22 +39,27 @@ obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o | |||
39 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o | 39 | obj-$(CONFIG_SC520_WDT) += sc520_wdt.o |
40 | obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o | 40 | obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o |
41 | obj-$(CONFIG_IB700_WDT) += ib700wdt.o | 41 | obj-$(CONFIG_IB700_WDT) += ib700wdt.o |
42 | obj-$(CONFIG_IBMASR) += ibmasr.o | ||
42 | obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o | 43 | obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o |
44 | obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o | ||
43 | obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o | 45 | obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o |
44 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o | 46 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o |
45 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o | 47 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o |
46 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o | 48 | obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o |
49 | obj-$(CONFIG_SBC8360_WDT) += sbc8360.o | ||
47 | obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o | 50 | obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o |
48 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o | 51 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o |
49 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o | 52 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o |
53 | obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o | ||
50 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o | 54 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o |
51 | 55 | ||
52 | # PowerPC Architecture | 56 | # PowerPC Architecture |
53 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o | 57 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o |
58 | obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o | ||
59 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o | ||
54 | 60 | ||
55 | # PPC64 Architecture | 61 | # PPC64 Architecture |
56 | obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o | 62 | obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o |
57 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o | ||
58 | 63 | ||
59 | # MIPS Architecture | 64 | # MIPS Architecture |
60 | obj-$(CONFIG_INDYDOG) += indydog.o | 65 | obj-$(CONFIG_INDYDOG) += indydog.o |
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c new file mode 100644 index 000000000000..93785f13242e --- /dev/null +++ b/drivers/char/watchdog/i6300esb.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * i6300esb: Watchdog timer driver for Intel 6300ESB chipset | ||
3 | * | ||
4 | * (c) Copyright 2004 Google Inc. | ||
5 | * (c) Copyright 2005 David Härdeman <david@2gen.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * based on i810-tco.c which is in turn based on softdog.c | ||
13 | * | ||
14 | * The timer is implemented in the following I/O controller hubs: | ||
15 | * (See the intel documentation on http://developer.intel.com.) | ||
16 | * 6300ESB chip : document number 300641-003 | ||
17 | * | ||
18 | * 2004YYZZ Ross Biro | ||
19 | * Initial version 0.01 | ||
20 | * 2004YYZZ Ross Biro | ||
21 | * Version 0.02 | ||
22 | * 20050210 David Härdeman <david@2gen.com> | ||
23 | * Ported driver to kernel 2.6 | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | * Includes, defines, variables, module parameters, ... | ||
28 | */ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/fs.h> | ||
34 | #include <linux/mm.h> | ||
35 | #include <linux/miscdevice.h> | ||
36 | #include <linux/watchdog.h> | ||
37 | #include <linux/reboot.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/pci.h> | ||
40 | #include <linux/ioport.h> | ||
41 | |||
42 | #include <asm/uaccess.h> | ||
43 | #include <asm/io.h> | ||
44 | |||
45 | /* Module and version information */ | ||
46 | #define ESB_VERSION "0.03" | ||
47 | #define ESB_MODULE_NAME "i6300ESB timer" | ||
48 | #define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION | ||
49 | #define PFX ESB_MODULE_NAME ": " | ||
50 | |||
51 | /* PCI configuration registers */ | ||
52 | #define ESB_CONFIG_REG 0x60 /* Config register */ | ||
53 | #define ESB_LOCK_REG 0x68 /* WDT lock register */ | ||
54 | |||
55 | /* Memory mapped registers */ | ||
56 | #define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */ | ||
57 | #define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */ | ||
58 | #define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */ | ||
59 | #define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ | ||
60 | |||
61 | /* Lock register bits */ | ||
62 | #define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */ | ||
63 | #define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */ | ||
64 | #define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */ | ||
65 | |||
66 | /* Config register bits */ | ||
67 | #define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */ | ||
68 | #define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */ | ||
69 | #define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */ | ||
70 | |||
71 | /* Reload register bits */ | ||
72 | #define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */ | ||
73 | |||
74 | /* Magic constants */ | ||
75 | #define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */ | ||
76 | #define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */ | ||
77 | |||
78 | /* internal variables */ | ||
79 | static void __iomem *BASEADDR; | ||
80 | static spinlock_t esb_lock; /* Guards the hardware */ | ||
81 | static unsigned long timer_alive; | ||
82 | static struct pci_dev *esb_pci; | ||
83 | static unsigned short triggered; /* The status of the watchdog upon boot */ | ||
84 | static char esb_expect_close; | ||
85 | |||
86 | /* module parameters */ | ||
87 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */ | ||
88 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | ||
89 | module_param(heartbeat, int, 0); | ||
90 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | ||
91 | |||
92 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
93 | module_param(nowayout, int, 0); | ||
94 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | ||
95 | |||
96 | /* | ||
97 | * Some i6300ESB specific functions | ||
98 | */ | ||
99 | |||
100 | /* | ||
101 | * Prepare for reloading the timer by unlocking the proper registers. | ||
102 | * This is performed by first writing 0x80 followed by 0x86 to the | ||
103 | * reload register. After this the appropriate registers can be written | ||
104 | * to once before they need to be unlocked again. | ||
105 | */ | ||
106 | static inline void esb_unlock_registers(void) { | ||
107 | writeb(ESB_UNLOCK1, ESB_RELOAD_REG); | ||
108 | writeb(ESB_UNLOCK2, ESB_RELOAD_REG); | ||
109 | } | ||
110 | |||
111 | static void esb_timer_start(void) | ||
112 | { | ||
113 | u8 val; | ||
114 | |||
115 | /* Enable or Enable + Lock? */ | ||
116 | val = 0x02 | (nowayout ? 0x01 : 0x00); | ||
117 | |||
118 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); | ||
119 | } | ||
120 | |||
121 | static int esb_timer_stop(void) | ||
122 | { | ||
123 | u8 val; | ||
124 | |||
125 | spin_lock(&esb_lock); | ||
126 | /* First, reset timers as suggested by the docs */ | ||
127 | esb_unlock_registers(); | ||
128 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); | ||
129 | /* Then disable the WDT */ | ||
130 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0); | ||
131 | pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val); | ||
132 | spin_unlock(&esb_lock); | ||
133 | |||
134 | /* Returns 0 if the timer was disabled, non-zero otherwise */ | ||
135 | return (val & 0x01); | ||
136 | } | ||
137 | |||
138 | static void esb_timer_keepalive(void) | ||
139 | { | ||
140 | spin_lock(&esb_lock); | ||
141 | esb_unlock_registers(); | ||
142 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); | ||
143 | /* FIXME: Do we need to flush anything here? */ | ||
144 | spin_unlock(&esb_lock); | ||
145 | } | ||
146 | |||
147 | static int esb_timer_set_heartbeat(int time) | ||
148 | { | ||
149 | u32 val; | ||
150 | |||
151 | if (time < 0x1 || time > (2 * 0x03ff)) | ||
152 | return -EINVAL; | ||
153 | |||
154 | spin_lock(&esb_lock); | ||
155 | |||
156 | /* We shift by 9, so if we are passed a value of 1 sec, | ||
157 | * val will be 1 << 9 = 512, then write that to two | ||
158 | * timers => 2 * 512 = 1024 (which is decremented at 1KHz) | ||
159 | */ | ||
160 | val = time << 9; | ||
161 | |||
162 | /* Write timer 1 */ | ||
163 | esb_unlock_registers(); | ||
164 | writel(val, ESB_TIMER1_REG); | ||
165 | |||
166 | /* Write timer 2 */ | ||
167 | esb_unlock_registers(); | ||
168 | writel(val, ESB_TIMER2_REG); | ||
169 | |||
170 | /* Reload */ | ||
171 | esb_unlock_registers(); | ||
172 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); | ||
173 | |||
174 | /* FIXME: Do we need to flush everything out? */ | ||
175 | |||
176 | /* Done */ | ||
177 | heartbeat = time; | ||
178 | spin_unlock(&esb_lock); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static int esb_timer_read (void) | ||
183 | { | ||
184 | u32 count; | ||
185 | |||
186 | /* This isn't documented, and doesn't take into | ||
187 | * acount which stage is running, but it looks | ||
188 | * like a 20 bit count down, so we might as well report it. | ||
189 | */ | ||
190 | pci_read_config_dword(esb_pci, 0x64, &count); | ||
191 | return (int)count; | ||
192 | } | ||
193 | |||
194 | /* | ||
195 | * /dev/watchdog handling | ||
196 | */ | ||
197 | |||
198 | static int esb_open (struct inode *inode, struct file *file) | ||
199 | { | ||
200 | /* /dev/watchdog can only be opened once */ | ||
201 | if (test_and_set_bit(0, &timer_alive)) | ||
202 | return -EBUSY; | ||
203 | |||
204 | /* Reload and activate timer */ | ||
205 | esb_timer_keepalive (); | ||
206 | esb_timer_start (); | ||
207 | |||
208 | return nonseekable_open(inode, file); | ||
209 | } | ||
210 | |||
211 | static int esb_release (struct inode *inode, struct file *file) | ||
212 | { | ||
213 | /* Shut off the timer. */ | ||
214 | if (esb_expect_close == 42) { | ||
215 | esb_timer_stop (); | ||
216 | } else { | ||
217 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | ||
218 | esb_timer_keepalive (); | ||
219 | } | ||
220 | clear_bit(0, &timer_alive); | ||
221 | esb_expect_close = 0; | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static ssize_t esb_write (struct file *file, const char __user *data, | ||
226 | size_t len, loff_t * ppos) | ||
227 | { | ||
228 | /* See if we got the magic character 'V' and reload the timer */ | ||
229 | if (len) { | ||
230 | if (!nowayout) { | ||
231 | size_t i; | ||
232 | |||
233 | /* note: just in case someone wrote the magic character | ||
234 | * five months ago... */ | ||
235 | esb_expect_close = 0; | ||
236 | |||
237 | /* scan to see whether or not we got the magic character */ | ||
238 | for (i = 0; i != len; i++) { | ||
239 | char c; | ||
240 | if(get_user(c, data+i)) | ||
241 | return -EFAULT; | ||
242 | if (c == 'V') | ||
243 | esb_expect_close = 42; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* someone wrote to us, we should reload the timer */ | ||
248 | esb_timer_keepalive (); | ||
249 | } | ||
250 | return len; | ||
251 | } | ||
252 | |||
253 | static int esb_ioctl (struct inode *inode, struct file *file, | ||
254 | unsigned int cmd, unsigned long arg) | ||
255 | { | ||
256 | int new_options, retval = -EINVAL; | ||
257 | int new_heartbeat; | ||
258 | void __user *argp = (void __user *)arg; | ||
259 | int __user *p = argp; | ||
260 | static struct watchdog_info ident = { | ||
261 | .options = WDIOF_SETTIMEOUT | | ||
262 | WDIOF_KEEPALIVEPING | | ||
263 | WDIOF_MAGICCLOSE, | ||
264 | .firmware_version = 0, | ||
265 | .identity = ESB_MODULE_NAME, | ||
266 | }; | ||
267 | |||
268 | switch (cmd) { | ||
269 | case WDIOC_GETSUPPORT: | ||
270 | return copy_to_user(argp, &ident, | ||
271 | sizeof (ident)) ? -EFAULT : 0; | ||
272 | |||
273 | case WDIOC_GETSTATUS: | ||
274 | return put_user (esb_timer_read(), p); | ||
275 | |||
276 | case WDIOC_GETBOOTSTATUS: | ||
277 | return put_user (triggered, p); | ||
278 | |||
279 | case WDIOC_KEEPALIVE: | ||
280 | esb_timer_keepalive (); | ||
281 | return 0; | ||
282 | |||
283 | case WDIOC_SETOPTIONS: | ||
284 | { | ||
285 | if (get_user (new_options, p)) | ||
286 | return -EFAULT; | ||
287 | |||
288 | if (new_options & WDIOS_DISABLECARD) { | ||
289 | esb_timer_stop (); | ||
290 | retval = 0; | ||
291 | } | ||
292 | |||
293 | if (new_options & WDIOS_ENABLECARD) { | ||
294 | esb_timer_keepalive (); | ||
295 | esb_timer_start (); | ||
296 | retval = 0; | ||
297 | } | ||
298 | |||
299 | return retval; | ||
300 | } | ||
301 | |||
302 | case WDIOC_SETTIMEOUT: | ||
303 | { | ||
304 | if (get_user(new_heartbeat, p)) | ||
305 | return -EFAULT; | ||
306 | |||
307 | if (esb_timer_set_heartbeat(new_heartbeat)) | ||
308 | return -EINVAL; | ||
309 | |||
310 | esb_timer_keepalive (); | ||
311 | /* Fall */ | ||
312 | } | ||
313 | |||
314 | case WDIOC_GETTIMEOUT: | ||
315 | return put_user(heartbeat, p); | ||
316 | |||
317 | default: | ||
318 | return -ENOIOCTLCMD; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * Notify system | ||
324 | */ | ||
325 | |||
326 | static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused) | ||
327 | { | ||
328 | if (code==SYS_DOWN || code==SYS_HALT) { | ||
329 | /* Turn the WDT off */ | ||
330 | esb_timer_stop (); | ||
331 | } | ||
332 | |||
333 | return NOTIFY_DONE; | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | * Kernel Interfaces | ||
338 | */ | ||
339 | |||
340 | static struct file_operations esb_fops = { | ||
341 | .owner = THIS_MODULE, | ||
342 | .llseek = no_llseek, | ||
343 | .write = esb_write, | ||
344 | .ioctl = esb_ioctl, | ||
345 | .open = esb_open, | ||
346 | .release = esb_release, | ||
347 | }; | ||
348 | |||
349 | static struct miscdevice esb_miscdev = { | ||
350 | .minor = WATCHDOG_MINOR, | ||
351 | .name = "watchdog", | ||
352 | .fops = &esb_fops, | ||
353 | }; | ||
354 | |||
355 | static struct notifier_block esb_notifier = { | ||
356 | .notifier_call = esb_notify_sys, | ||
357 | }; | ||
358 | |||
359 | /* | ||
360 | * Data for PCI driver interface | ||
361 | * | ||
362 | * This data only exists for exporting the supported | ||
363 | * PCI ids via MODULE_DEVICE_TABLE. We do not actually | ||
364 | * register a pci_driver, because someone else might one day | ||
365 | * want to register another driver on the same PCI id. | ||
366 | */ | ||
367 | static struct pci_device_id esb_pci_tbl[] = { | ||
368 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, | ||
369 | { 0, }, /* End of list */ | ||
370 | }; | ||
371 | MODULE_DEVICE_TABLE (pci, esb_pci_tbl); | ||
372 | |||
373 | /* | ||
374 | * Init & exit routines | ||
375 | */ | ||
376 | |||
377 | static unsigned char __init esb_getdevice (void) | ||
378 | { | ||
379 | u8 val1; | ||
380 | unsigned short val2; | ||
381 | |||
382 | struct pci_dev *dev = NULL; | ||
383 | /* | ||
384 | * Find the PCI device | ||
385 | */ | ||
386 | |||
387 | for_each_pci_dev(dev) { | ||
388 | if (pci_match_id(esb_pci_tbl, dev)) { | ||
389 | esb_pci = dev; | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | if (esb_pci) { | ||
395 | if (pci_enable_device(esb_pci)) { | ||
396 | printk (KERN_ERR PFX "failed to enable device\n"); | ||
397 | goto err_devput; | ||
398 | } | ||
399 | |||
400 | if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { | ||
401 | printk (KERN_ERR PFX "failed to request region\n"); | ||
402 | goto err_disable; | ||
403 | } | ||
404 | |||
405 | BASEADDR = ioremap(pci_resource_start(esb_pci, 0), | ||
406 | pci_resource_len(esb_pci, 0)); | ||
407 | if (BASEADDR == NULL) { | ||
408 | /* Something's wrong here, BASEADDR has to be set */ | ||
409 | printk (KERN_ERR PFX "failed to get BASEADDR\n"); | ||
410 | goto err_release; | ||
411 | } | ||
412 | |||
413 | /* | ||
414 | * The watchdog has two timers, it can be setup so that the | ||
415 | * expiry of timer1 results in an interrupt and the expiry of | ||
416 | * timer2 results in a reboot. We set it to not generate | ||
417 | * any interrupts as there is not much we can do with it | ||
418 | * right now. | ||
419 | * | ||
420 | * We also enable reboots and set the timer frequency to | ||
421 | * the PCI clock divided by 2^15 (approx 1KHz). | ||
422 | */ | ||
423 | pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003); | ||
424 | |||
425 | /* Check that the WDT isn't already locked */ | ||
426 | pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); | ||
427 | if (val1 & ESB_WDT_LOCK) | ||
428 | printk (KERN_WARNING PFX "nowayout already set\n"); | ||
429 | |||
430 | /* Set the timer to watchdog mode and disable it for now */ | ||
431 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); | ||
432 | |||
433 | /* Check if the watchdog was previously triggered */ | ||
434 | esb_unlock_registers(); | ||
435 | val2 = readw(ESB_RELOAD_REG); | ||
436 | triggered = (val2 & (0x01 << 9) >> 9); | ||
437 | |||
438 | /* Reset trigger flag and timers */ | ||
439 | esb_unlock_registers(); | ||
440 | writew((0x11 << 8), ESB_RELOAD_REG); | ||
441 | |||
442 | /* Done */ | ||
443 | return 1; | ||
444 | |||
445 | err_release: | ||
446 | pci_release_region(esb_pci, 0); | ||
447 | err_disable: | ||
448 | pci_disable_device(esb_pci); | ||
449 | err_devput: | ||
450 | pci_dev_put(esb_pci); | ||
451 | } | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int __init watchdog_init (void) | ||
456 | { | ||
457 | int ret; | ||
458 | |||
459 | spin_lock_init(&esb_lock); | ||
460 | |||
461 | /* Check whether or not the hardware watchdog is there */ | ||
462 | if (!esb_getdevice () || esb_pci == NULL) | ||
463 | return -ENODEV; | ||
464 | |||
465 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | ||
466 | if (esb_timer_set_heartbeat (heartbeat)) { | ||
467 | esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT); | ||
468 | printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n", | ||
469 | heartbeat); | ||
470 | } | ||
471 | |||
472 | ret = register_reboot_notifier(&esb_notifier); | ||
473 | if (ret != 0) { | ||
474 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | ||
475 | ret); | ||
476 | goto err_unmap; | ||
477 | } | ||
478 | |||
479 | ret = misc_register(&esb_miscdev); | ||
480 | if (ret != 0) { | ||
481 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | ||
482 | WATCHDOG_MINOR, ret); | ||
483 | goto err_notifier; | ||
484 | } | ||
485 | |||
486 | esb_timer_stop (); | ||
487 | |||
488 | printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", | ||
489 | BASEADDR, heartbeat, nowayout); | ||
490 | |||
491 | return 0; | ||
492 | |||
493 | err_notifier: | ||
494 | unregister_reboot_notifier(&esb_notifier); | ||
495 | err_unmap: | ||
496 | iounmap(BASEADDR); | ||
497 | /* err_release: */ | ||
498 | pci_release_region(esb_pci, 0); | ||
499 | /* err_disable: */ | ||
500 | pci_disable_device(esb_pci); | ||
501 | /* err_devput: */ | ||
502 | pci_dev_put(esb_pci); | ||
503 | return ret; | ||
504 | } | ||
505 | |||
506 | static void __exit watchdog_cleanup (void) | ||
507 | { | ||
508 | /* Stop the timer before we leave */ | ||
509 | if (!nowayout) | ||
510 | esb_timer_stop (); | ||
511 | |||
512 | /* Deregister */ | ||
513 | misc_deregister(&esb_miscdev); | ||
514 | unregister_reboot_notifier(&esb_notifier); | ||
515 | iounmap(BASEADDR); | ||
516 | pci_release_region(esb_pci, 0); | ||
517 | pci_disable_device(esb_pci); | ||
518 | pci_dev_put(esb_pci); | ||
519 | } | ||
520 | |||
521 | module_init(watchdog_init); | ||
522 | module_exit(watchdog_cleanup); | ||
523 | |||
524 | MODULE_AUTHOR("Ross Biro and David Härdeman"); | ||
525 | MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets"); | ||
526 | MODULE_LICENSE("GPL"); | ||
527 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c new file mode 100644 index 000000000000..294c474ae485 --- /dev/null +++ b/drivers/char/watchdog/ibmasr.c | |||
@@ -0,0 +1,405 @@ | |||
1 | /* | ||
2 | * IBM Automatic Server Restart driver. | ||
3 | * | ||
4 | * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru> | ||
5 | * | ||
6 | * Based on driver written by Pete Reynolds. | ||
7 | * Copyright (c) IBM Corporation, 1998-2004. | ||
8 | * | ||
9 | * This software may be used and distributed according to the terms | ||
10 | * of the GNU Public License, incorporated herein by reference. | ||
11 | */ | ||
12 | |||
13 | #include <linux/config.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/pci.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/miscdevice.h> | ||
21 | #include <linux/watchdog.h> | ||
22 | #include <linux/dmi.h> | ||
23 | |||
24 | #include <asm/io.h> | ||
25 | #include <asm/uaccess.h> | ||
26 | |||
27 | |||
28 | enum { | ||
29 | ASMTYPE_UNKNOWN, | ||
30 | ASMTYPE_TOPAZ, | ||
31 | ASMTYPE_JASPER, | ||
32 | ASMTYPE_PEARL, | ||
33 | ASMTYPE_JUNIPER, | ||
34 | ASMTYPE_SPRUCE, | ||
35 | }; | ||
36 | |||
37 | #define PFX "ibmasr: " | ||
38 | |||
39 | #define TOPAZ_ASR_REG_OFFSET 4 | ||
40 | #define TOPAZ_ASR_TOGGLE 0x40 | ||
41 | #define TOPAZ_ASR_DISABLE 0x80 | ||
42 | |||
43 | /* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */ | ||
44 | #define PEARL_BASE 0xe04 | ||
45 | #define PEARL_WRITE 0xe06 | ||
46 | #define PEARL_READ 0xe07 | ||
47 | |||
48 | #define PEARL_ASR_DISABLE_MASK 0x80 /* bit 7: disable = 1, enable = 0 */ | ||
49 | #define PEARL_ASR_TOGGLE_MASK 0x40 /* bit 6: 0, then 1, then 0 */ | ||
50 | |||
51 | /* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */ | ||
52 | #define JASPER_ASR_REG_OFFSET 0x38 | ||
53 | |||
54 | #define JASPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1, enable = 0 */ | ||
55 | #define JASPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */ | ||
56 | |||
57 | #define JUNIPER_BASE_ADDRESS 0x54b /* Base address of Juniper ASR */ | ||
58 | #define JUNIPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1 enable = 0 */ | ||
59 | #define JUNIPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */ | ||
60 | |||
61 | #define SPRUCE_BASE_ADDRESS 0x118e /* Base address of Spruce ASR */ | ||
62 | #define SPRUCE_ASR_DISABLE_MASK 0x01 /* bit 1: disable = 1 enable = 0 */ | ||
63 | #define SPRUCE_ASR_TOGGLE_MASK 0x02 /* bit 0: 0, then 1, then 0 */ | ||
64 | |||
65 | |||
66 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
67 | |||
68 | static unsigned long asr_is_open; | ||
69 | static char asr_expect_close; | ||
70 | |||
71 | static unsigned int asr_type, asr_base, asr_length; | ||
72 | static unsigned int asr_read_addr, asr_write_addr; | ||
73 | static unsigned char asr_toggle_mask, asr_disable_mask; | ||
74 | |||
75 | static void asr_toggle(void) | ||
76 | { | ||
77 | unsigned char reg = inb(asr_read_addr); | ||
78 | |||
79 | outb(reg & ~asr_toggle_mask, asr_write_addr); | ||
80 | reg = inb(asr_read_addr); | ||
81 | |||
82 | outb(reg | asr_toggle_mask, asr_write_addr); | ||
83 | reg = inb(asr_read_addr); | ||
84 | |||
85 | outb(reg & ~asr_toggle_mask, asr_write_addr); | ||
86 | reg = inb(asr_read_addr); | ||
87 | } | ||
88 | |||
89 | static void asr_enable(void) | ||
90 | { | ||
91 | unsigned char reg; | ||
92 | |||
93 | if (asr_type == ASMTYPE_TOPAZ) { | ||
94 | /* asr_write_addr == asr_read_addr */ | ||
95 | reg = inb(asr_read_addr); | ||
96 | outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE), | ||
97 | asr_read_addr); | ||
98 | } else { | ||
99 | /* | ||
100 | * First make sure the hardware timer is reset by toggling | ||
101 | * ASR hardware timer line. | ||
102 | */ | ||
103 | asr_toggle(); | ||
104 | |||
105 | reg = inb(asr_read_addr); | ||
106 | outb(reg & ~asr_disable_mask, asr_write_addr); | ||
107 | } | ||
108 | reg = inb(asr_read_addr); | ||
109 | } | ||
110 | |||
111 | static void asr_disable(void) | ||
112 | { | ||
113 | unsigned char reg = inb(asr_read_addr); | ||
114 | |||
115 | if (asr_type == ASMTYPE_TOPAZ) | ||
116 | /* asr_write_addr == asr_read_addr */ | ||
117 | outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE, | ||
118 | asr_read_addr); | ||
119 | else { | ||
120 | outb(reg | asr_toggle_mask, asr_write_addr); | ||
121 | reg = inb(asr_read_addr); | ||
122 | |||
123 | outb(reg | asr_disable_mask, asr_write_addr); | ||
124 | } | ||
125 | reg = inb(asr_read_addr); | ||
126 | } | ||
127 | |||
128 | static int __init asr_get_base_address(void) | ||
129 | { | ||
130 | unsigned char low, high; | ||
131 | const char *type = ""; | ||
132 | |||
133 | asr_length = 1; | ||
134 | |||
135 | switch (asr_type) { | ||
136 | case ASMTYPE_TOPAZ: | ||
137 | /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */ | ||
138 | outb(0x07, 0x2e); | ||
139 | outb(0x07, 0x2f); | ||
140 | |||
141 | /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */ | ||
142 | outb(0x60, 0x2e); | ||
143 | high = inb(0x2f); | ||
144 | |||
145 | /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */ | ||
146 | outb(0x61, 0x2e); | ||
147 | low = inb(0x2f); | ||
148 | |||
149 | asr_base = (high << 16) | low; | ||
150 | asr_read_addr = asr_write_addr = | ||
151 | asr_base + TOPAZ_ASR_REG_OFFSET; | ||
152 | asr_length = 5; | ||
153 | |||
154 | break; | ||
155 | |||
156 | case ASMTYPE_JASPER: | ||
157 | type = "Jaspers "; | ||
158 | |||
159 | /* FIXME: need to use pci_config_lock here, but it's not exported */ | ||
160 | |||
161 | /* spin_lock_irqsave(&pci_config_lock, flags);*/ | ||
162 | |||
163 | /* Select the SuperIO chip in the PCI I/O port register */ | ||
164 | outl(0x8000f858, 0xcf8); | ||
165 | |||
166 | /* | ||
167 | * Read the base address for the SuperIO chip. | ||
168 | * Only the lower 16 bits are valid, but the address is word | ||
169 | * aligned so the last bit must be masked off. | ||
170 | */ | ||
171 | asr_base = inl(0xcfc) & 0xfffe; | ||
172 | |||
173 | /* spin_unlock_irqrestore(&pci_config_lock, flags);*/ | ||
174 | |||
175 | asr_read_addr = asr_write_addr = | ||
176 | asr_base + JASPER_ASR_REG_OFFSET; | ||
177 | asr_toggle_mask = JASPER_ASR_TOGGLE_MASK; | ||
178 | asr_disable_mask = JASPER_ASR_DISABLE_MASK; | ||
179 | asr_length = JASPER_ASR_REG_OFFSET + 1; | ||
180 | |||
181 | break; | ||
182 | |||
183 | case ASMTYPE_PEARL: | ||
184 | type = "Pearls "; | ||
185 | asr_base = PEARL_BASE; | ||
186 | asr_read_addr = PEARL_READ; | ||
187 | asr_write_addr = PEARL_WRITE; | ||
188 | asr_toggle_mask = PEARL_ASR_TOGGLE_MASK; | ||
189 | asr_disable_mask = PEARL_ASR_DISABLE_MASK; | ||
190 | asr_length = 4; | ||
191 | break; | ||
192 | |||
193 | case ASMTYPE_JUNIPER: | ||
194 | type = "Junipers "; | ||
195 | asr_base = JUNIPER_BASE_ADDRESS; | ||
196 | asr_read_addr = asr_write_addr = asr_base; | ||
197 | asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK; | ||
198 | asr_disable_mask = JUNIPER_ASR_DISABLE_MASK; | ||
199 | break; | ||
200 | |||
201 | case ASMTYPE_SPRUCE: | ||
202 | type = "Spruce's "; | ||
203 | asr_base = SPRUCE_BASE_ADDRESS; | ||
204 | asr_read_addr = asr_write_addr = asr_base; | ||
205 | asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK; | ||
206 | asr_disable_mask = SPRUCE_ASR_DISABLE_MASK; | ||
207 | break; | ||
208 | } | ||
209 | |||
210 | if (!request_region(asr_base, asr_length, "ibmasr")) { | ||
211 | printk(KERN_ERR PFX "address %#x already in use\n", | ||
212 | asr_base); | ||
213 | return -EBUSY; | ||
214 | } | ||
215 | |||
216 | printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | |||
222 | static ssize_t asr_write(struct file *file, const char __user *buf, | ||
223 | size_t count, loff_t *ppos) | ||
224 | { | ||
225 | if (count) { | ||
226 | if (!nowayout) { | ||
227 | size_t i; | ||
228 | |||
229 | /* In case it was set long ago */ | ||
230 | asr_expect_close = 0; | ||
231 | |||
232 | for (i = 0; i != count; i++) { | ||
233 | char c; | ||
234 | if (get_user(c, buf + i)) | ||
235 | return -EFAULT; | ||
236 | if (c == 'V') | ||
237 | asr_expect_close = 42; | ||
238 | } | ||
239 | } | ||
240 | asr_toggle(); | ||
241 | } | ||
242 | return count; | ||
243 | } | ||
244 | |||
245 | static int asr_ioctl(struct inode *inode, struct file *file, | ||
246 | unsigned int cmd, unsigned long arg) | ||
247 | { | ||
248 | static const struct watchdog_info ident = { | ||
249 | .options = WDIOF_KEEPALIVEPING | | ||
250 | WDIOF_MAGICCLOSE, | ||
251 | .identity = "IBM ASR" | ||
252 | }; | ||
253 | void __user *argp = (void __user *)arg; | ||
254 | int __user *p = argp; | ||
255 | int heartbeat; | ||
256 | |||
257 | switch (cmd) { | ||
258 | case WDIOC_GETSUPPORT: | ||
259 | return copy_to_user(argp, &ident, sizeof(ident)) ? | ||
260 | -EFAULT : 0; | ||
261 | |||
262 | case WDIOC_GETSTATUS: | ||
263 | case WDIOC_GETBOOTSTATUS: | ||
264 | return put_user(0, p); | ||
265 | |||
266 | case WDIOC_KEEPALIVE: | ||
267 | asr_toggle(); | ||
268 | return 0; | ||
269 | |||
270 | /* | ||
271 | * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT | ||
272 | * and WDIOC_GETTIMEOUT always returns 256. | ||
273 | */ | ||
274 | case WDIOC_GETTIMEOUT: | ||
275 | heartbeat = 256; | ||
276 | return put_user(heartbeat, p); | ||
277 | |||
278 | case WDIOC_SETOPTIONS: { | ||
279 | int new_options, retval = -EINVAL; | ||
280 | |||
281 | if (get_user(new_options, p)) | ||
282 | return -EFAULT; | ||
283 | |||
284 | if (new_options & WDIOS_DISABLECARD) { | ||
285 | asr_disable(); | ||
286 | retval = 0; | ||
287 | } | ||
288 | |||
289 | if (new_options & WDIOS_ENABLECARD) { | ||
290 | asr_enable(); | ||
291 | asr_toggle(); | ||
292 | retval = 0; | ||
293 | } | ||
294 | |||
295 | return retval; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | return -ENOIOCTLCMD; | ||
300 | } | ||
301 | |||
302 | static int asr_open(struct inode *inode, struct file *file) | ||
303 | { | ||
304 | if(test_and_set_bit(0, &asr_is_open)) | ||
305 | return -EBUSY; | ||
306 | |||
307 | asr_toggle(); | ||
308 | asr_enable(); | ||
309 | |||
310 | return nonseekable_open(inode, file); | ||
311 | } | ||
312 | |||
313 | static int asr_release(struct inode *inode, struct file *file) | ||
314 | { | ||
315 | if (asr_expect_close == 42) | ||
316 | asr_disable(); | ||
317 | else { | ||
318 | printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); | ||
319 | asr_toggle(); | ||
320 | } | ||
321 | clear_bit(0, &asr_is_open); | ||
322 | asr_expect_close = 0; | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | static struct file_operations asr_fops = { | ||
327 | .owner = THIS_MODULE, | ||
328 | .llseek = no_llseek, | ||
329 | .write = asr_write, | ||
330 | .ioctl = asr_ioctl, | ||
331 | .open = asr_open, | ||
332 | .release = asr_release, | ||
333 | }; | ||
334 | |||
335 | static struct miscdevice asr_miscdev = { | ||
336 | .minor = WATCHDOG_MINOR, | ||
337 | .name = "watchdog", | ||
338 | .fops = &asr_fops, | ||
339 | }; | ||
340 | |||
341 | |||
342 | struct ibmasr_id { | ||
343 | const char *desc; | ||
344 | int type; | ||
345 | }; | ||
346 | |||
347 | static struct ibmasr_id __initdata ibmasr_id_table[] = { | ||
348 | { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ }, | ||
349 | { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL }, | ||
350 | { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER }, | ||
351 | { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER }, | ||
352 | { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE }, | ||
353 | { NULL } | ||
354 | }; | ||
355 | |||
356 | static int __init ibmasr_init(void) | ||
357 | { | ||
358 | struct ibmasr_id *id; | ||
359 | int rc; | ||
360 | |||
361 | for (id = ibmasr_id_table; id->desc; id++) { | ||
362 | if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) { | ||
363 | asr_type = id->type; | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | if (!asr_type) | ||
369 | return -ENODEV; | ||
370 | |||
371 | rc = misc_register(&asr_miscdev); | ||
372 | if (rc < 0) { | ||
373 | printk(KERN_ERR PFX "failed to register misc device\n"); | ||
374 | return rc; | ||
375 | } | ||
376 | |||
377 | rc = asr_get_base_address(); | ||
378 | if (rc) { | ||
379 | misc_deregister(&asr_miscdev); | ||
380 | return rc; | ||
381 | } | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static void __exit ibmasr_exit(void) | ||
387 | { | ||
388 | if (!nowayout) | ||
389 | asr_disable(); | ||
390 | |||
391 | misc_deregister(&asr_miscdev); | ||
392 | |||
393 | release_region(asr_base, asr_length); | ||
394 | } | ||
395 | |||
396 | module_init(ibmasr_init); | ||
397 | module_exit(ibmasr_exit); | ||
398 | |||
399 | module_param(nowayout, int, 0); | ||
400 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | ||
401 | |||
402 | MODULE_DESCRIPTION("IBM Automatic Server Restart driver"); | ||
403 | MODULE_AUTHOR("Andrey Panin"); | ||
404 | MODULE_LICENSE("GPL"); | ||
405 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c index c694eee1fb24..75ca84ed4adf 100644 --- a/drivers/char/watchdog/mpcore_wdt.c +++ b/drivers/char/watchdog/mpcore_wdt.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/device.h> | 32 | #include <linux/device.h> |
33 | |||
34 | #include <asm/hardware/arm_twd.h> | ||
33 | #include <asm/uaccess.h> | 35 | #include <asm/uaccess.h> |
34 | 36 | ||
35 | struct mpcore_wdt { | 37 | struct mpcore_wdt { |
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c new file mode 100644 index 000000000000..1436aea3b28f --- /dev/null +++ b/drivers/char/watchdog/mv64x60_wdt.c | |||
@@ -0,0 +1,252 @@ | |||
1 | /* | ||
2 | * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface | ||
3 | * | ||
4 | * Author: James Chapman <jchapman@katalix.com> | ||
5 | * | ||
6 | * Platform-specific setup code should configure the dog to generate | ||
7 | * interrupt or reset as required. This code only enables/disables | ||
8 | * and services the watchdog. | ||
9 | * | ||
10 | * Derived from mpc8xx_wdt.c, with the following copyright. | ||
11 | * | ||
12 | * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under | ||
13 | * the terms of the GNU General Public License version 2. This program | ||
14 | * is licensed "as is" without any warranty of any kind, whether express | ||
15 | * or implied. | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/miscdevice.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/watchdog.h> | ||
25 | #include <asm/mv64x60.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | /* MV64x60 WDC (config) register access definitions */ | ||
30 | #define MV64x60_WDC_CTL1_MASK (3 << 24) | ||
31 | #define MV64x60_WDC_CTL1(val) ((val & 3) << 24) | ||
32 | #define MV64x60_WDC_CTL2_MASK (3 << 26) | ||
33 | #define MV64x60_WDC_CTL2(val) ((val & 3) << 26) | ||
34 | |||
35 | /* Flags bits */ | ||
36 | #define MV64x60_WDOG_FLAG_OPENED 0 | ||
37 | #define MV64x60_WDOG_FLAG_ENABLED 1 | ||
38 | |||
39 | static unsigned long wdt_flags; | ||
40 | static int wdt_status; | ||
41 | static void __iomem *mv64x60_regs; | ||
42 | static int mv64x60_wdt_timeout; | ||
43 | |||
44 | static void mv64x60_wdt_reg_write(u32 val) | ||
45 | { | ||
46 | /* Allow write only to CTL1 / CTL2 fields, retaining values in | ||
47 | * other fields. | ||
48 | */ | ||
49 | u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC); | ||
50 | data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK); | ||
51 | data |= val; | ||
52 | writel(data, mv64x60_regs + MV64x60_WDT_WDC); | ||
53 | } | ||
54 | |||
55 | static void mv64x60_wdt_service(void) | ||
56 | { | ||
57 | /* Write 01 followed by 10 to CTL2 */ | ||
58 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01)); | ||
59 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02)); | ||
60 | } | ||
61 | |||
62 | static void mv64x60_wdt_handler_disable(void) | ||
63 | { | ||
64 | if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { | ||
65 | /* Write 01 followed by 10 to CTL1 */ | ||
66 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); | ||
67 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); | ||
68 | printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n"); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | static void mv64x60_wdt_handler_enable(void) | ||
73 | { | ||
74 | if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) { | ||
75 | /* Write 01 followed by 10 to CTL1 */ | ||
76 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01)); | ||
77 | mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02)); | ||
78 | printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n"); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | static int mv64x60_wdt_open(struct inode *inode, struct file *file) | ||
83 | { | ||
84 | if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags)) | ||
85 | return -EBUSY; | ||
86 | |||
87 | mv64x60_wdt_service(); | ||
88 | mv64x60_wdt_handler_enable(); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int mv64x60_wdt_release(struct inode *inode, struct file *file) | ||
94 | { | ||
95 | mv64x60_wdt_service(); | ||
96 | |||
97 | #if !defined(CONFIG_WATCHDOG_NOWAYOUT) | ||
98 | mv64x60_wdt_handler_disable(); | ||
99 | #endif | ||
100 | |||
101 | clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags); | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static ssize_t mv64x60_wdt_write(struct file *file, const char *data, | ||
107 | size_t len, loff_t * ppos) | ||
108 | { | ||
109 | if (*ppos != file->f_pos) | ||
110 | return -ESPIPE; | ||
111 | |||
112 | if (len) | ||
113 | mv64x60_wdt_service(); | ||
114 | |||
115 | return len; | ||
116 | } | ||
117 | |||
118 | static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, | ||
119 | unsigned int cmd, unsigned long arg) | ||
120 | { | ||
121 | int timeout; | ||
122 | static struct watchdog_info info = { | ||
123 | .options = WDIOF_KEEPALIVEPING, | ||
124 | .firmware_version = 0, | ||
125 | .identity = "MV64x60 watchdog", | ||
126 | }; | ||
127 | |||
128 | switch (cmd) { | ||
129 | case WDIOC_GETSUPPORT: | ||
130 | if (copy_to_user((void *)arg, &info, sizeof(info))) | ||
131 | return -EFAULT; | ||
132 | break; | ||
133 | |||
134 | case WDIOC_GETSTATUS: | ||
135 | case WDIOC_GETBOOTSTATUS: | ||
136 | if (put_user(wdt_status, (int *)arg)) | ||
137 | return -EFAULT; | ||
138 | wdt_status &= ~WDIOF_KEEPALIVEPING; | ||
139 | break; | ||
140 | |||
141 | case WDIOC_GETTEMP: | ||
142 | return -EOPNOTSUPP; | ||
143 | |||
144 | case WDIOC_SETOPTIONS: | ||
145 | return -EOPNOTSUPP; | ||
146 | |||
147 | case WDIOC_KEEPALIVE: | ||
148 | mv64x60_wdt_service(); | ||
149 | wdt_status |= WDIOF_KEEPALIVEPING; | ||
150 | break; | ||
151 | |||
152 | case WDIOC_SETTIMEOUT: | ||
153 | return -EOPNOTSUPP; | ||
154 | |||
155 | case WDIOC_GETTIMEOUT: | ||
156 | timeout = mv64x60_wdt_timeout * HZ; | ||
157 | if (put_user(timeout, (int *)arg)) | ||
158 | return -EFAULT; | ||
159 | break; | ||
160 | |||
161 | default: | ||
162 | return -ENOIOCTLCMD; | ||
163 | } | ||
164 | |||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static struct file_operations mv64x60_wdt_fops = { | ||
169 | .owner = THIS_MODULE, | ||
170 | .llseek = no_llseek, | ||
171 | .write = mv64x60_wdt_write, | ||
172 | .ioctl = mv64x60_wdt_ioctl, | ||
173 | .open = mv64x60_wdt_open, | ||
174 | .release = mv64x60_wdt_release, | ||
175 | }; | ||
176 | |||
177 | static struct miscdevice mv64x60_wdt_miscdev = { | ||
178 | .minor = WATCHDOG_MINOR, | ||
179 | .name = "watchdog", | ||
180 | .fops = &mv64x60_wdt_fops, | ||
181 | }; | ||
182 | |||
183 | static int __devinit mv64x60_wdt_probe(struct device *dev) | ||
184 | { | ||
185 | struct platform_device *pd = to_platform_device(dev); | ||
186 | struct mv64x60_wdt_pdata *pdata = pd->dev.platform_data; | ||
187 | int bus_clk = 133; | ||
188 | |||
189 | mv64x60_wdt_timeout = 10; | ||
190 | if (pdata) { | ||
191 | mv64x60_wdt_timeout = pdata->timeout; | ||
192 | bus_clk = pdata->bus_clk; | ||
193 | } | ||
194 | |||
195 | mv64x60_regs = mv64x60_get_bridge_vbase(); | ||
196 | |||
197 | writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8, | ||
198 | mv64x60_regs + MV64x60_WDT_WDC); | ||
199 | |||
200 | return misc_register(&mv64x60_wdt_miscdev); | ||
201 | } | ||
202 | |||
203 | static int __devexit mv64x60_wdt_remove(struct device *dev) | ||
204 | { | ||
205 | misc_deregister(&mv64x60_wdt_miscdev); | ||
206 | |||
207 | mv64x60_wdt_service(); | ||
208 | mv64x60_wdt_handler_disable(); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static struct device_driver mv64x60_wdt_driver = { | ||
214 | .name = MV64x60_WDT_NAME, | ||
215 | .bus = &platform_bus_type, | ||
216 | .probe = mv64x60_wdt_probe, | ||
217 | .remove = __devexit_p(mv64x60_wdt_remove), | ||
218 | }; | ||
219 | |||
220 | static struct platform_device *mv64x60_wdt_dev; | ||
221 | |||
222 | static int __init mv64x60_wdt_init(void) | ||
223 | { | ||
224 | int ret; | ||
225 | |||
226 | printk(KERN_INFO "MV64x60 watchdog driver\n"); | ||
227 | |||
228 | mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME, | ||
229 | -1, NULL, 0); | ||
230 | if (IS_ERR(mv64x60_wdt_dev)) { | ||
231 | ret = PTR_ERR(mv64x60_wdt_dev); | ||
232 | goto out; | ||
233 | } | ||
234 | |||
235 | ret = driver_register(&mv64x60_wdt_driver); | ||
236 | out: | ||
237 | return ret; | ||
238 | } | ||
239 | |||
240 | static void __exit mv64x60_wdt_exit(void) | ||
241 | { | ||
242 | driver_unregister(&mv64x60_wdt_driver); | ||
243 | platform_device_unregister(mv64x60_wdt_dev); | ||
244 | } | ||
245 | |||
246 | module_init(mv64x60_wdt_init); | ||
247 | module_exit(mv64x60_wdt_exit); | ||
248 | |||
249 | MODULE_AUTHOR("James Chapman <jchapman@katalix.com>"); | ||
250 | MODULE_DESCRIPTION("MV64x60 watchdog driver"); | ||
251 | MODULE_LICENSE("GPL"); | ||
252 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c index 2b13afb09c5d..5a80adbf8032 100644 --- a/drivers/char/watchdog/pcwd_pci.c +++ b/drivers/char/watchdog/pcwd_pci.c | |||
@@ -29,27 +29,29 @@ | |||
29 | * Includes, defines, variables, module parameters, ... | 29 | * Includes, defines, variables, module parameters, ... |
30 | */ | 30 | */ |
31 | 31 | ||
32 | #include <linux/config.h> | 32 | #include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */ |
33 | #include <linux/module.h> | 33 | #include <linux/module.h> /* For module specific items */ |
34 | #include <linux/moduleparam.h> | 34 | #include <linux/moduleparam.h> /* For new moduleparam's */ |
35 | #include <linux/types.h> | 35 | #include <linux/types.h> /* For standard types (like size_t) */ |
36 | #include <linux/delay.h> | 36 | #include <linux/errno.h> /* For the -ENODEV/... values */ |
37 | #include <linux/miscdevice.h> | 37 | #include <linux/kernel.h> /* For printk/panic/... */ |
38 | #include <linux/watchdog.h> | 38 | #include <linux/delay.h> /* For mdelay function */ |
39 | #include <linux/notifier.h> | 39 | #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ |
40 | #include <linux/reboot.h> | 40 | #include <linux/watchdog.h> /* For the watchdog specific items */ |
41 | #include <linux/init.h> | 41 | #include <linux/notifier.h> /* For notifier support */ |
42 | #include <linux/fs.h> | 42 | #include <linux/reboot.h> /* For reboot_notifier stuff */ |
43 | #include <linux/pci.h> | 43 | #include <linux/init.h> /* For __init/__exit/... */ |
44 | #include <linux/ioport.h> | 44 | #include <linux/fs.h> /* For file operations */ |
45 | #include <linux/spinlock.h> | 45 | #include <linux/pci.h> /* For pci functions */ |
46 | 46 | #include <linux/ioport.h> /* For io-port access */ | |
47 | #include <asm/uaccess.h> | 47 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ |
48 | #include <asm/io.h> | 48 | |
49 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | ||
50 | #include <asm/io.h> /* For inb/outb/... */ | ||
49 | 51 | ||
50 | /* Module and version information */ | 52 | /* Module and version information */ |
51 | #define WATCHDOG_VERSION "1.01" | 53 | #define WATCHDOG_VERSION "1.01" |
52 | #define WATCHDOG_DATE "15 Mar 2005" | 54 | #define WATCHDOG_DATE "02 Sep 2005" |
53 | #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" | 55 | #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" |
54 | #define WATCHDOG_NAME "pcwd_pci" | 56 | #define WATCHDOG_NAME "pcwd_pci" |
55 | #define PFX WATCHDOG_NAME ": " | 57 | #define PFX WATCHDOG_NAME ": " |
@@ -335,12 +337,14 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file, | |||
335 | return -EFAULT; | 337 | return -EFAULT; |
336 | 338 | ||
337 | if (new_options & WDIOS_DISABLECARD) { | 339 | if (new_options & WDIOS_DISABLECARD) { |
338 | pcipcwd_stop(); | 340 | if (pcipcwd_stop()) |
341 | return -EIO; | ||
339 | retval = 0; | 342 | retval = 0; |
340 | } | 343 | } |
341 | 344 | ||
342 | if (new_options & WDIOS_ENABLECARD) { | 345 | if (new_options & WDIOS_ENABLECARD) { |
343 | pcipcwd_start(); | 346 | if (pcipcwd_start()) |
347 | return -EIO; | ||
344 | retval = 0; | 348 | retval = 0; |
345 | } | 349 | } |
346 | 350 | ||
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index 8b292bf343c4..3625b2601b42 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c | |||
@@ -464,7 +464,7 @@ static void s3c2410wdt_shutdown(struct device *dev) | |||
464 | static unsigned long wtcon_save; | 464 | static unsigned long wtcon_save; |
465 | static unsigned long wtdat_save; | 465 | static unsigned long wtdat_save; |
466 | 466 | ||
467 | static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level) | 467 | static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level) |
468 | { | 468 | { |
469 | if (level == SUSPEND_POWER_DOWN) { | 469 | if (level == SUSPEND_POWER_DOWN) { |
470 | /* Save watchdog state, and turn it off. */ | 470 | /* Save watchdog state, and turn it off. */ |
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c new file mode 100644 index 000000000000..c6cbf808d8c2 --- /dev/null +++ b/drivers/char/watchdog/sbc8360.c | |||
@@ -0,0 +1,414 @@ | |||
1 | /* | ||
2 | * SBC8360 Watchdog driver | ||
3 | * | ||
4 | * (c) Copyright 2005 Webcon, Inc. | ||
5 | * | ||
6 | * Based on ib700wdt.c, which is based on advantechwdt.c which is based | ||
7 | * on acquirewdt.c which is based on wdt.c. | ||
8 | * | ||
9 | * (c) Copyright 2001 Charles Howes <chowes@vsol.net> | ||
10 | * | ||
11 | * Based on advantechwdt.c which is based on acquirewdt.c which | ||
12 | * is based on wdt.c. | ||
13 | * | ||
14 | * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl> | ||
15 | * | ||
16 | * Based on acquirewdt.c which is based on wdt.c. | ||
17 | * Original copyright messages: | ||
18 | * | ||
19 | * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved. | ||
20 | * http://www.redhat.com | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or | ||
23 | * modify it under the terms of the GNU General Public License | ||
24 | * as published by the Free Software Foundation; either version | ||
25 | * 2 of the License, or (at your option) any later version. | ||
26 | * | ||
27 | * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide | ||
28 | * warranty for any of this software. This material is provided | ||
29 | * "AS-IS" and at no charge. | ||
30 | * | ||
31 | * (c) Copyright 1995 Alan Cox <alan@redhat.com> | ||
32 | * | ||
33 | * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com> | ||
34 | * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT | ||
35 | * Added timeout module option to override default | ||
36 | * | ||
37 | */ | ||
38 | |||
39 | #include <linux/config.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/types.h> | ||
42 | #include <linux/miscdevice.h> | ||
43 | #include <linux/watchdog.h> | ||
44 | #include <linux/ioport.h> | ||
45 | #include <linux/delay.h> | ||
46 | #include <linux/notifier.h> | ||
47 | #include <linux/fs.h> | ||
48 | #include <linux/reboot.h> | ||
49 | #include <linux/init.h> | ||
50 | #include <linux/spinlock.h> | ||
51 | #include <linux/moduleparam.h> | ||
52 | |||
53 | #include <asm/io.h> | ||
54 | #include <asm/uaccess.h> | ||
55 | #include <asm/system.h> | ||
56 | |||
57 | static unsigned long sbc8360_is_open; | ||
58 | static spinlock_t sbc8360_lock; | ||
59 | static char expect_close; | ||
60 | |||
61 | #define PFX "sbc8360: " | ||
62 | |||
63 | /* | ||
64 | * | ||
65 | * Watchdog Timer Configuration | ||
66 | * | ||
67 | * The function of the watchdog timer is to reset the system automatically | ||
68 | * and is defined at I/O port 0120H and 0121H. To enable the watchdog timer | ||
69 | * and allow the system to reset, write appropriate values from the table | ||
70 | * below to I/O port 0120H and 0121H. To disable the timer, write a zero | ||
71 | * value to I/O port 0121H for the system to stop the watchdog function. | ||
72 | * | ||
73 | * The following describes how the timer should be programmed (according to | ||
74 | * the vendor documentation) | ||
75 | * | ||
76 | * Enabling Watchdog: | ||
77 | * MOV AX,000AH (enable, phase I) | ||
78 | * MOV DX,0120H | ||
79 | * OUT DX,AX | ||
80 | * MOV AX,000BH (enable, phase II) | ||
81 | * MOV DX,0120H | ||
82 | * OUT DX,AX | ||
83 | * MOV AX,000nH (set multiplier n, from 1-4) | ||
84 | * MOV DX,0120H | ||
85 | * OUT DX,AX | ||
86 | * MOV AX,000mH (set base timer m, from 0-F) | ||
87 | * MOV DX,0121H | ||
88 | * OUT DX,AX | ||
89 | * | ||
90 | * Reset timer: | ||
91 | * MOV AX,000mH (same as set base timer, above) | ||
92 | * MOV DX,0121H | ||
93 | * OUT DX,AX | ||
94 | * | ||
95 | * Disabling Watchdog: | ||
96 | * MOV AX,0000H (a zero value) | ||
97 | * MOV DX,0120H | ||
98 | * OUT DX,AX | ||
99 | * | ||
100 | * Watchdog timeout configuration values: | ||
101 | * N | ||
102 | * M | 1 2 3 4 | ||
103 | * --|---------------------------------- | ||
104 | * 0 | 0.5s 5s 50s 100s | ||
105 | * 1 | 1s 10s 100s 200s | ||
106 | * 2 | 1.5s 15s 150s 300s | ||
107 | * 3 | 2s 20s 200s 400s | ||
108 | * 4 | 2.5s 25s 250s 500s | ||
109 | * 5 | 3s 30s 300s 600s | ||
110 | * 6 | 3.5s 35s 350s 700s | ||
111 | * 7 | 4s 40s 400s 800s | ||
112 | * 8 | 4.5s 45s 450s 900s | ||
113 | * 9 | 5s 50s 500s 1000s | ||
114 | * A | 5.5s 55s 550s 1100s | ||
115 | * B | 6s 60s 600s 1200s | ||
116 | * C | 6.5s 65s 650s 1300s | ||
117 | * D | 7s 70s 700s 1400s | ||
118 | * E | 7.5s 75s 750s 1500s | ||
119 | * F | 8s 80s 800s 1600s | ||
120 | * | ||
121 | * Another way to say the same things is: | ||
122 | * For N=1, Timeout = (M+1) * 0.5s | ||
123 | * For N=2, Timeout = (M+1) * 5s | ||
124 | * For N=3, Timeout = (M+1) * 50s | ||
125 | * For N=4, Timeout = (M+1) * 100s | ||
126 | * | ||
127 | */ | ||
128 | |||
129 | static int wd_times[64][2] = { | ||
130 | {0, 1}, /* 0 = 0.5s */ | ||
131 | {1, 1}, /* 1 = 1s */ | ||
132 | {2, 1}, /* 2 = 1.5s */ | ||
133 | {3, 1}, /* 3 = 2s */ | ||
134 | {4, 1}, /* 4 = 2.5s */ | ||
135 | {5, 1}, /* 5 = 3s */ | ||
136 | {6, 1}, /* 6 = 3.5s */ | ||
137 | {7, 1}, /* 7 = 4s */ | ||
138 | {8, 1}, /* 8 = 4.5s */ | ||
139 | {9, 1}, /* 9 = 5s */ | ||
140 | {0xA, 1}, /* 10 = 5.5s */ | ||
141 | {0xB, 1}, /* 11 = 6s */ | ||
142 | {0xC, 1}, /* 12 = 6.5s */ | ||
143 | {0xD, 1}, /* 13 = 7s */ | ||
144 | {0xE, 1}, /* 14 = 7.5s */ | ||
145 | {0xF, 1}, /* 15 = 8s */ | ||
146 | {0, 2}, /* 16 = 5s */ | ||
147 | {1, 2}, /* 17 = 10s */ | ||
148 | {2, 2}, /* 18 = 15s */ | ||
149 | {3, 2}, /* 19 = 20s */ | ||
150 | {4, 2}, /* 20 = 25s */ | ||
151 | {5, 2}, /* 21 = 30s */ | ||
152 | {6, 2}, /* 22 = 35s */ | ||
153 | {7, 2}, /* 23 = 40s */ | ||
154 | {8, 2}, /* 24 = 45s */ | ||
155 | {9, 2}, /* 25 = 50s */ | ||
156 | {0xA, 2}, /* 26 = 55s */ | ||
157 | {0xB, 2}, /* 27 = 60s */ | ||
158 | {0xC, 2}, /* 28 = 65s */ | ||
159 | {0xD, 2}, /* 29 = 70s */ | ||
160 | {0xE, 2}, /* 30 = 75s */ | ||
161 | {0xF, 2}, /* 31 = 80s */ | ||
162 | {0, 3}, /* 32 = 50s */ | ||
163 | {1, 3}, /* 33 = 100s */ | ||
164 | {2, 3}, /* 34 = 150s */ | ||
165 | {3, 3}, /* 35 = 200s */ | ||
166 | {4, 3}, /* 36 = 250s */ | ||
167 | {5, 3}, /* 37 = 300s */ | ||
168 | {6, 3}, /* 38 = 350s */ | ||
169 | {7, 3}, /* 39 = 400s */ | ||
170 | {8, 3}, /* 40 = 450s */ | ||
171 | {9, 3}, /* 41 = 500s */ | ||
172 | {0xA, 3}, /* 42 = 550s */ | ||
173 | {0xB, 3}, /* 43 = 600s */ | ||
174 | {0xC, 3}, /* 44 = 650s */ | ||
175 | {0xD, 3}, /* 45 = 700s */ | ||
176 | {0xE, 3}, /* 46 = 750s */ | ||
177 | {0xF, 3}, /* 47 = 800s */ | ||
178 | {0, 4}, /* 48 = 100s */ | ||
179 | {1, 4}, /* 49 = 200s */ | ||
180 | {2, 4}, /* 50 = 300s */ | ||
181 | {3, 4}, /* 51 = 400s */ | ||
182 | {4, 4}, /* 52 = 500s */ | ||
183 | {5, 4}, /* 53 = 600s */ | ||
184 | {6, 4}, /* 54 = 700s */ | ||
185 | {7, 4}, /* 55 = 800s */ | ||
186 | {8, 4}, /* 56 = 900s */ | ||
187 | {9, 4}, /* 57 = 1000s */ | ||
188 | {0xA, 4}, /* 58 = 1100s */ | ||
189 | {0xB, 4}, /* 59 = 1200s */ | ||
190 | {0xC, 4}, /* 60 = 1300s */ | ||
191 | {0xD, 4}, /* 61 = 1400s */ | ||
192 | {0xE, 4}, /* 62 = 1500s */ | ||
193 | {0xF, 4} /* 63 = 1600s */ | ||
194 | }; | ||
195 | |||
196 | #define SBC8360_ENABLE 0x120 | ||
197 | #define SBC8360_BASETIME 0x121 | ||
198 | |||
199 | static int timeout = 27; | ||
200 | static int wd_margin = 0xB; | ||
201 | static int wd_multiplier = 2; | ||
202 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
203 | |||
204 | module_param(timeout, int, 27); | ||
205 | MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))"); | ||
206 | module_param(nowayout, int, 0); | ||
207 | MODULE_PARM_DESC(nowayout, | ||
208 | "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | ||
209 | |||
210 | /* | ||
211 | * Kernel methods. | ||
212 | */ | ||
213 | |||
214 | /* Activate and pre-configure watchdog */ | ||
215 | static void sbc8360_activate(void) | ||
216 | { | ||
217 | /* Enable the watchdog */ | ||
218 | outb(0x0A, SBC8360_ENABLE); | ||
219 | msleep_interruptible(100); | ||
220 | outb(0x0B, SBC8360_ENABLE); | ||
221 | msleep_interruptible(100); | ||
222 | /* Set timeout multiplier */ | ||
223 | outb(wd_multiplier, SBC8360_ENABLE); | ||
224 | msleep_interruptible(100); | ||
225 | /* Nothing happens until first sbc8360_ping() */ | ||
226 | } | ||
227 | |||
228 | /* Kernel pings watchdog */ | ||
229 | static void sbc8360_ping(void) | ||
230 | { | ||
231 | /* Write the base timer register */ | ||
232 | outb(wd_margin, SBC8360_BASETIME); | ||
233 | } | ||
234 | |||
235 | /* Userspace pings kernel driver, or requests clean close */ | ||
236 | static ssize_t sbc8360_write(struct file *file, const char __user * buf, | ||
237 | size_t count, loff_t * ppos) | ||
238 | { | ||
239 | if (count) { | ||
240 | if (!nowayout) { | ||
241 | size_t i; | ||
242 | |||
243 | /* In case it was set long ago */ | ||
244 | expect_close = 0; | ||
245 | |||
246 | for (i = 0; i != count; i++) { | ||
247 | char c; | ||
248 | if (get_user(c, buf + i)) | ||
249 | return -EFAULT; | ||
250 | if (c == 'V') | ||
251 | expect_close = 42; | ||
252 | } | ||
253 | } | ||
254 | sbc8360_ping(); | ||
255 | } | ||
256 | return count; | ||
257 | } | ||
258 | |||
259 | static int sbc8360_open(struct inode *inode, struct file *file) | ||
260 | { | ||
261 | spin_lock(&sbc8360_lock); | ||
262 | if (test_and_set_bit(0, &sbc8360_is_open)) { | ||
263 | spin_unlock(&sbc8360_lock); | ||
264 | return -EBUSY; | ||
265 | } | ||
266 | if (nowayout) | ||
267 | __module_get(THIS_MODULE); | ||
268 | |||
269 | /* Activate and ping once to start the countdown */ | ||
270 | spin_unlock(&sbc8360_lock); | ||
271 | sbc8360_activate(); | ||
272 | sbc8360_ping(); | ||
273 | return nonseekable_open(inode, file); | ||
274 | } | ||
275 | |||
276 | static int sbc8360_close(struct inode *inode, struct file *file) | ||
277 | { | ||
278 | spin_lock(&sbc8360_lock); | ||
279 | if (expect_close == 42) | ||
280 | outb(0, SBC8360_ENABLE); | ||
281 | else | ||
282 | printk(KERN_CRIT PFX | ||
283 | "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n"); | ||
284 | |||
285 | clear_bit(0, &sbc8360_is_open); | ||
286 | expect_close = 0; | ||
287 | spin_unlock(&sbc8360_lock); | ||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Notifier for system down | ||
293 | */ | ||
294 | |||
295 | static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code, | ||
296 | void *unused) | ||
297 | { | ||
298 | if (code == SYS_DOWN || code == SYS_HALT) { | ||
299 | /* Disable the SBC8360 Watchdog */ | ||
300 | outb(0, SBC8360_ENABLE); | ||
301 | } | ||
302 | return NOTIFY_DONE; | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * Kernel Interfaces | ||
307 | */ | ||
308 | |||
309 | static struct file_operations sbc8360_fops = { | ||
310 | .owner = THIS_MODULE, | ||
311 | .llseek = no_llseek, | ||
312 | .write = sbc8360_write, | ||
313 | .open = sbc8360_open, | ||
314 | .release = sbc8360_close, | ||
315 | }; | ||
316 | |||
317 | static struct miscdevice sbc8360_miscdev = { | ||
318 | .minor = WATCHDOG_MINOR, | ||
319 | .name = "watchdog", | ||
320 | .fops = &sbc8360_fops, | ||
321 | }; | ||
322 | |||
323 | /* | ||
324 | * The SBC8360 needs to learn about soft shutdowns in order to | ||
325 | * turn the timebomb registers off. | ||
326 | */ | ||
327 | |||
328 | static struct notifier_block sbc8360_notifier = { | ||
329 | .notifier_call = sbc8360_notify_sys, | ||
330 | }; | ||
331 | |||
332 | static int __init sbc8360_init(void) | ||
333 | { | ||
334 | int res; | ||
335 | unsigned long int mseconds = 60000; | ||
336 | |||
337 | spin_lock_init(&sbc8360_lock); | ||
338 | res = misc_register(&sbc8360_miscdev); | ||
339 | if (res) { | ||
340 | printk(KERN_ERR PFX "failed to register misc device\n"); | ||
341 | goto out_nomisc; | ||
342 | } | ||
343 | |||
344 | if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) { | ||
345 | printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n", | ||
346 | SBC8360_ENABLE); | ||
347 | res = -EIO; | ||
348 | goto out_noenablereg; | ||
349 | } | ||
350 | if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) { | ||
351 | printk(KERN_ERR PFX | ||
352 | "BASETIME method I/O %X is not available.\n", | ||
353 | SBC8360_BASETIME); | ||
354 | res = -EIO; | ||
355 | goto out_nobasetimereg; | ||
356 | } | ||
357 | |||
358 | res = register_reboot_notifier(&sbc8360_notifier); | ||
359 | if (res) { | ||
360 | printk(KERN_ERR PFX "Failed to register reboot notifier.\n"); | ||
361 | goto out_noreboot; | ||
362 | } | ||
363 | |||
364 | if (timeout < 0 || timeout > 63) { | ||
365 | printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n"); | ||
366 | res = -EINVAL; | ||
367 | goto out_noreboot; | ||
368 | } | ||
369 | |||
370 | wd_margin = wd_times[timeout][0]; | ||
371 | wd_multiplier = wd_times[timeout][1]; | ||
372 | |||
373 | if (wd_multiplier == 1) | ||
374 | mseconds = (wd_margin + 1) * 500; | ||
375 | else if (wd_multiplier == 2) | ||
376 | mseconds = (wd_margin + 1) * 5000; | ||
377 | else if (wd_multiplier == 3) | ||
378 | mseconds = (wd_margin + 1) * 50000; | ||
379 | else if (wd_multiplier == 4) | ||
380 | mseconds = (wd_margin + 1) * 100000; | ||
381 | |||
382 | /* My kingdom for the ability to print "0.5 seconds" in the kernel! */ | ||
383 | printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds); | ||
384 | |||
385 | return 0; | ||
386 | |||
387 | out_noreboot: | ||
388 | release_region(SBC8360_ENABLE, 1); | ||
389 | release_region(SBC8360_BASETIME, 1); | ||
390 | out_noenablereg: | ||
391 | out_nobasetimereg: | ||
392 | misc_deregister(&sbc8360_miscdev); | ||
393 | out_nomisc: | ||
394 | return res; | ||
395 | } | ||
396 | |||
397 | static void __exit sbc8360_exit(void) | ||
398 | { | ||
399 | misc_deregister(&sbc8360_miscdev); | ||
400 | unregister_reboot_notifier(&sbc8360_notifier); | ||
401 | release_region(SBC8360_ENABLE, 1); | ||
402 | release_region(SBC8360_BASETIME, 1); | ||
403 | } | ||
404 | |||
405 | module_init(sbc8360_init); | ||
406 | module_exit(sbc8360_exit); | ||
407 | |||
408 | MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>"); | ||
409 | MODULE_DESCRIPTION("SBC8360 watchdog driver"); | ||
410 | MODULE_LICENSE("GPL"); | ||
411 | MODULE_VERSION("1.0"); | ||
412 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
413 | |||
414 | /* end of sbc8360.c */ | ||
diff --git a/drivers/char/watchdog/w83977f_wdt.c b/drivers/char/watchdog/w83977f_wdt.c new file mode 100644 index 000000000000..a7ff64c8921f --- /dev/null +++ b/drivers/char/watchdog/w83977f_wdt.c | |||
@@ -0,0 +1,543 @@ | |||
1 | /* | ||
2 | * W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip | ||
3 | * | ||
4 | * (c) Copyright 2005 Jose Goncalves <jose.goncalves@inov.pt> | ||
5 | * | ||
6 | * Based on w83877f_wdt.c by Scott Jennings, | ||
7 | * and wdt977.c by Woody Suwalski | ||
8 | * | ||
9 | * ----------------------- | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleparam.h> | ||
20 | #include <linux/config.h> | ||
21 | #include <linux/types.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/fs.h> | ||
24 | #include <linux/miscdevice.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/ioport.h> | ||
27 | #include <linux/watchdog.h> | ||
28 | #include <linux/notifier.h> | ||
29 | #include <linux/reboot.h> | ||
30 | |||
31 | #include <asm/io.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | |||
35 | #define WATCHDOG_VERSION "1.00" | ||
36 | #define WATCHDOG_NAME "W83977F WDT" | ||
37 | #define PFX WATCHDOG_NAME ": " | ||
38 | #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" | ||
39 | |||
40 | #define IO_INDEX_PORT 0x3F0 | ||
41 | #define IO_DATA_PORT (IO_INDEX_PORT+1) | ||
42 | |||
43 | #define UNLOCK_DATA 0x87 | ||
44 | #define LOCK_DATA 0xAA | ||
45 | #define DEVICE_REGISTER 0x07 | ||
46 | |||
47 | #define DEFAULT_TIMEOUT 45 /* default timeout in seconds */ | ||
48 | |||
49 | static int timeout = DEFAULT_TIMEOUT; | ||
50 | static int timeoutW; /* timeout in watchdog counter units */ | ||
51 | static unsigned long timer_alive; | ||
52 | static int testmode; | ||
53 | static char expect_close; | ||
54 | static spinlock_t spinlock; | ||
55 | |||
56 | module_param(timeout, int, 0); | ||
57 | MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); | ||
58 | module_param(testmode, int, 0); | ||
59 | MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); | ||
60 | |||
61 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
62 | module_param(nowayout, int, 0); | ||
63 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | ||
64 | |||
65 | /* | ||
66 | * Start the watchdog | ||
67 | */ | ||
68 | |||
69 | static int wdt_start(void) | ||
70 | { | ||
71 | unsigned long flags; | ||
72 | |||
73 | spin_lock_irqsave(&spinlock, flags); | ||
74 | |||
75 | /* Unlock the SuperIO chip */ | ||
76 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
77 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
78 | |||
79 | /* | ||
80 | * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. | ||
81 | * F2 has the timeout in watchdog counter units. | ||
82 | * F3 is set to enable watchdog LED blink at timeout. | ||
83 | * F4 is used to just clear the TIMEOUT'ed state (bit 0). | ||
84 | */ | ||
85 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | ||
86 | outb_p(0x08,IO_DATA_PORT); | ||
87 | outb_p(0xF2,IO_INDEX_PORT); | ||
88 | outb_p(timeoutW,IO_DATA_PORT); | ||
89 | outb_p(0xF3,IO_INDEX_PORT); | ||
90 | outb_p(0x08,IO_DATA_PORT); | ||
91 | outb_p(0xF4,IO_INDEX_PORT); | ||
92 | outb_p(0x00,IO_DATA_PORT); | ||
93 | |||
94 | /* Set device Aux2 active */ | ||
95 | outb_p(0x30,IO_INDEX_PORT); | ||
96 | outb_p(0x01,IO_DATA_PORT); | ||
97 | |||
98 | /* | ||
99 | * Select device Aux1 (dev=7) to set GP16 as the watchdog output | ||
100 | * (in reg E6) and GP13 as the watchdog LED output (in reg E3). | ||
101 | * Map GP16 at pin 119. | ||
102 | * In test mode watch the bit 0 on F4 to indicate "triggered" or | ||
103 | * check watchdog LED on SBC. | ||
104 | */ | ||
105 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | ||
106 | outb_p(0x07,IO_DATA_PORT); | ||
107 | if (!testmode) | ||
108 | { | ||
109 | unsigned pin_map; | ||
110 | |||
111 | outb_p(0xE6,IO_INDEX_PORT); | ||
112 | outb_p(0x0A,IO_DATA_PORT); | ||
113 | outb_p(0x2C,IO_INDEX_PORT); | ||
114 | pin_map = inb_p(IO_DATA_PORT); | ||
115 | pin_map |= 0x10; | ||
116 | pin_map &= ~(0x20); | ||
117 | outb_p(0x2C,IO_INDEX_PORT); | ||
118 | outb_p(pin_map,IO_DATA_PORT); | ||
119 | } | ||
120 | outb_p(0xE3,IO_INDEX_PORT); | ||
121 | outb_p(0x08,IO_DATA_PORT); | ||
122 | |||
123 | /* Set device Aux1 active */ | ||
124 | outb_p(0x30,IO_INDEX_PORT); | ||
125 | outb_p(0x01,IO_DATA_PORT); | ||
126 | |||
127 | /* Lock the SuperIO chip */ | ||
128 | outb_p(LOCK_DATA,IO_INDEX_PORT); | ||
129 | |||
130 | spin_unlock_irqrestore(&spinlock, flags); | ||
131 | |||
132 | printk(KERN_INFO PFX "activated.\n"); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | /* | ||
138 | * Stop the watchdog | ||
139 | */ | ||
140 | |||
141 | static int wdt_stop(void) | ||
142 | { | ||
143 | unsigned long flags; | ||
144 | |||
145 | spin_lock_irqsave(&spinlock, flags); | ||
146 | |||
147 | /* Unlock the SuperIO chip */ | ||
148 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
149 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
150 | |||
151 | /* | ||
152 | * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. | ||
153 | * F2 is reset to its default value (watchdog timer disabled). | ||
154 | * F3 is reset to its default state. | ||
155 | * F4 clears the TIMEOUT'ed state (bit 0) - back to default. | ||
156 | */ | ||
157 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | ||
158 | outb_p(0x08,IO_DATA_PORT); | ||
159 | outb_p(0xF2,IO_INDEX_PORT); | ||
160 | outb_p(0xFF,IO_DATA_PORT); | ||
161 | outb_p(0xF3,IO_INDEX_PORT); | ||
162 | outb_p(0x00,IO_DATA_PORT); | ||
163 | outb_p(0xF4,IO_INDEX_PORT); | ||
164 | outb_p(0x00,IO_DATA_PORT); | ||
165 | outb_p(0xF2,IO_INDEX_PORT); | ||
166 | outb_p(0x00,IO_DATA_PORT); | ||
167 | |||
168 | /* | ||
169 | * Select device Aux1 (dev=7) to set GP16 (in reg E6) and | ||
170 | * Gp13 (in reg E3) as inputs. | ||
171 | */ | ||
172 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | ||
173 | outb_p(0x07,IO_DATA_PORT); | ||
174 | if (!testmode) | ||
175 | { | ||
176 | outb_p(0xE6,IO_INDEX_PORT); | ||
177 | outb_p(0x01,IO_DATA_PORT); | ||
178 | } | ||
179 | outb_p(0xE3,IO_INDEX_PORT); | ||
180 | outb_p(0x01,IO_DATA_PORT); | ||
181 | |||
182 | /* Lock the SuperIO chip */ | ||
183 | outb_p(LOCK_DATA,IO_INDEX_PORT); | ||
184 | |||
185 | spin_unlock_irqrestore(&spinlock, flags); | ||
186 | |||
187 | printk(KERN_INFO PFX "shutdown.\n"); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Send a keepalive ping to the watchdog | ||
194 | * This is done by simply re-writing the timeout to reg. 0xF2 | ||
195 | */ | ||
196 | |||
197 | static int wdt_keepalive(void) | ||
198 | { | ||
199 | unsigned long flags; | ||
200 | |||
201 | spin_lock_irqsave(&spinlock, flags); | ||
202 | |||
203 | /* Unlock the SuperIO chip */ | ||
204 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
205 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
206 | |||
207 | /* Select device Aux2 (device=8) to kick watchdog reg F2 */ | ||
208 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | ||
209 | outb_p(0x08,IO_DATA_PORT); | ||
210 | outb_p(0xF2,IO_INDEX_PORT); | ||
211 | outb_p(timeoutW,IO_DATA_PORT); | ||
212 | |||
213 | /* Lock the SuperIO chip */ | ||
214 | outb_p(LOCK_DATA,IO_INDEX_PORT); | ||
215 | |||
216 | spin_unlock_irqrestore(&spinlock, flags); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Set the watchdog timeout value | ||
223 | */ | ||
224 | |||
225 | static int wdt_set_timeout(int t) | ||
226 | { | ||
227 | int tmrval; | ||
228 | |||
229 | /* | ||
230 | * Convert seconds to watchdog counter time units, rounding up. | ||
231 | * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup | ||
232 | * value. This information is supplied in the PCM-5335 manual and was | ||
233 | * checked by me on a real board. This is a bit strange because W83977f | ||
234 | * datasheet says counter unit is in minutes! | ||
235 | */ | ||
236 | if (t < 15) | ||
237 | return -EINVAL; | ||
238 | |||
239 | tmrval = ((t + 15) + 29) / 30; | ||
240 | |||
241 | if (tmrval > 255) | ||
242 | return -EINVAL; | ||
243 | |||
244 | /* | ||
245 | * timeout is the timeout in seconds, | ||
246 | * timeoutW is the timeout in watchdog counter units. | ||
247 | */ | ||
248 | timeoutW = tmrval; | ||
249 | timeout = (timeoutW * 30) - 15; | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | /* | ||
254 | * Get the watchdog status | ||
255 | */ | ||
256 | |||
257 | static int wdt_get_status(int *status) | ||
258 | { | ||
259 | int new_status; | ||
260 | unsigned long flags; | ||
261 | |||
262 | spin_lock_irqsave(&spinlock, flags); | ||
263 | |||
264 | /* Unlock the SuperIO chip */ | ||
265 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
266 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | ||
267 | |||
268 | /* Select device Aux2 (device=8) to read watchdog reg F4 */ | ||
269 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | ||
270 | outb_p(0x08,IO_DATA_PORT); | ||
271 | outb_p(0xF4,IO_INDEX_PORT); | ||
272 | new_status = inb_p(IO_DATA_PORT); | ||
273 | |||
274 | /* Lock the SuperIO chip */ | ||
275 | outb_p(LOCK_DATA,IO_INDEX_PORT); | ||
276 | |||
277 | spin_unlock_irqrestore(&spinlock, flags); | ||
278 | |||
279 | *status = 0; | ||
280 | if (new_status & 1) | ||
281 | *status |= WDIOF_CARDRESET; | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | |||
287 | /* | ||
288 | * /dev/watchdog handling | ||
289 | */ | ||
290 | |||
291 | static int wdt_open(struct inode *inode, struct file *file) | ||
292 | { | ||
293 | /* If the watchdog is alive we don't need to start it again */ | ||
294 | if( test_and_set_bit(0, &timer_alive) ) | ||
295 | return -EBUSY; | ||
296 | |||
297 | if (nowayout) | ||
298 | __module_get(THIS_MODULE); | ||
299 | |||
300 | wdt_start(); | ||
301 | return nonseekable_open(inode, file); | ||
302 | } | ||
303 | |||
304 | static int wdt_release(struct inode *inode, struct file *file) | ||
305 | { | ||
306 | /* | ||
307 | * Shut off the timer. | ||
308 | * Lock it in if it's a module and we set nowayout | ||
309 | */ | ||
310 | if (expect_close == 42) | ||
311 | { | ||
312 | wdt_stop(); | ||
313 | clear_bit(0, &timer_alive); | ||
314 | } else { | ||
315 | wdt_keepalive(); | ||
316 | printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); | ||
317 | } | ||
318 | expect_close = 0; | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * wdt_write: | ||
324 | * @file: file handle to the watchdog | ||
325 | * @buf: buffer to write (unused as data does not matter here | ||
326 | * @count: count of bytes | ||
327 | * @ppos: pointer to the position to write. No seeks allowed | ||
328 | * | ||
329 | * A write to a watchdog device is defined as a keepalive signal. Any | ||
330 | * write of data will do, as we we don't define content meaning. | ||
331 | */ | ||
332 | |||
333 | static ssize_t wdt_write(struct file *file, const char __user *buf, | ||
334 | size_t count, loff_t *ppos) | ||
335 | { | ||
336 | /* See if we got the magic character 'V' and reload the timer */ | ||
337 | if(count) | ||
338 | { | ||
339 | if (!nowayout) | ||
340 | { | ||
341 | size_t ofs; | ||
342 | |||
343 | /* note: just in case someone wrote the magic character long ago */ | ||
344 | expect_close = 0; | ||
345 | |||
346 | /* scan to see whether or not we got the magic character */ | ||
347 | for(ofs = 0; ofs != count; ofs++) | ||
348 | { | ||
349 | char c; | ||
350 | if (get_user(c, buf + ofs)) | ||
351 | return -EFAULT; | ||
352 | if (c == 'V') { | ||
353 | expect_close = 42; | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | |||
358 | /* someone wrote to us, we should restart timer */ | ||
359 | wdt_keepalive(); | ||
360 | } | ||
361 | return count; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * wdt_ioctl: | ||
366 | * @inode: inode of the device | ||
367 | * @file: file handle to the device | ||
368 | * @cmd: watchdog command | ||
369 | * @arg: argument pointer | ||
370 | * | ||
371 | * The watchdog API defines a common set of functions for all watchdogs | ||
372 | * according to their available features. | ||
373 | */ | ||
374 | |||
375 | static struct watchdog_info ident = { | ||
376 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | ||
377 | .firmware_version = 1, | ||
378 | .identity = WATCHDOG_NAME, | ||
379 | }; | ||
380 | |||
381 | static int wdt_ioctl(struct inode *inode, struct file *file, | ||
382 | unsigned int cmd, unsigned long arg) | ||
383 | { | ||
384 | int status; | ||
385 | int new_options, retval = -EINVAL; | ||
386 | int new_timeout; | ||
387 | union { | ||
388 | struct watchdog_info __user *ident; | ||
389 | int __user *i; | ||
390 | } uarg; | ||
391 | |||
392 | uarg.i = (int __user *)arg; | ||
393 | |||
394 | switch(cmd) | ||
395 | { | ||
396 | default: | ||
397 | return -ENOIOCTLCMD; | ||
398 | |||
399 | case WDIOC_GETSUPPORT: | ||
400 | return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
401 | |||
402 | case WDIOC_GETSTATUS: | ||
403 | wdt_get_status(&status); | ||
404 | return put_user(status, uarg.i); | ||
405 | |||
406 | case WDIOC_GETBOOTSTATUS: | ||
407 | return put_user(0, uarg.i); | ||
408 | |||
409 | case WDIOC_KEEPALIVE: | ||
410 | wdt_keepalive(); | ||
411 | return 0; | ||
412 | |||
413 | case WDIOC_SETOPTIONS: | ||
414 | if (get_user (new_options, uarg.i)) | ||
415 | return -EFAULT; | ||
416 | |||
417 | if (new_options & WDIOS_DISABLECARD) { | ||
418 | wdt_stop(); | ||
419 | retval = 0; | ||
420 | } | ||
421 | |||
422 | if (new_options & WDIOS_ENABLECARD) { | ||
423 | wdt_start(); | ||
424 | retval = 0; | ||
425 | } | ||
426 | |||
427 | return retval; | ||
428 | |||
429 | case WDIOC_SETTIMEOUT: | ||
430 | if (get_user(new_timeout, uarg.i)) | ||
431 | return -EFAULT; | ||
432 | |||
433 | if (wdt_set_timeout(new_timeout)) | ||
434 | return -EINVAL; | ||
435 | |||
436 | wdt_keepalive(); | ||
437 | /* Fall */ | ||
438 | |||
439 | case WDIOC_GETTIMEOUT: | ||
440 | return put_user(timeout, uarg.i); | ||
441 | |||
442 | } | ||
443 | } | ||
444 | |||
445 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
446 | void *unused) | ||
447 | { | ||
448 | if (code==SYS_DOWN || code==SYS_HALT) | ||
449 | wdt_stop(); | ||
450 | return NOTIFY_DONE; | ||
451 | } | ||
452 | |||
453 | static struct file_operations wdt_fops= | ||
454 | { | ||
455 | .owner = THIS_MODULE, | ||
456 | .llseek = no_llseek, | ||
457 | .write = wdt_write, | ||
458 | .ioctl = wdt_ioctl, | ||
459 | .open = wdt_open, | ||
460 | .release = wdt_release, | ||
461 | }; | ||
462 | |||
463 | static struct miscdevice wdt_miscdev= | ||
464 | { | ||
465 | .minor = WATCHDOG_MINOR, | ||
466 | .name = "watchdog", | ||
467 | .fops = &wdt_fops, | ||
468 | }; | ||
469 | |||
470 | static struct notifier_block wdt_notifier = { | ||
471 | .notifier_call = wdt_notify_sys, | ||
472 | }; | ||
473 | |||
474 | static int __init w83977f_wdt_init(void) | ||
475 | { | ||
476 | int rc; | ||
477 | |||
478 | printk(KERN_INFO PFX DRIVER_VERSION); | ||
479 | |||
480 | spin_lock_init(&spinlock); | ||
481 | |||
482 | /* | ||
483 | * Check that the timeout value is within it's range ; | ||
484 | * if not reset to the default | ||
485 | */ | ||
486 | if (wdt_set_timeout(timeout)) { | ||
487 | wdt_set_timeout(DEFAULT_TIMEOUT); | ||
488 | printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n", | ||
489 | DEFAULT_TIMEOUT); | ||
490 | } | ||
491 | |||
492 | if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) | ||
493 | { | ||
494 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | ||
495 | IO_INDEX_PORT); | ||
496 | rc = -EIO; | ||
497 | goto err_out; | ||
498 | } | ||
499 | |||
500 | rc = misc_register(&wdt_miscdev); | ||
501 | if (rc) | ||
502 | { | ||
503 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | ||
504 | wdt_miscdev.minor, rc); | ||
505 | goto err_out_region; | ||
506 | } | ||
507 | |||
508 | rc = register_reboot_notifier(&wdt_notifier); | ||
509 | if (rc) | ||
510 | { | ||
511 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | ||
512 | rc); | ||
513 | goto err_out_miscdev; | ||
514 | } | ||
515 | |||
516 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", | ||
517 | timeout, nowayout, testmode); | ||
518 | |||
519 | return 0; | ||
520 | |||
521 | err_out_miscdev: | ||
522 | misc_deregister(&wdt_miscdev); | ||
523 | err_out_region: | ||
524 | release_region(IO_INDEX_PORT,2); | ||
525 | err_out: | ||
526 | return rc; | ||
527 | } | ||
528 | |||
529 | static void __exit w83977f_wdt_exit(void) | ||
530 | { | ||
531 | wdt_stop(); | ||
532 | misc_deregister(&wdt_miscdev); | ||
533 | unregister_reboot_notifier(&wdt_notifier); | ||
534 | release_region(IO_INDEX_PORT,2); | ||
535 | } | ||
536 | |||
537 | module_init(w83977f_wdt_init); | ||
538 | module_exit(w83977f_wdt_exit); | ||
539 | |||
540 | MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>"); | ||
541 | MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip"); | ||
542 | MODULE_LICENSE("GPL"); | ||
543 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 3b865f34a095..b66782398258 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c | |||
@@ -50,7 +50,7 @@ | |||
50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); | 50 | MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>"); |
51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); | 51 | MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems"); |
52 | MODULE_LICENSE("GPL"); | 52 | MODULE_LICENSE("GPL"); |
53 | MODULE_VERSION("1.0"); | 53 | MODULE_VERSION("2.0"); |
54 | 54 | ||
55 | #define BIOS_SCAN_LIMIT 0xffffffff | 55 | #define BIOS_SCAN_LIMIT 0xffffffff |
56 | #define MAX_IMAGE_LENGTH 16 | 56 | #define MAX_IMAGE_LENGTH 16 |
@@ -65,10 +65,11 @@ static struct _rbu_data { | |||
65 | unsigned long packet_write_count; | 65 | unsigned long packet_write_count; |
66 | unsigned long num_packets; | 66 | unsigned long num_packets; |
67 | unsigned long packetsize; | 67 | unsigned long packetsize; |
68 | int entry_created; | ||
68 | } rbu_data; | 69 | } rbu_data; |
69 | 70 | ||
70 | static char image_type[MAX_IMAGE_LENGTH] = "mono"; | 71 | static char image_type[MAX_IMAGE_LENGTH + 1] = "mono"; |
71 | module_param_string(image_type, image_type, sizeof(image_type), 0); | 72 | module_param_string(image_type, image_type, sizeof (image_type), 0); |
72 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); | 73 | MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet"); |
73 | 74 | ||
74 | struct packet_data { | 75 | struct packet_data { |
@@ -114,7 +115,7 @@ static int fill_last_packet(void *data, size_t length) | |||
114 | 115 | ||
115 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { | 116 | if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) { |
116 | pr_debug("dell_rbu:%s: packet size data " | 117 | pr_debug("dell_rbu:%s: packet size data " |
117 | "overrun\n", __FUNCTION__); | 118 | "overrun\n", __FUNCTION__); |
118 | return -EINVAL; | 119 | return -EINVAL; |
119 | } | 120 | } |
120 | 121 | ||
@@ -146,12 +147,14 @@ static int create_packet(size_t length) | |||
146 | pr_debug("create_packet: packetsize not specified\n"); | 147 | pr_debug("create_packet: packetsize not specified\n"); |
147 | return -EINVAL; | 148 | return -EINVAL; |
148 | } | 149 | } |
150 | spin_unlock(&rbu_data.lock); | ||
151 | newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL); | ||
152 | spin_lock(&rbu_data.lock); | ||
149 | 153 | ||
150 | newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL); | ||
151 | if (!newpacket) { | 154 | if (!newpacket) { |
152 | printk(KERN_WARNING | 155 | printk(KERN_WARNING |
153 | "dell_rbu:%s: failed to allocate new " | 156 | "dell_rbu:%s: failed to allocate new " |
154 | "packet\n", __FUNCTION__); | 157 | "packet\n", __FUNCTION__); |
155 | return -ENOMEM; | 158 | return -ENOMEM; |
156 | } | 159 | } |
157 | 160 | ||
@@ -160,15 +163,17 @@ static int create_packet(size_t length) | |||
160 | * there is no upper limit on memory | 163 | * there is no upper limit on memory |
161 | * address for packetized mechanism | 164 | * address for packetized mechanism |
162 | */ | 165 | */ |
163 | newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL, | 166 | spin_unlock(&rbu_data.lock); |
164 | ordernum); | 167 | newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL, |
168 | ordernum); | ||
169 | spin_lock(&rbu_data.lock); | ||
165 | 170 | ||
166 | pr_debug("create_packet: newpacket %p\n", newpacket->data); | 171 | pr_debug("create_packet: newpacket %p\n", newpacket->data); |
167 | 172 | ||
168 | if (!newpacket->data) { | 173 | if (!newpacket->data) { |
169 | printk(KERN_WARNING | 174 | printk(KERN_WARNING |
170 | "dell_rbu:%s: failed to allocate new " | 175 | "dell_rbu:%s: failed to allocate new " |
171 | "packet\n", __FUNCTION__); | 176 | "packet\n", __FUNCTION__); |
172 | kfree(newpacket); | 177 | kfree(newpacket); |
173 | return -ENOMEM; | 178 | return -ENOMEM; |
174 | } | 179 | } |
@@ -204,9 +209,8 @@ static int packetize_data(void *data, size_t length) | |||
204 | return rc; | 209 | return rc; |
205 | } | 210 | } |
206 | 211 | ||
207 | static int | 212 | static int do_packet_read(char *data, struct list_head *ptemp_list, |
208 | do_packet_read(char *data, struct list_head *ptemp_list, | 213 | int length, int bytes_read, int *list_read_count) |
209 | int length, int bytes_read, int *list_read_count) | ||
210 | { | 214 | { |
211 | void *ptemp_buf; | 215 | void *ptemp_buf; |
212 | struct packet_data *newpacket = NULL; | 216 | struct packet_data *newpacket = NULL; |
@@ -239,7 +243,7 @@ do_packet_read(char *data, struct list_head *ptemp_list, | |||
239 | return bytes_copied; | 243 | return bytes_copied; |
240 | } | 244 | } |
241 | 245 | ||
242 | static int packet_read_list(char *data, size_t * pread_length) | 246 | static int packet_read_list(char *data, size_t *pread_length) |
243 | { | 247 | { |
244 | struct list_head *ptemp_list; | 248 | struct list_head *ptemp_list; |
245 | int temp_count = 0; | 249 | int temp_count = 0; |
@@ -258,8 +262,7 @@ static int packet_read_list(char *data, size_t * pread_length) | |||
258 | ptemp_list = (&packet_data_head.list)->next; | 262 | ptemp_list = (&packet_data_head.list)->next; |
259 | while (!list_empty(ptemp_list)) { | 263 | while (!list_empty(ptemp_list)) { |
260 | bytes_copied = do_packet_read(pdest, ptemp_list, | 264 | bytes_copied = do_packet_read(pdest, ptemp_list, |
261 | remaining_bytes, bytes_read, | 265 | remaining_bytes, bytes_read, &temp_count); |
262 | &temp_count); | ||
263 | remaining_bytes -= bytes_copied; | 266 | remaining_bytes -= bytes_copied; |
264 | bytes_read += bytes_copied; | 267 | bytes_read += bytes_copied; |
265 | pdest += bytes_copied; | 268 | pdest += bytes_copied; |
@@ -287,7 +290,7 @@ static void packet_empty_list(void) | |||
287 | ptemp_list = (&packet_data_head.list)->next; | 290 | ptemp_list = (&packet_data_head.list)->next; |
288 | while (!list_empty(ptemp_list)) { | 291 | while (!list_empty(ptemp_list)) { |
289 | newpacket = | 292 | newpacket = |
290 | list_entry(ptemp_list, struct packet_data, list); | 293 | list_entry(ptemp_list, struct packet_data, list); |
291 | pnext_list = ptemp_list->next; | 294 | pnext_list = ptemp_list->next; |
292 | list_del(ptemp_list); | 295 | list_del(ptemp_list); |
293 | ptemp_list = pnext_list; | 296 | ptemp_list = pnext_list; |
@@ -296,8 +299,8 @@ static void packet_empty_list(void) | |||
296 | * to make sure there are no stale RBU packets left in memory | 299 | * to make sure there are no stale RBU packets left in memory |
297 | */ | 300 | */ |
298 | memset(newpacket->data, 0, rbu_data.packetsize); | 301 | memset(newpacket->data, 0, rbu_data.packetsize); |
299 | free_pages((unsigned long)newpacket->data, | 302 | free_pages((unsigned long) newpacket->data, |
300 | newpacket->ordernum); | 303 | newpacket->ordernum); |
301 | kfree(newpacket); | 304 | kfree(newpacket); |
302 | } | 305 | } |
303 | rbu_data.packet_write_count = 0; | 306 | rbu_data.packet_write_count = 0; |
@@ -319,14 +322,13 @@ static void img_update_free(void) | |||
319 | * BIOS image copied in memory. | 322 | * BIOS image copied in memory. |
320 | */ | 323 | */ |
321 | memset(rbu_data.image_update_buffer, 0, | 324 | memset(rbu_data.image_update_buffer, 0, |
322 | rbu_data.image_update_buffer_size); | 325 | rbu_data.image_update_buffer_size); |
323 | if (rbu_data.dma_alloc == 1) | 326 | if (rbu_data.dma_alloc == 1) |
324 | dma_free_coherent(NULL, rbu_data.bios_image_size, | 327 | dma_free_coherent(NULL, rbu_data.bios_image_size, |
325 | rbu_data.image_update_buffer, | 328 | rbu_data.image_update_buffer, dell_rbu_dmaaddr); |
326 | dell_rbu_dmaaddr); | ||
327 | else | 329 | else |
328 | free_pages((unsigned long)rbu_data.image_update_buffer, | 330 | free_pages((unsigned long) rbu_data.image_update_buffer, |
329 | rbu_data.image_update_ordernum); | 331 | rbu_data.image_update_ordernum); |
330 | 332 | ||
331 | /* | 333 | /* |
332 | * Re-initialize the rbu_data variables after a free | 334 | * Re-initialize the rbu_data variables after a free |
@@ -366,7 +368,7 @@ static int img_update_realloc(unsigned long size) | |||
366 | */ | 368 | */ |
367 | if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { | 369 | if ((size != 0) && (rbu_data.image_update_buffer == NULL)) { |
368 | printk(KERN_ERR "dell_rbu:%s: corruption " | 370 | printk(KERN_ERR "dell_rbu:%s: corruption " |
369 | "check failed\n", __FUNCTION__); | 371 | "check failed\n", __FUNCTION__); |
370 | return -EINVAL; | 372 | return -EINVAL; |
371 | } | 373 | } |
372 | /* | 374 | /* |
@@ -385,17 +387,16 @@ static int img_update_realloc(unsigned long size) | |||
385 | 387 | ||
386 | ordernum = get_order(size); | 388 | ordernum = get_order(size); |
387 | image_update_buffer = | 389 | image_update_buffer = |
388 | (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum); | 390 | (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum); |
389 | 391 | ||
390 | img_buf_phys_addr = | 392 | img_buf_phys_addr = |
391 | (unsigned long)virt_to_phys(image_update_buffer); | 393 | (unsigned long) virt_to_phys(image_update_buffer); |
392 | 394 | ||
393 | if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { | 395 | if (img_buf_phys_addr > BIOS_SCAN_LIMIT) { |
394 | free_pages((unsigned long)image_update_buffer, ordernum); | 396 | free_pages((unsigned long) image_update_buffer, ordernum); |
395 | ordernum = -1; | 397 | ordernum = -1; |
396 | image_update_buffer = dma_alloc_coherent(NULL, size, | 398 | image_update_buffer = dma_alloc_coherent(NULL, size, |
397 | &dell_rbu_dmaaddr, | 399 | &dell_rbu_dmaaddr, GFP_KERNEL); |
398 | GFP_KERNEL); | ||
399 | dma_alloc = 1; | 400 | dma_alloc = 1; |
400 | } | 401 | } |
401 | 402 | ||
@@ -405,13 +406,13 @@ static int img_update_realloc(unsigned long size) | |||
405 | rbu_data.image_update_buffer = image_update_buffer; | 406 | rbu_data.image_update_buffer = image_update_buffer; |
406 | rbu_data.image_update_buffer_size = size; | 407 | rbu_data.image_update_buffer_size = size; |
407 | rbu_data.bios_image_size = | 408 | rbu_data.bios_image_size = |
408 | rbu_data.image_update_buffer_size; | 409 | rbu_data.image_update_buffer_size; |
409 | rbu_data.image_update_ordernum = ordernum; | 410 | rbu_data.image_update_ordernum = ordernum; |
410 | rbu_data.dma_alloc = dma_alloc; | 411 | rbu_data.dma_alloc = dma_alloc; |
411 | rc = 0; | 412 | rc = 0; |
412 | } else { | 413 | } else { |
413 | pr_debug("Not enough memory for image update:" | 414 | pr_debug("Not enough memory for image update:" |
414 | "size = %ld\n", size); | 415 | "size = %ld\n", size); |
415 | rc = -ENOMEM; | 416 | rc = -ENOMEM; |
416 | } | 417 | } |
417 | 418 | ||
@@ -438,7 +439,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count) | |||
438 | if (pos > imagesize) { | 439 | if (pos > imagesize) { |
439 | retval = 0; | 440 | retval = 0; |
440 | printk(KERN_WARNING "dell_rbu:read_packet_data: " | 441 | printk(KERN_WARNING "dell_rbu:read_packet_data: " |
441 | "data underrun\n"); | 442 | "data underrun\n"); |
442 | goto read_rbu_data_exit; | 443 | goto read_rbu_data_exit; |
443 | } | 444 | } |
444 | 445 | ||
@@ -468,11 +469,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
468 | 469 | ||
469 | /* check to see if we have something to return */ | 470 | /* check to see if we have something to return */ |
470 | if ((rbu_data.image_update_buffer == NULL) || | 471 | if ((rbu_data.image_update_buffer == NULL) || |
471 | (rbu_data.bios_image_size == 0)) { | 472 | (rbu_data.bios_image_size == 0)) { |
472 | pr_debug("read_rbu_data_mono: image_update_buffer %p ," | 473 | pr_debug("read_rbu_data_mono: image_update_buffer %p ," |
473 | "bios_image_size %lu\n", | 474 | "bios_image_size %lu\n", |
474 | rbu_data.image_update_buffer, | 475 | rbu_data.image_update_buffer, |
475 | rbu_data.bios_image_size); | 476 | rbu_data.bios_image_size); |
476 | ret_count = -ENOMEM; | 477 | ret_count = -ENOMEM; |
477 | goto read_rbu_data_exit; | 478 | goto read_rbu_data_exit; |
478 | } | 479 | } |
@@ -497,8 +498,8 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count) | |||
497 | return ret_count; | 498 | return ret_count; |
498 | } | 499 | } |
499 | 500 | ||
500 | static ssize_t | 501 | static ssize_t read_rbu_data(struct kobject *kobj, char *buffer, |
501 | read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) | 502 | loff_t pos, size_t count) |
502 | { | 503 | { |
503 | ssize_t ret_count = 0; | 504 | ssize_t ret_count = 0; |
504 | 505 | ||
@@ -515,62 +516,20 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count) | |||
515 | return ret_count; | 516 | return ret_count; |
516 | } | 517 | } |
517 | 518 | ||
518 | static ssize_t | ||
519 | read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
520 | size_t count) | ||
521 | { | ||
522 | int size = 0; | ||
523 | if (!pos) | ||
524 | size = sprintf(buffer, "%s\n", image_type); | ||
525 | return size; | ||
526 | } | ||
527 | |||
528 | static ssize_t | ||
529 | write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos, | ||
530 | size_t count) | ||
531 | { | ||
532 | int rc = count; | ||
533 | spin_lock(&rbu_data.lock); | ||
534 | |||
535 | if (strlen(buffer) < MAX_IMAGE_LENGTH) | ||
536 | sscanf(buffer, "%s", image_type); | ||
537 | else | ||
538 | printk(KERN_WARNING "dell_rbu: image_type is invalid" | ||
539 | "max chars = %d, \n incoming str--%s-- \n", | ||
540 | MAX_IMAGE_LENGTH, buffer); | ||
541 | |||
542 | /* we must free all previous allocations */ | ||
543 | packet_empty_list(); | ||
544 | img_update_free(); | ||
545 | |||
546 | spin_unlock(&rbu_data.lock); | ||
547 | return rc; | ||
548 | |||
549 | } | ||
550 | |||
551 | static struct bin_attribute rbu_data_attr = { | ||
552 | .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444}, | ||
553 | .read = read_rbu_data, | ||
554 | }; | ||
555 | |||
556 | static struct bin_attribute rbu_image_type_attr = { | ||
557 | .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644}, | ||
558 | .read = read_rbu_image_type, | ||
559 | .write = write_rbu_image_type, | ||
560 | }; | ||
561 | |||
562 | static void callbackfn_rbu(const struct firmware *fw, void *context) | 519 | static void callbackfn_rbu(const struct firmware *fw, void *context) |
563 | { | 520 | { |
564 | int rc = 0; | 521 | int rc = 0; |
565 | 522 | ||
566 | if (!fw || !fw->size) | 523 | if (!fw || !fw->size) { |
524 | rbu_data.entry_created = 0; | ||
567 | return; | 525 | return; |
526 | } | ||
568 | 527 | ||
569 | spin_lock(&rbu_data.lock); | 528 | spin_lock(&rbu_data.lock); |
570 | if (!strcmp(image_type, "mono")) { | 529 | if (!strcmp(image_type, "mono")) { |
571 | if (!img_update_realloc(fw->size)) | 530 | if (!img_update_realloc(fw->size)) |
572 | memcpy(rbu_data.image_update_buffer, | 531 | memcpy(rbu_data.image_update_buffer, |
573 | fw->data, fw->size); | 532 | fw->data, fw->size); |
574 | } else if (!strcmp(image_type, "packet")) { | 533 | } else if (!strcmp(image_type, "packet")) { |
575 | if (!rbu_data.packetsize) | 534 | if (!rbu_data.packetsize) |
576 | rbu_data.packetsize = fw->size; | 535 | rbu_data.packetsize = fw->size; |
@@ -584,14 +543,103 @@ static void callbackfn_rbu(const struct firmware *fw, void *context) | |||
584 | spin_unlock(&rbu_data.lock); | 543 | spin_unlock(&rbu_data.lock); |
585 | 544 | ||
586 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 545 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, |
587 | "dell_rbu", &rbu_device->dev, | 546 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); |
588 | &context, callbackfn_rbu); | ||
589 | if (rc) | 547 | if (rc) |
590 | printk(KERN_ERR | 548 | printk(KERN_ERR |
591 | "dell_rbu:%s request_firmware_nowait failed" | 549 | "dell_rbu:%s request_firmware_nowait failed" |
592 | " %d\n", __FUNCTION__, rc); | 550 | " %d\n", __FUNCTION__, rc); |
551 | else | ||
552 | rbu_data.entry_created = 1; | ||
553 | } | ||
554 | |||
555 | static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer, | ||
556 | loff_t pos, size_t count) | ||
557 | { | ||
558 | int size = 0; | ||
559 | if (!pos) | ||
560 | size = sprintf(buffer, "%s\n", image_type); | ||
561 | return size; | ||
562 | } | ||
563 | |||
564 | static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer, | ||
565 | loff_t pos, size_t count) | ||
566 | { | ||
567 | int rc = count; | ||
568 | int req_firm_rc = 0; | ||
569 | int i; | ||
570 | spin_lock(&rbu_data.lock); | ||
571 | /* | ||
572 | * Find the first newline or space | ||
573 | */ | ||
574 | for (i = 0; i < count; ++i) | ||
575 | if (buffer[i] == '\n' || buffer[i] == ' ') { | ||
576 | buffer[i] = '\0'; | ||
577 | break; | ||
578 | } | ||
579 | if (i == count) | ||
580 | buffer[count] = '\0'; | ||
581 | |||
582 | if (strstr(buffer, "mono")) | ||
583 | strcpy(image_type, "mono"); | ||
584 | else if (strstr(buffer, "packet")) | ||
585 | strcpy(image_type, "packet"); | ||
586 | else if (strstr(buffer, "init")) { | ||
587 | /* | ||
588 | * If due to the user error the driver gets in a bad | ||
589 | * state where even though it is loaded , the | ||
590 | * /sys/class/firmware/dell_rbu entries are missing. | ||
591 | * to cover this situation the user can recreate entries | ||
592 | * by writing init to image_type. | ||
593 | */ | ||
594 | if (!rbu_data.entry_created) { | ||
595 | spin_unlock(&rbu_data.lock); | ||
596 | req_firm_rc = request_firmware_nowait(THIS_MODULE, | ||
597 | FW_ACTION_NOHOTPLUG, "dell_rbu", | ||
598 | &rbu_device->dev, &context, | ||
599 | callbackfn_rbu); | ||
600 | if (req_firm_rc) { | ||
601 | printk(KERN_ERR | ||
602 | "dell_rbu:%s request_firmware_nowait" | ||
603 | " failed %d\n", __FUNCTION__, rc); | ||
604 | rc = -EIO; | ||
605 | } else | ||
606 | rbu_data.entry_created = 1; | ||
607 | |||
608 | spin_lock(&rbu_data.lock); | ||
609 | } | ||
610 | } else { | ||
611 | printk(KERN_WARNING "dell_rbu: image_type is invalid\n"); | ||
612 | spin_unlock(&rbu_data.lock); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | |||
616 | /* we must free all previous allocations */ | ||
617 | packet_empty_list(); | ||
618 | img_update_free(); | ||
619 | spin_unlock(&rbu_data.lock); | ||
620 | |||
621 | return rc; | ||
593 | } | 622 | } |
594 | 623 | ||
624 | static struct bin_attribute rbu_data_attr = { | ||
625 | .attr = { | ||
626 | .name = "data", | ||
627 | .owner = THIS_MODULE, | ||
628 | .mode = 0444, | ||
629 | }, | ||
630 | .read = read_rbu_data, | ||
631 | }; | ||
632 | |||
633 | static struct bin_attribute rbu_image_type_attr = { | ||
634 | .attr = { | ||
635 | .name = "image_type", | ||
636 | .owner = THIS_MODULE, | ||
637 | .mode = 0644, | ||
638 | }, | ||
639 | .read = read_rbu_image_type, | ||
640 | .write = write_rbu_image_type, | ||
641 | }; | ||
642 | |||
595 | static int __init dcdrbu_init(void) | 643 | static int __init dcdrbu_init(void) |
596 | { | 644 | { |
597 | int rc = 0; | 645 | int rc = 0; |
@@ -599,11 +647,11 @@ static int __init dcdrbu_init(void) | |||
599 | 647 | ||
600 | init_packet_head(); | 648 | init_packet_head(); |
601 | rbu_device = | 649 | rbu_device = |
602 | platform_device_register_simple("dell_rbu", -1, NULL, 0); | 650 | platform_device_register_simple("dell_rbu", -1, NULL, 0); |
603 | if (!rbu_device) { | 651 | if (!rbu_device) { |
604 | printk(KERN_ERR | 652 | printk(KERN_ERR |
605 | "dell_rbu:%s:platform_device_register_simple " | 653 | "dell_rbu:%s:platform_device_register_simple " |
606 | "failed\n", __FUNCTION__); | 654 | "failed\n", __FUNCTION__); |
607 | return -EIO; | 655 | return -EIO; |
608 | } | 656 | } |
609 | 657 | ||
@@ -611,11 +659,12 @@ static int __init dcdrbu_init(void) | |||
611 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); | 659 | sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr); |
612 | 660 | ||
613 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, | 661 | rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, |
614 | "dell_rbu", &rbu_device->dev, | 662 | "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu); |
615 | &context, callbackfn_rbu); | ||
616 | if (rc) | 663 | if (rc) |
617 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" | 664 | printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait" |
618 | " failed %d\n", __FUNCTION__, rc); | 665 | " failed %d\n", __FUNCTION__, rc); |
666 | else | ||
667 | rbu_data.entry_created = 1; | ||
619 | 668 | ||
620 | return rc; | 669 | return rc; |
621 | 670 | ||
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index eaebfc14c933..4c56411f3993 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c | |||
@@ -5,10 +5,10 @@ | |||
5 | * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> | 5 | * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com> |
6 | * | 6 | * |
7 | * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad | 7 | * The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad |
8 | * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis | 8 | * T41, T42, T43, R50, R50p, R51, and X40, at least. It provides a basic |
9 | * accelerometer and other data, such as the device's temperature. | 9 | * two-axis accelerometer and other data, such as the device's temperature. |
10 | * | 10 | * |
11 | * Based on the document by Mark A. Smith available at | 11 | * This driver is based on the document by Mark A. Smith available at |
12 | * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial | 12 | * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial |
13 | * and error. | 13 | * and error. |
14 | * | 14 | * |
@@ -36,12 +36,7 @@ | |||
36 | #include <asm/io.h> | 36 | #include <asm/io.h> |
37 | 37 | ||
38 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ | 38 | #define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */ |
39 | #define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */ | 39 | #define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */ |
40 | |||
41 | #define STATE_FRESH 0x50 /* accelerometer data is fresh */ | ||
42 | |||
43 | #define REFRESH_ASYNC 0x00 /* do asynchronous refresh */ | ||
44 | #define REFRESH_SYNC 0x01 /* do synchronous refresh */ | ||
45 | 40 | ||
46 | #define HDAPS_PORT_STATE 0x1611 /* device state */ | 41 | #define HDAPS_PORT_STATE 0x1611 /* device state */ |
47 | #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ | 42 | #define HDAPS_PORT_YPOS 0x1612 /* y-axis position */ |
@@ -53,7 +48,7 @@ | |||
53 | #define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */ | 48 | #define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */ |
54 | #define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */ | 49 | #define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */ |
55 | 50 | ||
56 | #define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */ | 51 | #define STATE_FRESH 0x50 /* accelerometer data is fresh */ |
57 | 52 | ||
58 | #define KEYBD_MASK 0x20 /* set if keyboard activity */ | 53 | #define KEYBD_MASK 0x20 /* set if keyboard activity */ |
59 | #define MOUSE_MASK 0x40 /* set if mouse activity */ | 54 | #define MOUSE_MASK 0x40 /* set if mouse activity */ |
@@ -63,12 +58,11 @@ | |||
63 | #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ | 58 | #define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */ |
64 | #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ | 59 | #define INIT_WAIT_MSECS 200 /* ... in 200ms increments */ |
65 | 60 | ||
66 | static struct platform_device *pdev; | 61 | #define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */ |
67 | static struct input_dev hdaps_idev; | 62 | #define HDAPS_INPUT_FUZZ 4 /* input event threshold */ |
63 | |||
68 | static struct timer_list hdaps_timer; | 64 | static struct timer_list hdaps_timer; |
69 | static unsigned int hdaps_mousedev_threshold = 4; | 65 | static struct platform_device *pdev; |
70 | static unsigned long hdaps_poll_ms = 50; | ||
71 | static unsigned int hdaps_mousedev; | ||
72 | static unsigned int hdaps_invert; | 66 | static unsigned int hdaps_invert; |
73 | static u8 km_activity; | 67 | static u8 km_activity; |
74 | static int rest_x; | 68 | static int rest_x; |
@@ -81,14 +75,14 @@ static DECLARE_MUTEX(hdaps_sem); | |||
81 | */ | 75 | */ |
82 | static inline u8 __get_latch(u16 port) | 76 | static inline u8 __get_latch(u16 port) |
83 | { | 77 | { |
84 | return inb(port) & HDAPS_READ_MASK; | 78 | return inb(port) & 0xff; |
85 | } | 79 | } |
86 | 80 | ||
87 | /* | 81 | /* |
88 | * __check_latch - Check a port latch for a given value. Callers must hold | 82 | * __check_latch - Check a port latch for a given value. Returns zero if the |
89 | * hdaps_sem. Returns zero if the port contains the given value. | 83 | * port contains the given value. Callers must hold hdaps_sem. |
90 | */ | 84 | */ |
91 | static inline unsigned int __check_latch(u16 port, u8 val) | 85 | static inline int __check_latch(u16 port, u8 val) |
92 | { | 86 | { |
93 | if (__get_latch(port) == val) | 87 | if (__get_latch(port) == val) |
94 | return 0; | 88 | return 0; |
@@ -99,7 +93,7 @@ static inline unsigned int __check_latch(u16 port, u8 val) | |||
99 | * __wait_latch - Wait up to 100us for a port latch to get a certain value, | 93 | * __wait_latch - Wait up to 100us for a port latch to get a certain value, |
100 | * returning zero if the value is obtained. Callers must hold hdaps_sem. | 94 | * returning zero if the value is obtained. Callers must hold hdaps_sem. |
101 | */ | 95 | */ |
102 | static unsigned int __wait_latch(u16 port, u8 val) | 96 | static int __wait_latch(u16 port, u8 val) |
103 | { | 97 | { |
104 | unsigned int i; | 98 | unsigned int i; |
105 | 99 | ||
@@ -109,59 +103,42 @@ static unsigned int __wait_latch(u16 port, u8 val) | |||
109 | udelay(5); | 103 | udelay(5); |
110 | } | 104 | } |
111 | 105 | ||
112 | return -EINVAL; | 106 | return -EIO; |
113 | } | 107 | } |
114 | 108 | ||
115 | /* | 109 | /* |
116 | * __device_refresh - Request a refresh from the accelerometer. | 110 | * __device_refresh - request a refresh from the accelerometer. Does not wait |
117 | * | 111 | * for refresh to complete. Callers must hold hdaps_sem. |
118 | * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait. | ||
119 | * Returns zero if successful and nonzero on error. | ||
120 | * | ||
121 | * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is | ||
122 | * not up-to-date. Always returns zero. | ||
123 | * | ||
124 | * Callers must hold hdaps_sem. | ||
125 | */ | 112 | */ |
126 | static int __device_refresh(unsigned int sync) | 113 | static void __device_refresh(void) |
127 | { | 114 | { |
128 | u8 state; | 115 | udelay(200); |
129 | 116 | if (inb(0x1604) != STATE_FRESH) { | |
130 | udelay(100); | 117 | outb(0x11, 0x1610); |
131 | 118 | outb(0x01, 0x161f); | |
132 | state = inb(0x1604); | 119 | } |
133 | if (state == STATE_FRESH) | 120 | } |
134 | return 0; | ||
135 | |||
136 | outb(0x11, 0x1610); | ||
137 | outb(0x01, 0x161f); | ||
138 | if (sync == REFRESH_ASYNC) | ||
139 | return 0; | ||
140 | 121 | ||
122 | /* | ||
123 | * __device_refresh_sync - request a synchronous refresh from the | ||
124 | * accelerometer. We wait for the refresh to complete. Returns zero if | ||
125 | * successful and nonzero on error. Callers must hold hdaps_sem. | ||
126 | */ | ||
127 | static int __device_refresh_sync(void) | ||
128 | { | ||
129 | __device_refresh(); | ||
141 | return __wait_latch(0x1604, STATE_FRESH); | 130 | return __wait_latch(0x1604, STATE_FRESH); |
142 | } | 131 | } |
143 | 132 | ||
144 | /* | 133 | /* |
145 | * __device_complete - Indicate to the accelerometer that we are done reading | 134 | * __device_complete - indicate to the accelerometer that we are done reading |
146 | * data, and then initiate an async refresh. Callers must hold hdaps_sem. | 135 | * data, and then initiate an async refresh. Callers must hold hdaps_sem. |
147 | */ | 136 | */ |
148 | static inline void __device_complete(void) | 137 | static inline void __device_complete(void) |
149 | { | 138 | { |
150 | inb(0x161f); | 139 | inb(0x161f); |
151 | inb(0x1604); | 140 | inb(0x1604); |
152 | __device_refresh(REFRESH_ASYNC); | 141 | __device_refresh(); |
153 | } | ||
154 | |||
155 | static int __hdaps_readb_one(unsigned int port, u8 *val) | ||
156 | { | ||
157 | /* do a sync refresh -- we need to be sure that we read fresh data */ | ||
158 | if (__device_refresh(REFRESH_SYNC)) | ||
159 | return -EIO; | ||
160 | |||
161 | *val = inb(port); | ||
162 | __device_complete(); | ||
163 | |||
164 | return 0; | ||
165 | } | 142 | } |
166 | 143 | ||
167 | /* | 144 | /* |
@@ -174,17 +151,26 @@ static int hdaps_readb_one(unsigned int port, u8 *val) | |||
174 | int ret; | 151 | int ret; |
175 | 152 | ||
176 | down(&hdaps_sem); | 153 | down(&hdaps_sem); |
177 | ret = __hdaps_readb_one(port, val); | ||
178 | up(&hdaps_sem); | ||
179 | 154 | ||
155 | /* do a sync refresh -- we need to be sure that we read fresh data */ | ||
156 | ret = __device_refresh_sync(); | ||
157 | if (ret) | ||
158 | goto out; | ||
159 | |||
160 | *val = inb(port); | ||
161 | __device_complete(); | ||
162 | |||
163 | out: | ||
164 | up(&hdaps_sem); | ||
180 | return ret; | 165 | return ret; |
181 | } | 166 | } |
182 | 167 | ||
168 | /* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */ | ||
183 | static int __hdaps_read_pair(unsigned int port1, unsigned int port2, | 169 | static int __hdaps_read_pair(unsigned int port1, unsigned int port2, |
184 | int *x, int *y) | 170 | int *x, int *y) |
185 | { | 171 | { |
186 | /* do a sync refresh -- we need to be sure that we read fresh data */ | 172 | /* do a sync refresh -- we need to be sure that we read fresh data */ |
187 | if (__device_refresh(REFRESH_SYNC)) | 173 | if (__device_refresh_sync()) |
188 | return -EIO; | 174 | return -EIO; |
189 | 175 | ||
190 | *y = inw(port2); | 176 | *y = inw(port2); |
@@ -217,11 +203,13 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2, | |||
217 | return ret; | 203 | return ret; |
218 | } | 204 | } |
219 | 205 | ||
220 | /* initialize the accelerometer */ | 206 | /* |
207 | * hdaps_device_init - initialize the accelerometer. Returns zero on success | ||
208 | * and negative error code on failure. Can sleep. | ||
209 | */ | ||
221 | static int hdaps_device_init(void) | 210 | static int hdaps_device_init(void) |
222 | { | 211 | { |
223 | unsigned int total_msecs = INIT_TIMEOUT_MSECS; | 212 | int total, ret = -ENXIO; |
224 | int ret = -ENXIO; | ||
225 | 213 | ||
226 | down(&hdaps_sem); | 214 | down(&hdaps_sem); |
227 | 215 | ||
@@ -231,8 +219,10 @@ static int hdaps_device_init(void) | |||
231 | goto out; | 219 | goto out; |
232 | 220 | ||
233 | /* | 221 | /* |
234 | * The 0x03 value appears to only work on some thinkpads, such as the | 222 | * Most ThinkPads return 0x01. |
235 | * T42p. Others return 0x01. | 223 | * |
224 | * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops | ||
225 | * have "inverted" axises. | ||
236 | * | 226 | * |
237 | * The 0x02 value occurs when the chip has been previously initialized. | 227 | * The 0x02 value occurs when the chip has been previously initialized. |
238 | */ | 228 | */ |
@@ -267,24 +257,23 @@ static int hdaps_device_init(void) | |||
267 | outb(0x01, 0x161f); | 257 | outb(0x01, 0x161f); |
268 | if (__wait_latch(0x161f, 0x00)) | 258 | if (__wait_latch(0x161f, 0x00)) |
269 | goto out; | 259 | goto out; |
270 | if (__device_refresh(REFRESH_SYNC)) | 260 | if (__device_refresh_sync()) |
271 | goto out; | 261 | goto out; |
272 | if (__wait_latch(0x1611, 0x00)) | 262 | if (__wait_latch(0x1611, 0x00)) |
273 | goto out; | 263 | goto out; |
274 | 264 | ||
275 | /* we have done our dance, now let's wait for the applause */ | 265 | /* we have done our dance, now let's wait for the applause */ |
276 | while (total_msecs > 0) { | 266 | for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { |
277 | u8 ignored; | 267 | int x, y; |
278 | 268 | ||
279 | /* a read of the device helps push it into action */ | 269 | /* a read of the device helps push it into action */ |
280 | __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored); | 270 | __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y); |
281 | if (!__wait_latch(0x1611, 0x02)) { | 271 | if (!__wait_latch(0x1611, 0x02)) { |
282 | ret = 0; | 272 | ret = 0; |
283 | break; | 273 | break; |
284 | } | 274 | } |
285 | 275 | ||
286 | msleep(INIT_WAIT_MSECS); | 276 | msleep(INIT_WAIT_MSECS); |
287 | total_msecs -= INIT_WAIT_MSECS; | ||
288 | } | 277 | } |
289 | 278 | ||
290 | out: | 279 | out: |
@@ -293,96 +282,6 @@ out: | |||
293 | } | 282 | } |
294 | 283 | ||
295 | 284 | ||
296 | /* Input class stuff */ | ||
297 | |||
298 | /* | ||
299 | * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem. | ||
300 | */ | ||
301 | static void hdaps_calibrate(void) | ||
302 | { | ||
303 | int x, y; | ||
304 | |||
305 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) | ||
306 | return; | ||
307 | |||
308 | rest_x = x; | ||
309 | rest_y = y; | ||
310 | } | ||
311 | |||
312 | static void hdaps_mousedev_poll(unsigned long unused) | ||
313 | { | ||
314 | int x, y; | ||
315 | |||
316 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ | ||
317 | if (down_trylock(&hdaps_sem)) { | ||
318 | mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms)); | ||
319 | return; | ||
320 | } | ||
321 | |||
322 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) | ||
323 | goto out; | ||
324 | |||
325 | x -= rest_x; | ||
326 | y -= rest_y; | ||
327 | if (abs(x) > hdaps_mousedev_threshold) | ||
328 | input_report_rel(&hdaps_idev, REL_X, x); | ||
329 | if (abs(y) > hdaps_mousedev_threshold) | ||
330 | input_report_rel(&hdaps_idev, REL_Y, y); | ||
331 | input_sync(&hdaps_idev); | ||
332 | |||
333 | mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms)); | ||
334 | |||
335 | out: | ||
336 | up(&hdaps_sem); | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * hdaps_mousedev_enable - enable the input class device. Can sleep. | ||
341 | */ | ||
342 | static void hdaps_mousedev_enable(void) | ||
343 | { | ||
344 | down(&hdaps_sem); | ||
345 | |||
346 | /* calibrate the device before enabling */ | ||
347 | hdaps_calibrate(); | ||
348 | |||
349 | /* initialize the input class */ | ||
350 | init_input_dev(&hdaps_idev); | ||
351 | hdaps_idev.dev = &pdev->dev; | ||
352 | hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
353 | hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
354 | hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT); | ||
355 | input_register_device(&hdaps_idev); | ||
356 | |||
357 | /* start up our timer */ | ||
358 | init_timer(&hdaps_timer); | ||
359 | hdaps_timer.function = hdaps_mousedev_poll; | ||
360 | hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms); | ||
361 | add_timer(&hdaps_timer); | ||
362 | |||
363 | hdaps_mousedev = 1; | ||
364 | |||
365 | up(&hdaps_sem); | ||
366 | |||
367 | printk(KERN_INFO "hdaps: input device enabled.\n"); | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * hdaps_mousedev_disable - disable the input class device. Caller must hold | ||
372 | * hdaps_sem. | ||
373 | */ | ||
374 | static void hdaps_mousedev_disable(void) | ||
375 | { | ||
376 | down(&hdaps_sem); | ||
377 | if (hdaps_mousedev) { | ||
378 | hdaps_mousedev = 0; | ||
379 | del_timer_sync(&hdaps_timer); | ||
380 | input_unregister_device(&hdaps_idev); | ||
381 | } | ||
382 | up(&hdaps_sem); | ||
383 | } | ||
384 | |||
385 | |||
386 | /* Device model stuff */ | 285 | /* Device model stuff */ |
387 | 286 | ||
388 | static int hdaps_probe(struct device *dev) | 287 | static int hdaps_probe(struct device *dev) |
@@ -412,6 +311,49 @@ static struct device_driver hdaps_driver = { | |||
412 | .resume = hdaps_resume | 311 | .resume = hdaps_resume |
413 | }; | 312 | }; |
414 | 313 | ||
314 | /* Input class stuff */ | ||
315 | |||
316 | static struct input_dev hdaps_idev = { | ||
317 | .name = "hdaps", | ||
318 | .evbit = { BIT(EV_ABS) }, | ||
319 | .absbit = { BIT(ABS_X) | BIT(ABS_Y) }, | ||
320 | .absmin = { [ABS_X] = -256, [ABS_Y] = -256 }, | ||
321 | .absmax = { [ABS_X] = 256, [ABS_Y] = 256 }, | ||
322 | .absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, | ||
323 | .absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ }, | ||
324 | }; | ||
325 | |||
326 | /* | ||
327 | * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem. | ||
328 | */ | ||
329 | static void hdaps_calibrate(void) | ||
330 | { | ||
331 | __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y); | ||
332 | } | ||
333 | |||
334 | static void hdaps_mousedev_poll(unsigned long unused) | ||
335 | { | ||
336 | int x, y; | ||
337 | |||
338 | /* Cannot sleep. Try nonblockingly. If we fail, try again later. */ | ||
339 | if (down_trylock(&hdaps_sem)) { | ||
340 | mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD); | ||
341 | return; | ||
342 | } | ||
343 | |||
344 | if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y)) | ||
345 | goto out; | ||
346 | |||
347 | input_report_abs(&hdaps_idev, ABS_X, x - rest_x); | ||
348 | input_report_abs(&hdaps_idev, ABS_Y, y - rest_y); | ||
349 | input_sync(&hdaps_idev); | ||
350 | |||
351 | mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD); | ||
352 | |||
353 | out: | ||
354 | up(&hdaps_sem); | ||
355 | } | ||
356 | |||
415 | 357 | ||
416 | /* Sysfs Files */ | 358 | /* Sysfs Files */ |
417 | 359 | ||
@@ -517,69 +459,6 @@ static ssize_t hdaps_invert_store(struct device *dev, | |||
517 | return count; | 459 | return count; |
518 | } | 460 | } |
519 | 461 | ||
520 | static ssize_t hdaps_mousedev_show(struct device *dev, | ||
521 | struct device_attribute *attr, char *buf) | ||
522 | { | ||
523 | return sprintf(buf, "%d\n", hdaps_mousedev); | ||
524 | } | ||
525 | |||
526 | static ssize_t hdaps_mousedev_store(struct device *dev, | ||
527 | struct device_attribute *attr, | ||
528 | const char *buf, size_t count) | ||
529 | { | ||
530 | int enable; | ||
531 | |||
532 | if (sscanf(buf, "%d", &enable) != 1) | ||
533 | return -EINVAL; | ||
534 | |||
535 | if (enable == 1) | ||
536 | hdaps_mousedev_enable(); | ||
537 | else if (enable == 0) | ||
538 | hdaps_mousedev_disable(); | ||
539 | else | ||
540 | return -EINVAL; | ||
541 | |||
542 | return count; | ||
543 | } | ||
544 | |||
545 | static ssize_t hdaps_poll_show(struct device *dev, | ||
546 | struct device_attribute *attr, char *buf) | ||
547 | { | ||
548 | return sprintf(buf, "%lu\n", hdaps_poll_ms); | ||
549 | } | ||
550 | |||
551 | static ssize_t hdaps_poll_store(struct device *dev, | ||
552 | struct device_attribute *attr, | ||
553 | const char *buf, size_t count) | ||
554 | { | ||
555 | unsigned int poll; | ||
556 | |||
557 | if (sscanf(buf, "%u", &poll) != 1 || poll == 0) | ||
558 | return -EINVAL; | ||
559 | hdaps_poll_ms = poll; | ||
560 | |||
561 | return count; | ||
562 | } | ||
563 | |||
564 | static ssize_t hdaps_threshold_show(struct device *dev, | ||
565 | struct device_attribute *attr, char *buf) | ||
566 | { | ||
567 | return sprintf(buf, "%u\n", hdaps_mousedev_threshold); | ||
568 | } | ||
569 | |||
570 | static ssize_t hdaps_threshold_store(struct device *dev, | ||
571 | struct device_attribute *attr, | ||
572 | const char *buf, size_t count) | ||
573 | { | ||
574 | unsigned int threshold; | ||
575 | |||
576 | if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0) | ||
577 | return -EINVAL; | ||
578 | hdaps_mousedev_threshold = threshold; | ||
579 | |||
580 | return count; | ||
581 | } | ||
582 | |||
583 | static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL); | 462 | static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL); |
584 | static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL); | 463 | static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL); |
585 | static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL); | 464 | static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL); |
@@ -588,10 +467,6 @@ static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL); | |||
588 | static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL); | 467 | static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL); |
589 | static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store); | 468 | static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store); |
590 | static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store); | 469 | static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store); |
591 | static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store); | ||
592 | static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store); | ||
593 | static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show, | ||
594 | hdaps_threshold_store); | ||
595 | 470 | ||
596 | static struct attribute *hdaps_attributes[] = { | 471 | static struct attribute *hdaps_attributes[] = { |
597 | &dev_attr_position.attr, | 472 | &dev_attr_position.attr, |
@@ -601,9 +476,6 @@ static struct attribute *hdaps_attributes[] = { | |||
601 | &dev_attr_keyboard_activity.attr, | 476 | &dev_attr_keyboard_activity.attr, |
602 | &dev_attr_mouse_activity.attr, | 477 | &dev_attr_mouse_activity.attr, |
603 | &dev_attr_calibrate.attr, | 478 | &dev_attr_calibrate.attr, |
604 | &dev_attr_mousedev.attr, | ||
605 | &dev_attr_mousedev_threshold.attr, | ||
606 | &dev_attr_mousedev_poll_ms.attr, | ||
607 | &dev_attr_invert.attr, | 479 | &dev_attr_invert.attr, |
608 | NULL, | 480 | NULL, |
609 | }; | 481 | }; |
@@ -619,7 +491,7 @@ static struct attribute_group hdaps_attribute_group = { | |||
619 | * XXX: We should be able to return nonzero and halt the detection process. | 491 | * XXX: We should be able to return nonzero and halt the detection process. |
620 | * But there is a bug in dmi_check_system() where a nonzero return from the | 492 | * But there is a bug in dmi_check_system() where a nonzero return from the |
621 | * first match will result in a return of failure from dmi_check_system(). | 493 | * first match will result in a return of failure from dmi_check_system(). |
622 | * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make | 494 | * I fixed this; the patch is 2.6-git. Once in a released tree, we can make |
623 | * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. | 495 | * hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1. |
624 | */ | 496 | */ |
625 | static int hdaps_dmi_match(struct dmi_system_id *id) | 497 | static int hdaps_dmi_match(struct dmi_system_id *id) |
@@ -668,6 +540,7 @@ static int __init hdaps_init(void) | |||
668 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), | 540 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), |
669 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), | 541 | HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), |
670 | HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), | 542 | HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), |
543 | HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), | ||
671 | { .ident = NULL } | 544 | { .ident = NULL } |
672 | }; | 545 | }; |
673 | 546 | ||
@@ -696,8 +569,18 @@ static int __init hdaps_init(void) | |||
696 | if (ret) | 569 | if (ret) |
697 | goto out_device; | 570 | goto out_device; |
698 | 571 | ||
699 | if (hdaps_mousedev) | 572 | /* initial calibrate for the input device */ |
700 | hdaps_mousedev_enable(); | 573 | hdaps_calibrate(); |
574 | |||
575 | /* initialize the input class */ | ||
576 | hdaps_idev.dev = &pdev->dev; | ||
577 | input_register_device(&hdaps_idev); | ||
578 | |||
579 | /* start up our timer for the input device */ | ||
580 | init_timer(&hdaps_timer); | ||
581 | hdaps_timer.function = hdaps_mousedev_poll; | ||
582 | hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD; | ||
583 | add_timer(&hdaps_timer); | ||
701 | 584 | ||
702 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); | 585 | printk(KERN_INFO "hdaps: driver successfully loaded.\n"); |
703 | return 0; | 586 | return 0; |
@@ -715,8 +598,8 @@ out: | |||
715 | 598 | ||
716 | static void __exit hdaps_exit(void) | 599 | static void __exit hdaps_exit(void) |
717 | { | 600 | { |
718 | hdaps_mousedev_disable(); | 601 | del_timer_sync(&hdaps_timer); |
719 | 602 | input_unregister_device(&hdaps_idev); | |
720 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); | 603 | sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group); |
721 | platform_device_unregister(pdev); | 604 | platform_device_unregister(pdev); |
722 | driver_unregister(&hdaps_driver); | 605 | driver_unregister(&hdaps_driver); |
@@ -728,9 +611,6 @@ static void __exit hdaps_exit(void) | |||
728 | module_init(hdaps_init); | 611 | module_init(hdaps_init); |
729 | module_exit(hdaps_exit); | 612 | module_exit(hdaps_exit); |
730 | 613 | ||
731 | module_param_named(mousedev, hdaps_mousedev, bool, 0); | ||
732 | MODULE_PARM_DESC(mousedev, "enable the input class device"); | ||
733 | |||
734 | module_param_named(invert, hdaps_invert, bool, 0); | 614 | module_param_named(invert, hdaps_invert, bool, 0); |
735 | MODULE_PARM_DESC(invert, "invert data along each axis"); | 615 | MODULE_PARM_DESC(invert, "invert data along each axis"); |
736 | 616 | ||
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c index 37b49c2daf5f..eff5896ce865 100644 --- a/drivers/i2c/busses/i2c-keywest.c +++ b/drivers/i2c/busses/i2c-keywest.c | |||
@@ -611,7 +611,6 @@ create_iface(struct device_node *np, struct device *dev) | |||
611 | 611 | ||
612 | for (i=0; i<nchan; i++) { | 612 | for (i=0; i<nchan; i++) { |
613 | struct keywest_chan* chan = &iface->channels[i]; | 613 | struct keywest_chan* chan = &iface->channels[i]; |
614 | u8 addr; | ||
615 | 614 | ||
616 | sprintf(chan->adapter.name, "%s %d", np->parent->name, i); | 615 | sprintf(chan->adapter.name, "%s %d", np->parent->name, i); |
617 | chan->iface = iface; | 616 | chan->iface = iface; |
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index fdf53ce04248..44b595d90a4a 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -914,19 +914,23 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num | |||
914 | return ret; | 914 | return ret; |
915 | } | 915 | } |
916 | 916 | ||
917 | static u32 i2c_pxa_functionality(struct i2c_adapter *adap) | ||
918 | { | ||
919 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
920 | } | ||
921 | |||
917 | static struct i2c_algorithm i2c_pxa_algorithm = { | 922 | static struct i2c_algorithm i2c_pxa_algorithm = { |
918 | .name = "PXA-I2C-Algorithm", | ||
919 | .id = I2C_ALGO_PXA, | ||
920 | .master_xfer = i2c_pxa_xfer, | 923 | .master_xfer = i2c_pxa_xfer, |
924 | .functionality = i2c_pxa_functionality, | ||
921 | }; | 925 | }; |
922 | 926 | ||
923 | static struct pxa_i2c i2c_pxa = { | 927 | static struct pxa_i2c i2c_pxa = { |
924 | .lock = SPIN_LOCK_UNLOCKED, | 928 | .lock = SPIN_LOCK_UNLOCKED, |
925 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait), | 929 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait), |
926 | .adap = { | 930 | .adap = { |
927 | .name = "pxa2xx-i2c", | 931 | .owner = THIS_MODULE, |
928 | .id = I2C_ALGO_PXA, | ||
929 | .algo = &i2c_pxa_algorithm, | 932 | .algo = &i2c_pxa_algorithm, |
933 | .name = "pxa2xx-i2c", | ||
930 | .retries = 5, | 934 | .retries = 5, |
931 | }, | 935 | }, |
932 | }; | 936 | }; |
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index b443b04a4c5a..0b0aa4f51628 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -601,44 +601,15 @@ EXPORT_SYMBOL(ide_wait_stat); | |||
601 | */ | 601 | */ |
602 | u8 eighty_ninty_three (ide_drive_t *drive) | 602 | u8 eighty_ninty_three (ide_drive_t *drive) |
603 | { | 603 | { |
604 | #if 0 | 604 | if(HWIF(drive)->udma_four == 0) |
605 | if (!HWIF(drive)->udma_four) | 605 | return 0; |
606 | if (!(drive->id->hw_config & 0x6000)) | ||
606 | return 0; | 607 | return 0; |
607 | |||
608 | if (drive->id->major_rev_num) { | ||
609 | int hssbd = 0; | ||
610 | int i; | ||
611 | /* | ||
612 | * Determine highest Supported SPEC | ||
613 | */ | ||
614 | for (i=1; i<=15; i++) | ||
615 | if (drive->id->major_rev_num & (1<<i)) | ||
616 | hssbd++; | ||
617 | |||
618 | switch (hssbd) { | ||
619 | case 7: | ||
620 | case 6: | ||
621 | case 5: | ||
622 | /* ATA-4 and older do not support above Ultra 33 */ | ||
623 | default: | ||
624 | return 0; | ||
625 | } | ||
626 | } | ||
627 | |||
628 | return ((u8) ( | ||
629 | #ifndef CONFIG_IDEDMA_IVB | ||
630 | (drive->id->hw_config & 0x4000) && | ||
631 | #endif /* CONFIG_IDEDMA_IVB */ | ||
632 | (drive->id->hw_config & 0x6000)) ? 1 : 0); | ||
633 | |||
634 | #else | ||
635 | |||
636 | return ((u8) ((HWIF(drive)->udma_four) && | ||
637 | #ifndef CONFIG_IDEDMA_IVB | 608 | #ifndef CONFIG_IDEDMA_IVB |
638 | (drive->id->hw_config & 0x4000) && | 609 | if(!(drive->id->hw_config & 0x4000)) |
610 | return 0; | ||
639 | #endif /* CONFIG_IDEDMA_IVB */ | 611 | #endif /* CONFIG_IDEDMA_IVB */ |
640 | (drive->id->hw_config & 0x6000)) ? 1 : 0); | 612 | return 1; |
641 | #endif | ||
642 | } | 613 | } |
643 | 614 | ||
644 | EXPORT_SYMBOL(eighty_ninty_three); | 615 | EXPORT_SYMBOL(eighty_ninty_three); |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index d04f62ab5de1..ace8edad6e96 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
@@ -500,6 +500,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long | |||
500 | } | 500 | } |
501 | 501 | ||
502 | rq.special = args; | 502 | rq.special = args; |
503 | args->rq = &rq; | ||
503 | return ide_do_drive_cmd(drive, &rq, ide_wait); | 504 | return ide_do_drive_cmd(drive, &rq, ide_wait); |
504 | } | 505 | } |
505 | 506 | ||
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 3de9ab897e42..3d9c7afc8695 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c | |||
@@ -608,7 +608,7 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha | |||
608 | 608 | ||
609 | #ifdef __i386__ | 609 | #ifdef __i386__ |
610 | if (dev->resource[PCI_ROM_RESOURCE].start) { | 610 | if (dev->resource[PCI_ROM_RESOURCE].start) { |
611 | pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); | 611 | pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); |
612 | printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); | 612 | printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start); |
613 | } | 613 | } |
614 | #endif | 614 | #endif |
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c index bbde46279984..be334da7a754 100644 --- a/drivers/ide/pci/hpt34x.c +++ b/drivers/ide/pci/hpt34x.c | |||
@@ -173,7 +173,7 @@ static unsigned int __devinit init_chipset_hpt34x(struct pci_dev *dev, const cha | |||
173 | 173 | ||
174 | if (cmd & PCI_COMMAND_MEMORY) { | 174 | if (cmd & PCI_COMMAND_MEMORY) { |
175 | if (pci_resource_start(dev, PCI_ROM_RESOURCE)) { | 175 | if (pci_resource_start(dev, PCI_ROM_RESOURCE)) { |
176 | pci_write_config_byte(dev, PCI_ROM_ADDRESS, | 176 | pci_write_config_dword(dev, PCI_ROM_ADDRESS, |
177 | dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); | 177 | dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); |
178 | printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", | 178 | printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n", |
179 | dev->resource[PCI_ROM_RESOURCE].start); | 179 | dev->resource[PCI_ROM_RESOURCE].start); |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index e55dee390775..444f7756fee6 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
@@ -132,6 +132,17 @@ config KEYBOARD_CORGI | |||
132 | To compile this driver as a module, choose M here: the | 132 | To compile this driver as a module, choose M here: the |
133 | module will be called corgikbd. | 133 | module will be called corgikbd. |
134 | 134 | ||
135 | config KEYBOARD_SPITZ | ||
136 | tristate "Spitz keyboard" | ||
137 | depends on PXA_SHARPSL | ||
138 | default y | ||
139 | help | ||
140 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, | ||
141 | SL-C3000 and Sl-C3100 series of PDAs. | ||
142 | |||
143 | To compile this driver as a module, choose M here: the | ||
144 | module will be called spitzkbd. | ||
145 | |||
135 | config KEYBOARD_MAPLE | 146 | config KEYBOARD_MAPLE |
136 | tristate "Maple bus keyboard" | 147 | tristate "Maple bus keyboard" |
137 | depends on SH_DREAMCAST && MAPLE | 148 | depends on SH_DREAMCAST && MAPLE |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index b02eeceea3c3..9ce0b87f2fac 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o | |||
14 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o | 14 | obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o |
15 | obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o | 15 | obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o |
16 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | 16 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o |
17 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | ||
17 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 18 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
18 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 19 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
19 | 20 | ||
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c new file mode 100644 index 000000000000..1714045a182b --- /dev/null +++ b/drivers/input/keyboard/spitzkbd.c | |||
@@ -0,0 +1,478 @@ | |||
1 | /* | ||
2 | * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series) | ||
3 | * | ||
4 | * Copyright (c) 2005 Richard Purdie | ||
5 | * | ||
6 | * Based on corgikbd.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/delay.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/jiffies.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <asm/irq.h> | ||
23 | |||
24 | #include <asm/arch/spitz.h> | ||
25 | #include <asm/arch/hardware.h> | ||
26 | #include <asm/arch/pxa-regs.h> | ||
27 | |||
28 | #define KB_ROWS 7 | ||
29 | #define KB_COLS 11 | ||
30 | #define KB_ROWMASK(r) (1 << (r)) | ||
31 | #define SCANCODE(r,c) (((r)<<4) + (c) + 1) | ||
32 | #define NR_SCANCODES ((KB_ROWS<<4) + 1) | ||
33 | |||
34 | #define HINGE_SCAN_INTERVAL (150) /* ms */ | ||
35 | |||
36 | #define SPITZ_KEY_CALENDER KEY_F1 | ||
37 | #define SPITZ_KEY_ADDRESS KEY_F2 | ||
38 | #define SPITZ_KEY_FN KEY_F3 | ||
39 | #define SPITZ_KEY_CANCEL KEY_F4 | ||
40 | #define SPITZ_KEY_EXOK KEY_F5 | ||
41 | #define SPITZ_KEY_EXCANCEL KEY_F6 | ||
42 | #define SPITZ_KEY_EXJOGDOWN KEY_F7 | ||
43 | #define SPITZ_KEY_EXJOGUP KEY_F8 | ||
44 | #define SPITZ_KEY_JAP1 KEY_LEFTALT | ||
45 | #define SPITZ_KEY_JAP2 KEY_RIGHTCTRL | ||
46 | #define SPITZ_KEY_SYNC KEY_F9 | ||
47 | #define SPITZ_KEY_MAIL KEY_F10 | ||
48 | #define SPITZ_KEY_OK KEY_F11 | ||
49 | #define SPITZ_KEY_MENU KEY_F12 | ||
50 | |||
51 | static unsigned char spitzkbd_keycode[NR_SCANCODES] = { | ||
52 | 0, /* 0 */ | ||
53 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ | ||
54 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ | ||
55 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | ||
56 | SPITZ_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, /* 49-64 */ | ||
57 | SPITZ_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ | ||
58 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ | ||
59 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ | ||
60 | }; | ||
61 | |||
62 | static int spitz_strobes[] = { | ||
63 | SPITZ_GPIO_KEY_STROBE0, | ||
64 | SPITZ_GPIO_KEY_STROBE1, | ||
65 | SPITZ_GPIO_KEY_STROBE2, | ||
66 | SPITZ_GPIO_KEY_STROBE3, | ||
67 | SPITZ_GPIO_KEY_STROBE4, | ||
68 | SPITZ_GPIO_KEY_STROBE5, | ||
69 | SPITZ_GPIO_KEY_STROBE6, | ||
70 | SPITZ_GPIO_KEY_STROBE7, | ||
71 | SPITZ_GPIO_KEY_STROBE8, | ||
72 | SPITZ_GPIO_KEY_STROBE9, | ||
73 | SPITZ_GPIO_KEY_STROBE10, | ||
74 | }; | ||
75 | |||
76 | static int spitz_senses[] = { | ||
77 | SPITZ_GPIO_KEY_SENSE0, | ||
78 | SPITZ_GPIO_KEY_SENSE1, | ||
79 | SPITZ_GPIO_KEY_SENSE2, | ||
80 | SPITZ_GPIO_KEY_SENSE3, | ||
81 | SPITZ_GPIO_KEY_SENSE4, | ||
82 | SPITZ_GPIO_KEY_SENSE5, | ||
83 | SPITZ_GPIO_KEY_SENSE6, | ||
84 | }; | ||
85 | |||
86 | struct spitzkbd { | ||
87 | unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; | ||
88 | struct input_dev input; | ||
89 | char phys[32]; | ||
90 | |||
91 | spinlock_t lock; | ||
92 | struct timer_list timer; | ||
93 | struct timer_list htimer; | ||
94 | |||
95 | unsigned int suspended; | ||
96 | unsigned long suspend_jiffies; | ||
97 | }; | ||
98 | |||
99 | #define KB_DISCHARGE_DELAY 10 | ||
100 | #define KB_ACTIVATE_DELAY 10 | ||
101 | |||
102 | /* Helper functions for reading the keyboard matrix | ||
103 | * Note: We should really be using pxa_gpio_mode to alter GPDR but it | ||
104 | * requires a function call per GPIO bit which is excessive | ||
105 | * when we need to access 11 bits at once, multiple times. | ||
106 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
107 | * or similar. | ||
108 | */ | ||
109 | static inline void spitzkbd_discharge_all(void) | ||
110 | { | ||
111 | /* STROBE All HiZ */ | ||
112 | GPCR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
113 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
114 | GPCR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
115 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
116 | GPCR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
117 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
118 | GPCR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
119 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
120 | } | ||
121 | |||
122 | static inline void spitzkbd_activate_all(void) | ||
123 | { | ||
124 | /* STROBE ALL -> High */ | ||
125 | GPSR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
126 | GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT; | ||
127 | GPSR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
128 | GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT; | ||
129 | GPSR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
130 | GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT; | ||
131 | GPSR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
132 | GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT; | ||
133 | |||
134 | udelay(KB_DISCHARGE_DELAY); | ||
135 | |||
136 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ | ||
137 | GEDR0 = SPITZ_GPIO_G0_SENSE_BIT; | ||
138 | GEDR1 = SPITZ_GPIO_G1_SENSE_BIT; | ||
139 | GEDR2 = SPITZ_GPIO_G2_SENSE_BIT; | ||
140 | GEDR3 = SPITZ_GPIO_G3_SENSE_BIT; | ||
141 | } | ||
142 | |||
143 | static inline void spitzkbd_activate_col(int col) | ||
144 | { | ||
145 | int gpio = spitz_strobes[col]; | ||
146 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
147 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
148 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
149 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
150 | GPSR(gpio) = GPIO_bit(gpio); | ||
151 | GPDR(gpio) |= GPIO_bit(gpio); | ||
152 | } | ||
153 | |||
154 | static inline void spitzkbd_reset_col(int col) | ||
155 | { | ||
156 | int gpio = spitz_strobes[col]; | ||
157 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
158 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
159 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
160 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
161 | GPCR(gpio) = GPIO_bit(gpio); | ||
162 | GPDR(gpio) |= GPIO_bit(gpio); | ||
163 | } | ||
164 | |||
165 | static inline int spitzkbd_get_row_status(int col) | ||
166 | { | ||
167 | return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02) | ||
168 | | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08) | ||
169 | | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60); | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * The spitz keyboard only generates interrupts when a key is pressed. | ||
174 | * When a key is pressed, we enable a timer which then scans the | ||
175 | * keyboard to detect when the key is released. | ||
176 | */ | ||
177 | |||
178 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
179 | static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs *regs) | ||
180 | { | ||
181 | unsigned int row, col, rowd; | ||
182 | unsigned long flags; | ||
183 | unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0); | ||
184 | |||
185 | if (spitzkbd_data->suspended) | ||
186 | return; | ||
187 | |||
188 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
189 | |||
190 | if (regs) | ||
191 | input_regs(&spitzkbd_data->input, regs); | ||
192 | |||
193 | num_pressed = 0; | ||
194 | for (col = 0; col < KB_COLS; col++) { | ||
195 | /* | ||
196 | * Discharge the output driver capacitatance | ||
197 | * in the keyboard matrix. (Yes it is significant..) | ||
198 | */ | ||
199 | |||
200 | spitzkbd_discharge_all(); | ||
201 | udelay(KB_DISCHARGE_DELAY); | ||
202 | |||
203 | spitzkbd_activate_col(col); | ||
204 | udelay(KB_ACTIVATE_DELAY); | ||
205 | |||
206 | rowd = spitzkbd_get_row_status(col); | ||
207 | for (row = 0; row < KB_ROWS; row++) { | ||
208 | unsigned int scancode, pressed; | ||
209 | |||
210 | scancode = SCANCODE(row, col); | ||
211 | pressed = rowd & KB_ROWMASK(row); | ||
212 | |||
213 | input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); | ||
214 | |||
215 | if (pressed) | ||
216 | num_pressed++; | ||
217 | } | ||
218 | spitzkbd_reset_col(col); | ||
219 | } | ||
220 | |||
221 | spitzkbd_activate_all(); | ||
222 | |||
223 | input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); | ||
224 | input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey); | ||
225 | |||
226 | if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { | ||
227 | input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); | ||
228 | spitzkbd_data->suspend_jiffies = jiffies; | ||
229 | } | ||
230 | |||
231 | input_sync(&spitzkbd_data->input); | ||
232 | |||
233 | /* if any keys are pressed, enable the timer */ | ||
234 | if (num_pressed) | ||
235 | mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100)); | ||
236 | |||
237 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * spitz keyboard interrupt handler. | ||
242 | */ | ||
243 | static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
244 | { | ||
245 | struct spitzkbd *spitzkbd_data = dev_id; | ||
246 | |||
247 | if (!timer_pending(&spitzkbd_data->timer)) { | ||
248 | /** wait chattering delay **/ | ||
249 | udelay(20); | ||
250 | spitzkbd_scankeyboard(spitzkbd_data, regs); | ||
251 | } | ||
252 | |||
253 | return IRQ_HANDLED; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * spitz timer checking for released keys | ||
258 | */ | ||
259 | static void spitzkbd_timer_callback(unsigned long data) | ||
260 | { | ||
261 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
262 | spitzkbd_scankeyboard(spitzkbd_data, NULL); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * The hinge switches generate an interrupt. | ||
267 | * We debounce the switches and pass them to the input system. | ||
268 | */ | ||
269 | |||
270 | static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id, struct pt_regs *regs) | ||
271 | { | ||
272 | struct spitzkbd *spitzkbd_data = dev_id; | ||
273 | |||
274 | if (!timer_pending(&spitzkbd_data->htimer)) | ||
275 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
276 | |||
277 | return IRQ_HANDLED; | ||
278 | } | ||
279 | |||
280 | #define HINGE_STABLE_COUNT 2 | ||
281 | static int sharpsl_hinge_state; | ||
282 | static int hinge_count; | ||
283 | |||
284 | static void spitzkbd_hinge_timer(unsigned long data) | ||
285 | { | ||
286 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
287 | unsigned long state; | ||
288 | unsigned long flags; | ||
289 | |||
290 | state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); | ||
291 | if (state != sharpsl_hinge_state) { | ||
292 | hinge_count = 0; | ||
293 | sharpsl_hinge_state = state; | ||
294 | } else if (hinge_count < HINGE_STABLE_COUNT) { | ||
295 | hinge_count++; | ||
296 | } | ||
297 | |||
298 | if (hinge_count >= HINGE_STABLE_COUNT) { | ||
299 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
300 | |||
301 | input_report_switch(&spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); | ||
302 | input_report_switch(&spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); | ||
303 | input_sync(&spitzkbd_data->input); | ||
304 | |||
305 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
306 | } else { | ||
307 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | #ifdef CONFIG_PM | ||
312 | static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level) | ||
313 | { | ||
314 | if (level == SUSPEND_POWER_DOWN) { | ||
315 | int i; | ||
316 | struct spitzkbd *spitzkbd = dev_get_drvdata(dev); | ||
317 | spitzkbd->suspended = 1; | ||
318 | |||
319 | /* Set Strobe lines as inputs - *except* strobe line 0 leave this | ||
320 | enabled so we can detect a power button press for resume */ | ||
321 | for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) | ||
322 | pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); | ||
323 | } | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int spitzkbd_resume(struct device *dev, uint32_t level) | ||
328 | { | ||
329 | if (level == RESUME_POWER_ON) { | ||
330 | int i; | ||
331 | struct spitzkbd *spitzkbd = dev_get_drvdata(dev); | ||
332 | |||
333 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
334 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
335 | |||
336 | /* Upon resume, ignore the suspend key for a short while */ | ||
337 | spitzkbd->suspend_jiffies = jiffies; | ||
338 | spitzkbd->suspended = 0; | ||
339 | } | ||
340 | return 0; | ||
341 | } | ||
342 | #else | ||
343 | #define spitzkbd_suspend NULL | ||
344 | #define spitzkbd_resume NULL | ||
345 | #endif | ||
346 | |||
347 | static int __init spitzkbd_probe(struct device *dev) | ||
348 | { | ||
349 | int i; | ||
350 | struct spitzkbd *spitzkbd; | ||
351 | |||
352 | spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); | ||
353 | if (!spitzkbd) | ||
354 | return -ENOMEM; | ||
355 | |||
356 | dev_set_drvdata(dev,spitzkbd); | ||
357 | strcpy(spitzkbd->phys, "spitzkbd/input0"); | ||
358 | |||
359 | spin_lock_init(&spitzkbd->lock); | ||
360 | |||
361 | /* Init Keyboard rescan timer */ | ||
362 | init_timer(&spitzkbd->timer); | ||
363 | spitzkbd->timer.function = spitzkbd_timer_callback; | ||
364 | spitzkbd->timer.data = (unsigned long) spitzkbd; | ||
365 | |||
366 | /* Init Hinge Timer */ | ||
367 | init_timer(&spitzkbd->htimer); | ||
368 | spitzkbd->htimer.function = spitzkbd_hinge_timer; | ||
369 | spitzkbd->htimer.data = (unsigned long) spitzkbd; | ||
370 | |||
371 | spitzkbd->suspend_jiffies=jiffies; | ||
372 | |||
373 | init_input_dev(&spitzkbd->input); | ||
374 | spitzkbd->input.private = spitzkbd; | ||
375 | spitzkbd->input.name = "Spitz Keyboard"; | ||
376 | spitzkbd->input.dev = dev; | ||
377 | spitzkbd->input.phys = spitzkbd->phys; | ||
378 | spitzkbd->input.id.bustype = BUS_HOST; | ||
379 | spitzkbd->input.id.vendor = 0x0001; | ||
380 | spitzkbd->input.id.product = 0x0001; | ||
381 | spitzkbd->input.id.version = 0x0100; | ||
382 | spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW); | ||
383 | spitzkbd->input.keycode = spitzkbd->keycode; | ||
384 | spitzkbd->input.keycodesize = sizeof(unsigned char); | ||
385 | spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode); | ||
386 | |||
387 | memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); | ||
388 | for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) | ||
389 | set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit); | ||
390 | clear_bit(0, spitzkbd->input.keybit); | ||
391 | set_bit(SW_0, spitzkbd->input.swbit); | ||
392 | set_bit(SW_1, spitzkbd->input.swbit); | ||
393 | |||
394 | input_register_device(&spitzkbd->input); | ||
395 | mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
396 | |||
397 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
398 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { | ||
399 | pxa_gpio_mode(spitz_senses[i] | GPIO_IN); | ||
400 | if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, | ||
401 | SA_INTERRUPT, "Spitzkbd Sense", spitzkbd)) | ||
402 | printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); | ||
403 | else | ||
404 | set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING); | ||
405 | } | ||
406 | |||
407 | /* Set Strobe lines as outputs - set high */ | ||
408 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
409 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
410 | |||
411 | pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); | ||
412 | pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN); | ||
413 | pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); | ||
414 | pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); | ||
415 | |||
416 | request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd); | ||
417 | request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd); | ||
418 | request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd); | ||
419 | request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd); | ||
420 | |||
421 | set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE); | ||
422 | set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE); | ||
423 | set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE); | ||
424 | set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE); | ||
425 | |||
426 | printk(KERN_INFO "input: Spitz Keyboard Registered\n"); | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int spitzkbd_remove(struct device *dev) | ||
432 | { | ||
433 | int i; | ||
434 | struct spitzkbd *spitzkbd = dev_get_drvdata(dev); | ||
435 | |||
436 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) | ||
437 | free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd); | ||
438 | |||
439 | free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd); | ||
440 | free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); | ||
441 | free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); | ||
442 | free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); | ||
443 | |||
444 | del_timer_sync(&spitzkbd->htimer); | ||
445 | del_timer_sync(&spitzkbd->timer); | ||
446 | |||
447 | input_unregister_device(&spitzkbd->input); | ||
448 | |||
449 | kfree(spitzkbd); | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static struct device_driver spitzkbd_driver = { | ||
455 | .name = "spitz-keyboard", | ||
456 | .bus = &platform_bus_type, | ||
457 | .probe = spitzkbd_probe, | ||
458 | .remove = spitzkbd_remove, | ||
459 | .suspend = spitzkbd_suspend, | ||
460 | .resume = spitzkbd_resume, | ||
461 | }; | ||
462 | |||
463 | static int __devinit spitzkbd_init(void) | ||
464 | { | ||
465 | return driver_register(&spitzkbd_driver); | ||
466 | } | ||
467 | |||
468 | static void __exit spitzkbd_exit(void) | ||
469 | { | ||
470 | driver_unregister(&spitzkbd_driver); | ||
471 | } | ||
472 | |||
473 | module_init(spitzkbd_init); | ||
474 | module_exit(spitzkbd_exit); | ||
475 | |||
476 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
477 | MODULE_DESCRIPTION("Spitz Keyboard Driver"); | ||
478 | MODULE_LICENSE("GPLv2"); | ||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 0489af5a80c9..21d55ed4b88a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -24,17 +24,17 @@ config TOUCHSCREEN_BITSY | |||
24 | module will be called h3600_ts_input. | 24 | module will be called h3600_ts_input. |
25 | 25 | ||
26 | config TOUCHSCREEN_CORGI | 26 | config TOUCHSCREEN_CORGI |
27 | tristate "Corgi touchscreen (for Sharp SL-C7xx)" | 27 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver" |
28 | depends on PXA_SHARPSL | 28 | depends on PXA_SHARPSL |
29 | default y | 29 | default y |
30 | help | 30 | help |
31 | Say Y here to enable the driver for the touchscreen on the | 31 | Say Y here to enable the driver for the touchscreen on the |
32 | Sharp SL-C7xx series of PDAs. | 32 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. |
33 | 33 | ||
34 | If unsure, say N. | 34 | If unsure, say N. |
35 | 35 | ||
36 | To compile this driver as a module, choose M here: the | 36 | To compile this driver as a module, choose M here: the |
37 | module will be called ads7846_ts. | 37 | module will be called corgi_ts. |
38 | 38 | ||
39 | config TOUCHSCREEN_GUNZE | 39 | config TOUCHSCREEN_GUNZE |
40 | tristate "Gunze AHL-51S touchscreen" | 40 | tristate "Gunze AHL-51S touchscreen" |
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index 5d19261b884f..4c7fbe550365 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Touchscreen driver for Sharp Corgi models (SL-C7xx) | 2 | * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models |
3 | * | 3 | * |
4 | * Copyright (c) 2004-2005 Richard Purdie | 4 | * Copyright (c) 2004-2005 Richard Purdie |
5 | * | 5 | * |
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <asm/irq.h> | 20 | #include <asm/irq.h> |
21 | 21 | ||
22 | #include <asm/arch/corgi.h> | 22 | #include <asm/arch/sharpsl.h> |
23 | #include <asm/arch/hardware.h> | 23 | #include <asm/arch/hardware.h> |
24 | #include <asm/arch/pxa-regs.h> | 24 | #include <asm/arch/pxa-regs.h> |
25 | 25 | ||
@@ -47,15 +47,20 @@ struct corgi_ts { | |||
47 | struct ts_event tc; | 47 | struct ts_event tc; |
48 | int pendown; | 48 | int pendown; |
49 | int power_mode; | 49 | int power_mode; |
50 | int irq_gpio; | ||
51 | struct corgits_machinfo *machinfo; | ||
50 | }; | 52 | }; |
51 | 53 | ||
52 | #define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC)) | 54 | #ifdef CONFIG_PXA25x |
53 | |||
54 | #define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0); | ||
55 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) | 55 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) |
56 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) | 56 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) |
57 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) | 57 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) |
58 | 58 | #endif | |
59 | #ifdef CONFIG_PXA27x | ||
60 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) | ||
61 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) | ||
62 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) | ||
63 | #endif | ||
59 | 64 | ||
60 | /* ADS7846 Touch Screen Controller bit definitions */ | 65 | /* ADS7846 Touch Screen Controller bit definitions */ |
61 | #define ADSCTRL_PD0 (1u << 0) /* PD0 */ | 66 | #define ADSCTRL_PD0 (1u << 0) /* PD0 */ |
@@ -66,12 +71,11 @@ struct corgi_ts { | |||
66 | #define ADSCTRL_STS (1u << 7) /* Start Bit */ | 71 | #define ADSCTRL_STS (1u << 7) /* Start Bit */ |
67 | 72 | ||
68 | /* External Functions */ | 73 | /* External Functions */ |
69 | extern unsigned long w100fb_get_hsynclen(struct device *dev); | ||
70 | extern unsigned int get_clk_frequency_khz(int info); | 74 | extern unsigned int get_clk_frequency_khz(int info); |
71 | 75 | ||
72 | static unsigned long calc_waittime(void) | 76 | static unsigned long calc_waittime(struct corgi_ts *corgi_ts) |
73 | { | 77 | { |
74 | unsigned long hsync_len = w100fb_get_hsynclen(&corgifb_device.dev); | 78 | unsigned long hsync_len = corgi_ts->machinfo->get_hsync_len(); |
75 | 79 | ||
76 | if (hsync_len) | 80 | if (hsync_len) |
77 | return get_clk_frequency_khz(0)*1000/hsync_len; | 81 | return get_clk_frequency_khz(0)*1000/hsync_len; |
@@ -79,7 +83,8 @@ static unsigned long calc_waittime(void) | |||
79 | return 0; | 83 | return 0; |
80 | } | 84 | } |
81 | 85 | ||
82 | static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time) | 86 | static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, |
87 | unsigned int address, unsigned long wait_time) | ||
83 | { | 88 | { |
84 | unsigned long timer1 = 0, timer2, pmnc = 0; | 89 | unsigned long timer1 = 0, timer2, pmnc = 0; |
85 | int pos = 0; | 90 | int pos = 0; |
@@ -90,7 +95,7 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add | |||
90 | PMNC_SET(0x01); | 95 | PMNC_SET(0x01); |
91 | 96 | ||
92 | /* polling HSync */ | 97 | /* polling HSync */ |
93 | SyncHS(); | 98 | corgi_ts->machinfo->wait_hsync(); |
94 | /* get CCNT */ | 99 | /* get CCNT */ |
95 | CCNT(timer1); | 100 | CCNT(timer1); |
96 | } | 101 | } |
@@ -109,7 +114,7 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add | |||
109 | CCNT(timer2); | 114 | CCNT(timer2); |
110 | if (timer2-timer1 > wait_time) { | 115 | if (timer2-timer1 > wait_time) { |
111 | /* too slow - timeout, try again */ | 116 | /* too slow - timeout, try again */ |
112 | SyncHS(); | 117 | corgi_ts->machinfo->wait_hsync(); |
113 | /* get OSCR */ | 118 | /* get OSCR */ |
114 | CCNT(timer1); | 119 | CCNT(timer1); |
115 | /* Wait after HSync */ | 120 | /* Wait after HSync */ |
@@ -133,23 +138,23 @@ static int read_xydata(struct corgi_ts *corgi_ts) | |||
133 | /* critical section */ | 138 | /* critical section */ |
134 | local_irq_save(flags); | 139 | local_irq_save(flags); |
135 | corgi_ssp_ads7846_lock(); | 140 | corgi_ssp_ads7846_lock(); |
136 | wait_time=calc_waittime(); | 141 | wait_time = calc_waittime(corgi_ts); |
137 | 142 | ||
138 | /* Y-axis */ | 143 | /* Y-axis */ |
139 | sync_receive_data_send_cmd(0, 1, 1u, wait_time); | 144 | sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); |
140 | 145 | ||
141 | /* Y-axis */ | 146 | /* Y-axis */ |
142 | sync_receive_data_send_cmd(1, 1, 1u, wait_time); | 147 | sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); |
143 | 148 | ||
144 | /* X-axis */ | 149 | /* X-axis */ |
145 | y = sync_receive_data_send_cmd(1, 1, 5u, wait_time); | 150 | y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); |
146 | 151 | ||
147 | /* Z1 */ | 152 | /* Z1 */ |
148 | x = sync_receive_data_send_cmd(1, 1, 3u, wait_time); | 153 | x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); |
149 | 154 | ||
150 | /* Z2 */ | 155 | /* Z2 */ |
151 | z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time); | 156 | z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); |
152 | z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time); | 157 | z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); |
153 | 158 | ||
154 | /* Power-Down Enable */ | 159 | /* Power-Down Enable */ |
155 | corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | 160 | corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); |
@@ -189,9 +194,9 @@ static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs) | |||
189 | 194 | ||
190 | static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs) | 195 | static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs) |
191 | { | 196 | { |
192 | if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) { | 197 | if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { |
193 | /* Disable Interrupt */ | 198 | /* Disable Interrupt */ |
194 | set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE); | 199 | set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE); |
195 | if (read_xydata(corgi_ts)) { | 200 | if (read_xydata(corgi_ts)) { |
196 | corgi_ts->pendown = 1; | 201 | corgi_ts->pendown = 1; |
197 | new_data(corgi_ts, regs); | 202 | new_data(corgi_ts, regs); |
@@ -210,7 +215,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_ | |||
210 | } | 215 | } |
211 | 216 | ||
212 | /* Enable Falling Edge */ | 217 | /* Enable Falling Edge */ |
213 | set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING); | 218 | set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING); |
214 | corgi_ts->pendown = 0; | 219 | corgi_ts->pendown = 0; |
215 | } | 220 | } |
216 | } | 221 | } |
@@ -254,7 +259,7 @@ static int corgits_resume(struct device *dev, uint32_t level) | |||
254 | 259 | ||
255 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | 260 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); |
256 | /* Enable Falling Edge */ | 261 | /* Enable Falling Edge */ |
257 | set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING); | 262 | set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING); |
258 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | 263 | corgi_ts->power_mode = PWR_MODE_ACTIVE; |
259 | } | 264 | } |
260 | return 0; | 265 | return 0; |
@@ -267,6 +272,7 @@ static int corgits_resume(struct device *dev, uint32_t level) | |||
267 | static int __init corgits_probe(struct device *dev) | 272 | static int __init corgits_probe(struct device *dev) |
268 | { | 273 | { |
269 | struct corgi_ts *corgi_ts; | 274 | struct corgi_ts *corgi_ts; |
275 | struct platform_device *pdev = to_platform_device(dev); | ||
270 | 276 | ||
271 | if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL))) | 277 | if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL))) |
272 | return -ENOMEM; | 278 | return -ENOMEM; |
@@ -275,6 +281,14 @@ static int __init corgits_probe(struct device *dev) | |||
275 | 281 | ||
276 | memset(corgi_ts, 0, sizeof(struct corgi_ts)); | 282 | memset(corgi_ts, 0, sizeof(struct corgi_ts)); |
277 | 283 | ||
284 | corgi_ts->machinfo = dev->platform_data; | ||
285 | corgi_ts->irq_gpio = platform_get_irq(pdev, 0); | ||
286 | |||
287 | if (corgi_ts->irq_gpio < 0) { | ||
288 | kfree(corgi_ts); | ||
289 | return -ENODEV; | ||
290 | } | ||
291 | |||
278 | init_input_dev(&corgi_ts->input); | 292 | init_input_dev(&corgi_ts->input); |
279 | corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 293 | corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
280 | corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | 294 | corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); |
@@ -293,8 +307,7 @@ static int __init corgits_probe(struct device *dev) | |||
293 | corgi_ts->input.id.product = 0x0002; | 307 | corgi_ts->input.id.product = 0x0002; |
294 | corgi_ts->input.id.version = 0x0100; | 308 | corgi_ts->input.id.version = 0x0100; |
295 | 309 | ||
296 | pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN); | 310 | pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); |
297 | pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN); | ||
298 | 311 | ||
299 | /* Initiaize ADS7846 Difference Reference mode */ | 312 | /* Initiaize ADS7846 Difference Reference mode */ |
300 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | 313 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); |
@@ -313,14 +326,14 @@ static int __init corgits_probe(struct device *dev) | |||
313 | input_register_device(&corgi_ts->input); | 326 | input_register_device(&corgi_ts->input); |
314 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | 327 | corgi_ts->power_mode = PWR_MODE_ACTIVE; |
315 | 328 | ||
316 | if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) { | 329 | if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) { |
317 | input_unregister_device(&corgi_ts->input); | 330 | input_unregister_device(&corgi_ts->input); |
318 | kfree(corgi_ts); | 331 | kfree(corgi_ts); |
319 | return -EBUSY; | 332 | return -EBUSY; |
320 | } | 333 | } |
321 | 334 | ||
322 | /* Enable Falling Edge */ | 335 | /* Enable Falling Edge */ |
323 | set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING); | 336 | set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING); |
324 | 337 | ||
325 | printk(KERN_INFO "input: Corgi Touchscreen Registered\n"); | 338 | printk(KERN_INFO "input: Corgi Touchscreen Registered\n"); |
326 | 339 | ||
@@ -331,8 +344,9 @@ static int corgits_remove(struct device *dev) | |||
331 | { | 344 | { |
332 | struct corgi_ts *corgi_ts = dev_get_drvdata(dev); | 345 | struct corgi_ts *corgi_ts = dev_get_drvdata(dev); |
333 | 346 | ||
334 | free_irq(CORGI_IRQ_GPIO_TP_INT, NULL); | 347 | free_irq(corgi_ts->irq_gpio, NULL); |
335 | del_timer_sync(&corgi_ts->timer); | 348 | del_timer_sync(&corgi_ts->timer); |
349 | corgi_ts->machinfo->put_hsync(); | ||
336 | input_unregister_device(&corgi_ts->input); | 350 | input_unregister_device(&corgi_ts->input); |
337 | kfree(corgi_ts); | 351 | kfree(corgi_ts); |
338 | return 0; | 352 | return 0; |
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c index 8337b0f26cc4..4866fc32d8d9 100644 --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c | |||
@@ -61,6 +61,7 @@ static const PCI_ENTRY id_list[] = | |||
61 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, | 61 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, |
62 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, | 62 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, |
63 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, | 63 | {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, |
64 | {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"}, | ||
64 | {0, 0, NULL, NULL}, | 65 | {0, 0, NULL, NULL}, |
65 | }; | 66 | }; |
66 | 67 | ||
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index c6b5bf7d2aca..dc334aab433e 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c | |||
@@ -611,7 +611,7 @@ static int sedlbauer_event(event_t event, int priority, | |||
611 | } /* sedlbauer_event */ | 611 | } /* sedlbauer_event */ |
612 | 612 | ||
613 | static struct pcmcia_device_id sedlbauer_ids[] = { | 613 | static struct pcmcia_device_id sedlbauer_ids[] = { |
614 | PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c), | 614 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a), |
615 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90), | 615 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90), |
616 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce), | 616 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce), |
617 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe), | 617 | PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe), |
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h index 0fda5c89429b..9ffaae7c657a 100644 --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h | |||
@@ -466,10 +466,10 @@ void st5481_stop(struct st5481_adapter *adapter); | |||
466 | #define __debug_variable st5481_debug | 466 | #define __debug_variable st5481_debug |
467 | #include "hisax_debug.h" | 467 | #include "hisax_debug.h" |
468 | 468 | ||
469 | #ifdef CONFIG_HISAX_DEBUG | ||
470 | |||
471 | extern int st5481_debug; | 469 | extern int st5481_debug; |
472 | 470 | ||
471 | #ifdef CONFIG_HISAX_DEBUG | ||
472 | |||
473 | #define DBG_ISO_PACKET(level,urb) \ | 473 | #define DBG_ISO_PACKET(level,urb) \ |
474 | if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) | 474 | if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb) |
475 | 475 | ||
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c index 2fcd093921d8..0a2536d62402 100644 --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c | |||
@@ -172,14 +172,18 @@ static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs) | |||
172 | test_and_clear_bit(buf_nr, &b_out->busy); | 172 | test_and_clear_bit(buf_nr, &b_out->busy); |
173 | 173 | ||
174 | if (unlikely(urb->status < 0)) { | 174 | if (unlikely(urb->status < 0)) { |
175 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 175 | switch (urb->status) { |
176 | WARN("urb status %d",urb->status); | 176 | case -ENOENT: |
177 | if (b_out->busy == 0) { | 177 | case -ESHUTDOWN: |
178 | st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); | 178 | case -ECONNRESET: |
179 | } | 179 | DBG(4,"urb killed status %d", urb->status); |
180 | } else { | 180 | return; // Give up |
181 | DBG(1,"urb killed"); | 181 | default: |
182 | return; // Give up | 182 | WARN("urb status %d",urb->status); |
183 | if (b_out->busy == 0) { | ||
184 | st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL); | ||
185 | } | ||
186 | break; | ||
183 | } | 187 | } |
184 | } | 188 | } |
185 | 189 | ||
@@ -205,7 +209,9 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode) | |||
205 | bcs->mode = mode; | 209 | bcs->mode = mode; |
206 | 210 | ||
207 | // Cancel all USB transfers on this B channel | 211 | // Cancel all USB transfers on this B channel |
212 | b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; | ||
208 | usb_unlink_urb(b_out->urb[0]); | 213 | usb_unlink_urb(b_out->urb[0]); |
214 | b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; | ||
209 | usb_unlink_urb(b_out->urb[1]); | 215 | usb_unlink_urb(b_out->urb[1]); |
210 | b_out->busy = 0; | 216 | b_out->busy = 0; |
211 | 217 | ||
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c index 071b1d31999f..941f7022ada1 100644 --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c | |||
@@ -382,16 +382,20 @@ static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs) | |||
382 | test_and_clear_bit(buf_nr, &d_out->busy); | 382 | test_and_clear_bit(buf_nr, &d_out->busy); |
383 | 383 | ||
384 | if (unlikely(urb->status < 0)) { | 384 | if (unlikely(urb->status < 0)) { |
385 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 385 | switch (urb->status) { |
386 | WARN("urb status %d",urb->status); | 386 | case -ENOENT: |
387 | if (d_out->busy == 0) { | 387 | case -ESHUTDOWN: |
388 | st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); | 388 | case -ECONNRESET: |
389 | } | 389 | DBG(1,"urb killed status %d", urb->status); |
390 | return; | 390 | break; |
391 | } else { | 391 | default: |
392 | DBG(1,"urb killed"); | 392 | WARN("urb status %d",urb->status); |
393 | return; // Give up | 393 | if (d_out->busy == 0) { |
394 | st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter); | ||
395 | } | ||
396 | break; | ||
394 | } | 397 | } |
398 | return; // Give up | ||
395 | } | 399 | } |
396 | 400 | ||
397 | FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr); | 401 | FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr); |
@@ -709,14 +713,14 @@ int st5481_setup_d(struct st5481_adapter *adapter) | |||
709 | 713 | ||
710 | adapter->l1m.fsm = &l1fsm; | 714 | adapter->l1m.fsm = &l1fsm; |
711 | adapter->l1m.state = ST_L1_F3; | 715 | adapter->l1m.state = ST_L1_F3; |
712 | adapter->l1m.debug = 1; | 716 | adapter->l1m.debug = st5481_debug & 0x100; |
713 | adapter->l1m.userdata = adapter; | 717 | adapter->l1m.userdata = adapter; |
714 | adapter->l1m.printdebug = l1m_debug; | 718 | adapter->l1m.printdebug = l1m_debug; |
715 | FsmInitTimer(&adapter->l1m, &adapter->timer); | 719 | FsmInitTimer(&adapter->l1m, &adapter->timer); |
716 | 720 | ||
717 | adapter->d_out.fsm.fsm = &dout_fsm; | 721 | adapter->d_out.fsm.fsm = &dout_fsm; |
718 | adapter->d_out.fsm.state = ST_DOUT_NONE; | 722 | adapter->d_out.fsm.state = ST_DOUT_NONE; |
719 | adapter->d_out.fsm.debug = 1; | 723 | adapter->d_out.fsm.debug = st5481_debug & 0x100; |
720 | adapter->d_out.fsm.userdata = adapter; | 724 | adapter->d_out.fsm.userdata = adapter; |
721 | adapter->d_out.fsm.printdebug = dout_debug; | 725 | adapter->d_out.fsm.printdebug = dout_debug; |
722 | 726 | ||
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 7aa810d5d333..2cf5d1a6df6c 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c | |||
@@ -43,10 +43,10 @@ static int number_of_leds = 2; /* 2 LEDs on the adpater default */ | |||
43 | module_param(number_of_leds, int, 0); | 43 | module_param(number_of_leds, int, 0); |
44 | 44 | ||
45 | #ifdef CONFIG_HISAX_DEBUG | 45 | #ifdef CONFIG_HISAX_DEBUG |
46 | static int debug = 0x1; | 46 | static int debug = 0; |
47 | module_param(debug, int, 0); | 47 | module_param(debug, int, 0); |
48 | int st5481_debug; | ||
49 | #endif | 48 | #endif |
49 | int st5481_debug; | ||
50 | 50 | ||
51 | static LIST_HEAD(adapter_list); | 51 | static LIST_HEAD(adapter_list); |
52 | 52 | ||
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index ab62223297a5..ffd5b2d45552 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c | |||
@@ -132,11 +132,15 @@ static void usb_ctrl_complete(struct urb *urb, struct pt_regs *regs) | |||
132 | struct ctrl_msg *ctrl_msg; | 132 | struct ctrl_msg *ctrl_msg; |
133 | 133 | ||
134 | if (unlikely(urb->status < 0)) { | 134 | if (unlikely(urb->status < 0)) { |
135 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 135 | switch (urb->status) { |
136 | WARN("urb status %d",urb->status); | 136 | case -ENOENT: |
137 | } else { | 137 | case -ESHUTDOWN: |
138 | DBG(1,"urb killed"); | 138 | case -ECONNRESET: |
139 | return; // Give up | 139 | DBG(1,"urb killed status %d", urb->status); |
140 | return; // Give up | ||
141 | default: | ||
142 | WARN("urb status %d",urb->status); | ||
143 | break; | ||
140 | } | 144 | } |
141 | } | 145 | } |
142 | 146 | ||
@@ -184,22 +188,22 @@ static void usb_int_complete(struct urb *urb, struct pt_regs *regs) | |||
184 | int status; | 188 | int status; |
185 | 189 | ||
186 | switch (urb->status) { | 190 | switch (urb->status) { |
187 | case 0: | 191 | case 0: |
188 | /* success */ | 192 | /* success */ |
189 | break; | 193 | break; |
190 | case -ECONNRESET: | 194 | case -ECONNRESET: |
191 | case -ENOENT: | 195 | case -ENOENT: |
192 | case -ESHUTDOWN: | 196 | case -ESHUTDOWN: |
193 | /* this urb is terminated, clean up */ | 197 | /* this urb is terminated, clean up */ |
194 | DBG(1, "urb shutting down with status: %d", urb->status); | 198 | DBG(2, "urb shutting down with status: %d", urb->status); |
195 | return; | 199 | return; |
196 | default: | 200 | default: |
197 | WARN("nonzero urb status received: %d", urb->status); | 201 | WARN("nonzero urb status received: %d", urb->status); |
198 | goto exit; | 202 | goto exit; |
199 | } | 203 | } |
200 | 204 | ||
201 | 205 | ||
202 | DBG_PACKET(1, data, INT_PKT_SIZE); | 206 | DBG_PACKET(2, data, INT_PKT_SIZE); |
203 | 207 | ||
204 | if (urb->actual_length == 0) { | 208 | if (urb->actual_length == 0) { |
205 | goto exit; | 209 | goto exit; |
@@ -250,7 +254,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
250 | struct urb *urb; | 254 | struct urb *urb; |
251 | u8 *buf; | 255 | u8 *buf; |
252 | 256 | ||
253 | DBG(1,""); | 257 | DBG(2,""); |
254 | 258 | ||
255 | if ((status = usb_reset_configuration (dev)) < 0) { | 259 | if ((status = usb_reset_configuration (dev)) < 0) { |
256 | WARN("reset_configuration failed,status=%d",status); | 260 | WARN("reset_configuration failed,status=%d",status); |
@@ -330,15 +334,17 @@ void st5481_release_usb(struct st5481_adapter *adapter) | |||
330 | DBG(1,""); | 334 | DBG(1,""); |
331 | 335 | ||
332 | // Stop and free Control and Interrupt URBs | 336 | // Stop and free Control and Interrupt URBs |
333 | usb_unlink_urb(ctrl->urb); | 337 | usb_kill_urb(ctrl->urb); |
334 | if (ctrl->urb->transfer_buffer) | 338 | if (ctrl->urb->transfer_buffer) |
335 | kfree(ctrl->urb->transfer_buffer); | 339 | kfree(ctrl->urb->transfer_buffer); |
336 | usb_free_urb(ctrl->urb); | 340 | usb_free_urb(ctrl->urb); |
341 | ctrl->urb = NULL; | ||
337 | 342 | ||
338 | usb_unlink_urb(intr->urb); | 343 | usb_kill_urb(intr->urb); |
339 | if (intr->urb->transfer_buffer) | 344 | if (intr->urb->transfer_buffer) |
340 | kfree(intr->urb->transfer_buffer); | 345 | kfree(intr->urb->transfer_buffer); |
341 | usb_free_urb(intr->urb); | 346 | usb_free_urb(intr->urb); |
347 | ctrl->urb = NULL; | ||
342 | } | 348 | } |
343 | 349 | ||
344 | /* | 350 | /* |
@@ -406,6 +412,7 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev, | |||
406 | spin_lock_init(&urb->lock); | 412 | spin_lock_init(&urb->lock); |
407 | urb->dev=dev; | 413 | urb->dev=dev; |
408 | urb->pipe=pipe; | 414 | urb->pipe=pipe; |
415 | urb->interval = 1; | ||
409 | urb->transfer_buffer=buf; | 416 | urb->transfer_buffer=buf; |
410 | urb->number_of_packets = num_packets; | 417 | urb->number_of_packets = num_packets; |
411 | urb->transfer_buffer_length=num_packets*packet_size; | 418 | urb->transfer_buffer_length=num_packets*packet_size; |
@@ -452,7 +459,9 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev, | |||
452 | if (urb[j]) { | 459 | if (urb[j]) { |
453 | if (urb[j]->transfer_buffer) | 460 | if (urb[j]->transfer_buffer) |
454 | kfree(urb[j]->transfer_buffer); | 461 | kfree(urb[j]->transfer_buffer); |
462 | urb[j]->transfer_buffer = NULL; | ||
455 | usb_free_urb(urb[j]); | 463 | usb_free_urb(urb[j]); |
464 | urb[j] = NULL; | ||
456 | } | 465 | } |
457 | } | 466 | } |
458 | return retval; | 467 | return retval; |
@@ -463,10 +472,11 @@ void st5481_release_isocpipes(struct urb* urb[2]) | |||
463 | int j; | 472 | int j; |
464 | 473 | ||
465 | for (j = 0; j < 2; j++) { | 474 | for (j = 0; j < 2; j++) { |
466 | usb_unlink_urb(urb[j]); | 475 | usb_kill_urb(urb[j]); |
467 | if (urb[j]->transfer_buffer) | 476 | if (urb[j]->transfer_buffer) |
468 | kfree(urb[j]->transfer_buffer); | 477 | kfree(urb[j]->transfer_buffer); |
469 | usb_free_urb(urb[j]); | 478 | usb_free_urb(urb[j]); |
479 | urb[j] = NULL; | ||
470 | } | 480 | } |
471 | } | 481 | } |
472 | 482 | ||
@@ -485,11 +495,15 @@ static void usb_in_complete(struct urb *urb, struct pt_regs *regs) | |||
485 | int len, count, status; | 495 | int len, count, status; |
486 | 496 | ||
487 | if (unlikely(urb->status < 0)) { | 497 | if (unlikely(urb->status < 0)) { |
488 | if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) { | 498 | switch (urb->status) { |
489 | WARN("urb status %d",urb->status); | 499 | case -ENOENT: |
490 | } else { | 500 | case -ESHUTDOWN: |
491 | DBG(1,"urb killed"); | 501 | case -ECONNRESET: |
492 | return; // Give up | 502 | DBG(1,"urb killed status %d", urb->status); |
503 | return; // Give up | ||
504 | default: | ||
505 | WARN("urb status %d",urb->status); | ||
506 | break; | ||
493 | } | 507 | } |
494 | } | 508 | } |
495 | 509 | ||
@@ -631,7 +645,9 @@ void st5481_in_mode(struct st5481_in *in, int mode) | |||
631 | 645 | ||
632 | in->mode = mode; | 646 | in->mode = mode; |
633 | 647 | ||
648 | in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK; | ||
634 | usb_unlink_urb(in->urb[0]); | 649 | usb_unlink_urb(in->urb[0]); |
650 | in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK; | ||
635 | usb_unlink_urb(in->urb[1]); | 651 | usb_unlink_urb(in->urb[1]); |
636 | 652 | ||
637 | if (in->mode != L1_MODE_NULL) { | 653 | if (in->mode != L1_MODE_NULL) { |
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c index 40b0df04ed9f..1ebed041672d 100644 --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c | |||
@@ -87,7 +87,7 @@ static int __init sc_init(void) | |||
87 | */ | 87 | */ |
88 | for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) { | 88 | for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) { |
89 | if(!request_region(io[b] + i * 0x400, 1, "sc test")) { | 89 | if(!request_region(io[b] + i * 0x400, 1, "sc test")) { |
90 | pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400); | 90 | pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400); |
91 | io[b] = 0; | 91 | io[b] = 0; |
92 | break; | 92 | break; |
93 | } else | 93 | } else |
@@ -181,7 +181,7 @@ static int __init sc_init(void) | |||
181 | for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) { | 181 | for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) { |
182 | pr_debug("Checking RAM address 0x%x...\n", i); | 182 | pr_debug("Checking RAM address 0x%x...\n", i); |
183 | if(request_region(i, SRAM_PAGESIZE, "sc test")) { | 183 | if(request_region(i, SRAM_PAGESIZE, "sc test")) { |
184 | pr_debug(" check_region succeeded\n"); | 184 | pr_debug(" request_region succeeded\n"); |
185 | model = identify_board(i, io[b]); | 185 | model = identify_board(i, io[b]); |
186 | release_region(i, SRAM_PAGESIZE); | 186 | release_region(i, SRAM_PAGESIZE); |
187 | if (model >= 0) { | 187 | if (model >= 0) { |
diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h index f80ee6350edf..31cbee71365f 100644 --- a/drivers/md/raid6.h +++ b/drivers/md/raid6.h | |||
@@ -69,9 +69,13 @@ extern const char raid6_empty_zero_page[PAGE_SIZE]; | |||
69 | #define __init | 69 | #define __init |
70 | #define __exit | 70 | #define __exit |
71 | #define __attribute_const__ __attribute__((const)) | 71 | #define __attribute_const__ __attribute__((const)) |
72 | #define noinline __attribute__((noinline)) | ||
72 | 73 | ||
73 | #define preempt_enable() | 74 | #define preempt_enable() |
74 | #define preempt_disable() | 75 | #define preempt_disable() |
76 | #define cpu_has_feature(x) 1 | ||
77 | #define enable_kernel_altivec() | ||
78 | #define disable_kernel_altivec() | ||
75 | 79 | ||
76 | #endif /* __KERNEL__ */ | 80 | #endif /* __KERNEL__ */ |
77 | 81 | ||
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c index acf386fc4b4f..51c63c0cf1c9 100644 --- a/drivers/md/raid6algos.c +++ b/drivers/md/raid6algos.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include "raid6.h" | 19 | #include "raid6.h" |
20 | #ifndef __KERNEL__ | 20 | #ifndef __KERNEL__ |
21 | #include <sys/mman.h> | 21 | #include <sys/mman.h> |
22 | #include <stdio.h> | ||
22 | #endif | 23 | #endif |
23 | 24 | ||
24 | struct raid6_calls raid6_call; | 25 | struct raid6_calls raid6_call; |
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc index 1de8f030eee0..b9afd35b8812 100644 --- a/drivers/md/raid6altivec.uc +++ b/drivers/md/raid6altivec.uc | |||
@@ -27,16 +27,20 @@ | |||
27 | #ifdef CONFIG_ALTIVEC | 27 | #ifdef CONFIG_ALTIVEC |
28 | 28 | ||
29 | #include <altivec.h> | 29 | #include <altivec.h> |
30 | #include <asm/system.h> | 30 | #ifdef __KERNEL__ |
31 | #include <asm/cputable.h> | 31 | # include <asm/system.h> |
32 | # include <asm/cputable.h> | ||
33 | #endif | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * This is the C data type to use | 36 | * This is the C data type to use. We use a vector of |
37 | * signed char so vec_cmpgt() will generate the right | ||
38 | * instruction. | ||
35 | */ | 39 | */ |
36 | 40 | ||
37 | typedef vector unsigned char unative_t; | 41 | typedef vector signed char unative_t; |
38 | 42 | ||
39 | #define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) | 43 | #define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x}) |
40 | #define NSIZE sizeof(unative_t) | 44 | #define NSIZE sizeof(unative_t) |
41 | 45 | ||
42 | /* | 46 | /* |
@@ -108,7 +112,11 @@ int raid6_have_altivec(void); | |||
108 | int raid6_have_altivec(void) | 112 | int raid6_have_altivec(void) |
109 | { | 113 | { |
110 | /* This assumes either all CPUs have Altivec or none does */ | 114 | /* This assumes either all CPUs have Altivec or none does */ |
115 | # ifdef __KERNEL__ | ||
111 | return cpu_has_feature(CPU_FTR_ALTIVEC); | 116 | return cpu_has_feature(CPU_FTR_ALTIVEC); |
117 | # else | ||
118 | return 1; | ||
119 | # endif | ||
112 | } | 120 | } |
113 | #endif | 121 | #endif |
114 | 122 | ||
diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile index 557806728609..78e0396adf2a 100644 --- a/drivers/md/raid6test/Makefile +++ b/drivers/md/raid6test/Makefile | |||
@@ -8,6 +8,8 @@ OPTFLAGS = -O2 # Adjust as desired | |||
8 | CFLAGS = -I.. -g $(OPTFLAGS) | 8 | CFLAGS = -I.. -g $(OPTFLAGS) |
9 | LD = ld | 9 | LD = ld |
10 | PERL = perl | 10 | PERL = perl |
11 | AR = ar | ||
12 | RANLIB = ranlib | ||
11 | 13 | ||
12 | .c.o: | 14 | .c.o: |
13 | $(CC) $(CFLAGS) -c -o $@ $< | 15 | $(CC) $(CFLAGS) -c -o $@ $< |
@@ -18,18 +20,33 @@ PERL = perl | |||
18 | %.uc: ../%.uc | 20 | %.uc: ../%.uc |
19 | cp -f $< $@ | 21 | cp -f $< $@ |
20 | 22 | ||
21 | all: raid6.o raid6test | 23 | all: raid6.a raid6test |
22 | 24 | ||
23 | raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ | 25 | raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \ |
24 | raid6int32.o \ | 26 | raid6int32.o \ |
25 | raid6mmx.o raid6sse1.o raid6sse2.o \ | 27 | raid6mmx.o raid6sse1.o raid6sse2.o \ |
28 | raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \ | ||
26 | raid6recov.o raid6algos.o \ | 29 | raid6recov.o raid6algos.o \ |
27 | raid6tables.o | 30 | raid6tables.o |
28 | $(LD) -r -o $@ $^ | 31 | rm -f $@ |
32 | $(AR) cq $@ $^ | ||
33 | $(RANLIB) $@ | ||
29 | 34 | ||
30 | raid6test: raid6.o test.c | 35 | raid6test: test.c raid6.a |
31 | $(CC) $(CFLAGS) -o raid6test $^ | 36 | $(CC) $(CFLAGS) -o raid6test $^ |
32 | 37 | ||
38 | raid6altivec1.c: raid6altivec.uc ../unroll.pl | ||
39 | $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@ | ||
40 | |||
41 | raid6altivec2.c: raid6altivec.uc ../unroll.pl | ||
42 | $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@ | ||
43 | |||
44 | raid6altivec4.c: raid6altivec.uc ../unroll.pl | ||
45 | $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@ | ||
46 | |||
47 | raid6altivec8.c: raid6altivec.uc ../unroll.pl | ||
48 | $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@ | ||
49 | |||
33 | raid6int1.c: raid6int.uc ../unroll.pl | 50 | raid6int1.c: raid6int.uc ../unroll.pl |
34 | $(PERL) ../unroll.pl 1 < raid6int.uc > $@ | 51 | $(PERL) ../unroll.pl 1 < raid6int.uc > $@ |
35 | 52 | ||
@@ -52,7 +69,7 @@ raid6tables.c: mktables | |||
52 | ./mktables > raid6tables.c | 69 | ./mktables > raid6tables.c |
53 | 70 | ||
54 | clean: | 71 | clean: |
55 | rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test | 72 | rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test |
56 | 73 | ||
57 | spotless: clean | 74 | spotless: clean |
58 | rm -f *~ | 75 | rm -f *~ |
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c index 8b4ad70dd1b2..877c770558e9 100644 --- a/drivers/media/radio/radio-aimslab.c +++ b/drivers/media/radio/radio-aimslab.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/module.h> /* Modules */ | 30 | #include <linux/module.h> /* Modules */ |
31 | #include <linux/init.h> /* Initdata */ | 31 | #include <linux/init.h> /* Initdata */ |
32 | #include <linux/ioport.h> /* check_region, request_region */ | 32 | #include <linux/ioport.h> /* request_region */ |
33 | #include <linux/delay.h> /* udelay */ | 33 | #include <linux/delay.h> /* udelay */ |
34 | #include <asm/io.h> /* outb, outb_p */ | 34 | #include <asm/io.h> /* outb, outb_p */ |
35 | #include <asm/uaccess.h> /* copy to/from user */ | 35 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-aztech.c b/drivers/media/radio/radio-aztech.c index 013c835ed910..5319a9c9a979 100644 --- a/drivers/media/radio/radio-aztech.c +++ b/drivers/media/radio/radio-aztech.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | #include <linux/module.h> /* Modules */ | 27 | #include <linux/module.h> /* Modules */ |
28 | #include <linux/init.h> /* Initdata */ | 28 | #include <linux/init.h> /* Initdata */ |
29 | #include <linux/ioport.h> /* check_region, request_region */ | 29 | #include <linux/ioport.h> /* request_region */ |
30 | #include <linux/delay.h> /* udelay */ | 30 | #include <linux/delay.h> /* udelay */ |
31 | #include <asm/io.h> /* outb, outb_p */ | 31 | #include <asm/io.h> /* outb, outb_p */ |
32 | #include <asm/uaccess.h> /* copy to/from user */ | 32 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c index 53d399b6652b..022913da8c59 100644 --- a/drivers/media/radio/radio-cadet.c +++ b/drivers/media/radio/radio-cadet.c | |||
@@ -29,7 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/module.h> /* Modules */ | 30 | #include <linux/module.h> /* Modules */ |
31 | #include <linux/init.h> /* Initdata */ | 31 | #include <linux/init.h> /* Initdata */ |
32 | #include <linux/ioport.h> /* check_region, request_region */ | 32 | #include <linux/ioport.h> /* request_region */ |
33 | #include <linux/delay.h> /* udelay */ | 33 | #include <linux/delay.h> /* udelay */ |
34 | #include <asm/io.h> /* outb, outb_p */ | 34 | #include <asm/io.h> /* outb, outb_p */ |
35 | #include <asm/uaccess.h> /* copy to/from user */ | 35 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-gemtek.c b/drivers/media/radio/radio-gemtek.c index 202bfe6819b8..6418f03b9ce4 100644 --- a/drivers/media/radio/radio-gemtek.c +++ b/drivers/media/radio/radio-gemtek.c | |||
@@ -17,7 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/module.h> /* Modules */ | 18 | #include <linux/module.h> /* Modules */ |
19 | #include <linux/init.h> /* Initdata */ | 19 | #include <linux/init.h> /* Initdata */ |
20 | #include <linux/ioport.h> /* check_region, request_region */ | 20 | #include <linux/ioport.h> /* request_region */ |
21 | #include <linux/delay.h> /* udelay */ | 21 | #include <linux/delay.h> /* udelay */ |
22 | #include <asm/io.h> /* outb, outb_p */ | 22 | #include <asm/io.h> /* outb, outb_p */ |
23 | #include <asm/uaccess.h> /* copy to/from user */ | 23 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-rtrack2.c b/drivers/media/radio/radio-rtrack2.c index c00245d4d249..b2256d675b44 100644 --- a/drivers/media/radio/radio-rtrack2.c +++ b/drivers/media/radio/radio-rtrack2.c | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/module.h> /* Modules */ | 11 | #include <linux/module.h> /* Modules */ |
12 | #include <linux/init.h> /* Initdata */ | 12 | #include <linux/init.h> /* Initdata */ |
13 | #include <linux/ioport.h> /* check_region, request_region */ | 13 | #include <linux/ioport.h> /* request_region */ |
14 | #include <linux/delay.h> /* udelay */ | 14 | #include <linux/delay.h> /* udelay */ |
15 | #include <asm/io.h> /* outb, outb_p */ | 15 | #include <asm/io.h> /* outb, outb_p */ |
16 | #include <asm/uaccess.h> /* copy to/from user */ | 16 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c index 3a464a09221f..6f03ce4dd7b0 100644 --- a/drivers/media/radio/radio-sf16fmi.c +++ b/drivers/media/radio/radio-sf16fmi.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/kernel.h> /* __setup */ | 18 | #include <linux/kernel.h> /* __setup */ |
19 | #include <linux/module.h> /* Modules */ | 19 | #include <linux/module.h> /* Modules */ |
20 | #include <linux/init.h> /* Initdata */ | 20 | #include <linux/init.h> /* Initdata */ |
21 | #include <linux/ioport.h> /* check_region, request_region */ | 21 | #include <linux/ioport.h> /* request_region */ |
22 | #include <linux/delay.h> /* udelay */ | 22 | #include <linux/delay.h> /* udelay */ |
23 | #include <linux/videodev.h> /* kernel radio structs */ | 23 | #include <linux/videodev.h> /* kernel radio structs */ |
24 | #include <linux/isapnp.h> | 24 | #include <linux/isapnp.h> |
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c index 0732efda6a98..71971e9bb342 100644 --- a/drivers/media/radio/radio-sf16fmr2.c +++ b/drivers/media/radio/radio-sf16fmr2.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/module.h> /* Modules */ | 15 | #include <linux/module.h> /* Modules */ |
16 | #include <linux/init.h> /* Initdata */ | 16 | #include <linux/init.h> /* Initdata */ |
17 | #include <linux/ioport.h> /* check_region, request_region */ | 17 | #include <linux/ioport.h> /* request_region */ |
18 | #include <linux/delay.h> /* udelay */ | 18 | #include <linux/delay.h> /* udelay */ |
19 | #include <asm/io.h> /* outb, outb_p */ | 19 | #include <asm/io.h> /* outb, outb_p */ |
20 | #include <asm/uaccess.h> /* copy to/from user */ | 20 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-terratec.c b/drivers/media/radio/radio-terratec.c index 248d67fde037..b03573c6840e 100644 --- a/drivers/media/radio/radio-terratec.c +++ b/drivers/media/radio/radio-terratec.c | |||
@@ -25,7 +25,7 @@ | |||
25 | 25 | ||
26 | #include <linux/module.h> /* Modules */ | 26 | #include <linux/module.h> /* Modules */ |
27 | #include <linux/init.h> /* Initdata */ | 27 | #include <linux/init.h> /* Initdata */ |
28 | #include <linux/ioport.h> /* check_region, request_region */ | 28 | #include <linux/ioport.h> /* request_region */ |
29 | #include <linux/delay.h> /* udelay */ | 29 | #include <linux/delay.h> /* udelay */ |
30 | #include <asm/io.h> /* outb, outb_p */ | 30 | #include <asm/io.h> /* outb, outb_p */ |
31 | #include <asm/uaccess.h> /* copy to/from user */ | 31 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-typhoon.c b/drivers/media/radio/radio-typhoon.c index d7da901ebe90..f304f3c14763 100644 --- a/drivers/media/radio/radio-typhoon.c +++ b/drivers/media/radio/radio-typhoon.c | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | #include <linux/module.h> /* Modules */ | 32 | #include <linux/module.h> /* Modules */ |
33 | #include <linux/init.h> /* Initdata */ | 33 | #include <linux/init.h> /* Initdata */ |
34 | #include <linux/ioport.h> /* check_region, request_region */ | 34 | #include <linux/ioport.h> /* request_region */ |
35 | #include <linux/proc_fs.h> /* radio card status report */ | 35 | #include <linux/proc_fs.h> /* radio card status report */ |
36 | #include <asm/io.h> /* outb, outb_p */ | 36 | #include <asm/io.h> /* outb, outb_p */ |
37 | #include <asm/uaccess.h> /* copy to/from user */ | 37 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/radio/radio-zoltrix.c b/drivers/media/radio/radio-zoltrix.c index 342f92df4aba..4c6d6fb49034 100644 --- a/drivers/media/radio/radio-zoltrix.c +++ b/drivers/media/radio/radio-zoltrix.c | |||
@@ -28,7 +28,7 @@ | |||
28 | 28 | ||
29 | #include <linux/module.h> /* Modules */ | 29 | #include <linux/module.h> /* Modules */ |
30 | #include <linux/init.h> /* Initdata */ | 30 | #include <linux/init.h> /* Initdata */ |
31 | #include <linux/ioport.h> /* check_region, request_region */ | 31 | #include <linux/ioport.h> /* request_region */ |
32 | #include <linux/delay.h> /* udelay, msleep */ | 32 | #include <linux/delay.h> /* udelay, msleep */ |
33 | #include <asm/io.h> /* outb, outb_p */ | 33 | #include <asm/io.h> /* outb, outb_p */ |
34 | #include <asm/uaccess.h> /* copy to/from user */ | 34 | #include <asm/uaccess.h> /* copy to/from user */ |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index c9106b1d79df..4334744652de 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -221,9 +221,7 @@ static int lgdt330x_pll_set(struct dvb_frontend* fe, | |||
221 | int err; | 221 | int err; |
222 | 222 | ||
223 | /* Put the analog decoder in standby to keep it quiet */ | 223 | /* Put the analog decoder in standby to keep it quiet */ |
224 | if (core->tda9887_conf) { | 224 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); |
225 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
226 | } | ||
227 | 225 | ||
228 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); | 226 | dvb_pll_configure(core->pll_desc, buf, params->frequency, 0); |
229 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", | 227 | dprintk(1, "%s: tuner at 0x%02x bytes: 0x%02x 0x%02x 0x%02x 0x%02x\n", |
@@ -402,6 +400,9 @@ static int dvb_register(struct cx8802_dev *dev) | |||
402 | dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; | 400 | dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max; |
403 | } | 401 | } |
404 | 402 | ||
403 | /* Put the analog decoder in standby to keep it quiet */ | ||
404 | cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); | ||
405 | |||
405 | /* register everything */ | 406 | /* register everything */ |
406 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); | 407 | return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev); |
407 | } | 408 | } |
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index d15da6fd84c1..b7f093fbf9b0 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c | |||
@@ -82,7 +82,7 @@ int __init init_sharpsl(void) | |||
82 | } else if (machine_is_tosa()) { | 82 | } else if (machine_is_tosa()) { |
83 | sharpsl_partitions[0].size=0x006a0000; | 83 | sharpsl_partitions[0].size=0x006a0000; |
84 | sharpsl_partitions[0].offset=0x00160000; | 84 | sharpsl_partitions[0].offset=0x00160000; |
85 | } else if (machine_is_spitz()) { | 85 | } else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) { |
86 | sharpsl_partitions[0].size=0x006b0000; | 86 | sharpsl_partitions[0].size=0x006b0000; |
87 | sharpsl_partitions[0].offset=0x00140000; | 87 | sharpsl_partitions[0].offset=0x00140000; |
88 | } else { | 88 | } else { |
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 9853b87bb756..88b5b5b40b43 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c | |||
@@ -221,10 +221,16 @@ sharpsl_nand_init(void) | |||
221 | sharpsl_partition_info[1].size=25 * 1024 * 1024; | 221 | sharpsl_partition_info[1].size=25 * 1024 * 1024; |
222 | } else if (machine_is_husky()) { | 222 | } else if (machine_is_husky()) { |
223 | sharpsl_partition_info[1].size=53 * 1024 * 1024; | 223 | sharpsl_partition_info[1].size=53 * 1024 * 1024; |
224 | } | 224 | } else if (machine_is_spitz()) { |
225 | sharpsl_partition_info[1].size=5 * 1024 * 1024; | ||
226 | } else if (machine_is_akita()) { | ||
227 | sharpsl_partition_info[1].size=58 * 1024 * 1024; | ||
228 | } else if (machine_is_borzoi()) { | ||
229 | sharpsl_partition_info[1].size=32 * 1024 * 1024; | ||
230 | } | ||
225 | } | 231 | } |
226 | 232 | ||
227 | if (machine_is_husky()) { | 233 | if (machine_is_husky() || machine_is_borzoi()) { |
228 | /* Need to use small eraseblock size for backward compatibility */ | 234 | /* Need to use small eraseblock size for backward compatibility */ |
229 | sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; | 235 | sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS; |
230 | } | 236 | } |
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index 34b80de34fae..bc537440ca02 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
@@ -353,8 +353,6 @@ struct cp_private { | |||
353 | 353 | ||
354 | struct net_device_stats net_stats; | 354 | struct net_device_stats net_stats; |
355 | struct cp_extra_stats cp_stats; | 355 | struct cp_extra_stats cp_stats; |
356 | struct cp_dma_stats *nic_stats; | ||
357 | dma_addr_t nic_stats_dma; | ||
358 | 356 | ||
359 | unsigned rx_tail ____cacheline_aligned; | 357 | unsigned rx_tail ____cacheline_aligned; |
360 | struct cp_desc *rx_ring; | 358 | struct cp_desc *rx_ring; |
@@ -1143,10 +1141,6 @@ static int cp_alloc_rings (struct cp_private *cp) | |||
1143 | cp->rx_ring = mem; | 1141 | cp->rx_ring = mem; |
1144 | cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; | 1142 | cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE]; |
1145 | 1143 | ||
1146 | mem += (CP_RING_BYTES - CP_STATS_SIZE); | ||
1147 | cp->nic_stats = mem; | ||
1148 | cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE); | ||
1149 | |||
1150 | return cp_init_rings(cp); | 1144 | return cp_init_rings(cp); |
1151 | } | 1145 | } |
1152 | 1146 | ||
@@ -1187,7 +1181,6 @@ static void cp_free_rings (struct cp_private *cp) | |||
1187 | pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); | 1181 | pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma); |
1188 | cp->rx_ring = NULL; | 1182 | cp->rx_ring = NULL; |
1189 | cp->tx_ring = NULL; | 1183 | cp->tx_ring = NULL; |
1190 | cp->nic_stats = NULL; | ||
1191 | } | 1184 | } |
1192 | 1185 | ||
1193 | static int cp_open (struct net_device *dev) | 1186 | static int cp_open (struct net_device *dev) |
@@ -1516,13 +1509,17 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1516 | struct ethtool_stats *estats, u64 *tmp_stats) | 1509 | struct ethtool_stats *estats, u64 *tmp_stats) |
1517 | { | 1510 | { |
1518 | struct cp_private *cp = netdev_priv(dev); | 1511 | struct cp_private *cp = netdev_priv(dev); |
1512 | struct cp_dma_stats *nic_stats; | ||
1513 | dma_addr_t dma; | ||
1519 | int i; | 1514 | int i; |
1520 | 1515 | ||
1521 | memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats)); | 1516 | nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma); |
1517 | if (!nic_stats) | ||
1518 | return; | ||
1522 | 1519 | ||
1523 | /* begin NIC statistics dump */ | 1520 | /* begin NIC statistics dump */ |
1524 | cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16); | 1521 | cpw32(StatsAddr + 4, (u64)dma >> 32); |
1525 | cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats); | 1522 | cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats); |
1526 | cpr32(StatsAddr); | 1523 | cpr32(StatsAddr); |
1527 | 1524 | ||
1528 | for (i = 0; i < 1000; i++) { | 1525 | for (i = 0; i < 1000; i++) { |
@@ -1532,24 +1529,27 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1532 | } | 1529 | } |
1533 | cpw32(StatsAddr, 0); | 1530 | cpw32(StatsAddr, 0); |
1534 | cpw32(StatsAddr + 4, 0); | 1531 | cpw32(StatsAddr + 4, 0); |
1532 | cpr32(StatsAddr); | ||
1535 | 1533 | ||
1536 | i = 0; | 1534 | i = 0; |
1537 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok); | 1535 | tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok); |
1538 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok); | 1536 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok); |
1539 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err); | 1537 | tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err); |
1540 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err); | 1538 | tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err); |
1541 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo); | 1539 | tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo); |
1542 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align); | 1540 | tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align); |
1543 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col); | 1541 | tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col); |
1544 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol); | 1542 | tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol); |
1545 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys); | 1543 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys); |
1546 | tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast); | 1544 | tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast); |
1547 | tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast); | 1545 | tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast); |
1548 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort); | 1546 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); |
1549 | tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun); | 1547 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); |
1550 | tmp_stats[i++] = cp->cp_stats.rx_frags; | 1548 | tmp_stats[i++] = cp->cp_stats.rx_frags; |
1551 | if (i != CP_NUM_STATS) | 1549 | if (i != CP_NUM_STATS) |
1552 | BUG(); | 1550 | BUG(); |
1551 | |||
1552 | pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); | ||
1553 | } | 1553 | } |
1554 | 1554 | ||
1555 | static struct ethtool_ops cp_ethtool_ops = { | 1555 | static struct ethtool_ops cp_ethtool_ops = { |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 54fff9c2e802..96f14ab1c1f5 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1951,7 +1951,7 @@ config SKGE | |||
1951 | ---help--- | 1951 | ---help--- |
1952 | This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx | 1952 | This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx |
1953 | and related Gigabit Ethernet adapters. It is a new smaller driver | 1953 | and related Gigabit Ethernet adapters. It is a new smaller driver |
1954 | driver with better performance and more complete ethtool support. | 1954 | with better performance and more complete ethtool support. |
1955 | 1955 | ||
1956 | It does not support the link failover and network management | 1956 | It does not support the link failover and network management |
1957 | features that "portable" vendor supplied sk98lin driver does. | 1957 | features that "portable" vendor supplied sk98lin driver does. |
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 52c77cbe8c62..1f0302735416 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c | |||
@@ -160,7 +160,7 @@ static int __init com90io_probe(struct net_device *dev) | |||
160 | return -ENODEV; | 160 | return -ENODEV; |
161 | } | 161 | } |
162 | if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) { | 162 | if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) { |
163 | BUGMSG(D_INIT_REASONS, "IO check_region %x-%x failed.\n", | 163 | BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n", |
164 | ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); | 164 | ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); |
165 | return -ENXIO; | 165 | return -ENXIO; |
166 | } | 166 | } |
@@ -242,7 +242,7 @@ static int __init com90io_found(struct net_device *dev) | |||
242 | BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); | 242 | BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq); |
243 | return -ENODEV; | 243 | return -ENODEV; |
244 | } | 244 | } |
245 | /* Reserve the I/O region - guaranteed to work by check_region */ | 245 | /* Reserve the I/O region */ |
246 | if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) { | 246 | if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) { |
247 | free_irq(dev->irq, dev); | 247 | free_irq(dev->irq, dev); |
248 | return -EBUSY; | 248 | return -EBUSY; |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 94c9f68dd16b..90449a0f2a6c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -2879,6 +2879,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2879 | * This target is not on a VLAN | 2879 | * This target is not on a VLAN |
2880 | */ | 2880 | */ |
2881 | if (rt->u.dst.dev == bond->dev) { | 2881 | if (rt->u.dst.dev == bond->dev) { |
2882 | ip_rt_put(rt); | ||
2882 | dprintk("basa: rtdev == bond->dev: arp_send\n"); | 2883 | dprintk("basa: rtdev == bond->dev: arp_send\n"); |
2883 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], | 2884 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], |
2884 | bond->master_ip, 0); | 2885 | bond->master_ip, 0); |
@@ -2898,6 +2899,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2898 | } | 2899 | } |
2899 | 2900 | ||
2900 | if (vlan_id) { | 2901 | if (vlan_id) { |
2902 | ip_rt_put(rt); | ||
2901 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], | 2903 | bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], |
2902 | vlan->vlan_ip, vlan_id); | 2904 | vlan->vlan_ip, vlan_id); |
2903 | continue; | 2905 | continue; |
@@ -2909,6 +2911,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave) | |||
2909 | bond->dev->name, NIPQUAD(fl.fl4_dst), | 2911 | bond->dev->name, NIPQUAD(fl.fl4_dst), |
2910 | rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); | 2912 | rt->u.dst.dev ? rt->u.dst.dev->name : "NULL"); |
2911 | } | 2913 | } |
2914 | ip_rt_put(rt); | ||
2912 | } | 2915 | } |
2913 | } | 2916 | } |
2914 | 2917 | ||
@@ -5036,6 +5039,14 @@ static int __init bonding_init(void) | |||
5036 | return 0; | 5039 | return 0; |
5037 | 5040 | ||
5038 | out_err: | 5041 | out_err: |
5042 | /* | ||
5043 | * rtnl_unlock() will run netdev_run_todo(), putting the | ||
5044 | * thus-far-registered bonding devices into a state which | ||
5045 | * unregigister_netdevice() will accept | ||
5046 | */ | ||
5047 | rtnl_unlock(); | ||
5048 | rtnl_lock(); | ||
5049 | |||
5039 | /* free and unregister all bonds that were successfully added */ | 5050 | /* free and unregister all bonds that were successfully added */ |
5040 | bond_free_all(); | 5051 | bond_free_all(); |
5041 | 5052 | ||
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 25cc20e415da..fbf1c06ec5c1 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -1387,13 +1387,13 @@ static void e100_update_stats(struct nic *nic) | |||
1387 | ns->collisions += nic->tx_collisions; | 1387 | ns->collisions += nic->tx_collisions; |
1388 | ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + | 1388 | ns->tx_errors += le32_to_cpu(s->tx_max_collisions) + |
1389 | le32_to_cpu(s->tx_lost_crs); | 1389 | le32_to_cpu(s->tx_lost_crs); |
1390 | ns->rx_dropped += le32_to_cpu(s->rx_resource_errors); | ||
1391 | ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + | 1390 | ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) + |
1392 | nic->rx_over_length_errors; | 1391 | nic->rx_over_length_errors; |
1393 | ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); | 1392 | ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors); |
1394 | ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); | 1393 | ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors); |
1395 | ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); | 1394 | ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors); |
1396 | ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); | 1395 | ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors); |
1396 | ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors); | ||
1397 | ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + | 1397 | ns->rx_errors += le32_to_cpu(s->rx_crc_errors) + |
1398 | le32_to_cpu(s->rx_alignment_errors) + | 1398 | le32_to_cpu(s->rx_alignment_errors) + |
1399 | le32_to_cpu(s->rx_short_frame_errors) + | 1399 | le32_to_cpu(s->rx_short_frame_errors) + |
@@ -1727,12 +1727,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx, | |||
1727 | 1727 | ||
1728 | if(unlikely(!(rfd_status & cb_ok))) { | 1728 | if(unlikely(!(rfd_status & cb_ok))) { |
1729 | /* Don't indicate if hardware indicates errors */ | 1729 | /* Don't indicate if hardware indicates errors */ |
1730 | nic->net_stats.rx_dropped++; | ||
1731 | dev_kfree_skb_any(skb); | 1730 | dev_kfree_skb_any(skb); |
1732 | } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { | 1731 | } else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) { |
1733 | /* Don't indicate oversized frames */ | 1732 | /* Don't indicate oversized frames */ |
1734 | nic->rx_over_length_errors++; | 1733 | nic->rx_over_length_errors++; |
1735 | nic->net_stats.rx_dropped++; | ||
1736 | dev_kfree_skb_any(skb); | 1734 | dev_kfree_skb_any(skb); |
1737 | } else { | 1735 | } else { |
1738 | nic->net_stats.rx_packets++; | 1736 | nic->net_stats.rx_packets++; |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7c8a0a22dcd5..ee687c902a20 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -2544,7 +2544,6 @@ e1000_update_stats(struct e1000_adapter *adapter) | |||
2544 | adapter->stats.crcerrs + adapter->stats.algnerrc + | 2544 | adapter->stats.crcerrs + adapter->stats.algnerrc + |
2545 | adapter->stats.rlec + adapter->stats.mpc + | 2545 | adapter->stats.rlec + adapter->stats.mpc + |
2546 | adapter->stats.cexterr; | 2546 | adapter->stats.cexterr; |
2547 | adapter->net_stats.rx_dropped = adapter->stats.mpc; | ||
2548 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; | 2547 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; |
2549 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; | 2548 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; |
2550 | adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; | 2549 | adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc; |
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 5c555373adbe..89d6d69be382 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c | |||
@@ -1616,8 +1616,6 @@ ixgb_update_stats(struct ixgb_adapter *adapter) | |||
1616 | adapter->stats.icbc + | 1616 | adapter->stats.icbc + |
1617 | adapter->stats.ecbc + adapter->stats.mpc; | 1617 | adapter->stats.ecbc + adapter->stats.mpc; |
1618 | 1618 | ||
1619 | adapter->net_stats.rx_dropped = adapter->stats.mpc; | ||
1620 | |||
1621 | /* see above | 1619 | /* see above |
1622 | * adapter->net_stats.rx_length_errors = adapter->stats.rlec; | 1620 | * adapter->net_stats.rx_length_errors = adapter->stats.rlec; |
1623 | */ | 1621 | */ |
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index c829e6a2e8a6..dd451e099a4c 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -428,7 +428,7 @@ static int init_shared_mem(struct s2io_nic *nic) | |||
428 | DBG_PRINT(INIT_DBG, | 428 | DBG_PRINT(INIT_DBG, |
429 | "%s: Zero DMA address for TxDL. ", dev->name); | 429 | "%s: Zero DMA address for TxDL. ", dev->name); |
430 | DBG_PRINT(INIT_DBG, | 430 | DBG_PRINT(INIT_DBG, |
431 | "Virtual address %llx\n", (u64)tmp_v); | 431 | "Virtual address %p\n", tmp_v); |
432 | tmp_v = pci_alloc_consistent(nic->pdev, | 432 | tmp_v = pci_alloc_consistent(nic->pdev, |
433 | PAGE_SIZE, &tmp_p); | 433 | PAGE_SIZE, &tmp_p); |
434 | if (!tmp_v) { | 434 | if (!tmp_v) { |
@@ -657,9 +657,10 @@ static void free_shared_mem(struct s2io_nic *nic) | |||
657 | mac_control->zerodma_virt_addr, | 657 | mac_control->zerodma_virt_addr, |
658 | (dma_addr_t)0); | 658 | (dma_addr_t)0); |
659 | DBG_PRINT(INIT_DBG, | 659 | DBG_PRINT(INIT_DBG, |
660 | "%s: Freeing TxDL with zero DMA addr. ", dev->name); | 660 | "%s: Freeing TxDL with zero DMA addr. ", |
661 | DBG_PRINT(INIT_DBG, "Virtual address %llx\n", | 661 | dev->name); |
662 | (u64)(mac_control->zerodma_virt_addr)); | 662 | DBG_PRINT(INIT_DBG, "Virtual address %p\n", |
663 | mac_control->zerodma_virt_addr); | ||
663 | } | 664 | } |
664 | kfree(mac_control->fifos[i].list_info); | 665 | kfree(mac_control->fifos[i].list_info); |
665 | } | 666 | } |
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index 6ee4771addf1..2e72d79a143c 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c | |||
@@ -5216,17 +5216,15 @@ static struct pci_device_id skge_pci_tbl[] = { | |||
5216 | { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5216 | { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5217 | { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5217 | { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5218 | { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5218 | { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5219 | { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5219 | /* DLink card does not have valid VPD so this driver gags |
5220 | * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
5221 | */ | ||
5220 | { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5222 | { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5221 | #if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */ | ||
5222 | { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
5223 | { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | ||
5224 | #endif | ||
5225 | { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5223 | { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5226 | { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5224 | { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5227 | { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5225 | { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, }, |
5228 | { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 5226 | { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
5229 | { 0, } | 5227 | { 0 } |
5230 | }; | 5228 | }; |
5231 | 5229 | ||
5232 | MODULE_DEVICE_TABLE(pci, skge_pci_tbl); | 5230 | MODULE_DEVICE_TABLE(pci, skge_pci_tbl); |
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index d7c98515fdfd..0208258e7826 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #include "skge.h" | 42 | #include "skge.h" |
43 | 43 | ||
44 | #define DRV_NAME "skge" | 44 | #define DRV_NAME "skge" |
45 | #define DRV_VERSION "0.9" | 45 | #define DRV_VERSION "1.0" |
46 | #define PFX DRV_NAME " " | 46 | #define PFX DRV_NAME " " |
47 | 47 | ||
48 | #define DEFAULT_TX_RING_SIZE 128 | 48 | #define DEFAULT_TX_RING_SIZE 128 |
@@ -669,7 +669,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) | |||
669 | PHY_M_LED_BLINK_RT(BLINK_84MS) | | 669 | PHY_M_LED_BLINK_RT(BLINK_84MS) | |
670 | PHY_M_LEDC_TX_CTRL | | 670 | PHY_M_LEDC_TX_CTRL | |
671 | PHY_M_LEDC_DP_CTRL); | 671 | PHY_M_LEDC_DP_CTRL); |
672 | 672 | ||
673 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, | 673 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, |
674 | PHY_M_LED_MO_RX(MO_LED_OFF) | | 674 | PHY_M_LED_MO_RX(MO_LED_OFF) | |
675 | (skge->speed == SPEED_100 ? | 675 | (skge->speed == SPEED_100 ? |
@@ -876,7 +876,7 @@ static int skge_rx_fill(struct skge_port *skge) | |||
876 | 876 | ||
877 | static void skge_link_up(struct skge_port *skge) | 877 | static void skge_link_up(struct skge_port *skge) |
878 | { | 878 | { |
879 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), | 879 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), |
880 | LED_BLK_OFF|LED_SYNC_OFF|LED_ON); | 880 | LED_BLK_OFF|LED_SYNC_OFF|LED_ON); |
881 | 881 | ||
882 | netif_carrier_on(skge->netdev); | 882 | netif_carrier_on(skge->netdev); |
@@ -987,6 +987,8 @@ static void genesis_reset(struct skge_hw *hw, int port) | |||
987 | { | 987 | { |
988 | const u8 zero[8] = { 0 }; | 988 | const u8 zero[8] = { 0 }; |
989 | 989 | ||
990 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); | ||
991 | |||
990 | /* reset the statistics module */ | 992 | /* reset the statistics module */ |
991 | xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); | 993 | xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); |
992 | xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ | 994 | xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */ |
@@ -1021,8 +1023,6 @@ static void bcom_check_link(struct skge_hw *hw, int port) | |||
1021 | (void) xm_phy_read(hw, port, PHY_BCOM_STAT); | 1023 | (void) xm_phy_read(hw, port, PHY_BCOM_STAT); |
1022 | status = xm_phy_read(hw, port, PHY_BCOM_STAT); | 1024 | status = xm_phy_read(hw, port, PHY_BCOM_STAT); |
1023 | 1025 | ||
1024 | pr_debug("bcom_check_link status=0x%x\n", status); | ||
1025 | |||
1026 | if ((status & PHY_ST_LSYNC) == 0) { | 1026 | if ((status & PHY_ST_LSYNC) == 0) { |
1027 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); | 1027 | u16 cmd = xm_read16(hw, port, XM_MMU_CMD); |
1028 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); | 1028 | cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); |
@@ -1106,8 +1106,6 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo) | |||
1106 | { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, | 1106 | { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, |
1107 | }; | 1107 | }; |
1108 | 1108 | ||
1109 | pr_debug("bcom_phy_init\n"); | ||
1110 | |||
1111 | /* read Id from external PHY (all have the same address) */ | 1109 | /* read Id from external PHY (all have the same address) */ |
1112 | id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); | 1110 | id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); |
1113 | 1111 | ||
@@ -1340,6 +1338,8 @@ static void genesis_stop(struct skge_port *skge) | |||
1340 | int port = skge->port; | 1338 | int port = skge->port; |
1341 | u32 reg; | 1339 | u32 reg; |
1342 | 1340 | ||
1341 | genesis_reset(hw, port); | ||
1342 | |||
1343 | /* Clear Tx packet arbiter timeout IRQ */ | 1343 | /* Clear Tx packet arbiter timeout IRQ */ |
1344 | skge_write16(hw, B3_PA_CTRL, | 1344 | skge_write16(hw, B3_PA_CTRL, |
1345 | port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); | 1345 | port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); |
@@ -1465,7 +1465,6 @@ static void genesis_link_up(struct skge_port *skge) | |||
1465 | u16 cmd; | 1465 | u16 cmd; |
1466 | u32 mode, msk; | 1466 | u32 mode, msk; |
1467 | 1467 | ||
1468 | pr_debug("genesis_link_up\n"); | ||
1469 | cmd = xm_read16(hw, port, XM_MMU_CMD); | 1468 | cmd = xm_read16(hw, port, XM_MMU_CMD); |
1470 | 1469 | ||
1471 | /* | 1470 | /* |
@@ -1578,7 +1577,6 @@ static void yukon_init(struct skge_hw *hw, int port) | |||
1578 | struct skge_port *skge = netdev_priv(hw->dev[port]); | 1577 | struct skge_port *skge = netdev_priv(hw->dev[port]); |
1579 | u16 ctrl, ct1000, adv; | 1578 | u16 ctrl, ct1000, adv; |
1580 | 1579 | ||
1581 | pr_debug("yukon_init\n"); | ||
1582 | if (skge->autoneg == AUTONEG_ENABLE) { | 1580 | if (skge->autoneg == AUTONEG_ENABLE) { |
1583 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); | 1581 | u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); |
1584 | 1582 | ||
@@ -1677,9 +1675,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
1677 | 1675 | ||
1678 | /* WA code for COMA mode -- set PHY reset */ | 1676 | /* WA code for COMA mode -- set PHY reset */ |
1679 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1677 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
1680 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) | 1678 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { |
1681 | skge_write32(hw, B2_GP_IO, | 1679 | reg = skge_read32(hw, B2_GP_IO); |
1682 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9)); | 1680 | reg |= GP_DIR_9 | GP_IO_9; |
1681 | skge_write32(hw, B2_GP_IO, reg); | ||
1682 | } | ||
1683 | 1683 | ||
1684 | /* hard reset */ | 1684 | /* hard reset */ |
1685 | skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); | 1685 | skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); |
@@ -1687,10 +1687,12 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
1687 | 1687 | ||
1688 | /* WA code for COMA mode -- clear PHY reset */ | 1688 | /* WA code for COMA mode -- clear PHY reset */ |
1689 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1689 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
1690 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) | 1690 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { |
1691 | skge_write32(hw, B2_GP_IO, | 1691 | reg = skge_read32(hw, B2_GP_IO); |
1692 | (skge_read32(hw, B2_GP_IO) | GP_DIR_9) | 1692 | reg |= GP_DIR_9; |
1693 | & ~GP_IO_9); | 1693 | reg &= ~GP_IO_9; |
1694 | skge_write32(hw, B2_GP_IO, reg); | ||
1695 | } | ||
1694 | 1696 | ||
1695 | /* Set hardware config mode */ | 1697 | /* Set hardware config mode */ |
1696 | reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | | 1698 | reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | |
@@ -1729,7 +1731,7 @@ static void yukon_mac_init(struct skge_hw *hw, int port) | |||
1729 | } | 1731 | } |
1730 | 1732 | ||
1731 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1733 | gma_write16(hw, port, GM_GP_CTRL, reg); |
1732 | skge_read16(hw, GMAC_IRQ_SRC); | 1734 | skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); |
1733 | 1735 | ||
1734 | yukon_init(hw, port); | 1736 | yukon_init(hw, port); |
1735 | 1737 | ||
@@ -1801,20 +1803,26 @@ static void yukon_stop(struct skge_port *skge) | |||
1801 | struct skge_hw *hw = skge->hw; | 1803 | struct skge_hw *hw = skge->hw; |
1802 | int port = skge->port; | 1804 | int port = skge->port; |
1803 | 1805 | ||
1804 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | 1806 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); |
1805 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { | 1807 | yukon_reset(hw, port); |
1806 | skge_write32(hw, B2_GP_IO, | ||
1807 | skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9); | ||
1808 | } | ||
1809 | 1808 | ||
1810 | gma_write16(hw, port, GM_GP_CTRL, | 1809 | gma_write16(hw, port, GM_GP_CTRL, |
1811 | gma_read16(hw, port, GM_GP_CTRL) | 1810 | gma_read16(hw, port, GM_GP_CTRL) |
1812 | & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); | 1811 | & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); |
1813 | gma_read16(hw, port, GM_GP_CTRL); | 1812 | gma_read16(hw, port, GM_GP_CTRL); |
1814 | 1813 | ||
1814 | if (hw->chip_id == CHIP_ID_YUKON_LITE && | ||
1815 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { | ||
1816 | u32 io = skge_read32(hw, B2_GP_IO); | ||
1817 | |||
1818 | io |= GP_DIR_9 | GP_IO_9; | ||
1819 | skge_write32(hw, B2_GP_IO, io); | ||
1820 | skge_read32(hw, B2_GP_IO); | ||
1821 | } | ||
1822 | |||
1815 | /* set GPHY Control reset */ | 1823 | /* set GPHY Control reset */ |
1816 | skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); | 1824 | skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); |
1817 | skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); | 1825 | skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); |
1818 | } | 1826 | } |
1819 | 1827 | ||
1820 | static void yukon_get_stats(struct skge_port *skge, u64 *data) | 1828 | static void yukon_get_stats(struct skge_port *skge, u64 *data) |
@@ -1873,10 +1881,8 @@ static void yukon_link_up(struct skge_port *skge) | |||
1873 | int port = skge->port; | 1881 | int port = skge->port; |
1874 | u16 reg; | 1882 | u16 reg; |
1875 | 1883 | ||
1876 | pr_debug("yukon_link_up\n"); | ||
1877 | |||
1878 | /* Enable Transmit FIFO Underrun */ | 1884 | /* Enable Transmit FIFO Underrun */ |
1879 | skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK); | 1885 | skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); |
1880 | 1886 | ||
1881 | reg = gma_read16(hw, port, GM_GP_CTRL); | 1887 | reg = gma_read16(hw, port, GM_GP_CTRL); |
1882 | if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) | 1888 | if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) |
@@ -1896,7 +1902,6 @@ static void yukon_link_down(struct skge_port *skge) | |||
1896 | int port = skge->port; | 1902 | int port = skge->port; |
1897 | u16 ctrl; | 1903 | u16 ctrl; |
1898 | 1904 | ||
1899 | pr_debug("yukon_link_down\n"); | ||
1900 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); | 1905 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); |
1901 | 1906 | ||
1902 | ctrl = gma_read16(hw, port, GM_GP_CTRL); | 1907 | ctrl = gma_read16(hw, port, GM_GP_CTRL); |
@@ -2112,7 +2117,6 @@ static int skge_up(struct net_device *dev) | |||
2112 | skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); | 2117 | skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); |
2113 | skge_led(skge, LED_MODE_ON); | 2118 | skge_led(skge, LED_MODE_ON); |
2114 | 2119 | ||
2115 | pr_debug("skge_up completed\n"); | ||
2116 | return 0; | 2120 | return 0; |
2117 | 2121 | ||
2118 | free_rx_ring: | 2122 | free_rx_ring: |
@@ -2135,15 +2139,20 @@ static int skge_down(struct net_device *dev) | |||
2135 | 2139 | ||
2136 | netif_stop_queue(dev); | 2140 | netif_stop_queue(dev); |
2137 | 2141 | ||
2142 | skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); | ||
2143 | if (hw->chip_id == CHIP_ID_GENESIS) | ||
2144 | genesis_stop(skge); | ||
2145 | else | ||
2146 | yukon_stop(skge); | ||
2147 | |||
2148 | hw->intr_mask &= ~portirqmask[skge->port]; | ||
2149 | skge_write32(hw, B0_IMSK, hw->intr_mask); | ||
2150 | |||
2138 | /* Stop transmitter */ | 2151 | /* Stop transmitter */ |
2139 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); | 2152 | skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); |
2140 | skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), | 2153 | skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), |
2141 | RB_RST_SET|RB_DIS_OP_MD); | 2154 | RB_RST_SET|RB_DIS_OP_MD); |
2142 | 2155 | ||
2143 | if (hw->chip_id == CHIP_ID_GENESIS) | ||
2144 | genesis_stop(skge); | ||
2145 | else | ||
2146 | yukon_stop(skge); | ||
2147 | 2156 | ||
2148 | /* Disable Force Sync bit and Enable Alloc bit */ | 2157 | /* Disable Force Sync bit and Enable Alloc bit */ |
2149 | skge_write8(hw, SK_REG(port, TXA_CTRL), | 2158 | skge_write8(hw, SK_REG(port, TXA_CTRL), |
@@ -2367,8 +2376,6 @@ static void genesis_set_multicast(struct net_device *dev) | |||
2367 | u32 mode; | 2376 | u32 mode; |
2368 | u8 filter[8]; | 2377 | u8 filter[8]; |
2369 | 2378 | ||
2370 | pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count); | ||
2371 | |||
2372 | mode = xm_read32(hw, port, XM_MODE); | 2379 | mode = xm_read32(hw, port, XM_MODE); |
2373 | mode |= XM_MD_ENA_HASH; | 2380 | mode |= XM_MD_ENA_HASH; |
2374 | if (dev->flags & IFF_PROMISC) | 2381 | if (dev->flags & IFF_PROMISC) |
@@ -2530,8 +2537,6 @@ static int skge_poll(struct net_device *dev, int *budget) | |||
2530 | unsigned int to_do = min(dev->quota, *budget); | 2537 | unsigned int to_do = min(dev->quota, *budget); |
2531 | unsigned int work_done = 0; | 2538 | unsigned int work_done = 0; |
2532 | 2539 | ||
2533 | pr_debug("skge_poll\n"); | ||
2534 | |||
2535 | for (e = ring->to_clean; work_done < to_do; e = e->next) { | 2540 | for (e = ring->to_clean; work_done < to_do; e = e->next) { |
2536 | struct skge_rx_desc *rd = e->desc; | 2541 | struct skge_rx_desc *rd = e->desc; |
2537 | struct sk_buff *skb; | 2542 | struct sk_buff *skb; |
@@ -2672,9 +2677,9 @@ static void skge_error_irq(struct skge_hw *hw) | |||
2672 | if (hw->chip_id == CHIP_ID_GENESIS) { | 2677 | if (hw->chip_id == CHIP_ID_GENESIS) { |
2673 | /* clear xmac errors */ | 2678 | /* clear xmac errors */ |
2674 | if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) | 2679 | if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) |
2675 | skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT); | 2680 | skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT); |
2676 | if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) | 2681 | if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) |
2677 | skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT); | 2682 | skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT); |
2678 | } else { | 2683 | } else { |
2679 | /* Timestamp (unused) overflow */ | 2684 | /* Timestamp (unused) overflow */ |
2680 | if (hwstatus & IS_IRQ_TIST_OV) | 2685 | if (hwstatus & IS_IRQ_TIST_OV) |
@@ -3000,9 +3005,6 @@ static int skge_reset(struct skge_hw *hw) | |||
3000 | 3005 | ||
3001 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 3006 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
3002 | 3007 | ||
3003 | if (hw->chip_id != CHIP_ID_GENESIS) | ||
3004 | skge_write8(hw, GMAC_IRQ_MSK, 0); | ||
3005 | |||
3006 | spin_lock_bh(&hw->phy_lock); | 3008 | spin_lock_bh(&hw->phy_lock); |
3007 | for (i = 0; i < hw->ports; i++) { | 3009 | for (i = 0; i < hw->ports; i++) { |
3008 | if (hw->chip_id == CHIP_ID_GENESIS) | 3010 | if (hw->chip_id == CHIP_ID_GENESIS) |
@@ -3230,6 +3232,11 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
3230 | dev0 = hw->dev[0]; | 3232 | dev0 = hw->dev[0]; |
3231 | unregister_netdev(dev0); | 3233 | unregister_netdev(dev0); |
3232 | 3234 | ||
3235 | skge_write32(hw, B0_IMSK, 0); | ||
3236 | skge_write16(hw, B0_LED, LED_STAT_OFF); | ||
3237 | skge_pci_clear(hw); | ||
3238 | skge_write8(hw, B0_CTST, CS_RST_SET); | ||
3239 | |||
3233 | tasklet_kill(&hw->ext_tasklet); | 3240 | tasklet_kill(&hw->ext_tasklet); |
3234 | 3241 | ||
3235 | free_irq(pdev->irq, hw); | 3242 | free_irq(pdev->irq, hw); |
@@ -3238,7 +3245,7 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
3238 | if (dev1) | 3245 | if (dev1) |
3239 | free_netdev(dev1); | 3246 | free_netdev(dev1); |
3240 | free_netdev(dev0); | 3247 | free_netdev(dev0); |
3241 | skge_write16(hw, B0_LED, LED_STAT_OFF); | 3248 | |
3242 | iounmap(hw->regs); | 3249 | iounmap(hw->regs); |
3243 | kfree(hw); | 3250 | kfree(hw); |
3244 | pci_set_drvdata(pdev, NULL); | 3251 | pci_set_drvdata(pdev, NULL); |
@@ -3257,7 +3264,10 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3257 | struct skge_port *skge = netdev_priv(dev); | 3264 | struct skge_port *skge = netdev_priv(dev); |
3258 | if (netif_running(dev)) { | 3265 | if (netif_running(dev)) { |
3259 | netif_carrier_off(dev); | 3266 | netif_carrier_off(dev); |
3260 | skge_down(dev); | 3267 | if (skge->wol) |
3268 | netif_stop_queue(dev); | ||
3269 | else | ||
3270 | skge_down(dev); | ||
3261 | } | 3271 | } |
3262 | netif_device_detach(dev); | 3272 | netif_device_detach(dev); |
3263 | wol |= skge->wol; | 3273 | wol |= skge->wol; |
diff --git a/drivers/net/skge.h b/drivers/net/skge.h index f1680beb8e68..efbf98c675d2 100644 --- a/drivers/net/skge.h +++ b/drivers/net/skge.h | |||
@@ -2008,7 +2008,7 @@ enum { | |||
2008 | GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ | 2008 | GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ |
2009 | GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ | 2009 | GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ |
2010 | 2010 | ||
2011 | #define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR) | 2011 | #define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR) |
2012 | 2012 | ||
2013 | /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ | 2013 | /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ |
2014 | /* Bits 15.. 2: reserved */ | 2014 | /* Bits 15.. 2: reserved */ |
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 4e19220473d0..c796f41b4a52 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
@@ -1817,6 +1817,10 @@ spider_net_setup_phy(struct spider_net_card *card) | |||
1817 | /* LEDs active in both modes, autosense prio = fiber */ | 1817 | /* LEDs active in both modes, autosense prio = fiber */ |
1818 | spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); | 1818 | spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f); |
1819 | 1819 | ||
1820 | /* switch off fibre autoneg */ | ||
1821 | spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01); | ||
1822 | spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004); | ||
1823 | |||
1820 | phy->def->ops->read_link(phy); | 1824 | phy->def->ops->read_link(phy); |
1821 | pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, | 1825 | pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name, |
1822 | phy->speed, phy->duplex==1 ? "Full" : "Half"); | 1826 | phy->speed, phy->duplex==1 ? "Full" : "Half"); |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7599f52e15b3..81f4aedf534c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -67,8 +67,8 @@ | |||
67 | 67 | ||
68 | #define DRV_MODULE_NAME "tg3" | 68 | #define DRV_MODULE_NAME "tg3" |
69 | #define PFX DRV_MODULE_NAME ": " | 69 | #define PFX DRV_MODULE_NAME ": " |
70 | #define DRV_MODULE_VERSION "3.39" | 70 | #define DRV_MODULE_VERSION "3.40" |
71 | #define DRV_MODULE_RELDATE "September 5, 2005" | 71 | #define DRV_MODULE_RELDATE "September 15, 2005" |
72 | 72 | ||
73 | #define TG3_DEF_MAC_MODE 0 | 73 | #define TG3_DEF_MAC_MODE 0 |
74 | #define TG3_DEF_RX_MODE 0 | 74 | #define TG3_DEF_RX_MODE 0 |
@@ -3442,31 +3442,47 @@ static void tg3_tx_timeout(struct net_device *dev) | |||
3442 | schedule_work(&tp->reset_task); | 3442 | schedule_work(&tp->reset_task); |
3443 | } | 3443 | } |
3444 | 3444 | ||
3445 | /* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */ | ||
3446 | static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) | ||
3447 | { | ||
3448 | u32 base = (u32) mapping & 0xffffffff; | ||
3449 | |||
3450 | return ((base > 0xffffdcc0) && | ||
3451 | (base + len + 8 < base)); | ||
3452 | } | ||
3453 | |||
3445 | static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); | 3454 | static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32); |
3446 | 3455 | ||
3447 | static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, | 3456 | static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, |
3448 | u32 guilty_entry, int guilty_len, | 3457 | u32 last_plus_one, u32 *start, |
3449 | u32 last_plus_one, u32 *start, u32 mss) | 3458 | u32 base_flags, u32 mss) |
3450 | { | 3459 | { |
3451 | struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); | 3460 | struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC); |
3452 | dma_addr_t new_addr; | 3461 | dma_addr_t new_addr = 0; |
3453 | u32 entry = *start; | 3462 | u32 entry = *start; |
3454 | int i; | 3463 | int i, ret = 0; |
3455 | 3464 | ||
3456 | if (!new_skb) { | 3465 | if (!new_skb) { |
3457 | dev_kfree_skb(skb); | 3466 | ret = -1; |
3458 | return -1; | 3467 | } else { |
3468 | /* New SKB is guaranteed to be linear. */ | ||
3469 | entry = *start; | ||
3470 | new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, | ||
3471 | PCI_DMA_TODEVICE); | ||
3472 | /* Make sure new skb does not cross any 4G boundaries. | ||
3473 | * Drop the packet if it does. | ||
3474 | */ | ||
3475 | if (tg3_4g_overflow_test(new_addr, new_skb->len)) { | ||
3476 | ret = -1; | ||
3477 | dev_kfree_skb(new_skb); | ||
3478 | new_skb = NULL; | ||
3479 | } else { | ||
3480 | tg3_set_txd(tp, entry, new_addr, new_skb->len, | ||
3481 | base_flags, 1 | (mss << 1)); | ||
3482 | *start = NEXT_TX(entry); | ||
3483 | } | ||
3459 | } | 3484 | } |
3460 | 3485 | ||
3461 | /* New SKB is guaranteed to be linear. */ | ||
3462 | entry = *start; | ||
3463 | new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len, | ||
3464 | PCI_DMA_TODEVICE); | ||
3465 | tg3_set_txd(tp, entry, new_addr, new_skb->len, | ||
3466 | (skb->ip_summed == CHECKSUM_HW) ? | ||
3467 | TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1)); | ||
3468 | *start = NEXT_TX(entry); | ||
3469 | |||
3470 | /* Now clean up the sw ring entries. */ | 3486 | /* Now clean up the sw ring entries. */ |
3471 | i = 0; | 3487 | i = 0; |
3472 | while (entry != last_plus_one) { | 3488 | while (entry != last_plus_one) { |
@@ -3491,7 +3507,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb, | |||
3491 | 3507 | ||
3492 | dev_kfree_skb(skb); | 3508 | dev_kfree_skb(skb); |
3493 | 3509 | ||
3494 | return 0; | 3510 | return ret; |
3495 | } | 3511 | } |
3496 | 3512 | ||
3497 | static void tg3_set_txd(struct tg3 *tp, int entry, | 3513 | static void tg3_set_txd(struct tg3 *tp, int entry, |
@@ -3517,19 +3533,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry, | |||
3517 | txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; | 3533 | txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT; |
3518 | } | 3534 | } |
3519 | 3535 | ||
3520 | static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len) | ||
3521 | { | ||
3522 | u32 base = (u32) mapping & 0xffffffff; | ||
3523 | |||
3524 | return ((base > 0xffffdcc0) && | ||
3525 | (base + len + 8 < base)); | ||
3526 | } | ||
3527 | |||
3528 | static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | 3536 | static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) |
3529 | { | 3537 | { |
3530 | struct tg3 *tp = netdev_priv(dev); | 3538 | struct tg3 *tp = netdev_priv(dev); |
3531 | dma_addr_t mapping; | 3539 | dma_addr_t mapping; |
3532 | unsigned int i; | ||
3533 | u32 len, entry, base_flags, mss; | 3540 | u32 len, entry, base_flags, mss; |
3534 | int would_hit_hwbug; | 3541 | int would_hit_hwbug; |
3535 | 3542 | ||
@@ -3624,7 +3631,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3624 | would_hit_hwbug = 0; | 3631 | would_hit_hwbug = 0; |
3625 | 3632 | ||
3626 | if (tg3_4g_overflow_test(mapping, len)) | 3633 | if (tg3_4g_overflow_test(mapping, len)) |
3627 | would_hit_hwbug = entry + 1; | 3634 | would_hit_hwbug = 1; |
3628 | 3635 | ||
3629 | tg3_set_txd(tp, entry, mapping, len, base_flags, | 3636 | tg3_set_txd(tp, entry, mapping, len, base_flags, |
3630 | (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); | 3637 | (skb_shinfo(skb)->nr_frags == 0) | (mss << 1)); |
@@ -3648,12 +3655,8 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3648 | tp->tx_buffers[entry].skb = NULL; | 3655 | tp->tx_buffers[entry].skb = NULL; |
3649 | pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); | 3656 | pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping); |
3650 | 3657 | ||
3651 | if (tg3_4g_overflow_test(mapping, len)) { | 3658 | if (tg3_4g_overflow_test(mapping, len)) |
3652 | /* Only one should match. */ | 3659 | would_hit_hwbug = 1; |
3653 | if (would_hit_hwbug) | ||
3654 | BUG(); | ||
3655 | would_hit_hwbug = entry + 1; | ||
3656 | } | ||
3657 | 3660 | ||
3658 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) | 3661 | if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) |
3659 | tg3_set_txd(tp, entry, mapping, len, | 3662 | tg3_set_txd(tp, entry, mapping, len, |
@@ -3669,34 +3672,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3669 | if (would_hit_hwbug) { | 3672 | if (would_hit_hwbug) { |
3670 | u32 last_plus_one = entry; | 3673 | u32 last_plus_one = entry; |
3671 | u32 start; | 3674 | u32 start; |
3672 | unsigned int len = 0; | ||
3673 | |||
3674 | would_hit_hwbug -= 1; | ||
3675 | entry = entry - 1 - skb_shinfo(skb)->nr_frags; | ||
3676 | entry &= (TG3_TX_RING_SIZE - 1); | ||
3677 | start = entry; | ||
3678 | i = 0; | ||
3679 | while (entry != last_plus_one) { | ||
3680 | if (i == 0) | ||
3681 | len = skb_headlen(skb); | ||
3682 | else | ||
3683 | len = skb_shinfo(skb)->frags[i-1].size; | ||
3684 | 3675 | ||
3685 | if (entry == would_hit_hwbug) | 3676 | start = entry - 1 - skb_shinfo(skb)->nr_frags; |
3686 | break; | 3677 | start &= (TG3_TX_RING_SIZE - 1); |
3687 | |||
3688 | i++; | ||
3689 | entry = NEXT_TX(entry); | ||
3690 | |||
3691 | } | ||
3692 | 3678 | ||
3693 | /* If the workaround fails due to memory/mapping | 3679 | /* If the workaround fails due to memory/mapping |
3694 | * failure, silently drop this packet. | 3680 | * failure, silently drop this packet. |
3695 | */ | 3681 | */ |
3696 | if (tigon3_4gb_hwbug_workaround(tp, skb, | 3682 | if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one, |
3697 | entry, len, | 3683 | &start, base_flags, mss)) |
3698 | last_plus_one, | ||
3699 | &start, mss)) | ||
3700 | goto out_unlock; | 3684 | goto out_unlock; |
3701 | 3685 | ||
3702 | entry = start; | 3686 | entry = start; |
@@ -9271,6 +9255,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9271 | static struct pci_device_id write_reorder_chipsets[] = { | 9255 | static struct pci_device_id write_reorder_chipsets[] = { |
9272 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, | 9256 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, |
9273 | PCI_DEVICE_ID_AMD_FE_GATE_700C) }, | 9257 | PCI_DEVICE_ID_AMD_FE_GATE_700C) }, |
9258 | { PCI_DEVICE(PCI_VENDOR_ID_AMD, | ||
9259 | PCI_DEVICE_ID_AMD_K8_NB) }, | ||
9274 | { }, | 9260 | { }, |
9275 | }; | 9261 | }; |
9276 | u32 misc_ctrl_reg; | 9262 | u32 misc_ctrl_reg; |
@@ -9285,7 +9271,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9285 | tp->tg3_flags2 |= TG3_FLG2_SUN_570X; | 9271 | tp->tg3_flags2 |= TG3_FLG2_SUN_570X; |
9286 | #endif | 9272 | #endif |
9287 | 9273 | ||
9288 | /* If we have an AMD 762 chipset, write | 9274 | /* If we have an AMD 762 or K8 chipset, write |
9289 | * reordering to the mailbox registers done by the host | 9275 | * reordering to the mailbox registers done by the host |
9290 | * controller can cause major troubles. We read back from | 9276 | * controller can cause major troubles. We read back from |
9291 | * every mailbox register write to force the writes to be | 9277 | * every mailbox register write to force the writes to be |
@@ -9532,7 +9518,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
9532 | tp->write32_rx_mbox = tg3_write_indirect_mbox; | 9518 | tp->write32_rx_mbox = tg3_write_indirect_mbox; |
9533 | 9519 | ||
9534 | iounmap(tp->regs); | 9520 | iounmap(tp->regs); |
9535 | tp->regs = 0; | 9521 | tp->regs = NULL; |
9536 | 9522 | ||
9537 | pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); | 9523 | pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd); |
9538 | pci_cmd &= ~PCI_COMMAND_MEMORY; | 9524 | pci_cmd &= ~PCI_COMMAND_MEMORY; |
@@ -10680,7 +10666,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
10680 | err_out_iounmap: | 10666 | err_out_iounmap: |
10681 | if (tp->regs) { | 10667 | if (tp->regs) { |
10682 | iounmap(tp->regs); | 10668 | iounmap(tp->regs); |
10683 | tp->regs = 0; | 10669 | tp->regs = NULL; |
10684 | } | 10670 | } |
10685 | 10671 | ||
10686 | err_out_free_dev: | 10672 | err_out_free_dev: |
@@ -10705,7 +10691,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
10705 | unregister_netdev(dev); | 10691 | unregister_netdev(dev); |
10706 | if (tp->regs) { | 10692 | if (tp->regs) { |
10707 | iounmap(tp->regs); | 10693 | iounmap(tp->regs); |
10708 | tp->regs = 0; | 10694 | tp->regs = NULL; |
10709 | } | 10695 | } |
10710 | free_netdev(dev); | 10696 | free_netdev(dev); |
10711 | pci_release_regions(pdev); | 10697 | pci_release_regions(pdev); |
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 26cc4f6378c7..60d1e05ab732 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c | |||
@@ -117,7 +117,7 @@ static int xircom_open(struct net_device *dev); | |||
117 | static int xircom_close(struct net_device *dev); | 117 | static int xircom_close(struct net_device *dev); |
118 | static void xircom_up(struct xircom_private *card); | 118 | static void xircom_up(struct xircom_private *card); |
119 | static struct net_device_stats *xircom_get_stats(struct net_device *dev); | 119 | static struct net_device_stats *xircom_get_stats(struct net_device *dev); |
120 | #if CONFIG_NET_POLL_CONTROLLER | 120 | #ifdef CONFIG_NET_POLL_CONTROLLER |
121 | static void xircom_poll_controller(struct net_device *dev); | 121 | static void xircom_poll_controller(struct net_device *dev); |
122 | #endif | 122 | #endif |
123 | 123 | ||
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 48c03c11cd9a..a01efa6d5c62 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c | |||
@@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type, | |||
72 | } | 72 | } |
73 | skb_reserve(skb, 4); | 73 | skb_reserve(skb, 4); |
74 | cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); | 74 | cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0); |
75 | data = (cisco_packet*)skb->data; | 75 | data = (cisco_packet*)(skb->data + 4); |
76 | 76 | ||
77 | data->type = htonl(type); | 77 | data->type = htonl(type); |
78 | data->par1 = htonl(par1); | 78 | data->par1 = htonl(par1); |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 2be65d308fbe..06998c2240d9 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -6852,7 +6852,10 @@ static inline char *airo_translate_scan(struct net_device *dev, | |||
6852 | /* Add frequency */ | 6852 | /* Add frequency */ |
6853 | iwe.cmd = SIOCGIWFREQ; | 6853 | iwe.cmd = SIOCGIWFREQ; |
6854 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); | 6854 | iwe.u.freq.m = le16_to_cpu(bss->dsChannel); |
6855 | iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000; | 6855 | /* iwe.u.freq.m containt the channel (starting 1), our |
6856 | * frequency_list array start at index 0... | ||
6857 | */ | ||
6858 | iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000; | ||
6856 | iwe.u.freq.e = 1; | 6859 | iwe.u.freq.e = 1; |
6857 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); | 6860 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN); |
6858 | 6861 | ||
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index d1fb1bab8aa8..bedd7f9f23e4 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -629,6 +629,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { | |||
629 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), | 629 | PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), |
630 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), | 630 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), |
631 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), | 631 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), |
632 | PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), | ||
632 | PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), | 633 | PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), |
633 | PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), | 634 | PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), |
634 | PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), | 635 | PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), |
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index 8122fe734aa7..b1ba429e0a2d 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c | |||
@@ -558,7 +558,7 @@ static int configure_device (struct pci_func *func) | |||
558 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); | 558 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE); |
559 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); | 559 | pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY); |
560 | 560 | ||
561 | pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); | 561 | pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L); |
562 | pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); | 562 | pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE); |
563 | 563 | ||
564 | return 0; | 564 | return 0; |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 0e0947601526..898f6da6f0de 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -2526,7 +2526,6 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, | |||
2526 | int cloop; | 2526 | int cloop; |
2527 | u8 temp_byte; | 2527 | u8 temp_byte; |
2528 | u8 class_code; | 2528 | u8 class_code; |
2529 | u16 temp_word; | ||
2530 | u32 rc; | 2529 | u32 rc; |
2531 | u32 temp_register; | 2530 | u32 temp_register; |
2532 | u32 base; | 2531 | u32 base; |
@@ -2682,8 +2681,7 @@ configure_new_function(struct controller *ctrl, struct pci_func *func, | |||
2682 | } /* End of base register loop */ | 2681 | } /* End of base register loop */ |
2683 | 2682 | ||
2684 | /* disable ROM base Address */ | 2683 | /* disable ROM base Address */ |
2685 | temp_word = 0x00L; | 2684 | rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); |
2686 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); | ||
2687 | 2685 | ||
2688 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | 2686 | /* Set HP parameters (Cache Line Size, Latency Timer) */ |
2689 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); | 2687 | rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); |
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 783b5abb0717..91c9903e621f 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -2824,8 +2824,7 @@ static int configure_new_function (struct controller * ctrl, struct pci_func * f | |||
2824 | } | 2824 | } |
2825 | #endif | 2825 | #endif |
2826 | /* Disable ROM base Address */ | 2826 | /* Disable ROM base Address */ |
2827 | temp_word = 0x00L; | 2827 | rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00); |
2828 | rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word); | ||
2829 | 2828 | ||
2830 | /* Set HP parameters (Cache Line Size, Latency Timer) */ | 2829 | /* Set HP parameters (Cache Line Size, Latency Timer) */ |
2831 | rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); | 2830 | rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 992db89adce7..259d247b7551 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -309,17 +309,25 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
309 | 309 | ||
310 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); | 310 | pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr); |
311 | 311 | ||
312 | /* If we're in D3, force entire word to 0. | 312 | /* If we're (effectively) in D3, force entire word to 0. |
313 | * This doesn't affect PME_Status, disables PME_En, and | 313 | * This doesn't affect PME_Status, disables PME_En, and |
314 | * sets PowerState to 0. | 314 | * sets PowerState to 0. |
315 | */ | 315 | */ |
316 | if (dev->current_state >= PCI_D3hot) { | 316 | switch (dev->current_state) { |
317 | if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) | 317 | case PCI_UNKNOWN: /* Boot-up */ |
318 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot | ||
319 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) | ||
318 | need_restore = 1; | 320 | need_restore = 1; |
321 | /* Fall-through: force to D0 */ | ||
322 | case PCI_D3hot: | ||
323 | case PCI_D3cold: | ||
324 | case PCI_POWER_ERROR: | ||
319 | pmcsr = 0; | 325 | pmcsr = 0; |
320 | } else { | 326 | break; |
327 | default: | ||
321 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | 328 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; |
322 | pmcsr |= state; | 329 | pmcsr |= state; |
330 | break; | ||
323 | } | 331 | } |
324 | 332 | ||
325 | /* enter specified state */ | 333 | /* enter specified state */ |
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 39ba6406fd54..80969f7e7a0b 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
@@ -376,6 +376,7 @@ static int ds_open(struct inode *inode, struct file *file) | |||
376 | socket_t i = iminor(inode); | 376 | socket_t i = iminor(inode); |
377 | struct pcmcia_socket *s; | 377 | struct pcmcia_socket *s; |
378 | user_info_t *user; | 378 | user_info_t *user; |
379 | static int warning_printed = 0; | ||
379 | 380 | ||
380 | ds_dbg(0, "ds_open(socket %d)\n", i); | 381 | ds_dbg(0, "ds_open(socket %d)\n", i); |
381 | 382 | ||
@@ -407,6 +408,17 @@ static int ds_open(struct inode *inode, struct file *file) | |||
407 | s->user = user; | 408 | s->user = user; |
408 | file->private_data = user; | 409 | file->private_data = user; |
409 | 410 | ||
411 | if (!warning_printed) { | ||
412 | printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl " | ||
413 | "usage.\n"); | ||
414 | printk(KERN_INFO "pcmcia: This interface will soon be removed from " | ||
415 | "the kernel; please expect breakage unless you upgrade " | ||
416 | "to new tools.\n"); | ||
417 | printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/" | ||
418 | "utils/kernel/pcmcia/pcmcia.html for details.\n"); | ||
419 | warning_printed = 1; | ||
420 | } | ||
421 | |||
410 | if (s->pcmcia_state.present) | 422 | if (s->pcmcia_state.present) |
411 | queue_event(user, CS_EVENT_CARD_INSERTION); | 423 | queue_event(user, CS_EVENT_CARD_INSERTION); |
412 | return 0; | 424 | return 0; |
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index f0997c36c9b7..ba4d78e5b121 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
@@ -1045,7 +1045,18 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i | |||
1045 | { | 1045 | { |
1046 | struct yenta_socket *socket; | 1046 | struct yenta_socket *socket; |
1047 | int ret; | 1047 | int ret; |
1048 | 1048 | ||
1049 | /* | ||
1050 | * If we failed to assign proper bus numbers for this cardbus | ||
1051 | * controller during PCI probe, its subordinate pci_bus is NULL. | ||
1052 | * Bail out if so. | ||
1053 | */ | ||
1054 | if (!dev->subordinate) { | ||
1055 | printk(KERN_ERR "Yenta: no bus associated with %s! " | ||
1056 | "(try 'pci=assign-busses')\n", pci_name(dev)); | ||
1057 | return -ENODEV; | ||
1058 | } | ||
1059 | |||
1049 | socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); | 1060 | socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); |
1050 | if (!socket) | 1061 | if (!socket) |
1051 | return -ENOMEM; | 1062 | return -ENOMEM; |
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index aac83ce6469c..a1c52a682191 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/cio/blacklist.c | 2 | * drivers/s390/cio/blacklist.c |
3 | * S/390 common I/O routines -- blacklisting of specific devices | 3 | * S/390 common I/O routines -- blacklisting of specific devices |
4 | * $Revision: 1.34 $ | 4 | * $Revision: 1.35 $ |
5 | * | 5 | * |
6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, | 6 | * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, |
7 | * IBM Corporation | 7 | * IBM Corporation |
@@ -35,7 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | /* 65536 bits to indicate if a devno is blacklisted or not */ | 37 | /* 65536 bits to indicate if a devno is blacklisted or not */ |
38 | #define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \ | 38 | #define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \ |
39 | (8*sizeof(long))) | 39 | (8*sizeof(long))) |
40 | static unsigned long bl_dev[__BL_DEV_WORDS]; | 40 | static unsigned long bl_dev[__BL_DEV_WORDS]; |
41 | typedef enum {add, free} range_action; | 41 | typedef enum {add, free} range_action; |
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 6aeef3bacc33..0cb47eca91f3 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c | |||
@@ -682,9 +682,6 @@ z90crypt_cleanup_module(void) | |||
682 | del_timer(&config_timer); | 682 | del_timer(&config_timer); |
683 | del_timer(&cleanup_timer); | 683 | del_timer(&cleanup_timer); |
684 | 684 | ||
685 | if (z90_device_work) | ||
686 | destroy_workqueue(z90_device_work); | ||
687 | |||
688 | destroy_z90crypt(); | 685 | destroy_z90crypt(); |
689 | 686 | ||
690 | PRINTKN("Unloaded.\n"); | 687 | PRINTKN("Unloaded.\n"); |
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c index 96ca863eaff2..0db4f57a6a95 100644 --- a/drivers/s390/net/ctcmain.c +++ b/drivers/s390/net/ctcmain.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $ | 2 | * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $ |
3 | * | 3 | * |
4 | * CTC / ESCON network driver | 4 | * CTC / ESCON network driver |
5 | * | 5 | * |
@@ -37,10 +37,9 @@ | |||
37 | * along with this program; if not, write to the Free Software | 37 | * along with this program; if not, write to the Free Software |
38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 38 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
39 | * | 39 | * |
40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $ | 40 | * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $ |
41 | * | 41 | * |
42 | */ | 42 | */ |
43 | |||
44 | #undef DEBUG | 43 | #undef DEBUG |
45 | #include <linux/module.h> | 44 | #include <linux/module.h> |
46 | #include <linux/init.h> | 45 | #include <linux/init.h> |
@@ -135,7 +134,7 @@ static const char *dev_event_names[] = { | |||
135 | "TX down", | 134 | "TX down", |
136 | "Restart", | 135 | "Restart", |
137 | }; | 136 | }; |
138 | 137 | ||
139 | /** | 138 | /** |
140 | * Events of the channel statemachine | 139 | * Events of the channel statemachine |
141 | */ | 140 | */ |
@@ -249,7 +248,7 @@ static void | |||
249 | print_banner(void) | 248 | print_banner(void) |
250 | { | 249 | { |
251 | static int printed = 0; | 250 | static int printed = 0; |
252 | char vbuf[] = "$Revision: 1.74 $"; | 251 | char vbuf[] = "$Revision: 1.78 $"; |
253 | char *version = vbuf; | 252 | char *version = vbuf; |
254 | 253 | ||
255 | if (printed) | 254 | if (printed) |
@@ -334,7 +333,7 @@ static const char *ch_state_names[] = { | |||
334 | "Restarting", | 333 | "Restarting", |
335 | "Not operational", | 334 | "Not operational", |
336 | }; | 335 | }; |
337 | 336 | ||
338 | #ifdef DEBUG | 337 | #ifdef DEBUG |
339 | /** | 338 | /** |
340 | * Dump header and first 16 bytes of an sk_buff for debugging purposes. | 339 | * Dump header and first 16 bytes of an sk_buff for debugging purposes. |
@@ -671,7 +670,7 @@ static void | |||
671 | fsm_action_nop(fsm_instance * fi, int event, void *arg) | 670 | fsm_action_nop(fsm_instance * fi, int event, void *arg) |
672 | { | 671 | { |
673 | } | 672 | } |
674 | 673 | ||
675 | /** | 674 | /** |
676 | * Actions for channel - statemachines. | 675 | * Actions for channel - statemachines. |
677 | *****************************************************************************/ | 676 | *****************************************************************************/ |
@@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg) | |||
1514 | fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev); | 1513 | fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev); |
1515 | } | 1514 | } |
1516 | 1515 | ||
1517 | |||
1518 | /** | 1516 | /** |
1519 | * The statemachine for a channel. | 1517 | * The statemachine for a channel. |
1520 | */ | 1518 | */ |
@@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = { | |||
1625 | }; | 1623 | }; |
1626 | 1624 | ||
1627 | static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); | 1625 | static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node); |
1628 | 1626 | ||
1629 | /** | 1627 | /** |
1630 | * Functions related to setup and device detection. | 1628 | * Functions related to setup and device detection. |
1631 | *****************************************************************************/ | 1629 | *****************************************************************************/ |
@@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) | |||
1976 | fsm_event(ch->fsm, CH_EVENT_IRQ, ch); | 1974 | fsm_event(ch->fsm, CH_EVENT_IRQ, ch); |
1977 | 1975 | ||
1978 | } | 1976 | } |
1979 | 1977 | ||
1980 | /** | 1978 | /** |
1981 | * Actions for interface - statemachine. | 1979 | * Actions for interface - statemachine. |
1982 | *****************************************************************************/ | 1980 | *****************************************************************************/ |
@@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2209 | int rc = 0; | 2207 | int rc = 0; |
2210 | 2208 | ||
2211 | DBF_TEXT(trace, 5, __FUNCTION__); | 2209 | DBF_TEXT(trace, 5, __FUNCTION__); |
2210 | /* we need to acquire the lock for testing the state | ||
2211 | * otherwise we can have an IRQ changing the state to | ||
2212 | * TXIDLE after the test but before acquiring the lock. | ||
2213 | */ | ||
2214 | spin_lock_irqsave(&ch->collect_lock, saveflags); | ||
2212 | if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) { | 2215 | if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) { |
2213 | int l = skb->len + LL_HEADER_LENGTH; | 2216 | int l = skb->len + LL_HEADER_LENGTH; |
2214 | 2217 | ||
2215 | spin_lock_irqsave(&ch->collect_lock, saveflags); | 2218 | if (ch->collect_len + l > ch->max_bufsize - 2) { |
2216 | if (ch->collect_len + l > ch->max_bufsize - 2) | 2219 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); |
2217 | rc = -EBUSY; | 2220 | return -EBUSY; |
2218 | else { | 2221 | } else { |
2219 | atomic_inc(&skb->users); | 2222 | atomic_inc(&skb->users); |
2220 | header.length = l; | 2223 | header.length = l; |
2221 | header.type = skb->protocol; | 2224 | header.type = skb->protocol; |
@@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2231 | int ccw_idx; | 2234 | int ccw_idx; |
2232 | struct sk_buff *nskb; | 2235 | struct sk_buff *nskb; |
2233 | unsigned long hi; | 2236 | unsigned long hi; |
2234 | 2237 | spin_unlock_irqrestore(&ch->collect_lock, saveflags); | |
2235 | /** | 2238 | /** |
2236 | * Protect skb against beeing free'd by upper | 2239 | * Protect skb against beeing free'd by upper |
2237 | * layers. | 2240 | * layers. |
@@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2256 | if (!nskb) { | 2259 | if (!nskb) { |
2257 | atomic_dec(&skb->users); | 2260 | atomic_dec(&skb->users); |
2258 | skb_pull(skb, LL_HEADER_LENGTH + 2); | 2261 | skb_pull(skb, LL_HEADER_LENGTH + 2); |
2262 | ctc_clear_busy(ch->netdev); | ||
2259 | return -ENOMEM; | 2263 | return -ENOMEM; |
2260 | } else { | 2264 | } else { |
2261 | memcpy(skb_put(nskb, skb->len), | 2265 | memcpy(skb_put(nskb, skb->len), |
@@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2281 | */ | 2285 | */ |
2282 | atomic_dec(&skb->users); | 2286 | atomic_dec(&skb->users); |
2283 | skb_pull(skb, LL_HEADER_LENGTH + 2); | 2287 | skb_pull(skb, LL_HEADER_LENGTH + 2); |
2288 | ctc_clear_busy(ch->netdev); | ||
2284 | return -EBUSY; | 2289 | return -EBUSY; |
2285 | } | 2290 | } |
2286 | 2291 | ||
@@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb) | |||
2327 | } | 2332 | } |
2328 | } | 2333 | } |
2329 | 2334 | ||
2335 | ctc_clear_busy(ch->netdev); | ||
2330 | return rc; | 2336 | return rc; |
2331 | } | 2337 | } |
2332 | 2338 | ||
2333 | /** | 2339 | /** |
2334 | * Interface API for upper network layers | 2340 | * Interface API for upper network layers |
2335 | *****************************************************************************/ | 2341 | *****************************************************************************/ |
@@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev) | |||
2421 | dev->trans_start = jiffies; | 2427 | dev->trans_start = jiffies; |
2422 | if (transmit_skb(privptr->channel[WRITE], skb) != 0) | 2428 | if (transmit_skb(privptr->channel[WRITE], skb) != 0) |
2423 | rc = 1; | 2429 | rc = 1; |
2424 | ctc_clear_busy(dev); | ||
2425 | return rc; | 2430 | return rc; |
2426 | } | 2431 | } |
2427 | 2432 | ||
@@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf, | |||
2610 | return count; | 2615 | return count; |
2611 | } | 2616 | } |
2612 | 2617 | ||
2613 | |||
2614 | static void | 2618 | static void |
2615 | ctc_netdev_unregister(struct net_device * dev) | 2619 | ctc_netdev_unregister(struct net_device * dev) |
2616 | { | 2620 | { |
@@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b | |||
2685 | return count; | 2689 | return count; |
2686 | } | 2690 | } |
2687 | 2691 | ||
2688 | |||
2689 | static ssize_t | 2692 | static ssize_t |
2690 | ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf) | 2693 | ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf) |
2691 | { | 2694 | { |
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h index 3a0285669adf..2ad4797ce024 100644 --- a/drivers/s390/net/qeth.h +++ b/drivers/s390/net/qeth.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "qeth_mpc.h" | 25 | #include "qeth_mpc.h" |
26 | 26 | ||
27 | #define VERSION_QETH_H "$Revision: 1.139 $" | 27 | #define VERSION_QETH_H "$Revision: 1.142 $" |
28 | 28 | ||
29 | #ifdef CONFIG_QETH_IPV6 | 29 | #ifdef CONFIG_QETH_IPV6 |
30 | #define QETH_VERSION_IPV6 ":IPv6" | 30 | #define QETH_VERSION_IPV6 ":IPv6" |
@@ -1172,7 +1172,7 @@ extern int | |||
1172 | qeth_realloc_buffer_pool(struct qeth_card *, int); | 1172 | qeth_realloc_buffer_pool(struct qeth_card *, int); |
1173 | 1173 | ||
1174 | extern int | 1174 | extern int |
1175 | qeth_set_large_send(struct qeth_card *); | 1175 | qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types); |
1176 | 1176 | ||
1177 | extern void | 1177 | extern void |
1178 | qeth_fill_header(struct qeth_card *, struct qeth_hdr *, | 1178 | qeth_fill_header(struct qeth_card *, struct qeth_hdr *, |
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c index 79c74f3a11f5..86582cf1e19e 100644 --- a/drivers/s390/net/qeth_main.c +++ b/drivers/s390/net/qeth_main.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $) | 3 | * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * | 6 | * |
@@ -12,7 +12,7 @@ | |||
12 | * Frank Pavlic (pavlic@de.ibm.com) and | 12 | * Frank Pavlic (pavlic@de.ibm.com) and |
13 | * Thomas Spatzier <tspat@de.ibm.com> | 13 | * Thomas Spatzier <tspat@de.ibm.com> |
14 | * | 14 | * |
15 | * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $ | 15 | * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $ |
16 | * | 16 | * |
17 | * This program is free software; you can redistribute it and/or modify | 17 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 18 | * it under the terms of the GNU General Public License as published by |
@@ -29,14 +29,6 @@ | |||
29 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 29 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
30 | */ | 30 | */ |
31 | 31 | ||
32 | /*** | ||
33 | * eye catcher; just for debugging purposes | ||
34 | */ | ||
35 | void volatile | ||
36 | qeth_eyecatcher(void) | ||
37 | { | ||
38 | return; | ||
39 | } | ||
40 | 32 | ||
41 | #include <linux/config.h> | 33 | #include <linux/config.h> |
42 | #include <linux/module.h> | 34 | #include <linux/module.h> |
@@ -80,7 +72,7 @@ qeth_eyecatcher(void) | |||
80 | #include "qeth_eddp.h" | 72 | #include "qeth_eddp.h" |
81 | #include "qeth_tso.h" | 73 | #include "qeth_tso.h" |
82 | 74 | ||
83 | #define VERSION_QETH_C "$Revision: 1.214 $" | 75 | #define VERSION_QETH_C "$Revision: 1.224 $" |
84 | static const char *version = "qeth S/390 OSA-Express driver"; | 76 | static const char *version = "qeth S/390 OSA-Express driver"; |
85 | 77 | ||
86 | /** | 78 | /** |
@@ -2759,11 +2751,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int, | |||
2759 | queue->card->perf_stats.outbound_do_qdio_start_time; | 2751 | queue->card->perf_stats.outbound_do_qdio_start_time; |
2760 | #endif | 2752 | #endif |
2761 | if (rc){ | 2753 | if (rc){ |
2762 | QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO " | ||
2763 | "returned error (%i) on device %s.", | ||
2764 | rc, CARD_DDEV_ID(queue->card)); | ||
2765 | QETH_DBF_TEXT(trace, 2, "flushbuf"); | 2754 | QETH_DBF_TEXT(trace, 2, "flushbuf"); |
2766 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); | 2755 | QETH_DBF_TEXT_(trace, 2, " err%d", rc); |
2756 | QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card)); | ||
2767 | queue->card->stats.tx_errors += count; | 2757 | queue->card->stats.tx_errors += count; |
2768 | /* this must not happen under normal circumstances. if it | 2758 | /* this must not happen under normal circumstances. if it |
2769 | * happens something is really wrong -> recover */ | 2759 | * happens something is really wrong -> recover */ |
@@ -2909,11 +2899,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status, | |||
2909 | QETH_DBF_TEXT(trace, 6, "qdouhdl"); | 2899 | QETH_DBF_TEXT(trace, 6, "qdouhdl"); |
2910 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { | 2900 | if (status & QDIO_STATUS_LOOK_FOR_ERROR) { |
2911 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ | 2901 | if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){ |
2912 | QETH_DBF_SPRINTF(trace, 2, "On device %s: " | 2902 | QETH_DBF_TEXT(trace, 2, "achkcond"); |
2913 | "received active check " | 2903 | QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card)); |
2914 | "condition (0x%08x).", | ||
2915 | CARD_BUS_ID(card), status); | ||
2916 | QETH_DBF_TEXT(trace, 2, "chkcond"); | ||
2917 | QETH_DBF_TEXT_(trace, 2, "%08x", status); | 2904 | QETH_DBF_TEXT_(trace, 2, "%08x", status); |
2918 | netif_stop_queue(card->dev); | 2905 | netif_stop_queue(card->dev); |
2919 | qeth_schedule_recovery(card); | 2906 | qeth_schedule_recovery(card); |
@@ -3356,26 +3343,32 @@ qeth_halt_channel(struct qeth_channel *channel) | |||
3356 | static int | 3343 | static int |
3357 | qeth_halt_channels(struct qeth_card *card) | 3344 | qeth_halt_channels(struct qeth_card *card) |
3358 | { | 3345 | { |
3359 | int rc = 0; | 3346 | int rc1 = 0, rc2=0, rc3 = 0; |
3360 | 3347 | ||
3361 | QETH_DBF_TEXT(trace,3,"haltchs"); | 3348 | QETH_DBF_TEXT(trace,3,"haltchs"); |
3362 | if ((rc = qeth_halt_channel(&card->read))) | 3349 | rc1 = qeth_halt_channel(&card->read); |
3363 | return rc; | 3350 | rc2 = qeth_halt_channel(&card->write); |
3364 | if ((rc = qeth_halt_channel(&card->write))) | 3351 | rc3 = qeth_halt_channel(&card->data); |
3365 | return rc; | 3352 | if (rc1) |
3366 | return qeth_halt_channel(&card->data); | 3353 | return rc1; |
3354 | if (rc2) | ||
3355 | return rc2; | ||
3356 | return rc3; | ||
3367 | } | 3357 | } |
3368 | static int | 3358 | static int |
3369 | qeth_clear_channels(struct qeth_card *card) | 3359 | qeth_clear_channels(struct qeth_card *card) |
3370 | { | 3360 | { |
3371 | int rc = 0; | 3361 | int rc1 = 0, rc2=0, rc3 = 0; |
3372 | 3362 | ||
3373 | QETH_DBF_TEXT(trace,3,"clearchs"); | 3363 | QETH_DBF_TEXT(trace,3,"clearchs"); |
3374 | if ((rc = qeth_clear_channel(&card->read))) | 3364 | rc1 = qeth_clear_channel(&card->read); |
3375 | return rc; | 3365 | rc2 = qeth_clear_channel(&card->write); |
3376 | if ((rc = qeth_clear_channel(&card->write))) | 3366 | rc3 = qeth_clear_channel(&card->data); |
3377 | return rc; | 3367 | if (rc1) |
3378 | return qeth_clear_channel(&card->data); | 3368 | return rc1; |
3369 | if (rc2) | ||
3370 | return rc2; | ||
3371 | return rc3; | ||
3379 | } | 3372 | } |
3380 | 3373 | ||
3381 | static int | 3374 | static int |
@@ -3445,23 +3438,23 @@ qeth_mpc_initialize(struct qeth_card *card) | |||
3445 | } | 3438 | } |
3446 | if ((rc = qeth_cm_enable(card))){ | 3439 | if ((rc = qeth_cm_enable(card))){ |
3447 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); | 3440 | QETH_DBF_TEXT_(setup, 2, "2err%d", rc); |
3448 | return rc; | 3441 | goto out_qdio; |
3449 | } | 3442 | } |
3450 | if ((rc = qeth_cm_setup(card))){ | 3443 | if ((rc = qeth_cm_setup(card))){ |
3451 | QETH_DBF_TEXT_(setup, 2, "3err%d", rc); | 3444 | QETH_DBF_TEXT_(setup, 2, "3err%d", rc); |
3452 | return rc; | 3445 | goto out_qdio; |
3453 | } | 3446 | } |
3454 | if ((rc = qeth_ulp_enable(card))){ | 3447 | if ((rc = qeth_ulp_enable(card))){ |
3455 | QETH_DBF_TEXT_(setup, 2, "4err%d", rc); | 3448 | QETH_DBF_TEXT_(setup, 2, "4err%d", rc); |
3456 | return rc; | 3449 | goto out_qdio; |
3457 | } | 3450 | } |
3458 | if ((rc = qeth_ulp_setup(card))){ | 3451 | if ((rc = qeth_ulp_setup(card))){ |
3459 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); | 3452 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); |
3460 | return rc; | 3453 | goto out_qdio; |
3461 | } | 3454 | } |
3462 | if ((rc = qeth_alloc_qdio_buffers(card))){ | 3455 | if ((rc = qeth_alloc_qdio_buffers(card))){ |
3463 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); | 3456 | QETH_DBF_TEXT_(setup, 2, "5err%d", rc); |
3464 | return rc; | 3457 | goto out_qdio; |
3465 | } | 3458 | } |
3466 | if ((rc = qeth_qdio_establish(card))){ | 3459 | if ((rc = qeth_qdio_establish(card))){ |
3467 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); | 3460 | QETH_DBF_TEXT_(setup, 2, "6err%d", rc); |
@@ -3795,12 +3788,16 @@ static inline int | |||
3795 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, | 3788 | qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb, |
3796 | struct qeth_hdr **hdr, int ipv) | 3789 | struct qeth_hdr **hdr, int ipv) |
3797 | { | 3790 | { |
3791 | int rc; | ||
3798 | #ifdef CONFIG_QETH_VLAN | 3792 | #ifdef CONFIG_QETH_VLAN |
3799 | u16 *tag; | 3793 | u16 *tag; |
3800 | #endif | 3794 | #endif |
3801 | 3795 | ||
3802 | QETH_DBF_TEXT(trace, 6, "prepskb"); | 3796 | QETH_DBF_TEXT(trace, 6, "prepskb"); |
3803 | 3797 | ||
3798 | rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr)); | ||
3799 | if (rc) | ||
3800 | return rc; | ||
3804 | #ifdef CONFIG_QETH_VLAN | 3801 | #ifdef CONFIG_QETH_VLAN |
3805 | if (card->vlangrp && vlan_tx_tag_present(*skb) && | 3802 | if (card->vlangrp && vlan_tx_tag_present(*skb) && |
3806 | ((ipv == 6) || card->options.layer2) ) { | 3803 | ((ipv == 6) || card->options.layer2) ) { |
@@ -4251,7 +4248,8 @@ out: | |||
4251 | } | 4248 | } |
4252 | 4249 | ||
4253 | static inline int | 4250 | static inline int |
4254 | qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) | 4251 | qeth_get_elements_no(struct qeth_card *card, void *hdr, |
4252 | struct sk_buff *skb, int elems) | ||
4255 | { | 4253 | { |
4256 | int elements_needed = 0; | 4254 | int elements_needed = 0; |
4257 | 4255 | ||
@@ -4261,9 +4259,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb) | |||
4261 | if (elements_needed == 0 ) | 4259 | if (elements_needed == 0 ) |
4262 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) | 4260 | elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE) |
4263 | + skb->len) >> PAGE_SHIFT); | 4261 | + skb->len) >> PAGE_SHIFT); |
4264 | if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){ | 4262 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){ |
4265 | PRINT_ERR("qeth_do_send_packet: invalid size of " | 4263 | PRINT_ERR("qeth_do_send_packet: invalid size of " |
4266 | "IP packet. Discarded."); | 4264 | "IP packet (Number=%d / Length=%d). Discarded.\n", |
4265 | (elements_needed+elems), skb->len); | ||
4267 | return 0; | 4266 | return 0; |
4268 | } | 4267 | } |
4269 | return elements_needed; | 4268 | return elements_needed; |
@@ -4275,7 +4274,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4275 | int ipv = 0; | 4274 | int ipv = 0; |
4276 | int cast_type; | 4275 | int cast_type; |
4277 | struct qeth_qdio_out_q *queue; | 4276 | struct qeth_qdio_out_q *queue; |
4278 | struct qeth_hdr *hdr; | 4277 | struct qeth_hdr *hdr = NULL; |
4279 | int elements_needed = 0; | 4278 | int elements_needed = 0; |
4280 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; | 4279 | enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO; |
4281 | struct qeth_eddp_context *ctx = NULL; | 4280 | struct qeth_eddp_context *ctx = NULL; |
@@ -4337,9 +4336,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb) | |||
4337 | return -EINVAL; | 4336 | return -EINVAL; |
4338 | } | 4337 | } |
4339 | } else { | 4338 | } else { |
4340 | elements_needed += qeth_get_elements_no(card,(void*) hdr, skb); | 4339 | int elems = qeth_get_elements_no(card,(void*) hdr, skb, |
4341 | if (!elements_needed) | 4340 | elements_needed); |
4341 | if (!elems) | ||
4342 | return -EINVAL; | 4342 | return -EINVAL; |
4343 | elements_needed += elems; | ||
4343 | } | 4344 | } |
4344 | 4345 | ||
4345 | if (card->info.type != QETH_CARD_TYPE_IQD) | 4346 | if (card->info.type != QETH_CARD_TYPE_IQD) |
@@ -4504,7 +4505,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries) | |||
4504 | 4505 | ||
4505 | QETH_DBF_TEXT(trace,3,"arpstnoe"); | 4506 | QETH_DBF_TEXT(trace,3,"arpstnoe"); |
4506 | 4507 | ||
4507 | /* TODO: really not supported by GuestLAN? */ | 4508 | /* |
4509 | * currently GuestLAN only supports the ARP assist function | ||
4510 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES; | ||
4511 | * thus we say EOPNOTSUPP for this ARP function | ||
4512 | */ | ||
4508 | if (card->info.guestlan) | 4513 | if (card->info.guestlan) |
4509 | return -EOPNOTSUPP; | 4514 | return -EOPNOTSUPP; |
4510 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { | 4515 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { |
@@ -4681,14 +4686,6 @@ qeth_arp_query(struct qeth_card *card, char *udata) | |||
4681 | 4686 | ||
4682 | QETH_DBF_TEXT(trace,3,"arpquery"); | 4687 | QETH_DBF_TEXT(trace,3,"arpquery"); |
4683 | 4688 | ||
4684 | /* | ||
4685 | * currently GuestLAN does only deliver all zeros on query arp, | ||
4686 | * even though arp processing is supported (according to IPA supp. | ||
4687 | * funcs flags); since all zeros is no valueable information, | ||
4688 | * we say EOPNOTSUPP for all ARP functions | ||
4689 | */ | ||
4690 | /*if (card->info.guestlan) | ||
4691 | return -EOPNOTSUPP; */ | ||
4692 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ | 4689 | if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/ |
4693 | IPA_ARP_PROCESSING)) { | 4690 | IPA_ARP_PROCESSING)) { |
4694 | PRINT_WARN("ARP processing not supported " | 4691 | PRINT_WARN("ARP processing not supported " |
@@ -4894,10 +4891,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry) | |||
4894 | QETH_DBF_TEXT(trace,3,"arpadent"); | 4891 | QETH_DBF_TEXT(trace,3,"arpadent"); |
4895 | 4892 | ||
4896 | /* | 4893 | /* |
4897 | * currently GuestLAN does only deliver all zeros on query arp, | 4894 | * currently GuestLAN only supports the ARP assist function |
4898 | * even though arp processing is supported (according to IPA supp. | 4895 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY; |
4899 | * funcs flags); since all zeros is no valueable information, | 4896 | * thus we say EOPNOTSUPP for this ARP function |
4900 | * we say EOPNOTSUPP for all ARP functions | ||
4901 | */ | 4897 | */ |
4902 | if (card->info.guestlan) | 4898 | if (card->info.guestlan) |
4903 | return -EOPNOTSUPP; | 4899 | return -EOPNOTSUPP; |
@@ -4937,10 +4933,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry | |||
4937 | QETH_DBF_TEXT(trace,3,"arprment"); | 4933 | QETH_DBF_TEXT(trace,3,"arprment"); |
4938 | 4934 | ||
4939 | /* | 4935 | /* |
4940 | * currently GuestLAN does only deliver all zeros on query arp, | 4936 | * currently GuestLAN only supports the ARP assist function |
4941 | * even though arp processing is supported (according to IPA supp. | 4937 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY; |
4942 | * funcs flags); since all zeros is no valueable information, | 4938 | * thus we say EOPNOTSUPP for this ARP function |
4943 | * we say EOPNOTSUPP for all ARP functions | ||
4944 | */ | 4939 | */ |
4945 | if (card->info.guestlan) | 4940 | if (card->info.guestlan) |
4946 | return -EOPNOTSUPP; | 4941 | return -EOPNOTSUPP; |
@@ -4978,11 +4973,10 @@ qeth_arp_flush_cache(struct qeth_card *card) | |||
4978 | QETH_DBF_TEXT(trace,3,"arpflush"); | 4973 | QETH_DBF_TEXT(trace,3,"arpflush"); |
4979 | 4974 | ||
4980 | /* | 4975 | /* |
4981 | * currently GuestLAN does only deliver all zeros on query arp, | 4976 | * currently GuestLAN only supports the ARP assist function |
4982 | * even though arp processing is supported (according to IPA supp. | 4977 | * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE; |
4983 | * funcs flags); since all zeros is no valueable information, | 4978 | * thus we say EOPNOTSUPP for this ARP function |
4984 | * we say EOPNOTSUPP for all ARP functions | 4979 | */ |
4985 | */ | ||
4986 | if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) | 4980 | if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD)) |
4987 | return -EOPNOTSUPP; | 4981 | return -EOPNOTSUPP; |
4988 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { | 4982 | if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) { |
@@ -7038,14 +7032,16 @@ qeth_setrouting_v6(struct qeth_card *card) | |||
7038 | } | 7032 | } |
7039 | 7033 | ||
7040 | int | 7034 | int |
7041 | qeth_set_large_send(struct qeth_card *card) | 7035 | qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type) |
7042 | { | 7036 | { |
7043 | int rc = 0; | 7037 | int rc = 0; |
7044 | 7038 | ||
7045 | if (card->dev == NULL) | 7039 | if (card->dev == NULL) { |
7040 | card->options.large_send = type; | ||
7046 | return 0; | 7041 | return 0; |
7047 | 7042 | } | |
7048 | netif_stop_queue(card->dev); | 7043 | netif_stop_queue(card->dev); |
7044 | card->options.large_send = type; | ||
7049 | switch (card->options.large_send) { | 7045 | switch (card->options.large_send) { |
7050 | case QETH_LARGE_SEND_EDDP: | 7046 | case QETH_LARGE_SEND_EDDP: |
7051 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG; | 7047 | card->dev->features |= NETIF_F_TSO | NETIF_F_SG; |
@@ -7066,7 +7062,6 @@ qeth_set_large_send(struct qeth_card *card) | |||
7066 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); | 7062 | card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG); |
7067 | break; | 7063 | break; |
7068 | } | 7064 | } |
7069 | |||
7070 | netif_wake_queue(card->dev); | 7065 | netif_wake_queue(card->dev); |
7071 | return rc; | 7066 | return rc; |
7072 | } | 7067 | } |
@@ -8257,7 +8252,6 @@ qeth_init(void) | |||
8257 | { | 8252 | { |
8258 | int rc=0; | 8253 | int rc=0; |
8259 | 8254 | ||
8260 | qeth_eyecatcher(); | ||
8261 | PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", | 8255 | PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n", |
8262 | version, VERSION_QETH_C, VERSION_QETH_H, | 8256 | version, VERSION_QETH_C, VERSION_QETH_H, |
8263 | VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, | 8257 | VERSION_QETH_MPC_H, VERSION_QETH_MPC_C, |
@@ -8338,7 +8332,6 @@ again: | |||
8338 | printk("qeth: removed\n"); | 8332 | printk("qeth: removed\n"); |
8339 | } | 8333 | } |
8340 | 8334 | ||
8341 | EXPORT_SYMBOL(qeth_eyecatcher); | ||
8342 | module_init(qeth_init); | 8335 | module_init(qeth_init); |
8343 | module_exit(qeth_exit); | 8336 | module_exit(qeth_exit); |
8344 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); | 8337 | MODULE_AUTHOR("Frank Pavlic <pavlic@de.ibm.com>"); |
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c index 98bedb0cb387..dda105b73063 100644 --- a/drivers/s390/net/qeth_sys.c +++ b/drivers/s390/net/qeth_sys.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * | 2 | * |
3 | * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $) | 3 | * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $) |
4 | * | 4 | * |
5 | * Linux on zSeries OSA Express and HiperSockets support | 5 | * Linux on zSeries OSA Express and HiperSockets support |
6 | * This file contains code related to sysfs. | 6 | * This file contains code related to sysfs. |
@@ -20,7 +20,7 @@ | |||
20 | #include "qeth_mpc.h" | 20 | #include "qeth_mpc.h" |
21 | #include "qeth_fs.h" | 21 | #include "qeth_fs.h" |
22 | 22 | ||
23 | const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $"; | 23 | const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $"; |
24 | 24 | ||
25 | /*****************************************************************************/ | 25 | /*****************************************************************************/ |
26 | /* */ | 26 | /* */ |
@@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c | |||
722 | 722 | ||
723 | if (!card) | 723 | if (!card) |
724 | return -EINVAL; | 724 | return -EINVAL; |
725 | if (card->info.type == QETH_CARD_TYPE_IQD) { | ||
726 | PRINT_WARN("Layer2 on Hipersockets is not supported! \n"); | ||
727 | return -EPERM; | ||
728 | } | ||
725 | 729 | ||
726 | if (((card->state != CARD_STATE_DOWN) && | 730 | if (((card->state != CARD_STATE_DOWN) && |
727 | (card->state != CARD_STATE_RECOVER)) || | 731 | (card->state != CARD_STATE_RECOVER))) |
728 | (card->info.type != QETH_CARD_TYPE_OSAE)) | ||
729 | return -EPERM; | 732 | return -EPERM; |
730 | 733 | ||
731 | i = simple_strtoul(buf, &tmp, 16); | 734 | i = simple_strtoul(buf, &tmp, 16); |
@@ -771,9 +774,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con | |||
771 | 774 | ||
772 | if (!card) | 775 | if (!card) |
773 | return -EINVAL; | 776 | return -EINVAL; |
774 | |||
775 | tmp = strsep((char **) &buf, "\n"); | 777 | tmp = strsep((char **) &buf, "\n"); |
776 | |||
777 | if (!strcmp(tmp, "no")){ | 778 | if (!strcmp(tmp, "no")){ |
778 | type = QETH_LARGE_SEND_NO; | 779 | type = QETH_LARGE_SEND_NO; |
779 | } else if (!strcmp(tmp, "EDDP")) { | 780 | } else if (!strcmp(tmp, "EDDP")) { |
@@ -786,10 +787,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con | |||
786 | } | 787 | } |
787 | if (card->options.large_send == type) | 788 | if (card->options.large_send == type) |
788 | return count; | 789 | return count; |
789 | card->options.large_send = type; | 790 | if ((rc = qeth_set_large_send(card, type))) |
790 | if ((rc = qeth_set_large_send(card))) | ||
791 | return rc; | 791 | return rc; |
792 | |||
793 | return count; | 792 | return count; |
794 | } | 793 | } |
795 | 794 | ||
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index dbad7f35eb0a..24ed5893b4f0 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/major.h> | 14 | #include <linux/major.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/miscdevice.h> | 16 | #include <linux/miscdevice.h> |
17 | #include <linux/ioport.h> /* request_region, check_region */ | 17 | #include <linux/ioport.h> /* request_region */ |
18 | #include <asm/atomic.h> | 18 | #include <asm/atomic.h> |
19 | #include <asm/ebus.h> /* EBus device */ | 19 | #include <asm/ebus.h> /* EBus device */ |
20 | #include <asm/oplib.h> /* OpenProm Library */ | 20 | #include <asm/oplib.h> /* OpenProm Library */ |
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 5cc53cd9323e..d92273cbe0de 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c | |||
@@ -2465,9 +2465,12 @@ static unsigned long ata_pio_poll(struct ata_port *ap) | |||
2465 | * | 2465 | * |
2466 | * LOCKING: | 2466 | * LOCKING: |
2467 | * None. (executing in kernel thread context) | 2467 | * None. (executing in kernel thread context) |
2468 | * | ||
2469 | * RETURNS: | ||
2470 | * Non-zero if qc completed, zero otherwise. | ||
2468 | */ | 2471 | */ |
2469 | 2472 | ||
2470 | static void ata_pio_complete (struct ata_port *ap) | 2473 | static int ata_pio_complete (struct ata_port *ap) |
2471 | { | 2474 | { |
2472 | struct ata_queued_cmd *qc; | 2475 | struct ata_queued_cmd *qc; |
2473 | u8 drv_stat; | 2476 | u8 drv_stat; |
@@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap) | |||
2486 | if (drv_stat & (ATA_BUSY | ATA_DRQ)) { | 2489 | if (drv_stat & (ATA_BUSY | ATA_DRQ)) { |
2487 | ap->pio_task_state = PIO_ST_LAST_POLL; | 2490 | ap->pio_task_state = PIO_ST_LAST_POLL; |
2488 | ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; | 2491 | ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO; |
2489 | return; | 2492 | return 0; |
2490 | } | 2493 | } |
2491 | } | 2494 | } |
2492 | 2495 | ||
2493 | drv_stat = ata_wait_idle(ap); | 2496 | drv_stat = ata_wait_idle(ap); |
2494 | if (!ata_ok(drv_stat)) { | 2497 | if (!ata_ok(drv_stat)) { |
2495 | ap->pio_task_state = PIO_ST_ERR; | 2498 | ap->pio_task_state = PIO_ST_ERR; |
2496 | return; | 2499 | return 0; |
2497 | } | 2500 | } |
2498 | 2501 | ||
2499 | qc = ata_qc_from_tag(ap, ap->active_tag); | 2502 | qc = ata_qc_from_tag(ap, ap->active_tag); |
@@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap) | |||
2502 | ap->pio_task_state = PIO_ST_IDLE; | 2505 | ap->pio_task_state = PIO_ST_IDLE; |
2503 | 2506 | ||
2504 | ata_poll_qc_complete(qc, drv_stat); | 2507 | ata_poll_qc_complete(qc, drv_stat); |
2508 | |||
2509 | /* another command may start at this point */ | ||
2510 | |||
2511 | return 1; | ||
2505 | } | 2512 | } |
2506 | 2513 | ||
2507 | 2514 | ||
@@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes) | |||
2709 | 2716 | ||
2710 | next_sg: | 2717 | next_sg: |
2711 | if (unlikely(qc->cursg >= qc->n_elem)) { | 2718 | if (unlikely(qc->cursg >= qc->n_elem)) { |
2712 | /* | 2719 | /* |
2713 | * The end of qc->sg is reached and the device expects | 2720 | * The end of qc->sg is reached and the device expects |
2714 | * more data to transfer. In order not to overrun qc->sg | 2721 | * more data to transfer. In order not to overrun qc->sg |
2715 | * and fulfill length specified in the byte count register, | 2722 | * and fulfill length specified in the byte count register, |
@@ -2721,7 +2728,7 @@ next_sg: | |||
2721 | unsigned int i; | 2728 | unsigned int i; |
2722 | 2729 | ||
2723 | if (words) /* warning if bytes > 1 */ | 2730 | if (words) /* warning if bytes > 1 */ |
2724 | printk(KERN_WARNING "ata%u: %u bytes trailing data\n", | 2731 | printk(KERN_WARNING "ata%u: %u bytes trailing data\n", |
2725 | ap->id, bytes); | 2732 | ap->id, bytes); |
2726 | 2733 | ||
2727 | for (i = 0; i < words; i++) | 2734 | for (i = 0; i < words; i++) |
@@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap) | |||
2849 | if (is_atapi_taskfile(&qc->tf)) { | 2856 | if (is_atapi_taskfile(&qc->tf)) { |
2850 | /* no more data to transfer or unsupported ATAPI command */ | 2857 | /* no more data to transfer or unsupported ATAPI command */ |
2851 | if ((status & ATA_DRQ) == 0) { | 2858 | if ((status & ATA_DRQ) == 0) { |
2852 | ap->pio_task_state = PIO_ST_IDLE; | 2859 | ap->pio_task_state = PIO_ST_LAST; |
2853 | |||
2854 | ata_poll_qc_complete(qc, status); | ||
2855 | return; | 2860 | return; |
2856 | } | 2861 | } |
2857 | 2862 | ||
@@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap) | |||
2887 | static void ata_pio_task(void *_data) | 2892 | static void ata_pio_task(void *_data) |
2888 | { | 2893 | { |
2889 | struct ata_port *ap = _data; | 2894 | struct ata_port *ap = _data; |
2890 | unsigned long timeout = 0; | 2895 | unsigned long timeout; |
2896 | int qc_completed; | ||
2897 | |||
2898 | fsm_start: | ||
2899 | timeout = 0; | ||
2900 | qc_completed = 0; | ||
2891 | 2901 | ||
2892 | switch (ap->pio_task_state) { | 2902 | switch (ap->pio_task_state) { |
2893 | case PIO_ST_IDLE: | 2903 | case PIO_ST_IDLE: |
@@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data) | |||
2898 | break; | 2908 | break; |
2899 | 2909 | ||
2900 | case PIO_ST_LAST: | 2910 | case PIO_ST_LAST: |
2901 | ata_pio_complete(ap); | 2911 | qc_completed = ata_pio_complete(ap); |
2902 | break; | 2912 | break; |
2903 | 2913 | ||
2904 | case PIO_ST_POLL: | 2914 | case PIO_ST_POLL: |
@@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data) | |||
2913 | } | 2923 | } |
2914 | 2924 | ||
2915 | if (timeout) | 2925 | if (timeout) |
2916 | queue_delayed_work(ata_wq, &ap->pio_task, | 2926 | queue_delayed_work(ata_wq, &ap->pio_task, timeout); |
2917 | timeout); | 2927 | else if (!qc_completed) |
2918 | else | 2928 | goto fsm_start; |
2919 | queue_work(ata_wq, &ap->pio_task); | ||
2920 | } | 2929 | } |
2921 | 2930 | ||
2922 | static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, | 2931 | static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 3e9b64137873..23d095d3817b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -201,6 +201,7 @@ int | |||
201 | qla2100_pci_config(scsi_qla_host_t *ha) | 201 | qla2100_pci_config(scsi_qla_host_t *ha) |
202 | { | 202 | { |
203 | uint16_t w, mwi; | 203 | uint16_t w, mwi; |
204 | uint32_t d; | ||
204 | unsigned long flags; | 205 | unsigned long flags; |
205 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 206 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
206 | 207 | ||
@@ -215,9 +216,9 @@ qla2100_pci_config(scsi_qla_host_t *ha) | |||
215 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); | 216 | pci_write_config_word(ha->pdev, PCI_COMMAND, w); |
216 | 217 | ||
217 | /* Reset expansion ROM address decode enable */ | 218 | /* Reset expansion ROM address decode enable */ |
218 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | 219 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); |
219 | w &= ~PCI_ROM_ADDRESS_ENABLE; | 220 | d &= ~PCI_ROM_ADDRESS_ENABLE; |
220 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | 221 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); |
221 | 222 | ||
222 | /* Get PCI bus information. */ | 223 | /* Get PCI bus information. */ |
223 | spin_lock_irqsave(&ha->hardware_lock, flags); | 224 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -237,6 +238,7 @@ int | |||
237 | qla2300_pci_config(scsi_qla_host_t *ha) | 238 | qla2300_pci_config(scsi_qla_host_t *ha) |
238 | { | 239 | { |
239 | uint16_t w, mwi; | 240 | uint16_t w, mwi; |
241 | uint32_t d; | ||
240 | unsigned long flags = 0; | 242 | unsigned long flags = 0; |
241 | uint32_t cnt; | 243 | uint32_t cnt; |
242 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | 244 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; |
@@ -302,9 +304,9 @@ qla2300_pci_config(scsi_qla_host_t *ha) | |||
302 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); | 304 | pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80); |
303 | 305 | ||
304 | /* Reset expansion ROM address decode enable */ | 306 | /* Reset expansion ROM address decode enable */ |
305 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | 307 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); |
306 | w &= ~PCI_ROM_ADDRESS_ENABLE; | 308 | d &= ~PCI_ROM_ADDRESS_ENABLE; |
307 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | 309 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); |
308 | 310 | ||
309 | /* Get PCI bus information. */ | 311 | /* Get PCI bus information. */ |
310 | spin_lock_irqsave(&ha->hardware_lock, flags); | 312 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -324,6 +326,7 @@ int | |||
324 | qla24xx_pci_config(scsi_qla_host_t *ha) | 326 | qla24xx_pci_config(scsi_qla_host_t *ha) |
325 | { | 327 | { |
326 | uint16_t w, mwi; | 328 | uint16_t w, mwi; |
329 | uint32_t d; | ||
327 | unsigned long flags = 0; | 330 | unsigned long flags = 0; |
328 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; | 331 | struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; |
329 | int pcix_cmd_reg, pcie_dctl_reg; | 332 | int pcix_cmd_reg, pcie_dctl_reg; |
@@ -366,9 +369,9 @@ qla24xx_pci_config(scsi_qla_host_t *ha) | |||
366 | } | 369 | } |
367 | 370 | ||
368 | /* Reset expansion ROM address decode enable */ | 371 | /* Reset expansion ROM address decode enable */ |
369 | pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w); | 372 | pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d); |
370 | w &= ~PCI_ROM_ADDRESS_ENABLE; | 373 | d &= ~PCI_ROM_ADDRESS_ENABLE; |
371 | pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w); | 374 | pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d); |
372 | 375 | ||
373 | /* Get PCI bus information. */ | 376 | /* Get PCI bus information. */ |
374 | spin_lock_irqsave(&ha->hardware_lock, flags); | 377 | spin_lock_irqsave(&ha->hardware_lock, flags); |
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index a63f93186e41..b227e51d12f4 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c | |||
@@ -161,7 +161,7 @@ static u32 sis_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg) | |||
161 | { | 161 | { |
162 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); | 162 | struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); |
163 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device); | 163 | unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device); |
164 | u32 val, val2; | 164 | u32 val, val2 = 0; |
165 | u8 pmr; | 165 | u8 pmr; |
166 | 166 | ||
167 | if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ | 167 | if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */ |
@@ -289,7 +289,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
289 | if (ent->device != 0x182) { | 289 | if (ent->device != 0x182) { |
290 | if ((pmr & SIS_PMR_COMBINED) == 0) { | 290 | if ((pmr & SIS_PMR_COMBINED) == 0) { |
291 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n"); | 291 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n"); |
292 | port2_start=0x64; | 292 | port2_start = 64; |
293 | } | 293 | } |
294 | else { | 294 | else { |
295 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n"); | 295 | printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in combined mode\n"); |
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index aec39fb261ca..b5cf39468d18 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c | |||
@@ -463,7 +463,7 @@ static int __init serial21285_console_setup(struct console *co, char *options) | |||
463 | return uart_set_options(port, co, baud, parity, bits, flow); | 463 | return uart_set_options(port, co, baud, parity, bits, flow); |
464 | } | 464 | } |
465 | 465 | ||
466 | extern struct uart_driver serial21285_reg; | 466 | static struct uart_driver serial21285_reg; |
467 | 467 | ||
468 | static struct console serial21285_console = | 468 | static struct console serial21285_console = |
469 | { | 469 | { |
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 978e12437e61..679e678c7e6a 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c | |||
@@ -689,7 +689,7 @@ static int __init pl010_console_setup(struct console *co, char *options) | |||
689 | return uart_set_options(port, co, baud, parity, bits, flow); | 689 | return uart_set_options(port, co, baud, parity, bits, flow); |
690 | } | 690 | } |
691 | 691 | ||
692 | extern struct uart_driver amba_reg; | 692 | static struct uart_driver amba_reg; |
693 | static struct console amba_console = { | 693 | static struct console amba_console = { |
694 | .name = "ttyAM", | 694 | .name = "ttyAM", |
695 | .write = pl010_console_write, | 695 | .write = pl010_console_write, |
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 56071309744c..1ff629c74750 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c | |||
@@ -701,7 +701,7 @@ static int __init pl011_console_setup(struct console *co, char *options) | |||
701 | return uart_set_options(&uap->port, co, baud, parity, bits, flow); | 701 | return uart_set_options(&uap->port, co, baud, parity, bits, flow); |
702 | } | 702 | } |
703 | 703 | ||
704 | extern struct uart_driver amba_reg; | 704 | static struct uart_driver amba_reg; |
705 | static struct console amba_console = { | 705 | static struct console amba_console = { |
706 | .name = "ttyAMA", | 706 | .name = "ttyAMA", |
707 | .write = pl011_console_write, | 707 | .write = pl011_console_write, |
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index d822896b488c..78c1f36ad9b7 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c | |||
@@ -525,7 +525,7 @@ static int __init clps711xuart_console_setup(struct console *co, char *options) | |||
525 | return uart_set_options(port, co, baud, parity, bits, flow); | 525 | return uart_set_options(port, co, baud, parity, bits, flow); |
526 | } | 526 | } |
527 | 527 | ||
528 | extern struct uart_driver clps711x_reg; | 528 | static struct uart_driver clps711x_reg; |
529 | static struct console clps711x_console = { | 529 | static struct console clps711x_console = { |
530 | .name = "ttyCL", | 530 | .name = "ttyCL", |
531 | .write = clps711xuart_console_write, | 531 | .write = clps711xuart_console_write, |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index a3cd0ee8486d..0585ab27ffde 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
@@ -781,7 +781,7 @@ mpc52xx_uart_remove(struct device *dev) | |||
781 | 781 | ||
782 | #ifdef CONFIG_PM | 782 | #ifdef CONFIG_PM |
783 | static int | 783 | static int |
784 | mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level) | 784 | mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level) |
785 | { | 785 | { |
786 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); | 786 | struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev); |
787 | 787 | ||
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index eaa0af835290..672b359b07ce 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c | |||
@@ -589,8 +589,8 @@ serial_pxa_type(struct uart_port *port) | |||
589 | 589 | ||
590 | #ifdef CONFIG_SERIAL_PXA_CONSOLE | 590 | #ifdef CONFIG_SERIAL_PXA_CONSOLE |
591 | 591 | ||
592 | extern struct uart_pxa_port serial_pxa_ports[]; | 592 | static struct uart_pxa_port serial_pxa_ports[]; |
593 | extern struct uart_driver serial_pxa_reg; | 593 | static struct uart_driver serial_pxa_reg; |
594 | 594 | ||
595 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) | 595 | #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) |
596 | 596 | ||
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 1225b14f6e9d..dd8aed242357 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c | |||
@@ -799,7 +799,7 @@ sa1100_console_setup(struct console *co, char *options) | |||
799 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); | 799 | return uart_set_options(&sport->port, co, baud, parity, bits, flow); |
800 | } | 800 | } |
801 | 801 | ||
802 | extern struct uart_driver sa1100_reg; | 802 | static struct uart_driver sa1100_reg; |
803 | static struct console sa1100_console = { | 803 | static struct console sa1100_console = { |
804 | .name = "ttySA", | 804 | .name = "ttySA", |
805 | .write = sa1100_console_write, | 805 | .write = sa1100_console_write, |
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 8302376800c0..d01dbe5da3b9 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c | |||
@@ -632,7 +632,7 @@ static int __init lh7a40xuart_console_setup (struct console* co, char* options) | |||
632 | return uart_set_options (port, co, baud, parity, bits, flow); | 632 | return uart_set_options (port, co, baud, parity, bits, flow); |
633 | } | 633 | } |
634 | 634 | ||
635 | extern struct uart_driver lh7a40x_reg; | 635 | static struct uart_driver lh7a40x_reg; |
636 | static struct console lh7a40x_console = { | 636 | static struct console lh7a40x_console = { |
637 | .name = "ttyAM", | 637 | .name = "ttyAM", |
638 | .write = lh7a40xuart_console_write, | 638 | .write = lh7a40xuart_console_write, |
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c index 4382ee60b6a8..6bed8713897e 100644 --- a/drivers/tc/zs.c +++ b/drivers/tc/zs.c | |||
@@ -1683,7 +1683,7 @@ static void __init probe_sccs(void) | |||
1683 | #ifndef CONFIG_SERIAL_DEC_CONSOLE | 1683 | #ifndef CONFIG_SERIAL_DEC_CONSOLE |
1684 | /* | 1684 | /* |
1685 | * We're called early and memory managment isn't up, yet. | 1685 | * We're called early and memory managment isn't up, yet. |
1686 | * Thus check_region would fail. | 1686 | * Thus request_region would fail. |
1687 | */ | 1687 | */ |
1688 | if (!request_region((unsigned long) | 1688 | if (!request_region((unsigned long) |
1689 | zs_channels[n_channels].control, | 1689 | zs_channels[n_channels].control, |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 615874e03ce8..31ee13eef7af 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -753,7 +753,8 @@ config FB_I810_GTF | |||
753 | 753 | ||
754 | config FB_I810_I2C | 754 | config FB_I810_I2C |
755 | bool "Enable DDC Support" | 755 | bool "Enable DDC Support" |
756 | depends on FB_I810 && I2C && FB_I810_GTF | 756 | depends on FB_I810 && FB_I810_GTF |
757 | select I2C | ||
757 | select I2C_ALGOBIT | 758 | select I2C_ALGOBIT |
758 | help | 759 | help |
759 | 760 | ||
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 353cb3f73cf2..630f2dfa9699 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c | |||
@@ -19,17 +19,18 @@ | |||
19 | #include <linux/fb.h> | 19 | #include <linux/fb.h> |
20 | #include <linux/backlight.h> | 20 | #include <linux/backlight.h> |
21 | 21 | ||
22 | #include <asm/arch-pxa/corgi.h> | 22 | #include <asm/mach-types.h> |
23 | #include <asm/hardware/scoop.h> | 23 | #include <asm/arch/sharpsl.h> |
24 | 24 | ||
25 | #define CORGI_MAX_INTENSITY 0x3e | ||
26 | #define CORGI_DEFAULT_INTENSITY 0x1f | 25 | #define CORGI_DEFAULT_INTENSITY 0x1f |
27 | #define CORGI_LIMIT_MASK 0x0b | 26 | #define CORGI_LIMIT_MASK 0x0b |
28 | 27 | ||
29 | static int corgibl_powermode = FB_BLANK_UNBLANK; | 28 | static int corgibl_powermode = FB_BLANK_UNBLANK; |
30 | static int current_intensity = 0; | 29 | static int current_intensity = 0; |
31 | static int corgibl_limit = 0; | 30 | static int corgibl_limit = 0; |
31 | static void (*corgibl_mach_set_intensity)(int intensity); | ||
32 | static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; | 32 | static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED; |
33 | static struct backlight_properties corgibl_data; | ||
33 | 34 | ||
34 | static void corgibl_send_intensity(int intensity) | 35 | static void corgibl_send_intensity(int intensity) |
35 | { | 36 | { |
@@ -43,18 +44,10 @@ static void corgibl_send_intensity(int intensity) | |||
43 | intensity &= CORGI_LIMIT_MASK; | 44 | intensity &= CORGI_LIMIT_MASK; |
44 | } | 45 | } |
45 | 46 | ||
46 | /* Skip 0x20 as it will blank the display */ | ||
47 | if (intensity >= 0x20) | ||
48 | intensity++; | ||
49 | |||
50 | spin_lock_irqsave(&bl_lock, flags); | 47 | spin_lock_irqsave(&bl_lock, flags); |
51 | /* Bits 0-4 are accessed via the SSP interface */ | 48 | |
52 | corgi_ssp_blduty_set(intensity & 0x1f); | 49 | corgibl_mach_set_intensity(intensity); |
53 | /* Bit 5 is via SCOOP */ | 50 | |
54 | if (intensity & 0x0020) | ||
55 | set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT); | ||
56 | else | ||
57 | reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT); | ||
58 | spin_unlock_irqrestore(&bl_lock, flags); | 51 | spin_unlock_irqrestore(&bl_lock, flags); |
59 | } | 52 | } |
60 | 53 | ||
@@ -113,8 +106,8 @@ static int corgibl_get_power(struct backlight_device *bd) | |||
113 | 106 | ||
114 | static int corgibl_set_intensity(struct backlight_device *bd, int intensity) | 107 | static int corgibl_set_intensity(struct backlight_device *bd, int intensity) |
115 | { | 108 | { |
116 | if (intensity > CORGI_MAX_INTENSITY) | 109 | if (intensity > corgibl_data.max_brightness) |
117 | intensity = CORGI_MAX_INTENSITY; | 110 | intensity = corgibl_data.max_brightness; |
118 | corgibl_send_intensity(intensity); | 111 | corgibl_send_intensity(intensity); |
119 | current_intensity=intensity; | 112 | current_intensity=intensity; |
120 | return 0; | 113 | return 0; |
@@ -141,7 +134,6 @@ static struct backlight_properties corgibl_data = { | |||
141 | .owner = THIS_MODULE, | 134 | .owner = THIS_MODULE, |
142 | .get_power = corgibl_get_power, | 135 | .get_power = corgibl_get_power, |
143 | .set_power = corgibl_set_power, | 136 | .set_power = corgibl_set_power, |
144 | .max_brightness = CORGI_MAX_INTENSITY, | ||
145 | .get_brightness = corgibl_get_intensity, | 137 | .get_brightness = corgibl_get_intensity, |
146 | .set_brightness = corgibl_set_intensity, | 138 | .set_brightness = corgibl_set_intensity, |
147 | }; | 139 | }; |
@@ -150,12 +142,18 @@ static struct backlight_device *corgi_backlight_device; | |||
150 | 142 | ||
151 | static int __init corgibl_probe(struct device *dev) | 143 | static int __init corgibl_probe(struct device *dev) |
152 | { | 144 | { |
145 | struct corgibl_machinfo *machinfo = dev->platform_data; | ||
146 | |||
147 | corgibl_data.max_brightness = machinfo->max_intensity; | ||
148 | corgibl_mach_set_intensity = machinfo->set_bl_intensity; | ||
149 | |||
153 | corgi_backlight_device = backlight_device_register ("corgi-bl", | 150 | corgi_backlight_device = backlight_device_register ("corgi-bl", |
154 | NULL, &corgibl_data); | 151 | NULL, &corgibl_data); |
155 | if (IS_ERR (corgi_backlight_device)) | 152 | if (IS_ERR (corgi_backlight_device)) |
156 | return PTR_ERR (corgi_backlight_device); | 153 | return PTR_ERR (corgi_backlight_device); |
157 | 154 | ||
158 | corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY); | 155 | corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY); |
156 | corgibl_limit_intensity(0); | ||
159 | 157 | ||
160 | printk("Corgi Backlight Driver Initialized.\n"); | 158 | printk("Corgi Backlight Driver Initialized.\n"); |
161 | return 0; | 159 | return 0; |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 2e93224d2d55..0fc8bb499c3f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -767,7 +767,7 @@ static const char *fbcon_startup(void) | |||
767 | const char *display_desc = "frame buffer device"; | 767 | const char *display_desc = "frame buffer device"; |
768 | struct display *p = &fb_display[fg_console]; | 768 | struct display *p = &fb_display[fg_console]; |
769 | struct vc_data *vc = vc_cons[fg_console].d; | 769 | struct vc_data *vc = vc_cons[fg_console].d; |
770 | struct font_desc *font = NULL; | 770 | const struct font_desc *font = NULL; |
771 | struct module *owner; | 771 | struct module *owner; |
772 | struct fb_info *info = NULL; | 772 | struct fb_info *info = NULL; |
773 | struct fbcon_ops *ops; | 773 | struct fbcon_ops *ops; |
@@ -841,7 +841,7 @@ static const char *fbcon_startup(void) | |||
841 | info->var.yres); | 841 | info->var.yres); |
842 | vc->vc_font.width = font->width; | 842 | vc->vc_font.width = font->width; |
843 | vc->vc_font.height = font->height; | 843 | vc->vc_font.height = font->height; |
844 | vc->vc_font.data = p->fontdata = font->data; | 844 | vc->vc_font.data = (void *)(p->fontdata = font->data); |
845 | vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ | 845 | vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ |
846 | } | 846 | } |
847 | 847 | ||
@@ -941,7 +941,7 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
941 | fb, copy the font from that console */ | 941 | fb, copy the font from that console */ |
942 | t = &fb_display[svc->vc_num]; | 942 | t = &fb_display[svc->vc_num]; |
943 | if (!vc->vc_font.data) { | 943 | if (!vc->vc_font.data) { |
944 | vc->vc_font.data = p->fontdata = t->fontdata; | 944 | vc->vc_font.data = (void *)(p->fontdata = t->fontdata); |
945 | vc->vc_font.width = (*default_mode)->vc_font.width; | 945 | vc->vc_font.width = (*default_mode)->vc_font.width; |
946 | vc->vc_font.height = (*default_mode)->vc_font.height; | 946 | vc->vc_font.height = (*default_mode)->vc_font.height; |
947 | p->userfont = t->userfont; | 947 | p->userfont = t->userfont; |
@@ -1188,7 +1188,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, | |||
1188 | return; | 1188 | return; |
1189 | t = &fb_display[svc->vc_num]; | 1189 | t = &fb_display[svc->vc_num]; |
1190 | if (!vc->vc_font.data) { | 1190 | if (!vc->vc_font.data) { |
1191 | vc->vc_font.data = p->fontdata = t->fontdata; | 1191 | vc->vc_font.data = (void *)(p->fontdata = t->fontdata); |
1192 | vc->vc_font.width = (*default_mode)->vc_font.width; | 1192 | vc->vc_font.width = (*default_mode)->vc_font.width; |
1193 | vc->vc_font.height = (*default_mode)->vc_font.height; | 1193 | vc->vc_font.height = (*default_mode)->vc_font.height; |
1194 | p->userfont = t->userfont; | 1194 | p->userfont = t->userfont; |
@@ -1687,6 +1687,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, | |||
1687 | case SM_DOWN: | 1687 | case SM_DOWN: |
1688 | if (count > vc->vc_rows) /* Maximum realistic size */ | 1688 | if (count > vc->vc_rows) /* Maximum realistic size */ |
1689 | count = vc->vc_rows; | 1689 | count = vc->vc_rows; |
1690 | if (logo_shown >= 0) | ||
1691 | goto redraw_down; | ||
1690 | switch (p->scrollmode) { | 1692 | switch (p->scrollmode) { |
1691 | case SCROLL_MOVE: | 1693 | case SCROLL_MOVE: |
1692 | ops->bmove(vc, info, t, 0, t + count, 0, | 1694 | ops->bmove(vc, info, t, 0, t + count, 0, |
@@ -2148,7 +2150,7 @@ static int fbcon_get_font(struct vc_data *vc, struct console_font *font) | |||
2148 | } | 2150 | } |
2149 | 2151 | ||
2150 | static int fbcon_do_set_font(struct vc_data *vc, int w, int h, | 2152 | static int fbcon_do_set_font(struct vc_data *vc, int w, int h, |
2151 | u8 * data, int userfont) | 2153 | const u8 * data, int userfont) |
2152 | { | 2154 | { |
2153 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 2155 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
2154 | struct display *p = &fb_display[vc->vc_num]; | 2156 | struct display *p = &fb_display[vc->vc_num]; |
@@ -2166,7 +2168,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, | |||
2166 | cnt = FNTCHARCNT(data); | 2168 | cnt = FNTCHARCNT(data); |
2167 | else | 2169 | else |
2168 | cnt = 256; | 2170 | cnt = 256; |
2169 | vc->vc_font.data = p->fontdata = data; | 2171 | vc->vc_font.data = (void *)(p->fontdata = data); |
2170 | if ((p->userfont = userfont)) | 2172 | if ((p->userfont = userfont)) |
2171 | REFCOUNT(data)++; | 2173 | REFCOUNT(data)++; |
2172 | vc->vc_font.width = w; | 2174 | vc->vc_font.width = w; |
@@ -2323,7 +2325,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne | |||
2323 | tmp->vc_font.width == w && | 2325 | tmp->vc_font.width == w && |
2324 | !memcmp(fb_display[i].fontdata, new_data, size)) { | 2326 | !memcmp(fb_display[i].fontdata, new_data, size)) { |
2325 | kfree(new_data - FONT_EXTRA_WORDS * sizeof(int)); | 2327 | kfree(new_data - FONT_EXTRA_WORDS * sizeof(int)); |
2326 | new_data = fb_display[i].fontdata; | 2328 | new_data = (u8 *)fb_display[i].fontdata; |
2327 | break; | 2329 | break; |
2328 | } | 2330 | } |
2329 | } | 2331 | } |
@@ -2333,7 +2335,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne | |||
2333 | static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name) | 2335 | static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name) |
2334 | { | 2336 | { |
2335 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; | 2337 | struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
2336 | struct font_desc *f; | 2338 | const struct font_desc *f; |
2337 | 2339 | ||
2338 | if (!name) | 2340 | if (!name) |
2339 | f = get_default_font(info->var.xres, info->var.yres); | 2341 | f = get_default_font(info->var.xres, info->var.yres); |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 08befafe11d1..0738cd62def2 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -30,7 +30,7 @@ struct display { | |||
30 | /* Filled in by the frame buffer device */ | 30 | /* Filled in by the frame buffer device */ |
31 | u_short inverse; /* != 0 text black on white as default */ | 31 | u_short inverse; /* != 0 text black on white as default */ |
32 | /* Filled in by the low-level console driver */ | 32 | /* Filled in by the low-level console driver */ |
33 | u_char *fontdata; | 33 | const u_char *fontdata; |
34 | int userfont; /* != 0 if fontdata kmalloc()ed */ | 34 | int userfont; /* != 0 if fontdata kmalloc()ed */ |
35 | u_short scrollmode; /* Scroll Method */ | 35 | u_short scrollmode; /* Scroll Method */ |
36 | short yscroll; /* Hardware scrolling */ | 36 | short yscroll; /* Hardware scrolling */ |
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c index ff0af96e4dfc..e6aa0eab5bb6 100644 --- a/drivers/video/console/font_10x18.c +++ b/drivers/video/console/font_10x18.c | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | #define FONTDATAMAX 9216 | 8 | #define FONTDATAMAX 9216 |
9 | 9 | ||
10 | static unsigned char fontdata_10x18[FONTDATAMAX] = { | 10 | static const unsigned char fontdata_10x18[FONTDATAMAX] = { |
11 | 11 | ||
12 | /* 0 0x00 '^@' */ | 12 | /* 0 0x00 '^@' */ |
13 | 0x00, 0x00, /* 0000000000 */ | 13 | 0x00, 0x00, /* 0000000000 */ |
@@ -5132,7 +5132,7 @@ static unsigned char fontdata_10x18[FONTDATAMAX] = { | |||
5132 | }; | 5132 | }; |
5133 | 5133 | ||
5134 | 5134 | ||
5135 | struct font_desc font_10x18 = { | 5135 | const struct font_desc font_10x18 = { |
5136 | FONT10x18_IDX, | 5136 | FONT10x18_IDX, |
5137 | "10x18", | 5137 | "10x18", |
5138 | 10, | 5138 | 10, |
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c index c52f1294044a..89976cd97494 100644 --- a/drivers/video/console/font_6x11.c +++ b/drivers/video/console/font_6x11.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #define FONTDATAMAX (11*256) | 9 | #define FONTDATAMAX (11*256) |
10 | 10 | ||
11 | static unsigned char fontdata_6x11[FONTDATAMAX] = { | 11 | static const unsigned char fontdata_6x11[FONTDATAMAX] = { |
12 | 12 | ||
13 | /* 0 0x00 '^@' */ | 13 | /* 0 0x00 '^@' */ |
14 | 0x00, /* 00000000 */ | 14 | 0x00, /* 00000000 */ |
@@ -3341,7 +3341,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = { | |||
3341 | }; | 3341 | }; |
3342 | 3342 | ||
3343 | 3343 | ||
3344 | struct font_desc font_vga_6x11 = { | 3344 | const struct font_desc font_vga_6x11 = { |
3345 | VGA6x11_IDX, | 3345 | VGA6x11_IDX, |
3346 | "ProFont6x11", | 3346 | "ProFont6x11", |
3347 | 6, | 3347 | 6, |
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c index 1fa7fcf2ff72..bbf116647397 100644 --- a/drivers/video/console/font_7x14.c +++ b/drivers/video/console/font_7x14.c | |||
@@ -7,7 +7,7 @@ | |||
7 | 7 | ||
8 | #define FONTDATAMAX 3584 | 8 | #define FONTDATAMAX 3584 |
9 | 9 | ||
10 | static unsigned char fontdata_7x14[FONTDATAMAX] = { | 10 | static const unsigned char fontdata_7x14[FONTDATAMAX] = { |
11 | 11 | ||
12 | /* 0 0x00 '^@' */ | 12 | /* 0 0x00 '^@' */ |
13 | 0x00, /* 0000000 */ | 13 | 0x00, /* 0000000 */ |
@@ -4108,7 +4108,7 @@ static unsigned char fontdata_7x14[FONTDATAMAX] = { | |||
4108 | }; | 4108 | }; |
4109 | 4109 | ||
4110 | 4110 | ||
4111 | struct font_desc font_7x14 = { | 4111 | const struct font_desc font_7x14 = { |
4112 | FONT7x14_IDX, | 4112 | FONT7x14_IDX, |
4113 | "7x14", | 4113 | "7x14", |
4114 | 7, | 4114 | 7, |
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c index e6f8dbaa122b..74fe86f28ff4 100644 --- a/drivers/video/console/font_8x16.c +++ b/drivers/video/console/font_8x16.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #define FONTDATAMAX 4096 | 9 | #define FONTDATAMAX 4096 |
10 | 10 | ||
11 | static unsigned char fontdata_8x16[FONTDATAMAX] = { | 11 | static const unsigned char fontdata_8x16[FONTDATAMAX] = { |
12 | 12 | ||
13 | /* 0 0x00 '^@' */ | 13 | /* 0 0x00 '^@' */ |
14 | 0x00, /* 00000000 */ | 14 | 0x00, /* 00000000 */ |
@@ -4621,7 +4621,7 @@ static unsigned char fontdata_8x16[FONTDATAMAX] = { | |||
4621 | }; | 4621 | }; |
4622 | 4622 | ||
4623 | 4623 | ||
4624 | struct font_desc font_vga_8x16 = { | 4624 | const struct font_desc font_vga_8x16 = { |
4625 | VGA8x16_IDX, | 4625 | VGA8x16_IDX, |
4626 | "VGA8x16", | 4626 | "VGA8x16", |
4627 | 8, | 4627 | 8, |
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c index 57fbe266a6b9..26199f8ee908 100644 --- a/drivers/video/console/font_8x8.c +++ b/drivers/video/console/font_8x8.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #define FONTDATAMAX 2048 | 9 | #define FONTDATAMAX 2048 |
10 | 10 | ||
11 | static unsigned char fontdata_8x8[FONTDATAMAX] = { | 11 | static const unsigned char fontdata_8x8[FONTDATAMAX] = { |
12 | 12 | ||
13 | /* 0 0x00 '^@' */ | 13 | /* 0 0x00 '^@' */ |
14 | 0x00, /* 00000000 */ | 14 | 0x00, /* 00000000 */ |
@@ -2573,7 +2573,7 @@ static unsigned char fontdata_8x8[FONTDATAMAX] = { | |||
2573 | }; | 2573 | }; |
2574 | 2574 | ||
2575 | 2575 | ||
2576 | struct font_desc font_vga_8x8 = { | 2576 | const struct font_desc font_vga_8x8 = { |
2577 | VGA8x8_IDX, | 2577 | VGA8x8_IDX, |
2578 | "VGA8x8", | 2578 | "VGA8x8", |
2579 | 8, | 2579 | 8, |
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c index d565505e3069..2d2e39632e2d 100644 --- a/drivers/video/console/font_acorn_8x8.c +++ b/drivers/video/console/font_acorn_8x8.c | |||
@@ -3,7 +3,7 @@ | |||
3 | #include <linux/config.h> | 3 | #include <linux/config.h> |
4 | #include <linux/font.h> | 4 | #include <linux/font.h> |
5 | 5 | ||
6 | static unsigned char acorndata_8x8[] = { | 6 | static const unsigned char acorndata_8x8[] = { |
7 | /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */ | 7 | /* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */ |
8 | /* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */ | 8 | /* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */ |
9 | /* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */ | 9 | /* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */ |
@@ -262,7 +262,7 @@ static unsigned char acorndata_8x8[] = { | |||
262 | /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | 262 | /* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
263 | }; | 263 | }; |
264 | 264 | ||
265 | struct font_desc font_acorn_8x8 = { | 265 | const struct font_desc font_acorn_8x8 = { |
266 | ACORN8x8_IDX, | 266 | ACORN8x8_IDX, |
267 | "Acorn8x8", | 267 | "Acorn8x8", |
268 | 8, | 268 | 8, |
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c index 593b95500a0c..d818234fdf11 100644 --- a/drivers/video/console/font_mini_4x6.c +++ b/drivers/video/console/font_mini_4x6.c | |||
@@ -43,7 +43,7 @@ __END__; | |||
43 | 43 | ||
44 | #define FONTDATAMAX 1536 | 44 | #define FONTDATAMAX 1536 |
45 | 45 | ||
46 | static unsigned char fontdata_mini_4x6[FONTDATAMAX] = { | 46 | static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = { |
47 | 47 | ||
48 | /*{*/ | 48 | /*{*/ |
49 | /* Char 0: ' ' */ | 49 | /* Char 0: ' ' */ |
@@ -2147,7 +2147,7 @@ static unsigned char fontdata_mini_4x6[FONTDATAMAX] = { | |||
2147 | /*}*/ | 2147 | /*}*/ |
2148 | }; | 2148 | }; |
2149 | 2149 | ||
2150 | struct font_desc font_mini_4x6 = { | 2150 | const struct font_desc font_mini_4x6 = { |
2151 | MINI4x6_IDX, | 2151 | MINI4x6_IDX, |
2152 | "MINI4x6", | 2152 | "MINI4x6", |
2153 | 4, | 2153 | 4, |
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c index 5fa95f118818..e646c88f55c7 100644 --- a/drivers/video/console/font_pearl_8x8.c +++ b/drivers/video/console/font_pearl_8x8.c | |||
@@ -13,7 +13,7 @@ | |||
13 | 13 | ||
14 | #define FONTDATAMAX 2048 | 14 | #define FONTDATAMAX 2048 |
15 | 15 | ||
16 | static unsigned char fontdata_pearl8x8[FONTDATAMAX] = { | 16 | static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = { |
17 | 17 | ||
18 | /* 0 0x00 '^@' */ | 18 | /* 0 0x00 '^@' */ |
19 | 0x00, /* 00000000 */ | 19 | 0x00, /* 00000000 */ |
@@ -2577,7 +2577,7 @@ static unsigned char fontdata_pearl8x8[FONTDATAMAX] = { | |||
2577 | 2577 | ||
2578 | }; | 2578 | }; |
2579 | 2579 | ||
2580 | struct font_desc font_pearl_8x8 = { | 2580 | const struct font_desc font_pearl_8x8 = { |
2581 | PEARL8x8_IDX, | 2581 | PEARL8x8_IDX, |
2582 | "PEARL8x8", | 2582 | "PEARL8x8", |
2583 | 8, | 2583 | 8, |
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c index c7bd967ea100..ab5eb93407b4 100644 --- a/drivers/video/console/font_sun12x22.c +++ b/drivers/video/console/font_sun12x22.c | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | #define FONTDATAMAX 11264 | 3 | #define FONTDATAMAX 11264 |
4 | 4 | ||
5 | static unsigned char fontdata_sun12x22[FONTDATAMAX] = { | 5 | static const unsigned char fontdata_sun12x22[FONTDATAMAX] = { |
6 | 6 | ||
7 | /* 0 0x00 '^@' */ | 7 | /* 0 0x00 '^@' */ |
8 | 0x00, 0x00, /* 000000000000 */ | 8 | 0x00, 0x00, /* 000000000000 */ |
@@ -6151,7 +6151,7 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = { | |||
6151 | }; | 6151 | }; |
6152 | 6152 | ||
6153 | 6153 | ||
6154 | struct font_desc font_sun_12x22 = { | 6154 | const struct font_desc font_sun_12x22 = { |
6155 | SUN12x22_IDX, | 6155 | SUN12x22_IDX, |
6156 | "SUN12x22", | 6156 | "SUN12x22", |
6157 | 12, | 6157 | 12, |
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c index 2af3ab354652..41f910f5529c 100644 --- a/drivers/video/console/font_sun8x16.c +++ b/drivers/video/console/font_sun8x16.c | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | #define FONTDATAMAX 4096 | 3 | #define FONTDATAMAX 4096 |
4 | 4 | ||
5 | static unsigned char fontdata_sun8x16[FONTDATAMAX] = { | 5 | static const unsigned char fontdata_sun8x16[FONTDATAMAX] = { |
6 | /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | 6 | /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
7 | /* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, | 7 | /* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, |
8 | /* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, | 8 | /* */ 0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, |
@@ -261,7 +261,7 @@ static unsigned char fontdata_sun8x16[FONTDATAMAX] = { | |||
261 | /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, | 261 | /* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
262 | }; | 262 | }; |
263 | 263 | ||
264 | struct font_desc font_sun_8x16 = { | 264 | const struct font_desc font_sun_8x16 = { |
265 | SUN8x16_IDX, | 265 | SUN8x16_IDX, |
266 | "SUN8x16", | 266 | "SUN8x16", |
267 | 8, | 267 | 8, |
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index e79b29702649..4fd07d9eca03 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | #define NO_FONTS | 24 | #define NO_FONTS |
25 | 25 | ||
26 | static struct font_desc *fonts[] = { | 26 | static const struct font_desc *fonts[] = { |
27 | #ifdef CONFIG_FONT_8x8 | 27 | #ifdef CONFIG_FONT_8x8 |
28 | #undef NO_FONTS | 28 | #undef NO_FONTS |
29 | &font_vga_8x8, | 29 | &font_vga_8x8, |
@@ -84,7 +84,7 @@ static struct font_desc *fonts[] = { | |||
84 | * | 84 | * |
85 | */ | 85 | */ |
86 | 86 | ||
87 | struct font_desc *find_font(char *name) | 87 | const struct font_desc *find_font(const char *name) |
88 | { | 88 | { |
89 | unsigned int i; | 89 | unsigned int i; |
90 | 90 | ||
@@ -108,10 +108,10 @@ struct font_desc *find_font(char *name) | |||
108 | * | 108 | * |
109 | */ | 109 | */ |
110 | 110 | ||
111 | struct font_desc *get_default_font(int xres, int yres) | 111 | const struct font_desc *get_default_font(int xres, int yres) |
112 | { | 112 | { |
113 | int i, c, cc; | 113 | int i, c, cc; |
114 | struct font_desc *f, *g; | 114 | const struct font_desc *f, *g; |
115 | 115 | ||
116 | g = NULL; | 116 | g = NULL; |
117 | cc = -10000; | 117 | cc = -10000; |
@@ -138,7 +138,6 @@ struct font_desc *get_default_font(int xres, int yres) | |||
138 | return g; | 138 | return g; |
139 | } | 139 | } |
140 | 140 | ||
141 | EXPORT_SYMBOL(fonts); | ||
142 | EXPORT_SYMBOL(find_font); | 141 | EXPORT_SYMBOL(find_font); |
143 | EXPORT_SYMBOL(get_default_font); | 142 | EXPORT_SYMBOL(get_default_font); |
144 | 143 | ||
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 0705cd741411..6ef6f7760e47 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1020,7 +1020,9 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) | |||
1020 | static int vgacon_resize(struct vc_data *c, unsigned int width, | 1020 | static int vgacon_resize(struct vc_data *c, unsigned int width, |
1021 | unsigned int height) | 1021 | unsigned int height) |
1022 | { | 1022 | { |
1023 | if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES) | 1023 | if (width % 2 || width > ORIG_VIDEO_COLS || |
1024 | height > (ORIG_VIDEO_LINES * vga_default_font_height)/ | ||
1025 | c->vc_font.height) | ||
1024 | return -EINVAL; | 1026 | return -EINVAL; |
1025 | 1027 | ||
1026 | if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */ | 1028 | if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */ |
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index cabd53cec991..6c2244cf0e74 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -425,7 +425,7 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi) | |||
425 | * Power management hooks. Note that we won't be called from IRQ context, | 425 | * Power management hooks. Note that we won't be called from IRQ context, |
426 | * unlike the blank functions above, so we may sleep. | 426 | * unlike the blank functions above, so we may sleep. |
427 | */ | 427 | */ |
428 | static int imxfb_suspend(struct device *dev, u32 state, u32 level) | 428 | static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level) |
429 | { | 429 | { |
430 | struct imxfb_info *fbi = dev_get_drvdata(dev); | 430 | struct imxfb_info *fbi = dev_get_drvdata(dev); |
431 | pr_debug("%s\n",__FUNCTION__); | 431 | pr_debug("%s\n",__FUNCTION__); |
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 98e00d8601e5..e02da41f1b26 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c | |||
@@ -1285,7 +1285,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi | |||
1285 | vaddr_t vm; | 1285 | vaddr_t vm; |
1286 | unsigned int offs; | 1286 | unsigned int offs; |
1287 | unsigned int offs2; | 1287 | unsigned int offs2; |
1288 | unsigned char store; | 1288 | unsigned char store, orig; |
1289 | unsigned char bytes[32]; | 1289 | unsigned char bytes[32]; |
1290 | unsigned char* tmp; | 1290 | unsigned char* tmp; |
1291 | 1291 | ||
@@ -1298,7 +1298,8 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi | |||
1298 | if (maxSize > 0x2000000) maxSize = 0x2000000; | 1298 | if (maxSize > 0x2000000) maxSize = 0x2000000; |
1299 | 1299 | ||
1300 | mga_outb(M_EXTVGA_INDEX, 0x03); | 1300 | mga_outb(M_EXTVGA_INDEX, 0x03); |
1301 | mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80); | 1301 | orig = mga_inb(M_EXTVGA_DATA); |
1302 | mga_outb(M_EXTVGA_DATA, orig | 0x80); | ||
1302 | 1303 | ||
1303 | store = mga_readb(vm, 0x1234); | 1304 | store = mga_readb(vm, 0x1234); |
1304 | tmp = bytes; | 1305 | tmp = bytes; |
@@ -1323,7 +1324,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi | |||
1323 | mga_writeb(vm, 0x1234, store); | 1324 | mga_writeb(vm, 0x1234, store); |
1324 | 1325 | ||
1325 | mga_outb(M_EXTVGA_INDEX, 0x03); | 1326 | mga_outb(M_EXTVGA_INDEX, 0x03); |
1326 | mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80); | 1327 | mga_outb(M_EXTVGA_DATA, orig); |
1327 | 1328 | ||
1328 | *realSize = offs - 0x100000; | 1329 | *realSize = offs - 0x100000; |
1329 | #ifdef CONFIG_FB_MATROX_MILLENIUM | 1330 | #ifdef CONFIG_FB_MATROX_MILLENIUM |
@@ -1858,6 +1859,8 @@ static int initMatrox2(WPMINFO struct board* b){ | |||
1858 | to yres_virtual * xres_virtual < 2^32 */ | 1859 | to yres_virtual * xres_virtual < 2^32 */ |
1859 | } | 1860 | } |
1860 | matroxfb_init_fix(PMINFO2); | 1861 | matroxfb_init_fix(PMINFO2); |
1862 | ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase)); | ||
1863 | matroxfb_update_fix(PMINFO2); | ||
1861 | /* Normalize values (namely yres_virtual) */ | 1864 | /* Normalize values (namely yres_virtual) */ |
1862 | matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); | 1865 | matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon)); |
1863 | /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over | 1866 | /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over |
@@ -2010,11 +2013,11 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm | |||
2010 | } | 2013 | } |
2011 | /* not match... */ | 2014 | /* not match... */ |
2012 | if (!b->vendor) | 2015 | if (!b->vendor) |
2013 | return -1; | 2016 | return -ENODEV; |
2014 | if (dev > 0) { | 2017 | if (dev > 0) { |
2015 | /* not requested one... */ | 2018 | /* not requested one... */ |
2016 | dev--; | 2019 | dev--; |
2017 | return -1; | 2020 | return -ENODEV; |
2018 | } | 2021 | } |
2019 | pci_read_config_dword(pdev, PCI_COMMAND, &cmd); | 2022 | pci_read_config_dword(pdev, PCI_COMMAND, &cmd); |
2020 | if (pci_enable_device(pdev)) { | 2023 | if (pci_enable_device(pdev)) { |
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index ace484fa61ce..12f2884d3f0b 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c | |||
@@ -209,10 +209,13 @@ int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) | |||
209 | 209 | ||
210 | if (!edid && conn == 1) { | 210 | if (!edid && conn == 1) { |
211 | /* try to get from firmware */ | 211 | /* try to get from firmware */ |
212 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | 212 | const u8 *e = fb_firmware_edid(info->device); |
213 | if (edid) | 213 | |
214 | memcpy(edid, fb_firmware_edid(info->device), | 214 | if (e != NULL) { |
215 | EDID_LENGTH); | 215 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); |
216 | if (edid) | ||
217 | memcpy(edid, e, EDID_LENGTH); | ||
218 | } | ||
216 | } | 219 | } |
217 | 220 | ||
218 | if (out_edid) | 221 | if (out_edid) |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index e0dad948467b..2e11b601c488 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #include <linux/init.h> | 67 | #include <linux/init.h> |
68 | #include <linux/pci.h> | 68 | #include <linux/pci.h> |
69 | #include <linux/ioport.h> | 69 | #include <linux/ioport.h> |
70 | #include <linux/ctype.h> | ||
70 | 71 | ||
71 | #include <video/fbcon.h> | 72 | #include <video/fbcon.h> |
72 | #include <video/fbcon-mfb.h> | 73 | #include <video/fbcon-mfb.h> |
@@ -2594,7 +2595,7 @@ static char *pm3fb_boardnum_setup(char *options, unsigned long *bn) | |||
2594 | { | 2595 | { |
2595 | char *next; | 2596 | char *next; |
2596 | 2597 | ||
2597 | if (!(CHAR_IS_NUM(options[0]))) { | 2598 | if (!(isdigit(options[0]))) { |
2598 | (*bn) = 0; | 2599 | (*bn) = 0; |
2599 | return (options); | 2600 | return (options); |
2600 | } | 2601 | } |
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c index 959404ad68f4..3c98457783c4 100644 --- a/drivers/video/savage/savagefb-i2c.c +++ b/drivers/video/savage/savagefb-i2c.c | |||
@@ -274,10 +274,13 @@ int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid) | |||
274 | 274 | ||
275 | if (!edid) { | 275 | if (!edid) { |
276 | /* try to get from firmware */ | 276 | /* try to get from firmware */ |
277 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | 277 | const u8 *e = fb_firmware_edid(info->device); |
278 | if (edid) | 278 | |
279 | memcpy(edid, fb_firmware_edid(info->device), | 279 | if (e) { |
280 | EDID_LENGTH); | 280 | edid = kmalloc(EDID_LENGTH, GFP_KERNEL); |
281 | if (edid) | ||
282 | memcpy(edid, e, EDID_LENGTH); | ||
283 | } | ||
281 | } | 284 | } |
282 | 285 | ||
283 | if (out_edid) | 286 | if (out_edid) |
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h index d6f94742c9f2..ea17f7e0482c 100644 --- a/drivers/video/savage/savagefb.h +++ b/drivers/video/savage/savagefb.h | |||
@@ -60,8 +60,6 @@ | |||
60 | 60 | ||
61 | #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) | 61 | #define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) |
62 | 62 | ||
63 | #define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR)) | ||
64 | |||
65 | /* Chip tags. These are used to group the adapters into | 63 | /* Chip tags. These are used to group the adapters into |
66 | * related families. | 64 | * related families. |
67 | */ | 65 | */ |
@@ -74,8 +72,6 @@ typedef enum { | |||
74 | S3_PROSAVAGE, | 72 | S3_PROSAVAGE, |
75 | S3_SUPERSAVAGE, | 73 | S3_SUPERSAVAGE, |
76 | S3_SAVAGE2000, | 74 | S3_SAVAGE2000, |
77 | S3_PROSAVAGEDDR, | ||
78 | S3_TWISTER, | ||
79 | S3_LAST | 75 | S3_LAST |
80 | } savage_chipset; | 76 | } savage_chipset; |
81 | 77 | ||
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index b5ca3ef8271f..7c285455c924 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c | |||
@@ -1773,8 +1773,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par) | |||
1773 | } | 1773 | } |
1774 | } | 1774 | } |
1775 | 1775 | ||
1776 | if (S3_SAVAGE_MOBILE_SERIES(par->chip) || | 1776 | if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly) |
1777 | (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly)) | ||
1778 | par->display_type = DISP_LCD; | 1777 | par->display_type = DISP_LCD; |
1779 | else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) | 1778 | else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi)) |
1780 | par->display_type = DISP_DFP; | 1779 | par->display_type = DISP_DFP; |
@@ -1783,7 +1782,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par) | |||
1783 | 1782 | ||
1784 | /* Check LCD panel parrmation */ | 1783 | /* Check LCD panel parrmation */ |
1785 | 1784 | ||
1786 | if (par->chip == S3_SAVAGE_MX) { | 1785 | if (par->display_type == DISP_LCD) { |
1787 | unsigned char cr6b = VGArCR( 0x6b ); | 1786 | unsigned char cr6b = VGArCR( 0x6b ); |
1788 | 1787 | ||
1789 | int panelX = (VGArSEQ (0x61) + | 1788 | int panelX = (VGArSEQ (0x61) + |
@@ -1922,15 +1921,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info, | |||
1922 | snprintf (info->fix.id, 16, "ProSavageKM"); | 1921 | snprintf (info->fix.id, 16, "ProSavageKM"); |
1923 | break; | 1922 | break; |
1924 | case FB_ACCEL_S3TWISTER_P: | 1923 | case FB_ACCEL_S3TWISTER_P: |
1925 | par->chip = S3_TWISTER; | 1924 | par->chip = S3_PROSAVAGE; |
1926 | snprintf (info->fix.id, 16, "TwisterP"); | 1925 | snprintf (info->fix.id, 16, "TwisterP"); |
1927 | break; | 1926 | break; |
1928 | case FB_ACCEL_S3TWISTER_K: | 1927 | case FB_ACCEL_S3TWISTER_K: |
1929 | par->chip = S3_TWISTER; | 1928 | par->chip = S3_PROSAVAGE; |
1930 | snprintf (info->fix.id, 16, "TwisterK"); | 1929 | snprintf (info->fix.id, 16, "TwisterK"); |
1931 | break; | 1930 | break; |
1932 | case FB_ACCEL_PROSAVAGE_DDR: | 1931 | case FB_ACCEL_PROSAVAGE_DDR: |
1933 | par->chip = S3_PROSAVAGEDDR; | 1932 | par->chip = S3_PROSAVAGE; |
1934 | snprintf (info->fix.id, 16, "ProSavageDDR"); | 1933 | snprintf (info->fix.id, 16, "ProSavageDDR"); |
1935 | break; | 1934 | break; |
1936 | case FB_ACCEL_PROSAVAGE_DDRK: | 1935 | case FB_ACCEL_PROSAVAGE_DDRK: |