summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/attribute_container.c5
-rw-r--r--drivers/base/class.c10
-rw-r--r--drivers/base/firmware_class.c9
-rw-r--r--drivers/base/map.c3
-rw-r--r--drivers/base/platform.c3
-rw-r--r--drivers/block/cciss.c639
-rw-r--r--drivers/block/cciss.h10
-rw-r--r--drivers/block/cciss_cmd.h8
-rw-r--r--drivers/block/cciss_scsi.c69
-rw-r--r--drivers/block/paride/pf.c22
-rw-r--r--drivers/block/pktcdvd.c85
-rw-r--r--drivers/block/scsi_ioctl.c1
-rw-r--r--drivers/bluetooth/hci_usb.c19
-rw-r--r--drivers/bluetooth/hci_usb.h5
-rw-r--r--drivers/char/agp/hp-agp.c2
-rw-r--r--drivers/char/amiserial.c4
-rw-r--r--drivers/char/epca.c84
-rw-r--r--drivers/char/epca.h12
-rw-r--r--drivers/char/hvc_console.c6
-rw-r--r--drivers/char/vt.c5
-rw-r--r--drivers/char/watchdog/Kconfig93
-rw-r--r--drivers/char/watchdog/Makefile7
-rw-r--r--drivers/char/watchdog/i6300esb.c527
-rw-r--r--drivers/char/watchdog/ibmasr.c405
-rw-r--r--drivers/char/watchdog/mpcore_wdt.c2
-rw-r--r--drivers/char/watchdog/mv64x60_wdt.c252
-rw-r--r--drivers/char/watchdog/pcwd_pci.c44
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c2
-rw-r--r--drivers/char/watchdog/sbc8360.c414
-rw-r--r--drivers/char/watchdog/w83977f_wdt.c543
-rw-r--r--drivers/firmware/dell_rbu.c241
-rw-r--r--drivers/hwmon/hdaps.c356
-rw-r--r--drivers/i2c/busses/i2c-keywest.c1
-rw-r--r--drivers/i2c/busses/i2c-pxa.c12
-rw-r--r--drivers/ide/ide-iops.c41
-rw-r--r--drivers/ide/ide-taskfile.c1
-rw-r--r--drivers/ide/pci/cmd64x.c2
-rw-r--r--drivers/ide/pci/hpt34x.c2
-rw-r--r--drivers/input/keyboard/Kconfig11
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/spitzkbd.c478
-rw-r--r--drivers/input/touchscreen/Kconfig6
-rw-r--r--drivers/input/touchscreen/corgi_ts.c70
-rw-r--r--drivers/isdn/hisax/hfc_pci.c1
-rw-r--r--drivers/isdn/hisax/sedlbauer_cs.c2
-rw-r--r--drivers/isdn/hisax/st5481.h4
-rw-r--r--drivers/isdn/hisax/st5481_b.c22
-rw-r--r--drivers/isdn/hisax/st5481_d.c26
-rw-r--r--drivers/isdn/hisax/st5481_init.c4
-rw-r--r--drivers/isdn/hisax/st5481_usb.c70
-rw-r--r--drivers/isdn/sc/init.c4
-rw-r--r--drivers/md/raid6.h4
-rw-r--r--drivers/md/raid6algos.c1
-rw-r--r--drivers/md/raid6altivec.uc18
-rw-r--r--drivers/md/raid6test/Makefile27
-rw-r--r--drivers/media/radio/radio-aimslab.c2
-rw-r--r--drivers/media/radio/radio-aztech.c2
-rw-r--r--drivers/media/radio/radio-cadet.c2
-rw-r--r--drivers/media/radio/radio-gemtek.c2
-rw-r--r--drivers/media/radio/radio-rtrack2.c2
-rw-r--r--drivers/media/radio/radio-sf16fmi.c2
-rw-r--r--drivers/media/radio/radio-sf16fmr2.c2
-rw-r--r--drivers/media/radio/radio-terratec.c2
-rw-r--r--drivers/media/radio/radio-typhoon.c2
-rw-r--r--drivers/media/radio/radio-zoltrix.c2
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c7
-rw-r--r--drivers/mtd/maps/sharpsl-flash.c2
-rw-r--r--drivers/mtd/nand/sharpsl.c10
-rw-r--r--drivers/net/8139cp.c46
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/arcnet/com90io.c4
-rw-r--r--drivers/net/bonding/bond_main.c11
-rw-r--r--drivers/net/e100.c4
-rw-r--r--drivers/net/e1000/e1000_main.c1
-rw-r--r--drivers/net/ixgb/ixgb_main.c2
-rw-r--r--drivers/net/s2io.c9
-rw-r--r--drivers/net/sk98lin/skge.c12
-rw-r--r--drivers/net/skge.c98
-rw-r--r--drivers/net/skge.h2
-rw-r--r--drivers/net/spider_net.c4
-rw-r--r--drivers/net/tg3.c108
-rw-r--r--drivers/net/tulip/xircom_cb.c2
-rw-r--r--drivers/net/wan/hdlc_cisco.c2
-rw-r--r--drivers/net/wireless/airo.c5
-rw-r--r--drivers/net/wireless/orinoco_cs.c1
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c2
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c4
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c3
-rw-r--r--drivers/pci/pci.c16
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c12
-rw-r--r--drivers/pcmcia/yenta_socket.c13
-rw-r--r--drivers/s390/cio/blacklist.c4
-rw-r--r--drivers/s390/crypto/z90main.c3
-rw-r--r--drivers/s390/net/ctcmain.c41
-rw-r--r--drivers/s390/net/qeth.h4
-rw-r--r--drivers/s390/net/qeth_main.c133
-rw-r--r--drivers/s390/net/qeth_sys.c17
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/scsi/libata-core.c37
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c21
-rw-r--r--drivers/scsi/sata_sis.c4
-rw-r--r--drivers/serial/21285.c2
-rw-r--r--drivers/serial/amba-pl010.c2
-rw-r--r--drivers/serial/amba-pl011.c2
-rw-r--r--drivers/serial/clps711x.c2
-rw-r--r--drivers/serial/mpc52xx_uart.c2
-rw-r--r--drivers/serial/pxa.c4
-rw-r--r--drivers/serial/sa1100.c2
-rw-r--r--drivers/serial/serial_lh7a40x.c2
-rw-r--r--drivers/tc/zs.c2
-rw-r--r--drivers/video/Kconfig3
-rw-r--r--drivers/video/backlight/corgi_bl.c34
-rw-r--r--drivers/video/console/fbcon.c18
-rw-r--r--drivers/video/console/fbcon.h2
-rw-r--r--drivers/video/console/font_10x18.c4
-rw-r--r--drivers/video/console/font_6x11.c4
-rw-r--r--drivers/video/console/font_7x14.c4
-rw-r--r--drivers/video/console/font_8x16.c4
-rw-r--r--drivers/video/console/font_8x8.c4
-rw-r--r--drivers/video/console/font_acorn_8x8.c4
-rw-r--r--drivers/video/console/font_mini_4x6.c4
-rw-r--r--drivers/video/console/font_pearl_8x8.c4
-rw-r--r--drivers/video/console/font_sun12x22.c4
-rw-r--r--drivers/video/console/font_sun8x16.c4
-rw-r--r--drivers/video/console/fonts.c9
-rw-r--r--drivers/video/console/vgacon.c4
-rw-r--r--drivers/video/imxfb.c2
-rw-r--r--drivers/video/matrox/matroxfb_base.c13
-rw-r--r--drivers/video/nvidia/nv_i2c.c11
-rw-r--r--drivers/video/pm3fb.c3
-rw-r--r--drivers/video/savage/savagefb-i2c.c11
-rw-r--r--drivers/video/savage/savagefb.h4
-rw-r--r--drivers/video/savage/savagefb_driver.c11
133 files changed, 4290 insertions, 1258 deletions
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 373e7b7..6b2eb6f 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -152,12 +152,13 @@ attribute_container_add_device(struct device *dev,
if (!cont->match(cont, dev))
continue;
- ic = kmalloc(sizeof(struct internal_container), GFP_KERNEL);
+
+ ic = kzalloc(sizeof(*ic), GFP_KERNEL);
if (!ic) {
dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
continue;
}
- memset(ic, 0, sizeof(struct internal_container));
+
ic->cont = cont;
class_device_initialize(&ic->classdev);
ic->classdev.dev = get_device(dev);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d164c32..3b112e3 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -189,12 +189,11 @@ struct class *class_create(struct module *owner, char *name)
struct class *cls;
int retval;
- cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+ cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
- memset(cls, 0x00, sizeof(struct class));
cls->name = name;
cls->owner = owner;
@@ -500,13 +499,13 @@ int class_device_add(struct class_device *class_dev)
/* add the needed attributes to this device */
if (MAJOR(class_dev->devt)) {
struct class_device_attribute *attr;
- attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr) {
error = -ENOMEM;
kobject_del(&class_dev->kobj);
goto register_done;
}
- memset(attr, sizeof(*attr), 0x00);
+
attr->attr.name = "dev";
attr->attr.mode = S_IRUGO;
attr->attr.owner = parent->owner;
@@ -577,12 +576,11 @@ struct class_device *class_device_create(struct class *cls, dev_t devt,
if (cls == NULL || IS_ERR(cls))
goto error;
- class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+ class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
if (!class_dev) {
retval = -ENOMEM;
goto error;
}
- memset(class_dev, 0x00, sizeof(struct class_device));
class_dev->devt = devt;
class_dev->dev = device;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 5bfa2e9..4acb2c5 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,
const char *fw_name, struct device *device)
{
int retval;
- struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
+ struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv),
GFP_KERNEL);
- struct class_device *class_dev = kmalloc(sizeof (struct class_device),
+ struct class_device *class_dev = kzalloc(sizeof(*class_dev),
GFP_KERNEL);
*class_dev_p = NULL;
@@ -313,8 +313,6 @@ fw_register_class_device(struct class_device **class_dev_p,
retval = -ENOMEM;
goto error_kfree;
}
- memset(fw_priv, 0, sizeof (*fw_priv));
- memset(class_dev, 0, sizeof (*class_dev));
init_completion(&fw_priv->completion);
fw_priv->attr_data = firmware_attr_data_tmpl;
@@ -402,14 +400,13 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
if (!firmware_p)
return -EINVAL;
- *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
+ *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL);
if (!firmware) {
printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
__FUNCTION__);
retval = -ENOMEM;
goto out;
}
- memset(firmware, 0, sizeof (*firmware));
retval = fw_setup_class_device(firmware, &class_dev, name, device,
hotplug);
diff --git a/drivers/base/map.c b/drivers/base/map.c
index 2f455d8..b449dae 100644
--- a/drivers/base/map.c
+++ b/drivers/base/map.c
@@ -135,7 +135,7 @@ retry:
struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
{
struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
- struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
+ struct probe *base = kzalloc(sizeof(*base), GFP_KERNEL);
int i;
if ((p == NULL) || (base == NULL)) {
@@ -144,7 +144,6 @@ struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
return NULL;
}
- memset(base, 0, sizeof(struct probe));
base->dev = 1;
base->range = ~0;
base->get = base_probe;
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 3a5f4c9..361e204 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
struct platform_object *pobj;
int retval;
- pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL);
+ pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL);
if (!pobj) {
retval = -ENOMEM;
goto error;
}
- memset(pobj, 0, sizeof(*pobj));
pobj->pdev.name = name;
pobj->pdev.id = id;
pobj->pdev.dev.release = platform_device_release_simple;
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 28f2c17..c56f995 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -47,14 +47,14 @@
#include <linux/completion.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.6)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.8)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,8)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.8");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
- " SA6i P600 P800 E400 E300");
+ " SA6i P600 P800 P400 P400i E200 E200i");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -83,12 +83,22 @@ static const struct pci_device_id cciss_pci_device_id[] = {
0x0E11, 0x4091, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
0x103C, 0x3225, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
0x103c, 0x3223, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3231, 0, 0, 0},
+ 0x103c, 0x3234, 0, 0, 0},
{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3233, 0, 0, 0},
+ 0x103c, 0x3235, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3211, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3212, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3213, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3214, 0, 0, 0},
+ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD,
+ 0x103c, 0x3215, 0, 0, 0},
{0,}
};
MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -111,8 +121,13 @@ static struct board_type products[] = {
{ 0x40910E11, "Smart Array 6i", &SA5_access},
{ 0x3225103C, "Smart Array P600", &SA5_access},
{ 0x3223103C, "Smart Array P800", &SA5_access},
- { 0x3231103C, "Smart Array E400", &SA5_access},
- { 0x3233103C, "Smart Array E300", &SA5_access},
+ { 0x3234103C, "Smart Array P400", &SA5_access},
+ { 0x3235103C, "Smart Array P400i", &SA5_access},
+ { 0x3211103C, "Smart Array E200i", &SA5_access},
+ { 0x3212103C, "Smart Array E200", &SA5_access},
+ { 0x3213103C, "Smart Array E200i", &SA5_access},
+ { 0x3214103C, "Smart Array E200i", &SA5_access},
+ { 0x3215103C, "Smart Array E200i", &SA5_access},
};
/* 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,
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
-static int deregister_disk(struct gendisk *disk);
-static int register_new_disk(ctlr_info_t *h);
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv, int clear_all);
+static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
+ int withirq, unsigned int *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+ int withirq, unsigned int total_size,
+ unsigned int block_size, InquiryData_struct *inq_buff,
+ drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
static void start_io( ctlr_info_t *h);
static int sendcmd( __u8 cmd, int ctlr, void *buff, size_t size,
unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
unsigned char *scsi3addr, int cmd_type);
+static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size,
+ unsigned int use_unit_num, unsigned int log_unit, __u8 page_code,
+ int cmd_type);
+
+static void fail_all_cmds(unsigned long ctlr);
#ifdef CONFIG_PROC_FS
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,
for(i=0; i<=h->highest_lun; i++) {
drv = &h->drv[i];
- if (drv->block_size == 0)
+ if (drv->heads == 0)
continue;
vol_sz = drv->nr_blocks;
@@ -363,6 +389,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
return NULL;
memset(c, 0, sizeof(CommandList_struct));
+ c->cmdindex = -1;
+
c->err_info = (ErrorInfo_struct *)pci_alloc_consistent(
h->pdev, sizeof(ErrorInfo_struct),
&err_dma_handle);
@@ -393,6 +421,8 @@ static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
err_dma_handle = h->errinfo_pool_dhandle
+ i*sizeof(ErrorInfo_struct);
h->nr_allocs++;
+
+ c->cmdindex = i;
}
c->busaddr = (__u32) cmd_dma_handle;
@@ -453,6 +483,11 @@ static int cciss_open(struct inode *inode, struct file *filep)
printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
#endif /* CCISS_DEBUG */
+ if (host->busy_initializing)
+ return -EBUSY;
+
+ if (host->busy_initializing || drv->busy_configuring)
+ return -EBUSY;
/*
* Root is allowed to open raw volume zero even if it's not configured
* 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,
return(0);
}
case CCISS_DEREGDISK:
- return deregister_disk(disk);
+ return rebuild_lun_table(host, disk);
case CCISS_REGNEWD:
- return register_new_disk(host);
+ return rebuild_lun_table(host, NULL);
case CCISS_PASSTHRU:
{
@@ -1143,48 +1178,323 @@ static int revalidate_allvol(ctlr_info_t *host)
return 0;
}
-static int deregister_disk(struct gendisk *disk)
+/* This function will check the usage_count of the drive to be updated/added.
+ * If the usage_count is zero then the drive information will be updated and
+ * the disk will be re-registered with the kernel. If not then it will be
+ * left alone for the next reboot. The exception to this is disk 0 which
+ * will always be left registered with the kernel since it is also the
+ * controller node. Any changes to disk 0 will show up on the next
+ * reboot.
+*/
+static void cciss_update_drive_info(int ctlr, int drv_index)
+ {
+ ctlr_info_t *h = hba[ctlr];
+ struct gendisk *disk;
+ ReadCapdata_struct *size_buff = NULL;
+ InquiryData_struct *inq_buff = NULL;
+ unsigned int block_size;
+ unsigned int total_size;
+ unsigned long flags = 0;
+ int ret = 0;
+
+ /* if the disk already exists then deregister it before proceeding*/
+ if (h->drv[drv_index].raid_level != -1){
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ h->drv[drv_index].busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ ret = deregister_disk(h->gendisk[drv_index],
+ &h->drv[drv_index], 0);
+ h->drv[drv_index].busy_configuring = 0;
+ }
+
+ /* If the disk is in use return */
+ if (ret)
+ return;
+
+
+ /* Get information about the disk and modify the driver sturcture */
+ size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
+ if (size_buff == NULL)
+ goto mem_msg;
+ inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ if (inq_buff == NULL)
+ goto mem_msg;
+
+ cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+ &total_size, &block_size);
+ cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
+ inq_buff, &h->drv[drv_index]);
+
+ ++h->num_luns;
+ disk = h->gendisk[drv_index];
+ set_capacity(disk, h->drv[drv_index].nr_blocks);
+
+
+ /* if it's the controller it's already added */
+ if (drv_index){
+ disk->queue = blk_init_queue(do_cciss_request, &h->lock);
+
+ /* Set up queue information */
+ disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
+ blk_queue_bounce_limit(disk->queue, hba[ctlr]->pdev->dma_mask);
+
+ /* This is a hardware imposed limit. */
+ blk_queue_max_hw_segments(disk->queue, MAXSGENTRIES);
+
+ /* This is a limit in the driver and could be eliminated. */
+ blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
+
+ blk_queue_max_sectors(disk->queue, 512);
+
+ disk->queue->queuedata = hba[ctlr];
+
+ blk_queue_hardsect_size(disk->queue,
+ hba[ctlr]->drv[drv_index].block_size);
+
+ h->drv[drv_index].queue = disk->queue;
+ add_disk(disk);
+ }
+
+freeret:
+ kfree(size_buff);
+ kfree(inq_buff);
+ return;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will find the first index of the controllers drive array
+ * that has a -1 for the raid_level and will return that index. This is
+ * where new drives will be added. If the index to be returned is greater
+ * than the highest_lun index for the controller then highest_lun is set
+ * to this new index. If there are no available indexes then -1 is returned.
+*/
+static int cciss_find_free_drive_index(int ctlr)
{
+ int i;
+
+ for (i=0; i < CISS_MAX_LUN; i++){
+ if (hba[ctlr]->drv[i].raid_level == -1){
+ if (i > hba[ctlr]->highest_lun)
+ hba[ctlr]->highest_lun = i;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* This function will add and remove logical drives from the Logical
+ * drive array of the controller and maintain persistancy of ordering
+ * so that mount points are preserved until the next reboot. This allows
+ * for the removal of logical drives in the middle of the drive array
+ * without a re-ordering of those drives.
+ * INPUT
+ * h = The controller to perform the operations on
+ * del_disk = The disk to remove if specified. If the value given
+ * is NULL then no disk is removed.
+*/
+static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
+{
+ int ctlr = h->ctlr;
+ int num_luns;
+ ReportLunData_struct *ld_buff = NULL;
+ drive_info_struct *drv = NULL;
+ int return_code;
+ int listlength = 0;
+ int i;
+ int drv_found;
+ int drv_index = 0;
+ __u32 lunid = 0;
unsigned long flags;
+
+ /* Set busy_configuring flag for this operation */
+ spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
+ if (h->num_luns >= CISS_MAX_LUN){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EINVAL;
+ }
+
+ if (h->busy_configuring){
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return -EBUSY;
+ }
+ h->busy_configuring = 1;
+
+ /* if del_disk is NULL then we are being called to add a new disk
+ * and update the logical drive table. If it is not NULL then
+ * we will check if the disk is in use or not.
+ */
+ if (del_disk != NULL){
+ drv = get_drv(del_disk);
+ drv->busy_configuring = 1;
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ return_code = deregister_disk(del_disk, drv, 1);
+ drv->busy_configuring = 0;
+ h->busy_configuring = 0;
+ return return_code;
+ } else {
+ spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
+ if (ld_buff == NULL)
+ goto mem_msg;
+
+ return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
+ sizeof(ReportLunData_struct), 0, 0, 0,
+ TYPE_CMD);
+
+ if (return_code == IO_OK){
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
+ listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
+ listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+ } else{ /* reading number of logical volumes failed */
+ printk(KERN_WARNING "cciss: report logical volume"
+ " command failed\n");
+ listlength = 0;
+ goto freeret;
+ }
+
+ num_luns = listlength / 8; /* 8 bytes per entry */
+ if (num_luns > CISS_MAX_LUN){
+ num_luns = CISS_MAX_LUN;
+ printk(KERN_WARNING "cciss: more luns configured"
+ " on controller than can be handled by"
+ " this driver.\n");
+ }
+
+ /* Compare controller drive array to drivers drive array.
+ * Check for updates in the drive information and any new drives
+ * on the controller.
+ */
+ for (i=0; i < num_luns; i++){
+ int j;
+
+ drv_found = 0;
+
+ lunid = (0xff &
+ (unsigned int)(ld_buff->LUN[i][3])) << 24;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][2])) << 16;
+ lunid |= (0xff &
+ (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ lunid |= 0xff &
+ (unsigned int)(ld_buff->LUN[i][0]);
+
+ /* Find if the LUN is already in the drive array
+ * of the controller. If so then update its info
+ * if not is use. If it does not exist then find
+ * the first free index and add it.
+ */
+ for (j=0; j <= h->highest_lun; j++){
+ if (h->drv[j].LunID == lunid){
+ drv_index = j;
+ drv_found = 1;
+ }
+ }
+
+ /* check if the drive was found already in the array */
+ if (!drv_found){
+ drv_index = cciss_find_free_drive_index(ctlr);
+ if (drv_index == -1)
+ goto freeret;
+
+ }
+ h->drv[drv_index].LunID = lunid;
+ cciss_update_drive_info(ctlr, drv_index);
+ } /* end for */
+ } /* end else */
+
+freeret:
+ kfree(ld_buff);
+ h->busy_configuring = 0;
+ /* We return -1 here to tell the ACU that we have registered/updated
+ * all of the drives that we can and to keep it from calling us
+ * additional times.
+ */
+ return -1;
+mem_msg:
+ printk(KERN_ERR "cciss: out of memory\n");
+ goto freeret;
+}
+
+/* This function will deregister the disk and it's queue from the
+ * kernel. It must be called with the controller lock held and the
+ * drv structures busy_configuring flag set. It's parameters are:
+ *
+ * disk = This is the disk to be deregistered
+ * drv = This is the drive_info_struct associated with the disk to be
+ * deregistered. It contains information about the disk used
+ * by the driver.
+ * clear_all = This flag determines whether or not the disk information
+ * is going to be completely cleared out and the highest_lun
+ * reset. Sometimes we want to clear out information about
+ * the disk in preperation for re-adding it. In this case
+ * the highest_lun should be left unchanged and the LunID
+ * should not be cleared.
+*/
+static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
+ int clear_all)
+{
ctlr_info_t *h = get_host(disk);
- drive_info_struct *drv = get_drv(disk);
- int ctlr = h->ctlr;
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
/* make sure logical volume is NOT is use */
- if( drv->usage_count > 1) {
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ if(clear_all || (h->gendisk[0] == disk)) {
+ if (drv->usage_count > 1)
return -EBUSY;
}
- drv->usage_count++;
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ else
+ if( drv->usage_count > 0 )
+ return -EBUSY;
- /* invalidate the devices and deregister the disk */
- if (disk->flags & GENHD_FL_UP)
+ /* invalidate the devices and deregister the disk. If it is disk
+ * zero do not deregister it but just zero out it's values. This
+ * allows us to delete disk zero but keep the controller registered.
+ */
+ if (h->gendisk[0] != disk){
+ if (disk->flags & GENHD_FL_UP){
+ blk_cleanup_queue(disk->queue);
del_gendisk(disk);
+ drv->queue = NULL;
+ }
+ }
+
+ --h->num_luns;
+ /* zero out the disk size info */
+ drv->nr_blocks = 0;
+ drv->block_size = 0;
+ drv->heads = 0;
+ drv->sectors = 0;
+ drv->cylinders = 0;
+ drv->raid_level = -1; /* This can be used as a flag variable to
+ * indicate that this element of the drive
+ * array is free.
+ */
+
+ if (clear_all){
/* check to see if it was the last disk */
if (drv == h->drv + h->highest_lun) {
/* if so, find the new hightest lun */
int i, newhighest =-1;
for(i=0; i<h->highest_lun; i++) {
/* if the disk has size > 0, it is available */
- if (h->drv[i].nr_blocks)
+ if (h->drv[i].heads)
newhighest = i;
}
h->highest_lun = newhighest;
-
}
- --h->num_luns;
- /* zero out the disk size info */
- drv->nr_blocks = 0;
- drv->block_size = 0;
- drv->cylinders = 0;
+
drv->LunID = 0;
+ }
return(0);
}
+
static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
size_t size,
unsigned int use_unit_num, /* 0: address the controller,
@@ -1420,8 +1730,10 @@ case CMD_HARDWARE_ERR:
}
}
/* unlock the buffers from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(h, c, 0);
return(return_status);
@@ -1495,164 +1807,6 @@ cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
return;
}
-static int register_new_disk(ctlr_info_t *h)
-{
- struct gendisk *disk;
- int ctlr = h->ctlr;
- int i;
- int num_luns;
- int logvol;
- int new_lun_found = 0;
- int new_lun_index = 0;
- int free_index_found = 0;
- int free_index = 0;
- ReportLunData_struct *ld_buff = NULL;
- ReadCapdata_struct *size_buff = NULL;
- InquiryData_struct *inq_buff = NULL;
- int return_code;
- int listlength = 0;
- __u32 lunid = 0;
- unsigned int block_size;
- unsigned int total_size;
-
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- /* if we have no space in our disk array left to add anything */
- if( h->num_luns >= CISS_MAX_LUN)
- return -EINVAL;
-
- ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
- if (ld_buff == NULL)
- goto mem_msg;
- memset(ld_buff, 0, sizeof(ReportLunData_struct));
- size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- goto mem_msg;
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
- if (inq_buff == NULL)
- goto mem_msg;
-
- return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff,
- sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);
-
- if( return_code == IO_OK)
- {
-
- // printk("LUN Data\n--------------------------\n");
-
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;
- listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;
- listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
- } else /* reading number of logical volumes failed */
- {
- printk(KERN_WARNING "cciss: report logical volume"
- " command failed\n");
- listlength = 0;
- goto free_err;
- }
- num_luns = listlength / 8; // 8 bytes pre entry
- if (num_luns > CISS_MAX_LUN)
- {
- num_luns = CISS_MAX_LUN;
- }
-#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],
- ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],
- ld_buff->LUNListLength[3], num_luns);
-#endif
- for(i=0; i< num_luns; i++)
- {
- int j;
- int lunID_found = 0;
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
- lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
-
- /* check to see if this is a new lun */
- for(j=0; j <= h->highest_lun; j++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking %d %x against %x\n", j,h->drv[j].LunID,
- lunid);
-#endif /* CCISS_DEBUG */
- if (h->drv[j].LunID == lunid)
- {
- lunID_found = 1;
- break;
- }
-
- }
- if( lunID_found == 1)
- continue;
- else
- { /* It is the new lun we have been looking for */
-#ifdef CCISS_DEBUG
- printk("new lun found at %d\n", i);
-#endif /* CCISS_DEBUG */
- new_lun_index = i;
- new_lun_found = 1;
- break;
- }
- }
- if (!new_lun_found)
- {
- printk(KERN_WARNING "cciss: New Logical Volume not found\n");
- goto free_err;
- }
- /* Now find the free index */
- for(i=0; i <CISS_MAX_LUN; i++)
- {
-#ifdef CCISS_DEBUG
- printk("Checking Index %d\n", i);
-#endif /* CCISS_DEBUG */
- if(h->drv[i].LunID == 0)
- {
-#ifdef CCISS_DEBUG
- printk("free index found at %d\n", i);
-#endif /* CCISS_DEBUG */
- free_index_found = 1;
- free_index = i;
- break;
- }
- }
- if (!free_index_found)
- {
- printk(KERN_WARNING "cciss: unable to find free slot for disk\n");
- goto free_err;
- }
-
- logvol = free_index;
- h->drv[logvol].LunID = lunid;
- /* there could be gaps in lun numbers, track hightest */
- if(h->highest_lun < lunid)
- h->highest_lun = logvol;
- cciss_read_capacity(ctlr, logvol, size_buff, 1,
- &total_size, &block_size);
- cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,
- inq_buff, &h->drv[logvol]);
- h->drv[logvol].usage_count = 0;
- ++h->num_luns;
- /* setup partitions per disk */
- disk = h->gendisk[logvol];
- set_capacity(disk, h->drv[logvol].nr_blocks);
- /* if it's the controller it's already added */
- if(logvol)
- add_disk(disk);
-freeret:
- kfree(ld_buff);
- kfree(size_buff);
- kfree(inq_buff);
- return (logvol);
-mem_msg:
- printk(KERN_ERR "cciss: out of memory\n");
-free_err:
- logvol = -1;
- goto freeret;
-}
-
static int cciss_revalidate(struct gendisk *disk)
{
ctlr_info_t *h = get_host(disk);
@@ -1859,8 +2013,10 @@ resend_cmd1:
cleanup1:
/* unlock the data buffer from DMA */
+ buff_dma_handle.val32.lower = c->SG[0].Addr.lower;
+ buff_dma_handle.val32.upper = c->SG[0].Addr.upper;
pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,
- size, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(info_p, c, 1);
return (status);
}
@@ -2111,7 +2267,11 @@ queue:
/* fill in the request */
drv = creq->rq_disk->private_data;
c->Header.ReplyQueue = 0; // unused in simple mode
- c->Header.Tag.lower = c->busaddr; // use the physical address the cmd block for tag
+ /* got command from pool, so use the command block index instead */
+ /* for direct lookups. */
+ /* The first 2 bits are reserved for controller error reporting. */
+ c->Header.Tag.lower = (c->cmdindex << 3);
+ c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
c->Header.LUN.LogDev.VolId= drv->LunID;
c->Header.LUN.LogDev.Mode = 1;
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)
ctlr_info_t *h = dev_id;
CommandList_struct *c;
unsigned long flags;
- __u32 a, a1;
+ __u32 a, a1, a2;
int j;
int start_queue = h->next_to_run;
@@ -2204,10 +2364,21 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
while((a = h->access.command_completed(h)) != FIFO_EMPTY)
{
a1 = a;
+ if ((a & 0x04)) {
+ a2 = (a >> 3);
+ if (a2 >= NR_CMDS) {
+ printk(KERN_WARNING "cciss: controller cciss%d failed, stopping.\n", h->ctlr);
+ fail_all_cmds(h->ctlr);
+ return IRQ_HANDLED;
+ }
+
+ c = h->cmd_pool + a2;
+ a = c->busaddr;
+
+ } else {
a &= ~3;
- if ((c = h->cmpQ) == NULL)
- {
- printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
+ if ((c = h->cmpQ) == NULL) {
+ printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
continue;
}
while(c->busaddr != a) {
@@ -2215,6 +2386,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
if (c == h->cmpQ)
break;
}
+ }
/*
* If we've found the command, take it off the
* completion Q and free it
@@ -2634,12 +2806,16 @@ static void cciss_getgeometry(int cntl_num)
#endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns-1;
- for(i=0; i< hba[cntl_num]->num_luns; i++)
+// for(i=0; i< hba[cntl_num]->num_luns; i++)
+ for(i=0; i < CISS_MAX_LUN; i++)
{
-
- lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;
- lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;
+ if (i < hba[cntl_num]->num_luns){
+ lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
+ << 24;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2]))
+ << 16;
+ lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1]))
+ << 8;
lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);
hba[cntl_num]->drv[i].LunID = lunid;
@@ -2647,13 +2823,18 @@ static void cciss_getgeometry(int cntl_num)
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "LUN[%d]: %x %x %x %x = %x\n", i,
- ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2],
- ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);
+ ld_buff->LUN[i][0], ld_buff->LUN[i][1],
+ ld_buff->LUN[i][2], ld_buff->LUN[i][3],
+ hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */
cciss_read_capacity(cntl_num, i, size_buff, 0,
&total_size, &block_size);
- cciss_geometry_inquiry(cntl_num, i, 0, total_size, block_size,
- inq_buff, &hba[cntl_num]->drv[i]);
+ cciss_geometry_inquiry(cntl_num, i, 0, total_size,
+ block_size, inq_buff, &hba[cntl_num]->drv[i]);
+ } else {
+ /* initialize raid_level to indicate a free space */
+ hba[cntl_num]->drv[i].raid_level = -1;
+ }
}
kfree(ld_buff);
kfree(size_buff);
@@ -2727,6 +2908,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
i = alloc_cciss_hba();
if(i < 0)
return (-1);
+
+ hba[i]->busy_initializing = 1;
+
if (cciss_pci_init(hba[i], pdev) != 0)
goto clean1;
@@ -2849,6 +3033,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
add_disk(disk);
}
+ hba[i]->busy_initializing = 0;
return(1);
clean4:
@@ -2869,6 +3054,7 @@ clean2:
clean1:
release_io_mem(hba[i]);
free_hba(i);
+ hba[i]->busy_initializing = 0;
return(-1);
}
@@ -2913,9 +3099,10 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
/* remove it from the disk list */
for (j = 0; j < NWD; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
- if (disk->flags & GENHD_FL_UP)
- blk_cleanup_queue(disk->queue);
+ if (disk->flags & GENHD_FL_UP) {
del_gendisk(disk);
+ blk_cleanup_queue(disk->queue);
+ }
}
pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
@@ -2964,5 +3151,43 @@ static void __exit cciss_cleanup(void)
remove_proc_entry("cciss", proc_root_driver);
}
+static void fail_all_cmds(unsigned long ctlr)
+{
+ /* If we get here, the board is apparently dead. */
+ ctlr_info_t *h = hba[ctlr];
+ CommandList_struct *c;
+ unsigned long flags;
+
+ printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
+ h->alive = 0; /* the controller apparently died... */
+
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+
+ pci_disable_device(h->pdev); /* Make sure it is really dead. */
+
+ /* move everything off the request queue onto the completed queue */
+ while( (c = h->reqQ) != NULL ) {
+ removeQ(&(h->reqQ), c);
+ h->Qdepth--;
+ addQ (&(h->cmpQ), c);
+ }
+
+ /* Now, fail everything on the completed queue with a HW error */
+ while( (c = h->cmpQ) != NULL ) {
+ removeQ(&h->cmpQ, c);
+ c->err_info->CommandStatus = CMD_HARDWARE_ERR;
+ if (c->cmd_type == CMD_RWREQ) {
+ complete_command(h, c, 0);
+ } else if (c->cmd_type == CMD_IOCTL_PEND)
+ complete(c->waiting);
+#ifdef CONFIG_CISS_SCSI_TAPE
+ else if (c->cmd_type == CMD_SCSI)
+ complete_scsi_command(c, 0, 0);
+#endif
+ }
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ return;
+}
+
module_init(cciss_init);
module_exit(cciss_cleanup);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 566587d..ef277ba 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -35,7 +35,13 @@ typedef struct _drive_info_struct
int heads;
int sectors;
int cylinders;
- int raid_level;
+ int raid_level; /* set to -1 to indicate that
+ * the drive is not in use/configured
+ */
+ int busy_configuring; /*This is set when the drive is being removed
+ *to prevent it from being opened or it's queue
+ *from being started.
+ */
} drive_info_struct;
struct ctlr_info
@@ -83,6 +89,7 @@ struct ctlr_info
int nr_allocs;
int nr_frees;
int busy_configuring;
+ int busy_initializing;
/* This element holds the zero based queue number of the last
* queue to be started. It is used for fairness.
@@ -94,6 +101,7 @@ struct ctlr_info
#ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
#endif
+ unsigned char alive;
};
/* Defining the diffent access_menthods */
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index a88a888..53fea54 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -226,6 +226,10 @@ typedef struct _ErrorInfo_struct {
#define CMD_MSG_DONE 0x04
#define CMD_MSG_TIMEOUT 0x05
+/* This structure needs to be divisible by 8 for new
+ * indexing method.
+ */
+#define PADSIZE (sizeof(long) - 4)
typedef struct _CommandList_struct {
CommandListHeader_struct Header;
RequestBlock_struct Request;
@@ -236,14 +240,14 @@ typedef struct _CommandList_struct {
ErrorInfo_struct * err_info; /* pointer to the allocated mem */
int ctlr;
int cmd_type;
+ long cmdindex;
struct _CommandList_struct *prev;
struct _CommandList_struct *next;
struct request * rq;
struct completion *waiting;
int retry_count;
-#ifdef CONFIG_CISS_SCSI_TAPE
void * scsi_cmd;
-#endif
+ char pad[PADSIZE];
} CommandList_struct;
//Configuration Table Structure
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index f16e3ca..e183a3e 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -93,6 +93,7 @@ struct cciss_scsi_cmd_stack_elem_t {
CommandList_struct cmd;
ErrorInfo_struct Err;
__u32 busaddr;
+ __u32 pad;
};
#pragma pack()
@@ -877,7 +878,7 @@ cciss_scsi_interpret_error(CommandList_struct *cp)
static int
cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
- InquiryData_struct *buf)
+ unsigned char *buf, unsigned char bufsize)
{
int rc;
CommandList_struct *cp;
@@ -900,11 +901,10 @@ cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
cdb[1] = 0;
cdb[2] = 0;
cdb[3] = 0;
- cdb[4] = sizeof(*buf) & 0xff;
+ cdb[4] = bufsize;
cdb[5] = 0;
rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb,
- 6, (unsigned char *) buf,
- sizeof(*buf), XFER_READ);
+ 6, buf, bufsize, XFER_READ);
if (rc != 0) return rc; /* something went wrong */
@@ -1000,9 +1000,10 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
that though.
*/
-
+#define OBDR_TAPE_INQ_SIZE 49
+#define OBDR_TAPE_SIG "$DR-10"
ReportLunData_struct *ld_buff;
- InquiryData_struct *inq_buff;
+ unsigned char *inq_buff;
unsigned char scsi3addr[8];
ctlr_info_t *c;
__u32 num_luns=0;
@@ -1020,7 +1021,7 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
return;
}
memset(ld_buff, 0, reportlunsize);
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
@@ -1051,19 +1052,36 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
/* for each physical lun, do an inquiry */
if (ld_buff->LUN[i][3] & 0xC0) continue;
- memset(inq_buff, 0, sizeof(InquiryData_struct));
+ memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
- if (cciss_scsi_do_inquiry(hba[cntl_num],
- scsi3addr, inq_buff) != 0)
- {
+ if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, inq_buff,
+ (unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
/* Inquiry failed (msg printed already) */
devtype = 0; /* so we will skip this device. */
} else /* what kind of device is this? */
- devtype = (inq_buff->data_byte[0] & 0x1f);
+ devtype = (inq_buff[0] & 0x1f);
switch (devtype)
{
+ case 0x05: /* CD-ROM */ {
+
+ /* We don't *really* support actual CD-ROM devices,
+ * just this "One Button Disaster Recovery" tape drive
+ * which temporarily pretends to be a CD-ROM drive.
+ * So we check that the device is really an OBDR tape
+ * device by checking for "$DR-10" in bytes 43-48 of
+ * the inquiry data.
+ */
+ char obdr_sig[7];
+
+ strncpy(obdr_sig, &inq_buff[43], 6);
+ obdr_sig[6] = '\0';
+ if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
+ /* Not OBDR device, ignore it. */
+ break;
+ }
+ /* fall through . . . */
case 0x01: /* sequential access, (tape) */
case 0x08: /* medium changer */
if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
@@ -1126,6 +1144,7 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
int buflen, datalen;
ctlr_info_t *ci;
+ int i;
int cntl_num;
@@ -1136,8 +1155,28 @@ cciss_scsi_proc_info(struct Scsi_Host *sh,
cntl_num = ci->ctlr; /* Get our index into the hba[] array */
if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
- buflen = sprintf(buffer, "hostnum=%d\n", sh->host_no);
-
+ buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
+ cntl_num, sh->host_no);
+
+ /* this information is needed by apps to know which cciss
+ device corresponds to which scsi host number without
+ having to open a scsi target device node. The device
+ information is not a duplicate of /proc/scsi/scsi because
+ the two may be out of sync due to scsi hotplug, rather
+ this info is for an app to be able to use to know how to
+ get them back in sync. */
+
+ for (i=0;i<ccissscsi[cntl_num].ndevices;i++) {
+ struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i];
+ buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+ sh->host_no, sd->bus, sd->target, sd->lun,
+ sd->devtype,
+ sd->scsi3addr[0], sd->scsi3addr[1],
+ sd->scsi3addr[2], sd->scsi3addr[3],
+ sd->scsi3addr[4], sd->scsi3addr[5],
+ sd->scsi3addr[6], sd->scsi3addr[7]);
+ }
datalen = buflen - offset;
if (datalen < 0) { /* they're reading past EOF. */
datalen = 0;
@@ -1399,7 +1438,7 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
CPQ_TAPE_LOCK(ctlr, flags);
size = sprintf(buffer + *len,
- " Sequential access devices: %d\n\n",
+ "Sequential access devices: %d\n\n",
ccissscsi[ctlr].ndevices);
CPQ_TAPE_UNLOCK(ctlr, flags);
*pos += size; *len += size;
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 711d2f3..94af920 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -750,6 +750,14 @@ static int pf_ready(void)
static struct request_queue *pf_queue;
+static void pf_end_request(int uptodate)
+{
+ if (pf_req) {
+ end_request(pf_req, uptodate);
+ pf_req = NULL;
+ }
+}
+
static void do_pf_request(request_queue_t * q)
{
if (pf_busy)
@@ -765,7 +773,7 @@ repeat:
pf_count = pf_req->current_nr_sectors;
if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) {
- end_request(pf_req, 0);
+ pf_end_request(0);
goto repeat;
}
@@ -780,7 +788,7 @@ repeat:
pi_do_claimed(pf_current->pi, do_pf_write);
else {
pf_busy = 0;
- end_request(pf_req, 0);
+ pf_end_request(0);
goto repeat;
}
}
@@ -798,9 +806,11 @@ static int pf_next_buf(void)
if (!pf_count)
return 1;
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- end_request(pf_req, 1);
- pf_count = pf_req->current_nr_sectors;
- pf_buf = pf_req->buffer;
+ pf_end_request(1);
+ if (pf_req) {
+ pf_count = pf_req->current_nr_sectors;
+ pf_buf = pf_req->buffer;
+ }
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
return 1;
}
@@ -810,7 +820,7 @@ static inline void next_request(int success)
unsigned long saved_flags;
spin_lock_irqsave(&pf_spin_lock, saved_flags);
- end_request(pf_req, success);
+ pf_end_request(success);
pf_busy = 0;
do_pf_request(pf_queue);
spin_unlock_irqrestore(&pf_spin_lock, saved_flags);
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 7b83834..7e22a58 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -5,29 +5,41 @@
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
*
- * Packet writing layer for ATAPI and SCSI CD-R, CD-RW, DVD-R, and
- * DVD-RW devices (aka an exercise in block layer masturbation)
+ * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and
+ * DVD-RAM devices.
*
+ * Theory of operation:
*
- * TODO: (circa order of when I will fix it)
- * - Only able to write on CD-RW media right now.
- * - check host application code on media and set it in write page
- * - interface for UDF <-> packet to negotiate a new location when a write
- * fails.
- * - handle OPC, especially for -RW media
+ * At the lowest level, there is the standard driver for the CD/DVD device,
+ * typically ide-cd.c or sr.c. This driver can handle read and write requests,
+ * but it doesn't know anything about the special restrictions that apply to
+ * packet writing. One restriction is that write requests must be aligned to
+ * packet boundaries on the physical media, and the size of a write request
+ * must be equal to the packet size. Another restriction is that a
+ * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read
+ * command, if the previous command was a write.
*
- * Theory of operation:
+ * The purpose of the packet writing driver is to hide these restrictions from
+ * higher layers, such as file systems, and present a block device that can be
+ * randomly read and written using 2kB-sized blocks.
+ *
+ * The lowest layer in the packet writing driver is the packet I/O scheduler.
+ * Its data is defined by the struct packet_iosched and includes two bio
+ * queues with pending read and write requests. These queues are processed
+ * by the pkt_iosched_process_queue() function. The write requests in this
+ * queue are already properly aligned and sized. This layer is responsible for
+ * issuing the flush cache commands and scheduling the I/O in a good order.
*
- * We use a custom make_request_fn function that forwards reads directly to
- * the underlying CD device. Write requests are either attached directly to
- * a live packet_data object, or simply stored sequentially in a list for
- * later processing by the kcdrwd kernel thread. This driver doesn't use
- * any elevator functionally as defined by the elevator_s struct, but the
- * underlying CD device uses a standard elevator.
+ * The next layer transforms unaligned write requests to aligned writes. This
+ * transformation requires reading missing pieces of data from the underlying
+ * block device, assembling the pieces to full packets and queuing them to the
+ * packet I/O scheduler.
*
- * This strategy makes it possible to do very late merging of IO requests.
- * A new bio sent to pkt_make_request can be merged with a live packet_data
- * object even if the object is in the data gathering state.
+ * At the top layer there is a custom make_request_fn function that forwards
+ * read requests directly to the iosched queue and puts write requests in the
+ * unaligned write queue. A kernel thread performs the necessary read
+ * gathering to convert the unaligned writes to aligned writes and then feeds
+ * them to the packet I/O scheduler.
*
*************************************************************************/
@@ -100,10 +112,9 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
goto no_bio;
bio_init(bio);
- bvl = kmalloc(nr_iovecs * sizeof(struct bio_vec), GFP_KERNEL);
+ bvl = kcalloc(nr_iovecs, sizeof(struct bio_vec), GFP_KERNEL);
if (!bvl)
goto no_bvl;
- memset(bvl, 0, nr_iovecs * sizeof(struct bio_vec));
bio->bi_max_vecs = nr_iovecs;
bio->bi_io_vec = bvl;
@@ -125,10 +136,9 @@ static struct packet_data *pkt_alloc_packet_data(void)
int i;
struct packet_data *pkt;
- pkt = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
+ pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL);
if (!pkt)
goto no_pkt;
- memset(pkt, 0, sizeof(struct packet_data));
pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE);
if (!pkt->w_bio)
@@ -659,7 +669,6 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in
}
offs += CD_FRAMESIZE;
if (offs >= PAGE_SIZE) {
- BUG_ON(offs > PAGE_SIZE);
offs = 0;
p++;
}
@@ -724,12 +733,6 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_set(&pkt->io_wait, 0);
atomic_set(&pkt->io_errors, 0);
- if (pkt->cache_valid) {
- VPRINTK("pkt_gather_data: zone %llx cached\n",
- (unsigned long long)pkt->sector);
- goto out_account;
- }
-
/*
* Figure out which frames we need to read before we can write.
*/
@@ -738,6 +741,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
for (bio = pkt->orig_bios; bio; bio = bio->bi_next) {
int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
int num_frames = bio->bi_size / CD_FRAMESIZE;
+ pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
BUG_ON(first_frame < 0);
BUG_ON(first_frame + num_frames > pkt->frames);
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)
}
spin_unlock(&pkt->lock);
+ if (pkt->cache_valid) {
+ VPRINTK("pkt_gather_data: zone %llx cached\n",
+ (unsigned long long)pkt->sector);
+ goto out_account;
+ }
+
/*
* Schedule reads for missing parts of the packet.
*/
@@ -778,7 +788,6 @@ out_account:
frames_read, (unsigned long long)pkt->sector);
pd->stats.pkt_started++;
pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
- pd->stats.secs_w += pd->settings.size;
}
/*
@@ -794,10 +803,11 @@ static struct packet_data *pkt_get_packet_data(struct pktcdvd_device *pd, int zo
list_del_init(&pkt->list);
if (pkt->sector != zone)
pkt->cache_valid = 0;
- break;
+ return pkt;
}
}
- return pkt;
+ BUG();
+ return NULL;
}
static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt)
@@ -941,12 +951,10 @@ try_next_bio:
}
pkt = pkt_get_packet_data(pd, zone);
- BUG_ON(!pkt);
pd->current_sector = zone + pd->settings.size;
pkt->sector = zone;
pkt->frames = pd->settings.size >> 2;
- BUG_ON(pkt->frames > PACKET_MAX_SIZE);
pkt->write_size = 0;
/*
@@ -1636,6 +1644,10 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
printk("pktcdvd: detected zero packet size!\n");
pd->settings.size = 128;
}
+ if (pd->settings.size > PACKET_MAX_SECTORS) {
+ printk("pktcdvd: packet size is too big\n");
+ return -ENXIO;
+ }
pd->settings.fp = ti.fp;
pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
@@ -2198,7 +2210,6 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
* No matching packet found. Store the bio in the work queue.
*/
node = mempool_alloc(pd->rb_pool, GFP_NOIO);
- BUG_ON(!node);
node->bio = bio;
spin_lock(&pd->lock);
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
struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data;
VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode));
- BUG_ON(!pd);
switch (cmd) {
/*
@@ -2477,10 +2487,9 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
return -EBUSY;
}
- pd = kmalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
+ pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
if (!pd)
return ret;
- memset(pd, 0, sizeof(struct pktcdvd_device));
pd->rb_pool = mempool_create(PKT_RB_POOL_SIZE, pkt_rb_alloc, pkt_rb_free, NULL);
if (!pd->rb_pool)
diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c
index 856c227..079ec34 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)
safe_for_write(WRITE_VERIFY_12),
safe_for_write(WRITE_16),
safe_for_write(WRITE_LONG),
+ safe_for_write(WRITE_LONG_2),
safe_for_write(ERASE),
safe_for_write(GPCMD_MODE_SELECT_10),
safe_for_write(MODE_SELECT),
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 67d96b5..57c48bb 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -65,13 +65,15 @@
#endif
static int ignore = 0;
+static int ignore_csr = 0;
+static int ignore_sniffer = 0;
static int reset = 0;
#ifdef CONFIG_BT_HCIUSB_SCO
static int isoc = 2;
#endif
-#define VERSION "2.8"
+#define VERSION "2.9"
static struct usb_driver hci_usb_driver;
@@ -98,6 +100,9 @@ static struct usb_device_id bluetooth_ids[] = {
MODULE_DEVICE_TABLE (usb, bluetooth_ids);
static struct usb_device_id blacklist_ids[] = {
+ /* CSR BlueCore devices */
+ { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR },
+
/* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
@@ -836,6 +841,12 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
if (ignore || id->driver_info & HCI_IGNORE)
return -ENODEV;
+ if (ignore_csr && id->driver_info & HCI_CSR)
+ return -ENODEV;
+
+ if (ignore_sniffer && id->driver_info & HCI_SNIFFER)
+ return -ENODEV;
+
if (intf->cur_altsetting->desc.bInterfaceNumber > 0)
return -ENODEV;
@@ -1061,6 +1072,12 @@ module_exit(hci_usb_exit);
module_param(ignore, bool, 0644);
MODULE_PARM_DESC(ignore, "Ignore devices from the matching table");
+module_param(ignore_csr, bool, 0644);
+MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
+
+module_param(ignore_sniffer, bool, 0644);
+MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
+
module_param(reset, bool, 0644);
MODULE_PARM_DESC(reset, "Send HCI reset command on initialization");
diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h
index 29936b4..37100a6 100644
--- a/drivers/bluetooth/hci_usb.h
+++ b/drivers/bluetooth/hci_usb.h
@@ -31,9 +31,10 @@
#define HCI_IGNORE 0x01
#define HCI_RESET 0x02
#define HCI_DIGIANSWER 0x04
-#define HCI_SNIFFER 0x08
-#define HCI_BROKEN_ISOC 0x10
+#define HCI_CSR 0x08
+#define HCI_SNIFFER 0x10
#define HCI_BCM92035 0x20
+#define HCI_BROKEN_ISOC 0x40
#define HCI_MAX_IFACE_NUM 3
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 99762b6..de5d6d2 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -252,7 +252,7 @@ hp_zx1_configure (void)
readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
readl(hp->ioc_regs+HP_ZX1_TCNFG);
- writel(~(HP_ZX1_IOVA_SIZE-1), hp->ioc_regs+HP_ZX1_IMASK);
+ writel((unsigned int)(~(HP_ZX1_IOVA_SIZE-1)), hp->ioc_regs+HP_ZX1_IMASK);
readl(hp->ioc_regs+HP_ZX1_IMASK);
writel(hp->iova_base|1, hp->ioc_regs+HP_ZX1_IBASE);
readl(hp->ioc_regs+HP_ZX1_IBASE);
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 2a36561..a124f8c 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -2053,10 +2053,6 @@ static int __init rs_init(void)
state->icount.rx = state->icount.tx = 0;
state->icount.frame = state->icount.parity = 0;
state->icount.overrun = state->icount.brk = 0;
- /*
- if(state->port && check_region(state->port,REGION_LENGTH(state)))
- continue;
- */
printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
state->line);
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 58d3738..407708a 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -534,7 +534,7 @@ static void shutdown(struct channel *ch)
unsigned long flags;
struct tty_struct *tty;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
if (!(ch->asyncflags & ASYNC_INITIALIZED))
return;
@@ -618,7 +618,7 @@ static int pc_write(struct tty_struct * tty,
struct channel *ch;
unsigned long flags;
int remain;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
/* ----------------------------------------------------------------
pc_write is primarily called directly by the kernel routine
@@ -685,7 +685,7 @@ static int pc_write(struct tty_struct * tty,
------------------------------------------------------------------- */
dataLen = min(bytesAvailable, dataLen);
- memcpy(ch->txptr + head, buf, dataLen);
+ memcpy_toio(ch->txptr + head, buf, dataLen);
buf += dataLen;
head += dataLen;
amountCopied += dataLen;
@@ -726,7 +726,7 @@ static int pc_write_room(struct tty_struct *tty)
struct channel *ch;
unsigned long flags;
unsigned int head, tail;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
remain = 0;
@@ -773,7 +773,7 @@ static int pc_chars_in_buffer(struct tty_struct *tty)
int remain;
unsigned long flags;
struct channel *ch;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
@@ -830,7 +830,7 @@ static void pc_flush_buffer(struct tty_struct *tty)
unsigned int tail;
unsigned long flags;
struct channel *ch;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
/* ---------------------------------------------------------
verifyChannel returns the channel from the tty struct
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)
struct channel *ch;
unsigned long flags;
int line, retval, boardnum;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned int head;
line = tty->index;
@@ -1041,7 +1041,7 @@ static int pc_open(struct tty_struct *tty, struct file * filp)
ch->statusflags = 0;
/* Save boards current modem status */
- ch->imodem = bc->mstat;
+ ch->imodem = readb(&bc->mstat);
/* ----------------------------------------------------------------
Set receive head and tail ptrs to each other. This indicates
@@ -1399,10 +1399,10 @@ static void post_fep_init(unsigned int crd)
{ /* Begin post_fep_init */
int i;
- unsigned char *memaddr;
- struct global_data *gd;
+ void __iomem *memaddr;
+ struct global_data __iomem *gd;
struct board_info *bd;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
struct channel *ch;
int shrinkmem = 0, lowwater ;
@@ -1461,7 +1461,7 @@ static void post_fep_init(unsigned int crd)
8 and 64 of these structures.
-------------------------------------------------------------------- */
- bc = (struct board_chan *)(memaddr + CHANSTRUCT);
+ bc = memaddr + CHANSTRUCT;
/* -------------------------------------------------------------------
The below assignment will set gd to point at the BEGINING of
@@ -1470,7 +1470,7 @@ static void post_fep_init(unsigned int crd)
pointer begins at 0xd10.
---------------------------------------------------------------------- */
- gd = (struct global_data *)(memaddr + GLOBAL);
+ gd = memaddr + GLOBAL;
/* --------------------------------------------------------------------
XEPORTS (address 0xc22) points at the number of channels the
@@ -1493,6 +1493,7 @@ static void post_fep_init(unsigned int crd)
for (i = 0; i < bd->numports; i++, ch++, bc++) { /* Begin for each port */
unsigned long flags;
+ u16 tseg, rseg;
ch->brdchan = bc;
ch->mailbox = gd;
@@ -1553,50 +1554,53 @@ static void post_fep_init(unsigned int crd)
shrinkmem = 0;
}
+ tseg = readw(&bc->tseg);
+ rseg = readw(&bc->rseg);
+
switch (bd->type) {
case PCIXEM:
case PCIXRJ:
case PCIXR:
/* Cover all the 2MEG cards */
- ch->txptr = memaddr + (((bc->tseg) << 4) & 0x1fffff);
- ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x1fffff);
- ch->txwin = FEPWIN | ((bc->tseg) >> 11);
- ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+ ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
break;
case PCXEM:
case EISAXEM:
/* Cover all the 32K windowed cards */
/* Mask equal to window size - 1 */
- ch->txptr = memaddr + (((bc->tseg) << 4) & 0x7fff);
- ch->rxptr = memaddr + (((bc->rseg) << 4) & 0x7fff);
- ch->txwin = FEPWIN | ((bc->tseg) >> 11);
- ch->rxwin = FEPWIN | ((bc->rseg) >> 11);
+ ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
+ ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
+ ch->txwin = FEPWIN | (tseg >> 11);
+ ch->rxwin = FEPWIN | (rseg >> 11);
break;
case PCXEVE:
case PCXE:
- ch->txptr = memaddr + (((bc->tseg - bd->memory_seg) << 4) & 0x1fff);
- ch->txwin = FEPWIN | ((bc->tseg - bd->memory_seg) >> 9);
- ch->rxptr = memaddr + (((bc->rseg - bd->memory_seg) << 4) & 0x1fff);
- ch->rxwin = FEPWIN | ((bc->rseg - bd->memory_seg) >>9 );
+ ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
+ ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4) & 0x1fff);
+ ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >>9 );
break;
case PCXI:
case PC64XE:
- ch->txptr = memaddr + ((bc->tseg - bd->memory_seg) << 4);
- ch->rxptr = memaddr + ((bc->rseg - bd->memory_seg) << 4);
+ ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
+ ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
ch->txwin = ch->rxwin = 0;
break;
} /* End switch bd->type */
ch->txbufhead = 0;
- ch->txbufsize = bc->tmax + 1;
+ ch->txbufsize = readw(&bc->tmax) + 1;
ch->rxbufhead = 0;
- ch->rxbufsize = bc->rmax + 1;
+ ch->rxbufsize = readw(&bc->rmax) + 1;
lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
@@ -1718,11 +1722,11 @@ static void epcapoll(unsigned long ignored)
static void doevent(int crd)
{ /* Begin doevent */
- void *eventbuf;
+ void __iomem *eventbuf;
struct channel *ch, *chan0;
static struct tty_struct *tty;
struct board_info *bd;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned int tail, head;
int event, channel;
int mstat, lstat;
@@ -1817,7 +1821,7 @@ static void doevent(int crd)
static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
int byte2, int ncmds, int bytecmd)
{ /* Begin fepcmd */
- unchar *memaddr;
+ unchar __iomem *memaddr;
unsigned int head, cmdTail, cmdStart, cmdMax;
long count;
int n;
@@ -2000,7 +2004,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
unsigned int cmdHead;
struct termios *ts;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned mval, hflow, cflag, iflag;
bc = ch->brdchan;
@@ -2010,7 +2014,7 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch)
ts = tty->termios;
if ((ts->c_cflag & CBAUD) == 0) { /* Begin CBAUD detected */
cmdHead = readw(&bc->rin);
- bc->rout = cmdHead;
+ writew(cmdHead, &bc->rout);
cmdHead = readw(&bc->tin);
/* Changing baud in mid-stream transmission can be wonderful */
/* ---------------------------------------------------------------
@@ -2116,7 +2120,7 @@ static void receive_data(struct channel *ch)
unchar *rptr;
struct termios *ts = NULL;
struct tty_struct *tty;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
int dataToRead, wrapgap, bytesAvailable;
unsigned int tail, head;
unsigned int wrapmask;
@@ -2154,7 +2158,7 @@ static void receive_data(struct channel *ch)
--------------------------------------------------------------------- */
if (!tty || !ts || !(ts->c_cflag & CREAD)) {
- bc->rout = head;
+ writew(head, &bc->rout);
return;
}
@@ -2270,7 +2274,7 @@ static int info_ioctl(struct tty_struct *tty, struct file * file,
static int pc_tiocmget(struct tty_struct *tty, struct file *file)
{
struct channel *ch = (struct channel *) tty->driver_data;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
unsigned int mstat, mflag = 0;
unsigned long flags;
@@ -2351,7 +2355,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file * file,
unsigned long flags;
unsigned int mflag, mstat;
unsigned char startc, stopc;
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
struct channel *ch = (struct channel *) tty->driver_data;
void __user *argp = (void __user *)arg;
@@ -2633,7 +2637,7 @@ static void pc_start(struct tty_struct *tty)
spin_lock_irqsave(&epca_lock, flags);
/* Just in case output was resumed because of a change in Digi-flow */
if (ch->statusflags & TXSTOPPED) { /* Begin transmit resume requested */
- struct board_chan *bc;
+ struct board_chan __iomem *bc;
globalwinon(ch);
bc = ch->brdchan;
if (ch->statusflags & LOWWAIT)
@@ -2727,7 +2731,7 @@ void digi_send_break(struct channel *ch, int msec)
static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
{ /* Begin setup_empty_event */
- struct board_chan *bc = ch->brdchan;
+ struct board_chan __iomem *bc = ch->brdchan;
globalwinon(ch);
ch->statusflags |= EMPTYWAIT;
diff --git a/drivers/char/epca.h b/drivers/char/epca.h
index 20eeb5a..456d6c8 100644
--- a/drivers/char/epca.h
+++ b/drivers/char/epca.h
@@ -128,17 +128,17 @@ struct channel
unsigned long c_cflag;
unsigned long c_lflag;
unsigned long c_oflag;
- unsigned char *txptr;
- unsigned char *rxptr;
+ unsigned char __iomem *txptr;
+ unsigned char __iomem *rxptr;
unsigned char *tmp_buf;
struct board_info *board;
- struct board_chan *brdchan;
+ struct board_chan __iomem *brdchan;
struct digi_struct digiext;
struct tty_struct *tty;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
struct work_struct tqueue;
- struct global_data *mailbox;
+ struct global_data __iomem *mailbox;
};
struct board_info
@@ -149,8 +149,8 @@ struct board_info
unsigned short numports;
unsigned long port;
unsigned long membase;
- unsigned char __iomem *re_map_port;
- unsigned char *re_map_membase;
+ void __iomem *re_map_port;
+ void __iomem *re_map_membase;
unsigned long memory_seg;
void ( * memwinon ) (struct board_info *, unsigned int) ;
void ( * memwinoff ) (struct board_info *, unsigned int) ;
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index cddb789..f921776 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -839,9 +839,6 @@ int __init hvc_init(void)
hvc_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(hvc_driver, &hvc_ops);
- if (tty_register_driver(hvc_driver))
- panic("Couldn't register hvc console driver\n");
-
/* Always start the kthread because there can be hotplug vty adapters
* added later. */
hvc_task = kthread_run(khvcd, NULL, "khvcd");
@@ -851,6 +848,9 @@ int __init hvc_init(void)
return -EIO;
}
+ if (tty_register_driver(hvc_driver))
+ panic("Couldn't register hvc console driver\n");
+
return 0;
}
module_init(hvc_init);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 1e33cb0..e91268e 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)
* from the top and bottom of cursor position
*/
old_origin += (vc->vc_y - new_rows/2) * old_row_size;
- end = old_origin + new_screen_size;
+ end = old_origin + (old_row_size * new_rows);
}
} else
/*
* Cursor near the top, copy contents from the top of buffer
*/
- end = (old_rows > new_rows) ? old_origin + new_screen_size :
+ end = (old_rows > new_rows) ? old_origin +
+ (old_row_size * new_rows) :
vc->vc_scr_end;
update_attr(vc);
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index fa789ea..344001b 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -84,6 +84,17 @@ config 977_WATCHDOG
Not sure? It's safe to say N.
+config IXP2000_WATCHDOG
+ tristate "IXP2000 Watchdog"
+ depends on WATCHDOG && ARCH_IXP2000
+ help
+ Say Y here if to include support for the watchdog timer
+ in the Intel IXP2000(2400, 2800, 2850) network processors.
+ This driver can be built as a module by choosing M. The module
+ will be called ixp2000_wdt.
+
+ Say N if you are unsure.
+
config IXP4XX_WATCHDOG
tristate "IXP4xx Watchdog"
depends on WATCHDOG && ARCH_IXP4XX
@@ -100,17 +111,6 @@ config IXP4XX_WATCHDOG
Say N if you are unsure.
-config IXP2000_WATCHDOG
- tristate "IXP2000 Watchdog"
- depends on WATCHDOG && ARCH_IXP2000
- help
- Say Y here if to include support for the watchdog timer
- in the Intel IXP2000(2400, 2800, 2850) network processors.
- This driver can be built as a module by choosing M. The module
- will be called ixp2000_wdt.
-
- Say N if you are unsure.
-
config S3C2410_WATCHDOG
tristate "S3C2410 Watchdog"
depends on WATCHDOG && ARCH_S3C2410
@@ -233,6 +233,16 @@ config IB700_WDT
Most people will say N.
+config IBMASR
+ tristate "IBM Automatic Server Restart"
+ depends on WATCHDOG && X86
+ help
+ This is the driver for the IBM Automatic Server Restart watchdog
+ timer builtin into some eServer xSeries machines.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ibmasr.
+
config WAFER_WDT
tristate "ICP Wafer 5823 Single Board Computer Watchdog"
depends on WATCHDOG && X86
@@ -243,6 +253,16 @@ config WAFER_WDT
To compile this driver as a module, choose M here: the
module will be called wafer5823wdt.
+config I6300ESB_WDT
+ tristate "Intel 6300ESB Timer/Watchdog"
+ depends on WATCHDOG && X86 && PCI
+ ---help---
+ Hardware driver for the watchdog timer built into the Intel
+ 6300ESB controller hub.
+
+ To compile this driver as a module, choose M here: the
+ module will be called i6300esb.
+
config I8XX_TCO
tristate "Intel i8xx TCO Timer/Watchdog"
depends on WATCHDOG && (X86 || IA64) && PCI
@@ -298,6 +318,19 @@ config 60XX_WDT
You can compile this driver directly into the kernel, or use
it as a module. The module will be called sbc60xxwdt.
+config SBC8360_WDT
+ tristate "SBC8360 Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+
+ This is the driver for the hardware watchdog on the SBC8360 Single
+ Board Computer produced by Axiomtek Co., Ltd. (www.axiomtek.com).
+
+ To compile this driver as a module, choose M here: the
+ module will be called sbc8360.ko.
+
+ Most people will say N.
+
config CPU5_WDT
tristate "SMA CPU5 Watchdog"
depends on WATCHDOG && X86
@@ -336,6 +369,19 @@ config W83877F_WDT
Most people will say N.
+config W83977F_WDT
+ tristate "W83977F (PCM-5335) Watchdog Timer"
+ depends on WATCHDOG && X86
+ ---help---
+ This is the driver for the hardware watchdog on the W83977F I/O chip
+ as used in AAEON's PCM-5335 SBC (and likely others). This
+ watchdog simply watches your kernel to make sure it doesn't freeze,
+ and if it does, it reboots your computer after a certain amount of
+ time.
+
+ To compile this driver as a module, choose M here: the
+ module will be called w83977f_wdt.
+
config MACHZ_WDT
tristate "ZF MachZ Watchdog"
depends on WATCHDOG && X86
@@ -355,6 +401,10 @@ config 8xx_WDT
tristate "MPC8xx Watchdog Timer"
depends on WATCHDOG && 8xx
+config MV64X60_WDT
+ tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
+ depends on WATCHDOG && MV64X60
+
config BOOKE_WDT
tristate "PowerPC Book-E Watchdog Timer"
depends on WATCHDOG && (BOOKE || 4xx)
@@ -362,6 +412,17 @@ config BOOKE_WDT
Please see Documentation/watchdog/watchdog-api.txt for
more information.
+# PPC64 Architecture
+
+config WATCHDOG_RTAS
+ tristate "RTAS watchdog"
+ depends on WATCHDOG && PPC_RTAS
+ help
+ This driver adds watchdog support for the RTAS watchdog.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wdrtas.
+
# MIPS Architecture
config INDYDOG
@@ -430,16 +491,6 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
-# ppc64 RTAS watchdog
-config WATCHDOG_RTAS
- tristate "RTAS watchdog"
- depends on WATCHDOG && PPC_RTAS
- help
- This driver adds watchdog support for the RTAS watchdog.
-
- To compile this driver as a module, choose M here. The module
- will be called wdrtas.
-
#
# ISA-based Watchdog Cards
#
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index bc6f5fe..cfd0a39 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -39,22 +39,27 @@ obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o
obj-$(CONFIG_SC520_WDT) += sc520_wdt.o
obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
obj-$(CONFIG_IB700_WDT) += ib700wdt.o
+obj-$(CONFIG_IBMASR) += ibmasr.o
obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
+obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o
obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
+obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o
obj-$(CONFIG_MACHZ_WDT) += machzwd.o
# PowerPC Architecture
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
+obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
# PPC64 Architecture
obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
-obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o
# MIPS Architecture
obj-$(CONFIG_INDYDOG) += indydog.o
diff --git a/drivers/char/watchdog/i6300esb.c b/drivers/char/watchdog/i6300esb.c
new file mode 100644
index 0000000..93785f1
--- /dev/null
+++ b/drivers/char/watchdog/i6300esb.c
@@ -0,0 +1,527 @@
+/*
+ * i6300esb: Watchdog timer driver for Intel 6300ESB chipset
+ *
+ * (c) Copyright 2004 Google Inc.
+ * (c) Copyright 2005 David Härdeman <david@2gen.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * based on i810-tco.c which is in turn based on softdog.c
+ *
+ * The timer is implemented in the following I/O controller hubs:
+ * (See the intel documentation on http://developer.intel.com.)
+ * 6300ESB chip : document number 300641-003
+ *
+ * 2004YYZZ Ross Biro
+ * Initial version 0.01
+ * 2004YYZZ Ross Biro
+ * Version 0.02
+ * 20050210 David Härdeman <david@2gen.com>
+ * Ported driver to kernel 2.6
+ */
+
+/*
+ * Includes, defines, variables, module parameters, ...
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* Module and version information */
+#define ESB_VERSION "0.03"
+#define ESB_MODULE_NAME "i6300ESB timer"
+#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
+#define PFX ESB_MODULE_NAME ": "
+
+/* PCI configuration registers */
+#define ESB_CONFIG_REG 0x60 /* Config register */
+#define ESB_LOCK_REG 0x68 /* WDT lock register */
+
+/* Memory mapped registers */
+#define ESB_TIMER1_REG BASEADDR + 0x00 /* Timer1 value after each reset */
+#define ESB_TIMER2_REG BASEADDR + 0x04 /* Timer2 value after each reset */
+#define ESB_GINTSR_REG BASEADDR + 0x08 /* General Interrupt Status Register */
+#define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */
+
+/* Lock register bits */
+#define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */
+#define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */
+#define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */
+
+/* Config register bits */
+#define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */
+#define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */
+#define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */
+
+/* Reload register bits */
+#define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */
+
+/* Magic constants */
+#define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */
+#define ESB_UNLOCK2 0x86 /* Step 2 to unlock reset registers */
+
+/* internal variables */
+static void __iomem *BASEADDR;
+static spinlock_t esb_lock; /* Guards the hardware */
+static unsigned long timer_alive;
+static struct pci_dev *esb_pci;
+static unsigned short triggered; /* The status of the watchdog upon boot */
+static char esb_expect_close;
+
+/* module parameters */
+#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */
+static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Some i6300ESB specific functions
+ */
+
+/*
+ * Prepare for reloading the timer by unlocking the proper registers.
+ * This is performed by first writing 0x80 followed by 0x86 to the
+ * reload register. After this the appropriate registers can be written
+ * to once before they need to be unlocked again.
+ */
+static inline void esb_unlock_registers(void) {
+ writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
+ writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+}
+
+static void esb_timer_start(void)
+{
+ u8 val;
+
+ /* Enable or Enable + Lock? */
+ val = 0x02 | (nowayout ? 0x01 : 0x00);
+
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, val);
+}
+
+static int esb_timer_stop(void)
+{
+ u8 val;
+
+ spin_lock(&esb_lock);
+ /* First, reset timers as suggested by the docs */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* Then disable the WDT */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x0);
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val);
+ spin_unlock(&esb_lock);
+
+ /* Returns 0 if the timer was disabled, non-zero otherwise */
+ return (val & 0x01);
+}
+
+static void esb_timer_keepalive(void)
+{
+ spin_lock(&esb_lock);
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+ /* FIXME: Do we need to flush anything here? */
+ spin_unlock(&esb_lock);
+}
+
+static int esb_timer_set_heartbeat(int time)
+{
+ u32 val;
+
+ if (time < 0x1 || time > (2 * 0x03ff))
+ return -EINVAL;
+
+ spin_lock(&esb_lock);
+
+ /* We shift by 9, so if we are passed a value of 1 sec,
+ * val will be 1 << 9 = 512, then write that to two
+ * timers => 2 * 512 = 1024 (which is decremented at 1KHz)
+ */
+ val = time << 9;
+
+ /* Write timer 1 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER1_REG);
+
+ /* Write timer 2 */
+ esb_unlock_registers();
+ writel(val, ESB_TIMER2_REG);
+
+ /* Reload */
+ esb_unlock_registers();
+ writew(ESB_WDT_RELOAD, ESB_RELOAD_REG);
+
+ /* FIXME: Do we need to flush everything out? */
+
+ /* Done */
+ heartbeat = time;
+ spin_unlock(&esb_lock);
+ return 0;
+}
+
+static int esb_timer_read (void)
+{
+ u32 count;
+
+ /* This isn't documented, and doesn't take into
+ * acount which stage is running, but it looks
+ * like a 20 bit count down, so we might as well report it.
+ */
+ pci_read_config_dword(esb_pci, 0x64, &count);
+ return (int)count;
+}
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int esb_open (struct inode *inode, struct file *file)
+{
+ /* /dev/watchdog can only be opened once */
+ if (test_and_set_bit(0, &timer_alive))
+ return -EBUSY;
+
+ /* Reload and activate timer */
+ esb_timer_keepalive ();
+ esb_timer_start ();
+
+ return nonseekable_open(inode, file);
+}
+
+static int esb_release (struct inode *inode, struct file *file)
+{
+ /* Shut off the timer. */
+ if (esb_expect_close == 42) {
+ esb_timer_stop ();
+ } else {
+ printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
+ esb_timer_keepalive ();
+ }
+ clear_bit(0, &timer_alive);
+ esb_expect_close = 0;
+ return 0;
+}
+
+static ssize_t esb_write (struct file *file, const char __user *data,
+ size_t len, loff_t * ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ /* note: just in case someone wrote the magic character
+ * five months ago... */
+ esb_expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for (i = 0; i != len; i++) {
+ char c;
+ if(get_user(c, data+i))
+ return -EFAULT;
+ if (c == 'V')
+ esb_expect_close = 42;
+ }
+ }
+
+ /* someone wrote to us, we should reload the timer */
+ esb_timer_keepalive ();
+ }
+ return len;
+}
+
+static int esb_ioctl (struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int new_options, retval = -EINVAL;
+ int new_heartbeat;
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 0,
+ .identity = ESB_MODULE_NAME,
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident,
+ sizeof (ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ return put_user (esb_timer_read(), p);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user (triggered, p);
+
+ case WDIOC_KEEPALIVE:
+ esb_timer_keepalive ();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ {
+ if (get_user (new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ esb_timer_stop ();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ esb_timer_keepalive ();
+ esb_timer_start ();
+ retval = 0;
+ }
+
+ return retval;
+ }
+
+ case WDIOC_SETTIMEOUT:
+ {
+ if (get_user(new_heartbeat, p))
+ return -EFAULT;
+
+ if (esb_timer_set_heartbeat(new_heartbeat))
+ return -EINVAL;
+
+ esb_timer_keepalive ();
+ /* Fall */
+ }
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(heartbeat, p);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/*
+ * Notify system
+ */
+
+static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT) {
+ /* Turn the WDT off */
+ esb_timer_stop ();
+ }
+
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations esb_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = esb_write,
+ .ioctl = esb_ioctl,
+ .open = esb_open,
+ .release = esb_release,
+};
+
+static struct miscdevice esb_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &esb_fops,
+};
+
+static struct notifier_block esb_notifier = {
+ .notifier_call = esb_notify_sys,
+};
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE. We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id esb_pci_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
+ { 0, }, /* End of list */
+};
+MODULE_DEVICE_TABLE (pci, esb_pci_tbl);
+
+/*
+ * Init & exit routines
+ */
+
+static unsigned char __init esb_getdevice (void)
+{
+ u8 val1;
+ unsigned short val2;
+
+ struct pci_dev *dev = NULL;
+ /*
+ * Find the PCI device
+ */
+
+ for_each_pci_dev(dev) {
+ if (pci_match_id(esb_pci_tbl, dev)) {
+ esb_pci = dev;
+ break;
+ }
+ }
+
+ if (esb_pci) {
+ if (pci_enable_device(esb_pci)) {
+ printk (KERN_ERR PFX "failed to enable device\n");
+ goto err_devput;
+ }
+
+ if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+ printk (KERN_ERR PFX "failed to request region\n");
+ goto err_disable;
+ }
+
+ BASEADDR = ioremap(pci_resource_start(esb_pci, 0),
+ pci_resource_len(esb_pci, 0));
+ if (BASEADDR == NULL) {
+ /* Something's wrong here, BASEADDR has to be set */
+ printk (KERN_ERR PFX "failed to get BASEADDR\n");
+ goto err_release;
+ }
+
+ /*
+ * The watchdog has two timers, it can be setup so that the
+ * expiry of timer1 results in an interrupt and the expiry of
+ * timer2 results in a reboot. We set it to not generate
+ * any interrupts as there is not much we can do with it
+ * right now.
+ *
+ * We also enable reboots and set the timer frequency to
+ * the PCI clock divided by 2^15 (approx 1KHz).
+ */
+ pci_write_config_word(esb_pci, ESB_CONFIG_REG, 0x0003);
+
+ /* Check that the WDT isn't already locked */
+ pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1);
+ if (val1 & ESB_WDT_LOCK)
+ printk (KERN_WARNING PFX "nowayout already set\n");
+
+ /* Set the timer to watchdog mode and disable it for now */
+ pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00);
+
+ /* Check if the watchdog was previously triggered */
+ esb_unlock_registers();
+ val2 = readw(ESB_RELOAD_REG);
+ triggered = (val2 & (0x01 << 9) >> 9);
+
+ /* Reset trigger flag and timers */
+ esb_unlock_registers();
+ writew((0x11 << 8), ESB_RELOAD_REG);
+
+ /* Done */
+ return 1;
+
+err_release:
+ pci_release_region(esb_pci, 0);
+err_disable:
+ pci_disable_device(esb_pci);
+err_devput:
+ pci_dev_put(esb_pci);
+ }
+ return 0;
+}
+
+static int __init watchdog_init (void)
+{
+ int ret;
+
+ spin_lock_init(&esb_lock);
+
+ /* Check whether or not the hardware watchdog is there */
+ if (!esb_getdevice () || esb_pci == NULL)
+ return -ENODEV;
+
+ /* Check that the heartbeat value is within it's range ; if not reset to the default */
+ if (esb_timer_set_heartbeat (heartbeat)) {
+ esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT);
+ printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n",
+ heartbeat);
+ }
+
+ ret = register_reboot_notifier(&esb_notifier);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ ret);
+ goto err_unmap;
+ }
+
+ ret = misc_register(&esb_miscdev);
+ if (ret != 0) {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto err_notifier;
+ }
+
+ esb_timer_stop ();
+
+ printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+ BASEADDR, heartbeat, nowayout);
+
+ return 0;
+
+err_notifier:
+ unregister_reboot_notifier(&esb_notifier);
+err_unmap:
+ iounmap(BASEADDR);
+/* err_release: */
+ pci_release_region(esb_pci, 0);
+/* err_disable: */
+ pci_disable_device(esb_pci);
+/* err_devput: */
+ pci_dev_put(esb_pci);
+ return ret;
+}
+
+static void __exit watchdog_cleanup (void)
+{
+ /* Stop the timer before we leave */
+ if (!nowayout)
+ esb_timer_stop ();
+
+ /* Deregister */
+ misc_deregister(&esb_miscdev);
+ unregister_reboot_notifier(&esb_notifier);
+ iounmap(BASEADDR);
+ pci_release_region(esb_pci, 0);
+ pci_disable_device(esb_pci);
+ pci_dev_put(esb_pci);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
+
+MODULE_AUTHOR("Ross Biro and David Härdeman");
+MODULE_DESCRIPTION("Watchdog driver for Intel 6300ESB chipsets");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
new file mode 100644
index 0000000..294c474
--- /dev/null
+++ b/drivers/char/watchdog/ibmasr.c
@@ -0,0 +1,405 @@
+/*
+ * IBM Automatic Server Restart driver.
+ *
+ * Copyright (c) 2005 Andrey Panin <pazke@donpac.ru>
+ *
+ * Based on driver written by Pete Reynolds.
+ * Copyright (c) IBM Corporation, 1998-2004.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/timer.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/dmi.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+
+enum {
+ ASMTYPE_UNKNOWN,
+ ASMTYPE_TOPAZ,
+ ASMTYPE_JASPER,
+ ASMTYPE_PEARL,
+ ASMTYPE_JUNIPER,
+ ASMTYPE_SPRUCE,
+};
+
+#define PFX "ibmasr: "
+
+#define TOPAZ_ASR_REG_OFFSET 4
+#define TOPAZ_ASR_TOGGLE 0x40
+#define TOPAZ_ASR_DISABLE 0x80
+
+/* PEARL ASR S/W REGISTER SUPERIO PORT ADDRESSES */
+#define PEARL_BASE 0xe04
+#define PEARL_WRITE 0xe06
+#define PEARL_READ 0xe07
+
+#define PEARL_ASR_DISABLE_MASK 0x80 /* bit 7: disable = 1, enable = 0 */
+#define PEARL_ASR_TOGGLE_MASK 0x40 /* bit 6: 0, then 1, then 0 */
+
+/* JASPER OFFSET FROM SIO BASE ADDR TO ASR S/W REGISTERS. */
+#define JASPER_ASR_REG_OFFSET 0x38
+
+#define JASPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1, enable = 0 */
+#define JASPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define JUNIPER_BASE_ADDRESS 0x54b /* Base address of Juniper ASR */
+#define JUNIPER_ASR_DISABLE_MASK 0x01 /* bit 0: disable = 1 enable = 0 */
+#define JUNIPER_ASR_TOGGLE_MASK 0x02 /* bit 1: 0, then 1, then 0 */
+
+#define SPRUCE_BASE_ADDRESS 0x118e /* Base address of Spruce ASR */
+#define SPRUCE_ASR_DISABLE_MASK 0x01 /* bit 1: disable = 1 enable = 0 */
+#define SPRUCE_ASR_TOGGLE_MASK 0x02 /* bit 0: 0, then 1, then 0 */
+
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static unsigned long asr_is_open;
+static char asr_expect_close;
+
+static unsigned int asr_type, asr_base, asr_length;
+static unsigned int asr_read_addr, asr_write_addr;
+static unsigned char asr_toggle_mask, asr_disable_mask;
+
+static void asr_toggle(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg & ~asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+}
+
+static void asr_enable(void)
+{
+ unsigned char reg;
+
+ if (asr_type == ASMTYPE_TOPAZ) {
+ /* asr_write_addr == asr_read_addr */
+ reg = inb(asr_read_addr);
+ outb(reg & ~(TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE),
+ asr_read_addr);
+ } else {
+ /*
+ * First make sure the hardware timer is reset by toggling
+ * ASR hardware timer line.
+ */
+ asr_toggle();
+
+ reg = inb(asr_read_addr);
+ outb(reg & ~asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static void asr_disable(void)
+{
+ unsigned char reg = inb(asr_read_addr);
+
+ if (asr_type == ASMTYPE_TOPAZ)
+ /* asr_write_addr == asr_read_addr */
+ outb(reg | TOPAZ_ASR_TOGGLE | TOPAZ_ASR_DISABLE,
+ asr_read_addr);
+ else {
+ outb(reg | asr_toggle_mask, asr_write_addr);
+ reg = inb(asr_read_addr);
+
+ outb(reg | asr_disable_mask, asr_write_addr);
+ }
+ reg = inb(asr_read_addr);
+}
+
+static int __init asr_get_base_address(void)
+{
+ unsigned char low, high;
+ const char *type = "";
+
+ asr_length = 1;
+
+ switch (asr_type) {
+ case ASMTYPE_TOPAZ:
+ /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+ outb(0x07, 0x2e);
+ outb(0x07, 0x2f);
+
+ /* SELECT AND READ THE HIGH-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x60, 0x2e);
+ high = inb(0x2f);
+
+ /* SELECT AND READ THE LOW-NIBBLE OF THE GPIO BASE ADDRESS */
+ outb(0x61, 0x2e);
+ low = inb(0x2f);
+
+ asr_base = (high << 16) | low;
+ asr_read_addr = asr_write_addr =
+ asr_base + TOPAZ_ASR_REG_OFFSET;
+ asr_length = 5;
+
+ break;
+
+ case ASMTYPE_JASPER:
+ type = "Jaspers ";
+
+ /* FIXME: need to use pci_config_lock here, but it's not exported */
+
+/* spin_lock_irqsave(&pci_config_lock, flags);*/
+
+ /* Select the SuperIO chip in the PCI I/O port register */
+ outl(0x8000f858, 0xcf8);
+
+ /*
+ * Read the base address for the SuperIO chip.
+ * Only the lower 16 bits are valid, but the address is word
+ * aligned so the last bit must be masked off.
+ */
+ asr_base = inl(0xcfc) & 0xfffe;
+
+/* spin_unlock_irqrestore(&pci_config_lock, flags);*/
+
+ asr_read_addr = asr_write_addr =
+ asr_base + JASPER_ASR_REG_OFFSET;
+ asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JASPER_ASR_DISABLE_MASK;
+ asr_length = JASPER_ASR_REG_OFFSET + 1;
+
+ break;
+
+ case ASMTYPE_PEARL:
+ type = "Pearls ";
+ asr_base = PEARL_BASE;
+ asr_read_addr = PEARL_READ;
+ asr_write_addr = PEARL_WRITE;
+ asr_toggle_mask = PEARL_ASR_TOGGLE_MASK;
+ asr_disable_mask = PEARL_ASR_DISABLE_MASK;
+ asr_length = 4;
+ break;
+
+ case ASMTYPE_JUNIPER:
+ type = "Junipers ";
+ asr_base = JUNIPER_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = JUNIPER_ASR_TOGGLE_MASK;
+ asr_disable_mask = JUNIPER_ASR_DISABLE_MASK;
+ break;
+
+ case ASMTYPE_SPRUCE:
+ type = "Spruce's ";
+ asr_base = SPRUCE_BASE_ADDRESS;
+ asr_read_addr = asr_write_addr = asr_base;
+ asr_toggle_mask = SPRUCE_ASR_TOGGLE_MASK;
+ asr_disable_mask = SPRUCE_ASR_DISABLE_MASK;
+ break;
+ }
+
+ if (!request_region(asr_base, asr_length, "ibmasr")) {
+ printk(KERN_ERR PFX "address %#x already in use\n",
+ asr_base);
+ return -EBUSY;
+ }
+
+ printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+
+ return 0;
+}
+
+
+static ssize_t asr_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ asr_expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ asr_expect_close = 42;
+ }
+ }
+ asr_toggle();
+ }
+ return count;
+}
+
+static int asr_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ static const struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_MAGICCLOSE,
+ .identity = "IBM ASR"
+ };
+ void __user *argp = (void __user *)arg;
+ int __user *p = argp;
+ int heartbeat;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ?
+ -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ asr_toggle();
+ return 0;
+
+ /*
+ * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
+ * and WDIOC_GETTIMEOUT always returns 256.
+ */
+ case WDIOC_GETTIMEOUT:
+ heartbeat = 256;
+ return put_user(heartbeat, p);
+
+ case WDIOC_SETOPTIONS: {
+ int new_options, retval = -EINVAL;
+
+ if (get_user(new_options, p))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ asr_disable();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ asr_enable();
+ asr_toggle();
+ retval = 0;
+ }
+
+ return retval;
+ }
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static int asr_open(struct inode *inode, struct file *file)
+{
+ if(test_and_set_bit(0, &asr_is_open))
+ return -EBUSY;
+
+ asr_toggle();
+ asr_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int asr_release(struct inode *inode, struct file *file)
+{
+ if (asr_expect_close == 42)
+ asr_disable();
+ else {
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ asr_toggle();
+ }
+ clear_bit(0, &asr_is_open);
+ asr_expect_close = 0;
+ return 0;
+}
+
+static struct file_operations asr_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = asr_write,
+ .ioctl = asr_ioctl,
+ .open = asr_open,
+ .release = asr_release,
+};
+
+static struct miscdevice asr_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &asr_fops,
+};
+
+
+struct ibmasr_id {
+ const char *desc;
+ int type;
+};
+
+static struct ibmasr_id __initdata ibmasr_id_table[] = {
+ { "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
+ { "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
+ { "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
+ { "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
+ { "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
+ { NULL }
+};
+
+static int __init ibmasr_init(void)
+{
+ struct ibmasr_id *id;
+ int rc;
+
+ for (id = ibmasr_id_table; id->desc; id++) {
+ if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
+ asr_type = id->type;
+ break;
+ }
+ }
+
+ if (!asr_type)
+ return -ENODEV;
+
+ rc = misc_register(&asr_miscdev);
+ if (rc < 0) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ return rc;
+ }
+
+ rc = asr_get_base_address();
+ if (rc) {
+ misc_deregister(&asr_miscdev);
+ return rc;
+ }
+
+ return 0;
+}
+
+static void __exit ibmasr_exit(void)
+{
+ if (!nowayout)
+ asr_disable();
+
+ misc_deregister(&asr_miscdev);
+
+ release_region(asr_base, asr_length);
+}
+
+module_init(ibmasr_init);
+module_exit(ibmasr_exit);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
+MODULE_AUTHOR("Andrey Panin");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/mpcore_wdt.c b/drivers/char/watchdog/mpcore_wdt.c
index c694eee..75ca84e 100644
--- a/drivers/char/watchdog/mpcore_wdt.c
+++ b/drivers/char/watchdog/mpcore_wdt.c
@@ -30,6 +30,8 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+
+#include <asm/hardware/arm_twd.h>
#include <asm/uaccess.h>
struct mpcore_wdt {
diff --git a/drivers/char/watchdog/mv64x60_wdt.c b/drivers/char/watchdog/mv64x60_wdt.c
new file mode 100644
index 0000000..1436aea
--- /dev/null
+++ b/drivers/char/watchdog/mv64x60_wdt.c
@@ -0,0 +1,252 @@
+/*
+ * mv64x60_wdt.c - MV64X60 (Marvell Discovery) watchdog userspace interface
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Platform-specific setup code should configure the dog to generate
+ * interrupt or reset as required. This code only enables/disables
+ * and services the watchdog.
+ *
+ * Derived from mpc8xx_wdt.c, with the following copyright.
+ *
+ * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/watchdog.h>
+#include <asm/mv64x60.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* MV64x60 WDC (config) register access definitions */
+#define MV64x60_WDC_CTL1_MASK (3 << 24)
+#define MV64x60_WDC_CTL1(val) ((val & 3) << 24)
+#define MV64x60_WDC_CTL2_MASK (3 << 26)
+#define MV64x60_WDC_CTL2(val) ((val & 3) << 26)
+
+/* Flags bits */
+#define MV64x60_WDOG_FLAG_OPENED 0
+#define MV64x60_WDOG_FLAG_ENABLED 1
+
+static unsigned long wdt_flags;
+static int wdt_status;
+static void __iomem *mv64x60_regs;
+static int mv64x60_wdt_timeout;
+
+static void mv64x60_wdt_reg_write(u32 val)
+{
+ /* Allow write only to CTL1 / CTL2 fields, retaining values in
+ * other fields.
+ */
+ u32 data = readl(mv64x60_regs + MV64x60_WDT_WDC);
+ data &= ~(MV64x60_WDC_CTL1_MASK | MV64x60_WDC_CTL2_MASK);
+ data |= val;
+ writel(data, mv64x60_regs + MV64x60_WDT_WDC);
+}
+
+static void mv64x60_wdt_service(void)
+{
+ /* Write 01 followed by 10 to CTL2 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL2(0x02));
+}
+
+static void mv64x60_wdt_handler_disable(void)
+{
+ if (test_and_clear_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog deactivated\n");
+ }
+}
+
+static void mv64x60_wdt_handler_enable(void)
+{
+ if (!test_and_set_bit(MV64x60_WDOG_FLAG_ENABLED, &wdt_flags)) {
+ /* Write 01 followed by 10 to CTL1 */
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x01));
+ mv64x60_wdt_reg_write(MV64x60_WDC_CTL1(0x02));
+ printk(KERN_NOTICE "mv64x60_wdt: watchdog activated\n");
+ }
+}
+
+static int mv64x60_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags))
+ return -EBUSY;
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_enable();
+
+ return 0;
+}
+
+static int mv64x60_wdt_release(struct inode *inode, struct file *file)
+{
+ mv64x60_wdt_service();
+
+#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
+ mv64x60_wdt_handler_disable();
+#endif
+
+ clear_bit(MV64x60_WDOG_FLAG_OPENED, &wdt_flags);
+
+ return 0;
+}
+
+static ssize_t mv64x60_wdt_write(struct file *file, const char *data,
+ size_t len, loff_t * ppos)
+{
+ if (*ppos != file->f_pos)
+ return -ESPIPE;
+
+ if (len)
+ mv64x60_wdt_service();
+
+ return len;
+}
+
+static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int timeout;
+ static struct watchdog_info info = {
+ .options = WDIOF_KEEPALIVEPING,
+ .firmware_version = 0,
+ .identity = "MV64x60 watchdog",
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ if (put_user(wdt_status, (int *)arg))
+ return -EFAULT;
+ wdt_status &= ~WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_GETTEMP:
+ return -EOPNOTSUPP;
+
+ case WDIOC_SETOPTIONS:
+ return -EOPNOTSUPP;
+
+ case WDIOC_KEEPALIVE:
+ mv64x60_wdt_service();
+ wdt_status |= WDIOF_KEEPALIVEPING;
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ return -EOPNOTSUPP;
+
+ case WDIOC_GETTIMEOUT:
+ timeout = mv64x60_wdt_timeout * HZ;
+ if (put_user(timeout, (int *)arg))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ return 0;
+}
+
+static struct file_operations mv64x60_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = mv64x60_wdt_write,
+ .ioctl = mv64x60_wdt_ioctl,
+ .open = mv64x60_wdt_open,
+ .release = mv64x60_wdt_release,
+};
+
+static struct miscdevice mv64x60_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &mv64x60_wdt_fops,
+};
+
+static int __devinit mv64x60_wdt_probe(struct device *dev)
+{
+ struct platform_device *pd = to_platform_device(dev);
+ struct mv64x60_wdt_pdata *pdata = pd->dev.platform_data;
+ int bus_clk = 133;
+
+ mv64x60_wdt_timeout = 10;
+ if (pdata) {
+ mv64x60_wdt_timeout = pdata->timeout;
+ bus_clk = pdata->bus_clk;
+ }
+
+ mv64x60_regs = mv64x60_get_bridge_vbase();
+
+ writel((mv64x60_wdt_timeout * (bus_clk * 1000000)) >> 8,
+ mv64x60_regs + MV64x60_WDT_WDC);
+
+ return misc_register(&mv64x60_wdt_miscdev);
+}
+
+static int __devexit mv64x60_wdt_remove(struct device *dev)
+{
+ misc_deregister(&mv64x60_wdt_miscdev);
+
+ mv64x60_wdt_service();
+ mv64x60_wdt_handler_disable();
+
+ return 0;
+}
+
+static struct device_driver mv64x60_wdt_driver = {
+ .name = MV64x60_WDT_NAME,
+ .bus = &platform_bus_type,
+ .probe = mv64x60_wdt_probe,
+ .remove = __devexit_p(mv64x60_wdt_remove),
+};
+
+static struct platform_device *mv64x60_wdt_dev;
+
+static int __init mv64x60_wdt_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "MV64x60 watchdog driver\n");
+
+ mv64x60_wdt_dev = platform_device_register_simple(MV64x60_WDT_NAME,
+ -1, NULL, 0);
+ if (IS_ERR(mv64x60_wdt_dev)) {
+ ret = PTR_ERR(mv64x60_wdt_dev);
+ goto out;
+ }
+
+ ret = driver_register(&mv64x60_wdt_driver);
+ out:
+ return ret;
+}
+
+static void __exit mv64x60_wdt_exit(void)
+{
+ driver_unregister(&mv64x60_wdt_driver);
+ platform_device_unregister(mv64x60_wdt_dev);
+}
+
+module_init(mv64x60_wdt_init);
+module_exit(mv64x60_wdt_exit);
+
+MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
+MODULE_DESCRIPTION("MV64x60 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 2b13afb..5a80adb 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -29,27 +29,29 @@
* Includes, defines, variables, module parameters, ...
*/
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/spinlock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
+#include <linux/config.h> /* For CONFIG_WATCHDOG_NOWAYOUT/... */
+#include <linux/module.h> /* For module specific items */
+#include <linux/moduleparam.h> /* For new moduleparam's */
+#include <linux/types.h> /* For standard types (like size_t) */
+#include <linux/errno.h> /* For the -ENODEV/... values */
+#include <linux/kernel.h> /* For printk/panic/... */
+#include <linux/delay.h> /* For mdelay function */
+#include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
+#include <linux/watchdog.h> /* For the watchdog specific items */
+#include <linux/notifier.h> /* For notifier support */
+#include <linux/reboot.h> /* For reboot_notifier stuff */
+#include <linux/init.h> /* For __init/__exit/... */
+#include <linux/fs.h> /* For file operations */
+#include <linux/pci.h> /* For pci functions */
+#include <linux/ioport.h> /* For io-port access */
+#include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */
+
+#include <asm/uaccess.h> /* For copy_to_user/put_user/... */
+#include <asm/io.h> /* For inb/outb/... */
/* Module and version information */
#define WATCHDOG_VERSION "1.01"
-#define WATCHDOG_DATE "15 Mar 2005"
+#define WATCHDOG_DATE "02 Sep 2005"
#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
#define WATCHDOG_NAME "pcwd_pci"
#define PFX WATCHDOG_NAME ": "
@@ -335,12 +337,14 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
if (new_options & WDIOS_DISABLECARD) {
- pcipcwd_stop();
+ if (pcipcwd_stop())
+ return -EIO;
retval = 0;
}
if (new_options & WDIOS_ENABLECARD) {
- pcipcwd_start();
+ if (pcipcwd_start())
+ return -EIO;
retval = 0;
}
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 8b292bf..3625b26 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)
static unsigned long wtcon_save;
static unsigned long wtdat_save;
-static int s3c2410wdt_suspend(struct device *dev, u32 state, u32 level)
+static int s3c2410wdt_suspend(struct device *dev, pm_message_t state, u32 level)
{
if (level == SUSPEND_POWER_DOWN) {
/* 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 0000000..c6cbf80
--- /dev/null
+++ b/drivers/char/watchdog/sbc8360.c
@@ -0,0 +1,414 @@
+/*
+ * SBC8360 Watchdog driver
+ *
+ * (c) Copyright 2005 Webcon, Inc.
+ *
+ * Based on ib700wdt.c, which is based on advantechwdt.c which is based
+ * on acquirewdt.c which is based on wdt.c.
+ *
+ * (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ * Based on advantechwdt.c which is based on acquirewdt.c which
+ * is based on wdt.c.
+ *
+ * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ * Based on acquirewdt.c which is based on wdt.c.
+ * Original copyright messages:
+ *
+ * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ * http://www.redhat.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
+ *
+ * (c) Copyright 1995 Alan Cox <alan@redhat.com>
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ * Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * Added timeout module option to override default
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/notifier.h>
+#include <linux/fs.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/moduleparam.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long sbc8360_is_open;
+static spinlock_t sbc8360_lock;
+static char expect_close;
+
+#define PFX "sbc8360: "
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system automatically
+ * and is defined at I/O port 0120H and 0121H. To enable the watchdog timer
+ * and allow the system to reset, write appropriate values from the table
+ * below to I/O port 0120H and 0121H. To disable the timer, write a zero
+ * value to I/O port 0121H for the system to stop the watchdog function.
+ *
+ * The following describes how the timer should be programmed (according to
+ * the vendor documentation)
+ *
+ * Enabling Watchdog:
+ * MOV AX,000AH (enable, phase I)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000BH (enable, phase II)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000nH (set multiplier n, from 1-4)
+ * MOV DX,0120H
+ * OUT DX,AX
+ * MOV AX,000mH (set base timer m, from 0-F)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Reset timer:
+ * MOV AX,000mH (same as set base timer, above)
+ * MOV DX,0121H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,0000H (a zero value)
+ * MOV DX,0120H
+ * OUT DX,AX
+ *
+ * Watchdog timeout configuration values:
+ * N
+ * M | 1 2 3 4
+ * --|----------------------------------
+ * 0 | 0.5s 5s 50s 100s
+ * 1 | 1s 10s 100s 200s
+ * 2 | 1.5s 15s 150s 300s
+ * 3 | 2s 20s 200s 400s
+ * 4 | 2.5s 25s 250s 500s
+ * 5 | 3s 30s 300s 600s
+ * 6 | 3.5s 35s 350s 700s
+ * 7 | 4s 40s 400s 800s
+ * 8 | 4.5s 45s 450s 900s
+ * 9 | 5s 50s 500s 1000s
+ * A | 5.5s 55s 550s 1100s
+ * B | 6s 60s 600s 1200s
+ * C | 6.5s 65s 650s 1300s
+ * D | 7s 70s 700s 1400s
+ * E | 7.5s 75s 750s 1500s
+ * F | 8s 80s 800s 1600s
+ *
+ * Another way to say the same things is:
+ * For N=1, Timeout = (M+1) * 0.5s
+ * For N=2, Timeout = (M+1) * 5s
+ * For N=3, Timeout = (M+1) * 50s
+ * For N=4, Timeout = (M+1) * 100s
+ *
+ */
+
+static int wd_times[64][2] = {
+ {0, 1}, /* 0 = 0.5s */
+ {1, 1}, /* 1 = 1s */
+ {2, 1}, /* 2 = 1.5s */
+ {3, 1}, /* 3 = 2s */
+ {4, 1}, /* 4 = 2.5s */
+ {5, 1}, /* 5 = 3s */
+ {6, 1}, /* 6 = 3.5s */
+ {7, 1}, /* 7 = 4s */
+ {8, 1}, /* 8 = 4.5s */
+ {9, 1}, /* 9 = 5s */
+ {0xA, 1}, /* 10 = 5.5s */
+ {0xB, 1}, /* 11 = 6s */
+ {0xC, 1}, /* 12 = 6.5s */
+ {0xD, 1}, /* 13 = 7s */
+ {0xE, 1}, /* 14 = 7.5s */
+ {0xF, 1}, /* 15 = 8s */
+ {0, 2}, /* 16 = 5s */
+ {1, 2}, /* 17 = 10s */
+ {2, 2}, /* 18 = 15s */
+ {3, 2}, /* 19 = 20s */
+ {4, 2}, /* 20 = 25s */
+ {5, 2}, /* 21 = 30s */
+ {6, 2}, /* 22 = 35s */
+ {7, 2}, /* 23 = 40s */
+ {8, 2}, /* 24 = 45s */
+ {9, 2}, /* 25 = 50s */
+ {0xA, 2}, /* 26 = 55s */
+ {0xB, 2}, /* 27 = 60s */
+ {0xC, 2}, /* 28 = 65s */
+ {0xD, 2}, /* 29 = 70s */
+ {0xE, 2}, /* 30 = 75s */
+ {0xF, 2}, /* 31 = 80s */
+ {0, 3}, /* 32 = 50s */
+ {1, 3}, /* 33 = 100s */
+ {2, 3}, /* 34 = 150s */
+ {3, 3}, /* 35 = 200s */
+ {4, 3}, /* 36 = 250s */
+ {5, 3}, /* 37 = 300s */
+ {6, 3}, /* 38 = 350s */
+ {7, 3}, /* 39 = 400s */
+ {8, 3}, /* 40 = 450s */
+ {9, 3}, /* 41 = 500s */
+ {0xA, 3}, /* 42 = 550s */
+ {0xB, 3}, /* 43 = 600s */
+ {0xC, 3}, /* 44 = 650s */
+ {0xD, 3}, /* 45 = 700s */
+ {0xE, 3}, /* 46 = 750s */
+ {0xF, 3}, /* 47 = 800s */
+ {0, 4}, /* 48 = 100s */
+ {1, 4}, /* 49 = 200s */
+ {2, 4}, /* 50 = 300s */
+ {3, 4}, /* 51 = 400s */
+ {4, 4}, /* 52 = 500s */
+ {5, 4}, /* 53 = 600s */
+ {6, 4}, /* 54 = 700s */
+ {7, 4}, /* 55 = 800s */
+ {8, 4}, /* 56 = 900s */
+ {9, 4}, /* 57 = 1000s */
+ {0xA, 4}, /* 58 = 1100s */
+ {0xB, 4}, /* 59 = 1200s */
+ {0xC, 4}, /* 60 = 1300s */
+ {0xD, 4}, /* 61 = 1400s */
+ {0xE, 4}, /* 62 = 1500s */
+ {0xF, 4} /* 63 = 1600s */
+};
+
+#define SBC8360_ENABLE 0x120
+#define SBC8360_BASETIME 0x121
+
+static int timeout = 27;
+static int wd_margin = 0xB;
+static int wd_multiplier = 2;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(timeout, int, 27);
+MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))");
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Kernel methods.
+ */
+
+/* Activate and pre-configure watchdog */
+static void sbc8360_activate(void)
+{
+ /* Enable the watchdog */
+ outb(0x0A, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ outb(0x0B, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Set timeout multiplier */
+ outb(wd_multiplier, SBC8360_ENABLE);
+ msleep_interruptible(100);
+ /* Nothing happens until first sbc8360_ping() */
+}
+
+/* Kernel pings watchdog */
+static void sbc8360_ping(void)
+{
+ /* Write the base timer register */
+ outb(wd_margin, SBC8360_BASETIME);
+}
+
+/* Userspace pings kernel driver, or requests clean close */
+static ssize_t sbc8360_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * ppos)
+{
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* In case it was set long ago */
+ expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ expect_close = 42;
+ }
+ }
+ sbc8360_ping();
+ }
+ return count;
+}
+
+static int sbc8360_open(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (test_and_set_bit(0, &sbc8360_is_open)) {
+ spin_unlock(&sbc8360_lock);
+ return -EBUSY;
+ }
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ /* Activate and ping once to start the countdown */
+ spin_unlock(&sbc8360_lock);
+ sbc8360_activate();
+ sbc8360_ping();
+ return nonseekable_open(inode, file);
+}
+
+static int sbc8360_close(struct inode *inode, struct file *file)
+{
+ spin_lock(&sbc8360_lock);
+ if (expect_close == 42)
+ outb(0, SBC8360_ENABLE);
+ else
+ printk(KERN_CRIT PFX
+ "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n");
+
+ clear_bit(0, &sbc8360_is_open);
+ expect_close = 0;
+ spin_unlock(&sbc8360_lock);
+ return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code == SYS_DOWN || code == SYS_HALT) {
+ /* Disable the SBC8360 Watchdog */
+ outb(0, SBC8360_ENABLE);
+ }
+ return NOTIFY_DONE;
+}
+
+/*
+ * Kernel Interfaces
+ */
+
+static struct file_operations sbc8360_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = sbc8360_write,
+ .open = sbc8360_open,
+ .release = sbc8360_close,
+};
+
+static struct miscdevice sbc8360_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &sbc8360_fops,
+};
+
+/*
+ * The SBC8360 needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block sbc8360_notifier = {
+ .notifier_call = sbc8360_notify_sys,
+};
+
+static int __init sbc8360_init(void)
+{
+ int res;
+ unsigned long int mseconds = 60000;
+
+ spin_lock_init(&sbc8360_lock);
+ res = misc_register(&sbc8360_miscdev);
+ if (res) {
+ printk(KERN_ERR PFX "failed to register misc device\n");
+ goto out_nomisc;
+ }
+
+ if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
+ printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
+ SBC8360_ENABLE);
+ res = -EIO;
+ goto out_noenablereg;
+ }
+ if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
+ printk(KERN_ERR PFX
+ "BASETIME method I/O %X is not available.\n",
+ SBC8360_BASETIME);
+ res = -EIO;
+ goto out_nobasetimereg;
+ }
+
+ res = register_reboot_notifier(&sbc8360_notifier);
+ if (res) {
+ printk(KERN_ERR PFX "Failed to register reboot notifier.\n");
+ goto out_noreboot;
+ }
+
+ if (timeout < 0 || timeout > 63) {
+ printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+ res = -EINVAL;
+ goto out_noreboot;
+ }
+
+ wd_margin = wd_times[timeout][0];
+ wd_multiplier = wd_times[timeout][1];
+
+ if (wd_multiplier == 1)
+ mseconds = (wd_margin + 1) * 500;
+ else if (wd_multiplier == 2)
+ mseconds = (wd_margin + 1) * 5000;
+ else if (wd_multiplier == 3)
+ mseconds = (wd_margin + 1) * 50000;
+ else if (wd_multiplier == 4)
+ mseconds = (wd_margin + 1) * 100000;
+
+ /* My kingdom for the ability to print "0.5 seconds" in the kernel! */
+ printk(KERN_INFO PFX "Timeout set at %ld ms.\n", mseconds);
+
+ return 0;
+
+ out_noreboot:
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+ out_noenablereg:
+ out_nobasetimereg:
+ misc_deregister(&sbc8360_miscdev);
+ out_nomisc:
+ return res;
+}
+
+static void __exit sbc8360_exit(void)
+{
+ misc_deregister(&sbc8360_miscdev);
+ unregister_reboot_notifier(&sbc8360_notifier);
+ release_region(SBC8360_ENABLE, 1);
+ release_region(SBC8360_BASETIME, 1);
+}
+
+module_init(sbc8360_init);
+module_exit(sbc8360_exit);
+
+MODULE_AUTHOR("Ian E. Morgan <imorgan@webcon.ca>");
+MODULE_DESCRIPTION("SBC8360 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.0");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+
+/* 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 0000000..a7ff64c
--- /dev/null
+++ b/drivers/char/watchdog/w83977f_wdt.c
@@ -0,0 +1,543 @@
+/*
+ * W83977F Watchdog Timer Driver for Winbond W83977F I/O Chip
+ *
+ * (c) Copyright 2005 Jose Goncalves <jose.goncalves@inov.pt>
+ *
+ * Based on w83877f_wdt.c by Scott Jennings,
+ * and wdt977.c by Woody Suwalski
+ *
+ * -----------------------
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#define WATCHDOG_VERSION "1.00"
+#define WATCHDOG_NAME "W83977F WDT"
+#define PFX WATCHDOG_NAME ": "
+#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n"
+
+#define IO_INDEX_PORT 0x3F0
+#define IO_DATA_PORT (IO_INDEX_PORT+1)
+
+#define UNLOCK_DATA 0x87
+#define LOCK_DATA 0xAA
+#define DEVICE_REGISTER 0x07
+
+#define DEFAULT_TIMEOUT 45 /* default timeout in seconds */
+
+static int timeout = DEFAULT_TIMEOUT;
+static int timeoutW; /* timeout in watchdog counter units */
+static unsigned long timer_alive;
+static int testmode;
+static char expect_close;
+static spinlock_t spinlock;
+
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")");
+module_param(testmode, int, 0);
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
+
+/*
+ * Start the watchdog
+ */
+
+static int wdt_start(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 has the timeout in watchdog counter units.
+ * F3 is set to enable watchdog LED blink at timeout.
+ * F4 is used to just clear the TIMEOUT'ed state (bit 0).
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /* Set device Aux2 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 as the watchdog output
+ * (in reg E6) and GP13 as the watchdog LED output (in reg E3).
+ * Map GP16 at pin 119.
+ * In test mode watch the bit 0 on F4 to indicate "triggered" or
+ * check watchdog LED on SBC.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ unsigned pin_map;
+
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x0A,IO_DATA_PORT);
+ outb_p(0x2C,IO_INDEX_PORT);
+ pin_map = inb_p(IO_DATA_PORT);
+ pin_map |= 0x10;
+ pin_map &= ~(0x20);
+ outb_p(0x2C,IO_INDEX_PORT);
+ outb_p(pin_map,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+
+ /* Set device Aux1 active */
+ outb_p(0x30,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "activated.\n");
+
+ return 0;
+}
+
+/*
+ * Stop the watchdog
+ */
+
+static int wdt_stop(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /*
+ * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4.
+ * F2 is reset to its default value (watchdog timer disabled).
+ * F3 is reset to its default state.
+ * F4 clears the TIMEOUT'ed state (bit 0) - back to default.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0xFF,IO_DATA_PORT);
+ outb_p(0xF3,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(0x00,IO_DATA_PORT);
+
+ /*
+ * Select device Aux1 (dev=7) to set GP16 (in reg E6) and
+ * Gp13 (in reg E3) as inputs.
+ */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x07,IO_DATA_PORT);
+ if (!testmode)
+ {
+ outb_p(0xE6,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+ }
+ outb_p(0xE3,IO_INDEX_PORT);
+ outb_p(0x01,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ printk(KERN_INFO PFX "shutdown.\n");
+
+ return 0;
+}
+
+/*
+ * Send a keepalive ping to the watchdog
+ * This is done by simply re-writing the timeout to reg. 0xF2
+ */
+
+static int wdt_keepalive(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to kick watchdog reg F2 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF2,IO_INDEX_PORT);
+ outb_p(timeoutW,IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ return 0;
+}
+
+/*
+ * Set the watchdog timeout value
+ */
+
+static int wdt_set_timeout(int t)
+{
+ int tmrval;
+
+ /*
+ * Convert seconds to watchdog counter time units, rounding up.
+ * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup
+ * value. This information is supplied in the PCM-5335 manual and was
+ * checked by me on a real board. This is a bit strange because W83977f
+ * datasheet says counter unit is in minutes!
+ */
+ if (t < 15)
+ return -EINVAL;
+
+ tmrval = ((t + 15) + 29) / 30;
+
+ if (tmrval > 255)
+ return -EINVAL;
+
+ /*
+ * timeout is the timeout in seconds,
+ * timeoutW is the timeout in watchdog counter units.
+ */
+ timeoutW = tmrval;
+ timeout = (timeoutW * 30) - 15;
+ return 0;
+}
+
+/*
+ * Get the watchdog status
+ */
+
+static int wdt_get_status(int *status)
+{
+ int new_status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&spinlock, flags);
+
+ /* Unlock the SuperIO chip */
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+ outb_p(UNLOCK_DATA,IO_INDEX_PORT);
+
+ /* Select device Aux2 (device=8) to read watchdog reg F4 */
+ outb_p(DEVICE_REGISTER,IO_INDEX_PORT);
+ outb_p(0x08,IO_DATA_PORT);
+ outb_p(0xF4,IO_INDEX_PORT);
+ new_status = inb_p(IO_DATA_PORT);
+
+ /* Lock the SuperIO chip */
+ outb_p(LOCK_DATA,IO_INDEX_PORT);
+
+ spin_unlock_irqrestore(&spinlock, flags);
+
+ *status = 0;
+ if (new_status & 1)
+ *status |= WDIOF_CARDRESET;
+
+ return 0;
+}
+
+
+/*
+ * /dev/watchdog handling
+ */
+
+static int wdt_open(struct inode *inode, struct file *file)
+{
+ /* If the watchdog is alive we don't need to start it again */
+ if( test_and_set_bit(0, &timer_alive) )
+ return -EBUSY;
+
+ if (nowayout)
+ __module_get(THIS_MODULE);
+
+ wdt_start();
+ return nonseekable_open(inode, file);
+}
+
+static int wdt_release(struct inode *inode, struct file *file)
+{
+ /*
+ * Shut off the timer.
+ * Lock it in if it's a module and we set nowayout
+ */
+ if (expect_close == 42)
+ {
+ wdt_stop();
+ clear_bit(0, &timer_alive);
+ } else {
+ wdt_keepalive();
+ printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ }
+ expect_close = 0;
+ return 0;
+}
+
+/*
+ * wdt_write:
+ * @file: file handle to the watchdog
+ * @buf: buffer to write (unused as data does not matter here
+ * @count: count of bytes
+ * @ppos: pointer to the position to write. No seeks allowed
+ *
+ * A write to a watchdog device is defined as a keepalive signal. Any
+ * write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /* See if we got the magic character 'V' and reload the timer */
+ if(count)
+ {
+ if (!nowayout)
+ {
+ size_t ofs;
+
+ /* note: just in case someone wrote the magic character long ago */
+ expect_close = 0;
+
+ /* scan to see whether or not we got the magic character */
+ for(ofs = 0; ofs != count; ofs++)
+ {
+ char c;
+ if (get_user(c, buf + ofs))
+ return -EFAULT;
+ if (c == 'V') {
+ expect_close = 42;
+ }
+ }
+ }
+
+ /* someone wrote to us, we should restart timer */
+ wdt_keepalive();
+ }
+ return count;
+}
+
+/*
+ * wdt_ioctl:
+ * @inode: inode of the device
+ * @file: file handle to the device
+ * @cmd: watchdog command
+ * @arg: argument pointer
+ *
+ * The watchdog API defines a common set of functions for all watchdogs
+ * according to their available features.
+ */
+
+static struct watchdog_info ident = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .firmware_version = 1,
+ .identity = WATCHDOG_NAME,
+};
+
+static int wdt_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int status;
+ int new_options, retval = -EINVAL;
+ int new_timeout;
+ union {
+ struct watchdog_info __user *ident;
+ int __user *i;
+ } uarg;
+
+ uarg.i = (int __user *)arg;
+
+ switch(cmd)
+ {
+ default:
+ return -ENOIOCTLCMD;
+
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;
+
+ case WDIOC_GETSTATUS:
+ wdt_get_status(&status);
+ return put_user(status, uarg.i);
+
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, uarg.i);
+
+ case WDIOC_KEEPALIVE:
+ wdt_keepalive();
+ return 0;
+
+ case WDIOC_SETOPTIONS:
+ if (get_user (new_options, uarg.i))
+ return -EFAULT;
+
+ if (new_options & WDIOS_DISABLECARD) {
+ wdt_stop();
+ retval = 0;
+ }
+
+ if (new_options & WDIOS_ENABLECARD) {
+ wdt_start();
+ retval = 0;
+ }
+
+ return retval;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(new_timeout, uarg.i))
+ return -EFAULT;
+
+ if (wdt_set_timeout(new_timeout))
+ return -EINVAL;
+
+ wdt_keepalive();
+ /* Fall */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(timeout, uarg.i);
+
+ }
+}
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ if (code==SYS_DOWN || code==SYS_HALT)
+ wdt_stop();
+ return NOTIFY_DONE;
+}
+
+static struct file_operations wdt_fops=
+{
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = wdt_write,
+ .ioctl = wdt_ioctl,
+ .open = wdt_open,
+ .release = wdt_release,
+};
+
+static struct miscdevice wdt_miscdev=
+{
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdt_fops,
+};
+
+static struct notifier_block wdt_notifier = {
+ .notifier_call = wdt_notify_sys,
+};
+
+static int __init w83977f_wdt_init(void)
+{
+ int rc;
+
+ printk(KERN_INFO PFX DRIVER_VERSION);
+
+ spin_lock_init(&spinlock);
+
+ /*
+ * Check that the timeout value is within it's range ;
+ * if not reset to the default
+ */
+ if (wdt_set_timeout(timeout)) {
+ wdt_set_timeout(DEFAULT_TIMEOUT);
+ printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n",
+ DEFAULT_TIMEOUT);
+ }
+
+ if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME))
+ {
+ printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
+ IO_INDEX_PORT);
+ rc = -EIO;
+ goto err_out;
+ }
+
+ rc = misc_register(&wdt_miscdev);
+ if (rc)
+ {
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ wdt_miscdev.minor, rc);
+ goto err_out_region;
+ }
+
+ rc = register_reboot_notifier(&wdt_notifier);
+ if (rc)
+ {
+ printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
+ rc);
+ goto err_out_miscdev;
+ }
+
+ printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
+ timeout, nowayout, testmode);
+
+ return 0;
+
+err_out_miscdev:
+ misc_deregister(&wdt_miscdev);
+err_out_region:
+ release_region(IO_INDEX_PORT,2);
+err_out:
+ return rc;
+}
+
+static void __exit w83977f_wdt_exit(void)
+{
+ wdt_stop();
+ misc_deregister(&wdt_miscdev);
+ unregister_reboot_notifier(&wdt_notifier);
+ release_region(IO_INDEX_PORT,2);
+}
+
+module_init(w83977f_wdt_init);
+module_exit(w83977f_wdt_exit);
+
+MODULE_AUTHOR("Jose Goncalves <jose.goncalves@inov.pt>");
+MODULE_DESCRIPTION("Driver for watchdog timer in W83977F I/O chip");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 3b865f3..b667823 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -50,7 +50,7 @@
MODULE_AUTHOR("Abhay Salunke <abhay_salunke@dell.com>");
MODULE_DESCRIPTION("Driver for updating BIOS image on DELL systems");
MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
+MODULE_VERSION("2.0");
#define BIOS_SCAN_LIMIT 0xffffffff
#define MAX_IMAGE_LENGTH 16
@@ -65,10 +65,11 @@ static struct _rbu_data {
unsigned long packet_write_count;
unsigned long num_packets;
unsigned long packetsize;
+ int entry_created;
} rbu_data;
-static char image_type[MAX_IMAGE_LENGTH] = "mono";
-module_param_string(image_type, image_type, sizeof(image_type), 0);
+static char image_type[MAX_IMAGE_LENGTH + 1] = "mono";
+module_param_string(image_type, image_type, sizeof (image_type), 0);
MODULE_PARM_DESC(image_type, "BIOS image type. choose- mono or packet");
struct packet_data {
@@ -114,7 +115,7 @@ static int fill_last_packet(void *data, size_t length)
if ((rbu_data.packet_write_count + length) > rbu_data.packetsize) {
pr_debug("dell_rbu:%s: packet size data "
- "overrun\n", __FUNCTION__);
+ "overrun\n", __FUNCTION__);
return -EINVAL;
}
@@ -146,12 +147,14 @@ static int create_packet(size_t length)
pr_debug("create_packet: packetsize not specified\n");
return -EINVAL;
}
+ spin_unlock(&rbu_data.lock);
+ newpacket = kmalloc(sizeof (struct packet_data), GFP_KERNEL);
+ spin_lock(&rbu_data.lock);
- newpacket = kmalloc(sizeof(struct packet_data), GFP_KERNEL);
if (!newpacket) {
printk(KERN_WARNING
- "dell_rbu:%s: failed to allocate new "
- "packet\n", __FUNCTION__);
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
return -ENOMEM;
}
@@ -160,15 +163,17 @@ static int create_packet(size_t length)
* there is no upper limit on memory
* address for packetized mechanism
*/
- newpacket->data = (unsigned char *)__get_free_pages(GFP_KERNEL,
- ordernum);
+ spin_unlock(&rbu_data.lock);
+ newpacket->data = (unsigned char *) __get_free_pages(GFP_KERNEL,
+ ordernum);
+ spin_lock(&rbu_data.lock);
pr_debug("create_packet: newpacket %p\n", newpacket->data);
if (!newpacket->data) {
printk(KERN_WARNING
- "dell_rbu:%s: failed to allocate new "
- "packet\n", __FUNCTION__);
+ "dell_rbu:%s: failed to allocate new "
+ "packet\n", __FUNCTION__);
kfree(newpacket);
return -ENOMEM;
}
@@ -204,9 +209,8 @@ static int packetize_data(void *data, size_t length)
return rc;
}
-static int
-do_packet_read(char *data, struct list_head *ptemp_list,
- int length, int bytes_read, int *list_read_count)
+static int do_packet_read(char *data, struct list_head *ptemp_list,
+ int length, int bytes_read, int *list_read_count)
{
void *ptemp_buf;
struct packet_data *newpacket = NULL;
@@ -239,7 +243,7 @@ do_packet_read(char *data, struct list_head *ptemp_list,
return bytes_copied;
}
-static int packet_read_list(char *data, size_t * pread_length)
+static int packet_read_list(char *data, size_t *pread_length)
{
struct list_head *ptemp_list;
int temp_count = 0;
@@ -258,8 +262,7 @@ static int packet_read_list(char *data, size_t * pread_length)
ptemp_list = (&packet_data_head.list)->next;
while (!list_empty(ptemp_list)) {
bytes_copied = do_packet_read(pdest, ptemp_list,
- remaining_bytes, bytes_read,
- &temp_count);
+ remaining_bytes, bytes_read, &temp_count);
remaining_bytes -= bytes_copied;
bytes_read += bytes_copied;
pdest += bytes_copied;
@@ -287,7 +290,7 @@ static void packet_empty_list(void)
ptemp_list = (&packet_data_head.list)->next;
while (!list_empty(ptemp_list)) {
newpacket =
- list_entry(ptemp_list, struct packet_data, list);
+ list_entry(ptemp_list, struct packet_data, list);
pnext_list = ptemp_list->next;
list_del(ptemp_list);
ptemp_list = pnext_list;
@@ -296,8 +299,8 @@ static void packet_empty_list(void)
* to make sure there are no stale RBU packets left in memory
*/
memset(newpacket->data, 0, rbu_data.packetsize);
- free_pages((unsigned long)newpacket->data,
- newpacket->ordernum);
+ free_pages((unsigned long) newpacket->data,
+ newpacket->ordernum);
kfree(newpacket);
}
rbu_data.packet_write_count = 0;
@@ -319,14 +322,13 @@ static void img_update_free(void)
* BIOS image copied in memory.
*/
memset(rbu_data.image_update_buffer, 0,
- rbu_data.image_update_buffer_size);
+ rbu_data.image_update_buffer_size);
if (rbu_data.dma_alloc == 1)
dma_free_coherent(NULL, rbu_data.bios_image_size,
- rbu_data.image_update_buffer,
- dell_rbu_dmaaddr);
+ rbu_data.image_update_buffer, dell_rbu_dmaaddr);
else
- free_pages((unsigned long)rbu_data.image_update_buffer,
- rbu_data.image_update_ordernum);
+ free_pages((unsigned long) rbu_data.image_update_buffer,
+ rbu_data.image_update_ordernum);
/*
* Re-initialize the rbu_data variables after a free
@@ -366,7 +368,7 @@ static int img_update_realloc(unsigned long size)
*/
if ((size != 0) && (rbu_data.image_update_buffer == NULL)) {
printk(KERN_ERR "dell_rbu:%s: corruption "
- "check failed\n", __FUNCTION__);
+ "check failed\n", __FUNCTION__);
return -EINVAL;
}
/*
@@ -385,17 +387,16 @@ static int img_update_realloc(unsigned long size)
ordernum = get_order(size);
image_update_buffer =
- (unsigned char *)__get_free_pages(GFP_KERNEL, ordernum);
+ (unsigned char *) __get_free_pages(GFP_KERNEL, ordernum);
img_buf_phys_addr =
- (unsigned long)virt_to_phys(image_update_buffer);
+ (unsigned long) virt_to_phys(image_update_buffer);
if (img_buf_phys_addr > BIOS_SCAN_LIMIT) {
- free_pages((unsigned long)image_update_buffer, ordernum);
+ free_pages((unsigned long) image_update_buffer, ordernum);
ordernum = -1;
image_update_buffer = dma_alloc_coherent(NULL, size,
- &dell_rbu_dmaaddr,
- GFP_KERNEL);
+ &dell_rbu_dmaaddr, GFP_KERNEL);
dma_alloc = 1;
}
@@ -405,13 +406,13 @@ static int img_update_realloc(unsigned long size)
rbu_data.image_update_buffer = image_update_buffer;
rbu_data.image_update_buffer_size = size;
rbu_data.bios_image_size =
- rbu_data.image_update_buffer_size;
+ rbu_data.image_update_buffer_size;
rbu_data.image_update_ordernum = ordernum;
rbu_data.dma_alloc = dma_alloc;
rc = 0;
} else {
pr_debug("Not enough memory for image update:"
- "size = %ld\n", size);
+ "size = %ld\n", size);
rc = -ENOMEM;
}
@@ -438,7 +439,7 @@ static ssize_t read_packet_data(char *buffer, loff_t pos, size_t count)
if (pos > imagesize) {
retval = 0;
printk(KERN_WARNING "dell_rbu:read_packet_data: "
- "data underrun\n");
+ "data underrun\n");
goto read_rbu_data_exit;
}
@@ -468,11 +469,11 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
/* check to see if we have something to return */
if ((rbu_data.image_update_buffer == NULL) ||
- (rbu_data.bios_image_size == 0)) {
+ (rbu_data.bios_image_size == 0)) {
pr_debug("read_rbu_data_mono: image_update_buffer %p ,"
- "bios_image_size %lu\n",
- rbu_data.image_update_buffer,
- rbu_data.bios_image_size);
+ "bios_image_size %lu\n",
+ rbu_data.image_update_buffer,
+ rbu_data.bios_image_size);
ret_count = -ENOMEM;
goto read_rbu_data_exit;
}
@@ -497,8 +498,8 @@ static ssize_t read_rbu_mono_data(char *buffer, loff_t pos, size_t count)
return ret_count;
}
-static ssize_t
-read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
+static ssize_t read_rbu_data(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
{
ssize_t ret_count = 0;
@@ -515,62 +516,20 @@ read_rbu_data(struct kobject *kobj, char *buffer, loff_t pos, size_t count)
return ret_count;
}
-static ssize_t
-read_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
- size_t count)
-{
- int size = 0;
- if (!pos)
- size = sprintf(buffer, "%s\n", image_type);
- return size;
-}
-
-static ssize_t
-write_rbu_image_type(struct kobject *kobj, char *buffer, loff_t pos,
- size_t count)
-{
- int rc = count;
- spin_lock(&rbu_data.lock);
-
- if (strlen(buffer) < MAX_IMAGE_LENGTH)
- sscanf(buffer, "%s", image_type);
- else
- printk(KERN_WARNING "dell_rbu: image_type is invalid"
- "max chars = %d, \n incoming str--%s-- \n",
- MAX_IMAGE_LENGTH, buffer);
-
- /* we must free all previous allocations */
- packet_empty_list();
- img_update_free();
-
- spin_unlock(&rbu_data.lock);
- return rc;
-
-}
-
-static struct bin_attribute rbu_data_attr = {
- .attr = {.name = "data",.owner = THIS_MODULE,.mode = 0444},
- .read = read_rbu_data,
-};
-
-static struct bin_attribute rbu_image_type_attr = {
- .attr = {.name = "image_type",.owner = THIS_MODULE,.mode = 0644},
- .read = read_rbu_image_type,
- .write = write_rbu_image_type,
-};
-
static void callbackfn_rbu(const struct firmware *fw, void *context)
{
int rc = 0;
- if (!fw || !fw->size)
+ if (!fw || !fw->size) {
+ rbu_data.entry_created = 0;
return;
+ }
spin_lock(&rbu_data.lock);
if (!strcmp(image_type, "mono")) {
if (!img_update_realloc(fw->size))
memcpy(rbu_data.image_update_buffer,
- fw->data, fw->size);
+ fw->data, fw->size);
} else if (!strcmp(image_type, "packet")) {
if (!rbu_data.packetsize)
rbu_data.packetsize = fw->size;
@@ -584,14 +543,103 @@ static void callbackfn_rbu(const struct firmware *fw, void *context)
spin_unlock(&rbu_data.lock);
rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "dell_rbu", &rbu_device->dev,
- &context, callbackfn_rbu);
+ "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
if (rc)
printk(KERN_ERR
- "dell_rbu:%s request_firmware_nowait failed"
- " %d\n", __FUNCTION__, rc);
+ "dell_rbu:%s request_firmware_nowait failed"
+ " %d\n", __FUNCTION__, rc);
+ else
+ rbu_data.entry_created = 1;
+}
+
+static ssize_t read_rbu_image_type(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ int size = 0;
+ if (!pos)
+ size = sprintf(buffer, "%s\n", image_type);
+ return size;
+}
+
+static ssize_t write_rbu_image_type(struct kobject *kobj, char *buffer,
+ loff_t pos, size_t count)
+{
+ int rc = count;
+ int req_firm_rc = 0;
+ int i;
+ spin_lock(&rbu_data.lock);
+ /*
+ * Find the first newline or space
+ */
+ for (i = 0; i < count; ++i)
+ if (buffer[i] == '\n' || buffer[i] == ' ') {
+ buffer[i] = '\0';
+ break;
+ }
+ if (i == count)
+ buffer[count] = '\0';
+
+ if (strstr(buffer, "mono"))
+ strcpy(image_type, "mono");
+ else if (strstr(buffer, "packet"))
+ strcpy(image_type, "packet");
+ else if (strstr(buffer, "init")) {
+ /*
+ * If due to the user error the driver gets in a bad
+ * state where even though it is loaded , the
+ * /sys/class/firmware/dell_rbu entries are missing.
+ * to cover this situation the user can recreate entries
+ * by writing init to image_type.
+ */
+ if (!rbu_data.entry_created) {
+ spin_unlock(&rbu_data.lock);
+ req_firm_rc = request_firmware_nowait(THIS_MODULE,
+ FW_ACTION_NOHOTPLUG, "dell_rbu",
+ &rbu_device->dev, &context,
+ callbackfn_rbu);
+ if (req_firm_rc) {
+ printk(KERN_ERR
+ "dell_rbu:%s request_firmware_nowait"
+ " failed %d\n", __FUNCTION__, rc);
+ rc = -EIO;
+ } else
+ rbu_data.entry_created = 1;
+
+ spin_lock(&rbu_data.lock);
+ }
+ } else {
+ printk(KERN_WARNING "dell_rbu: image_type is invalid\n");
+ spin_unlock(&rbu_data.lock);
+ return -EINVAL;
+ }
+
+ /* we must free all previous allocations */
+ packet_empty_list();
+ img_update_free();
+ spin_unlock(&rbu_data.lock);
+
+ return rc;
}
+static struct bin_attribute rbu_data_attr = {
+ .attr = {
+ .name = "data",
+ .owner = THIS_MODULE,
+ .mode = 0444,
+ },
+ .read = read_rbu_data,
+};
+
+static struct bin_attribute rbu_image_type_attr = {
+ .attr = {
+ .name = "image_type",
+ .owner = THIS_MODULE,
+ .mode = 0644,
+ },
+ .read = read_rbu_image_type,
+ .write = write_rbu_image_type,
+};
+
static int __init dcdrbu_init(void)
{
int rc = 0;
@@ -599,11 +647,11 @@ static int __init dcdrbu_init(void)
init_packet_head();
rbu_device =
- platform_device_register_simple("dell_rbu", -1, NULL, 0);
+ platform_device_register_simple("dell_rbu", -1, NULL, 0);
if (!rbu_device) {
printk(KERN_ERR
- "dell_rbu:%s:platform_device_register_simple "
- "failed\n", __FUNCTION__);
+ "dell_rbu:%s:platform_device_register_simple "
+ "failed\n", __FUNCTION__);
return -EIO;
}
@@ -611,11 +659,12 @@ static int __init dcdrbu_init(void)
sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_image_type_attr);
rc = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- "dell_rbu", &rbu_device->dev,
- &context, callbackfn_rbu);
+ "dell_rbu", &rbu_device->dev, &context, callbackfn_rbu);
if (rc)
printk(KERN_ERR "dell_rbu:%s:request_firmware_nowait"
- " failed %d\n", __FUNCTION__, rc);
+ " failed %d\n", __FUNCTION__, rc);
+ else
+ rbu_data.entry_created = 1;
return rc;
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index eaebfc1..4c56411 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -5,10 +5,10 @@
* Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
*
* The HardDisk Active Protection System (hdaps) is present in the IBM ThinkPad
- * T41, T42, T43, R51, and X40, at least. It provides a basic two-axis
- * accelerometer and other data, such as the device's temperature.
+ * T41, T42, T43, R50, R50p, R51, and X40, at least. It provides a basic
+ * two-axis accelerometer and other data, such as the device's temperature.
*
- * Based on the document by Mark A. Smith available at
+ * This driver is based on the document by Mark A. Smith available at
* http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
* and error.
*
@@ -36,12 +36,7 @@
#include <asm/io.h>
#define HDAPS_LOW_PORT 0x1600 /* first port used by hdaps */
-#define HDAPS_NR_PORTS 0x30 /* 0x1600 - 0x162f */
-
-#define STATE_FRESH 0x50 /* accelerometer data is fresh */
-
-#define REFRESH_ASYNC 0x00 /* do asynchronous refresh */
-#define REFRESH_SYNC 0x01 /* do synchronous refresh */
+#define HDAPS_NR_PORTS 0x30 /* number of ports: 0x1600 - 0x162f */
#define HDAPS_PORT_STATE 0x1611 /* device state */
#define HDAPS_PORT_YPOS 0x1612 /* y-axis position */
@@ -53,7 +48,7 @@
#define HDAPS_PORT_UNKNOWN 0x161c /* what is this? */
#define HDAPS_PORT_KMACT 0x161d /* keyboard or mouse activity */
-#define HDAPS_READ_MASK 0xff /* some reads have the low 8 bits set */
+#define STATE_FRESH 0x50 /* accelerometer data is fresh */
#define KEYBD_MASK 0x20 /* set if keyboard activity */
#define MOUSE_MASK 0x40 /* set if mouse activity */
@@ -63,12 +58,11 @@
#define INIT_TIMEOUT_MSECS 4000 /* wait up to 4s for device init ... */
#define INIT_WAIT_MSECS 200 /* ... in 200ms increments */
-static struct platform_device *pdev;
-static struct input_dev hdaps_idev;
+#define HDAPS_POLL_PERIOD (HZ/20) /* poll for input every 1/20s */
+#define HDAPS_INPUT_FUZZ 4 /* input event threshold */
+
static struct timer_list hdaps_timer;
-static unsigned int hdaps_mousedev_threshold = 4;
-static unsigned long hdaps_poll_ms = 50;
-static unsigned int hdaps_mousedev;
+static struct platform_device *pdev;
static unsigned int hdaps_invert;
static u8 km_activity;
static int rest_x;
@@ -81,14 +75,14 @@ static DECLARE_MUTEX(hdaps_sem);
*/
static inline u8 __get_latch(u16 port)
{
- return inb(port) & HDAPS_READ_MASK;
+ return inb(port) & 0xff;
}
/*
- * __check_latch - Check a port latch for a given value. Callers must hold
- * hdaps_sem. Returns zero if the port contains the given value.
+ * __check_latch - Check a port latch for a given value. Returns zero if the
+ * port contains the given value. Callers must hold hdaps_sem.
*/
-static inline unsigned int __check_latch(u16 port, u8 val)
+static inline int __check_latch(u16 port, u8 val)
{
if (__get_latch(port) == val)
return 0;
@@ -99,7 +93,7 @@ static inline unsigned int __check_latch(u16 port, u8 val)
* __wait_latch - Wait up to 100us for a port latch to get a certain value,
* returning zero if the value is obtained. Callers must hold hdaps_sem.
*/
-static unsigned int __wait_latch(u16 port, u8 val)
+static int __wait_latch(u16 port, u8 val)
{
unsigned int i;
@@ -109,59 +103,42 @@ static unsigned int __wait_latch(u16 port, u8 val)
udelay(5);
}
- return -EINVAL;
+ return -EIO;
}
/*
- * __device_refresh - Request a refresh from the accelerometer.
- *
- * If sync is REFRESH_SYNC, we perform a synchronous refresh and will wait.
- * Returns zero if successful and nonzero on error.
- *
- * If sync is REFRESH_ASYNC, we merely kick off a new refresh if the device is
- * not up-to-date. Always returns zero.
- *
- * Callers must hold hdaps_sem.
+ * __device_refresh - request a refresh from the accelerometer. Does not wait
+ * for refresh to complete. Callers must hold hdaps_sem.
*/
-static int __device_refresh(unsigned int sync)
+static void __device_refresh(void)
{
- u8 state;
-
- udelay(100);
-
- state = inb(0x1604);
- if (state == STATE_FRESH)
- return 0;
-
- outb(0x11, 0x1610);
- outb(0x01, 0x161f);
- if (sync == REFRESH_ASYNC)
- return 0;
+ udelay(200);
+ if (inb(0x1604) != STATE_FRESH) {
+ outb(0x11, 0x1610);
+ outb(0x01, 0x161f);
+ }
+}
+/*
+ * __device_refresh_sync - request a synchronous refresh from the
+ * accelerometer. We wait for the refresh to complete. Returns zero if
+ * successful and nonzero on error. Callers must hold hdaps_sem.
+ */
+static int __device_refresh_sync(void)
+{
+ __device_refresh();
return __wait_latch(0x1604, STATE_FRESH);
}
/*
- * __device_complete - Indicate to the accelerometer that we are done reading
+ * __device_complete - indicate to the accelerometer that we are done reading
* data, and then initiate an async refresh. Callers must hold hdaps_sem.
*/
static inline void __device_complete(void)
{
inb(0x161f);
inb(0x1604);
- __device_refresh(REFRESH_ASYNC);
-}
-
-static int __hdaps_readb_one(unsigned int port, u8 *val)
-{
- /* do a sync refresh -- we need to be sure that we read fresh data */
- if (__device_refresh(REFRESH_SYNC))
- return -EIO;
-
- *val = inb(port);
- __device_complete();
-
- return 0;
+ __device_refresh();
}
/*
@@ -174,17 +151,26 @@ static int hdaps_readb_one(unsigned int port, u8 *val)
int ret;
down(&hdaps_sem);
- ret = __hdaps_readb_one(port, val);
- up(&hdaps_sem);
+ /* do a sync refresh -- we need to be sure that we read fresh data */
+ ret = __device_refresh_sync();
+ if (ret)
+ goto out;
+
+ *val = inb(port);
+ __device_complete();
+
+out:
+ up(&hdaps_sem);
return ret;
}
+/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
int *x, int *y)
{
/* do a sync refresh -- we need to be sure that we read fresh data */
- if (__device_refresh(REFRESH_SYNC))
+ if (__device_refresh_sync())
return -EIO;
*y = inw(port2);
@@ -217,11 +203,13 @@ static int hdaps_read_pair(unsigned int port1, unsigned int port2,
return ret;
}
-/* initialize the accelerometer */
+/*
+ * hdaps_device_init - initialize the accelerometer. Returns zero on success
+ * and negative error code on failure. Can sleep.
+ */
static int hdaps_device_init(void)
{
- unsigned int total_msecs = INIT_TIMEOUT_MSECS;
- int ret = -ENXIO;
+ int total, ret = -ENXIO;
down(&hdaps_sem);
@@ -231,8 +219,10 @@ static int hdaps_device_init(void)
goto out;
/*
- * The 0x03 value appears to only work on some thinkpads, such as the
- * T42p. Others return 0x01.
+ * Most ThinkPads return 0x01.
+ *
+ * Others--namely the R50p, T41p, and T42p--return 0x03. These laptops
+ * have "inverted" axises.
*
* The 0x02 value occurs when the chip has been previously initialized.
*/
@@ -267,24 +257,23 @@ static int hdaps_device_init(void)
outb(0x01, 0x161f);
if (__wait_latch(0x161f, 0x00))
goto out;
- if (__device_refresh(REFRESH_SYNC))
+ if (__device_refresh_sync())
goto out;
if (__wait_latch(0x1611, 0x00))
goto out;
/* we have done our dance, now let's wait for the applause */
- while (total_msecs > 0) {
- u8 ignored;
+ for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+ int x, y;
/* a read of the device helps push it into action */
- __hdaps_readb_one(HDAPS_PORT_UNKNOWN, &ignored);
+ __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
if (!__wait_latch(0x1611, 0x02)) {
ret = 0;
break;
}
msleep(INIT_WAIT_MSECS);
- total_msecs -= INIT_WAIT_MSECS;
}
out:
@@ -293,96 +282,6 @@ out:
}
-/* Input class stuff */
-
-/*
- * hdaps_calibrate - Zero out our "resting" values. Callers must hold hdaps_sem.
- */
-static void hdaps_calibrate(void)
-{
- int x, y;
-
- if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
- return;
-
- rest_x = x;
- rest_y = y;
-}
-
-static void hdaps_mousedev_poll(unsigned long unused)
-{
- int x, y;
-
- /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
- if (down_trylock(&hdaps_sem)) {
- mod_timer(&hdaps_timer,jiffies+msecs_to_jiffies(hdaps_poll_ms));
- return;
- }
-
- if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
- goto out;
-
- x -= rest_x;
- y -= rest_y;
- if (abs(x) > hdaps_mousedev_threshold)
- input_report_rel(&hdaps_idev, REL_X, x);
- if (abs(y) > hdaps_mousedev_threshold)
- input_report_rel(&hdaps_idev, REL_Y, y);
- input_sync(&hdaps_idev);
-
- mod_timer(&hdaps_timer, jiffies + msecs_to_jiffies(hdaps_poll_ms));
-
-out:
- up(&hdaps_sem);
-}
-
-/*
- * hdaps_mousedev_enable - enable the input class device. Can sleep.
- */
-static void hdaps_mousedev_enable(void)
-{
- down(&hdaps_sem);
-
- /* calibrate the device before enabling */
- hdaps_calibrate();
-
- /* initialize the input class */
- init_input_dev(&hdaps_idev);
- hdaps_idev.dev = &pdev->dev;
- hdaps_idev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
- hdaps_idev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
- hdaps_idev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT);
- input_register_device(&hdaps_idev);
-
- /* start up our timer */
- init_timer(&hdaps_timer);
- hdaps_timer.function = hdaps_mousedev_poll;
- hdaps_timer.expires = jiffies + msecs_to_jiffies(hdaps_poll_ms);
- add_timer(&hdaps_timer);
-
- hdaps_mousedev = 1;
-
- up(&hdaps_sem);
-
- printk(KERN_INFO "hdaps: input device enabled.\n");
-}
-
-/*
- * hdaps_mousedev_disable - disable the input class device. Caller must hold
- * hdaps_sem.
- */
-static void hdaps_mousedev_disable(void)
-{
- down(&hdaps_sem);
- if (hdaps_mousedev) {
- hdaps_mousedev = 0;
- del_timer_sync(&hdaps_timer);
- input_unregister_device(&hdaps_idev);
- }
- up(&hdaps_sem);
-}
-
-
/* Device model stuff */
static int hdaps_probe(struct device *dev)
@@ -412,6 +311,49 @@ static struct device_driver hdaps_driver = {
.resume = hdaps_resume
};
+/* Input class stuff */
+
+static struct input_dev hdaps_idev = {
+ .name = "hdaps",
+ .evbit = { BIT(EV_ABS) },
+ .absbit = { BIT(ABS_X) | BIT(ABS_Y) },
+ .absmin = { [ABS_X] = -256, [ABS_Y] = -256 },
+ .absmax = { [ABS_X] = 256, [ABS_Y] = 256 },
+ .absfuzz = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+ .absflat = { [ABS_X] = HDAPS_INPUT_FUZZ, [ABS_Y] = HDAPS_INPUT_FUZZ },
+};
+
+/*
+ * hdaps_calibrate - Set our "resting" values. Callers must hold hdaps_sem.
+ */
+static void hdaps_calibrate(void)
+{
+ __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
+}
+
+static void hdaps_mousedev_poll(unsigned long unused)
+{
+ int x, y;
+
+ /* Cannot sleep. Try nonblockingly. If we fail, try again later. */
+ if (down_trylock(&hdaps_sem)) {
+ mod_timer(&hdaps_timer,jiffies + HDAPS_POLL_PERIOD);
+ return;
+ }
+
+ if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+ goto out;
+
+ input_report_abs(&hdaps_idev, ABS_X, x - rest_x);
+ input_report_abs(&hdaps_idev, ABS_Y, y - rest_y);
+ input_sync(&hdaps_idev);
+
+ mod_timer(&hdaps_timer, jiffies + HDAPS_POLL_PERIOD);
+
+out:
+ up(&hdaps_sem);
+}
+
/* Sysfs Files */
@@ -517,69 +459,6 @@ static ssize_t hdaps_invert_store(struct device *dev,
return count;
}
-static ssize_t hdaps_mousedev_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%d\n", hdaps_mousedev);
-}
-
-static ssize_t hdaps_mousedev_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int enable;
-
- if (sscanf(buf, "%d", &enable) != 1)
- return -EINVAL;
-
- if (enable == 1)
- hdaps_mousedev_enable();
- else if (enable == 0)
- hdaps_mousedev_disable();
- else
- return -EINVAL;
-
- return count;
-}
-
-static ssize_t hdaps_poll_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%lu\n", hdaps_poll_ms);
-}
-
-static ssize_t hdaps_poll_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned int poll;
-
- if (sscanf(buf, "%u", &poll) != 1 || poll == 0)
- return -EINVAL;
- hdaps_poll_ms = poll;
-
- return count;
-}
-
-static ssize_t hdaps_threshold_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "%u\n", hdaps_mousedev_threshold);
-}
-
-static ssize_t hdaps_threshold_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned int threshold;
-
- if (sscanf(buf, "%u", &threshold) != 1 || threshold == 0)
- return -EINVAL;
- hdaps_mousedev_threshold = threshold;
-
- return count;
-}
-
static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
@@ -588,10 +467,6 @@ static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
-static DEVICE_ATTR(mousedev, 0644, hdaps_mousedev_show, hdaps_mousedev_store);
-static DEVICE_ATTR(mousedev_poll_ms, 0644, hdaps_poll_show, hdaps_poll_store);
-static DEVICE_ATTR(mousedev_threshold, 0644, hdaps_threshold_show,
- hdaps_threshold_store);
static struct attribute *hdaps_attributes[] = {
&dev_attr_position.attr,
@@ -601,9 +476,6 @@ static struct attribute *hdaps_attributes[] = {
&dev_attr_keyboard_activity.attr,
&dev_attr_mouse_activity.attr,
&dev_attr_calibrate.attr,
- &dev_attr_mousedev.attr,
- &dev_attr_mousedev_threshold.attr,
- &dev_attr_mousedev_poll_ms.attr,
&dev_attr_invert.attr,
NULL,
};
@@ -619,7 +491,7 @@ static struct attribute_group hdaps_attribute_group = {
* XXX: We should be able to return nonzero and halt the detection process.
* But there is a bug in dmi_check_system() where a nonzero return from the
* first match will result in a return of failure from dmi_check_system().
- * I fixed this; the patch is in 2.6-mm. Once in Linus's tree we can make
+ * I fixed this; the patch is 2.6-git. Once in a released tree, we can make
* hdaps_dmi_match_invert() return hdaps_dmi_match(), which in turn returns 1.
*/
static int hdaps_dmi_match(struct dmi_system_id *id)
@@ -668,6 +540,7 @@ static int __init hdaps_init(void)
HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"),
HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"),
+ HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"),
{ .ident = NULL }
};
@@ -696,8 +569,18 @@ static int __init hdaps_init(void)
if (ret)
goto out_device;
- if (hdaps_mousedev)
- hdaps_mousedev_enable();
+ /* initial calibrate for the input device */
+ hdaps_calibrate();
+
+ /* initialize the input class */
+ hdaps_idev.dev = &pdev->dev;
+ input_register_device(&hdaps_idev);
+
+ /* start up our timer for the input device */
+ init_timer(&hdaps_timer);
+ hdaps_timer.function = hdaps_mousedev_poll;
+ hdaps_timer.expires = jiffies + HDAPS_POLL_PERIOD;
+ add_timer(&hdaps_timer);
printk(KERN_INFO "hdaps: driver successfully loaded.\n");
return 0;
@@ -715,8 +598,8 @@ out:
static void __exit hdaps_exit(void)
{
- hdaps_mousedev_disable();
-
+ del_timer_sync(&hdaps_timer);
+ input_unregister_device(&hdaps_idev);
sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
platform_device_unregister(pdev);
driver_unregister(&hdaps_driver);
@@ -728,9 +611,6 @@ static void __exit hdaps_exit(void)
module_init(hdaps_init);
module_exit(hdaps_exit);
-module_param_named(mousedev, hdaps_mousedev, bool, 0);
-MODULE_PARM_DESC(mousedev, "enable the input class device");
-
module_param_named(invert, hdaps_invert, bool, 0);
MODULE_PARM_DESC(invert, "invert data along each axis");
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 37b49c2..eff5896 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)
for (i=0; i<nchan; i++) {
struct keywest_chan* chan = &iface->channels[i];
- u8 addr;
sprintf(chan->adapter.name, "%s %d", np->parent->name, i);
chan->iface = iface;
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index fdf53ce..44b595d 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
return ret;
}
+static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
static struct i2c_algorithm i2c_pxa_algorithm = {
- .name = "PXA-I2C-Algorithm",
- .id = I2C_ALGO_PXA,
.master_xfer = i2c_pxa_xfer,
+ .functionality = i2c_pxa_functionality,
};
static struct pxa_i2c i2c_pxa = {
.lock = SPIN_LOCK_UNLOCKED,
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait),
.adap = {
- .name = "pxa2xx-i2c",
- .id = I2C_ALGO_PXA,
+ .owner = THIS_MODULE,
.algo = &i2c_pxa_algorithm,
+ .name = "pxa2xx-i2c",
.retries = 5,
},
};
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index b443b04..0b0aa4f 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -601,44 +601,15 @@ EXPORT_SYMBOL(ide_wait_stat);
*/
u8 eighty_ninty_three (ide_drive_t *drive)
{
-#if 0
- if (!HWIF(drive)->udma_four)
+ if(HWIF(drive)->udma_four == 0)
+ return 0;
+ if (!(drive->id->hw_config & 0x6000))
return 0;
-
- if (drive->id->major_rev_num) {
- int hssbd = 0;
- int i;
- /*
- * Determine highest Supported SPEC
- */
- for (i=1; i<=15; i++)
- if (drive->id->major_rev_num & (1<<i))
- hssbd++;
-
- switch (hssbd) {
- case 7:
- case 6:
- case 5:
- /* ATA-4 and older do not support above Ultra 33 */
- default:
- return 0;
- }
- }
-
- return ((u8) (
-#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
-#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-
-#else
-
- return ((u8) ((HWIF(drive)->udma_four) &&
#ifndef CONFIG_IDEDMA_IVB
- (drive->id->hw_config & 0x4000) &&
+ if(!(drive->id->hw_config & 0x4000))
+ return 0;
#endif /* CONFIG_IDEDMA_IVB */
- (drive->id->hw_config & 0x6000)) ? 1 : 0);
-#endif
+ return 1;
}
EXPORT_SYMBOL(eighty_ninty_three);
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index d04f62a..ace8eda 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
}
rq.special = args;
+ args->rq = &rq;
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 3de9ab8..3d9c7af 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
#ifdef __i386__
if (dev->resource[PCI_ROM_RESOURCE].start) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
}
#endif
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index bbde462..be334da 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
if (cmd & PCI_COMMAND_MEMORY) {
if (pci_resource_start(dev, PCI_ROM_RESOURCE)) {
- pci_write_config_byte(dev, PCI_ROM_ADDRESS,
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
printk(KERN_INFO "HPT345: ROM enabled at 0x%08lx\n",
dev->resource[PCI_ROM_RESOURCE].start);
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index e55dee3..444f775 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -132,6 +132,17 @@ config KEYBOARD_CORGI
To compile this driver as a module, choose M here: the
module will be called corgikbd.
+config KEYBOARD_SPITZ
+ tristate "Spitz keyboard"
+ depends on PXA_SHARPSL
+ default y
+ help
+ Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000,
+ SL-C3000 and Sl-C3100 series of PDAs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called spitzkbd.
+
config KEYBOARD_MAPLE
tristate "Maple bus keyboard"
depends on SH_DREAMCAST && MAPLE
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index b02eece..9ce0b87 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_KEYBOARD_LOCOMO) += locomokbd.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_98KBD) += 98kbd.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
+obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c
new file mode 100644
index 0000000..1714045
--- /dev/null
+++ b/drivers/input/keyboard/spitzkbd.c
@@ -0,0 +1,478 @@
+/*
+ * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series)
+ *
+ * Copyright (c) 2005 Richard Purdie
+ *
+ * Based on corgikbd.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/spitz.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+#define KB_ROWS 7
+#define KB_COLS 11
+#define KB_ROWMASK(r) (1 << (r))
+#define SCANCODE(r,c) (((r)<<4) + (c) + 1)
+#define NR_SCANCODES ((KB_ROWS<<4) + 1)
+
+#define HINGE_SCAN_INTERVAL (150) /* ms */
+
+#define SPITZ_KEY_CALENDER KEY_F1
+#define SPITZ_KEY_ADDRESS KEY_F2
+#define SPITZ_KEY_FN KEY_F3
+#define SPITZ_KEY_CANCEL KEY_F4
+#define SPITZ_KEY_EXOK KEY_F5
+#define SPITZ_KEY_EXCANCEL KEY_F6
+#define SPITZ_KEY_EXJOGDOWN KEY_F7
+#define SPITZ_KEY_EXJOGUP KEY_F8
+#define SPITZ_KEY_JAP1 KEY_LEFTALT
+#define SPITZ_KEY_JAP2 KEY_RIGHTCTRL
+#define SPITZ_KEY_SYNC KEY_F9
+#define SPITZ_KEY_MAIL KEY_F10
+#define SPITZ_KEY_OK KEY_F11
+#define SPITZ_KEY_MENU KEY_F12
+
+static unsigned char spitzkbd_keycode[NR_SCANCODES] = {
+ 0, /* 0 */
+ 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 */
+ 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 */
+ 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 */
+ 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 */
+ 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 */
+ 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 */
+ 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 */
+};
+
+static int spitz_strobes[] = {
+ SPITZ_GPIO_KEY_STROBE0,
+ SPITZ_GPIO_KEY_STROBE1,
+ SPITZ_GPIO_KEY_STROBE2,
+ SPITZ_GPIO_KEY_STROBE3,
+ SPITZ_GPIO_KEY_STROBE4,
+ SPITZ_GPIO_KEY_STROBE5,
+ SPITZ_GPIO_KEY_STROBE6,
+ SPITZ_GPIO_KEY_STROBE7,
+ SPITZ_GPIO_KEY_STROBE8,
+ SPITZ_GPIO_KEY_STROBE9,
+ SPITZ_GPIO_KEY_STROBE10,
+};
+
+static int spitz_senses[] = {
+ SPITZ_GPIO_KEY_SENSE0,
+ SPITZ_GPIO_KEY_SENSE1,
+ SPITZ_GPIO_KEY_SENSE2,
+ SPITZ_GPIO_KEY_SENSE3,
+ SPITZ_GPIO_KEY_SENSE4,
+ SPITZ_GPIO_KEY_SENSE5,
+ SPITZ_GPIO_KEY_SENSE6,
+};
+
+struct spitzkbd {
+ unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)];
+ struct input_dev input;
+ char phys[32];
+
+ spinlock_t lock;
+ struct timer_list timer;
+ struct timer_list htimer;
+
+ unsigned int suspended;
+ unsigned long suspend_jiffies;
+};
+
+#define KB_DISCHARGE_DELAY 10
+#define KB_ACTIVATE_DELAY 10
+
+/* Helper functions for reading the keyboard matrix
+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it
+ * requires a function call per GPIO bit which is excessive
+ * when we need to access 11 bits at once, multiple times.
+ * These functions must be called within local_irq_save()/local_irq_restore()
+ * or similar.
+ */
+static inline void spitzkbd_discharge_all(void)
+{
+ /* STROBE All HiZ */
+ GPCR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPCR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPCR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPCR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+}
+
+static inline void spitzkbd_activate_all(void)
+{
+ /* STROBE ALL -> High */
+ GPSR0 = SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT;
+ GPSR1 = SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT;
+ GPSR2 = SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT;
+ GPSR3 = SPITZ_GPIO_G3_STROBE_BIT;
+ GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT;
+
+ udelay(KB_DISCHARGE_DELAY);
+
+ /* Clear any interrupts we may have triggered when altering the GPIO lines */
+ GEDR0 = SPITZ_GPIO_G0_SENSE_BIT;
+ GEDR1 = SPITZ_GPIO_G1_SENSE_BIT;
+ GEDR2 = SPITZ_GPIO_G2_SENSE_BIT;
+ GEDR3 = SPITZ_GPIO_G3_SENSE_BIT;
+}
+
+static inline void spitzkbd_activate_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPSR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline void spitzkbd_reset_col(int col)
+{
+ int gpio = spitz_strobes[col];
+ GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT;
+ GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT;
+ GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT;
+ GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
+ GPCR(gpio) = GPIO_bit(gpio);
+ GPDR(gpio) |= GPIO_bit(gpio);
+}
+
+static inline int spitzkbd_get_row_status(int col)
+{
+ return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02)
+ | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08)
+ | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60);
+}
+
+/*
+ * The spitz keyboard only generates interrupts when a key is pressed.
+ * When a key is pressed, we enable a timer which then scans the
+ * keyboard to detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data, struct pt_regs *regs)
+{
+ unsigned int row, col, rowd;
+ unsigned long flags;
+ unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0);
+
+ if (spitzkbd_data->suspended)
+ return;
+
+ spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+ if (regs)
+ input_regs(&spitzkbd_data->input, regs);
+
+ num_pressed = 0;
+ for (col = 0; col < KB_COLS; col++) {
+ /*
+ * Discharge the output driver capacitatance
+ * in the keyboard matrix. (Yes it is significant..)
+ */
+
+ spitzkbd_discharge_all();
+ udelay(KB_DISCHARGE_DELAY);
+
+ spitzkbd_activate_col(col);
+ udelay(KB_ACTIVATE_DELAY);
+
+ rowd = spitzkbd_get_row_status(col);
+ for (row = 0; row < KB_ROWS; row++) {
+ unsigned int scancode, pressed;
+
+ scancode = SCANCODE(row, col);
+ pressed = rowd & KB_ROWMASK(row);
+
+ input_report_key(&spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed);
+
+ if (pressed)
+ num_pressed++;
+ }
+ spitzkbd_reset_col(col);
+ }
+
+ spitzkbd_activate_all();
+
+ input_report_key(&spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 );
+ input_report_key(&spitzkbd_data->input, KEY_SUSPEND, pwrkey);
+
+ if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) {
+ input_event(&spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1);
+ spitzkbd_data->suspend_jiffies = jiffies;
+ }
+
+ input_sync(&spitzkbd_data->input);
+
+ /* if any keys are pressed, enable the timer */
+ if (num_pressed)
+ mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(100));
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+}
+
+/*
+ * spitz keyboard interrupt handler.
+ */
+static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->timer)) {
+ /** wait chattering delay **/
+ udelay(20);
+ spitzkbd_scankeyboard(spitzkbd_data, regs);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * spitz timer checking for released keys
+ */
+static void spitzkbd_timer_callback(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+ spitzkbd_scankeyboard(spitzkbd_data, NULL);
+}
+
+/*
+ * The hinge switches generate an interrupt.
+ * We debounce the switches and pass them to the input system.
+ */
+
+static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct spitzkbd *spitzkbd_data = dev_id;
+
+ if (!timer_pending(&spitzkbd_data->htimer))
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ return IRQ_HANDLED;
+}
+
+#define HINGE_STABLE_COUNT 2
+static int sharpsl_hinge_state;
+static int hinge_count;
+
+static void spitzkbd_hinge_timer(unsigned long data)
+{
+ struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data;
+ unsigned long state;
+ unsigned long flags;
+
+ state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB));
+ if (state != sharpsl_hinge_state) {
+ hinge_count = 0;
+ sharpsl_hinge_state = state;
+ } else if (hinge_count < HINGE_STABLE_COUNT) {
+ hinge_count++;
+ }
+
+ if (hinge_count >= HINGE_STABLE_COUNT) {
+ spin_lock_irqsave(&spitzkbd_data->lock, flags);
+
+ input_report_switch(&spitzkbd_data->input, SW_0, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0));
+ input_report_switch(&spitzkbd_data->input, SW_1, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0));
+ input_sync(&spitzkbd_data->input);
+
+ spin_unlock_irqrestore(&spitzkbd_data->lock, flags);
+ } else {
+ mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+ }
+}
+
+#ifdef CONFIG_PM
+static int spitzkbd_suspend(struct device *dev, pm_message_t state, uint32_t level)
+{
+ if (level == SUSPEND_POWER_DOWN) {
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+ spitzkbd->suspended = 1;
+
+ /* Set Strobe lines as inputs - *except* strobe line 0 leave this
+ enabled so we can detect a power button press for resume */
+ for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_IN);
+ }
+ return 0;
+}
+
+static int spitzkbd_resume(struct device *dev, uint32_t level)
+{
+ if (level == RESUME_POWER_ON) {
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ /* Upon resume, ignore the suspend key for a short while */
+ spitzkbd->suspend_jiffies = jiffies;
+ spitzkbd->suspended = 0;
+ }
+ return 0;
+}
+#else
+#define spitzkbd_suspend NULL
+#define spitzkbd_resume NULL
+#endif
+
+static int __init spitzkbd_probe(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd;
+
+ spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL);
+ if (!spitzkbd)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev,spitzkbd);
+ strcpy(spitzkbd->phys, "spitzkbd/input0");
+
+ spin_lock_init(&spitzkbd->lock);
+
+ /* Init Keyboard rescan timer */
+ init_timer(&spitzkbd->timer);
+ spitzkbd->timer.function = spitzkbd_timer_callback;
+ spitzkbd->timer.data = (unsigned long) spitzkbd;
+
+ /* Init Hinge Timer */
+ init_timer(&spitzkbd->htimer);
+ spitzkbd->htimer.function = spitzkbd_hinge_timer;
+ spitzkbd->htimer.data = (unsigned long) spitzkbd;
+
+ spitzkbd->suspend_jiffies=jiffies;
+
+ init_input_dev(&spitzkbd->input);
+ spitzkbd->input.private = spitzkbd;
+ spitzkbd->input.name = "Spitz Keyboard";
+ spitzkbd->input.dev = dev;
+ spitzkbd->input.phys = spitzkbd->phys;
+ spitzkbd->input.id.bustype = BUS_HOST;
+ spitzkbd->input.id.vendor = 0x0001;
+ spitzkbd->input.id.product = 0x0001;
+ spitzkbd->input.id.version = 0x0100;
+ spitzkbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR) | BIT(EV_SW);
+ spitzkbd->input.keycode = spitzkbd->keycode;
+ spitzkbd->input.keycodesize = sizeof(unsigned char);
+ spitzkbd->input.keycodemax = ARRAY_SIZE(spitzkbd_keycode);
+
+ memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode));
+ for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++)
+ set_bit(spitzkbd->keycode[i], spitzkbd->input.keybit);
+ clear_bit(0, spitzkbd->input.keybit);
+ set_bit(SW_0, spitzkbd->input.swbit);
+ set_bit(SW_1, spitzkbd->input.swbit);
+
+ input_register_device(&spitzkbd->input);
+ mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
+
+ /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) {
+ pxa_gpio_mode(spitz_senses[i] | GPIO_IN);
+ if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt,
+ SA_INTERRUPT, "Spitzkbd Sense", spitzkbd))
+ printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i);
+ else
+ set_irq_type(IRQ_GPIO(spitz_senses[i]),IRQT_RISING);
+ }
+
+ /* Set Strobe lines as outputs - set high */
+ for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++)
+ pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH);
+
+ pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN);
+ pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN);
+
+ request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd Sync", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, SA_INTERRUPT, "Spitzkbd PwrOn", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWA", spitzkbd);
+ request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, SA_INTERRUPT, "Spitzkbd SWB", spitzkbd);
+
+ set_irq_type(SPITZ_IRQ_GPIO_SYNC, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_ON_KEY, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWA, IRQT_BOTHEDGE);
+ set_irq_type(SPITZ_IRQ_GPIO_SWB, IRQT_BOTHEDGE);
+
+ printk(KERN_INFO "input: Spitz Keyboard Registered\n");
+
+ return 0;
+}
+
+static int spitzkbd_remove(struct device *dev)
+{
+ int i;
+ struct spitzkbd *spitzkbd = dev_get_drvdata(dev);
+
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++)
+ free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd);
+
+ free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd);
+ free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd);
+
+ del_timer_sync(&spitzkbd->htimer);
+ del_timer_sync(&spitzkbd->timer);
+
+ input_unregister_device(&spitzkbd->input);
+
+ kfree(spitzkbd);
+
+ return 0;
+}
+
+static struct device_driver spitzkbd_driver = {
+ .name = "spitz-keyboard",
+ .bus = &platform_bus_type,
+ .probe = spitzkbd_probe,
+ .remove = spitzkbd_remove,
+ .suspend = spitzkbd_suspend,
+ .resume = spitzkbd_resume,
+};
+
+static int __devinit spitzkbd_init(void)
+{
+ return driver_register(&spitzkbd_driver);
+}
+
+static void __exit spitzkbd_exit(void)
+{
+ driver_unregister(&spitzkbd_driver);
+}
+
+module_init(spitzkbd_init);
+module_exit(spitzkbd_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Spitz Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 0489af5..21d55ed 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -24,17 +24,17 @@ config TOUCHSCREEN_BITSY
module will be called h3600_ts_input.
config TOUCHSCREEN_CORGI
- tristate "Corgi touchscreen (for Sharp SL-C7xx)"
+ tristate "SharpSL (Corgi and Spitz series) touchscreen driver"
depends on PXA_SHARPSL
default y
help
Say Y here to enable the driver for the touchscreen on the
- Sharp SL-C7xx series of PDAs.
+ Sharp SL-C7xx and SL-Cxx00 series of PDAs.
If unsure, say N.
To compile this driver as a module, choose M here: the
- module will be called ads7846_ts.
+ module will be called corgi_ts.
config TOUCHSCREEN_GUNZE
tristate "Gunze AHL-51S touchscreen"
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
index 5d19261..4c7fbe5 100644
--- a/drivers/input/touchscreen/corgi_ts.c
+++ b/drivers/input/touchscreen/corgi_ts.c
@@ -1,5 +1,5 @@
/*
- * Touchscreen driver for Sharp Corgi models (SL-C7xx)
+ * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models
*
* Copyright (c) 2004-2005 Richard Purdie
*
@@ -19,7 +19,7 @@
#include <linux/slab.h>
#include <asm/irq.h>
-#include <asm/arch/corgi.h>
+#include <asm/arch/sharpsl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
@@ -47,15 +47,20 @@ struct corgi_ts {
struct ts_event tc;
int pendown;
int power_mode;
+ int irq_gpio;
+ struct corgits_machinfo *machinfo;
};
-#define STATUS_HSYNC (GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
-
-#define SyncHS() while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
+#ifdef CONFIG_PXA25x
#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x))
#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x))
-
+#endif
+#ifdef CONFIG_PXA27x
+#define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a))
+#define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x))
+#define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x))
+#endif
/* ADS7846 Touch Screen Controller bit definitions */
#define ADSCTRL_PD0 (1u << 0) /* PD0 */
@@ -66,12 +71,11 @@ struct corgi_ts {
#define ADSCTRL_STS (1u << 7) /* Start Bit */
/* External Functions */
-extern unsigned long w100fb_get_hsynclen(struct device *dev);
extern unsigned int get_clk_frequency_khz(int info);
-static unsigned long calc_waittime(void)
+static unsigned long calc_waittime(struct corgi_ts *corgi_ts)
{
- unsigned long hsync_len = w100fb_get_hsynclen(&corgifb_device.dev);
+ unsigned long hsync_len = corgi_ts->machinfo->get_hsync_len();
if (hsync_len)
return get_clk_frequency_khz(0)*1000/hsync_len;
@@ -79,7 +83,8 @@ static unsigned long calc_waittime(void)
return 0;
}
-static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
+static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend,
+ unsigned int address, unsigned long wait_time)
{
unsigned long timer1 = 0, timer2, pmnc = 0;
int pos = 0;
@@ -90,7 +95,7 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
PMNC_SET(0x01);
/* polling HSync */
- SyncHS();
+ corgi_ts->machinfo->wait_hsync();
/* get CCNT */
CCNT(timer1);
}
@@ -109,7 +114,7 @@ static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int add
CCNT(timer2);
if (timer2-timer1 > wait_time) {
/* too slow - timeout, try again */
- SyncHS();
+ corgi_ts->machinfo->wait_hsync();
/* get OSCR */
CCNT(timer1);
/* Wait after HSync */
@@ -133,23 +138,23 @@ static int read_xydata(struct corgi_ts *corgi_ts)
/* critical section */
local_irq_save(flags);
corgi_ssp_ads7846_lock();
- wait_time=calc_waittime();
+ wait_time = calc_waittime(corgi_ts);
/* Y-axis */
- sync_receive_data_send_cmd(0, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time);
/* Y-axis */
- sync_receive_data_send_cmd(1, 1, 1u, wait_time);
+ sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time);
/* X-axis */
- y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
+ y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time);
/* Z1 */
- x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
+ x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time);
/* Z2 */
- z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
- z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
+ z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time);
+ z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time);
/* Power-Down Enable */
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)
static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
{
- if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+ if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) {
/* Disable Interrupt */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_NOEDGE);
if (read_xydata(corgi_ts)) {
corgi_ts->pendown = 1;
new_data(corgi_ts, regs);
@@ -210,7 +215,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_
}
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
corgi_ts->pendown = 0;
}
}
@@ -254,7 +259,7 @@ static int corgits_resume(struct device *dev, uint32_t level)
corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
corgi_ts->power_mode = PWR_MODE_ACTIVE;
}
return 0;
@@ -267,6 +272,7 @@ static int corgits_resume(struct device *dev, uint32_t level)
static int __init corgits_probe(struct device *dev)
{
struct corgi_ts *corgi_ts;
+ struct platform_device *pdev = to_platform_device(dev);
if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
return -ENOMEM;
@@ -275,6 +281,14 @@ static int __init corgits_probe(struct device *dev)
memset(corgi_ts, 0, sizeof(struct corgi_ts));
+ corgi_ts->machinfo = dev->platform_data;
+ corgi_ts->irq_gpio = platform_get_irq(pdev, 0);
+
+ if (corgi_ts->irq_gpio < 0) {
+ kfree(corgi_ts);
+ return -ENODEV;
+ }
+
init_input_dev(&corgi_ts->input);
corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
@@ -293,8 +307,7 @@ static int __init corgits_probe(struct device *dev)
corgi_ts->input.id.product = 0x0002;
corgi_ts->input.id.version = 0x0100;
- pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
- pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+ pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN);
/* Initiaize ADS7846 Difference Reference mode */
corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
@@ -313,14 +326,14 @@ static int __init corgits_probe(struct device *dev)
input_register_device(&corgi_ts->input);
corgi_ts->power_mode = PWR_MODE_ACTIVE;
- if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
+ if (request_irq(corgi_ts->irq_gpio, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
input_unregister_device(&corgi_ts->input);
kfree(corgi_ts);
return -EBUSY;
}
/* Enable Falling Edge */
- set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+ set_irq_type(corgi_ts->irq_gpio, IRQT_FALLING);
printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
@@ -331,8 +344,9 @@ static int corgits_remove(struct device *dev)
{
struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
- free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+ free_irq(corgi_ts->irq_gpio, NULL);
del_timer_sync(&corgi_ts->timer);
+ corgi_ts->machinfo->put_hsync();
input_unregister_device(&corgi_ts->input);
kfree(corgi_ts);
return 0;
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index 8337b0f..4866fc3 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[] =
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"},
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"},
{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"},
+ {PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"},
{0, 0, NULL, NULL},
};
diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c
index c6b5bf7..dc334aa 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,
} /* sedlbauer_event */
static struct pcmcia_device_id sedlbauer_ids[] = {
- PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", "speed star II", "V 3.1", "(c) 93 - 98 cb ", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a, 0x50d4149c),
+ PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
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 0fda5c8..9ffaae7 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -466,10 +466,10 @@ void st5481_stop(struct st5481_adapter *adapter);
#define __debug_variable st5481_debug
#include "hisax_debug.h"
-#ifdef CONFIG_HISAX_DEBUG
-
extern int st5481_debug;
+#ifdef CONFIG_HISAX_DEBUG
+
#define DBG_ISO_PACKET(level,urb) \
if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 2fcd093..0a2536d 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)
test_and_clear_bit(buf_nr, &b_out->busy);
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- if (b_out->busy == 0) {
- st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
- }
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(4,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ if (b_out->busy == 0) {
+ st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
+ }
+ break;
}
}
@@ -205,7 +209,9 @@ static void st5481B_mode(struct st5481_bcs *bcs, int mode)
bcs->mode = mode;
// Cancel all USB transfers on this B channel
+ b_out->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(b_out->urb[0]);
+ b_out->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(b_out->urb[1]);
b_out->busy = 0;
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 071b1d3..941f702 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)
test_and_clear_bit(buf_nr, &d_out->busy);
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- if (d_out->busy == 0) {
- st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
- }
- return;
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ break;
+ default:
+ WARN("urb status %d",urb->status);
+ if (d_out->busy == 0) {
+ st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
+ }
+ break;
}
+ return; // Give up
}
FsmEvent(&adapter->d_out.fsm, EV_DOUT_COMPLETE, (void *) buf_nr);
@@ -709,14 +713,14 @@ int st5481_setup_d(struct st5481_adapter *adapter)
adapter->l1m.fsm = &l1fsm;
adapter->l1m.state = ST_L1_F3;
- adapter->l1m.debug = 1;
+ adapter->l1m.debug = st5481_debug & 0x100;
adapter->l1m.userdata = adapter;
adapter->l1m.printdebug = l1m_debug;
FsmInitTimer(&adapter->l1m, &adapter->timer);
adapter->d_out.fsm.fsm = &dout_fsm;
adapter->d_out.fsm.state = ST_DOUT_NONE;
- adapter->d_out.fsm.debug = 1;
+ adapter->d_out.fsm.debug = st5481_debug & 0x100;
adapter->d_out.fsm.userdata = adapter;
adapter->d_out.fsm.printdebug = dout_debug;
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 7aa810d..2cf5d1a 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 */
module_param(number_of_leds, int, 0);
#ifdef CONFIG_HISAX_DEBUG
-static int debug = 0x1;
+static int debug = 0;
module_param(debug, int, 0);
-int st5481_debug;
#endif
+int st5481_debug;
static LIST_HEAD(adapter_list);
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index ab62223..ffd5b2d 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)
struct ctrl_msg *ctrl_msg;
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ break;
}
}
@@ -184,22 +188,22 @@ static void usb_int_complete(struct urb *urb, struct pt_regs *regs)
int status;
switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- /* this urb is terminated, clean up */
- DBG(1, "urb shutting down with status: %d", urb->status);
- return;
- default:
- WARN("nonzero urb status received: %d", urb->status);
- goto exit;
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ DBG(2, "urb shutting down with status: %d", urb->status);
+ return;
+ default:
+ WARN("nonzero urb status received: %d", urb->status);
+ goto exit;
}
- DBG_PACKET(1, data, INT_PKT_SIZE);
+ DBG_PACKET(2, data, INT_PKT_SIZE);
if (urb->actual_length == 0) {
goto exit;
@@ -250,7 +254,7 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
struct urb *urb;
u8 *buf;
- DBG(1,"");
+ DBG(2,"");
if ((status = usb_reset_configuration (dev)) < 0) {
WARN("reset_configuration failed,status=%d",status);
@@ -330,15 +334,17 @@ void st5481_release_usb(struct st5481_adapter *adapter)
DBG(1,"");
// Stop and free Control and Interrupt URBs
- usb_unlink_urb(ctrl->urb);
+ usb_kill_urb(ctrl->urb);
if (ctrl->urb->transfer_buffer)
kfree(ctrl->urb->transfer_buffer);
usb_free_urb(ctrl->urb);
+ ctrl->urb = NULL;
- usb_unlink_urb(intr->urb);
+ usb_kill_urb(intr->urb);
if (intr->urb->transfer_buffer)
kfree(intr->urb->transfer_buffer);
usb_free_urb(intr->urb);
+ ctrl->urb = NULL;
}
/*
@@ -406,6 +412,7 @@ fill_isoc_urb(struct urb *urb, struct usb_device *dev,
spin_lock_init(&urb->lock);
urb->dev=dev;
urb->pipe=pipe;
+ urb->interval = 1;
urb->transfer_buffer=buf;
urb->number_of_packets = num_packets;
urb->transfer_buffer_length=num_packets*packet_size;
@@ -452,7 +459,9 @@ st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
if (urb[j]) {
if (urb[j]->transfer_buffer)
kfree(urb[j]->transfer_buffer);
+ urb[j]->transfer_buffer = NULL;
usb_free_urb(urb[j]);
+ urb[j] = NULL;
}
}
return retval;
@@ -463,10 +472,11 @@ void st5481_release_isocpipes(struct urb* urb[2])
int j;
for (j = 0; j < 2; j++) {
- usb_unlink_urb(urb[j]);
+ usb_kill_urb(urb[j]);
if (urb[j]->transfer_buffer)
kfree(urb[j]->transfer_buffer);
usb_free_urb(urb[j]);
+ urb[j] = NULL;
}
}
@@ -485,11 +495,15 @@ static void usb_in_complete(struct urb *urb, struct pt_regs *regs)
int len, count, status;
if (unlikely(urb->status < 0)) {
- if (urb->status != -ENOENT && urb->status != -ESHUTDOWN) {
- WARN("urb status %d",urb->status);
- } else {
- DBG(1,"urb killed");
- return; // Give up
+ switch (urb->status) {
+ case -ENOENT:
+ case -ESHUTDOWN:
+ case -ECONNRESET:
+ DBG(1,"urb killed status %d", urb->status);
+ return; // Give up
+ default:
+ WARN("urb status %d",urb->status);
+ break;
}
}
@@ -631,7 +645,9 @@ void st5481_in_mode(struct st5481_in *in, int mode)
in->mode = mode;
+ in->urb[0]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(in->urb[0]);
+ in->urb[1]->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(in->urb[1]);
if (in->mode != L1_MODE_NULL) {
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index 40b0df0..1ebed04 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -87,7 +87,7 @@ static int __init sc_init(void)
*/
for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) {
if(!request_region(io[b] + i * 0x400, 1, "sc test")) {
- pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400);
+ pr_debug("request_region for 0x%x failed\n", io[b] + i * 0x400);
io[b] = 0;
break;
} else
@@ -181,7 +181,7 @@ static int __init sc_init(void)
for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) {
pr_debug("Checking RAM address 0x%x...\n", i);
if(request_region(i, SRAM_PAGESIZE, "sc test")) {
- pr_debug(" check_region succeeded\n");
+ pr_debug(" request_region succeeded\n");
model = identify_board(i, io[b]);
release_region(i, SRAM_PAGESIZE);
if (model >= 0) {
diff --git a/drivers/md/raid6.h b/drivers/md/raid6.h
index f80ee63..31cbee7 100644
--- a/drivers/md/raid6.h
+++ b/drivers/md/raid6.h
@@ -69,9 +69,13 @@ extern const char raid6_empty_zero_page[PAGE_SIZE];
#define __init
#define __exit
#define __attribute_const__ __attribute__((const))
+#define noinline __attribute__((noinline))
#define preempt_enable()
#define preempt_disable()
+#define cpu_has_feature(x) 1
+#define enable_kernel_altivec()
+#define disable_kernel_altivec()
#endif /* __KERNEL__ */
diff --git a/drivers/md/raid6algos.c b/drivers/md/raid6algos.c
index acf386f..51c63c0 100644
--- a/drivers/md/raid6algos.c
+++ b/drivers/md/raid6algos.c
@@ -19,6 +19,7 @@
#include "raid6.h"
#ifndef __KERNEL__
#include <sys/mman.h>
+#include <stdio.h>
#endif
struct raid6_calls raid6_call;
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc
index 1de8f03..b9afd35 100644
--- a/drivers/md/raid6altivec.uc
+++ b/drivers/md/raid6altivec.uc
@@ -27,16 +27,20 @@
#ifdef CONFIG_ALTIVEC
#include <altivec.h>
-#include <asm/system.h>
-#include <asm/cputable.h>
+#ifdef __KERNEL__
+# include <asm/system.h>
+# include <asm/cputable.h>
+#endif
/*
- * This is the C data type to use
+ * This is the C data type to use. We use a vector of
+ * signed char so vec_cmpgt() will generate the right
+ * instruction.
*/
-typedef vector unsigned char unative_t;
+typedef vector signed char unative_t;
-#define NBYTES(x) ((vector unsigned char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
+#define NBYTES(x) ((vector signed char) {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x})
#define NSIZE sizeof(unative_t)
/*
@@ -108,7 +112,11 @@ int raid6_have_altivec(void);
int raid6_have_altivec(void)
{
/* This assumes either all CPUs have Altivec or none does */
+# ifdef __KERNEL__
return cpu_has_feature(CPU_FTR_ALTIVEC);
+# else
+ return 1;
+# endif
}
#endif
diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile
index 5578067..78e0396 100644
--- a/drivers/md/raid6test/Makefile
+++ b/drivers/md/raid6test/Makefile
@@ -8,6 +8,8 @@ OPTFLAGS = -O2 # Adjust as desired
CFLAGS = -I.. -g $(OPTFLAGS)
LD = ld
PERL = perl
+AR = ar
+RANLIB = ranlib
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
@@ -18,18 +20,33 @@ PERL = perl
%.uc: ../%.uc
cp -f $< $@
-all: raid6.o raid6test
+all: raid6.a raid6test
-raid6.o: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
+raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
raid6int32.o \
raid6mmx.o raid6sse1.o raid6sse2.o \
+ raid6altivec1.o raid6altivec2.o raid6altivec4.o raid6altivec8.o \
raid6recov.o raid6algos.o \
raid6tables.o
- $(LD) -r -o $@ $^
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
-raid6test: raid6.o test.c
+raid6test: test.c raid6.a
$(CC) $(CFLAGS) -o raid6test $^
+raid6altivec1.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@
+
+raid6altivec2.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@
+
+raid6altivec4.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@
+
+raid6altivec8.c: raid6altivec.uc ../unroll.pl
+ $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@
+
raid6int1.c: raid6int.uc ../unroll.pl
$(PERL) ../unroll.pl 1 < raid6int.uc > $@
@@ -52,7 +69,7 @@ raid6tables.c: mktables
./mktables > raid6tables.c
clean:
- rm -f *.o mktables mktables.c raid6int.uc raid6*.c raid6test
+ rm -f *.o *.a mktables mktables.c raid6int.uc raid6*.c raid6test
spotless: clean
rm -f *~
diff --git a/drivers/media/radio/radio-aimslab.c b/drivers/media/radio/radio-aimslab.c
index 8b4ad70..877c770 100644
--- a/drivers/media/radio/radio-aimslab.c
+++ b/drivers/media/radio/radio-aimslab.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#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 013c835..5319a9c 100644
--- a/drivers/media/radio/radio-aztech.c
+++ b/drivers/media/radio/radio-aztech.c
@@ -26,7 +26,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#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 53d399b..022913d 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -29,7 +29,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#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 202bfe6..6418f03 100644
--- a/drivers/media/radio/radio-gemtek.c
+++ b/drivers/media/radio/radio-gemtek.c
@@ -17,7 +17,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#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 c00245d..b2256d6 100644
--- a/drivers/media/radio/radio-rtrack2.c
+++ b/drivers/media/radio/radio-rtrack2.c
@@ -10,7 +10,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#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 3a464a0..6f03ce4 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -18,7 +18,7 @@
#include <linux/kernel.h> /* __setup */
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <linux/videodev.h> /* kernel radio structs */
#include <linux/isapnp.h>
diff --git a/drivers/media/radio/radio-sf16fmr2.c b/drivers/media/radio/radio-sf16fmr2.c
index 0732efd..71971e9 100644
--- a/drivers/media/radio/radio-sf16fmr2.c
+++ b/drivers/media/radio/radio-sf16fmr2.c
@@ -14,7 +14,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#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 248d67f..b03573c 100644
--- a/drivers/media/radio/radio-terratec.c
+++ b/drivers/media/radio/radio-terratec.c
@@ -25,7 +25,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay */
#include <asm/io.h> /* outb, outb_p */
#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 d7da901..f304f3c 100644
--- a/drivers/media/radio/radio-typhoon.c
+++ b/drivers/media/radio/radio-typhoon.c
@@ -31,7 +31,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/proc_fs.h> /* radio card status report */
#include <asm/io.h> /* outb, outb_p */
#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 342f92d..4c6d6fb 100644
--- a/drivers/media/radio/radio-zoltrix.c
+++ b/drivers/media/radio/radio-zoltrix.c
@@ -28,7 +28,7 @@
#include <linux/module.h> /* Modules */
#include <linux/init.h> /* Initdata */
-#include <linux/ioport.h> /* check_region, request_region */
+#include <linux/ioport.h> /* request_region */
#include <linux/delay.h> /* udelay, msleep */
#include <asm/io.h> /* outb, outb_p */
#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 c9106b1..4334744 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,
int err;
/* Put the analog decoder in standby to keep it quiet */
- if (core->tda9887_conf) {
- cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
- }
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
dvb_pll_configure(core->pll_desc, buf, params->frequency, 0);
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)
dev->dvb.frontend->ops->info.frequency_max = dev->core->pll_desc->max;
}
+ /* Put the analog decoder in standby to keep it quiet */
+ cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL);
+
/* register everything */
return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev);
}
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c
index d15da6f..b7f093f 100644
--- a/drivers/mtd/maps/sharpsl-flash.c
+++ b/drivers/mtd/maps/sharpsl-flash.c
@@ -82,7 +82,7 @@ int __init init_sharpsl(void)
} else if (machine_is_tosa()) {
sharpsl_partitions[0].size=0x006a0000;
sharpsl_partitions[0].offset=0x00160000;
- } else if (machine_is_spitz()) {
+ } else if (machine_is_spitz() || machine_is_akita() || machine_is_borzoi()) {
sharpsl_partitions[0].size=0x006b0000;
sharpsl_partitions[0].offset=0x00140000;
} else {
diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 9853b87..88b5b5b 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -221,10 +221,16 @@ sharpsl_nand_init(void)
sharpsl_partition_info[1].size=25 * 1024 * 1024;
} else if (machine_is_husky()) {
sharpsl_partition_info[1].size=53 * 1024 * 1024;
- }
+ } else if (machine_is_spitz()) {
+ sharpsl_partition_info[1].size=5 * 1024 * 1024;
+ } else if (machine_is_akita()) {
+ sharpsl_partition_info[1].size=58 * 1024 * 1024;
+ } else if (machine_is_borzoi()) {
+ sharpsl_partition_info[1].size=32 * 1024 * 1024;
+ }
}
- if (machine_is_husky()) {
+ if (machine_is_husky() || machine_is_borzoi()) {
/* Need to use small eraseblock size for backward compatibility */
sharpsl_mtd->flags |= MTD_NO_VIRTBLOCKS;
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 34b80de..bc53744 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -353,8 +353,6 @@ struct cp_private {
struct net_device_stats net_stats;
struct cp_extra_stats cp_stats;
- struct cp_dma_stats *nic_stats;
- dma_addr_t nic_stats_dma;
unsigned rx_tail ____cacheline_aligned;
struct cp_desc *rx_ring;
@@ -1143,10 +1141,6 @@ static int cp_alloc_rings (struct cp_private *cp)
cp->rx_ring = mem;
cp->tx_ring = &cp->rx_ring[CP_RX_RING_SIZE];
- mem += (CP_RING_BYTES - CP_STATS_SIZE);
- cp->nic_stats = mem;
- cp->nic_stats_dma = cp->ring_dma + (CP_RING_BYTES - CP_STATS_SIZE);
-
return cp_init_rings(cp);
}
@@ -1187,7 +1181,6 @@ static void cp_free_rings (struct cp_private *cp)
pci_free_consistent(cp->pdev, CP_RING_BYTES, cp->rx_ring, cp->ring_dma);
cp->rx_ring = NULL;
cp->tx_ring = NULL;
- cp->nic_stats = NULL;
}
static int cp_open (struct net_device *dev)
@@ -1516,13 +1509,17 @@ static void cp_get_ethtool_stats (struct net_device *dev,
struct ethtool_stats *estats, u64 *tmp_stats)
{
struct cp_private *cp = netdev_priv(dev);
+ struct cp_dma_stats *nic_stats;
+ dma_addr_t dma;
int i;
- memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats));
+ nic_stats = pci_alloc_consistent(cp->pdev, sizeof(*nic_stats), &dma);
+ if (!nic_stats)
+ return;
/* begin NIC statistics dump */
- cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
- cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
+ cpw32(StatsAddr + 4, (u64)dma >> 32);
+ cpw32(StatsAddr, ((u64)dma & DMA_32BIT_MASK) | DumpStats);
cpr32(StatsAddr);
for (i = 0; i < 1000; i++) {
@@ -1532,24 +1529,27 @@ static void cp_get_ethtool_stats (struct net_device *dev,
}
cpw32(StatsAddr, 0);
cpw32(StatsAddr + 4, 0);
+ cpr32(StatsAddr);
i = 0;
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_err);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_err);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->rx_fifo);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->frame_align);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_1col);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->tx_ok_mcol);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_phys);
- tmp_stats[i++] = le64_to_cpu(cp->nic_stats->rx_ok_bcast);
- tmp_stats[i++] = le32_to_cpu(cp->nic_stats->rx_ok_mcast);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_abort);
- tmp_stats[i++] = le16_to_cpu(cp->nic_stats->tx_underrun);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->tx_ok);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->tx_err);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->rx_err);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->rx_fifo);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->frame_align);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_1col);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->tx_ok_mcol);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_phys);
+ tmp_stats[i++] = le64_to_cpu(nic_stats->rx_ok_bcast);
+ tmp_stats[i++] = le32_to_cpu(nic_stats->rx_ok_mcast);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort);
+ tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun);
tmp_stats[i++] = cp->cp_stats.rx_frags;
if (i != CP_NUM_STATS)
BUG();
+
+ pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma);
}
static struct ethtool_ops cp_ethtool_ops = {
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 54fff9c..96f14ab 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1951,7 +1951,7 @@ config SKGE
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
and related Gigabit Ethernet adapters. It is a new smaller driver
- driver with better performance and more complete ethtool support.
+ with better performance and more complete ethtool support.
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 52c77cb..1f03027 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)
return -ENODEV;
}
if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com90io probe")) {
- BUGMSG(D_INIT_REASONS, "IO check_region %x-%x failed.\n",
+ BUGMSG(D_INIT_REASONS, "IO request_region %x-%x failed.\n",
ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1);
return -ENXIO;
}
@@ -242,7 +242,7 @@ static int __init com90io_found(struct net_device *dev)
BUGMSG(D_NORMAL, "Can't get IRQ %d!\n", dev->irq);
return -ENODEV;
}
- /* Reserve the I/O region - guaranteed to work by check_region */
+ /* Reserve the I/O region */
if (!request_region(dev->base_addr, ARCNET_TOTAL_SIZE, "arcnet (COM90xx-IO)")) {
free_irq(dev->irq, dev);
return -EBUSY;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 94c9f68..90449a0 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)
* This target is not on a VLAN
*/
if (rt->u.dst.dev == bond->dev) {
+ ip_rt_put(rt);
dprintk("basa: rtdev == bond->dev: arp_send\n");
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
bond->master_ip, 0);
@@ -2898,6 +2899,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
}
if (vlan_id) {
+ ip_rt_put(rt);
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
vlan->vlan_ip, vlan_id);
continue;
@@ -2909,6 +2911,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
bond->dev->name, NIPQUAD(fl.fl4_dst),
rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
}
+ ip_rt_put(rt);
}
}
@@ -5036,6 +5039,14 @@ static int __init bonding_init(void)
return 0;
out_err:
+ /*
+ * rtnl_unlock() will run netdev_run_todo(), putting the
+ * thus-far-registered bonding devices into a state which
+ * unregigister_netdevice() will accept
+ */
+ rtnl_unlock();
+ rtnl_lock();
+
/* free and unregister all bonds that were successfully added */
bond_free_all();
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 25cc20e..fbf1c06 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1387,13 +1387,13 @@ static void e100_update_stats(struct nic *nic)
ns->collisions += nic->tx_collisions;
ns->tx_errors += le32_to_cpu(s->tx_max_collisions) +
le32_to_cpu(s->tx_lost_crs);
- ns->rx_dropped += le32_to_cpu(s->rx_resource_errors);
ns->rx_length_errors += le32_to_cpu(s->rx_short_frame_errors) +
nic->rx_over_length_errors;
ns->rx_crc_errors += le32_to_cpu(s->rx_crc_errors);
ns->rx_frame_errors += le32_to_cpu(s->rx_alignment_errors);
ns->rx_over_errors += le32_to_cpu(s->rx_overrun_errors);
ns->rx_fifo_errors += le32_to_cpu(s->rx_overrun_errors);
+ ns->rx_missed_errors += le32_to_cpu(s->rx_resource_errors);
ns->rx_errors += le32_to_cpu(s->rx_crc_errors) +
le32_to_cpu(s->rx_alignment_errors) +
le32_to_cpu(s->rx_short_frame_errors) +
@@ -1727,12 +1727,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
if(unlikely(!(rfd_status & cb_ok))) {
/* Don't indicate if hardware indicates errors */
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else if(actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN) {
/* Don't indicate oversized frames */
nic->rx_over_length_errors++;
- nic->net_stats.rx_dropped++;
dev_kfree_skb_any(skb);
} else {
nic->net_stats.rx_packets++;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 7c8a0a2..ee687c9 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)
adapter->stats.crcerrs + adapter->stats.algnerrc +
adapter->stats.rlec + adapter->stats.mpc +
adapter->stats.cexterr;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
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 5c55537..89d6d69 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)
adapter->stats.icbc +
adapter->stats.ecbc + adapter->stats.mpc;
- adapter->net_stats.rx_dropped = adapter->stats.mpc;
-
/* see above
* adapter->net_stats.rx_length_errors = adapter->stats.rlec;
*/
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index c829e6a..dd451e0 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -428,7 +428,7 @@ static int init_shared_mem(struct s2io_nic *nic)
DBG_PRINT(INIT_DBG,
"%s: Zero DMA address for TxDL. ", dev->name);
DBG_PRINT(INIT_DBG,
- "Virtual address %llx\n", (u64)tmp_v);
+ "Virtual address %p\n", tmp_v);
tmp_v = pci_alloc_consistent(nic->pdev,
PAGE_SIZE, &tmp_p);
if (!tmp_v) {
@@ -657,9 +657,10 @@ static void free_shared_mem(struct s2io_nic *nic)
mac_control->zerodma_virt_addr,
(dma_addr_t)0);
DBG_PRINT(INIT_DBG,
- "%s: Freeing TxDL with zero DMA addr. ", dev->name);
- DBG_PRINT(INIT_DBG, "Virtual address %llx\n",
- (u64)(mac_control->zerodma_virt_addr));
+ "%s: Freeing TxDL with zero DMA addr. ",
+ dev->name);
+ DBG_PRINT(INIT_DBG, "Virtual address %p\n",
+ mac_control->zerodma_virt_addr);
}
kfree(mac_control->fifos[i].list_info);
}
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 6ee4771..2e72d79 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[] = {
{ PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+/* DLink card does not have valid VPD so this driver gags
+ * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ */
{ PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#if 0 /* don't handle Yukon2 cards at the moment -- mlindner@syskonnect.de */
- { PCI_VENDOR_ID_MARVELL, 0x4360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_MARVELL, 0x4361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-#endif
{ PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, },
{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0, }
+ { 0 }
};
MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index d7c9851..0208258 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -42,7 +42,7 @@
#include "skge.h"
#define DRV_NAME "skge"
-#define DRV_VERSION "0.9"
+#define DRV_VERSION "1.0"
#define PFX DRV_NAME " "
#define DEFAULT_TX_RING_SIZE 128
@@ -669,7 +669,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode)
PHY_M_LED_BLINK_RT(BLINK_84MS) |
PHY_M_LEDC_TX_CTRL |
PHY_M_LEDC_DP_CTRL);
-
+
gm_phy_write(hw, port, PHY_MARV_LED_OVER,
PHY_M_LED_MO_RX(MO_LED_OFF) |
(skge->speed == SPEED_100 ?
@@ -876,7 +876,7 @@ static int skge_rx_fill(struct skge_port *skge)
static void skge_link_up(struct skge_port *skge)
{
- skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG),
LED_BLK_OFF|LED_SYNC_OFF|LED_ON);
netif_carrier_on(skge->netdev);
@@ -987,6 +987,8 @@ static void genesis_reset(struct skge_hw *hw, int port)
{
const u8 zero[8] = { 0 };
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+
/* reset the statistics module */
xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
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)
(void) xm_phy_read(hw, port, PHY_BCOM_STAT);
status = xm_phy_read(hw, port, PHY_BCOM_STAT);
- pr_debug("bcom_check_link status=0x%x\n", status);
-
if ((status & PHY_ST_LSYNC) == 0) {
u16 cmd = xm_read16(hw, port, XM_MMU_CMD);
cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
@@ -1106,8 +1106,6 @@ static void bcom_phy_init(struct skge_port *skge, int jumbo)
{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
};
- pr_debug("bcom_phy_init\n");
-
/* read Id from external PHY (all have the same address) */
id1 = xm_phy_read(hw, port, PHY_XMAC_ID1);
@@ -1340,6 +1338,8 @@ static void genesis_stop(struct skge_port *skge)
int port = skge->port;
u32 reg;
+ genesis_reset(hw, port);
+
/* Clear Tx packet arbiter timeout IRQ */
skge_write16(hw, B3_PA_CTRL,
port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
@@ -1465,7 +1465,6 @@ static void genesis_link_up(struct skge_port *skge)
u16 cmd;
u32 mode, msk;
- pr_debug("genesis_link_up\n");
cmd = xm_read16(hw, port, XM_MMU_CMD);
/*
@@ -1578,7 +1577,6 @@ static void yukon_init(struct skge_hw *hw, int port)
struct skge_port *skge = netdev_priv(hw->dev[port]);
u16 ctrl, ct1000, adv;
- pr_debug("yukon_init\n");
if (skge->autoneg == AUTONEG_ENABLE) {
u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
@@ -1677,9 +1675,11 @@ static void yukon_mac_init(struct skge_hw *hw, int port)
/* WA code for COMA mode -- set PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* hard reset */
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)
/* WA code for COMA mode -- clear PHY reset */
if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3)
- skge_write32(hw, B2_GP_IO,
- (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
- & ~GP_IO_9);
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ reg = skge_read32(hw, B2_GP_IO);
+ reg |= GP_DIR_9;
+ reg &= ~GP_IO_9;
+ skge_write32(hw, B2_GP_IO, reg);
+ }
/* Set hardware config mode */
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)
}
gma_write16(hw, port, GM_GP_CTRL, reg);
- skge_read16(hw, GMAC_IRQ_SRC);
+ skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC));
yukon_init(hw, port);
@@ -1801,20 +1803,26 @@ static void yukon_stop(struct skge_port *skge)
struct skge_hw *hw = skge->hw;
int port = skge->port;
- if (hw->chip_id == CHIP_ID_YUKON_LITE &&
- hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
- skge_write32(hw, B2_GP_IO,
- skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
- }
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0);
+ yukon_reset(hw, port);
gma_write16(hw, port, GM_GP_CTRL,
gma_read16(hw, port, GM_GP_CTRL)
& ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA));
gma_read16(hw, port, GM_GP_CTRL);
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ hw->chip_rev >= CHIP_REV_YU_LITE_A3) {
+ u32 io = skge_read32(hw, B2_GP_IO);
+
+ io |= GP_DIR_9 | GP_IO_9;
+ skge_write32(hw, B2_GP_IO, io);
+ skge_read32(hw, B2_GP_IO);
+ }
+
/* set GPHY Control reset */
- skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
- skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
+ skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET);
}
static void yukon_get_stats(struct skge_port *skge, u64 *data)
@@ -1873,10 +1881,8 @@ static void yukon_link_up(struct skge_port *skge)
int port = skge->port;
u16 reg;
- pr_debug("yukon_link_up\n");
-
/* Enable Transmit FIFO Underrun */
- skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+ skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK);
reg = gma_read16(hw, port, GM_GP_CTRL);
if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
@@ -1896,7 +1902,6 @@ static void yukon_link_down(struct skge_port *skge)
int port = skge->port;
u16 ctrl;
- pr_debug("yukon_link_down\n");
gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
ctrl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2112,7 +2117,6 @@ static int skge_up(struct net_device *dev)
skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
skge_led(skge, LED_MODE_ON);
- pr_debug("skge_up completed\n");
return 0;
free_rx_ring:
@@ -2135,15 +2139,20 @@ static int skge_down(struct net_device *dev)
netif_stop_queue(dev);
+ skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF);
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_stop(skge);
+ else
+ yukon_stop(skge);
+
+ hw->intr_mask &= ~portirqmask[skge->port];
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
/* Stop transmitter */
skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
RB_RST_SET|RB_DIS_OP_MD);
- if (hw->chip_id == CHIP_ID_GENESIS)
- genesis_stop(skge);
- else
- yukon_stop(skge);
/* Disable Force Sync bit and Enable Alloc bit */
skge_write8(hw, SK_REG(port, TXA_CTRL),
@@ -2367,8 +2376,6 @@ static void genesis_set_multicast(struct net_device *dev)
u32 mode;
u8 filter[8];
- pr_debug("genesis_set_multicast flags=%x count=%d\n", dev->flags, dev->mc_count);
-
mode = xm_read32(hw, port, XM_MODE);
mode |= XM_MD_ENA_HASH;
if (dev->flags & IFF_PROMISC)
@@ -2530,8 +2537,6 @@ static int skge_poll(struct net_device *dev, int *budget)
unsigned int to_do = min(dev->quota, *budget);
unsigned int work_done = 0;
- pr_debug("skge_poll\n");
-
for (e = ring->to_clean; work_done < to_do; e = e->next) {
struct skge_rx_desc *rd = e->desc;
struct sk_buff *skb;
@@ -2672,9 +2677,9 @@ static void skge_error_irq(struct skge_hw *hw)
if (hw->chip_id == CHIP_ID_GENESIS) {
/* clear xmac errors */
if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT);
if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
- skge_write16(hw, SK_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+ skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT);
} else {
/* Timestamp (unused) overflow */
if (hwstatus & IS_IRQ_TIST_OV)
@@ -3000,9 +3005,6 @@ static int skge_reset(struct skge_hw *hw)
skge_write32(hw, B0_IMSK, hw->intr_mask);
- if (hw->chip_id != CHIP_ID_GENESIS)
- skge_write8(hw, GMAC_IRQ_MSK, 0);
-
spin_lock_bh(&hw->phy_lock);
for (i = 0; i < hw->ports; i++) {
if (hw->chip_id == CHIP_ID_GENESIS)
@@ -3230,6 +3232,11 @@ static void __devexit skge_remove(struct pci_dev *pdev)
dev0 = hw->dev[0];
unregister_netdev(dev0);
+ skge_write32(hw, B0_IMSK, 0);
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+ skge_pci_clear(hw);
+ skge_write8(hw, B0_CTST, CS_RST_SET);
+
tasklet_kill(&hw->ext_tasklet);
free_irq(pdev->irq, hw);
@@ -3238,7 +3245,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
if (dev1)
free_netdev(dev1);
free_netdev(dev0);
- skge_write16(hw, B0_LED, LED_STAT_OFF);
+
iounmap(hw->regs);
kfree(hw);
pci_set_drvdata(pdev, NULL);
@@ -3257,7 +3264,10 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
struct skge_port *skge = netdev_priv(dev);
if (netif_running(dev)) {
netif_carrier_off(dev);
- skge_down(dev);
+ if (skge->wol)
+ netif_stop_queue(dev);
+ else
+ skge_down(dev);
}
netif_device_detach(dev);
wol |= skge->wol;
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index f1680be..efbf98c 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -2008,7 +2008,7 @@ enum {
GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR)
/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
/* Bits 15.. 2: reserved */
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 4e19220..c796f41 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)
/* LEDs active in both modes, autosense prio = fiber */
spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0x945f);
+ /* switch off fibre autoneg */
+ spider_net_write_phy(card->netdev, 1, MII_NCONFIG, 0xfc01);
+ spider_net_write_phy(card->netdev, 1, 0x0b, 0x0004);
+
phy->def->ops->read_link(phy);
pr_info("Found %s with %i Mbps, %s-duplex.\n", phy->def->name,
phy->speed, phy->duplex==1 ? "Full" : "Half");
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7599f52..81f4aed 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -67,8 +67,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.39"
-#define DRV_MODULE_RELDATE "September 5, 2005"
+#define DRV_MODULE_VERSION "3.40"
+#define DRV_MODULE_RELDATE "September 15, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -3442,31 +3442,47 @@ static void tg3_tx_timeout(struct net_device *dev)
schedule_work(&tp->reset_task);
}
+/* Test for DMA buffers crossing any 4GB boundaries: 4G, 8G, etc */
+static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
+{
+ u32 base = (u32) mapping & 0xffffffff;
+
+ return ((base > 0xffffdcc0) &&
+ (base + len + 8 < base));
+}
+
static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
- u32 guilty_entry, int guilty_len,
- u32 last_plus_one, u32 *start, u32 mss)
+ u32 last_plus_one, u32 *start,
+ u32 base_flags, u32 mss)
{
struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
- dma_addr_t new_addr;
+ dma_addr_t new_addr = 0;
u32 entry = *start;
- int i;
+ int i, ret = 0;
if (!new_skb) {
- dev_kfree_skb(skb);
- return -1;
+ ret = -1;
+ } else {
+ /* New SKB is guaranteed to be linear. */
+ entry = *start;
+ new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
+ PCI_DMA_TODEVICE);
+ /* Make sure new skb does not cross any 4G boundaries.
+ * Drop the packet if it does.
+ */
+ if (tg3_4g_overflow_test(new_addr, new_skb->len)) {
+ ret = -1;
+ dev_kfree_skb(new_skb);
+ new_skb = NULL;
+ } else {
+ tg3_set_txd(tp, entry, new_addr, new_skb->len,
+ base_flags, 1 | (mss << 1));
+ *start = NEXT_TX(entry);
+ }
}
- /* New SKB is guaranteed to be linear. */
- entry = *start;
- new_addr = pci_map_single(tp->pdev, new_skb->data, new_skb->len,
- PCI_DMA_TODEVICE);
- tg3_set_txd(tp, entry, new_addr, new_skb->len,
- (skb->ip_summed == CHECKSUM_HW) ?
- TXD_FLAG_TCPUDP_CSUM : 0, 1 | (mss << 1));
- *start = NEXT_TX(entry);
-
/* Now clean up the sw ring entries. */
i = 0;
while (entry != last_plus_one) {
@@ -3491,7 +3507,7 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
dev_kfree_skb(skb);
- return 0;
+ return ret;
}
static void tg3_set_txd(struct tg3 *tp, int entry,
@@ -3517,19 +3533,10 @@ static void tg3_set_txd(struct tg3 *tp, int entry,
txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
}
-static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
-{
- u32 base = (u32) mapping & 0xffffffff;
-
- return ((base > 0xffffdcc0) &&
- (base + len + 8 < base));
-}
-
static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
dma_addr_t mapping;
- unsigned int i;
u32 len, entry, base_flags, mss;
int would_hit_hwbug;
@@ -3624,7 +3631,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
would_hit_hwbug = 0;
if (tg3_4g_overflow_test(mapping, len))
- would_hit_hwbug = entry + 1;
+ would_hit_hwbug = 1;
tg3_set_txd(tp, entry, mapping, len, base_flags,
(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)
tp->tx_buffers[entry].skb = NULL;
pci_unmap_addr_set(&tp->tx_buffers[entry], mapping, mapping);
- if (tg3_4g_overflow_test(mapping, len)) {
- /* Only one should match. */
- if (would_hit_hwbug)
- BUG();
- would_hit_hwbug = entry + 1;
- }
+ if (tg3_4g_overflow_test(mapping, len))
+ would_hit_hwbug = 1;
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
tg3_set_txd(tp, entry, mapping, len,
@@ -3669,34 +3672,15 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (would_hit_hwbug) {
u32 last_plus_one = entry;
u32 start;
- unsigned int len = 0;
-
- would_hit_hwbug -= 1;
- entry = entry - 1 - skb_shinfo(skb)->nr_frags;
- entry &= (TG3_TX_RING_SIZE - 1);
- start = entry;
- i = 0;
- while (entry != last_plus_one) {
- if (i == 0)
- len = skb_headlen(skb);
- else
- len = skb_shinfo(skb)->frags[i-1].size;
- if (entry == would_hit_hwbug)
- break;
-
- i++;
- entry = NEXT_TX(entry);
-
- }
+ start = entry - 1 - skb_shinfo(skb)->nr_frags;
+ start &= (TG3_TX_RING_SIZE - 1);
/* If the workaround fails due to memory/mapping
* failure, silently drop this packet.
*/
- if (tigon3_4gb_hwbug_workaround(tp, skb,
- entry, len,
- last_plus_one,
- &start, mss))
+ if (tigon3_4gb_hwbug_workaround(tp, skb, last_plus_one,
+ &start, base_flags, mss))
goto out_unlock;
entry = start;
@@ -9271,6 +9255,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
static struct pci_device_id write_reorder_chipsets[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD,
+ PCI_DEVICE_ID_AMD_K8_NB) },
{ },
};
u32 misc_ctrl_reg;
@@ -9285,7 +9271,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
#endif
- /* If we have an AMD 762 chipset, write
+ /* If we have an AMD 762 or K8 chipset, write
* reordering to the mailbox registers done by the host
* controller can cause major troubles. We read back from
* every mailbox register write to force the writes to be
@@ -9532,7 +9518,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->write32_rx_mbox = tg3_write_indirect_mbox;
iounmap(tp->regs);
- tp->regs = 0;
+ tp->regs = NULL;
pci_read_config_word(tp->pdev, PCI_COMMAND, &pci_cmd);
pci_cmd &= ~PCI_COMMAND_MEMORY;
@@ -10680,7 +10666,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
err_out_iounmap:
if (tp->regs) {
iounmap(tp->regs);
- tp->regs = 0;
+ tp->regs = NULL;
}
err_out_free_dev:
@@ -10705,7 +10691,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev)
unregister_netdev(dev);
if (tp->regs) {
iounmap(tp->regs);
- tp->regs = 0;
+ tp->regs = NULL;
}
free_netdev(dev);
pci_release_regions(pdev);
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 26cc4f6..60d1e05 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);
static int xircom_close(struct net_device *dev);
static void xircom_up(struct xircom_private *card);
static struct net_device_stats *xircom_get_stats(struct net_device *dev);
-#if CONFIG_NET_POLL_CONTROLLER
+#ifdef CONFIG_NET_POLL_CONTROLLER
static void xircom_poll_controller(struct net_device *dev);
#endif
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c
index 48c03c1..a01efa6 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,
}
skb_reserve(skb, 4);
cisco_hard_header(skb, dev, CISCO_KEEPALIVE, NULL, NULL, 0);
- data = (cisco_packet*)skb->data;
+ data = (cisco_packet*)(skb->data + 4);
data->type = htonl(type);
data->par1 = htonl(par1);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 2be65d3..06998c2 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,
/* Add frequency */
iwe.cmd = SIOCGIWFREQ;
iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
- iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
+ /* iwe.u.freq.m containt the channel (starting 1), our
+ * frequency_list array start at index 0...
+ */
+ iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d1fb1ba..bedd7f9f 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[] = {
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
+ PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
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 8122fe7..b1ba429 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)
pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_CACHE_LINE_SIZE, CACHE);
pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_LATENCY_TIMER, LATENCY);
- pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
+ pci_bus_write_config_dword (ibmphp_pci_bus, devfn, PCI_ROM_ADDRESS, 0x00L);
pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_COMMAND, DEVICEENABLE);
return 0;
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 0e09476..898f6da 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,
int cloop;
u8 temp_byte;
u8 class_code;
- u16 temp_word;
u32 rc;
u32 temp_register;
u32 base;
@@ -2682,8 +2681,7 @@ configure_new_function(struct controller *ctrl, struct pci_func *func,
} /* End of base register loop */
/* disable ROM base Address */
- temp_word = 0x00L;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+ rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
/* Set HP parameters (Cache Line Size, Latency Timer) */
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 783b5ab..91c9903 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
}
#endif
/* Disable ROM base Address */
- temp_word = 0x00L;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_ROM_ADDRESS, temp_word);
+ rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
/* Set HP parameters (Cache Line Size, Latency Timer) */
rc = shpchprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 992db89..259d247 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)
pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
- /* If we're in D3, force entire word to 0.
+ /* If we're (effectively) in D3, force entire word to 0.
* This doesn't affect PME_Status, disables PME_En, and
* sets PowerState to 0.
*/
- if (dev->current_state >= PCI_D3hot) {
- if (!(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
+ switch (dev->current_state) {
+ case PCI_UNKNOWN: /* Boot-up */
+ if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
+ && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
need_restore = 1;
+ /* Fall-through: force to D0 */
+ case PCI_D3hot:
+ case PCI_D3cold:
+ case PCI_POWER_ERROR:
pmcsr = 0;
- } else {
+ break;
+ default:
pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
pmcsr |= state;
+ break;
}
/* enter specified state */
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 39ba640..80969f7 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)
socket_t i = iminor(inode);
struct pcmcia_socket *s;
user_info_t *user;
+ static int warning_printed = 0;
ds_dbg(0, "ds_open(socket %d)\n", i);
@@ -407,6 +408,17 @@ static int ds_open(struct inode *inode, struct file *file)
s->user = user;
file->private_data = user;
+ if (!warning_printed) {
+ printk(KERN_INFO "pcmcia: Detected deprecated PCMCIA ioctl "
+ "usage.\n");
+ printk(KERN_INFO "pcmcia: This interface will soon be removed from "
+ "the kernel; please expect breakage unless you upgrade "
+ "to new tools.\n");
+ printk(KERN_INFO "pcmcia: see http://www.kernel.org/pub/linux/"
+ "utils/kernel/pcmcia/pcmcia.html for details.\n");
+ warning_printed = 1;
+ }
+
if (s->pcmcia_state.present)
queue_event(user, CS_EVENT_CARD_INSERTION);
return 0;
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index f0997c3..ba4d78e 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
{
struct yenta_socket *socket;
int ret;
-
+
+ /*
+ * If we failed to assign proper bus numbers for this cardbus
+ * controller during PCI probe, its subordinate pci_bus is NULL.
+ * Bail out if so.
+ */
+ if (!dev->subordinate) {
+ printk(KERN_ERR "Yenta: no bus associated with %s! "
+ "(try 'pci=assign-busses')\n", pci_name(dev));
+ return -ENODEV;
+ }
+
socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL);
if (!socket)
return -ENOMEM;
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index aac83ce..a1c52a6 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.34 $
+ * $Revision: 1.35 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -35,7 +35,7 @@
*/
/* 65536 bits to indicate if a devno is blacklisted or not */
-#define __BL_DEV_WORDS (__MAX_SUBCHANNELS + (8*sizeof(long) - 1) / \
+#define __BL_DEV_WORDS ((__MAX_SUBCHANNELS + (8*sizeof(long) - 1)) / \
(8*sizeof(long)))
static unsigned long bl_dev[__BL_DEV_WORDS];
typedef enum {add, free} range_action;
diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
index 6aeef3b..0cb47ec 100644
--- a/drivers/s390/crypto/z90main.c
+++ b/drivers/s390/crypto/z90main.c
@@ -682,9 +682,6 @@ z90crypt_cleanup_module(void)
del_timer(&config_timer);
del_timer(&cleanup_timer);
- if (z90_device_work)
- destroy_workqueue(z90_device_work);
-
destroy_z90crypt();
PRINTKN("Unloaded.\n");
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 96ca863..0db4f57 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
+ * $Id: ctcmain.c,v 1.78 2005/09/07 12:18:02 pavlic Exp $
*
* CTC / ESCON network driver
*
@@ -37,10 +37,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.78 $
*
*/
-
#undef DEBUG
#include <linux/module.h>
#include <linux/init.h>
@@ -135,7 +134,7 @@ static const char *dev_event_names[] = {
"TX down",
"Restart",
};
-
+
/**
* Events of the channel statemachine
*/
@@ -249,7 +248,7 @@ static void
print_banner(void)
{
static int printed = 0;
- char vbuf[] = "$Revision: 1.74 $";
+ char vbuf[] = "$Revision: 1.78 $";
char *version = vbuf;
if (printed)
@@ -334,7 +333,7 @@ static const char *ch_state_names[] = {
"Restarting",
"Not operational",
};
-
+
#ifdef DEBUG
/**
* Dump header and first 16 bytes of an sk_buff for debugging purposes.
@@ -671,7 +670,7 @@ static void
fsm_action_nop(fsm_instance * fi, int event, void *arg)
{
}
-
+
/**
* Actions for channel - statemachines.
*****************************************************************************/
@@ -1514,7 +1513,6 @@ ch_action_reinit(fsm_instance *fi, int event, void *arg)
fsm_addtimer(&privptr->restart_timer, 1000, DEV_EVENT_RESTART, dev);
}
-
/**
* The statemachine for a channel.
*/
@@ -1625,7 +1623,7 @@ static const fsm_node ch_fsm[] = {
};
static const int CH_FSM_LEN = sizeof (ch_fsm) / sizeof (fsm_node);
-
+
/**
* Functions related to setup and device detection.
*****************************************************************************/
@@ -1976,7 +1974,7 @@ ctc_irq_handler(struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
}
-
+
/**
* Actions for interface - statemachine.
*****************************************************************************/
@@ -2209,13 +2207,18 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
int rc = 0;
DBF_TEXT(trace, 5, __FUNCTION__);
+ /* we need to acquire the lock for testing the state
+ * otherwise we can have an IRQ changing the state to
+ * TXIDLE after the test but before acquiring the lock.
+ */
+ spin_lock_irqsave(&ch->collect_lock, saveflags);
if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
int l = skb->len + LL_HEADER_LENGTH;
- spin_lock_irqsave(&ch->collect_lock, saveflags);
- if (ch->collect_len + l > ch->max_bufsize - 2)
- rc = -EBUSY;
- else {
+ if (ch->collect_len + l > ch->max_bufsize - 2) {
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+ return -EBUSY;
+ } else {
atomic_inc(&skb->users);
header.length = l;
header.type = skb->protocol;
@@ -2231,7 +2234,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
int ccw_idx;
struct sk_buff *nskb;
unsigned long hi;
-
+ spin_unlock_irqrestore(&ch->collect_lock, saveflags);
/**
* Protect skb against beeing free'd by upper
* layers.
@@ -2256,6 +2259,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
if (!nskb) {
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -ENOMEM;
} else {
memcpy(skb_put(nskb, skb->len),
@@ -2281,6 +2285,7 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
*/
atomic_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
+ ctc_clear_busy(ch->netdev);
return -EBUSY;
}
@@ -2327,9 +2332,10 @@ transmit_skb(struct channel *ch, struct sk_buff *skb)
}
}
+ ctc_clear_busy(ch->netdev);
return rc;
}
-
+
/**
* Interface API for upper network layers
*****************************************************************************/
@@ -2421,7 +2427,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
dev->trans_start = jiffies;
if (transmit_skb(privptr->channel[WRITE], skb) != 0)
rc = 1;
- ctc_clear_busy(dev);
return rc;
}
@@ -2610,7 +2615,6 @@ stats_write(struct device *dev, struct device_attribute *attr, const char *buf,
return count;
}
-
static void
ctc_netdev_unregister(struct net_device * dev)
{
@@ -2685,7 +2689,6 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b
return count;
}
-
static ssize_t
ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index 3a02856..2ad4797 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.139 $"
+#define VERSION_QETH_H "$Revision: 1.142 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -1172,7 +1172,7 @@ extern int
qeth_realloc_buffer_pool(struct qeth_card *, int);
extern int
-qeth_set_large_send(struct qeth_card *);
+qeth_set_large_send(struct qeth_card *, enum qeth_large_send_types);
extern void
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 79c74f3..86582cf 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.224 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $
+ * $Revision: 1.224 $ $Date: 2005/05/04 20:19:18 $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,14 +29,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/***
- * eye catcher; just for debugging purposes
- */
-void volatile
-qeth_eyecatcher(void)
-{
- return;
-}
#include <linux/config.h>
#include <linux/module.h>
@@ -80,7 +72,7 @@ qeth_eyecatcher(void)
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.214 $"
+#define VERSION_QETH_C "$Revision: 1.224 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -2759,11 +2751,9 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
queue->card->perf_stats.outbound_do_qdio_start_time;
#endif
if (rc){
- QETH_DBF_SPRINTF(trace, 0, "qeth_flush_buffers: do_QDIO "
- "returned error (%i) on device %s.",
- rc, CARD_DDEV_ID(queue->card));
QETH_DBF_TEXT(trace, 2, "flushbuf");
QETH_DBF_TEXT_(trace, 2, " err%d", rc);
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_DDEV_ID(queue->card));
queue->card->stats.tx_errors += count;
/* this must not happen under normal circumstances. if it
* happens something is really wrong -> recover */
@@ -2909,11 +2899,8 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
QETH_DBF_TEXT(trace, 6, "qdouhdl");
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
- QETH_DBF_SPRINTF(trace, 2, "On device %s: "
- "received active check "
- "condition (0x%08x).",
- CARD_BUS_ID(card), status);
- QETH_DBF_TEXT(trace, 2, "chkcond");
+ QETH_DBF_TEXT(trace, 2, "achkcond");
+ QETH_DBF_TEXT_(trace, 2, "%s", CARD_BUS_ID(card));
QETH_DBF_TEXT_(trace, 2, "%08x", status);
netif_stop_queue(card->dev);
qeth_schedule_recovery(card);
@@ -3356,26 +3343,32 @@ qeth_halt_channel(struct qeth_channel *channel)
static int
qeth_halt_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"haltchs");
- if ((rc = qeth_halt_channel(&card->read)))
- return rc;
- if ((rc = qeth_halt_channel(&card->write)))
- return rc;
- return qeth_halt_channel(&card->data);
+ rc1 = qeth_halt_channel(&card->read);
+ rc2 = qeth_halt_channel(&card->write);
+ rc3 = qeth_halt_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
qeth_clear_channels(struct qeth_card *card)
{
- int rc = 0;
+ int rc1 = 0, rc2=0, rc3 = 0;
QETH_DBF_TEXT(trace,3,"clearchs");
- if ((rc = qeth_clear_channel(&card->read)))
- return rc;
- if ((rc = qeth_clear_channel(&card->write)))
- return rc;
- return qeth_clear_channel(&card->data);
+ rc1 = qeth_clear_channel(&card->read);
+ rc2 = qeth_clear_channel(&card->write);
+ rc3 = qeth_clear_channel(&card->data);
+ if (rc1)
+ return rc1;
+ if (rc2)
+ return rc2;
+ return rc3;
}
static int
@@ -3445,23 +3438,23 @@ qeth_mpc_initialize(struct qeth_card *card)
}
if ((rc = qeth_cm_enable(card))){
QETH_DBF_TEXT_(setup, 2, "2err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_cm_setup(card))){
QETH_DBF_TEXT_(setup, 2, "3err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_enable(card))){
QETH_DBF_TEXT_(setup, 2, "4err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_ulp_setup(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_alloc_qdio_buffers(card))){
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
- return rc;
+ goto out_qdio;
}
if ((rc = qeth_qdio_establish(card))){
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
@@ -3795,12 +3788,16 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
+ int rc;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
+ rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
+ if (rc)
+ return rc;
#ifdef CONFIG_QETH_VLAN
if (card->vlangrp && vlan_tx_tag_present(*skb) &&
((ipv == 6) || card->options.layer2) ) {
@@ -4251,7 +4248,8 @@ out:
}
static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+qeth_get_elements_no(struct qeth_card *card, void *hdr,
+ struct sk_buff *skb, int elems)
{
int elements_needed = 0;
@@ -4261,9 +4259,10 @@ qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
if (elements_needed == 0 )
elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+ skb->len) >> PAGE_SHIFT);
- if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+ if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)){
PRINT_ERR("qeth_do_send_packet: invalid size of "
- "IP packet. Discarded.");
+ "IP packet (Number=%d / Length=%d). Discarded.\n",
+ (elements_needed+elems), skb->len);
return 0;
}
return elements_needed;
@@ -4275,7 +4274,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
int ipv = 0;
int cast_type;
struct qeth_qdio_out_q *queue;
- struct qeth_hdr *hdr;
+ struct qeth_hdr *hdr = NULL;
int elements_needed = 0;
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
struct qeth_eddp_context *ctx = NULL;
@@ -4337,9 +4336,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
return -EINVAL;
}
} else {
- elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
- if (!elements_needed)
+ int elems = qeth_get_elements_no(card,(void*) hdr, skb,
+ elements_needed);
+ if (!elems)
return -EINVAL;
+ elements_needed += elems;
}
if (card->info.type != QETH_CARD_TYPE_IQD)
@@ -4504,7 +4505,11 @@ qeth_arp_set_no_entries(struct qeth_card *card, int no_entries)
QETH_DBF_TEXT(trace,3,"arpstnoe");
- /* TODO: really not supported by GuestLAN? */
+ /*
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_SET_NO_ENTRIES;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan)
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -4681,14 +4686,6 @@ qeth_arp_query(struct qeth_card *card, char *udata)
QETH_DBF_TEXT(trace,3,"arpquery");
- /*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
- /*if (card->info.guestlan)
- return -EOPNOTSUPP; */
if (!qeth_is_supported(card,/*IPA_QUERY_ARP_ADDR_INFO*/
IPA_ARP_PROCESSING)) {
PRINT_WARN("ARP processing not supported "
@@ -4894,10 +4891,9 @@ qeth_arp_add_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry)
QETH_DBF_TEXT(trace,3,"arpadent");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_ADD_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4937,10 +4933,9 @@ qeth_arp_remove_entry(struct qeth_card *card, struct qeth_arp_cache_entry *entry
QETH_DBF_TEXT(trace,3,"arprment");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY;
+ * thus we say EOPNOTSUPP for this ARP function
*/
if (card->info.guestlan)
return -EOPNOTSUPP;
@@ -4978,11 +4973,10 @@ qeth_arp_flush_cache(struct qeth_card *card)
QETH_DBF_TEXT(trace,3,"arpflush");
/*
- * currently GuestLAN does only deliver all zeros on query arp,
- * even though arp processing is supported (according to IPA supp.
- * funcs flags); since all zeros is no valueable information,
- * we say EOPNOTSUPP for all ARP functions
- */
+ * currently GuestLAN only supports the ARP assist function
+ * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_FLUSH_CACHE;
+ * thus we say EOPNOTSUPP for this ARP function
+ */
if (card->info.guestlan || (card->info.type == QETH_CARD_TYPE_IQD))
return -EOPNOTSUPP;
if (!qeth_is_supported(card,IPA_ARP_PROCESSING)) {
@@ -7038,14 +7032,16 @@ qeth_setrouting_v6(struct qeth_card *card)
}
int
-qeth_set_large_send(struct qeth_card *card)
+qeth_set_large_send(struct qeth_card *card, enum qeth_large_send_types type)
{
int rc = 0;
- if (card->dev == NULL)
+ if (card->dev == NULL) {
+ card->options.large_send = type;
return 0;
-
+ }
netif_stop_queue(card->dev);
+ card->options.large_send = type;
switch (card->options.large_send) {
case QETH_LARGE_SEND_EDDP:
card->dev->features |= NETIF_F_TSO | NETIF_F_SG;
@@ -7066,7 +7062,6 @@ qeth_set_large_send(struct qeth_card *card)
card->dev->features &= ~(NETIF_F_TSO | NETIF_F_SG);
break;
}
-
netif_wake_queue(card->dev);
return rc;
}
@@ -8257,7 +8252,6 @@ qeth_init(void)
{
int rc=0;
- qeth_eyecatcher();
PRINT_INFO("loading %s (%s/%s/%s/%s/%s/%s/%s %s %s)\n",
version, VERSION_QETH_C, VERSION_QETH_H,
VERSION_QETH_MPC_H, VERSION_QETH_MPC_C,
@@ -8338,7 +8332,6 @@ again:
printk("qeth: removed\n");
}
-EXPORT_SYMBOL(qeth_eyecatcher);
module_init(qeth_init);
module_exit(qeth_exit);
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 98bedb0..dda105b 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.51 $)
+ * linux/drivers/s390/net/qeth_sys.c ($Revision: 1.54 $)
*
* Linux on zSeries OSA Express and HiperSockets support
* This file contains code related to sysfs.
@@ -20,7 +20,7 @@
#include "qeth_mpc.h"
#include "qeth_fs.h"
-const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $";
+const char *VERSION_QETH_SYS_C = "$Revision: 1.54 $";
/*****************************************************************************/
/* */
@@ -722,10 +722,13 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c
if (!card)
return -EINVAL;
+ if (card->info.type == QETH_CARD_TYPE_IQD) {
+ PRINT_WARN("Layer2 on Hipersockets is not supported! \n");
+ return -EPERM;
+ }
if (((card->state != CARD_STATE_DOWN) &&
- (card->state != CARD_STATE_RECOVER)) ||
- (card->info.type != QETH_CARD_TYPE_OSAE))
+ (card->state != CARD_STATE_RECOVER)))
return -EPERM;
i = simple_strtoul(buf, &tmp, 16);
@@ -771,9 +774,7 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
if (!card)
return -EINVAL;
-
tmp = strsep((char **) &buf, "\n");
-
if (!strcmp(tmp, "no")){
type = QETH_LARGE_SEND_NO;
} else if (!strcmp(tmp, "EDDP")) {
@@ -786,10 +787,8 @@ qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, con
}
if (card->options.large_send == type)
return count;
- card->options.large_send = type;
- if ((rc = qeth_set_large_send(card)))
+ if ((rc = qeth_set_large_send(card, type)))
return rc;
-
return count;
}
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index dbad7f3..24ed589 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -14,7 +14,7 @@
#include <linux/major.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
-#include <linux/ioport.h> /* request_region, check_region */
+#include <linux/ioport.h> /* request_region */
#include <asm/atomic.h>
#include <asm/ebus.h> /* EBus device */
#include <asm/oplib.h> /* OpenProm Library */
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 5cc53cd..d92273c 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)
*
* LOCKING:
* None. (executing in kernel thread context)
+ *
+ * RETURNS:
+ * Non-zero if qc completed, zero otherwise.
*/
-static void ata_pio_complete (struct ata_port *ap)
+static int ata_pio_complete (struct ata_port *ap)
{
struct ata_queued_cmd *qc;
u8 drv_stat;
@@ -2486,14 +2489,14 @@ static void ata_pio_complete (struct ata_port *ap)
if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
ap->pio_task_state = PIO_ST_LAST_POLL;
ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
- return;
+ return 0;
}
}
drv_stat = ata_wait_idle(ap);
if (!ata_ok(drv_stat)) {
ap->pio_task_state = PIO_ST_ERR;
- return;
+ return 0;
}
qc = ata_qc_from_tag(ap, ap->active_tag);
@@ -2502,6 +2505,10 @@ static void ata_pio_complete (struct ata_port *ap)
ap->pio_task_state = PIO_ST_IDLE;
ata_poll_qc_complete(qc, drv_stat);
+
+ /* another command may start at this point */
+
+ return 1;
}
@@ -2709,7 +2716,7 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
next_sg:
if (unlikely(qc->cursg >= qc->n_elem)) {
- /*
+ /*
* The end of qc->sg is reached and the device expects
* more data to transfer. In order not to overrun qc->sg
* and fulfill length specified in the byte count register,
@@ -2721,7 +2728,7 @@ next_sg:
unsigned int i;
if (words) /* warning if bytes > 1 */
- printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
+ printk(KERN_WARNING "ata%u: %u bytes trailing data\n",
ap->id, bytes);
for (i = 0; i < words; i++)
@@ -2849,9 +2856,7 @@ static void ata_pio_block(struct ata_port *ap)
if (is_atapi_taskfile(&qc->tf)) {
/* no more data to transfer or unsupported ATAPI command */
if ((status & ATA_DRQ) == 0) {
- ap->pio_task_state = PIO_ST_IDLE;
-
- ata_poll_qc_complete(qc, status);
+ ap->pio_task_state = PIO_ST_LAST;
return;
}
@@ -2887,7 +2892,12 @@ static void ata_pio_error(struct ata_port *ap)
static void ata_pio_task(void *_data)
{
struct ata_port *ap = _data;
- unsigned long timeout = 0;
+ unsigned long timeout;
+ int qc_completed;
+
+fsm_start:
+ timeout = 0;
+ qc_completed = 0;
switch (ap->pio_task_state) {
case PIO_ST_IDLE:
@@ -2898,7 +2908,7 @@ static void ata_pio_task(void *_data)
break;
case PIO_ST_LAST:
- ata_pio_complete(ap);
+ qc_completed = ata_pio_complete(ap);
break;
case PIO_ST_POLL:
@@ -2913,10 +2923,9 @@ static void ata_pio_task(void *_data)
}
if (timeout)
- queue_delayed_work(ata_wq, &ap->pio_task,
- timeout);
- else
- queue_work(ata_wq, &ap->pio_task);
+ queue_delayed_work(ata_wq, &ap->pio_task, timeout);
+ else if (!qc_completed)
+ goto fsm_start;
}
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 3e9b641..23d095d 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -201,6 +201,7 @@ int
qla2100_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -215,9 +216,9 @@ qla2100_pci_config(scsi_qla_host_t *ha)
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -237,6 +238,7 @@ int
qla2300_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags = 0;
uint32_t cnt;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
@@ -302,9 +304,9 @@ qla2300_pci_config(scsi_qla_host_t *ha)
pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
@@ -324,6 +326,7 @@ int
qla24xx_pci_config(scsi_qla_host_t *ha)
{
uint16_t w, mwi;
+ uint32_t d;
unsigned long flags = 0;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
int pcix_cmd_reg, pcie_dctl_reg;
@@ -366,9 +369,9 @@ qla24xx_pci_config(scsi_qla_host_t *ha)
}
/* Reset expansion ROM address decode enable */
- pci_read_config_word(ha->pdev, PCI_ROM_ADDRESS, &w);
- w &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_word(ha->pdev, PCI_ROM_ADDRESS, w);
+ pci_read_config_dword(ha->pdev, PCI_ROM_ADDRESS, &d);
+ d &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(ha->pdev, PCI_ROM_ADDRESS, d);
/* Get PCI bus information. */
spin_lock_irqsave(&ha->hardware_lock, flags);
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index a63f931..b227e51 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)
{
struct pci_dev *pdev = to_pci_dev(ap->host_set->dev);
unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg, pdev->device);
- u32 val, val2;
+ u32 val, val2 = 0;
u8 pmr;
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)
if (ent->device != 0x182) {
if ((pmr & SIS_PMR_COMBINED) == 0) {
printk(KERN_INFO "sata_sis: Detected SiS 180/181 chipset in SATA mode\n");
- port2_start=0x64;
+ port2_start = 64;
}
else {
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 aec39fb..b5cf394 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)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver serial21285_reg;
+static struct uart_driver serial21285_reg;
static struct console serial21285_console =
{
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index 978e124..679e678 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)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
static struct console amba_console = {
.name = "ttyAM",
.write = pl010_console_write,
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 5607130..1ff629c 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)
return uart_set_options(&uap->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver amba_reg;
+static struct uart_driver amba_reg;
static struct console amba_console = {
.name = "ttyAMA",
.write = pl011_console_write,
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index d822896..78c1f36 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)
return uart_set_options(port, co, baud, parity, bits, flow);
}
-extern struct uart_driver clps711x_reg;
+static struct uart_driver clps711x_reg;
static struct console clps711x_console = {
.name = "ttyCL",
.write = clps711xuart_console_write,
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index a3cd0ee..0585ab2 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -781,7 +781,7 @@ mpc52xx_uart_remove(struct device *dev)
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct device *dev, u32 state, u32 level)
+mpc52xx_uart_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct uart_port *port = (struct uart_port *) dev_get_drvdata(dev);
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index eaa0af8..672b359 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -589,8 +589,8 @@ serial_pxa_type(struct uart_port *port)
#ifdef CONFIG_SERIAL_PXA_CONSOLE
-extern struct uart_pxa_port serial_pxa_ports[];
-extern struct uart_driver serial_pxa_reg;
+static struct uart_pxa_port serial_pxa_ports[];
+static struct uart_driver serial_pxa_reg;
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 1225b14..dd8aed2 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -799,7 +799,7 @@ sa1100_console_setup(struct console *co, char *options)
return uart_set_options(&sport->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver sa1100_reg;
+static struct uart_driver sa1100_reg;
static struct console sa1100_console = {
.name = "ttySA",
.write = sa1100_console_write,
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 8302376..d01dbe5 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)
return uart_set_options (port, co, baud, parity, bits, flow);
}
-extern struct uart_driver lh7a40x_reg;
+static struct uart_driver lh7a40x_reg;
static struct console lh7a40x_console = {
.name = "ttyAM",
.write = lh7a40xuart_console_write,
diff --git a/drivers/tc/zs.c b/drivers/tc/zs.c
index 4382ee6..6bed871 100644
--- a/drivers/tc/zs.c
+++ b/drivers/tc/zs.c
@@ -1683,7 +1683,7 @@ static void __init probe_sccs(void)
#ifndef CONFIG_SERIAL_DEC_CONSOLE
/*
* We're called early and memory managment isn't up, yet.
- * Thus check_region would fail.
+ * Thus request_region would fail.
*/
if (!request_region((unsigned long)
zs_channels[n_channels].control,
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 615874e..31ee13e 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -753,7 +753,8 @@ config FB_I810_GTF
config FB_I810_I2C
bool "Enable DDC Support"
- depends on FB_I810 && I2C && FB_I810_GTF
+ depends on FB_I810 && FB_I810_GTF
+ select I2C
select I2C_ALGOBIT
help
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 353cb3f..630f2df 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -19,17 +19,18 @@
#include <linux/fb.h>
#include <linux/backlight.h>
-#include <asm/arch-pxa/corgi.h>
-#include <asm/hardware/scoop.h>
+#include <asm/mach-types.h>
+#include <asm/arch/sharpsl.h>
-#define CORGI_MAX_INTENSITY 0x3e
#define CORGI_DEFAULT_INTENSITY 0x1f
-#define CORGI_LIMIT_MASK 0x0b
+#define CORGI_LIMIT_MASK 0x0b
static int corgibl_powermode = FB_BLANK_UNBLANK;
static int current_intensity = 0;
static int corgibl_limit = 0;
+static void (*corgibl_mach_set_intensity)(int intensity);
static spinlock_t bl_lock = SPIN_LOCK_UNLOCKED;
+static struct backlight_properties corgibl_data;
static void corgibl_send_intensity(int intensity)
{
@@ -43,18 +44,10 @@ static void corgibl_send_intensity(int intensity)
intensity &= CORGI_LIMIT_MASK;
}
- /* Skip 0x20 as it will blank the display */
- if (intensity >= 0x20)
- intensity++;
-
spin_lock_irqsave(&bl_lock, flags);
- /* Bits 0-4 are accessed via the SSP interface */
- corgi_ssp_blduty_set(intensity & 0x1f);
- /* Bit 5 is via SCOOP */
- if (intensity & 0x0020)
- set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
- else
- reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
+
+ corgibl_mach_set_intensity(intensity);
+
spin_unlock_irqrestore(&bl_lock, flags);
}
@@ -113,8 +106,8 @@ static int corgibl_get_power(struct backlight_device *bd)
static int corgibl_set_intensity(struct backlight_device *bd, int intensity)
{
- if (intensity > CORGI_MAX_INTENSITY)
- intensity = CORGI_MAX_INTENSITY;
+ if (intensity > corgibl_data.max_brightness)
+ intensity = corgibl_data.max_brightness;
corgibl_send_intensity(intensity);
current_intensity=intensity;
return 0;
@@ -141,7 +134,6 @@ static struct backlight_properties corgibl_data = {
.owner = THIS_MODULE,
.get_power = corgibl_get_power,
.set_power = corgibl_set_power,
- .max_brightness = CORGI_MAX_INTENSITY,
.get_brightness = corgibl_get_intensity,
.set_brightness = corgibl_set_intensity,
};
@@ -150,12 +142,18 @@ static struct backlight_device *corgi_backlight_device;
static int __init corgibl_probe(struct device *dev)
{
+ struct corgibl_machinfo *machinfo = dev->platform_data;
+
+ corgibl_data.max_brightness = machinfo->max_intensity;
+ corgibl_mach_set_intensity = machinfo->set_bl_intensity;
+
corgi_backlight_device = backlight_device_register ("corgi-bl",
NULL, &corgibl_data);
if (IS_ERR (corgi_backlight_device))
return PTR_ERR (corgi_backlight_device);
corgibl_set_intensity(NULL, CORGI_DEFAULT_INTENSITY);
+ corgibl_limit_intensity(0);
printk("Corgi Backlight Driver Initialized.\n");
return 0;
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 2e93224..0fc8bb4 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -767,7 +767,7 @@ static const char *fbcon_startup(void)
const char *display_desc = "frame buffer device";
struct display *p = &fb_display[fg_console];
struct vc_data *vc = vc_cons[fg_console].d;
- struct font_desc *font = NULL;
+ const struct font_desc *font = NULL;
struct module *owner;
struct fb_info *info = NULL;
struct fbcon_ops *ops;
@@ -841,7 +841,7 @@ static const char *fbcon_startup(void)
info->var.yres);
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
- vc->vc_font.data = p->fontdata = font->data;
+ vc->vc_font.data = (void *)(p->fontdata = font->data);
vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */
}
@@ -941,7 +941,7 @@ static void fbcon_init(struct vc_data *vc, int init)
fb, copy the font from that console */
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -1188,7 +1188,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
return;
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
- vc->vc_font.data = p->fontdata = t->fontdata;
+ vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
p->userfont = t->userfont;
@@ -1687,6 +1687,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
case SM_DOWN:
if (count > vc->vc_rows) /* Maximum realistic size */
count = vc->vc_rows;
+ if (logo_shown >= 0)
+ goto redraw_down;
switch (p->scrollmode) {
case SCROLL_MOVE:
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)
}
static int fbcon_do_set_font(struct vc_data *vc, int w, int h,
- u8 * data, int userfont)
+ const u8 * data, int userfont)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
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,
cnt = FNTCHARCNT(data);
else
cnt = 256;
- vc->vc_font.data = p->fontdata = data;
+ vc->vc_font.data = (void *)(p->fontdata = data);
if ((p->userfont = userfont))
REFCOUNT(data)++;
vc->vc_font.width = w;
@@ -2323,7 +2325,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
tmp->vc_font.width == w &&
!memcmp(fb_display[i].fontdata, new_data, size)) {
kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
- new_data = fb_display[i].fontdata;
+ new_data = (u8 *)fb_display[i].fontdata;
break;
}
}
@@ -2333,7 +2335,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name)
{
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
- struct font_desc *f;
+ const struct font_desc *f;
if (!name)
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 08befaf..0738cd6 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -30,7 +30,7 @@ struct display {
/* Filled in by the frame buffer device */
u_short inverse; /* != 0 text black on white as default */
/* Filled in by the low-level console driver */
- u_char *fontdata;
+ const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */
u_short scrollmode; /* Scroll Method */
short yscroll; /* Hardware scrolling */
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
index ff0af96..e6aa0ea 100644
--- a/drivers/video/console/font_10x18.c
+++ b/drivers/video/console/font_10x18.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 9216
-static unsigned char fontdata_10x18[FONTDATAMAX] = {
+static const unsigned char fontdata_10x18[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 0000000000 */
@@ -5132,7 +5132,7 @@ static unsigned char fontdata_10x18[FONTDATAMAX] = {
};
-struct font_desc font_10x18 = {
+const struct font_desc font_10x18 = {
FONT10x18_IDX,
"10x18",
10,
diff --git a/drivers/video/console/font_6x11.c b/drivers/video/console/font_6x11.c
index c52f129..89976cd 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX (11*256)
-static unsigned char fontdata_6x11[FONTDATAMAX] = {
+static const unsigned char fontdata_6x11[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -3341,7 +3341,7 @@ static unsigned char fontdata_6x11[FONTDATAMAX] = {
};
-struct font_desc font_vga_6x11 = {
+const struct font_desc font_vga_6x11 = {
VGA6x11_IDX,
"ProFont6x11",
6,
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
index 1fa7fcf..bbf1166 100644
--- a/drivers/video/console/font_7x14.c
+++ b/drivers/video/console/font_7x14.c
@@ -7,7 +7,7 @@
#define FONTDATAMAX 3584
-static unsigned char fontdata_7x14[FONTDATAMAX] = {
+static const unsigned char fontdata_7x14[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 0000000 */
@@ -4108,7 +4108,7 @@ static unsigned char fontdata_7x14[FONTDATAMAX] = {
};
-struct font_desc font_7x14 = {
+const struct font_desc font_7x14 = {
FONT7x14_IDX,
"7x14",
7,
diff --git a/drivers/video/console/font_8x16.c b/drivers/video/console/font_8x16.c
index e6f8dba..74fe86f 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_8x16[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -4621,7 +4621,7 @@ static unsigned char fontdata_8x16[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x16 = {
+const struct font_desc font_vga_8x16 = {
VGA8x16_IDX,
"VGA8x16",
8,
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index 57fbe26..26199f8 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -8,7 +8,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2573,7 +2573,7 @@ static unsigned char fontdata_8x8[FONTDATAMAX] = {
};
-struct font_desc font_vga_8x8 = {
+const struct font_desc font_vga_8x8 = {
VGA8x8_IDX,
"VGA8x8",
8,
diff --git a/drivers/video/console/font_acorn_8x8.c b/drivers/video/console/font_acorn_8x8.c
index d565505..2d2e396 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -3,7 +3,7 @@
#include <linux/config.h>
#include <linux/font.h>
-static unsigned char acorndata_8x8[] = {
+static const unsigned char acorndata_8x8[] = {
/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
/* 01 */ 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, /* ^A */
/* 02 */ 0x7e, 0xff, 0xbd, 0xff, 0xc3, 0xe7, 0xff, 0x7e, /* ^B */
@@ -262,7 +262,7 @@ static unsigned char acorndata_8x8[] = {
/* FF */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-struct font_desc font_acorn_8x8 = {
+const struct font_desc font_acorn_8x8 = {
ACORN8x8_IDX,
"Acorn8x8",
8,
diff --git a/drivers/video/console/font_mini_4x6.c b/drivers/video/console/font_mini_4x6.c
index 593b955..d818234 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -43,7 +43,7 @@ __END__;
#define FONTDATAMAX 1536
-static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
+static const unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*{*/
/* Char 0: ' ' */
@@ -2147,7 +2147,7 @@ static unsigned char fontdata_mini_4x6[FONTDATAMAX] = {
/*}*/
};
-struct font_desc font_mini_4x6 = {
+const struct font_desc font_mini_4x6 = {
MINI4x6_IDX,
"MINI4x6",
4,
diff --git a/drivers/video/console/font_pearl_8x8.c b/drivers/video/console/font_pearl_8x8.c
index 5fa95f1..e646c88 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -13,7 +13,7 @@
#define FONTDATAMAX 2048
-static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
+static const unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, /* 00000000 */
@@ -2577,7 +2577,7 @@ static unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
};
-struct font_desc font_pearl_8x8 = {
+const struct font_desc font_pearl_8x8 = {
PEARL8x8_IDX,
"PEARL8x8",
8,
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index c7bd967..ab5eb93 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 11264
-static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
+static const unsigned char fontdata_sun12x22[FONTDATAMAX] = {
/* 0 0x00 '^@' */
0x00, 0x00, /* 000000000000 */
@@ -6151,7 +6151,7 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
};
-struct font_desc font_sun_12x22 = {
+const struct font_desc font_sun_12x22 = {
SUN12x22_IDX,
"SUN12x22",
12,
diff --git a/drivers/video/console/font_sun8x16.c b/drivers/video/console/font_sun8x16.c
index 2af3ab3..41f910f 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -2,7 +2,7 @@
#define FONTDATAMAX 4096
-static unsigned char fontdata_sun8x16[FONTDATAMAX] = {
+static const unsigned char fontdata_sun8x16[FONTDATAMAX] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* */ 0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00,
/* */ 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] = {
/* */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
-struct font_desc font_sun_8x16 = {
+const struct font_desc font_sun_8x16 = {
SUN8x16_IDX,
"SUN8x16",
8,
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index e79b297..4fd07d9 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -23,7 +23,7 @@
#define NO_FONTS
-static struct font_desc *fonts[] = {
+static const struct font_desc *fonts[] = {
#ifdef CONFIG_FONT_8x8
#undef NO_FONTS
&font_vga_8x8,
@@ -84,7 +84,7 @@ static struct font_desc *fonts[] = {
*
*/
-struct font_desc *find_font(char *name)
+const struct font_desc *find_font(const char *name)
{
unsigned int i;
@@ -108,10 +108,10 @@ struct font_desc *find_font(char *name)
*
*/
-struct font_desc *get_default_font(int xres, int yres)
+const struct font_desc *get_default_font(int xres, int yres)
{
int i, c, cc;
- struct font_desc *f, *g;
+ const struct font_desc *f, *g;
g = NULL;
cc = -10000;
@@ -138,7 +138,6 @@ struct font_desc *get_default_font(int xres, int yres)
return g;
}
-EXPORT_SYMBOL(fonts);
EXPORT_SYMBOL(find_font);
EXPORT_SYMBOL(get_default_font);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 0705cd7..6ef6f77 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)
static int vgacon_resize(struct vc_data *c, unsigned int width,
unsigned int height)
{
- if (width % 2 || width > ORIG_VIDEO_COLS || height > ORIG_VIDEO_LINES)
+ if (width % 2 || width > ORIG_VIDEO_COLS ||
+ height > (ORIG_VIDEO_LINES * vga_default_font_height)/
+ c->vc_font.height)
return -EINVAL;
if (CON_IS_VISIBLE(c) && !vga_is_gfx) /* who knows */
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index cabd53c..6c2244c 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -425,7 +425,7 @@ static void imxfb_setup_gpio(struct imxfb_info *fbi)
* Power management hooks. Note that we won't be called from IRQ context,
* unlike the blank functions above, so we may sleep.
*/
-static int imxfb_suspend(struct device *dev, u32 state, u32 level)
+static int imxfb_suspend(struct device *dev, pm_message_t state, u32 level)
{
struct imxfb_info *fbi = dev_get_drvdata(dev);
pr_debug("%s\n",__FUNCTION__);
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 98e00d8..e02da41 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
vaddr_t vm;
unsigned int offs;
unsigned int offs2;
- unsigned char store;
+ unsigned char store, orig;
unsigned char bytes[32];
unsigned char* tmp;
@@ -1298,7 +1298,8 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
if (maxSize > 0x2000000) maxSize = 0x2000000;
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
+ orig = mga_inb(M_EXTVGA_DATA);
+ mga_outb(M_EXTVGA_DATA, orig | 0x80);
store = mga_readb(vm, 0x1234);
tmp = bytes;
@@ -1323,7 +1324,7 @@ static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int *realSi
mga_writeb(vm, 0x1234, store);
mga_outb(M_EXTVGA_INDEX, 0x03);
- mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
+ mga_outb(M_EXTVGA_DATA, orig);
*realSize = offs - 0x100000;
#ifdef CONFIG_FB_MATROX_MILLENIUM
@@ -1858,6 +1859,8 @@ static int initMatrox2(WPMINFO struct board* b){
to yres_virtual * xres_virtual < 2^32 */
}
matroxfb_init_fix(PMINFO2);
+ ACCESS_FBINFO(fbcon.screen_base) = vaddr_va(ACCESS_FBINFO(video.vbase));
+ matroxfb_update_fix(PMINFO2);
/* Normalize values (namely yres_virtual) */
matroxfb_check_var(&vesafb_defined, &ACCESS_FBINFO(fbcon));
/* 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
}
/* not match... */
if (!b->vendor)
- return -1;
+ return -ENODEV;
if (dev > 0) {
/* not requested one... */
dev--;
- return -1;
+ return -ENODEV;
}
pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
if (pci_enable_device(pdev)) {
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
index ace484f..12f2884 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)
if (!edid && conn == 1) {
/* try to get from firmware */
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, fb_firmware_edid(info->device),
- EDID_LENGTH);
+ const u8 *e = fb_firmware_edid(info->device);
+
+ if (e != NULL) {
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, e, EDID_LENGTH);
+ }
}
if (out_edid)
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index e0dad94..2e11b60 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -67,6 +67,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
+#include <linux/ctype.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
@@ -2594,7 +2595,7 @@ static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
{
char *next;
- if (!(CHAR_IS_NUM(options[0]))) {
+ if (!(isdigit(options[0]))) {
(*bn) = 0;
return (options);
}
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 959404a..3c98457 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)
if (!edid) {
/* try to get from firmware */
- edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
- if (edid)
- memcpy(edid, fb_firmware_edid(info->device),
- EDID_LENGTH);
+ const u8 *e = fb_firmware_edid(info->device);
+
+ if (e) {
+ edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+ if (edid)
+ memcpy(edid, e, EDID_LENGTH);
+ }
}
if (out_edid)
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index d6f9474..ea17f7e 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -60,8 +60,6 @@
#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
-#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR))
-
/* Chip tags. These are used to group the adapters into
* related families.
*/
@@ -74,8 +72,6 @@ typedef enum {
S3_PROSAVAGE,
S3_SUPERSAVAGE,
S3_SAVAGE2000,
- S3_PROSAVAGEDDR,
- S3_TWISTER,
S3_LAST
} savage_chipset;
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index b5ca3ef..7c28545 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)
}
}
- if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
- (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly))
+ if (S3_SAVAGE_MOBILE_SERIES(par->chip) && !par->crtonly)
par->display_type = DISP_LCD;
else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
par->display_type = DISP_DFP;
@@ -1783,7 +1782,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
/* Check LCD panel parrmation */
- if (par->chip == S3_SAVAGE_MX) {
+ if (par->display_type == DISP_LCD) {
unsigned char cr6b = VGArCR( 0x6b );
int panelX = (VGArSEQ (0x61) +
@@ -1922,15 +1921,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
snprintf (info->fix.id, 16, "ProSavageKM");
break;
case FB_ACCEL_S3TWISTER_P:
- par->chip = S3_TWISTER;
+ par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "TwisterP");
break;
case FB_ACCEL_S3TWISTER_K:
- par->chip = S3_TWISTER;
+ par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "TwisterK");
break;
case FB_ACCEL_PROSAVAGE_DDR:
- par->chip = S3_PROSAVAGEDDR;
+ par->chip = S3_PROSAVAGE;
snprintf (info->fix.id, 16, "ProSavageDDR");
break;
case FB_ACCEL_PROSAVAGE_DDRK:
OpenPOWER on IntegriCloud