summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/amiflop.c1
-rw-r--r--drivers/block/cciss.c3216
-rw-r--r--drivers/block/cciss.h2
-rw-r--r--drivers/block/cpqarray.c9
-rw-r--r--drivers/block/loop.c24
-rw-r--r--drivers/block/nbd.c34
-rw-r--r--drivers/cdrom/mcdx.c2
-rw-r--r--drivers/char/Kconfig1
-rw-r--r--drivers/char/applicom.c40
-rw-r--r--drivers/char/cyclades.c7
-rw-r--r--drivers/char/esp.c4
-rw-r--r--drivers/char/ip2/ip2main.c12
-rw-r--r--drivers/char/isicom.c4
-rw-r--r--drivers/char/keyboard.c1
-rw-r--r--drivers/char/mmtimer.c1
-rw-r--r--drivers/char/mxser.c836
-rw-r--r--drivers/char/n_r3964.c3
-rw-r--r--drivers/char/pcmcia/synclink_cs.c4
-rw-r--r--drivers/char/rocket.c62
-rw-r--r--drivers/char/specialix.c4
-rw-r--r--drivers/char/synclink_gt.c119
-rw-r--r--drivers/char/synclinkmp.c4
-rw-r--r--drivers/firmware/Kconfig3
-rw-r--r--drivers/firmware/dmi_scan.c13
-rw-r--r--drivers/ide/ide-cd.c120
-rw-r--r--drivers/ide/ide-floppy.c2
-rw-r--r--drivers/ide/ide-io.c57
-rw-r--r--drivers/ide/ide-tape.c49
-rw-r--r--drivers/ieee1394/Kconfig2
-rw-r--r--drivers/ieee1394/nodemgr.c5
-rw-r--r--drivers/input/touchscreen/ads7846.c3
-rw-r--r--drivers/input/touchscreen/h3600_ts_input.c6
-rw-r--r--drivers/leds/Kconfig9
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/ledtrig-heartbeat.c118
-rw-r--r--drivers/macintosh/Kconfig19
-rw-r--r--drivers/macintosh/Makefile1
-rw-r--r--drivers/macintosh/adbhid.c28
-rw-r--r--drivers/macintosh/via-pmu-backlight.c150
-rw-r--r--drivers/macintosh/via-pmu.c120
-rw-r--r--drivers/net/irda/irda-usb.c2
-rw-r--r--drivers/net/sun3lance.c2
-rw-r--r--drivers/net/wan/sdla.c4
-rw-r--r--drivers/oprofile/buffer_sync.c8
-rw-r--r--drivers/oprofile/event_buffer.c12
-rw-r--r--drivers/oprofile/event_buffer.h4
-rw-r--r--drivers/oprofile/oprof.c26
-rw-r--r--drivers/parport/Kconfig12
-rw-r--r--drivers/parport/Makefile3
-rw-r--r--drivers/parport/daisy.c2
-rw-r--r--drivers/parport/parport_ax88796.c443
-rw-r--r--drivers/parport/share.c2
-rw-r--r--drivers/pnp/card.c48
-rw-r--r--drivers/rtc/Kconfig91
-rw-r--r--drivers/rtc/Makefile8
-rw-r--r--drivers/rtc/class.c1
-rw-r--r--drivers/rtc/interface.c22
-rw-r--r--drivers/rtc/rtc-at91.c407
-rw-r--r--drivers/rtc/rtc-dev.c131
-rw-r--r--drivers/rtc/rtc-ds1307.c388
-rw-r--r--drivers/rtc/rtc-ds1553.c414
-rw-r--r--drivers/rtc/rtc-ds1742.c259
-rw-r--r--drivers/rtc/rtc-lib.c19
-rw-r--r--drivers/rtc/rtc-max6902.c286
-rw-r--r--drivers/rtc/rtc-pcf8583.c394
-rw-r--r--drivers/rtc/rtc-pl031.c233
-rw-r--r--drivers/rtc/rtc-sa1100.c4
-rw-r--r--drivers/rtc/rtc-v3020.c264
-rw-r--r--drivers/rtc/rtc-vr41xx.c8
-rw-r--r--drivers/s390/char/sclp_quiesce.c3
-rw-r--r--drivers/sbus/char/flash.c1
-rw-r--r--drivers/sbus/char/vfc_dev.c2
-rw-r--r--drivers/scsi/advansys.c6
-rw-r--r--drivers/scsi/mac_esp.c7
-rw-r--r--drivers/scsi/mac_scsi.c7
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c2
-rw-r--r--drivers/scsi/sun3x_esp.c8
-rw-r--r--drivers/scsi/wd7000.c2
-rw-r--r--drivers/video/Kconfig56
-rw-r--r--drivers/video/aty/Makefile1
-rw-r--r--drivers/video/aty/aty128fb.c322
-rw-r--r--drivers/video/aty/atyfb.h1
-rw-r--r--drivers/video/aty/atyfb_base.c178
-rw-r--r--drivers/video/aty/radeon_backlight.c247
-rw-r--r--drivers/video/aty/radeon_base.c140
-rw-r--r--drivers/video/aty/radeonfb.h9
-rw-r--r--drivers/video/chipsfb.c30
-rw-r--r--drivers/video/fbsysfs.c88
-rw-r--r--drivers/video/igafb.c3
-rw-r--r--drivers/video/nvidia/Makefile3
-rw-r--r--drivers/video/nvidia/nv_backlight.c175
-rw-r--r--drivers/video/nvidia/nv_proto.h10
-rw-r--r--drivers/video/nvidia/nvidia.c95
-rw-r--r--drivers/video/riva/fbdev.c222
-rw-r--r--drivers/video/tridentfb.c6
95 files changed, 7354 insertions, 2863 deletions
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 2a8af68..2641597 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -64,6 +64,7 @@
#include <linux/buffer_head.h>
#include <linux/blkdev.h>
#include <linux/elevator.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 25c3c4a..39b0f53 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -34,7 +34,7 @@
#include <linux/blkpg.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
-#include <linux/init.h>
+#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/spinlock.h>
#include <linux/compat.h>
@@ -64,143 +64,129 @@ MODULE_LICENSE("GPL");
/* define the PCI info for the cards we can control */
static const struct pci_device_id cciss_pci_device_id[] = {
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS,
- 0x0E11, 0x4070, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
- 0x0E11, 0x4080, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
- 0x0E11, 0x4082, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB,
- 0x0E11, 0x4083, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
- 0x0E11, 0x409A, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
- 0x0E11, 0x409B, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
- 0x0E11, 0x409C, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
- 0x0E11, 0x409D, 0, 0, 0},
- { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC,
- 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_CISSC,
- 0x103c, 0x3223, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 0x103c, 0x3234, 0, 0, 0},
- { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC,
- 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},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISS, 0x0E11, 0x4070},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4080},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4082},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSB, 0x0E11, 0x4083},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x4091},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409A},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409B},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409C},
+ {PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_CISSC, 0x0E11, 0x409D},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA, 0x103C, 0x3225},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3223},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3234},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3235},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3211},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3212},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3213},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215},
{0,}
};
-MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
-#define NR_PRODUCTS ARRAY_SIZE(products)
+MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
/* board_id = Subsystem Device ID & Vendor ID
* product = Marketing Name for the board
- * access = Address of the struct of function pointers
+ * access = Address of the struct of function pointers
*/
static struct board_type products[] = {
- { 0x40700E11, "Smart Array 5300", &SA5_access },
- { 0x40800E11, "Smart Array 5i", &SA5B_access},
- { 0x40820E11, "Smart Array 532", &SA5B_access},
- { 0x40830E11, "Smart Array 5312", &SA5B_access},
- { 0x409A0E11, "Smart Array 641", &SA5_access},
- { 0x409B0E11, "Smart Array 642", &SA5_access},
- { 0x409C0E11, "Smart Array 6400", &SA5_access},
- { 0x409D0E11, "Smart Array 6400 EM", &SA5_access},
- { 0x40910E11, "Smart Array 6i", &SA5_access},
- { 0x3225103C, "Smart Array P600", &SA5_access},
- { 0x3223103C, "Smart Array P800", &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},
+ {0x40700E11, "Smart Array 5300", &SA5_access},
+ {0x40800E11, "Smart Array 5i", &SA5B_access},
+ {0x40820E11, "Smart Array 532", &SA5B_access},
+ {0x40830E11, "Smart Array 5312", &SA5B_access},
+ {0x409A0E11, "Smart Array 641", &SA5_access},
+ {0x409B0E11, "Smart Array 642", &SA5_access},
+ {0x409C0E11, "Smart Array 6400", &SA5_access},
+ {0x409D0E11, "Smart Array 6400 EM", &SA5_access},
+ {0x40910E11, "Smart Array 6i", &SA5_access},
+ {0x3225103C, "Smart Array P600", &SA5_access},
+ {0x3223103C, "Smart Array P800", &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 */
-#define MAX_CONFIG_WAIT 30000
+/* How long to wait (in milliseconds) for board to go into simple mode */
+#define MAX_CONFIG_WAIT 30000
#define MAX_IOCTL_CONFIG_WAIT 1000
/*define how many times we will try a command because of bus resets */
#define MAX_CMD_RETRIES 3
#define READ_AHEAD 1024
-#define NR_CMDS 384 /* #commands that can be outstanding */
+#define NR_CMDS 384 /* #commands that can be outstanding */
#define MAX_CTLR 32
/* Originally cciss driver only supports 8 major numbers */
#define MAX_CTLR_ORIG 8
-
static ctlr_info_t *hba[MAX_CTLR];
static void do_cciss_request(request_queue_t *q);
static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs);
static int cciss_open(struct inode *inode, struct file *filep);
static int cciss_release(struct inode *inode, struct file *filep);
-static int cciss_ioctl(struct inode *inode, struct file *filep,
- unsigned int cmd, unsigned long arg);
+static int cciss_ioctl(struct inode *inode, struct file *filep,
+ unsigned int cmd, unsigned long arg);
static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
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 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);
+ 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 __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, __u32);
-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 __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
+ __u32);
+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,
- int length, int *eof, void *data);
+static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data);
static void cciss_procinit(int i);
#else
-static void cciss_procinit(int i) {}
-#endif /* CONFIG_PROC_FS */
+static void cciss_procinit(int i)
+{
+}
+#endif /* CONFIG_PROC_FS */
#ifdef CONFIG_COMPAT
static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
#endif
-static struct block_device_operations cciss_fops = {
- .owner = THIS_MODULE,
- .open = cciss_open,
- .release = cciss_release,
- .ioctl = cciss_ioctl,
- .getgeo = cciss_getgeo,
+static struct block_device_operations cciss_fops = {
+ .owner = THIS_MODULE,
+ .open = cciss_open,
+ .release = cciss_release,
+ .ioctl = cciss_ioctl,
+ .getgeo = cciss_getgeo,
#ifdef CONFIG_COMPAT
- .compat_ioctl = cciss_compat_ioctl,
+ .compat_ioctl = cciss_compat_ioctl,
#endif
- .revalidate_disk= cciss_revalidate,
+ .revalidate_disk = cciss_revalidate,
};
/*
@@ -208,28 +194,29 @@ static struct block_device_operations cciss_fops = {
*/
static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c)
{
- if (*Qptr == NULL) {
- *Qptr = c;
- c->next = c->prev = c;
- } else {
- c->prev = (*Qptr)->prev;
- c->next = (*Qptr);
- (*Qptr)->prev->next = c;
- (*Qptr)->prev = c;
- }
+ if (*Qptr == NULL) {
+ *Qptr = c;
+ c->next = c->prev = c;
+ } else {
+ c->prev = (*Qptr)->prev;
+ c->next = (*Qptr);
+ (*Qptr)->prev->next = c;
+ (*Qptr)->prev = c;
+ }
}
-static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
- CommandList_struct *c)
+static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
+ CommandList_struct *c)
{
- if (c && c->next != c) {
- if (*Qptr == c) *Qptr = c->next;
- c->prev->next = c->next;
- c->next->prev = c->prev;
- } else {
- *Qptr = NULL;
- }
- return c;
+ if (c && c->next != c) {
+ if (*Qptr == c)
+ *Qptr = c->next;
+ c->prev->next = c->next;
+ c->next->prev = c->prev;
+ } else {
+ *Qptr = NULL;
+ }
+ return c;
}
#include "cciss_scsi.c" /* For SCSI tape support */
@@ -242,23 +229,24 @@ static inline CommandList_struct *removeQ(CommandList_struct **Qptr,
#define ENG_GIG 1000000000
#define ENG_GIG_FACTOR (ENG_GIG/512)
#define RAID_UNKNOWN 6
-static const char *raid_label[] = {"0","4","1(1+0)","5","5+1","ADG",
- "UNKNOWN"};
+static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
+ "UNKNOWN"
+};
static struct proc_dir_entry *proc_cciss;
-static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
- int length, int *eof, void *data)
+static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
+ int length, int *eof, void *data)
{
- off_t pos = 0;
- off_t len = 0;
- int size, i, ctlr;
- ctlr_info_t *h = (ctlr_info_t*)data;
- drive_info_struct *drv;
+ off_t pos = 0;
+ off_t len = 0;
+ int size, i, ctlr;
+ ctlr_info_t *h = (ctlr_info_t *) data;
+ drive_info_struct *drv;
unsigned long flags;
- sector_t vol_sz, vol_sz_frac;
+ sector_t vol_sz, vol_sz_frac;
- ctlr = h->ctlr;
+ ctlr = h->ctlr;
/* prevent displaying bogus info during configuration
* or deconfiguration of a logical volume
@@ -266,35 +254,35 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
if (h->busy_configuring) {
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- return -EBUSY;
+ return -EBUSY;
}
h->busy_configuring = 1;
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- size = sprintf(buffer, "%s: HP %s Controller\n"
- "Board ID: 0x%08lx\n"
- "Firmware Version: %c%c%c%c\n"
- "IRQ: %d\n"
- "Logical drives: %d\n"
- "Current Q depth: %d\n"
- "Current # commands on controller: %d\n"
- "Max Q depth since init: %d\n"
- "Max # commands on controller since init: %d\n"
- "Max SG entries since init: %d\n\n",
- h->devname,
- h->product_name,
- (unsigned long)h->board_id,
- h->firm_ver[0], h->firm_ver[1], h->firm_ver[2], h->firm_ver[3],
- (unsigned int)h->intr[SIMPLE_MODE_INT],
- h->num_luns,
- h->Qdepth, h->commands_outstanding,
- h->maxQsinceinit, h->max_outstanding, h->maxSG);
-
- pos += size; len += size;
+ size = sprintf(buffer, "%s: HP %s Controller\n"
+ "Board ID: 0x%08lx\n"
+ "Firmware Version: %c%c%c%c\n"
+ "IRQ: %d\n"
+ "Logical drives: %d\n"
+ "Current Q depth: %d\n"
+ "Current # commands on controller: %d\n"
+ "Max Q depth since init: %d\n"
+ "Max # commands on controller since init: %d\n"
+ "Max SG entries since init: %d\n\n",
+ h->devname,
+ h->product_name,
+ (unsigned long)h->board_id,
+ h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
+ h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT],
+ h->num_luns, h->Qdepth, h->commands_outstanding,
+ h->maxQsinceinit, h->max_outstanding, h->maxSG);
+
+ pos += size;
+ len += size;
cciss_proc_tape_report(ctlr, buffer, &pos, &len);
- for(i=0; i<=h->highest_lun; i++) {
+ for (i = 0; i <= h->highest_lun; i++) {
- drv = &h->drv[i];
+ drv = &h->drv[i];
if (drv->heads == 0)
continue;
@@ -305,25 +293,26 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
if (drv->raid_level > 5)
drv->raid_level = RAID_UNKNOWN;
- size = sprintf(buffer+len, "cciss/c%dd%d:"
- "\t%4u.%02uGB\tRAID %s\n",
- ctlr, i, (int)vol_sz, (int)vol_sz_frac,
- raid_label[drv->raid_level]);
- pos += size; len += size;
- }
-
- *eof = 1;
- *start = buffer+offset;
- len -= offset;
- if (len>length)
- len = length;
+ size = sprintf(buffer + len, "cciss/c%dd%d:"
+ "\t%4u.%02uGB\tRAID %s\n",
+ ctlr, i, (int)vol_sz, (int)vol_sz_frac,
+ raid_label[drv->raid_level]);
+ pos += size;
+ len += size;
+ }
+
+ *eof = 1;
+ *start = buffer + offset;
+ len -= offset;
+ if (len > length)
+ len = length;
h->busy_configuring = 0;
- return len;
+ return len;
}
-static int
-cciss_proc_write(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
+static int
+cciss_proc_write(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
{
unsigned char cmd[80];
int len;
@@ -332,20 +321,23 @@ cciss_proc_write(struct file *file, const char __user *buffer,
int rc;
#endif
- if (count > sizeof(cmd)-1) return -EINVAL;
- if (copy_from_user(cmd, buffer, count)) return -EFAULT;
+ if (count > sizeof(cmd) - 1)
+ return -EINVAL;
+ if (copy_from_user(cmd, buffer, count))
+ return -EFAULT;
cmd[count] = '\0';
len = strlen(cmd); // above 3 lines ensure safety
- if (len && cmd[len-1] == '\n')
+ if (len && cmd[len - 1] == '\n')
cmd[--len] = '\0';
# ifdef CONFIG_CISS_SCSI_TAPE
- if (strcmp("engage scsi", cmd)==0) {
- rc = cciss_engage_scsi(h->ctlr);
- if (rc != 0) return -rc;
- return count;
- }
- /* might be nice to have "disengage" too, but it's not
- safely possible. (only 1 module use count, lock issues.) */
+ if (strcmp("engage scsi", cmd) == 0) {
+ rc = cciss_engage_scsi(h->ctlr);
+ if (rc != 0)
+ return -rc;
+ return count;
+ }
+ /* might be nice to have "disengage" too, but it's not
+ safely possible. (only 1 module use count, lock issues.) */
# endif
return -EINVAL;
}
@@ -358,116 +350,113 @@ static void __devinit cciss_procinit(int i)
{
struct proc_dir_entry *pde;
- if (proc_cciss == NULL) {
- proc_cciss = proc_mkdir("cciss", proc_root_driver);
- if (!proc_cciss)
+ if (proc_cciss == NULL) {
+ proc_cciss = proc_mkdir("cciss", proc_root_driver);
+ if (!proc_cciss)
return;
- }
+ }
- pde = create_proc_read_entry(hba[i]->devname,
- S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH,
- proc_cciss, cciss_proc_get_info, hba[i]);
+ pde = create_proc_read_entry(hba[i]->devname,
+ S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH,
+ proc_cciss, cciss_proc_get_info, hba[i]);
pde->write_proc = cciss_proc_write;
}
-#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_PROC_FS */
-/*
- * For operations that cannot sleep, a command block is allocated at init,
+/*
+ * For operations that cannot sleep, a command block is allocated at init,
* and managed by cmd_alloc() and cmd_free() using a simple bitmap to track
- * which ones are free or in use. For operations that can wait for kmalloc
- * to possible sleep, this routine can be called with get_from_pool set to 0.
- * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was.
- */
-static CommandList_struct * cmd_alloc(ctlr_info_t *h, int get_from_pool)
+ * which ones are free or in use. For operations that can wait for kmalloc
+ * to possible sleep, this routine can be called with get_from_pool set to 0.
+ * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was.
+ */
+static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
{
CommandList_struct *c;
- int i;
+ int i;
u64bit temp64;
dma_addr_t cmd_dma_handle, err_dma_handle;
- if (!get_from_pool)
- {
- c = (CommandList_struct *) pci_alloc_consistent(
- h->pdev, sizeof(CommandList_struct), &cmd_dma_handle);
- if(c==NULL)
- return NULL;
+ if (!get_from_pool) {
+ c = (CommandList_struct *) pci_alloc_consistent(h->pdev,
+ sizeof(CommandList_struct), &cmd_dma_handle);
+ if (c == NULL)
+ 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);
-
- if (c->err_info == NULL)
- {
- pci_free_consistent(h->pdev,
+ c->err_info = (ErrorInfo_struct *)
+ pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct),
+ &err_dma_handle);
+
+ if (c->err_info == NULL) {
+ pci_free_consistent(h->pdev,
sizeof(CommandList_struct), c, cmd_dma_handle);
return NULL;
}
memset(c->err_info, 0, sizeof(ErrorInfo_struct));
- } else /* get it out of the controllers pool */
- {
- do {
- i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
- if (i == NR_CMDS)
- return NULL;
- } while(test_and_set_bit(i & (BITS_PER_LONG - 1), h->cmd_pool_bits+(i/BITS_PER_LONG)) != 0);
+ } else { /* get it out of the controllers pool */
+
+ do {
+ i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
+ if (i == NR_CMDS)
+ return NULL;
+ } while (test_and_set_bit
+ (i & (BITS_PER_LONG - 1),
+ h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0);
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss: using command buffer %d\n", i);
#endif
- c = h->cmd_pool + i;
+ c = h->cmd_pool + i;
memset(c, 0, sizeof(CommandList_struct));
- cmd_dma_handle = h->cmd_pool_dhandle
- + i*sizeof(CommandList_struct);
+ cmd_dma_handle = h->cmd_pool_dhandle
+ + i * sizeof(CommandList_struct);
c->err_info = h->errinfo_pool + i;
memset(c->err_info, 0, sizeof(ErrorInfo_struct));
- err_dma_handle = h->errinfo_pool_dhandle
- + i*sizeof(ErrorInfo_struct);
- h->nr_allocs++;
+ err_dma_handle = h->errinfo_pool_dhandle
+ + i * sizeof(ErrorInfo_struct);
+ h->nr_allocs++;
c->cmdindex = i;
- }
+ }
c->busaddr = (__u32) cmd_dma_handle;
- temp64.val = (__u64) err_dma_handle;
+ temp64.val = (__u64) err_dma_handle;
c->ErrDesc.Addr.lower = temp64.val32.lower;
c->ErrDesc.Addr.upper = temp64.val32.upper;
c->ErrDesc.Len = sizeof(ErrorInfo_struct);
-
- c->ctlr = h->ctlr;
- return c;
-
+ c->ctlr = h->ctlr;
+ return c;
}
-/*
- * Frees a command block that was previously allocated with cmd_alloc().
+/*
+ * Frees a command block that was previously allocated with cmd_alloc().
*/
static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool)
{
int i;
u64bit temp64;
- if( !got_from_pool)
- {
+ if (!got_from_pool) {
temp64.val32.lower = c->ErrDesc.Addr.lower;
temp64.val32.upper = c->ErrDesc.Addr.upper;
- pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct),
- c->err_info, (dma_addr_t) temp64.val);
- pci_free_consistent(h->pdev, sizeof(CommandList_struct),
- c, (dma_addr_t) c->busaddr);
- } else
- {
+ pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct),
+ c->err_info, (dma_addr_t) temp64.val);
+ pci_free_consistent(h->pdev, sizeof(CommandList_struct),
+ c, (dma_addr_t) c->busaddr);
+ } else {
i = c - h->cmd_pool;
- clear_bit(i&(BITS_PER_LONG-1), h->cmd_pool_bits+(i/BITS_PER_LONG));
- h->nr_frees++;
- }
+ clear_bit(i & (BITS_PER_LONG - 1),
+ h->cmd_pool_bits + (i / BITS_PER_LONG));
+ h->nr_frees++;
+ }
}
static inline ctlr_info_t *get_host(struct gendisk *disk)
{
- return disk->queue->queuedata;
+ return disk->queue->queuedata;
}
static inline drive_info_struct *get_drv(struct gendisk *disk)
@@ -485,7 +474,7 @@ static int cciss_open(struct inode *inode, struct file *filep)
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss_open %s\n", inode->i_bdev->bd_disk->disk_name);
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
if (host->busy_initializing || drv->busy_configuring)
return -EBUSY;
@@ -498,10 +487,10 @@ static int cciss_open(struct inode *inode, struct file *filep)
* for "raw controller".
*/
if (drv->nr_blocks == 0) {
- if (iminor(inode) != 0) { /* not node 0? */
+ if (iminor(inode) != 0) { /* not node 0? */
/* if not node 0 make sure it is a partition = 0 */
if (iminor(inode) & 0x0f) {
- return -ENXIO;
+ return -ENXIO;
/* if it is, make sure we have a LUN ID */
} else if (drv->LunID == 0) {
return -ENXIO;
@@ -514,6 +503,7 @@ static int cciss_open(struct inode *inode, struct file *filep)
host->usage_count++;
return 0;
}
+
/*
* Close. Sync first.
*/
@@ -523,8 +513,9 @@ static int cciss_release(struct inode *inode, struct file *filep)
drive_info_struct *drv = get_drv(inode->i_bdev->bd_disk);
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss_release %s\n", inode->i_bdev->bd_disk->disk_name);
-#endif /* CCISS_DEBUG */
+ printk(KERN_DEBUG "cciss_release %s\n",
+ inode->i_bdev->bd_disk->disk_name);
+#endif /* CCISS_DEBUG */
drv->usage_count--;
host->usage_count--;
@@ -542,8 +533,10 @@ static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg)
return ret;
}
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, unsigned long arg);
-static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd, unsigned long arg);
+static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
+ unsigned long arg);
+static int cciss_ioctl32_big_passthru(struct file *f, unsigned cmd,
+ unsigned long arg);
static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
{
@@ -575,19 +568,26 @@ static long cciss_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
}
}
-static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, unsigned long arg)
+static int cciss_ioctl32_passthru(struct file *f, unsigned cmd,
+ unsigned long arg)
{
IOCTL32_Command_struct __user *arg32 =
- (IOCTL32_Command_struct __user *) arg;
+ (IOCTL32_Command_struct __user *) arg;
IOCTL_Command_struct arg64;
IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
int err;
u32 cp;
err = 0;
- err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
- err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
- err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+ err |=
+ copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+ sizeof(arg64.LUN_info));
+ err |=
+ copy_from_user(&arg64.Request, &arg32->Request,
+ sizeof(arg64.Request));
+ err |=
+ copy_from_user(&arg64.error_info, &arg32->error_info,
+ sizeof(arg64.error_info));
err |= get_user(arg64.buf_size, &arg32->buf_size);
err |= get_user(cp, &arg32->buf);
arg64.buf = compat_ptr(cp);
@@ -596,28 +596,38 @@ static int cciss_ioctl32_passthru(struct file *f, unsigned cmd, unsigned long ar
if (err)
return -EFAULT;
- err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long) p);
+ err = do_ioctl(f, CCISS_PASSTHRU, (unsigned long)p);
if (err)
return err;
- err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
+ err |=
+ copy_in_user(&arg32->error_info, &p->error_info,
+ sizeof(arg32->error_info));
if (err)
return -EFAULT;
return err;
}
-static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned long arg)
+static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd,
+ unsigned long arg)
{
BIG_IOCTL32_Command_struct __user *arg32 =
- (BIG_IOCTL32_Command_struct __user *) arg;
+ (BIG_IOCTL32_Command_struct __user *) arg;
BIG_IOCTL_Command_struct arg64;
- BIG_IOCTL_Command_struct __user *p = compat_alloc_user_space(sizeof(arg64));
+ BIG_IOCTL_Command_struct __user *p =
+ compat_alloc_user_space(sizeof(arg64));
int err;
u32 cp;
err = 0;
- err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, sizeof(arg64.LUN_info));
- err |= copy_from_user(&arg64.Request, &arg32->Request, sizeof(arg64.Request));
- err |= copy_from_user(&arg64.error_info, &arg32->error_info, sizeof(arg64.error_info));
+ err |=
+ copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
+ sizeof(arg64.LUN_info));
+ err |=
+ copy_from_user(&arg64.Request, &arg32->Request,
+ sizeof(arg64.Request));
+ err |=
+ copy_from_user(&arg64.error_info, &arg32->error_info,
+ sizeof(arg64.error_info));
err |= get_user(arg64.buf_size, &arg32->buf_size);
err |= get_user(arg64.malloc_size, &arg32->malloc_size);
err |= get_user(cp, &arg32->buf);
@@ -625,12 +635,14 @@ static int cciss_ioctl32_big_passthru(struct file *file, unsigned cmd, unsigned
err |= copy_to_user(p, &arg64, sizeof(arg64));
if (err)
- return -EFAULT;
+ return -EFAULT;
- err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long) p);
+ err = do_ioctl(file, CCISS_BIG_PASSTHRU, (unsigned long)p);
if (err)
return err;
- err |= copy_in_user(&arg32->error_info, &p->error_info, sizeof(arg32->error_info));
+ err |=
+ copy_in_user(&arg32->error_info, &p->error_info,
+ sizeof(arg32->error_info));
if (err)
return -EFAULT;
return err;
@@ -651,10 +663,10 @@ static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo)
}
/*
- * ioctl
+ * ioctl
*/
-static int cciss_ioctl(struct inode *inode, struct file *filep,
- unsigned int cmd, unsigned long arg)
+static int cciss_ioctl(struct inode *inode, struct file *filep,
+ unsigned int cmd, unsigned long arg)
{
struct block_device *bdev = inode->i_bdev;
struct gendisk *disk = bdev->bd_disk;
@@ -665,171 +677,193 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg);
-#endif /* CCISS_DEBUG */
-
- switch(cmd) {
+#endif /* CCISS_DEBUG */
+
+ switch (cmd) {
case CCISS_GETPCIINFO:
- {
- cciss_pci_info_struct pciinfo;
-
- if (!arg) return -EINVAL;
- pciinfo.domain = pci_domain_nr(host->pdev->bus);
- pciinfo.bus = host->pdev->bus->number;
- pciinfo.dev_fn = host->pdev->devfn;
- pciinfo.board_id = host->board_id;
- if (copy_to_user(argp, &pciinfo, sizeof( cciss_pci_info_struct )))
- return -EFAULT;
- return(0);
- }
+ {
+ cciss_pci_info_struct pciinfo;
+
+ if (!arg)
+ return -EINVAL;
+ pciinfo.domain = pci_domain_nr(host->pdev->bus);
+ pciinfo.bus = host->pdev->bus->number;
+ pciinfo.dev_fn = host->pdev->devfn;
+ pciinfo.board_id = host->board_id;
+ if (copy_to_user
+ (argp, &pciinfo, sizeof(cciss_pci_info_struct)))
+ return -EFAULT;
+ return 0;
+ }
case CCISS_GETINTINFO:
- {
- cciss_coalint_struct intinfo;
- if (!arg) return -EINVAL;
- intinfo.delay = readl(&host->cfgtable->HostWrite.CoalIntDelay);
- intinfo.count = readl(&host->cfgtable->HostWrite.CoalIntCount);
- if (copy_to_user(argp, &intinfo, sizeof( cciss_coalint_struct )))
- return -EFAULT;
- return(0);
- }
+ {
+ cciss_coalint_struct intinfo;
+ if (!arg)
+ return -EINVAL;
+ intinfo.delay =
+ readl(&host->cfgtable->HostWrite.CoalIntDelay);
+ intinfo.count =
+ readl(&host->cfgtable->HostWrite.CoalIntCount);
+ if (copy_to_user
+ (argp, &intinfo, sizeof(cciss_coalint_struct)))
+ return -EFAULT;
+ return 0;
+ }
case CCISS_SETINTINFO:
- {
- cciss_coalint_struct intinfo;
- unsigned long flags;
- int i;
-
- if (!arg) return -EINVAL;
- if (!capable(CAP_SYS_ADMIN)) return -EPERM;
- if (copy_from_user(&intinfo, argp, sizeof( cciss_coalint_struct)))
- return -EFAULT;
- if ( (intinfo.delay == 0 ) && (intinfo.count == 0))
-
{
-// printk("cciss_ioctl: delay and count cannot be 0\n");
- return( -EINVAL);
+ cciss_coalint_struct intinfo;
+ unsigned long flags;
+ int i;
+
+ if (!arg)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (copy_from_user
+ (&intinfo, argp, sizeof(cciss_coalint_struct)))
+ return -EFAULT;
+ if ((intinfo.delay == 0) && (intinfo.count == 0))
+ {
+// printk("cciss_ioctl: delay and count cannot be 0\n");
+ return -EINVAL;
+ }
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+ /* Update the field, and then ring the doorbell */
+ writel(intinfo.delay,
+ &(host->cfgtable->HostWrite.CoalIntDelay));
+ writel(intinfo.count,
+ &(host->cfgtable->HostWrite.CoalIntCount));
+ writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
+
+ for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+ if (!(readl(host->vaddr + SA5_DOORBELL)
+ & CFGTBL_ChangeReq))
+ break;
+ /* delay and try again */
+ udelay(1000);
+ }
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ return -EAGAIN;
+ return 0;
}
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
- /* Update the field, and then ring the doorbell */
- writel( intinfo.delay,
- &(host->cfgtable->HostWrite.CoalIntDelay));
- writel( intinfo.count,
- &(host->cfgtable->HostWrite.CoalIntCount));
- writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
-
- for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) {
- if (!(readl(host->vaddr + SA5_DOORBELL)
- & CFGTBL_ChangeReq))
- break;
- /* delay and try again */
- udelay(1000);
- }
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- if (i >= MAX_IOCTL_CONFIG_WAIT)
- return -EAGAIN;
- return(0);
- }
case CCISS_GETNODENAME:
- {
- NodeName_type NodeName;
- int i;
-
- if (!arg) return -EINVAL;
- for(i=0;i<16;i++)
- NodeName[i] = readb(&host->cfgtable->ServerName[i]);
- if (copy_to_user(argp, NodeName, sizeof( NodeName_type)))
- return -EFAULT;
- return(0);
- }
+ {
+ NodeName_type NodeName;
+ int i;
+
+ if (!arg)
+ return -EINVAL;
+ for (i = 0; i < 16; i++)
+ NodeName[i] =
+ readb(&host->cfgtable->ServerName[i]);
+ if (copy_to_user(argp, NodeName, sizeof(NodeName_type)))
+ return -EFAULT;
+ return 0;
+ }
case CCISS_SETNODENAME:
- {
- NodeName_type NodeName;
- unsigned long flags;
- int i;
-
- if (!arg) return -EINVAL;
- if (!capable(CAP_SYS_ADMIN)) return -EPERM;
-
- if (copy_from_user(NodeName, argp, sizeof( NodeName_type)))
- return -EFAULT;
-
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
-
- /* Update the field, and then ring the doorbell */
- for(i=0;i<16;i++)
- writeb( NodeName[i], &host->cfgtable->ServerName[i]);
-
- writel( CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
-
- for(i=0;i<MAX_IOCTL_CONFIG_WAIT;i++) {
- if (!(readl(host->vaddr + SA5_DOORBELL)
- & CFGTBL_ChangeReq))
- break;
- /* delay and try again */
- udelay(1000);
- }
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- if (i >= MAX_IOCTL_CONFIG_WAIT)
- return -EAGAIN;
- return(0);
- }
+ {
+ NodeName_type NodeName;
+ unsigned long flags;
+ int i;
+
+ if (!arg)
+ return -EINVAL;
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user
+ (NodeName, argp, sizeof(NodeName_type)))
+ return -EFAULT;
+
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+
+ /* Update the field, and then ring the doorbell */
+ for (i = 0; i < 16; i++)
+ writeb(NodeName[i],
+ &host->cfgtable->ServerName[i]);
+
+ writel(CFGTBL_ChangeReq, host->vaddr + SA5_DOORBELL);
+
+ for (i = 0; i < MAX_IOCTL_CONFIG_WAIT; i++) {
+ if (!(readl(host->vaddr + SA5_DOORBELL)
+ & CFGTBL_ChangeReq))
+ break;
+ /* delay and try again */
+ udelay(1000);
+ }
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ if (i >= MAX_IOCTL_CONFIG_WAIT)
+ return -EAGAIN;
+ return 0;
+ }
case CCISS_GETHEARTBEAT:
- {
- Heartbeat_type heartbeat;
-
- if (!arg) return -EINVAL;
- heartbeat = readl(&host->cfgtable->HeartBeat);
- if (copy_to_user(argp, &heartbeat, sizeof( Heartbeat_type)))
- return -EFAULT;
- return(0);
- }
+ {
+ Heartbeat_type heartbeat;
+
+ if (!arg)
+ return -EINVAL;
+ heartbeat = readl(&host->cfgtable->HeartBeat);
+ if (copy_to_user
+ (argp, &heartbeat, sizeof(Heartbeat_type)))
+ return -EFAULT;
+ return 0;
+ }
case CCISS_GETBUSTYPES:
- {
- BusTypes_type BusTypes;
-
- if (!arg) return -EINVAL;
- BusTypes = readl(&host->cfgtable->BusTypes);
- if (copy_to_user(argp, &BusTypes, sizeof( BusTypes_type) ))
- return -EFAULT;
- return(0);
- }
+ {
+ BusTypes_type BusTypes;
+
+ if (!arg)
+ return -EINVAL;
+ BusTypes = readl(&host->cfgtable->BusTypes);
+ if (copy_to_user
+ (argp, &BusTypes, sizeof(BusTypes_type)))
+ return -EFAULT;
+ return 0;
+ }
case CCISS_GETFIRMVER:
- {
- FirmwareVer_type firmware;
+ {
+ FirmwareVer_type firmware;
- if (!arg) return -EINVAL;
- memcpy(firmware, host->firm_ver, 4);
+ if (!arg)
+ return -EINVAL;
+ memcpy(firmware, host->firm_ver, 4);
- if (copy_to_user(argp, firmware, sizeof( FirmwareVer_type)))
- return -EFAULT;
- return(0);
- }
- case CCISS_GETDRIVVER:
- {
- DriverVer_type DriverVer = DRIVER_VERSION;
+ if (copy_to_user
+ (argp, firmware, sizeof(FirmwareVer_type)))
+ return -EFAULT;
+ return 0;
+ }
+ case CCISS_GETDRIVVER:
+ {
+ DriverVer_type DriverVer = DRIVER_VERSION;
- if (!arg) return -EINVAL;
+ if (!arg)
+ return -EINVAL;
- if (copy_to_user(argp, &DriverVer, sizeof( DriverVer_type) ))
- return -EFAULT;
- return(0);
- }
+ if (copy_to_user
+ (argp, &DriverVer, sizeof(DriverVer_type)))
+ return -EFAULT;
+ return 0;
+ }
case CCISS_REVALIDVOLS:
if (bdev != bdev->bd_contains || drv != host->drv)
return -ENXIO;
- return revalidate_allvol(host);
-
- case CCISS_GETLUNINFO: {
- LogvolInfo_struct luninfo;
-
- luninfo.LunID = drv->LunID;
- luninfo.num_opens = drv->usage_count;
- luninfo.num_parts = 0;
- if (copy_to_user(argp, &luninfo,
- sizeof(LogvolInfo_struct)))
- return -EFAULT;
- return(0);
- }
+ return revalidate_allvol(host);
+
+ case CCISS_GETLUNINFO:{
+ LogvolInfo_struct luninfo;
+
+ luninfo.LunID = drv->LunID;
+ luninfo.num_opens = drv->usage_count;
+ luninfo.num_parts = 0;
+ if (copy_to_user(argp, &luninfo,
+ sizeof(LogvolInfo_struct)))
+ return -EFAULT;
+ return 0;
+ }
case CCISS_DEREGDISK:
return rebuild_lun_table(host, disk);
@@ -837,278 +871,284 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
return rebuild_lun_table(host, NULL);
case CCISS_PASSTHRU:
- {
- IOCTL_Command_struct iocommand;
- CommandList_struct *c;
- char *buff = NULL;
- u64bit temp64;
- unsigned long flags;
- DECLARE_COMPLETION(wait);
-
- if (!arg) return -EINVAL;
-
- if (!capable(CAP_SYS_RAWIO)) return -EPERM;
-
- if (copy_from_user(&iocommand, argp, sizeof( IOCTL_Command_struct) ))
- return -EFAULT;
- if((iocommand.buf_size < 1) &&
- (iocommand.Request.Type.Direction != XFER_NONE))
- {
- return -EINVAL;
- }
-#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
- /* Check kmalloc limits */
- if(iocommand.buf_size > 128000)
- return -EINVAL;
-#endif
- if(iocommand.buf_size > 0)
- {
- buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
- if( buff == NULL)
- return -EFAULT;
- }
- if (iocommand.Request.Type.Direction == XFER_WRITE)
- {
- /* Copy the data into the buffer we created */
- if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))
- {
- kfree(buff);
- return -EFAULT;
- }
- } else {
- memset(buff, 0, iocommand.buf_size);
- }
- if ((c = cmd_alloc(host , 0)) == NULL)
- {
- kfree(buff);
- return -ENOMEM;
- }
- // Fill in the command type
- c->cmd_type = CMD_IOCTL_PEND;
- // Fill in Command Header
- c->Header.ReplyQueue = 0; // unused in simple mode
- if( iocommand.buf_size > 0) // buffer to fill
{
- c->Header.SGList = 1;
- c->Header.SGTotal= 1;
- } else // no buffers to fill
- {
- c->Header.SGList = 0;
- c->Header.SGTotal= 0;
- }
- c->Header.LUN = iocommand.LUN_info;
- c->Header.Tag.lower = c->busaddr; // use the kernel address the cmd block for tag
-
- // Fill in Request block
- c->Request = iocommand.Request;
-
- // Fill in the scatter gather information
- if (iocommand.buf_size > 0 )
- {
- temp64.val = pci_map_single( host->pdev, buff,
- iocommand.buf_size,
- PCI_DMA_BIDIRECTIONAL);
- c->SG[0].Addr.lower = temp64.val32.lower;
- c->SG[0].Addr.upper = temp64.val32.upper;
- c->SG[0].Len = iocommand.buf_size;
- c->SG[0].Ext = 0; // we are not chaining
- }
- c->waiting = &wait;
+ IOCTL_Command_struct iocommand;
+ CommandList_struct *c;
+ char *buff = NULL;
+ u64bit temp64;
+ unsigned long flags;
+ DECLARE_COMPLETION(wait);
- /* Put the request on the tail of the request queue */
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
- addQ(&host->reqQ, c);
- host->Qdepth++;
- start_io(host);
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ if (!arg)
+ return -EINVAL;
- wait_for_completion(&wait);
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
- /* unlock the buffers from DMA */
- temp64.val32.lower = c->SG[0].Addr.lower;
- temp64.val32.upper = c->SG[0].Addr.upper;
- pci_unmap_single( host->pdev, (dma_addr_t) temp64.val,
- iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);
+ if (copy_from_user
+ (&iocommand, argp, sizeof(IOCTL_Command_struct)))
+ return -EFAULT;
+ if ((iocommand.buf_size < 1) &&
+ (iocommand.Request.Type.Direction != XFER_NONE)) {
+ return -EINVAL;
+ }
+#if 0 /* 'buf_size' member is 16-bits, and always smaller than kmalloc limit */
+ /* Check kmalloc limits */
+ if (iocommand.buf_size > 128000)
+ return -EINVAL;
+#endif
+ if (iocommand.buf_size > 0) {
+ buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
+ if (buff == NULL)
+ return -EFAULT;
+ }
+ if (iocommand.Request.Type.Direction == XFER_WRITE) {
+ /* Copy the data into the buffer we created */
+ if (copy_from_user
+ (buff, iocommand.buf, iocommand.buf_size)) {
+ kfree(buff);
+ return -EFAULT;
+ }
+ } else {
+ memset(buff, 0, iocommand.buf_size);
+ }
+ if ((c = cmd_alloc(host, 0)) == NULL) {
+ kfree(buff);
+ return -ENOMEM;
+ }
+ // Fill in the command type
+ c->cmd_type = CMD_IOCTL_PEND;
+ // Fill in Command Header
+ c->Header.ReplyQueue = 0; // unused in simple mode
+ if (iocommand.buf_size > 0) // buffer to fill
+ {
+ c->Header.SGList = 1;
+ c->Header.SGTotal = 1;
+ } else // no buffers to fill
+ {
+ c->Header.SGList = 0;
+ c->Header.SGTotal = 0;
+ }
+ c->Header.LUN = iocommand.LUN_info;
+ c->Header.Tag.lower = c->busaddr; // use the kernel address the cmd block for tag
- /* Copy the error information out */
- iocommand.error_info = *(c->err_info);
- if ( copy_to_user(argp, &iocommand, sizeof( IOCTL_Command_struct) ) )
- {
- kfree(buff);
- cmd_free(host, c, 0);
- return( -EFAULT);
- }
+ // Fill in Request block
+ c->Request = iocommand.Request;
- if (iocommand.Request.Type.Direction == XFER_READ)
- {
- /* Copy the data out of the buffer we created */
- if (copy_to_user(iocommand.buf, buff, iocommand.buf_size))
- {
- kfree(buff);
+ // Fill in the scatter gather information
+ if (iocommand.buf_size > 0) {
+ temp64.val = pci_map_single(host->pdev, buff,
+ iocommand.buf_size,
+ PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Addr.lower = temp64.val32.lower;
+ c->SG[0].Addr.upper = temp64.val32.upper;
+ c->SG[0].Len = iocommand.buf_size;
+ c->SG[0].Ext = 0; // we are not chaining
+ }
+ c->waiting = &wait;
+
+ /* Put the request on the tail of the request queue */
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+ addQ(&host->reqQ, c);
+ host->Qdepth++;
+ start_io(host);
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+
+ wait_for_completion(&wait);
+
+ /* unlock the buffers from DMA */
+ temp64.val32.lower = c->SG[0].Addr.lower;
+ temp64.val32.upper = c->SG[0].Addr.upper;
+ pci_unmap_single(host->pdev, (dma_addr_t) temp64.val,
+ iocommand.buf_size,
+ PCI_DMA_BIDIRECTIONAL);
+
+ /* Copy the error information out */
+ iocommand.error_info = *(c->err_info);
+ if (copy_to_user
+ (argp, &iocommand, sizeof(IOCTL_Command_struct))) {
+ kfree(buff);
cmd_free(host, c, 0);
return -EFAULT;
}
- }
- kfree(buff);
- cmd_free(host, c, 0);
- return(0);
- }
- case CCISS_BIG_PASSTHRU: {
- BIG_IOCTL_Command_struct *ioc;
- CommandList_struct *c;
- unsigned char **buff = NULL;
- int *buff_size = NULL;
- u64bit temp64;
- unsigned long flags;
- BYTE sg_used = 0;
- int status = 0;
- int i;
- DECLARE_COMPLETION(wait);
- __u32 left;
- __u32 sz;
- BYTE __user *data_ptr;
-
- if (!arg)
- return -EINVAL;
- if (!capable(CAP_SYS_RAWIO))
- return -EPERM;
- ioc = (BIG_IOCTL_Command_struct *)
- kmalloc(sizeof(*ioc), GFP_KERNEL);
- if (!ioc) {
- status = -ENOMEM;
- goto cleanup1;
- }
- if (copy_from_user(ioc, argp, sizeof(*ioc))) {
- status = -EFAULT;
- goto cleanup1;
+
+ if (iocommand.Request.Type.Direction == XFER_READ) {
+ /* Copy the data out of the buffer we created */
+ if (copy_to_user
+ (iocommand.buf, buff, iocommand.buf_size)) {
+ kfree(buff);
+ cmd_free(host, c, 0);
+ return -EFAULT;
+ }
+ }
+ kfree(buff);
+ cmd_free(host, c, 0);
+ return 0;
}
- if ((ioc->buf_size < 1) &&
- (ioc->Request.Type.Direction != XFER_NONE)) {
+ case CCISS_BIG_PASSTHRU:{
+ BIG_IOCTL_Command_struct *ioc;
+ CommandList_struct *c;
+ unsigned char **buff = NULL;
+ int *buff_size = NULL;
+ u64bit temp64;
+ unsigned long flags;
+ BYTE sg_used = 0;
+ int status = 0;
+ int i;
+ DECLARE_COMPLETION(wait);
+ __u32 left;
+ __u32 sz;
+ BYTE __user *data_ptr;
+
+ if (!arg)
+ return -EINVAL;
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ ioc = (BIG_IOCTL_Command_struct *)
+ kmalloc(sizeof(*ioc), GFP_KERNEL);
+ if (!ioc) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ if (copy_from_user(ioc, argp, sizeof(*ioc))) {
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ if ((ioc->buf_size < 1) &&
+ (ioc->Request.Type.Direction != XFER_NONE)) {
status = -EINVAL;
goto cleanup1;
- }
- /* Check kmalloc limits using all SGs */
- if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
- status = -EINVAL;
- goto cleanup1;
- }
- if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
- status = -EINVAL;
- goto cleanup1;
- }
- buff = kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
- if (!buff) {
- status = -ENOMEM;
- goto cleanup1;
- }
- buff_size = (int *) kmalloc(MAXSGENTRIES * sizeof(int),
- GFP_KERNEL);
- if (!buff_size) {
- status = -ENOMEM;
- goto cleanup1;
- }
- left = ioc->buf_size;
- data_ptr = ioc->buf;
- while (left) {
- sz = (left > ioc->malloc_size) ? ioc->malloc_size : left;
- buff_size[sg_used] = sz;
- buff[sg_used] = kmalloc(sz, GFP_KERNEL);
- if (buff[sg_used] == NULL) {
+ }
+ /* Check kmalloc limits using all SGs */
+ if (ioc->malloc_size > MAX_KMALLOC_SIZE) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ if (ioc->buf_size > ioc->malloc_size * MAXSGENTRIES) {
+ status = -EINVAL;
+ goto cleanup1;
+ }
+ buff =
+ kzalloc(MAXSGENTRIES * sizeof(char *), GFP_KERNEL);
+ if (!buff) {
status = -ENOMEM;
goto cleanup1;
}
- if (ioc->Request.Type.Direction == XFER_WRITE) {
- if (copy_from_user(buff[sg_used], data_ptr, sz)) {
+ buff_size = (int *)kmalloc(MAXSGENTRIES * sizeof(int),
+ GFP_KERNEL);
+ if (!buff_size) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ left = ioc->buf_size;
+ data_ptr = ioc->buf;
+ while (left) {
+ sz = (left >
+ ioc->malloc_size) ? ioc->
+ malloc_size : left;
+ buff_size[sg_used] = sz;
+ buff[sg_used] = kmalloc(sz, GFP_KERNEL);
+ if (buff[sg_used] == NULL) {
status = -ENOMEM;
goto cleanup1;
}
+ if (ioc->Request.Type.Direction == XFER_WRITE) {
+ if (copy_from_user
+ (buff[sg_used], data_ptr, sz)) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ } else {
+ memset(buff[sg_used], 0, sz);
+ }
+ left -= sz;
+ data_ptr += sz;
+ sg_used++;
+ }
+ if ((c = cmd_alloc(host, 0)) == NULL) {
+ status = -ENOMEM;
+ goto cleanup1;
+ }
+ c->cmd_type = CMD_IOCTL_PEND;
+ c->Header.ReplyQueue = 0;
+
+ if (ioc->buf_size > 0) {
+ c->Header.SGList = sg_used;
+ c->Header.SGTotal = sg_used;
} else {
- memset(buff[sg_used], 0, sz);
+ c->Header.SGList = 0;
+ c->Header.SGTotal = 0;
}
- left -= sz;
- data_ptr += sz;
- sg_used++;
- }
- if ((c = cmd_alloc(host , 0)) == NULL) {
- status = -ENOMEM;
- goto cleanup1;
- }
- c->cmd_type = CMD_IOCTL_PEND;
- c->Header.ReplyQueue = 0;
-
- if( ioc->buf_size > 0) {
- c->Header.SGList = sg_used;
- c->Header.SGTotal= sg_used;
- } else {
- c->Header.SGList = 0;
- c->Header.SGTotal= 0;
- }
- c->Header.LUN = ioc->LUN_info;
- c->Header.Tag.lower = c->busaddr;
-
- c->Request = ioc->Request;
- if (ioc->buf_size > 0 ) {
- int i;
- for(i=0; i<sg_used; i++) {
- temp64.val = pci_map_single( host->pdev, buff[i],
- buff_size[i],
+ c->Header.LUN = ioc->LUN_info;
+ c->Header.Tag.lower = c->busaddr;
+
+ c->Request = ioc->Request;
+ if (ioc->buf_size > 0) {
+ int i;
+ for (i = 0; i < sg_used; i++) {
+ temp64.val =
+ pci_map_single(host->pdev, buff[i],
+ buff_size[i],
+ PCI_DMA_BIDIRECTIONAL);
+ c->SG[i].Addr.lower =
+ temp64.val32.lower;
+ c->SG[i].Addr.upper =
+ temp64.val32.upper;
+ c->SG[i].Len = buff_size[i];
+ c->SG[i].Ext = 0; /* we are not chaining */
+ }
+ }
+ c->waiting = &wait;
+ /* Put the request on the tail of the request queue */
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+ addQ(&host->reqQ, c);
+ host->Qdepth++;
+ start_io(host);
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ wait_for_completion(&wait);
+ /* unlock the buffers from DMA */
+ for (i = 0; i < sg_used; i++) {
+ temp64.val32.lower = c->SG[i].Addr.lower;
+ temp64.val32.upper = c->SG[i].Addr.upper;
+ pci_unmap_single(host->pdev,
+ (dma_addr_t) temp64.val, buff_size[i],
PCI_DMA_BIDIRECTIONAL);
- c->SG[i].Addr.lower = temp64.val32.lower;
- c->SG[i].Addr.upper = temp64.val32.upper;
- c->SG[i].Len = buff_size[i];
- c->SG[i].Ext = 0; /* we are not chaining */
}
- }
- c->waiting = &wait;
- /* Put the request on the tail of the request queue */
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
- addQ(&host->reqQ, c);
- host->Qdepth++;
- start_io(host);
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- wait_for_completion(&wait);
- /* unlock the buffers from DMA */
- for(i=0; i<sg_used; i++) {
- temp64.val32.lower = c->SG[i].Addr.lower;
- temp64.val32.upper = c->SG[i].Addr.upper;
- pci_unmap_single( host->pdev, (dma_addr_t) temp64.val,
- buff_size[i], PCI_DMA_BIDIRECTIONAL);
- }
- /* Copy the error information out */
- ioc->error_info = *(c->err_info);
- if (copy_to_user(argp, ioc, sizeof(*ioc))) {
- cmd_free(host, c, 0);
- status = -EFAULT;
- goto cleanup1;
- }
- if (ioc->Request.Type.Direction == XFER_READ) {
- /* Copy the data out of the buffer we created */
- BYTE __user *ptr = ioc->buf;
- for(i=0; i< sg_used; i++) {
- if (copy_to_user(ptr, buff[i], buff_size[i])) {
- cmd_free(host, c, 0);
- status = -EFAULT;
- goto cleanup1;
+ /* Copy the error information out */
+ ioc->error_info = *(c->err_info);
+ if (copy_to_user(argp, ioc, sizeof(*ioc))) {
+ cmd_free(host, c, 0);
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ if (ioc->Request.Type.Direction == XFER_READ) {
+ /* Copy the data out of the buffer we created */
+ BYTE __user *ptr = ioc->buf;
+ for (i = 0; i < sg_used; i++) {
+ if (copy_to_user
+ (ptr, buff[i], buff_size[i])) {
+ cmd_free(host, c, 0);
+ status = -EFAULT;
+ goto cleanup1;
+ }
+ ptr += buff_size[i];
}
- ptr += buff_size[i];
}
+ cmd_free(host, c, 0);
+ status = 0;
+ cleanup1:
+ if (buff) {
+ for (i = 0; i < sg_used; i++)
+ kfree(buff[i]);
+ kfree(buff);
+ }
+ kfree(buff_size);
+ kfree(ioc);
+ return status;
}
- cmd_free(host, c, 0);
- status = 0;
-cleanup1:
- if (buff) {
- for(i=0; i<sg_used; i++)
- kfree(buff[i]);
- kfree(buff);
- }
- kfree(buff_size);
- kfree(ioc);
- return(status);
- }
default:
return -ENOTTY;
}
-
}
/*
@@ -1119,7 +1159,7 @@ cleanup1:
*
* Right now I'm using the getgeometry() function to do this, but this
* function should probably be finer grained and allow you to revalidate one
- * particualar logical volume (instead of all of them on a particular
+ * particular logical volume (instead of all of them on a particular
* controller).
*/
static int revalidate_allvol(ctlr_info_t *host)
@@ -1127,17 +1167,17 @@ static int revalidate_allvol(ctlr_info_t *host)
int ctlr = host->ctlr, i;
unsigned long flags;
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
- if (host->usage_count > 1) {
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- printk(KERN_WARNING "cciss: Device busy for volume"
- " revalidation (usage=%d)\n", host->usage_count);
- return -EBUSY;
- }
- host->usage_count++;
+ spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
+ if (host->usage_count > 1) {
+ spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
+ printk(KERN_WARNING "cciss: Device busy for volume"
+ " revalidation (usage=%d)\n", host->usage_count);
+ return -EBUSY;
+ }
+ host->usage_count++;
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- for(i=0; i< NWD; i++) {
+ for (i = 0; i < NWD; i++) {
struct gendisk *disk = host->gendisk[i];
if (disk) {
request_queue_t *q = disk->queue;
@@ -1149,22 +1189,22 @@ static int revalidate_allvol(ctlr_info_t *host)
}
}
- /*
- * Set the partition and block size structures for all volumes
- * on this controller to zero. We will reread all of this data
- */
- memset(host->drv, 0, sizeof(drive_info_struct)
- * CISS_MAX_LUN);
- /*
- * Tell the array controller not to give us any interrupts while
- * we check the new geometry. Then turn interrupts back on when
- * we're done.
- */
- host->access.set_intr_mask(host, CCISS_INTR_OFF);
- cciss_getgeometry(ctlr);
- host->access.set_intr_mask(host, CCISS_INTR_ON);
-
- /* Loop through each real device */
+ /*
+ * Set the partition and block size structures for all volumes
+ * on this controller to zero. We will reread all of this data
+ */
+ memset(host->drv, 0, sizeof(drive_info_struct)
+ * CISS_MAX_LUN);
+ /*
+ * Tell the array controller not to give us any interrupts while
+ * we check the new geometry. Then turn interrupts back on when
+ * we're done.
+ */
+ host->access.set_intr_mask(host, CCISS_INTR_OFF);
+ cciss_getgeometry(ctlr);
+ host->access.set_intr_mask(host, CCISS_INTR_ON);
+
+ /* Loop through each real device */
for (i = 0; i < NWD; i++) {
struct gendisk *disk = host->gendisk[i];
drive_info_struct *drv = &(host->drv[i]);
@@ -1176,8 +1216,8 @@ static int revalidate_allvol(ctlr_info_t *host)
set_capacity(disk, drv->nr_blocks);
add_disk(disk);
}
- host->usage_count--;
- return 0;
+ host->usage_count--;
+ return 0;
}
static inline void complete_buffers(struct bio *bio, int status)
@@ -1191,7 +1231,6 @@ static inline void complete_buffers(struct bio *bio, int status)
bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
bio = xbh;
}
-
}
static void cciss_softirq_done(struct request *rq)
@@ -1209,7 +1248,7 @@ static void cciss_softirq_done(struct request *rq)
/* command did not need to be retried */
/* unmap the DMA mapping for all the scatter gather elements */
- for(i=0; i<cmd->Header.SGList; i++) {
+ for (i = 0; i < cmd->Header.SGList; i++) {
temp64.val32.lower = cmd->SG[i].Addr.lower;
temp64.val32.upper = cmd->SG[i].Addr.upper;
pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
@@ -1219,11 +1258,12 @@ static void cciss_softirq_done(struct request *rq)
#ifdef CCISS_DEBUG
printk("Done with %p\n", rq);
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
+ add_disk_randomness(rq->rq_disk);
spin_lock_irqsave(&h->lock, flags);
end_that_request_last(rq, rq->errors);
- cmd_free(h, cmd,1);
+ cmd_free(h, cmd, 1);
spin_unlock_irqrestore(&h->lock, flags);
}
@@ -1234,9 +1274,9 @@ static void cciss_softirq_done(struct request *rq)
* 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;
@@ -1246,13 +1286,13 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
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){
+ /* 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], 0);
h->drv[drv_index].busy_configuring = 0;
}
@@ -1260,27 +1300,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
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)
+ /* Get information about the disk and modify the driver structure */
+ size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+ if (size_buff == NULL)
goto mem_msg;
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
+ 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);
+ &total_size, &block_size);
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
- inq_buff, &h->drv[drv_index]);
+ 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){
+ if (drv_index) {
disk->queue = blk_init_queue(do_cciss_request, &h->lock);
/* Set up queue information */
@@ -1300,17 +1338,17 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
disk->queue->queuedata = hba[ctlr];
blk_queue_hardsect_size(disk->queue,
- hba[ctlr]->drv[drv_index].block_size);
+ hba[ctlr]->drv[drv_index].block_size);
h->drv[drv_index].queue = disk->queue;
add_disk(disk);
}
-freeret:
+ freeret:
kfree(size_buff);
kfree(inq_buff);
return;
-mem_msg:
+ mem_msg:
printk(KERN_ERR "cciss: out of memory\n");
goto freeret;
}
@@ -1320,13 +1358,13 @@ mem_msg:
* 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){
+ 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;
@@ -1336,7 +1374,7 @@ static int cciss_find_free_drive_index(int ctlr)
}
/* This function will add and remove logical drives from the Logical
- * drive array of the controller and maintain persistancy of ordering
+ * drive array of the controller and maintain persistency 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.
@@ -1344,7 +1382,7 @@ static int cciss_find_free_drive_index(int ctlr)
* 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;
@@ -1361,12 +1399,12 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
/* Set busy_configuring flag for this operation */
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
- if (h->num_luns >= CISS_MAX_LUN){
+ if (h->num_luns >= CISS_MAX_LUN) {
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return -EINVAL;
}
- if (h->busy_configuring){
+ if (h->busy_configuring) {
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return -EBUSY;
}
@@ -1376,7 +1414,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_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){
+ if (del_disk != NULL) {
drv = get_drv(del_disk);
drv->busy_configuring = 1;
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
@@ -1394,61 +1432,67 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
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 */
+ 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");
+ " command failed\n");
listlength = 0;
goto freeret;
}
num_luns = listlength / 8; /* 8 bytes per entry */
- if (num_luns > CISS_MAX_LUN){
+ 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");
+ " 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++){
+ * 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]);
+ 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){
+ */
+ 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){
+ if (!drv_found) {
drv_index = cciss_find_free_drive_index(ctlr);
if (drv_index == -1)
goto freeret;
@@ -1456,18 +1500,18 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
}
h->drv[drv_index].LunID = lunid;
cciss_update_drive_info(ctlr, drv_index);
- } /* end for */
- } /* end else */
+ } /* end for */
+ } /* end else */
-freeret:
+ 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:
+ mem_msg:
printk(KERN_ERR "cciss: out of memory\n");
goto freeret;
}
@@ -1483,7 +1527,7 @@ mem_msg:
* 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 disk in preparation for re-adding it. In this case
* the highest_lun should be left unchanged and the LunID
* should not be cleared.
*/
@@ -1496,19 +1540,17 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
return -EPERM;
/* make sure logical volume is NOT is use */
- if(clear_all || (h->gendisk[0] == disk)) {
- if (drv->usage_count > 1)
- return -EBUSY;
- }
- else
- if( drv->usage_count > 0 )
- return -EBUSY;
+ if (clear_all || (h->gendisk[0] == disk)) {
+ if (drv->usage_count > 1)
+ return -EBUSY;
+ } else if (drv->usage_count > 0)
+ return -EBUSY;
/* 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 (h->gendisk[0] != disk) {
if (disk) {
request_queue_t *q = disk->queue;
if (disk->flags & GENHD_FL_UP)
@@ -1530,91 +1572,90 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
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 (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].heads)
- newhighest = i;
+ newhighest = i;
+ }
+ h->highest_lun = newhighest;
}
- h->highest_lun = newhighest;
- }
- drv->LunID = 0;
+ drv->LunID = 0;
}
- return(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,
- 1: address logical volume log_unit,
- 2: periph device address is scsi3addr */
- unsigned int log_unit, __u8 page_code, unsigned char *scsi3addr,
- int cmd_type)
+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,
+ 1: address logical volume log_unit,
+ 2: periph device address is scsi3addr */
+ unsigned int log_unit, __u8 page_code,
+ unsigned char *scsi3addr, int cmd_type)
{
- ctlr_info_t *h= hba[ctlr];
+ ctlr_info_t *h = hba[ctlr];
u64bit buff_dma_handle;
int status = IO_OK;
c->cmd_type = CMD_IOCTL_PEND;
c->Header.ReplyQueue = 0;
- if( buff != NULL) {
+ if (buff != NULL) {
c->Header.SGList = 1;
- c->Header.SGTotal= 1;
+ c->Header.SGTotal = 1;
} else {
c->Header.SGList = 0;
- c->Header.SGTotal= 0;
+ c->Header.SGTotal = 0;
}
c->Header.Tag.lower = c->busaddr;
c->Request.Type.Type = cmd_type;
if (cmd_type == TYPE_CMD) {
- switch(cmd) {
- case CISS_INQUIRY:
+ switch (cmd) {
+ case CISS_INQUIRY:
/* If the logical unit number is 0 then, this is going
- to controller so It's a physical command
- mode = 0 target = 0. So we have nothing to write.
- otherwise, if use_unit_num == 1,
- mode = 1(volume set addressing) target = LUNID
- otherwise, if use_unit_num == 2,
- mode = 0(periph dev addr) target = scsi3addr */
+ to controller so It's a physical command
+ mode = 0 target = 0. So we have nothing to write.
+ otherwise, if use_unit_num == 1,
+ mode = 1(volume set addressing) target = LUNID
+ otherwise, if use_unit_num == 2,
+ mode = 0(periph dev addr) target = scsi3addr */
if (use_unit_num == 1) {
- c->Header.LUN.LogDev.VolId=
- h->drv[log_unit].LunID;
- c->Header.LUN.LogDev.Mode = 1;
+ c->Header.LUN.LogDev.VolId =
+ h->drv[log_unit].LunID;
+ c->Header.LUN.LogDev.Mode = 1;
} else if (use_unit_num == 2) {
- memcpy(c->Header.LUN.LunAddrBytes,scsi3addr,8);
+ memcpy(c->Header.LUN.LunAddrBytes, scsi3addr,
+ 8);
c->Header.LUN.LogDev.Mode = 0;
}
/* are we trying to read a vital product page */
- if(page_code != 0) {
+ if (page_code != 0) {
c->Request.CDB[1] = 0x01;
c->Request.CDB[2] = page_code;
}
c->Request.CDBLen = 6;
- c->Request.Type.Attribute = ATTR_SIMPLE;
+ c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ;
c->Request.Timeout = 0;
- c->Request.CDB[0] = CISS_INQUIRY;
- c->Request.CDB[4] = size & 0xFF;
- break;
+ c->Request.CDB[0] = CISS_INQUIRY;
+ c->Request.CDB[4] = size & 0xFF;
+ break;
case CISS_REPORT_LOG:
case CISS_REPORT_PHYS:
- /* Talking to controller so It's a physical command
+ /* Talking to controller so It's a physical command
mode = 00 target = 0. Nothing to write.
- */
+ */
c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_READ;
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
- c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB
+ c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB
c->Request.CDB[7] = (size >> 16) & 0xFF;
c->Request.CDB[8] = (size >> 8) & 0xFF;
c->Request.CDB[9] = size & 0xFF;
@@ -1628,7 +1669,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
c->Request.Type.Direction = XFER_READ;
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
- break;
+ break;
case CCISS_CACHE_FLUSH:
c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1636,32 +1677,32 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
c->Request.Timeout = 0;
c->Request.CDB[0] = BMIC_WRITE;
c->Request.CDB[6] = BMIC_CACHE_FLUSH;
- break;
+ break;
default:
printk(KERN_WARNING
- "cciss%d: Unknown Command 0x%c\n", ctlr, cmd);
- return(IO_ERROR);
+ "cciss%d: Unknown Command 0x%c\n", ctlr, cmd);
+ return IO_ERROR;
}
} else if (cmd_type == TYPE_MSG) {
switch (cmd) {
- case 0: /* ABORT message */
+ case 0: /* ABORT message */
c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_WRITE;
c->Request.Timeout = 0;
- c->Request.CDB[0] = cmd; /* abort */
- c->Request.CDB[1] = 0; /* abort a command */
+ c->Request.CDB[0] = cmd; /* abort */
+ c->Request.CDB[1] = 0; /* abort a command */
/* buff contains the tag of the command to abort */
memcpy(&c->Request.CDB[4], buff, 8);
break;
- case 1: /* RESET message */
+ case 1: /* RESET message */
c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction = XFER_WRITE;
c->Request.Timeout = 0;
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
- c->Request.CDB[0] = cmd; /* reset */
- c->Request.CDB[1] = 0x04; /* reset a LUN */
+ c->Request.CDB[0] = cmd; /* reset */
+ c->Request.CDB[1] = 0x04; /* reset a LUN */
case 3: /* No-Op message */
c->Request.CDBLen = 1;
c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1671,168 +1712,164 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
break;
default:
printk(KERN_WARNING
- "cciss%d: unknown message type %d\n",
- ctlr, cmd);
+ "cciss%d: unknown message type %d\n", ctlr, cmd);
return IO_ERROR;
}
} else {
printk(KERN_WARNING
- "cciss%d: unknown command type %d\n", ctlr, cmd_type);
+ "cciss%d: unknown command type %d\n", ctlr, cmd_type);
return IO_ERROR;
}
/* Fill in the scatter gather information */
if (size > 0) {
buff_dma_handle.val = (__u64) pci_map_single(h->pdev,
- buff, size, PCI_DMA_BIDIRECTIONAL);
+ buff, size,
+ PCI_DMA_BIDIRECTIONAL);
c->SG[0].Addr.lower = buff_dma_handle.val32.lower;
c->SG[0].Addr.upper = buff_dma_handle.val32.upper;
c->SG[0].Len = size;
- c->SG[0].Ext = 0; /* we are not chaining */
+ c->SG[0].Ext = 0; /* we are not chaining */
}
return status;
}
-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 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)
{
ctlr_info_t *h = hba[ctlr];
CommandList_struct *c;
- u64bit buff_dma_handle;
+ u64bit buff_dma_handle;
unsigned long flags;
int return_status;
DECLARE_COMPLETION(wait);
-
- if ((c = cmd_alloc(h , 0)) == NULL)
+
+ if ((c = cmd_alloc(h, 0)) == NULL)
return -ENOMEM;
return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
- log_unit, page_code, NULL, cmd_type);
+ log_unit, page_code, NULL, cmd_type);
if (return_status != IO_OK) {
cmd_free(h, c, 0);
return return_status;
}
-resend_cmd2:
+ resend_cmd2:
c->waiting = &wait;
-
+
/* Put the request on the tail of the queue and send it */
spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
addQ(&h->reqQ, c);
h->Qdepth++;
start_io(h);
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-
+
wait_for_completion(&wait);
- if(c->err_info->CommandStatus != 0)
- { /* an error has occurred */
- switch(c->err_info->CommandStatus)
- {
- case CMD_TARGET_STATUS:
- printk(KERN_WARNING "cciss: cmd %p has "
- " completed with errors\n", c);
- if( c->err_info->ScsiStatus)
- {
- printk(KERN_WARNING "cciss: cmd %p "
- "has SCSI Status = %x\n",
- c,
- c->err_info->ScsiStatus);
- }
+ if (c->err_info->CommandStatus != 0) { /* an error has occurred */
+ switch (c->err_info->CommandStatus) {
+ case CMD_TARGET_STATUS:
+ printk(KERN_WARNING "cciss: cmd %p has "
+ " completed with errors\n", c);
+ if (c->err_info->ScsiStatus) {
+ printk(KERN_WARNING "cciss: cmd %p "
+ "has SCSI Status = %x\n",
+ c, c->err_info->ScsiStatus);
+ }
break;
- case CMD_DATA_UNDERRUN:
- case CMD_DATA_OVERRUN:
+ case CMD_DATA_UNDERRUN:
+ case CMD_DATA_OVERRUN:
/* expected for inquire and report lun commands */
break;
- case CMD_INVALID:
- printk(KERN_WARNING "cciss: Cmd %p is "
- "reported invalid\n", c);
- return_status = IO_ERROR;
+ case CMD_INVALID:
+ printk(KERN_WARNING "cciss: Cmd %p is "
+ "reported invalid\n", c);
+ return_status = IO_ERROR;
break;
- case CMD_PROTOCOL_ERR:
- printk(KERN_WARNING "cciss: cmd %p has "
- "protocol error \n", c);
- return_status = IO_ERROR;
- break;
-case CMD_HARDWARE_ERR:
- printk(KERN_WARNING "cciss: cmd %p had "
- " hardware error\n", c);
- return_status = IO_ERROR;
- break;
- case CMD_CONNECTION_LOST:
- printk(KERN_WARNING "cciss: cmd %p had "
- "connection lost\n", c);
- return_status = IO_ERROR;
+ case CMD_PROTOCOL_ERR:
+ printk(KERN_WARNING "cciss: cmd %p has "
+ "protocol error \n", c);
+ return_status = IO_ERROR;
break;
- case CMD_ABORTED:
- printk(KERN_WARNING "cciss: cmd %p was "
- "aborted\n", c);
- return_status = IO_ERROR;
+ case CMD_HARDWARE_ERR:
+ printk(KERN_WARNING "cciss: cmd %p had "
+ " hardware error\n", c);
+ return_status = IO_ERROR;
break;
- case CMD_ABORT_FAILED:
- printk(KERN_WARNING "cciss: cmd %p reports "
- "abort failed\n", c);
- return_status = IO_ERROR;
+ case CMD_CONNECTION_LOST:
+ printk(KERN_WARNING "cciss: cmd %p had "
+ "connection lost\n", c);
+ return_status = IO_ERROR;
break;
- case CMD_UNSOLICITED_ABORT:
- printk(KERN_WARNING
- "cciss%d: unsolicited abort %p\n",
- ctlr, c);
- if (c->retry_count < MAX_CMD_RETRIES) {
- printk(KERN_WARNING
- "cciss%d: retrying %p\n",
- ctlr, c);
- c->retry_count++;
- /* erase the old error information */
- memset(c->err_info, 0,
- sizeof(ErrorInfo_struct));
- return_status = IO_OK;
- INIT_COMPLETION(wait);
- goto resend_cmd2;
- }
- return_status = IO_ERROR;
+ case CMD_ABORTED:
+ printk(KERN_WARNING "cciss: cmd %p was "
+ "aborted\n", c);
+ return_status = IO_ERROR;
+ break;
+ case CMD_ABORT_FAILED:
+ printk(KERN_WARNING "cciss: cmd %p reports "
+ "abort failed\n", c);
+ return_status = IO_ERROR;
break;
- default:
- printk(KERN_WARNING "cciss: cmd %p returned "
- "unknown status %x\n", c,
- c->err_info->CommandStatus);
- return_status = IO_ERROR;
+ case CMD_UNSOLICITED_ABORT:
+ printk(KERN_WARNING
+ "cciss%d: unsolicited abort %p\n", ctlr, c);
+ if (c->retry_count < MAX_CMD_RETRIES) {
+ printk(KERN_WARNING
+ "cciss%d: retrying %p\n", ctlr, c);
+ c->retry_count++;
+ /* erase the old error information */
+ memset(c->err_info, 0,
+ sizeof(ErrorInfo_struct));
+ return_status = IO_OK;
+ INIT_COMPLETION(wait);
+ goto resend_cmd2;
+ }
+ return_status = IO_ERROR;
+ break;
+ default:
+ printk(KERN_WARNING "cciss: cmd %p returned "
+ "unknown status %x\n", c,
+ c->err_info->CommandStatus);
+ return_status = IO_ERROR;
}
- }
+ }
/* 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,
- c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
+ pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val,
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
cmd_free(h, c, 0);
- return(return_status);
-
+ return return_status;
}
+
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)
+ int withirq, unsigned int total_size,
+ unsigned int block_size,
+ InquiryData_struct *inq_buff,
+ drive_info_struct *drv)
{
int return_code;
memset(inq_buff, 0, sizeof(InquiryData_struct));
if (withirq)
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
- inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1, TYPE_CMD);
+ inq_buff, sizeof(*inq_buff), 1,
+ logvol, 0xC1, TYPE_CMD);
else
return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,
- sizeof(*inq_buff), 1, logvol ,0xC1, NULL, TYPE_CMD);
+ sizeof(*inq_buff), 1, logvol, 0xC1, NULL,
+ TYPE_CMD);
if (return_code == IO_OK) {
- if(inq_buff->data_byte[8] == 0xFF) {
+ if (inq_buff->data_byte[8] == 0xFF) {
printk(KERN_WARNING
- "cciss: reading geometry failed, volume "
- "does not support reading geometry\n");
+ "cciss: reading geometry failed, volume "
+ "does not support reading geometry\n");
drv->block_size = block_size;
drv->nr_blocks = total_size;
drv->heads = 255;
- drv->sectors = 32; // Sectors per track
+ drv->sectors = 32; // Sectors per track
drv->cylinders = total_size / 255 / 32;
} else {
unsigned int t;
@@ -1846,37 +1883,42 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
drv->raid_level = inq_buff->data_byte[8];
t = drv->heads * drv->sectors;
if (t > 1) {
- drv->cylinders = total_size/t;
+ drv->cylinders = total_size / t;
}
}
- } else { /* Get geometry failed */
+ } else { /* Get geometry failed */
printk(KERN_WARNING "cciss: reading geometry failed\n");
}
printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n",
- drv->heads, drv->sectors, drv->cylinders);
+ drv->heads, drv->sectors, drv->cylinders);
}
+
static void
cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
- int withirq, unsigned int *total_size, unsigned int *block_size)
+ int withirq, unsigned int *total_size,
+ unsigned int *block_size)
{
int return_code;
memset(buf, 0, sizeof(*buf));
if (withirq)
return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
- ctlr, buf, sizeof(*buf), 1, logvol, 0, TYPE_CMD);
+ ctlr, buf, sizeof(*buf), 1,
+ logvol, 0, TYPE_CMD);
else
return_code = sendcmd(CCISS_READ_CAPACITY,
- ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD);
+ ctlr, buf, sizeof(*buf), 1, logvol, 0,
+ NULL, TYPE_CMD);
if (return_code == IO_OK) {
- *total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1;
- *block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0]));
- } else { /* read capacity command failed */
+ *total_size =
+ be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1;
+ *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0]));
+ } else { /* read capacity command failed */
printk(KERN_WARNING "cciss: read capacity failed\n");
*total_size = 0;
*block_size = BLOCK_SIZE;
}
printk(KERN_INFO " blocks= %u block_size= %d\n",
- *total_size, *block_size);
+ *total_size, *block_size);
return;
}
@@ -1885,38 +1927,38 @@ static int cciss_revalidate(struct gendisk *disk)
ctlr_info_t *h = get_host(disk);
drive_info_struct *drv = get_drv(disk);
int logvol;
- int FOUND=0;
+ int FOUND = 0;
unsigned int block_size;
unsigned int total_size;
ReadCapdata_struct *size_buff = NULL;
InquiryData_struct *inq_buff = NULL;
- for(logvol=0; logvol < CISS_MAX_LUN; logvol++)
- {
- if(h->drv[logvol].LunID == drv->LunID) {
- FOUND=1;
+ for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
+ if (h->drv[logvol].LunID == drv->LunID) {
+ FOUND = 1;
break;
}
}
- if (!FOUND) return 1;
+ if (!FOUND)
+ return 1;
- size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- {
- printk(KERN_WARNING "cciss: out of memory\n");
- return 1;
- }
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
- if (inq_buff == NULL)
- {
- printk(KERN_WARNING "cciss: out of memory\n");
+ size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+ if (size_buff == NULL) {
+ printk(KERN_WARNING "cciss: out of memory\n");
+ return 1;
+ }
+ inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+ if (inq_buff == NULL) {
+ printk(KERN_WARNING "cciss: out of memory\n");
kfree(size_buff);
- return 1;
- }
+ return 1;
+ }
- cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, &block_size);
- cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, inq_buff, drv);
+ cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size,
+ &block_size);
+ cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
+ inq_buff, drv);
blk_queue_hardsect_size(drv->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks);
@@ -1943,7 +1985,7 @@ static unsigned long pollcomplete(int ctlr)
if (done == FIFO_EMPTY)
schedule_timeout_uninterruptible(1);
else
- return (done);
+ return done;
}
/* Invalid address to tell caller we ran out of time */
return 1;
@@ -1952,28 +1994,28 @@ static unsigned long pollcomplete(int ctlr)
static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
{
/* We get in here if sendcmd() is polling for completions
- and gets some command back that it wasn't expecting --
- something other than that which it just sent down.
- Ordinarily, that shouldn't happen, but it can happen when
+ and gets some command back that it wasn't expecting --
+ something other than that which it just sent down.
+ Ordinarily, that shouldn't happen, but it can happen when
the scsi tape stuff gets into error handling mode, and
- starts using sendcmd() to try to abort commands and
+ starts using sendcmd() to try to abort commands and
reset tape drives. In that case, sendcmd may pick up
completions of commands that were sent to logical drives
- through the block i/o system, or cciss ioctls completing, etc.
+ through the block i/o system, or cciss ioctls completing, etc.
In that case, we need to save those completions for later
processing by the interrupt handler.
- */
+ */
#ifdef CONFIG_CISS_SCSI_TAPE
- struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects;
+ struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects;
/* If it's not the scsi tape stuff doing error handling, (abort */
/* or reset) then we don't expect anything weird. */
if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) {
#endif
- printk( KERN_WARNING "cciss cciss%d: SendCmd "
- "Invalid command list address returned! (%lx)\n",
- ctlr, complete);
+ printk(KERN_WARNING "cciss cciss%d: SendCmd "
+ "Invalid command list address returned! (%lx)\n",
+ ctlr, complete);
/* not much we can do. */
#ifdef CONFIG_CISS_SCSI_TAPE
return 1;
@@ -1984,7 +2026,7 @@ static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
if (srl->ncompletions >= (NR_CMDS + 2)) {
/* Uh oh. No room to save it for later... */
printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, "
- "reject list overflow, command lost!\n", ctlr);
+ "reject list overflow, command lost!\n", ctlr);
return 1;
}
/* Save it for later */
@@ -1995,340 +2037,327 @@ static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
}
/*
- * Send a command to the controller, and wait for it to complete.
- * Only used at init time.
+ * Send a command to the controller, and wait for it to complete.
+ * Only used at init time.
*/
-static int sendcmd(
- __u8 cmd,
- int ctlr,
- void *buff,
- size_t size,
- unsigned int use_unit_num, /* 0: address the controller,
- 1: address logical volume log_unit,
- 2: periph device address is scsi3addr */
- unsigned int log_unit,
- __u8 page_code,
- unsigned char *scsi3addr,
- int cmd_type)
+static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller,
+ 1: address logical volume log_unit,
+ 2: periph device address is scsi3addr */
+ unsigned int log_unit,
+ __u8 page_code, unsigned char *scsi3addr, int cmd_type)
{
CommandList_struct *c;
int i;
unsigned long complete;
- ctlr_info_t *info_p= hba[ctlr];
+ ctlr_info_t *info_p = hba[ctlr];
u64bit buff_dma_handle;
int status, done = 0;
if ((c = cmd_alloc(info_p, 1)) == NULL) {
printk(KERN_WARNING "cciss: unable to get memory");
- return(IO_ERROR);
+ return IO_ERROR;
}
status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,
- log_unit, page_code, scsi3addr, cmd_type);
+ log_unit, page_code, scsi3addr, cmd_type);
if (status != IO_OK) {
cmd_free(info_p, c, 1);
return status;
}
-resend_cmd1:
+ resend_cmd1:
/*
- * Disable interrupt
- */
+ * Disable interrupt
+ */
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss: turning intr off\n");
-#endif /* CCISS_DEBUG */
- info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);
-
+#endif /* CCISS_DEBUG */
+ info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);
+
/* Make sure there is room in the command FIFO */
- /* Actually it should be completely empty at this time */
+ /* Actually it should be completely empty at this time */
/* unless we are in here doing error handling for the scsi */
/* tape side of the driver. */
- for (i = 200000; i > 0; i--)
- {
+ for (i = 200000; i > 0; i--) {
/* if fifo isn't full go */
- if (!(info_p->access.fifo_full(info_p)))
- {
-
- break;
- }
- udelay(10);
- printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
- " waiting!\n", ctlr);
- }
- /*
- * Send the cmd
- */
- info_p->access.submit_command(info_p, c);
+ if (!(info_p->access.fifo_full(info_p))) {
+
+ break;
+ }
+ udelay(10);
+ printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"
+ " waiting!\n", ctlr);
+ }
+ /*
+ * Send the cmd
+ */
+ info_p->access.submit_command(info_p, c);
done = 0;
do {
complete = pollcomplete(ctlr);
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "cciss: command completed\n");
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
if (complete == 1) {
- printk( KERN_WARNING
- "cciss cciss%d: SendCmd Timeout out, "
- "No command list address returned!\n",
- ctlr);
+ printk(KERN_WARNING
+ "cciss cciss%d: SendCmd Timeout out, "
+ "No command list address returned!\n", ctlr);
status = IO_ERROR;
done = 1;
break;
}
/* This will need to change for direct lookup completions */
- if ( (complete & CISS_ERROR_BIT)
- && (complete & ~CISS_ERROR_BIT) == c->busaddr)
- {
- /* if data overrun or underun on Report command
- ignore it
- */
+ if ((complete & CISS_ERROR_BIT)
+ && (complete & ~CISS_ERROR_BIT) == c->busaddr) {
+ /* if data overrun or underun on Report command
+ ignore it
+ */
if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||
(c->Request.CDB[0] == CISS_REPORT_PHYS) ||
(c->Request.CDB[0] == CISS_INQUIRY)) &&
- ((c->err_info->CommandStatus ==
- CMD_DATA_OVERRUN) ||
- (c->err_info->CommandStatus ==
- CMD_DATA_UNDERRUN)
- ))
- {
+ ((c->err_info->CommandStatus ==
+ CMD_DATA_OVERRUN) ||
+ (c->err_info->CommandStatus == CMD_DATA_UNDERRUN)
+ )) {
complete = c->busaddr;
} else {
if (c->err_info->CommandStatus ==
- CMD_UNSOLICITED_ABORT) {
+ CMD_UNSOLICITED_ABORT) {
printk(KERN_WARNING "cciss%d: "
- "unsolicited abort %p\n",
- ctlr, c);
+ "unsolicited abort %p\n",
+ ctlr, c);
if (c->retry_count < MAX_CMD_RETRIES) {
printk(KERN_WARNING
- "cciss%d: retrying %p\n",
- ctlr, c);
+ "cciss%d: retrying %p\n",
+ ctlr, c);
c->retry_count++;
/* erase the old error */
/* information */
memset(c->err_info, 0,
- sizeof(ErrorInfo_struct));
+ sizeof
+ (ErrorInfo_struct));
goto resend_cmd1;
} else {
printk(KERN_WARNING
- "cciss%d: retried %p too "
- "many times\n", ctlr, c);
+ "cciss%d: retried %p too "
+ "many times\n", ctlr, c);
status = IO_ERROR;
goto cleanup1;
}
- } else if (c->err_info->CommandStatus == CMD_UNABORTABLE) {
- printk(KERN_WARNING "cciss%d: command could not be aborted.\n", ctlr);
+ } else if (c->err_info->CommandStatus ==
+ CMD_UNABORTABLE) {
+ printk(KERN_WARNING
+ "cciss%d: command could not be aborted.\n",
+ ctlr);
status = IO_ERROR;
goto cleanup1;
}
printk(KERN_WARNING "ciss ciss%d: sendcmd"
- " Error %x \n", ctlr,
- c->err_info->CommandStatus);
+ " Error %x \n", ctlr,
+ c->err_info->CommandStatus);
printk(KERN_WARNING "ciss ciss%d: sendcmd"
- " offensive info\n"
- " size %x\n num %x value %x\n", ctlr,
- c->err_info->MoreErrInfo.Invalid_Cmd.offense_size,
- c->err_info->MoreErrInfo.Invalid_Cmd.offense_num,
- c->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
+ " offensive info\n"
+ " size %x\n num %x value %x\n",
+ ctlr,
+ c->err_info->MoreErrInfo.Invalid_Cmd.
+ offense_size,
+ c->err_info->MoreErrInfo.Invalid_Cmd.
+ offense_num,
+ c->err_info->MoreErrInfo.Invalid_Cmd.
+ offense_value);
status = IO_ERROR;
goto cleanup1;
}
}
/* This will need changing for direct lookup completions */
- if (complete != c->busaddr) {
+ if (complete != c->busaddr) {
if (add_sendcmd_reject(cmd, ctlr, complete) != 0) {
- BUG(); /* we are pretty much hosed if we get here. */
+ BUG(); /* we are pretty much hosed if we get here. */
}
continue;
- } else
+ } else
done = 1;
- } while (!done);
-
-cleanup1:
+ } while (!done);
+
+ 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,
- c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
+ c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);
#ifdef CONFIG_CISS_SCSI_TAPE
/* if we saved some commands for later, process them now. */
if (info_p->scsi_rejects.ncompletions > 0)
do_cciss_intr(0, info_p, NULL);
#endif
cmd_free(info_p, c, 1);
- return (status);
-}
+ return status;
+}
+
/*
* Map (physical) PCI mem into (virtual) kernel space
*/
static void __iomem *remap_pci_mem(ulong base, ulong size)
{
- ulong page_base = ((ulong) base) & PAGE_MASK;
- ulong page_offs = ((ulong) base) - page_base;
- void __iomem *page_remapped = ioremap(page_base, page_offs+size);
+ ulong page_base = ((ulong) base) & PAGE_MASK;
+ ulong page_offs = ((ulong) base) - page_base;
+ void __iomem *page_remapped = ioremap(page_base, page_offs + size);
- return page_remapped ? (page_remapped + page_offs) : NULL;
+ return page_remapped ? (page_remapped + page_offs) : NULL;
}
-/*
- * Takes jobs of the Q and sends them to the hardware, then puts it on
- * the Q to wait for completion.
- */
-static void start_io( ctlr_info_t *h)
+/*
+ * Takes jobs of the Q and sends them to the hardware, then puts it on
+ * the Q to wait for completion.
+ */
+static void start_io(ctlr_info_t *h)
{
CommandList_struct *c;
-
- while(( c = h->reqQ) != NULL )
- {
+
+ while ((c = h->reqQ) != NULL) {
/* can't do anything if fifo is full */
if ((h->access.fifo_full(h))) {
printk(KERN_WARNING "cciss: fifo full\n");
break;
}
- /* Get the first entry from the Request Q */
+ /* Get the first entry from the Request Q */
removeQ(&(h->reqQ), c);
h->Qdepth--;
-
- /* Tell the controller execute command */
+
+ /* Tell the controller execute command */
h->access.submit_command(h, c);
-
- /* Put job onto the completed Q */
- addQ (&(h->cmpQ), c);
+
+ /* Put job onto the completed Q */
+ addQ(&(h->cmpQ), c);
}
}
+
/* Assumes that CCISS_LOCK(h->ctlr) is held. */
/* Zeros out the error record and then resends the command back */
/* to the controller */
-static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
+static inline void resend_cciss_cmd(ctlr_info_t *h, CommandList_struct *c)
{
/* erase the old error information */
memset(c->err_info, 0, sizeof(ErrorInfo_struct));
/* add it to software queue and then send it to the controller */
- addQ(&(h->reqQ),c);
+ addQ(&(h->reqQ), c);
h->Qdepth++;
- if(h->Qdepth > h->maxQsinceinit)
+ if (h->Qdepth > h->maxQsinceinit)
h->maxQsinceinit = h->Qdepth;
start_io(h);
}
-/* checks the status of the job and calls complete buffers to mark all
+/* checks the status of the job and calls complete buffers to mark all
* buffers for the completed job. Note that this function does not need
* to hold the hba/queue lock.
- */
-static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
- int timeout)
+ */
+static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd,
+ int timeout)
{
int status = 1;
int retry_cmd = 0;
-
+
if (timeout)
- status = 0;
+ status = 0;
- if(cmd->err_info->CommandStatus != 0)
- { /* an error has occurred */
- switch(cmd->err_info->CommandStatus)
- {
+ if (cmd->err_info->CommandStatus != 0) { /* an error has occurred */
+ switch (cmd->err_info->CommandStatus) {
unsigned char sense_key;
- case CMD_TARGET_STATUS:
- status = 0;
-
- if( cmd->err_info->ScsiStatus == 0x02)
- {
- printk(KERN_WARNING "cciss: cmd %p "
- "has CHECK CONDITION "
- " byte 2 = 0x%x\n", cmd,
- cmd->err_info->SenseInfo[2]
- );
- /* check the sense key */
- sense_key = 0xf &
- cmd->err_info->SenseInfo[2];
- /* no status or recovered error */
- if((sense_key == 0x0) ||
- (sense_key == 0x1))
- {
- status = 1;
- }
- } else
- {
- printk(KERN_WARNING "cciss: cmd %p "
- "has SCSI Status 0x%x\n",
- cmd, cmd->err_info->ScsiStatus);
+ case CMD_TARGET_STATUS:
+ status = 0;
+
+ if (cmd->err_info->ScsiStatus == 0x02) {
+ printk(KERN_WARNING "cciss: cmd %p "
+ "has CHECK CONDITION "
+ " byte 2 = 0x%x\n", cmd,
+ cmd->err_info->SenseInfo[2]
+ );
+ /* check the sense key */
+ sense_key = 0xf & cmd->err_info->SenseInfo[2];
+ /* no status or recovered error */
+ if ((sense_key == 0x0) || (sense_key == 0x1)) {
+ status = 1;
}
+ } else {
+ printk(KERN_WARNING "cciss: cmd %p "
+ "has SCSI Status 0x%x\n",
+ cmd, cmd->err_info->ScsiStatus);
+ }
break;
- case CMD_DATA_UNDERRUN:
- printk(KERN_WARNING "cciss: cmd %p has"
- " completed with data underrun "
- "reported\n", cmd);
+ case CMD_DATA_UNDERRUN:
+ printk(KERN_WARNING "cciss: cmd %p has"
+ " completed with data underrun "
+ "reported\n", cmd);
break;
- case CMD_DATA_OVERRUN:
- printk(KERN_WARNING "cciss: cmd %p has"
- " completed with data overrun "
- "reported\n", cmd);
+ case CMD_DATA_OVERRUN:
+ printk(KERN_WARNING "cciss: cmd %p has"
+ " completed with data overrun "
+ "reported\n", cmd);
break;
- case CMD_INVALID:
- printk(KERN_WARNING "cciss: cmd %p is "
- "reported invalid\n", cmd);
- status = 0;
+ case CMD_INVALID:
+ printk(KERN_WARNING "cciss: cmd %p is "
+ "reported invalid\n", cmd);
+ status = 0;
break;
- case CMD_PROTOCOL_ERR:
- printk(KERN_WARNING "cciss: cmd %p has "
- "protocol error \n", cmd);
- status = 0;
- break;
- case CMD_HARDWARE_ERR:
- printk(KERN_WARNING "cciss: cmd %p had "
- " hardware error\n", cmd);
- status = 0;
- break;
- case CMD_CONNECTION_LOST:
- printk(KERN_WARNING "cciss: cmd %p had "
- "connection lost\n", cmd);
- status=0;
+ case CMD_PROTOCOL_ERR:
+ printk(KERN_WARNING "cciss: cmd %p has "
+ "protocol error \n", cmd);
+ status = 0;
break;
- case CMD_ABORTED:
- printk(KERN_WARNING "cciss: cmd %p was "
- "aborted\n", cmd);
- status=0;
+ case CMD_HARDWARE_ERR:
+ printk(KERN_WARNING "cciss: cmd %p had "
+ " hardware error\n", cmd);
+ status = 0;
break;
- case CMD_ABORT_FAILED:
- printk(KERN_WARNING "cciss: cmd %p reports "
- "abort failed\n", cmd);
- status=0;
+ case CMD_CONNECTION_LOST:
+ printk(KERN_WARNING "cciss: cmd %p had "
+ "connection lost\n", cmd);
+ status = 0;
break;
- case CMD_UNSOLICITED_ABORT:
- printk(KERN_WARNING "cciss%d: unsolicited "
- "abort %p\n", h->ctlr, cmd);
- if (cmd->retry_count < MAX_CMD_RETRIES) {
- retry_cmd=1;
- printk(KERN_WARNING
- "cciss%d: retrying %p\n",
- h->ctlr, cmd);
- cmd->retry_count++;
- } else
- printk(KERN_WARNING
- "cciss%d: %p retried too "
- "many times\n", h->ctlr, cmd);
- status=0;
+ case CMD_ABORTED:
+ printk(KERN_WARNING "cciss: cmd %p was "
+ "aborted\n", cmd);
+ status = 0;
+ break;
+ case CMD_ABORT_FAILED:
+ printk(KERN_WARNING "cciss: cmd %p reports "
+ "abort failed\n", cmd);
+ status = 0;
+ break;
+ case CMD_UNSOLICITED_ABORT:
+ printk(KERN_WARNING "cciss%d: unsolicited "
+ "abort %p\n", h->ctlr, cmd);
+ if (cmd->retry_count < MAX_CMD_RETRIES) {
+ retry_cmd = 1;
+ printk(KERN_WARNING
+ "cciss%d: retrying %p\n", h->ctlr, cmd);
+ cmd->retry_count++;
+ } else
+ printk(KERN_WARNING
+ "cciss%d: %p retried too "
+ "many times\n", h->ctlr, cmd);
+ status = 0;
break;
- case CMD_TIMEOUT:
- printk(KERN_WARNING "cciss: cmd %p timedout\n",
- cmd);
- status=0;
+ case CMD_TIMEOUT:
+ printk(KERN_WARNING "cciss: cmd %p timedout\n", cmd);
+ status = 0;
break;
- default:
- printk(KERN_WARNING "cciss: cmd %p returned "
- "unknown status %x\n", cmd,
- cmd->err_info->CommandStatus);
- status=0;
+ default:
+ printk(KERN_WARNING "cciss: cmd %p returned "
+ "unknown status %x\n", cmd,
+ cmd->err_info->CommandStatus);
+ status = 0;
}
}
/* We need to return this command */
- if(retry_cmd) {
- resend_cciss_cmd(h,cmd);
+ if (retry_cmd) {
+ resend_cciss_cmd(h, cmd);
return;
- }
+ }
cmd->rq->completion_data = cmd;
cmd->rq->errors = status;
@@ -2336,12 +2365,12 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,
blk_complete_request(cmd->rq);
}
-/*
- * Get a request and submit it to the controller.
+/*
+ * Get a request and submit it to the controller.
*/
static void do_cciss_request(request_queue_t *q)
{
- ctlr_info_t *h= q->queuedata;
+ ctlr_info_t *h = q->queuedata;
CommandList_struct *c;
int start_blk, seg;
struct request *creq;
@@ -2352,18 +2381,18 @@ static void do_cciss_request(request_queue_t *q)
/* We call start_io here in case there is a command waiting on the
* queue that has not been sent.
- */
+ */
if (blk_queue_plugged(q))
goto startio;
-queue:
+ queue:
creq = elv_next_request(q);
if (!creq)
goto startio;
BUG_ON(creq->nr_phys_segments > MAXSGENTRIES);
- if (( c = cmd_alloc(h, 1)) == NULL)
+ if ((c = cmd_alloc(h, 1)) == NULL)
goto full;
blkdev_dequeue_request(creq);
@@ -2372,81 +2401,82 @@ queue:
c->cmd_type = CMD_RWREQ;
c->rq = creq;
-
- /* fill in the request */
+
+ /* fill in the request */
drv = creq->rq_disk->private_data;
- c->Header.ReplyQueue = 0; // unused in simple mode
+ c->Header.ReplyQueue = 0; // unused in simple mode
/* 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.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;
- c->Request.Type.Type = TYPE_CMD; // It is a command.
- c->Request.Type.Attribute = ATTR_SIMPLE;
- c->Request.Type.Direction =
- (rq_data_dir(creq) == READ) ? XFER_READ: XFER_WRITE;
- c->Request.Timeout = 0; // Don't time out
- c->Request.CDB[0] = (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
+ c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
+ c->Request.Type.Type = TYPE_CMD; // It is a command.
+ c->Request.Type.Attribute = ATTR_SIMPLE;
+ c->Request.Type.Direction =
+ (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
+ c->Request.Timeout = 0; // Don't time out
+ c->Request.CDB[0] =
+ (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
start_blk = creq->sector;
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",(int) creq->sector,
- (int) creq->nr_sectors);
-#endif /* CCISS_DEBUG */
+ printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
+ (int)creq->nr_sectors);
+#endif /* CCISS_DEBUG */
seg = blk_rq_map_sg(q, creq, tmp_sg);
- /* get the DMA records for the setup */
+ /* get the DMA records for the setup */
if (c->Request.Type.Direction == XFER_READ)
dir = PCI_DMA_FROMDEVICE;
else
dir = PCI_DMA_TODEVICE;
- for (i=0; i<seg; i++)
- {
+ for (i = 0; i < seg; i++) {
c->SG[i].Len = tmp_sg[i].length;
temp64.val = (__u64) pci_map_page(h->pdev, tmp_sg[i].page,
- tmp_sg[i].offset, tmp_sg[i].length,
- dir);
+ tmp_sg[i].offset,
+ tmp_sg[i].length, dir);
c->SG[i].Addr.lower = temp64.val32.lower;
- c->SG[i].Addr.upper = temp64.val32.upper;
- c->SG[i].Ext = 0; // we are not chaining
+ c->SG[i].Addr.upper = temp64.val32.upper;
+ c->SG[i].Ext = 0; // we are not chaining
}
- /* track how many SG entries we are using */
- if( seg > h->maxSG)
- h->maxSG = seg;
+ /* track how many SG entries we are using */
+ if (seg > h->maxSG)
+ h->maxSG = seg;
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", creq->nr_sectors, seg);
-#endif /* CCISS_DEBUG */
+ printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n",
+ creq->nr_sectors, seg);
+#endif /* CCISS_DEBUG */
c->Header.SGList = c->Header.SGTotal = seg;
- c->Request.CDB[1]= 0;
- c->Request.CDB[2]= (start_blk >> 24) & 0xff; //MSB
- c->Request.CDB[3]= (start_blk >> 16) & 0xff;
- c->Request.CDB[4]= (start_blk >> 8) & 0xff;
- c->Request.CDB[5]= start_blk & 0xff;
- c->Request.CDB[6]= 0; // (sect >> 24) & 0xff; MSB
- c->Request.CDB[7]= (creq->nr_sectors >> 8) & 0xff;
- c->Request.CDB[8]= creq->nr_sectors & 0xff;
+ c->Request.CDB[1] = 0;
+ c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
+ c->Request.CDB[3] = (start_blk >> 16) & 0xff;
+ c->Request.CDB[4] = (start_blk >> 8) & 0xff;
+ c->Request.CDB[5] = start_blk & 0xff;
+ c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
+ c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
+ c->Request.CDB[8] = creq->nr_sectors & 0xff;
c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
spin_lock_irq(q->queue_lock);
- addQ(&(h->reqQ),c);
+ addQ(&(h->reqQ), c);
h->Qdepth++;
- if(h->Qdepth > h->maxQsinceinit)
- h->maxQsinceinit = h->Qdepth;
+ if (h->Qdepth > h->maxQsinceinit)
+ h->maxQsinceinit = h->Qdepth;
goto queue;
-full:
+ full:
blk_stop_queue(q);
-startio:
+ startio:
/* We will already have the driver lock here so not need
* to lock it.
- */
+ */
start_io(h);
}
@@ -2473,7 +2503,7 @@ static inline unsigned long get_next_completion(ctlr_info_t *h)
static inline int interrupt_pending(ctlr_info_t *h)
{
#ifdef CONFIG_CISS_SCSI_TAPE
- return ( h->access.intr_pending(h)
+ return (h->access.intr_pending(h)
|| (h->scsi_rejects.ncompletions > 0));
#else
return h->access.intr_pending(h);
@@ -2483,11 +2513,11 @@ static inline int interrupt_pending(ctlr_info_t *h)
static inline long interrupt_not_for_us(ctlr_info_t *h)
{
#ifdef CONFIG_CISS_SCSI_TAPE
- return (((h->access.intr_pending(h) == 0) ||
- (h->interrupts_enabled == 0))
- && (h->scsi_rejects.ncompletions == 0));
+ return (((h->access.intr_pending(h) == 0) ||
+ (h->interrupts_enabled == 0))
+ && (h->scsi_rejects.ncompletions == 0));
#else
- return (((h->access.intr_pending(h) == 0) ||
+ return (((h->access.intr_pending(h) == 0) ||
(h->interrupts_enabled == 0)));
#endif
}
@@ -2509,12 +2539,14 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
*/
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
while (interrupt_pending(h)) {
- while((a = get_next_completion(h)) != FIFO_EMPTY) {
+ while ((a = get_next_completion(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);
+ printk(KERN_WARNING
+ "cciss: controller cciss%d failed, stopping.\n",
+ h->ctlr);
fail_all_cmds(h->ctlr);
return IRQ_HANDLED;
}
@@ -2523,22 +2555,24 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
a = c->busaddr;
} else {
- a &= ~3;
+ a &= ~3;
if ((c = h->cmpQ) == NULL) {
- printk(KERN_WARNING "cciss: Completion of %08x ignored\n", a1);
- continue;
- }
- while(c->busaddr != a) {
- c = c->next;
- if (c == h->cmpQ)
- break;
- }
+ printk(KERN_WARNING
+ "cciss: Completion of %08x ignored\n",
+ a1);
+ continue;
+ }
+ while (c->busaddr != a) {
+ c = c->next;
+ if (c == h->cmpQ)
+ break;
+ }
}
/*
* If we've found the command, take it off the
* completion Q and free it
*/
- if (c->busaddr == a) {
+ if (c->busaddr == a) {
removeQ(&h->cmpQ, c);
if (c->cmd_type == CMD_RWREQ) {
complete_command(h, c, 0);
@@ -2554,130 +2588,118 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
}
}
- /* check to see if we have maxed out the number of commands that can
- * be placed on the queue. If so then exit. We do this check here
- * in case the interrupt we serviced was from an ioctl and did not
- * free any new commands.
+ /* check to see if we have maxed out the number of commands that can
+ * be placed on the queue. If so then exit. We do this check here
+ * in case the interrupt we serviced was from an ioctl and did not
+ * free any new commands.
+ */
+ if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+ goto cleanup;
+
+ /* We have room on the queue for more commands. Now we need to queue
+ * them up. We will also keep track of the next queue to run so
+ * that every queue gets a chance to be started first.
*/
- if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
- goto cleanup;
-
- /* We have room on the queue for more commands. Now we need to queue
- * them up. We will also keep track of the next queue to run so
- * that every queue gets a chance to be started first.
- */
- for (j=0; j < h->highest_lun + 1; j++){
+ for (j = 0; j < h->highest_lun + 1; j++) {
int curr_queue = (start_queue + j) % (h->highest_lun + 1);
- /* make sure the disk has been added and the drive is real
- * because this can be called from the middle of init_one.
- */
- if(!(h->drv[curr_queue].queue) ||
- !(h->drv[curr_queue].heads))
- continue;
- blk_start_queue(h->gendisk[curr_queue]->queue);
-
- /* check to see if we have maxed out the number of commands
- * that can be placed on the queue.
- */
- if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
- {
- if (curr_queue == start_queue){
- h->next_to_run = (start_queue + 1) % (h->highest_lun + 1);
- goto cleanup;
- } else {
- h->next_to_run = curr_queue;
- goto cleanup;
- }
- } else {
+ /* make sure the disk has been added and the drive is real
+ * because this can be called from the middle of init_one.
+ */
+ if (!(h->drv[curr_queue].queue) || !(h->drv[curr_queue].heads))
+ continue;
+ blk_start_queue(h->gendisk[curr_queue]->queue);
+
+ /* check to see if we have maxed out the number of commands
+ * that can be placed on the queue.
+ */
+ if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) {
+ if (curr_queue == start_queue) {
+ h->next_to_run =
+ (start_queue + 1) % (h->highest_lun + 1);
+ goto cleanup;
+ } else {
+ h->next_to_run = curr_queue;
+ goto cleanup;
+ }
+ } else {
curr_queue = (curr_queue + 1) % (h->highest_lun + 1);
- }
- }
+ }
+ }
-cleanup:
+ cleanup:
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return IRQ_HANDLED;
}
-/*
- * We cannot read the structure directly, for portablity we must use
+
+/*
+ * We cannot read the structure directly, for portability we must use
* the io functions.
- * This is for debug only.
+ * This is for debug only.
*/
#ifdef CCISS_DEBUG
-static void print_cfg_table( CfgTable_struct *tb)
+static void print_cfg_table(CfgTable_struct *tb)
{
int i;
char temp_name[17];
printk("Controller Configuration information\n");
printk("------------------------------------\n");
- for(i=0;i<4;i++)
+ for (i = 0; i < 4; i++)
temp_name[i] = readb(&(tb->Signature[i]));
- temp_name[4]='\0';
- printk(" Signature = %s\n", temp_name);
+ temp_name[4] = '\0';
+ printk(" Signature = %s\n", temp_name);
printk(" Spec Number = %d\n", readl(&(tb->SpecValence)));
- printk(" Transport methods supported = 0x%x\n",
- readl(&(tb-> TransportSupport)));
- printk(" Transport methods active = 0x%x\n",
- readl(&(tb->TransportActive)));
- printk(" Requested transport Method = 0x%x\n",
- readl(&(tb->HostWrite.TransportRequest)));
- printk(" Coalese Interrupt Delay = 0x%x\n",
- readl(&(tb->HostWrite.CoalIntDelay)));
- printk(" Coalese Interrupt Count = 0x%x\n",
- readl(&(tb->HostWrite.CoalIntCount)));
- printk(" Max outstanding commands = 0x%d\n",
- readl(&(tb->CmdsOutMax)));
- printk(" Bus Types = 0x%x\n", readl(&(tb-> BusTypes)));
- for(i=0;i<16;i++)
+ printk(" Transport methods supported = 0x%x\n",
+ readl(&(tb->TransportSupport)));
+ printk(" Transport methods active = 0x%x\n",
+ readl(&(tb->TransportActive)));
+ printk(" Requested transport Method = 0x%x\n",
+ readl(&(tb->HostWrite.TransportRequest)));
+ printk(" Coalesce Interrupt Delay = 0x%x\n",
+ readl(&(tb->HostWrite.CoalIntDelay)));
+ printk(" Coalesce Interrupt Count = 0x%x\n",
+ readl(&(tb->HostWrite.CoalIntCount)));
+ printk(" Max outstanding commands = 0x%d\n",
+ readl(&(tb->CmdsOutMax)));
+ printk(" Bus Types = 0x%x\n", readl(&(tb->BusTypes)));
+ for (i = 0; i < 16; i++)
temp_name[i] = readb(&(tb->ServerName[i]));
temp_name[16] = '\0';
printk(" Server Name = %s\n", temp_name);
- printk(" Heartbeat Counter = 0x%x\n\n\n",
- readl(&(tb->HeartBeat)));
-}
-#endif /* CCISS_DEBUG */
-
-static void release_io_mem(ctlr_info_t *c)
-{
- /* if IO mem was not protected do nothing */
- if( c->io_mem_addr == 0)
- return;
- release_region(c->io_mem_addr, c->io_mem_length);
- c->io_mem_addr = 0;
- c->io_mem_length = 0;
+ printk(" Heartbeat Counter = 0x%x\n\n\n", readl(&(tb->HeartBeat)));
}
+#endif /* CCISS_DEBUG */
-static int find_PCI_BAR_index(struct pci_dev *pdev,
- unsigned long pci_bar_addr)
+static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
{
int i, offset, mem_type, bar_type;
- if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */
+ if (pci_bar_addr == PCI_BASE_ADDRESS_0) /* looking for BAR zero? */
return 0;
offset = 0;
- for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
- bar_type = pci_resource_flags(pdev, i) &
- PCI_BASE_ADDRESS_SPACE;
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ bar_type = pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE;
if (bar_type == PCI_BASE_ADDRESS_SPACE_IO)
offset += 4;
else {
mem_type = pci_resource_flags(pdev, i) &
- PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+ PCI_BASE_ADDRESS_MEM_TYPE_MASK;
switch (mem_type) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- case PCI_BASE_ADDRESS_MEM_TYPE_1M:
- offset += 4; /* 32 bit */
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- offset += 8;
- break;
- default: /* reserved in PCI 2.2 */
- printk(KERN_WARNING "Base address is invalid\n");
- return -1;
+ case PCI_BASE_ADDRESS_MEM_TYPE_32:
+ case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+ offset += 4; /* 32 bit */
+ break;
+ case PCI_BASE_ADDRESS_MEM_TYPE_64:
+ offset += 8;
+ break;
+ default: /* reserved in PCI 2.2 */
+ printk(KERN_WARNING
+ "Base address is invalid\n");
+ return -1;
break;
}
}
- if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0)
- return i+1;
+ if (offset == pci_bar_addr - PCI_BASE_ADDRESS_0)
+ return i + 1;
}
return -1;
}
@@ -2686,53 +2708,54 @@ static int find_PCI_BAR_index(struct pci_dev *pdev,
* controllers that are capable. If not, we use IO-APIC mode.
*/
-static void __devinit cciss_interrupt_mode(ctlr_info_t *c, struct pci_dev *pdev, __u32 board_id)
+static void __devinit cciss_interrupt_mode(ctlr_info_t *c,
+ struct pci_dev *pdev, __u32 board_id)
{
#ifdef CONFIG_PCI_MSI
- int err;
- struct msix_entry cciss_msix_entries[4] = {{0,0}, {0,1},
- {0,2}, {0,3}};
+ int err;
+ struct msix_entry cciss_msix_entries[4] = { {0, 0}, {0, 1},
+ {0, 2}, {0, 3}
+ };
/* Some boards advertise MSI but don't really support it */
if ((board_id == 0x40700E11) ||
- (board_id == 0x40800E11) ||
- (board_id == 0x40820E11) ||
- (board_id == 0x40830E11))
+ (board_id == 0x40800E11) ||
+ (board_id == 0x40820E11) || (board_id == 0x40830E11))
goto default_int_mode;
- if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
- err = pci_enable_msix(pdev, cciss_msix_entries, 4);
- if (!err) {
- c->intr[0] = cciss_msix_entries[0].vector;
- c->intr[1] = cciss_msix_entries[1].vector;
- c->intr[2] = cciss_msix_entries[2].vector;
- c->intr[3] = cciss_msix_entries[3].vector;
- c->msix_vector = 1;
- return;
- }
- if (err > 0) {
- printk(KERN_WARNING "cciss: only %d MSI-X vectors "
- "available\n", err);
- } else {
- printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
- err);
- }
- }
- if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
- if (!pci_enable_msi(pdev)) {
- c->intr[SIMPLE_MODE_INT] = pdev->irq;
- c->msi_vector = 1;
- return;
- } else {
- printk(KERN_WARNING "cciss: MSI init failed\n");
- c->intr[SIMPLE_MODE_INT] = pdev->irq;
- return;
- }
- }
-default_int_mode:
-#endif /* CONFIG_PCI_MSI */
+ if (pci_find_capability(pdev, PCI_CAP_ID_MSIX)) {
+ err = pci_enable_msix(pdev, cciss_msix_entries, 4);
+ if (!err) {
+ c->intr[0] = cciss_msix_entries[0].vector;
+ c->intr[1] = cciss_msix_entries[1].vector;
+ c->intr[2] = cciss_msix_entries[2].vector;
+ c->intr[3] = cciss_msix_entries[3].vector;
+ c->msix_vector = 1;
+ return;
+ }
+ if (err > 0) {
+ printk(KERN_WARNING "cciss: only %d MSI-X vectors "
+ "available\n", err);
+ } else {
+ printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
+ err);
+ }
+ }
+ if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
+ if (!pci_enable_msi(pdev)) {
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ c->msi_vector = 1;
+ return;
+ } else {
+ printk(KERN_WARNING "cciss: MSI init failed\n");
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ return;
+ }
+ }
+ default_int_mode:
+#endif /* CONFIG_PCI_MSI */
/* if we get here we're going to use the default interrupt mode */
- c->intr[SIMPLE_MODE_INT] = pdev->irq;
+ c->intr[SIMPLE_MODE_INT] = pdev->irq;
return;
}
@@ -2743,58 +2766,40 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
__u64 cfg_offset;
__u32 cfg_base_addr;
__u64 cfg_base_addr_index;
- int i;
+ int i, err;
/* check to see if controller has been disabled */
/* BEFORE trying to enable it */
- (void) pci_read_config_word(pdev, PCI_COMMAND,&command);
- if(!(command & 0x02))
- {
- printk(KERN_WARNING "cciss: controller appears to be disabled\n");
- return(-1);
+ (void)pci_read_config_word(pdev, PCI_COMMAND, &command);
+ if (!(command & 0x02)) {
+ printk(KERN_WARNING
+ "cciss: controller appears to be disabled\n");
+ return -ENODEV;
}
- if (pci_enable_device(pdev))
- {
+ err = pci_enable_device(pdev);
+ if (err) {
printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
- return( -1);
+ return err;
+ }
+
+ err = pci_request_regions(pdev, "cciss");
+ if (err) {
+ printk(KERN_ERR "cciss: Cannot obtain PCI resources, "
+ "aborting\n");
+ goto err_out_disable_pdev;
}
subsystem_vendor_id = pdev->subsystem_vendor;
subsystem_device_id = pdev->subsystem_device;
board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) |
- subsystem_vendor_id);
-
- /* search for our IO range so we can protect it */
- for(i=0; i<DEVICE_COUNT_RESOURCE; i++)
- {
- /* is this an IO range */
- if( pci_resource_flags(pdev, i) & 0x01 ) {
- c->io_mem_addr = pci_resource_start(pdev, i);
- c->io_mem_length = pci_resource_end(pdev, i) -
- pci_resource_start(pdev, i) +1;
-#ifdef CCISS_DEBUG
- printk("IO value found base_addr[%d] %lx %lx\n", i,
- c->io_mem_addr, c->io_mem_length);
-#endif /* CCISS_DEBUG */
- /* register the IO range */
- if(!request_region( c->io_mem_addr,
- c->io_mem_length, "cciss"))
- {
- printk(KERN_WARNING "cciss I/O memory range already in use addr=%lx length=%ld\n",
- c->io_mem_addr, c->io_mem_length);
- c->io_mem_addr= 0;
- c->io_mem_length = 0;
- }
- break;
- }
- }
+ subsystem_vendor_id);
#ifdef CCISS_DEBUG
printk("command = %x\n", command);
printk("irq = %x\n", pdev->irq);
printk("board_id = %x\n", board_id);
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
/* If the kernel supports MSI/MSI-X we will try to enable that functionality,
* else we use the IO-APIC interrupt assigned to us by system ROM.
@@ -2803,27 +2808,28 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
/*
* Memory base addr is first addr , the second points to the config
- * table
+ * table
*/
- c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
+ c->paddr = pci_resource_start(pdev, 0); /* addressing mode bits already removed */
#ifdef CCISS_DEBUG
printk("address 0 = %x\n", c->paddr);
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
c->vaddr = remap_pci_mem(c->paddr, 200);
/* Wait for the board to become ready. (PCI hotplug needs this.)
* We poll for up to 120 secs, once per 100ms. */
- for (i=0; i < 1200; i++) {
+ for (i = 0; i < 1200; i++) {
scratchpad = readl(c->vaddr + SA5_SCRATCHPAD_OFFSET);
if (scratchpad == CCISS_FIRMWARE_READY)
break;
set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ / 10); /* wait 100ms */
+ schedule_timeout(HZ / 10); /* wait 100ms */
}
if (scratchpad != CCISS_FIRMWARE_READY) {
printk(KERN_WARNING "cciss: Board not ready. Timed out.\n");
- return -1;
+ err = -ENODEV;
+ goto err_out_free_res;
}
/* get the address index number */
@@ -2831,103 +2837,108 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
cfg_base_addr &= (__u32) 0x0000ffff;
#ifdef CCISS_DEBUG
printk("cfg base address = %x\n", cfg_base_addr);
-#endif /* CCISS_DEBUG */
- cfg_base_addr_index =
- find_PCI_BAR_index(pdev, cfg_base_addr);
+#endif /* CCISS_DEBUG */
+ cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
#ifdef CCISS_DEBUG
printk("cfg base address index = %x\n", cfg_base_addr_index);
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
if (cfg_base_addr_index == -1) {
printk(KERN_WARNING "cciss: Cannot find cfg_base_addr_index\n");
- release_io_mem(c);
- return -1;
+ err = -ENODEV;
+ goto err_out_free_res;
}
cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
#ifdef CCISS_DEBUG
printk("cfg offset = %x\n", cfg_offset);
-#endif /* CCISS_DEBUG */
- c->cfgtable = remap_pci_mem(pci_resource_start(pdev,
- cfg_base_addr_index) + cfg_offset,
- sizeof(CfgTable_struct));
+#endif /* CCISS_DEBUG */
+ c->cfgtable = remap_pci_mem(pci_resource_start(pdev,
+ cfg_base_addr_index) +
+ cfg_offset, sizeof(CfgTable_struct));
c->board_id = board_id;
#ifdef CCISS_DEBUG
print_cfg_table(c->cfgtable);
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
- for(i=0; i<NR_PRODUCTS; i++) {
+ for (i = 0; i < ARRAY_SIZE(products); i++) {
if (board_id == products[i].board_id) {
c->product_name = products[i].product_name;
c->access = *(products[i].access);
break;
}
}
- if (i == NR_PRODUCTS) {
+ if (i == ARRAY_SIZE(products)) {
printk(KERN_WARNING "cciss: Sorry, I don't know how"
- " to access the Smart Array controller %08lx\n",
- (unsigned long)board_id);
- return -1;
- }
- if ( (readb(&c->cfgtable->Signature[0]) != 'C') ||
- (readb(&c->cfgtable->Signature[1]) != 'I') ||
- (readb(&c->cfgtable->Signature[2]) != 'S') ||
- (readb(&c->cfgtable->Signature[3]) != 'S') )
- {
+ " to access the Smart Array controller %08lx\n",
+ (unsigned long)board_id);
+ err = -ENODEV;
+ goto err_out_free_res;
+ }
+ if ((readb(&c->cfgtable->Signature[0]) != 'C') ||
+ (readb(&c->cfgtable->Signature[1]) != 'I') ||
+ (readb(&c->cfgtable->Signature[2]) != 'S') ||
+ (readb(&c->cfgtable->Signature[3]) != 'S')) {
printk("Does not appear to be a valid CISS config table\n");
- return -1;
+ err = -ENODEV;
+ goto err_out_free_res;
}
-
#ifdef CONFIG_X86
-{
- /* Need to enable prefetch in the SCSI core for 6400 in x86 */
- __u32 prefetch;
- prefetch = readl(&(c->cfgtable->SCSI_Prefetch));
- prefetch |= 0x100;
- writel(prefetch, &(c->cfgtable->SCSI_Prefetch));
-}
+ {
+ /* Need to enable prefetch in the SCSI core for 6400 in x86 */
+ __u32 prefetch;
+ prefetch = readl(&(c->cfgtable->SCSI_Prefetch));
+ prefetch |= 0x100;
+ writel(prefetch, &(c->cfgtable->SCSI_Prefetch));
+ }
#endif
#ifdef CCISS_DEBUG
printk("Trying to put board into Simple mode\n");
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */
c->max_commands = readl(&(c->cfgtable->CmdsOutMax));
- /* Update the field, and then ring the doorbell */
- writel( CFGTBL_Trans_Simple,
- &(c->cfgtable->HostWrite.TransportRequest));
- writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);
+ /* Update the field, and then ring the doorbell */
+ writel(CFGTBL_Trans_Simple, &(c->cfgtable->HostWrite.TransportRequest));
+ writel(CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);
/* under certain very rare conditions, this can take awhile.
* (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
* as we enter this code.) */
- for(i=0;i<MAX_CONFIG_WAIT;i++) {
+ for (i = 0; i < MAX_CONFIG_WAIT; i++) {
if (!(readl(c->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
break;
/* delay and try again */
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(10);
- }
+ }
#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "I counter got to %d %x\n", i, readl(c->vaddr + SA5_DOORBELL));
-#endif /* CCISS_DEBUG */
+ printk(KERN_DEBUG "I counter got to %d %x\n", i,
+ readl(c->vaddr + SA5_DOORBELL));
+#endif /* CCISS_DEBUG */
#ifdef CCISS_DEBUG
- print_cfg_table(c->cfgtable);
-#endif /* CCISS_DEBUG */
+ print_cfg_table(c->cfgtable);
+#endif /* CCISS_DEBUG */
- if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple))
- {
+ if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple)) {
printk(KERN_WARNING "cciss: unable to get board into"
- " simple mode\n");
- return -1;
+ " simple mode\n");
+ err = -ENODEV;
+ goto err_out_free_res;
}
return 0;
+ err_out_free_res:
+ pci_release_regions(pdev);
+
+ err_out_disable_pdev:
+ pci_disable_device(pdev);
+ return err;
}
-/*
- * Gets information about the local volumes attached to the controller.
- */
+/*
+ * Gets information about the local volumes attached to the controller.
+ */
static void cciss_getgeometry(int cntl_num)
{
ReportLunData_struct *ld_buff;
@@ -2938,102 +2949,102 @@ static void cciss_getgeometry(int cntl_num)
int listlength = 0;
__u32 lunid = 0;
int block_size;
- int total_size;
+ int total_size;
ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
- if (ld_buff == NULL)
- {
+ if (ld_buff == NULL) {
+ printk(KERN_ERR "cciss: out of memory\n");
+ return;
+ }
+ size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+ if (size_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
+ kfree(ld_buff);
return;
}
- size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- {
- printk(KERN_ERR "cciss: out of memory\n");
+ inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
+ if (inq_buff == NULL) {
+ printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
- return;
- }
- inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
- if (inq_buff == NULL)
- {
- printk(KERN_ERR "cciss: out of memory\n");
- kfree(ld_buff);
kfree(size_buff);
- return;
- }
- /* Get the firmware version */
- return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
- sizeof(InquiryData_struct), 0, 0 ,0, NULL, TYPE_CMD);
- if (return_code == IO_OK)
- {
+ return;
+ }
+ /* Get the firmware version */
+ return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
+ sizeof(InquiryData_struct), 0, 0, 0, NULL,
+ TYPE_CMD);
+ if (return_code == IO_OK) {
hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32];
hba[cntl_num]->firm_ver[1] = inq_buff->data_byte[33];
hba[cntl_num]->firm_ver[2] = inq_buff->data_byte[34];
hba[cntl_num]->firm_ver[3] = inq_buff->data_byte[35];
- } else /* send command failed */
- {
+ } else { /* send command failed */
+
printk(KERN_WARNING "cciss: unable to determine firmware"
- " version of controller\n");
+ " version of controller\n");
}
- /* Get the number of logical volumes */
- return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff,
- sizeof(ReportLunData_struct), 0, 0, 0, NULL, TYPE_CMD);
+ /* Get the number of logical volumes */
+ return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff,
+ sizeof(ReportLunData_struct), 0, 0, 0, NULL,
+ TYPE_CMD);
- if( return_code == IO_OK)
- {
+ if (return_code == IO_OK) {
#ifdef CCISS_DEBUG
printk("LUN Data\n--------------------------\n");
-#endif /* CCISS_DEBUG */
-
- 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;
+#endif /* CCISS_DEBUG */
+
+ 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 */
- {
+ } else { /* reading number of logical volumes failed */
+
printk(KERN_WARNING "cciss: report logical volume"
- " command failed\n");
+ " command failed\n");
listlength = 0;
}
- hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry
- if (hba[cntl_num]->num_luns > CISS_MAX_LUN)
- {
- printk(KERN_ERR "ciss: only %d number of logical volumes supported\n",
- CISS_MAX_LUN);
+ hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry
+ if (hba[cntl_num]->num_luns > CISS_MAX_LUN) {
+ printk(KERN_ERR
+ "ciss: only %d number of logical volumes supported\n",
+ CISS_MAX_LUN);
hba[cntl_num]->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], hba[cntl_num]->num_luns);
-#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 < CISS_MAX_LUN; i++)
- {
- 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;
-
+ 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],
+ hba[cntl_num]->num_luns);
+#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 < CISS_MAX_LUN; i++) {
+ 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;
#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);
-#endif /* CCISS_DEBUG */
- cciss_read_capacity(cntl_num, i, size_buff, 0,
- &total_size, &block_size);
+ 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);
+#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]);
+ 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;
@@ -3042,7 +3053,7 @@ static void cciss_getgeometry(int cntl_num)
kfree(ld_buff);
kfree(size_buff);
kfree(inq_buff);
-}
+}
/* Function to find the first free pointer into our hba[] array */
/* Returns -1 if no free entries are left. */
@@ -3056,7 +3067,7 @@ static int alloc_cciss_hba(void)
goto out;
}
- for(i=0; i< MAX_CTLR; i++) {
+ for (i = 0; i < MAX_CTLR; i++) {
if (!hba[i]) {
ctlr_info_t *p;
p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
@@ -3069,11 +3080,11 @@ static int alloc_cciss_hba(void)
}
}
printk(KERN_WARNING "cciss: This driver supports a maximum"
- " of %d controllers.\n", MAX_CTLR);
+ " of %d controllers.\n", MAX_CTLR);
goto out;
-Enomem:
+ Enomem:
printk(KERN_ERR "cciss: out of memory.\n");
-out:
+ out:
while (n--)
put_disk(disk[n]);
return -1;
@@ -3096,20 +3107,17 @@ static void free_hba(int i)
* returns the number of block devices registered.
*/
static int __devinit cciss_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
request_queue_t *q;
int i;
int j;
int rc;
+ int dac;
- printk(KERN_DEBUG "cciss: Device 0x%x has been found at"
- " bus %d dev %d func %d\n",
- pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
- PCI_FUNC(pdev->devfn));
i = alloc_cciss_hba();
- if(i < 0)
- return (-1);
+ if (i < 0)
+ return -1;
hba[i]->busy_initializing = 1;
@@ -3122,11 +3130,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
/* configure PCI DMA stuff */
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
- printk("cciss: using DAC cycles\n");
+ dac = 1;
else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
- printk("cciss: not using DAC cycles\n");
+ dac = 0;
else {
- printk("cciss: no suitable DMA available\n");
+ printk(KERN_ERR "cciss: no suitable DMA available\n");
goto clean1;
}
@@ -3138,60 +3146,69 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
if (i < MAX_CTLR_ORIG)
hba[i]->major = COMPAQ_CISS_MAJOR + i;
rc = register_blkdev(hba[i]->major, hba[i]->devname);
- if(rc == -EBUSY || rc == -EINVAL) {
+ if (rc == -EBUSY || rc == -EINVAL) {
printk(KERN_ERR
- "cciss: Unable to get major number %d for %s "
- "on hba %d\n", hba[i]->major, hba[i]->devname, i);
+ "cciss: Unable to get major number %d for %s "
+ "on hba %d\n", hba[i]->major, hba[i]->devname, i);
goto clean1;
- }
- else {
+ } else {
if (i >= MAX_CTLR_ORIG)
hba[i]->major = rc;
}
/* make sure the board interrupts are off */
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
- if( request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr,
- SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM,
- hba[i]->devname, hba[i])) {
+ if (request_irq(hba[i]->intr[SIMPLE_MODE_INT], do_cciss_intr,
+ SA_INTERRUPT | SA_SHIRQ, hba[i]->devname, hba[i])) {
printk(KERN_ERR "cciss: Unable to get irq %d for %s\n",
- hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname);
+ hba[i]->intr[SIMPLE_MODE_INT], hba[i]->devname);
goto clean2;
}
- hba[i]->cmd_pool_bits = kmalloc(((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long), GFP_KERNEL);
- hba[i]->cmd_pool = (CommandList_struct *)pci_alloc_consistent(
- hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
- &(hba[i]->cmd_pool_dhandle));
- hba[i]->errinfo_pool = (ErrorInfo_struct *)pci_alloc_consistent(
- hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
- &(hba[i]->errinfo_pool_dhandle));
- if((hba[i]->cmd_pool_bits == NULL)
- || (hba[i]->cmd_pool == NULL)
- || (hba[i]->errinfo_pool == NULL)) {
- printk( KERN_ERR "cciss: out of memory");
+
+ printk(KERN_INFO "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
+ hba[i]->devname, pdev->device, pci_name(pdev),
+ hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not");
+
+ hba[i]->cmd_pool_bits =
+ kmalloc(((NR_CMDS + BITS_PER_LONG -
+ 1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
+ hba[i]->cmd_pool = (CommandList_struct *)
+ pci_alloc_consistent(hba[i]->pdev,
+ NR_CMDS * sizeof(CommandList_struct),
+ &(hba[i]->cmd_pool_dhandle));
+ hba[i]->errinfo_pool = (ErrorInfo_struct *)
+ pci_alloc_consistent(hba[i]->pdev,
+ NR_CMDS * sizeof(ErrorInfo_struct),
+ &(hba[i]->errinfo_pool_dhandle));
+ if ((hba[i]->cmd_pool_bits == NULL)
+ || (hba[i]->cmd_pool == NULL)
+ || (hba[i]->errinfo_pool == NULL)) {
+ printk(KERN_ERR "cciss: out of memory");
goto clean4;
}
#ifdef CONFIG_CISS_SCSI_TAPE
- hba[i]->scsi_rejects.complete =
- kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) *
- (NR_CMDS + 5), GFP_KERNEL);
+ hba[i]->scsi_rejects.complete =
+ kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) *
+ (NR_CMDS + 5), GFP_KERNEL);
if (hba[i]->scsi_rejects.complete == NULL) {
- printk( KERN_ERR "cciss: out of memory");
+ printk(KERN_ERR "cciss: out of memory");
goto clean4;
}
#endif
spin_lock_init(&hba[i]->lock);
- /* Initialize the pdev driver private data.
- have it point to hba[i]. */
+ /* Initialize the pdev driver private data.
+ have it point to hba[i]. */
pci_set_drvdata(pdev, hba[i]);
- /* command and error info recs zeroed out before
- they are used */
- memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+BITS_PER_LONG-1)/BITS_PER_LONG)*sizeof(unsigned long));
+ /* command and error info recs zeroed out before
+ they are used */
+ memset(hba[i]->cmd_pool_bits, 0,
+ ((NR_CMDS + BITS_PER_LONG -
+ 1) / BITS_PER_LONG) * sizeof(unsigned long));
-#ifdef CCISS_DEBUG
- printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);
-#endif /* CCISS_DEBUG */
+#ifdef CCISS_DEBUG
+ printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n", i);
+#endif /* CCISS_DEBUG */
cciss_getgeometry(i);
@@ -3203,15 +3220,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
cciss_procinit(i);
hba[i]->busy_initializing = 0;
- for(j=0; j < NWD; j++) { /* mfm */
+ for (j = 0; j < NWD; j++) { /* mfm */
drive_info_struct *drv = &(hba[i]->drv[j]);
struct gendisk *disk = hba[i]->gendisk[j];
q = blk_init_queue(do_cciss_request, &hba[i]->lock);
if (!q) {
printk(KERN_ERR
- "cciss: unable to allocate queue for disk %d\n",
- j);
+ "cciss: unable to allocate queue for disk %d\n",
+ j);
break;
}
drv->queue = q;
@@ -3240,92 +3257,87 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
disk->driverfs_dev = &pdev->dev;
/* we must register the controller even if no disks exist */
/* this is for the online array utilities */
- if(!drv->heads && j)
+ if (!drv->heads && j)
continue;
blk_queue_hardsect_size(q, drv->block_size);
set_capacity(disk, drv->nr_blocks);
add_disk(disk);
}
- return(1);
+ return 1;
-clean4:
+ clean4:
#ifdef CONFIG_CISS_SCSI_TAPE
kfree(hba[i]->scsi_rejects.complete);
#endif
kfree(hba[i]->cmd_pool_bits);
- if(hba[i]->cmd_pool)
+ if (hba[i]->cmd_pool)
pci_free_consistent(hba[i]->pdev,
- NR_CMDS * sizeof(CommandList_struct),
- hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
- if(hba[i]->errinfo_pool)
+ NR_CMDS * sizeof(CommandList_struct),
+ hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
+ if (hba[i]->errinfo_pool)
pci_free_consistent(hba[i]->pdev,
- NR_CMDS * sizeof( ErrorInfo_struct),
- hba[i]->errinfo_pool,
- hba[i]->errinfo_pool_dhandle);
+ NR_CMDS * sizeof(ErrorInfo_struct),
+ hba[i]->errinfo_pool,
+ hba[i]->errinfo_pool_dhandle);
free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]);
-clean2:
+ clean2:
unregister_blkdev(hba[i]->major, hba[i]->devname);
-clean1:
- release_io_mem(hba[i]);
+ clean1:
hba[i]->busy_initializing = 0;
free_hba(i);
- return(-1);
+ return -1;
}
-static void __devexit cciss_remove_one (struct pci_dev *pdev)
+static void __devexit cciss_remove_one(struct pci_dev *pdev)
{
ctlr_info_t *tmp_ptr;
int i, j;
char flush_buf[4];
- int return_code;
+ int return_code;
- if (pci_get_drvdata(pdev) == NULL)
- {
- printk( KERN_ERR "cciss: Unable to remove device \n");
+ if (pci_get_drvdata(pdev) == NULL) {
+ printk(KERN_ERR "cciss: Unable to remove device \n");
return;
}
tmp_ptr = pci_get_drvdata(pdev);
i = tmp_ptr->ctlr;
- if (hba[i] == NULL)
- {
+ if (hba[i] == NULL) {
printk(KERN_ERR "cciss: device appears to "
- "already be removed \n");
+ "already be removed \n");
return;
}
/* Turn board interrupts off and send the flush cache command */
/* sendcmd will turn off interrupt, and send the flush...
- * To write all data in the battery backed cache to disks */
+ * To write all data in the battery backed cache to disks */
memset(flush_buf, 0, 4);
return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL,
- TYPE_CMD);
- if(return_code != IO_OK)
- {
- printk(KERN_WARNING "Error Flushing cache on controller %d\n",
- i);
+ TYPE_CMD);
+ if (return_code != IO_OK) {
+ printk(KERN_WARNING "Error Flushing cache on controller %d\n",
+ i);
}
free_irq(hba[i]->intr[2], hba[i]);
#ifdef CONFIG_PCI_MSI
- if (hba[i]->msix_vector)
- pci_disable_msix(hba[i]->pdev);
- else if (hba[i]->msi_vector)
- pci_disable_msi(hba[i]->pdev);
-#endif /* CONFIG_PCI_MSI */
+ if (hba[i]->msix_vector)
+ pci_disable_msix(hba[i]->pdev);
+ else if (hba[i]->msi_vector)
+ pci_disable_msi(hba[i]->pdev);
+#endif /* CONFIG_PCI_MSI */
- pci_set_drvdata(pdev, NULL);
iounmap(hba[i]->vaddr);
- cciss_unregister_scsi(i); /* unhook from SCSI subsystem */
+ cciss_unregister_scsi(i); /* unhook from SCSI subsystem */
unregister_blkdev(hba[i]->major, hba[i]->devname);
- remove_proc_entry(hba[i]->devname, proc_cciss);
-
+ remove_proc_entry(hba[i]->devname, proc_cciss);
+
/* remove it from the disk list */
for (j = 0; j < NWD; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
if (disk) {
request_queue_t *q = disk->queue;
- if (disk->flags & GENHD_FL_UP)
+ if (disk->flags & GENHD_FL_UP)
del_gendisk(disk);
if (q)
blk_cleanup_queue(q);
@@ -3334,26 +3346,28 @@ static void __devexit cciss_remove_one (struct pci_dev *pdev)
pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
- pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
- hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
+ pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(ErrorInfo_struct),
+ hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
kfree(hba[i]->cmd_pool_bits);
#ifdef CONFIG_CISS_SCSI_TAPE
kfree(hba[i]->scsi_rejects.complete);
#endif
- release_io_mem(hba[i]);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
free_hba(i);
-}
+}
static struct pci_driver cciss_pci_driver = {
- .name = "cciss",
- .probe = cciss_init_one,
- .remove = __devexit_p(cciss_remove_one),
- .id_table = cciss_pci_device_id, /* id_table */
+ .name = "cciss",
+ .probe = cciss_init_one,
+ .remove = __devexit_p(cciss_remove_one),
+ .id_table = cciss_pci_device_id, /* id_table */
};
/*
* This is it. Register the PCI driver information for the cards we control
- * the OS will call our registered routines when it finds one of our cards.
+ * the OS will call our registered routines when it finds one of our cards.
*/
static int __init cciss_init(void)
{
@@ -3369,12 +3383,10 @@ static void __exit cciss_cleanup(void)
pci_unregister_driver(&cciss_pci_driver);
/* double check that all controller entrys have been removed */
- for (i=0; i< MAX_CTLR; i++)
- {
- if (hba[i] != NULL)
- {
+ for (i = 0; i < MAX_CTLR; i++) {
+ if (hba[i] != NULL) {
printk(KERN_WARNING "cciss: had to remove"
- " controller %d\n", i);
+ " controller %d\n", i);
cciss_remove_one(hba[i]->pdev);
}
}
@@ -3389,21 +3401,21 @@ static void fail_all_cmds(unsigned long ctlr)
unsigned long flags;
printk(KERN_WARNING "cciss%d: controller not responding.\n", h->ctlr);
- h->alive = 0; /* the controller apparently died... */
+ 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. */
+ 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 ) {
+ while ((c = h->reqQ) != NULL) {
removeQ(&(h->reqQ), c);
h->Qdepth--;
- addQ (&(h->cmpQ), c);
+ addQ(&(h->cmpQ), c);
}
/* Now, fail everything on the completed queue with a HW error */
- while( (c = h->cmpQ) != NULL ) {
+ while ((c = h->cmpQ) != NULL) {
removeQ(&h->cmpQ, c);
c->err_info->CommandStatus = CMD_HARDWARE_ERR;
if (c->cmd_type == CMD_RWREQ) {
@@ -3411,8 +3423,8 @@ static void fail_all_cmds(unsigned long ctlr)
} 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);
+ else if (c->cmd_type == CMD_SCSI)
+ complete_scsi_command(c, 0, 0);
#endif
}
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index b24fc05..868e0d8 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -60,8 +60,6 @@ struct ctlr_info
__u32 board_id;
void __iomem *vaddr;
unsigned long paddr;
- unsigned long io_mem_addr;
- unsigned long io_mem_length;
CfgTable_struct __iomem *cfgtable;
int interrupts_enabled;
int major;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index b6ea2f0..5eb6fb7 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -392,7 +392,7 @@ static void __devexit cpqarray_remove_one_eisa (int i)
}
/* pdev is NULL for eisa */
-static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
+static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev)
{
request_queue_t *q;
int j;
@@ -410,8 +410,7 @@ static int cpqarray_register_ctlr( int i, struct pci_dev *pdev)
}
hba[i]->access.set_intr_mask(hba[i], 0);
if (request_irq(hba[i]->intr, do_ida_intr,
- SA_INTERRUPT|SA_SHIRQ|SA_SAMPLE_RANDOM,
- hba[i]->devname, hba[i]))
+ SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))
{
printk(KERN_ERR "cpqarray: Unable to get irq %d for %s\n",
hba[i]->intr, hba[i]->devname);
@@ -745,7 +744,7 @@ __setup("smart2=", cpqarray_setup);
/*
* Find an EISA controller's signature. Set up an hba if we find it.
*/
-static int cpqarray_eisa_detect(void)
+static int __init cpqarray_eisa_detect(void)
{
int i=0, j;
__u32 board_id;
@@ -1036,6 +1035,8 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
complete_buffers(cmd->rq->bio, ok);
+ add_disk_randomness(cmd->rq->rq_disk);
+
DBGPX(printk("Done with %p\n", cmd->rq););
end_that_request_last(cmd->rq, ok ? 1 : -EIO);
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 3c74ea7..9dc294a 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -74,6 +74,7 @@
#include <linux/completion.h>
#include <linux/highmem.h>
#include <linux/gfp.h>
+#include <linux/kthread.h>
#include <asm/uaccess.h>
@@ -578,8 +579,6 @@ static int loop_thread(void *data)
struct loop_device *lo = data;
struct bio *bio;
- daemonize("loop%d", lo->lo_number);
-
/*
* loop can be used in an encrypted device,
* hence, it mustn't be stopped at all
@@ -592,11 +591,6 @@ static int loop_thread(void *data)
lo->lo_state = Lo_bound;
lo->lo_pending = 1;
- /*
- * complete it, we are running
- */
- complete(&lo->lo_done);
-
for (;;) {
int pending;
@@ -629,7 +623,6 @@ static int loop_thread(void *data)
break;
}
- complete(&lo->lo_done);
return 0;
}
@@ -746,6 +739,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
unsigned lo_blocksize;
int lo_flags = 0;
int error;
+ struct task_struct *tsk;
loff_t size;
/* This is safe, since we have a reference from open(). */
@@ -839,10 +833,11 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
set_blocksize(bdev, lo_blocksize);
- error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
- if (error < 0)
+ tsk = kthread_run(loop_thread, lo, "loop%d", lo->lo_number);
+ if (IS_ERR(tsk)) {
+ error = PTR_ERR(tsk);
goto out_putf;
- wait_for_completion(&lo->lo_done);
+ }
return 0;
out_putf:
@@ -898,6 +893,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
if (lo->lo_state != Lo_bound)
return -ENXIO;
+ if (!lo->lo_thread)
+ return -EINVAL;
+
if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */
return -EBUSY;
@@ -911,7 +909,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
- wait_for_completion(&lo->lo_done);
+ kthread_stop(lo->lo_thread);
lo->lo_backing_file = NULL;
@@ -924,6 +922,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
lo->lo_sizelimit = 0;
lo->lo_encrypt_key_size = 0;
lo->lo_flags = 0;
+ lo->lo_thread = NULL;
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
@@ -1288,7 +1287,6 @@ static int __init loop_init(void)
if (!lo->lo_queue)
goto out_mem4;
mutex_init(&lo->lo_ctl_mutex);
- init_completion(&lo->lo_done);
init_completion(&lo->lo_bh_done);
lo->lo_number = i;
spin_lock_init(&lo->lo_lock);
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 8bca490..7f554f2 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -7,39 +7,9 @@
* Copyright 1997-2000 Pavel Machek <pavel@ucw.cz>
* Parts copyright 2001 Steven Whitehouse <steve@chygwyn.com>
*
- * (part of code stolen from loop.c)
+ * This file is released under GPLv2 or later.
*
- * 97-3-25 compiled 0-th version, not yet tested it
- * (it did not work, BTW) (later that day) HEY! it works!
- * (bit later) hmm, not that much... 2:00am next day:
- * yes, it works, but it gives something like 50kB/sec
- * 97-4-01 complete rewrite to make it possible for many requests at
- * once to be processed
- * 97-4-11 Making protocol independent of endianity etc.
- * 97-9-13 Cosmetic changes
- * 98-5-13 Attempt to make 64-bit-clean on 64-bit machines
- * 99-1-11 Attempt to make 64-bit-clean on 32-bit machines <ankry@mif.pg.gda.pl>
- * 01-2-27 Fix to store proper blockcount for kernel (calculated using
- * BLOCK_SIZE_BITS, not device blocksize) <aga@permonline.ru>
- * 01-3-11 Make nbd work with new Linux block layer code. It now supports
- * plugging like all the other block devices. Also added in MSG_MORE to
- * reduce number of partial TCP segments sent. <steve@chygwyn.com>
- * 01-12-6 Fix deadlock condition by making queue locks independent of
- * the transmit lock. <steve@chygwyn.com>
- * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes.
- * <Paul.Clements@SteelEye.com> <James.Bottomley@SteelEye.com>
- * 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes
- * memory corruption from module removal and possible memory corruption
- * from sending/receiving disk data. <ldl@aros.net>
- * 03-06-23 Cosmetic changes. <ldl@aros.net>
- * 03-06-23 Enhance diagnostics support. <ldl@aros.net>
- * 03-06-24 Remove unneeded blksize_bits field from nbd_device struct.
- * <ldl@aros.net>
- * 03-06-24 Cleanup PARANOIA usage & code. <ldl@aros.net>
- * 04-02-19 Remove PARANOIA, plus various cleanups (Paul Clements)
- * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall
- * why not: would need access_ok and friends, would share yet another
- * structure with userland
+ * (part of code stolen from loop.c)
*/
#include <linux/major.h>
diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
index a0b580c..0f6e7aa 100644
--- a/drivers/cdrom/mcdx.c
+++ b/drivers/cdrom/mcdx.c
@@ -1006,7 +1006,7 @@ static int mcdx_talk(struct s_drive_stuff *stuffp,
/* MODULE STUFF ***********************************************************/
-int __mcdx_init(void)
+static int __init __mcdx_init(void)
{
int i;
int drives = 0;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 78d928f..63f28d1 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -865,6 +865,7 @@ config SONYPI
config TANBAC_TB0219
tristate "TANBAC TB0219 base board support"
depends TANBAC_TB022X
+ select GPIO_VR41XX
menu "Ftape, the floppy tape device driver"
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index a370e7a..9275d5e 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -166,11 +166,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc,
return boardno + 1;
}
-#ifdef MODULE
-
-#define applicom_init init_module
-
-void cleanup_module(void)
+static void __exit applicom_exit(void)
{
unsigned int i;
@@ -188,9 +184,7 @@ void cleanup_module(void)
}
}
-#endif /* MODULE */
-
-int __init applicom_init(void)
+static int __init applicom_init(void)
{
int i, numisa = 0;
struct pci_dev *dev = NULL;
@@ -355,10 +349,9 @@ out:
return ret;
}
+module_init(applicom_init);
+module_exit(applicom_exit);
-#ifndef MODULE
-__initcall(applicom_init);
-#endif
static ssize_t ac_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{
@@ -851,28 +844,3 @@ static int ac_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
return 0;
}
-#ifndef MODULE
-static int __init applicom_setup(char *str)
-{
- int ints[4];
-
- (void) get_options(str, 4, ints);
-
- if (ints[0] > 2) {
- printk(KERN_WARNING "Too many arguments to 'applicom=', expected mem,irq only.\n");
- }
-
- if (ints[0] < 2) {
- printk(KERN_INFO"applicom numargs: %d\n", ints[0]);
- return 0;
- }
-
- mem = ints[1];
- irq = ints[2];
- return 1;
-}
-
-__setup("applicom=", applicom_setup);
-
-#endif /* MODULE */
-
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index cc7acf8..122e7a7 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2833,9 +2833,8 @@ cy_write(struct tty_struct * tty, const unsigned char *buf, int count)
return 0;
}
- if (!tty || !info->xmit_buf || !tmp_buf){
- return 0;
- }
+ if (!info->xmit_buf || !tmp_buf)
+ return 0;
CY_LOCK(info, flags);
while (1) {
@@ -2884,7 +2883,7 @@ cy_put_char(struct tty_struct *tty, unsigned char ch)
if (serial_paranoia_check(info, tty->name, "cy_put_char"))
return;
- if (!tty || !info->xmit_buf)
+ if (!info->xmit_buf)
return;
CY_LOCK(info, flags);
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 09dc4b0..922174d 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1212,7 +1212,7 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
if (serial_paranoia_check(info, tty->name, "rs_put_char"))
return;
- if (!tty || !info->xmit_buf)
+ if (!info->xmit_buf)
return;
spin_lock_irqsave(&info->lock, flags);
@@ -1256,7 +1256,7 @@ static int rs_write(struct tty_struct * tty,
if (serial_paranoia_check(info, tty->name, "rs_write"))
return 0;
- if (!tty || !info->xmit_buf)
+ if (!info->xmit_buf)
return 0;
while (1) {
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 03db1cb..9ab33c3 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -305,7 +305,7 @@ static struct class *ip2_class;
// Some functions to keep track of what irq's we have
-static int __init
+static int
is_valid_irq(int irq)
{
int *i = Valid_Irqs;
@@ -316,14 +316,14 @@ is_valid_irq(int irq)
return (*i);
}
-static void __init
+static void
mark_requested_irq( char irq )
{
rirqs[iindx++] = irq;
}
#ifdef MODULE
-static int __init
+static int
clear_requested_irq( char irq )
{
int i;
@@ -337,7 +337,7 @@ clear_requested_irq( char irq )
}
#endif
-static int __init
+static int
have_requested_irq( char irq )
{
// array init to zeros so 0 irq will not be requested as a side effect
@@ -818,7 +818,7 @@ EXPORT_SYMBOL(ip2_loadmain);
/* the board, the channel structures are initialized, and the board details */
/* are reported on the console. */
/******************************************************************************/
-static void __init
+static void
ip2_init_board( int boardnum )
{
int i;
@@ -961,7 +961,7 @@ err_initialize:
/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
/* it returns the base address of the controller. */
/******************************************************************************/
-static unsigned short __init
+static unsigned short
find_eisa_board( int start_slot )
{
int i, j;
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index e9ebaba..efaaa19 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1145,7 +1145,7 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
if (isicom_paranoia_check(port, tty->name, "isicom_write"))
return 0;
- if (!tty || !port->xmit_buf)
+ if (!port->xmit_buf)
return 0;
spin_lock_irqsave(&card->card_lock, flags);
@@ -1180,7 +1180,7 @@ static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
return;
- if (!tty || !port->xmit_buf)
+ if (!port->xmit_buf)
return;
spin_lock_irqsave(&card->card_lock, flags);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 5755b7e..edd996f 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -39,6 +39,7 @@
#include <linux/vt_kern.h>
#include <linux/sysrq.h>
#include <linux/input.h>
+#include <linux/reboot.h>
static void kbd_disconnect(struct input_handle *handle);
extern void ctrl_alt_del(void);
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index 1b05fa6..d65b310 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -329,7 +329,6 @@ static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma)
if (PAGE_SIZE > (1 << 16))
return -ENOSYS;
- vma->vm_flags |= (VM_IO | VM_SHM | VM_LOCKED );
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
mmtimer_addr = __pa(RTC_COUNTER_ADDR);
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 0fb2fb9..645d9d7 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -9,7 +9,7 @@
* 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.
+ * (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -71,8 +71,8 @@
#define MXSERMAJOR 174
#define MXSERCUMAJOR 175
-#define MXSER_EVENT_TXLOW 1
-#define MXSER_EVENT_HANGUP 2
+#define MXSER_EVENT_TXLOW 1
+#define MXSER_EVENT_HANGUP 2
#define MXSER_BOARDS 4 /* Max. boards */
#define MXSER_PORTS 32 /* Max. ports */
@@ -92,7 +92,8 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|IXON|IXOFF))
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
+ IXON|IXOFF))
#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
@@ -152,27 +153,27 @@ static char *mxser_brdname[] = {
};
static int mxser_numports[] = {
- 8, // C168-ISA
- 4, // C104-ISA
- 4, // CI104J
- 8, // C168-PCI
- 4, // C104-PCI
- 2, // C102-ISA
- 2, // CI132
- 4, // CI134
- 2, // CP132
- 4, // CP114
- 4, // CT114
- 2, // CP102
- 4, // CP104U
- 8, // CP168U
- 2, // CP132U
- 4, // CP134U
- 4, // CP104JU
- 8, // RC7000
- 8, // CP118U
- 2, // CP102UL
- 2, // CP102U
+ 8, /* C168-ISA */
+ 4, /* C104-ISA */
+ 4, /* CI104J */
+ 8, /* C168-PCI */
+ 4, /* C104-PCI */
+ 2, /* C102-ISA */
+ 2, /* CI132 */
+ 4, /* CI134 */
+ 2, /* CP132 */
+ 4, /* CP114 */
+ 4, /* CT114 */
+ 2, /* CP102 */
+ 4, /* CP104U */
+ 8, /* CP168U */
+ 2, /* CP132U */
+ 4, /* CP134U */
+ 4, /* CP104JU */
+ 8, /* RC7000 */
+ 8, /* CP118U */
+ 2, /* CP102UL */
+ 2, /* CP102U */
};
#define UART_TYPE_NUM 2
@@ -182,7 +183,7 @@ static const unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = {
MOXA_MUST_MU860_HWID
};
-// This is only for PCI
+/* This is only for PCI */
#define UART_INFO_NUM 3
struct mxpciuart_info {
int type;
@@ -231,7 +232,7 @@ MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
typedef struct _moxa_pci_info {
unsigned short busNum;
unsigned short devNum;
- struct pci_dev *pdev; // add by Victor Yu. 06-23-2003
+ struct pci_dev *pdev; /* add by Victor Yu. 06-23-2003 */
} moxa_pci_info;
static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 };
@@ -280,6 +281,7 @@ struct mxser_mon_ext {
int fifo[32];
int iftype[32];
};
+
struct mxser_hwconf {
int board_type;
int ports;
@@ -290,9 +292,9 @@ struct mxser_hwconf {
int ioaddr[MXSER_PORTS_PER_BOARD];
int baud_base[MXSER_PORTS_PER_BOARD];
moxa_pci_info pciInfo;
- int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002
- int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 09-04-2002
- int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; // add by Victor Yu. 01-05-2004
+ int IsMoxaMustChipFlag; /* add by Victor Yu. 08-30-2002 */
+ int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; /* add by Victor Yu. 09-04-2002 */
+ int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; /* add by Victor Yu. 01-05-2004 */
};
struct mxser_struct {
@@ -334,9 +336,9 @@ struct mxser_struct {
wait_queue_head_t delta_msr_wait;
struct async_icount icount; /* kernel counters for the 4 input interrupts */
int timeout;
- int IsMoxaMustChipFlag; // add by Victor Yu. 08-30-2002
- int MaxCanSetBaudRate; // add by Victor Yu. 09-04-2002
- int opmode_ioaddr; // add by Victor Yu. 01-05-2004
+ int IsMoxaMustChipFlag; /* add by Victor Yu. 08-30-2002 */
+ int MaxCanSetBaudRate; /* add by Victor Yu. 09-04-2002 */
+ int opmode_ioaddr; /* add by Victor Yu. 01-05-2004 */
unsigned char stop_rx;
unsigned char ldisc_stop_rx;
long realbaud;
@@ -345,7 +347,6 @@ struct mxser_struct {
spinlock_t slock;
};
-
struct mxser_mstatus {
tcflag_t cflag;
int cts;
@@ -358,7 +359,7 @@ static struct mxser_mstatus GMStatus[MXSER_PORTS];
static int mxserBoardCAP[MXSER_BOARDS] = {
0, 0, 0, 0
- /* 0x180, 0x280, 0x200, 0x320 */
+ /* 0x180, 0x280, 0x200, 0x320 */
};
static struct tty_driver *mxvar_sdriver;
@@ -386,7 +387,7 @@ static struct mxser_hwconf mxsercfg[MXSER_BOARDS];
static void mxser_getcfg(int board, struct mxser_hwconf *hwconf);
static int mxser_init(void);
-//static void mxser_poll(unsigned long);
+/* static void mxser_poll(unsigned long); */
static int mxser_get_ISA_conf(int, struct mxser_hwconf *);
static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *);
static void mxser_do_softint(void *);
@@ -440,18 +441,18 @@ static int CheckIsMoxaMust(int io)
SET_MOXA_MUST_XON1_VALUE(io, 0x11);
if ((hwid = inb(io + UART_MCR)) != 0) {
outb(oldmcr, io + UART_MCR);
- return (MOXA_OTHER_UART);
+ return MOXA_OTHER_UART;
}
GET_MOXA_MUST_HARDWARE_ID(io, &hwid);
for (i = 0; i < UART_TYPE_NUM; i++) {
if (hwid == Gmoxa_uart_id[i])
- return (int) hwid;
+ return (int)hwid;
}
return MOXA_OTHER_UART;
}
-// above is modified by Victor Yu. 08-15-2002
+/* above is modified by Victor Yu. 08-15-2002 */
static struct tty_operations mxser_ops = {
.open = mxser_open,
@@ -504,7 +505,6 @@ static void __exit mxser_module_exit(void)
else
printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n");
-
for (i = 0; i < MXSER_BOARDS; i++) {
struct pci_dev *pdev;
@@ -513,7 +513,7 @@ static void __exit mxser_module_exit(void)
else {
pdev = mxsercfg[i].pciInfo.pdev;
free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
- if (pdev != NULL) { //PCI
+ if (pdev != NULL) { /* PCI */
release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));
release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
} else {
@@ -524,7 +524,6 @@ static void __exit mxser_module_exit(void)
}
if (verbose)
printk(KERN_DEBUG "Done.\n");
-
}
static void process_txrx_fifo(struct mxser_struct *info)
@@ -558,8 +557,10 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
n = board * MXSER_PORTS_PER_BOARD;
info = &mxvar_table[n];
/*if (verbose) */ {
- printk(KERN_DEBUG " ttyM%d - ttyM%d ", n, n + hwconf->ports - 1);
- printk(" max. baud rate = %d bps.\n", hwconf->MaxCanSetBaudRate[0]);
+ printk(KERN_DEBUG " ttyM%d - ttyM%d ",
+ n, n + hwconf->ports - 1);
+ printk(" max. baud rate = %d bps.\n",
+ hwconf->MaxCanSetBaudRate[0]);
}
for (i = 0; i < hwconf->ports; i++, n++, info++) {
@@ -568,12 +569,12 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
info->irq = hwconf->irq;
info->vector = hwconf->vector;
info->vectormask = hwconf->vector_mask;
- info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; // add by Victor Yu. 01-05-2004
+ info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; /* add by Victor Yu. 01-05-2004 */
info->stop_rx = 0;
info->ldisc_stop_rx = 0;
info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag;
- //Enhance mode enabled here
+ /* Enhance mode enabled here */
if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base);
}
@@ -606,22 +607,25 @@ static int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
/* before set INT ISR, disable all int */
for (i = 0; i < hwconf->ports; i++) {
- outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0, hwconf->ioaddr[i] + UART_IER);
+ outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0,
+ hwconf->ioaddr[i] + UART_IER);
}
n = board * MXSER_PORTS_PER_BOARD;
info = &mxvar_table[n];
- retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info), "mxser", info);
+ retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),
+ "mxser", info);
if (retval) {
- printk(KERN_ERR "Board %d: %s", board, mxser_brdname[hwconf->board_type - 1]);
- printk(" Request irq fail,IRQ (%d) may be conflit with another device.\n", info->irq);
+ printk(KERN_ERR "Board %d: %s",
+ board, mxser_brdname[hwconf->board_type - 1]);
+ printk(" Request irq failed, IRQ (%d) may conflict with"
+ " another device.\n", info->irq);
return retval;
}
return 0;
}
-
static void mxser_getcfg(int board, struct mxser_hwconf *hwconf)
{
mxsercfg[board] = *hwconf;
@@ -631,26 +635,27 @@ static void mxser_getcfg(int board, struct mxser_hwconf *hwconf)
static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxser_hwconf *hwconf)
{
int i, j;
-// unsigned int val;
+ /* unsigned int val; */
unsigned int ioaddress;
struct pci_dev *pdev = hwconf->pciInfo.pdev;
- //io address
+ /* io address */
hwconf->board_type = board_type;
hwconf->ports = mxser_numports[board_type - 1];
ioaddress = pci_resource_start(pdev, 2);
- request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2), "mxser(IO)");
+ request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2),
+ "mxser(IO)");
- for (i = 0; i < hwconf->ports; i++) {
+ for (i = 0; i < hwconf->ports; i++)
hwconf->ioaddr[i] = ioaddress + 8 * i;
- }
- //vector
+ /* vector */
ioaddress = pci_resource_start(pdev, 3);
- request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3), "mxser(vector)");
+ request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3),
+ "mxser(vector)");
hwconf->vector = ioaddress;
- //irq
+ /* irq */
hwconf->irq = hwconf->pciInfo.pdev->irq;
hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]);
@@ -663,7 +668,7 @@ static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxs
if (Gpci_uart_info[j].type == hwconf->IsMoxaMustChipFlag) {
hwconf->MaxCanSetBaudRate[i] = Gpci_uart_info[j].max_baud;
- //exception....CP-102
+ /* exception....CP-102 */
if (board_type == MXSER_BOARD_CP102)
hwconf->MaxCanSetBaudRate[i] = 921600;
break;
@@ -678,15 +683,15 @@ static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxs
else
hwconf->opmode_ioaddr[i] = ioaddress + 0x0c;
}
- outb(0, ioaddress + 4); // default set to RS232 mode
- outb(0, ioaddress + 0x0c); //default set to RS232 mode
+ outb(0, ioaddress + 4); /* default set to RS232 mode */
+ outb(0, ioaddress + 0x0c); /* default set to RS232 mode */
}
for (i = 0; i < hwconf->ports; i++) {
hwconf->vector_mask |= (1 << i);
hwconf->baud_base[i] = 921600;
}
- return (0);
+ return 0;
}
#endif
@@ -707,7 +712,8 @@ static int mxser_init(void)
mxsercfg[i].board_type = -1;
}
- printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", MXSER_VERSION);
+ printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
+ MXSER_VERSION);
/* Initialize the tty_driver structure */
memset(mxvar_sdriver, 0, sizeof(struct tty_driver));
@@ -719,7 +725,7 @@ static int mxser_init(void)
mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
mxvar_sdriver->init_termios = tty_std_termios;
- mxvar_sdriver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(mxvar_sdriver, &mxser_ops);
mxvar_sdriver->ttys = mxvar_tty;
@@ -739,23 +745,29 @@ static int mxser_init(void)
/* Start finding ISA boards here */
for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
int cap;
+
if (!(cap = mxserBoardCAP[b]))
continue;
retval = mxser_get_ISA_conf(cap, &hwconf);
if (retval != 0)
- printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
+ printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n",
+ mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
if (retval <= 0) {
if (retval == MXSER_ERR_IRQ)
- printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+ printk(KERN_ERR "Invalid interrupt number, "
+ "board not configured\n");
else if (retval == MXSER_ERR_IRQ_CONFLIT)
- printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+ printk(KERN_ERR "Invalid interrupt number, "
+ "board not configured\n");
else if (retval == MXSER_ERR_VECTOR)
- printk(KERN_ERR "Invalid interrupt vector,board not configured\n");
+ printk(KERN_ERR "Invalid interrupt vector, "
+ "board not configured\n");
else if (retval == MXSER_ERR_IOADDR)
- printk(KERN_ERR "Invalid I/O address,board not configured\n");
+ printk(KERN_ERR "Invalid I/O address, "
+ "board not configured\n");
continue;
}
@@ -765,35 +777,43 @@ static int mxser_init(void)
hwconf.pciInfo.pdev = NULL;
mxser_getcfg(m, &hwconf);
- //init mxsercfg first, or mxsercfg data is not correct on ISR.
- //mxser_initbrd will hook ISR.
+ /*
+ * init mxsercfg first,
+ * or mxsercfg data is not correct on ISR.
+ */
+ /* mxser_initbrd will hook ISR. */
if (mxser_initbrd(m, &hwconf) < 0)
continue;
-
m++;
}
/* Start finding ISA boards from module arg */
for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
int cap;
+
if (!(cap = ioaddr[b]))
continue;
retval = mxser_get_ISA_conf(cap, &hwconf);
if (retval != 0)
- printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
+ printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n",
+ mxser_brdname[hwconf.board_type - 1], ioaddr[b]);
if (retval <= 0) {
if (retval == MXSER_ERR_IRQ)
- printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+ printk(KERN_ERR "Invalid interrupt number, "
+ "board not configured\n");
else if (retval == MXSER_ERR_IRQ_CONFLIT)
- printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+ printk(KERN_ERR "Invalid interrupt number, "
+ "board not configured\n");
else if (retval == MXSER_ERR_VECTOR)
- printk(KERN_ERR "Invalid interrupt vector,board not configured\n");
+ printk(KERN_ERR "Invalid interrupt vector, "
+ "board not configured\n");
else if (retval == MXSER_ERR_IOADDR)
- printk(KERN_ERR "Invalid I/O address,board not configured\n");
+ printk(KERN_ERR "Invalid I/O address, "
+ "board not configured\n");
continue;
}
@@ -803,8 +823,11 @@ static int mxser_init(void)
hwconf.pciInfo.pdev = NULL;
mxser_getcfg(m, &hwconf);
- //init mxsercfg first, or mxsercfg data is not correct on ISR.
- //mxser_initbrd will hook ISR.
+ /*
+ * init mxsercfg first,
+ * or mxsercfg data is not correct on ISR.
+ */
+ /* mxser_initbrd will hook ISR. */
if (mxser_initbrd(m, &hwconf) < 0)
continue;
@@ -817,7 +840,8 @@ static int mxser_init(void)
index = 0;
b = 0;
while (b < n) {
- pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev);
+ pdev = pci_find_device(mxser_pcibrds[b].vendor,
+ mxser_pcibrds[b].device, pdev);
if (pdev == NULL) {
b++;
continue;
@@ -825,30 +849,48 @@ static int mxser_init(void)
hwconf.pciInfo.busNum = busnum = pdev->bus->number;
hwconf.pciInfo.devNum = devnum = PCI_SLOT(pdev->devfn) << 3;
hwconf.pciInfo.pdev = pdev;
- printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n", mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1], busnum, devnum >> 3);
+ printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
+ mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1],
+ busnum, devnum >> 3);
index++;
- if (m >= MXSER_BOARDS) {
- printk(KERN_ERR "Too many Smartio/Industio family boards find (maximum %d),board not configured\n", MXSER_BOARDS);
- } else {
+ if (m >= MXSER_BOARDS)
+ printk(KERN_ERR
+ "Too many Smartio/Industio family boards find "
+ "(maximum %d), board not configured\n",
+ MXSER_BOARDS);
+ else {
if (pci_enable_device(pdev)) {
- printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n");
+ printk(KERN_ERR "Moxa SmartI/O PCI enable "
+ "fail !\n");
continue;
}
- retval = mxser_get_PCI_conf(busnum, devnum, (int) mxser_pcibrds[b].driver_data, &hwconf);
+ retval = mxser_get_PCI_conf(busnum, devnum,
+ (int)mxser_pcibrds[b].driver_data,
+ &hwconf);
if (retval < 0) {
if (retval == MXSER_ERR_IRQ)
- printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+ printk(KERN_ERR
+ "Invalid interrupt number, "
+ "board not configured\n");
else if (retval == MXSER_ERR_IRQ_CONFLIT)
- printk(KERN_ERR "Invalid interrupt number,board not configured\n");
+ printk(KERN_ERR
+ "Invalid interrupt number, "
+ "board not configured\n");
else if (retval == MXSER_ERR_VECTOR)
- printk(KERN_ERR "Invalid interrupt vector,board not configured\n");
+ printk(KERN_ERR
+ "Invalid interrupt vector, "
+ "board not configured\n");
else if (retval == MXSER_ERR_IOADDR)
- printk(KERN_ERR "Invalid I/O address,board not configured\n");
+ printk(KERN_ERR
+ "Invalid I/O address, "
+ "board not configured\n");
continue;
}
mxser_getcfg(m, &hwconf);
- //init mxsercfg first, or mxsercfg data is not correct on ISR.
- //mxser_initbrd will hook ISR.
+ /* init mxsercfg first,
+ * or mxsercfg data is not correct on ISR.
+ */
+ /* mxser_initbrd will hook ISR. */
if (mxser_initbrd(m, &hwconf) < 0)
continue;
m++;
@@ -858,7 +900,8 @@ static int mxser_init(void)
retval = tty_register_driver(mxvar_sdriver);
if (retval) {
- printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family driver !\n");
+ printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family"
+ " driver !\n");
put_tty_driver(mxvar_sdriver);
for (i = 0; i < MXSER_BOARDS; i++) {
@@ -866,7 +909,7 @@ static int mxser_init(void)
continue;
else {
free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
- //todo: release io, vector
+ /* todo: release io, vector */
}
}
return retval;
@@ -877,7 +920,7 @@ static int mxser_init(void)
static void mxser_do_softint(void *private_)
{
- struct mxser_struct *info = (struct mxser_struct *) private_;
+ struct mxser_struct *info = private_;
struct tty_struct *tty;
tty = info->tty;
@@ -926,7 +969,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
return -ENODEV;
info = mxvar_table + line;
if (!info->base)
- return (-ENODEV);
+ return -ENODEV;
tty->driver_data = info;
info->tty = tty;
@@ -935,11 +978,11 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
*/
retval = mxser_startup(info);
if (retval)
- return (retval);
+ return retval;
retval = mxser_block_til_ready(tty, filp, info);
if (retval)
- return (retval);
+ return retval;
info->count++;
@@ -955,11 +998,12 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
info->pgrp = process_group(current);
clear_bit(TTY_DONT_FLIP, &tty->flags);
- //status = mxser_get_msr(info->base, 0, info->port);
- //mxser_check_modem_status(info, status);
+ /*
+ status = mxser_get_msr(info->base, 0, info->port);
+ mxser_check_modem_status(info, status);
+ */
-/* unmark here for very high baud rate (ex. 921600 bps) used
-*/
+/* unmark here for very high baud rate (ex. 921600 bps) used */
tty->low_latency = 1;
return 0;
}
@@ -972,7 +1016,7 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
*/
static void mxser_close(struct tty_struct *tty, struct file *filp)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long timeout;
unsigned long flags;
@@ -997,11 +1041,13 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
* one, we've got real problems, since it means the
* serial port won't be shutdown.
*/
- printk(KERN_ERR "mxser_close: bad serial port count; tty->count is 1, " "info->count is %d\n", info->count);
+ printk(KERN_ERR "mxser_close: bad serial port count; "
+ "tty->count is 1, info->count is %d\n", info->count);
info->count = 1;
}
if (--info->count < 0) {
- printk(KERN_ERR "mxser_close: bad serial port count for ttys%d: %d\n", info->port, info->count);
+ printk(KERN_ERR "mxser_close: bad serial port count for "
+ "ttys%d: %d\n", info->port, info->count);
info->count = 0;
}
if (info->count) {
@@ -1056,7 +1102,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
ld = tty_ldisc_ref(tty);
if (ld) {
- if(ld->flush_buffer)
+ if (ld->flush_buffer)
ld->flush_buffer(tty);
tty_ldisc_deref(ld);
}
@@ -1078,31 +1124,34 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
{
int c, total = 0;
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
- if (!tty || !info->xmit_buf)
- return (0);
+ if (!info->xmit_buf)
+ return 0;
while (1) {
- c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head));
+ c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
if (c <= 0)
break;
memcpy(info->xmit_buf + info->xmit_head, buf, c);
spin_lock_irqsave(&info->slock, flags);
- info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+ info->xmit_head = (info->xmit_head + c) &
+ (SERIAL_XMIT_SIZE - 1);
info->xmit_cnt += c;
spin_unlock_irqrestore(&info->slock, flags);
buf += c;
count -= c;
total += c;
-
}
if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) {
- if (!tty->hw_stopped || (info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) {
+ if (!tty->hw_stopped ||
+ (info->type == PORT_16550A) ||
+ (info->IsMoxaMustChipFlag)) {
spin_lock_irqsave(&info->slock, flags);
info->IER |= UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
@@ -1114,10 +1163,10 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou
static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
- if (!tty || !info->xmit_buf)
+ if (!info->xmit_buf)
return;
if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
@@ -1129,7 +1178,9 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
info->xmit_cnt++;
spin_unlock_irqrestore(&info->slock, flags);
if (!tty->stopped && !(info->IER & UART_IER_THRI)) {
- if (!tty->hw_stopped || (info->type == PORT_16550A) || info->IsMoxaMustChipFlag) {
+ if (!tty->hw_stopped ||
+ (info->type == PORT_16550A) ||
+ info->IsMoxaMustChipFlag) {
spin_lock_irqsave(&info->slock, flags);
info->IER |= UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
@@ -1141,10 +1192,16 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
static void mxser_flush_chars(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
- if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf || (tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)))
+ if (info->xmit_cnt <= 0 ||
+ tty->stopped ||
+ !info->xmit_buf ||
+ (tty->hw_stopped &&
+ (info->type != PORT_16550A) &&
+ (!info->IsMoxaMustChipFlag)
+ ))
return;
spin_lock_irqsave(&info->slock, flags);
@@ -1157,24 +1214,24 @@ static void mxser_flush_chars(struct tty_struct *tty)
static int mxser_write_room(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
int ret;
ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
if (ret < 0)
ret = 0;
- return (ret);
+ return ret;
}
static int mxser_chars_in_buffer(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
return info->xmit_cnt;
}
static void mxser_flush_buffer(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
char fcr;
unsigned long flags;
@@ -1184,7 +1241,8 @@ static void mxser_flush_buffer(struct tty_struct *tty)
/* below added by shinhay */
fcr = inb(info->base + UART_FCR);
- outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
+ outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+ info->base + UART_FCR);
outb(fcr, info->base + UART_FCR);
spin_unlock_irqrestore(&info->slock, flags);
@@ -1197,7 +1255,7 @@ static void mxser_flush_buffer(struct tty_struct *tty)
static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
int retval;
struct async_icount cprev, cnow; /* kernel counter temps */
struct serial_icounter_struct __user *p_cuser;
@@ -1206,9 +1264,9 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
void __user *argp = (void __user *)arg;
if (tty->index == MXSER_PORTS)
- return (mxser_ioctl_special(cmd, argp));
+ return mxser_ioctl_special(cmd, argp);
- // following add by Victor Yu. 01-05-2004
+ /* following add by Victor Yu. 01-05-2004 */
if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
int opmode, p;
static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
@@ -1219,7 +1277,10 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
if (cmd == MOXA_SET_OP_MODE) {
if (get_user(opmode, (int __user *) argp))
return -EFAULT;
- if (opmode != RS232_MODE && opmode != RS485_2WIRE_MODE && opmode != RS422_MODE && opmode != RS485_4WIRE_MODE)
+ if (opmode != RS232_MODE &&
+ opmode != RS485_2WIRE_MODE &&
+ opmode != RS422_MODE &&
+ opmode != RS485_4WIRE_MODE)
return -EFAULT;
mask = ModeMask[p];
shiftbit = p * 2;
@@ -1236,36 +1297,36 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
}
return 0;
}
- // above add by Victor Yu. 01-05-2004
+ /* above add by Victor Yu. 01-05-2004 */
if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
- return (-EIO);
+ return -EIO;
}
switch (cmd) {
case TCSBRK: /* SVID version: non-zero arg --> no break */
retval = tty_check_change(tty);
if (retval)
- return (retval);
+ return retval;
tty_wait_until_sent(tty, 0);
if (!arg)
mxser_send_break(info, HZ / 4); /* 1/4 second */
- return (0);
+ return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
retval = tty_check_change(tty);
if (retval)
- return (retval);
+ return retval;
tty_wait_until_sent(tty, 0);
mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
- return (0);
+ return 0;
case TIOCGSOFTCAR:
- return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
+ return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
case TIOCSSOFTCAR:
if (get_user(templ, (unsigned long __user *) argp))
return -EFAULT;
arg = templ;
tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
- return (0);
+ return 0;
case TIOCGSERIAL:
return mxser_get_serial_info(info, argp);
case TIOCSSERIAL:
@@ -1278,7 +1339,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
* (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
* Caller should use TIOCGICOUNT to see which one it was
*/
- case TIOCMIWAIT:{
+ case TIOCMIWAIT: {
DECLARE_WAITQUEUE(wait, current);
int ret;
spin_lock_irqsave(&info->slock, flags);
@@ -1292,7 +1353,14 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
spin_unlock_irqrestore(&info->slock, flags);
set_current_state(TASK_INTERRUPTIBLE);
- if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+ if (((arg & TIOCM_RNG) &&
+ (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) &&
+ (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) &&
+ (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) &&
+ (cnow.cts != cprev.cts))) {
ret = 0;
break;
}
@@ -1338,21 +1406,18 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
put_user(cnow.dsr, &p_cuser->dsr);
put_user(cnow.rng, &p_cuser->rng);
put_user(cnow.dcd, &p_cuser->dcd);
-
-/* */
return 0;
case MOXA_HighSpeedOn:
- return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *) argp);
-
- case MOXA_SDS_RSTICOUNTER:{
+ return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
+ case MOXA_SDS_RSTICOUNTER: {
info->mon_data.rxcnt = 0;
info->mon_data.txcnt = 0;
return 0;
}
-// (above) added by James.
+/* (above) added by James. */
case MOXA_ASPP_SETBAUD:{
long baud;
- if (get_user(baud, (long __user *) argp))
+ if (get_user(baud, (long __user *)argp))
return -EFAULT;
mxser_set_baud(info, baud);
return 0;
@@ -1377,9 +1442,10 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
return 0;
}
- case MOXA_ASPP_MON:{
+ case MOXA_ASPP_MON: {
int mcr, status;
-// info->mon_data.ser_param = tty->termios->c_cflag;
+
+ /* info->mon_data.ser_param = tty->termios->c_cflag; */
status = mxser_get_msr(info->base, 1, info->port, info);
mxser_check_modem_status(info, status);
@@ -1400,25 +1466,25 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c
else
info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
-
- if (copy_to_user(argp, &info->mon_data, sizeof(struct mxser_mon)))
+ if (copy_to_user(argp, &info->mon_data,
+ sizeof(struct mxser_mon)))
return -EFAULT;
return 0;
-
}
- case MOXA_ASPP_LSTATUS:{
- if (copy_to_user(argp, &info->err_shadow, sizeof(unsigned char)))
+ case MOXA_ASPP_LSTATUS: {
+ if (copy_to_user(argp, &info->err_shadow,
+ sizeof(unsigned char)))
return -EFAULT;
info->err_shadow = 0;
return 0;
-
}
- case MOXA_SET_BAUD_METHOD:{
+ case MOXA_SET_BAUD_METHOD: {
int method;
- if (get_user(method, (int __user *) argp))
+
+ if (get_user(method, (int __user *)argp))
return -EFAULT;
mxser_set_baud_method[info->port] = method;
if (copy_to_user(argp, &method, sizeof(int)))
@@ -1442,7 +1508,8 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
switch (cmd) {
case MOXA_GET_CONF:
- if (copy_to_user(argp, mxsercfg, sizeof(struct mxser_hwconf) * 4))
+ if (copy_to_user(argp, mxsercfg,
+ sizeof(struct mxser_hwconf) * 4))
return -EFAULT;
return 0;
case MOXA_GET_MAJOR:
@@ -1461,11 +1528,11 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
if (mxvar_table[i].base)
result |= (1 << i);
}
- return put_user(result, (unsigned long __user *) argp);
+ return put_user(result, (unsigned long __user *)argp);
case MOXA_GETDATACOUNT:
if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
return -EFAULT;
- return (0);
+ return 0;
case MOXA_GETMSTATUS:
for (i = 0; i < MXSER_PORTS; i++) {
GMStatus[i].ri = 0;
@@ -1498,22 +1565,26 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
else
GMStatus[i].cts = 0;
}
- if (copy_to_user(argp, GMStatus, sizeof(struct mxser_mstatus) * MXSER_PORTS))
+ if (copy_to_user(argp, GMStatus,
+ sizeof(struct mxser_mstatus) * MXSER_PORTS))
return -EFAULT;
return 0;
- case MOXA_ASPP_MON_EXT:{
+ case MOXA_ASPP_MON_EXT: {
int status;
int opmode, p;
int shiftbit;
unsigned cflag, iflag;
for (i = 0; i < MXSER_PORTS; i++) {
-
if (!mxvar_table[i].base)
continue;
- status = mxser_get_msr(mxvar_table[i].base, 0, i, &(mxvar_table[i]));
-// mxser_check_modem_status(&mxvar_table[i], status);
+ status = mxser_get_msr(mxvar_table[i].base, 0,
+ i, &(mxvar_table[i]));
+ /*
+ mxser_check_modem_status(&mxvar_table[i],
+ status);
+ */
if (status & UART_MSR_TERI)
mxvar_table[i].icount.rng++;
if (status & UART_MSR_DDSR)
@@ -1578,75 +1649,76 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
return 0;
}
-
static void mxser_stoprx(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
- //unsigned long flags;
-
+ struct mxser_struct *info = tty->driver_data;
+ /* unsigned long flags; */
info->ldisc_stop_rx = 1;
if (I_IXOFF(tty)) {
-
- //MX_LOCK(&info->slock);
- // following add by Victor Yu. 09-02-2002
+ /* MX_LOCK(&info->slock); */
+ /* following add by Victor Yu. 09-02-2002 */
if (info->IsMoxaMustChipFlag) {
info->IER &= ~MOXA_MUST_RECV_ISR;
outb(info->IER, info->base + UART_IER);
} else {
- // above add by Victor Yu. 09-02-2002
-
+ /* above add by Victor Yu. 09-02-2002 */
info->x_char = STOP_CHAR(tty);
- // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002
+ /* mask by Victor Yu. 09-02-2002 */
+ /* outb(info->IER, 0); */
outb(0, info->base + UART_IER);
info->IER |= UART_IER_THRI;
- outb(info->IER, info->base + UART_IER); /* force Tx interrupt */
- } // add by Victor Yu. 09-02-2002
- //MX_UNLOCK(&info->slock);
+ /* force Tx interrupt */
+ outb(info->IER, info->base + UART_IER);
+ } /* add by Victor Yu. 09-02-2002 */
+ /* MX_UNLOCK(&info->slock); */
}
if (info->tty->termios->c_cflag & CRTSCTS) {
- //MX_LOCK(&info->slock);
+ /* MX_LOCK(&info->slock); */
info->MCR &= ~UART_MCR_RTS;
outb(info->MCR, info->base + UART_MCR);
- //MX_UNLOCK(&info->slock);
+ /* MX_UNLOCK(&info->slock); */
}
}
static void mxser_startrx(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
- //unsigned long flags;
+ struct mxser_struct *info = tty->driver_data;
+ /* unsigned long flags; */
info->ldisc_stop_rx = 0;
if (I_IXOFF(tty)) {
if (info->x_char)
info->x_char = 0;
else {
- //MX_LOCK(&info->slock);
+ /* MX_LOCK(&info->slock); */
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
if (info->IsMoxaMustChipFlag) {
info->IER |= MOXA_MUST_RECV_ISR;
outb(info->IER, info->base + UART_IER);
} else {
- // above add by Victor Yu. 09-02-2002
+ /* above add by Victor Yu. 09-02-2002 */
info->x_char = START_CHAR(tty);
- // outb(info->IER, 0); // mask by Victor Yu. 09-02-2002
- outb(0, info->base + UART_IER); // add by Victor Yu. 09-02-2002
- info->IER |= UART_IER_THRI; /* force Tx interrupt */
+ /* mask by Victor Yu. 09-02-2002 */
+ /* outb(info->IER, 0); */
+ /* add by Victor Yu. 09-02-2002 */
+ outb(0, info->base + UART_IER);
+ /* force Tx interrupt */
+ info->IER |= UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
- } // add by Victor Yu. 09-02-2002
- //MX_UNLOCK(&info->slock);
+ } /* add by Victor Yu. 09-02-2002 */
+ /* MX_UNLOCK(&info->slock); */
}
}
if (info->tty->termios->c_cflag & CRTSCTS) {
- //MX_LOCK(&info->slock);
+ /* MX_LOCK(&info->slock); */
info->MCR |= UART_MCR_RTS;
outb(info->MCR, info->base + UART_MCR);
- //MX_UNLOCK(&info->slock);
+ /* MX_UNLOCK(&info->slock); */
}
}
@@ -1656,48 +1728,53 @@ static void mxser_startrx(struct tty_struct *tty)
*/
static void mxser_throttle(struct tty_struct *tty)
{
- //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
- //unsigned long flags;
- //MX_LOCK(&info->slock);
+ /* struct mxser_struct *info = tty->driver_data; */
+ /* unsigned long flags; */
+
+ /* MX_LOCK(&info->slock); */
mxser_stoprx(tty);
- //MX_UNLOCK(&info->slock);
+ /* MX_UNLOCK(&info->slock); */
}
static void mxser_unthrottle(struct tty_struct *tty)
{
- //struct mxser_struct *info = (struct mxser_struct *)tty->driver_data;
- //unsigned long flags;
- //MX_LOCK(&info->slock);
+ /* struct mxser_struct *info = tty->driver_data; */
+ /* unsigned long flags; */
+
+ /* MX_LOCK(&info->slock); */
mxser_startrx(tty);
- //MX_UNLOCK(&info->slock);
+ /* MX_UNLOCK(&info->slock); */
}
static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termios)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
- if ((tty->termios->c_cflag != old_termios->c_cflag) || (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+ if ((tty->termios->c_cflag != old_termios->c_cflag) ||
+ (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
mxser_change_speed(info, old_termios);
- if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
mxser_start(tty);
}
}
/* Handle sw stopped */
- if ((old_termios->c_iflag & IXON) && !(tty->termios->c_iflag & IXON)) {
+ if ((old_termios->c_iflag & IXON) &&
+ !(tty->termios->c_iflag & IXON)) {
tty->stopped = 0;
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
if (info->IsMoxaMustChipFlag) {
spin_lock_irqsave(&info->slock, flags);
DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base);
spin_unlock_irqrestore(&info->slock, flags);
}
- // above add by Victor Yu. 09-02-2002
+ /* above add by Victor Yu. 09-02-2002 */
mxser_start(tty);
}
@@ -1711,7 +1788,7 @@ static void mxser_set_termios(struct tty_struct *tty, struct termios *old_termio
*/
static void mxser_stop(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
@@ -1724,7 +1801,7 @@ static void mxser_stop(struct tty_struct *tty)
static void mxser_start(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
@@ -1740,7 +1817,7 @@ static void mxser_start(struct tty_struct *tty)
*/
static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long orig_jiffies, char_time;
int lsr;
@@ -1777,7 +1854,8 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
if (!timeout || timeout > 2 * info->timeout)
timeout = 2 * info->timeout;
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
- printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
+ printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
+ timeout, char_time);
printk("jiff=%lu...", jiffies);
#endif
while (!((lsr = inb(info->base + UART_LSR)) & UART_LSR_TEMT)) {
@@ -1803,7 +1881,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
*/
void mxser_hangup(struct tty_struct *tty)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
mxser_flush_buffer(tty);
mxser_shutdown(info);
@@ -1815,24 +1893,26 @@ void mxser_hangup(struct tty_struct *tty)
}
-// added by James 03-12-2004.
+/* added by James 03-12-2004. */
/*
* mxser_rs_break() --- routine which turns the break handling on or off
*/
static void mxser_rs_break(struct tty_struct *tty, int break_state)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
spin_lock_irqsave(&info->slock, flags);
if (break_state == -1)
- outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
+ outb(inb(info->base + UART_LCR) | UART_LCR_SBC,
+ info->base + UART_LCR);
else
- outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
+ outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC,
+ info->base + UART_LCR);
spin_unlock_irqrestore(&info->slock, flags);
}
-// (above) added by James.
+/* (above) added by James. */
/*
@@ -1848,7 +1928,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int handled = IRQ_NONE;
port = NULL;
- //spin_lock(&gm_lock);
+ /* spin_lock(&gm_lock); */
for (i = 0; i < MXSER_BOARDS; i++) {
if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
@@ -1857,29 +1937,25 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
}
- if (i == MXSER_BOARDS) {
+ if (i == MXSER_BOARDS)
goto irq_stop;
- }
- if (port == 0) {
+ if (port == 0)
goto irq_stop;
- }
max = mxser_numports[mxsercfg[i].board_type - 1];
while (1) {
irqbits = inb(port->vector) & port->vectormask;
- if (irqbits == port->vectormask) {
+ if (irqbits == port->vectormask)
break;
- }
handled = IRQ_HANDLED;
for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
- if (irqbits == port->vectormask) {
+ if (irqbits == port->vectormask)
break;
- }
if (bits & irqbits)
continue;
info = port + i;
- // following add by Victor Yu. 09-13-2002
+ /* following add by Victor Yu. 09-13-2002 */
iir = inb(info->base + UART_IIR);
if (iir & UART_IIR_NO_INT)
continue;
@@ -1890,9 +1966,9 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
inb(info->base + UART_MSR);
continue;
}
- // above add by Victor Yu. 09-13-2002
+ /* above add by Victor Yu. 09-13-2002 */
/*
- if ( info->tty->flip.count < TTY_FLIPBUF_SIZE/4 ){
+ if (info->tty->flip.count < TTY_FLIPBUF_SIZE / 4) {
info->IER |= MOXA_MUST_RECV_ISR;
outb(info->IER, info->base + UART_IER);
}
@@ -1908,18 +1984,15 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
status = inb(info->base + UART_LSR) & info->read_status_mask;
*/
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
status = inb(info->base + UART_LSR);
- if (status & UART_LSR_PE) {
+ if (status & UART_LSR_PE)
info->err_shadow |= NPPI_NOTIFY_PARITY;
- }
- if (status & UART_LSR_FE) {
+ if (status & UART_LSR_FE)
info->err_shadow |= NPPI_NOTIFY_FRAMING;
- }
- if (status & UART_LSR_OE) {
+ if (status & UART_LSR_OE)
info->err_shadow |= NPPI_NOTIFY_HW_OVERRUN;
- }
if (status & UART_LSR_BI)
info->err_shadow |= NPPI_NOTIFY_BREAK;
@@ -1930,11 +2003,14 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
continue;
}
*/
- if (iir == MOXA_MUST_IIR_GDA || iir == MOXA_MUST_IIR_RDA || iir == MOXA_MUST_IIR_RTO || iir == MOXA_MUST_IIR_LSR)
+ if (iir == MOXA_MUST_IIR_GDA ||
+ iir == MOXA_MUST_IIR_RDA ||
+ iir == MOXA_MUST_IIR_RTO ||
+ iir == MOXA_MUST_IIR_LSR)
mxser_receive_chars(info, &status);
} else {
- // above add by Victor Yu. 09-02-2002
+ /* above add by Victor Yu. 09-02-2002 */
status &= info->read_status_mask;
if (status & UART_LSR_DR)
@@ -1944,13 +2020,13 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (msr & UART_MSR_ANY_DELTA) {
mxser_check_modem_status(info, msr);
}
- // following add by Victor Yu. 09-13-2002
+ /* following add by Victor Yu. 09-13-2002 */
if (info->IsMoxaMustChipFlag) {
if ((iir == 0x02) && (status & UART_LSR_THRE)) {
mxser_transmit_chars(info);
}
} else {
- // above add by Victor Yu. 09-13-2002
+ /* above add by Victor Yu. 09-13-2002 */
if (status & UART_LSR_THRE) {
/* 8-2-99 by William
@@ -1966,7 +2042,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
irq_stop:
- //spin_unlock(&gm_lock);
+ /* spin_unlock(&gm_lock); */
return handled;
}
@@ -1984,56 +2060,58 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
recv_room = tty->receive_room;
if ((recv_room == 0) && (!info->ldisc_stop_rx)) {
- //mxser_throttle(tty);
+ /* mxser_throttle(tty); */
mxser_stoprx(tty);
- //return;
+ /* return; */
}
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
if (*status & UART_LSR_SPECIAL) {
goto intr_old;
}
- // following add by Victor Yu. 02-11-2004
- if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID && (*status & MOXA_MUST_LSR_RERR))
+ /* following add by Victor Yu. 02-11-2004 */
+ if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID &&
+ (*status & MOXA_MUST_LSR_RERR))
goto intr_old;
- // above add by Victor Yu. 02-14-2004
+ /* above add by Victor Yu. 02-14-2004 */
if (*status & MOXA_MUST_LSR_RERR)
goto intr_old;
gdl = inb(info->base + MOXA_MUST_GDL_REGISTER);
- if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID) // add by Victor Yu. 02-11-2004
+ /* add by Victor Yu. 02-11-2004 */
+ if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID)
gdl &= MOXA_MUST_GDL_MASK;
if (gdl >= recv_room) {
if (!info->ldisc_stop_rx) {
- //mxser_throttle(tty);
+ /* mxser_throttle(tty); */
mxser_stoprx(tty);
}
- //return;
+ /* return; */
}
while (gdl--) {
ch = inb(info->base + UART_RX);
tty_insert_flip_char(tty, ch, 0);
cnt++;
/*
- if((cnt>=HI_WATER) && (info->stop_rx==0)){
+ if ((cnt >= HI_WATER) && (info->stop_rx == 0)) {
mxser_stoprx(tty);
- info->stop_rx=1;
+ info->stop_rx = 1;
break;
} */
}
goto end_intr;
}
-intr_old:
- // above add by Victor Yu. 09-02-2002
+ intr_old:
+ /* above add by Victor Yu. 09-02-2002 */
do {
if (max-- < 0)
break;
/*
- if((cnt>=HI_WATER) && (info->stop_rx==0)){
+ if ((cnt >= HI_WATER) && (info->stop_rx == 0)) {
mxser_stoprx(tty);
info->stop_rx=1;
break;
@@ -2041,11 +2119,11 @@ intr_old:
*/
ch = inb(info->base + UART_RX);
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
if (info->IsMoxaMustChipFlag && (*status & UART_LSR_OE) /*&& !(*status&UART_LSR_DR) */ )
outb(0x23, info->base + UART_FCR);
*status &= info->read_status_mask;
- // above add by Victor Yu. 09-02-2002
+ /* above add by Victor Yu. 09-02-2002 */
if (*status & info->ignore_status_mask) {
if (++ignored > 100)
break;
@@ -2080,7 +2158,7 @@ intr_old:
cnt++;
if (cnt >= recv_room) {
if (!info->ldisc_stop_rx) {
- //mxser_throttle(tty);
+ /* mxser_throttle(tty); */
mxser_stoprx(tty);
}
break;
@@ -2088,21 +2166,20 @@ intr_old:
}
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
if (info->IsMoxaMustChipFlag)
break;
- // above add by Victor Yu. 09-02-2002
+ /* above add by Victor Yu. 09-02-2002 */
/* mask by Victor Yu. 09-02-2002
*status = inb(info->base + UART_LSR) & info->read_status_mask;
*/
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
*status = inb(info->base + UART_LSR);
- // above add by Victor Yu. 09-02-2002
+ /* above add by Victor Yu. 09-02-2002 */
} while (*status & UART_LSR_DR);
-end_intr: // add by Victor Yu. 09-02-2002
-
+end_intr: /* add by Victor Yu. 09-02-2002 */
mxvar_log.rxcnt[info->port] += cnt;
info->mon_data.rxcnt += cnt;
info->mon_data.up_rxcnt += cnt;
@@ -2137,7 +2214,10 @@ static void mxser_transmit_chars(struct mxser_struct *info)
return;
}
- if ((info->xmit_cnt <= 0) || info->tty->stopped || (info->tty->hw_stopped && (info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag))) {
+ if ((info->xmit_cnt <= 0) || info->tty->stopped ||
+ (info->tty->hw_stopped &&
+ (info->type != PORT_16550A) &&
+ (!info->IsMoxaMustChipFlag))) {
info->IER &= ~UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
spin_unlock_irqrestore(&info->slock, flags);
@@ -2147,17 +2227,18 @@ static void mxser_transmit_chars(struct mxser_struct *info)
cnt = info->xmit_cnt;
count = info->xmit_fifo_size;
do {
- outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
+ outb(info->xmit_buf[info->xmit_tail++],
+ info->base + UART_TX);
info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
if (--info->xmit_cnt <= 0)
break;
} while (--count > 0);
mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
-// added by James 03-12-2004.
+/* added by James 03-12-2004. */
info->mon_data.txcnt += (cnt - info->xmit_cnt);
info->mon_data.up_txcnt += (cnt - info->xmit_cnt);
-// (above) added by James.
+/* (above) added by James. */
/* added by casper 1/11/2000 */
info->icount.tx += (cnt - info->xmit_cnt);
@@ -2188,7 +2269,6 @@ static void mxser_check_modem_status(struct mxser_struct *info, int status)
info->mon_data.modem_status = status;
wake_up_interruptible(&info->delta_msr_wait);
-
if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
if (status & UART_MSR_DCD)
wake_up_interruptible(&info->open_wait);
@@ -2200,7 +2280,8 @@ static void mxser_check_modem_status(struct mxser_struct *info, int status)
if (status & UART_MSR_CTS) {
info->tty->hw_stopped = 0;
- if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+ if ((info->type != PORT_16550A) &&
+ (!info->IsMoxaMustChipFlag)) {
info->IER |= UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
}
@@ -2209,7 +2290,8 @@ static void mxser_check_modem_status(struct mxser_struct *info, int status)
} else {
if (!(status & UART_MSR_CTS)) {
info->tty->hw_stopped = 1;
- if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+ if ((info->type != PORT_16550A) &&
+ (!info->IsMoxaMustChipFlag)) {
info->IER &= ~UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
}
@@ -2231,7 +2313,7 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, stru
*/
if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
info->flags |= ASYNC_NORMAL_ACTIVE;
- return (0);
+ return 0;
}
if (tty->termios->c_cflag & CLOCAL)
@@ -2254,7 +2336,8 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, stru
info->blocked_open++;
while (1) {
spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR);
+ outb(inb(info->base + UART_MCR) |
+ UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR);
spin_unlock_irqrestore(&info->slock, flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) {
@@ -2264,7 +2347,9 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, stru
retval = -ERESTARTSYS;
break;
}
- if (!(info->flags & ASYNC_CLOSING) && (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)))
+ if (!(info->flags & ASYNC_CLOSING) &&
+ (do_clocal ||
+ (inb(info->base + UART_MSR) & UART_MSR_DCD)))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
@@ -2278,27 +2363,26 @@ static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, stru
info->count++;
info->blocked_open--;
if (retval)
- return (retval);
+ return retval;
info->flags |= ASYNC_NORMAL_ACTIVE;
- return (0);
+ return 0;
}
static int mxser_startup(struct mxser_struct *info)
{
-
unsigned long page;
unsigned long flags;
page = __get_free_page(GFP_KERNEL);
if (!page)
- return (-ENOMEM);
+ return -ENOMEM;
spin_lock_irqsave(&info->slock, flags);
if (info->flags & ASYNC_INITIALIZED) {
free_page(page);
spin_unlock_irqrestore(&info->slock, flags);
- return (0);
+ return 0;
}
if (!info->base || !info->type) {
@@ -2306,7 +2390,7 @@ static int mxser_startup(struct mxser_struct *info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
free_page(page);
spin_unlock_irqrestore(&info->slock, flags);
- return (0);
+ return 0;
}
if (info->xmit_buf)
free_page(page);
@@ -2318,9 +2402,12 @@ static int mxser_startup(struct mxser_struct *info)
* (they will be reenabled in mxser_change_speed())
*/
if (info->IsMoxaMustChipFlag)
- outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
+ outb((UART_FCR_CLEAR_RCVR |
+ UART_FCR_CLEAR_XMIT |
+ MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
else
- outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
+ outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+ info->base + UART_FCR);
/*
* At this point there's no way the LSR could still be 0xFF;
@@ -2332,9 +2419,9 @@ static int mxser_startup(struct mxser_struct *info)
if (capable(CAP_SYS_ADMIN)) {
if (info->tty)
set_bit(TTY_IO_ERROR, &info->tty->flags);
- return (0);
+ return 0;
} else
- return (-ENODEV);
+ return -ENODEV;
}
/*
@@ -2356,12 +2443,12 @@ static int mxser_startup(struct mxser_struct *info)
* Finally, enable interrupts
*/
info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
-// info->IER = UART_IER_RLSI | UART_IER_RDI;
+ /* info->IER = UART_IER_RLSI | UART_IER_RDI; */
- // following add by Victor Yu. 08-30-2002
+ /* following add by Victor Yu. 08-30-2002 */
if (info->IsMoxaMustChipFlag)
info->IER |= MOXA_MUST_IER_EGDAI;
- // above add by Victor Yu. 08-30-2002
+ /* above add by Victor Yu. 08-30-2002 */
outb(info->IER, info->base + UART_IER); /* enable interrupts */
/*
@@ -2383,7 +2470,7 @@ static int mxser_startup(struct mxser_struct *info)
mxser_change_speed(info, NULL);
info->flags |= ASYNC_INITIALIZED;
- return (0);
+ return 0;
}
/*
@@ -2421,12 +2508,15 @@ static void mxser_shutdown(struct mxser_struct *info)
outb(info->MCR, info->base + UART_MCR);
/* clear Rx/Tx FIFO's */
- // following add by Victor Yu. 08-30-2002
+ /* following add by Victor Yu. 08-30-2002 */
if (info->IsMoxaMustChipFlag)
- outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
+ outb((UART_FCR_CLEAR_RCVR |
+ UART_FCR_CLEAR_XMIT |
+ MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR);
else
- // above add by Victor Yu. 08-30-2002
- outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
+ /* above add by Victor Yu. 08-30-2002 */
+ outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+ info->base + UART_FCR);
/* read data port to reset things */
(void) inb(info->base + UART_RX);
@@ -2436,11 +2526,10 @@ static void mxser_shutdown(struct mxser_struct *info)
info->flags &= ~ASYNC_INITIALIZED;
- // following add by Victor Yu. 09-23-2002
- if (info->IsMoxaMustChipFlag) {
+ /* following add by Victor Yu. 09-23-2002 */
+ if (info->IsMoxaMustChipFlag)
SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base);
- }
- // above add by Victor Yu. 09-23-2002
+ /* above add by Victor Yu. 09-23-2002 */
spin_unlock_irqrestore(&info->slock, flags);
}
@@ -2457,14 +2546,12 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
long baud;
unsigned long flags;
-
if (!info->tty || !info->tty->termios)
return ret;
cflag = info->tty->termios->c_cflag;
if (!(info->base))
return ret;
-
#ifndef B921600
#define B921600 (B460800 +1)
#endif
@@ -2559,9 +2646,8 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
cval |= 0x04;
if (cflag & PARENB)
cval |= UART_LCR_PARITY;
- if (!(cflag & PARODD)) {
+ if (!(cflag & PARODD))
cval |= UART_LCR_EPAR;
- }
if (cflag & CMSPAR)
cval |= UART_LCR_SPAR;
@@ -2574,13 +2660,12 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
fcr = 0;
} else {
fcr = UART_FCR_ENABLE_FIFO;
- // following add by Victor Yu. 08-30-2002
+ /* following add by Victor Yu. 08-30-2002 */
if (info->IsMoxaMustChipFlag) {
fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
SET_MOXA_MUST_FIFO_VALUE(info);
} else {
- // above add by Victor Yu. 08-30-2002
-
+ /* above add by Victor Yu. 08-30-2002 */
switch (info->rx_trigger) {
case 1:
fcr |= UART_FCR_TRIGGER_1;
@@ -2606,22 +2691,24 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
info->IER |= UART_IER_MSI;
if ((info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) {
info->MCR |= UART_MCR_AFE;
- //status = mxser_get_msr(info->base, 0, info->port);
-/* save_flags(flags);
+ /* status = mxser_get_msr(info->base, 0, info->port); */
+/*
+ save_flags(flags);
cli();
status = inb(baseaddr + UART_MSR);
- restore_flags(flags);*/
- //mxser_check_modem_status(info, status);
+ restore_flags(flags);
+*/
+ /* mxser_check_modem_status(info, status); */
} else {
- //status = mxser_get_msr(info->base, 0, info->port);
-
- //MX_LOCK(&info->slock);
+ /* status = mxser_get_msr(info->base, 0, info->port); */
+ /* MX_LOCK(&info->slock); */
status = inb(info->base + UART_MSR);
- //MX_UNLOCK(&info->slock);
+ /* MX_UNLOCK(&info->slock); */
if (info->tty->hw_stopped) {
if (status & UART_MSR_CTS) {
info->tty->hw_stopped = 0;
- if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+ if ((info->type != PORT_16550A) &&
+ (!info->IsMoxaMustChipFlag)) {
info->IER |= UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
}
@@ -2630,7 +2717,8 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
} else {
if (!(status & UART_MSR_CTS)) {
info->tty->hw_stopped = 1;
- if ((info->type != PORT_16550A) && (!info->IsMoxaMustChipFlag)) {
+ if ((info->type != PORT_16550A) &&
+ (!info->IsMoxaMustChipFlag)) {
info->IER &= ~UART_IER_THRI;
outb(info->IER, info->base + UART_IER);
}
@@ -2668,11 +2756,17 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
* overruns too. (For real raw support).
*/
if (I_IGNPAR(info->tty)) {
- info->ignore_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
- info->read_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
+ info->ignore_status_mask |=
+ UART_LSR_OE |
+ UART_LSR_PE |
+ UART_LSR_FE;
+ info->read_status_mask |=
+ UART_LSR_OE |
+ UART_LSR_PE |
+ UART_LSR_FE;
}
}
- // following add by Victor Yu. 09-02-2002
+ /* following add by Victor Yu. 09-02-2002 */
if (info->IsMoxaMustChipFlag) {
spin_lock_irqsave(&info->slock, flags);
SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty));
@@ -2698,7 +2792,7 @@ static int mxser_change_speed(struct mxser_struct *info, struct termios *old_ter
*/
spin_unlock_irqrestore(&info->slock, flags);
}
- // above add by Victor Yu. 09-02-2002
+ /* above add by Victor Yu. 09-02-2002 */
outb(fcr, info->base + UART_FCR); /* set fcr */
@@ -2729,10 +2823,8 @@ static int mxser_set_baud(struct mxser_struct *info, long newspd)
quot = (2 * info->baud_base / 269);
} else if (newspd) {
quot = info->baud_base / newspd;
-
if (quot == 0)
quot = 1;
-
} else {
quot = 0;
}
@@ -2765,8 +2857,6 @@ static int mxser_set_baud(struct mxser_struct *info, long newspd)
return ret;
}
-
-
/*
* ------------------------------------------------------------
* friends of mxser_ioctl()
@@ -2777,7 +2867,7 @@ static int mxser_get_serial_info(struct mxser_struct *info, struct serial_struct
struct serial_struct tmp;
if (!retinfo)
- return (-EFAULT);
+ return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
tmp.type = info->type;
tmp.line = info->port;
@@ -2791,7 +2881,7 @@ static int mxser_get_serial_info(struct mxser_struct *info, struct serial_struct
tmp.hub6 = 0;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
- return (0);
+ return 0;
}
static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct __user *new_info)
@@ -2801,29 +2891,37 @@ static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct
int retval = 0;
if (!new_info || !info->base)
- return (-EFAULT);
+ return -EFAULT;
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
return -EFAULT;
- if ((new_serial.irq != info->irq) || (new_serial.port != info->base) || (new_serial.custom_divisor != info->custom_divisor) || (new_serial.baud_base != info->baud_base))
- return (-EPERM);
+ if ((new_serial.irq != info->irq) ||
+ (new_serial.port != info->base) ||
+ (new_serial.custom_divisor != info->custom_divisor) ||
+ (new_serial.baud_base != info->baud_base))
+ return -EPERM;
flags = info->flags & ASYNC_SPD_MASK;
if (!capable(CAP_SYS_ADMIN)) {
- if ((new_serial.baud_base != info->baud_base) || (new_serial.close_delay != info->close_delay) || ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK)))
- return (-EPERM);
- info->flags = ((info->flags & ~ASYNC_USR_MASK) | (new_serial.flags & ASYNC_USR_MASK));
+ if ((new_serial.baud_base != info->baud_base) ||
+ (new_serial.close_delay != info->close_delay) ||
+ ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK)))
+ return -EPERM;
+ info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+ (new_serial.flags & ASYNC_USR_MASK));
} else {
/*
* OK, past this point, all the error checking has been done.
* At this point, we start making changes.....
*/
- info->flags = ((info->flags & ~ASYNC_FLAGS) | (new_serial.flags & ASYNC_FLAGS));
+ info->flags = ((info->flags & ~ASYNC_FLAGS) |
+ (new_serial.flags & ASYNC_FLAGS));
info->close_delay = new_serial.close_delay * HZ / 100;
info->closing_wait = new_serial.closing_wait * HZ / 100;
- info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
- info->tty->low_latency = 0; //(info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ info->tty->low_latency =
+ (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ info->tty->low_latency = 0; /* (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; */
}
/* added by casper, 3/17/2000, for mouse */
@@ -2831,7 +2929,6 @@ static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct
process_txrx_fifo(info);
- /* */
if (info->flags & ASYNC_INITIALIZED) {
if (flags != (info->flags & ASYNC_SPD_MASK)) {
mxser_change_speed(info, NULL);
@@ -2839,7 +2936,7 @@ static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct
} else {
retval = mxser_startup(info);
}
- return (retval);
+ return retval;
}
/*
@@ -2876,25 +2973,27 @@ static void mxser_send_break(struct mxser_struct *info, int duration)
return;
set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
+ outb(inb(info->base + UART_LCR) | UART_LCR_SBC,
+ info->base + UART_LCR);
spin_unlock_irqrestore(&info->slock, flags);
schedule_timeout(duration);
spin_lock_irqsave(&info->slock, flags);
- outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
+ outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC,
+ info->base + UART_LCR);
spin_unlock_irqrestore(&info->slock, flags);
}
static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned char control, status;
unsigned long flags;
if (tty->index == MXSER_PORTS)
- return (-ENOIOCTLCMD);
+ return -ENOIOCTLCMD;
if (tty->flags & (1 << TTY_IO_ERROR))
- return (-EIO);
+ return -EIO;
control = info->MCR;
@@ -2904,12 +3003,16 @@ static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
mxser_check_modem_status(info, status);
spin_unlock_irqrestore(&info->slock, flags);
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
- ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+ ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
+ ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
+ ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
+ ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
+ ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
}
static int mxser_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear)
{
- struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+ struct mxser_struct *info = tty->driver_data;
unsigned long flags;
@@ -2968,38 +3071,36 @@ static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf)
hwconf->board_type = MXSER_BOARD_CI104J;
hwconf->ports = 4;
} else
- return (0);
+ return 0;
irq = 0;
if (hwconf->ports == 2) {
irq = regs[9] & 0xF000;
irq = irq | (irq >> 4);
if (irq != (regs[9] & 0xFF00))
- return (MXSER_ERR_IRQ_CONFLIT);
+ return MXSER_ERR_IRQ_CONFLIT;
} else if (hwconf->ports == 4) {
irq = regs[9] & 0xF000;
irq = irq | (irq >> 4);
irq = irq | (irq >> 8);
if (irq != regs[9])
- return (MXSER_ERR_IRQ_CONFLIT);
+ return MXSER_ERR_IRQ_CONFLIT;
} else if (hwconf->ports == 8) {
irq = regs[9] & 0xF000;
irq = irq | (irq >> 4);
irq = irq | (irq >> 8);
if ((irq != regs[9]) || (irq != regs[10]))
- return (MXSER_ERR_IRQ_CONFLIT);
+ return MXSER_ERR_IRQ_CONFLIT;
}
- if (!irq) {
- return (MXSER_ERR_IRQ);
- }
- hwconf->irq = ((int) (irq & 0xF000) >> 12);
+ if (!irq)
+ return MXSER_ERR_IRQ;
+ hwconf->irq = ((int)(irq & 0xF000) >> 12);
for (i = 0; i < 8; i++)
hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8;
- if ((regs[12] & 0x80) == 0) {
- return (MXSER_ERR_VECTOR);
- }
- hwconf->vector = (int) regs[11]; /* interrupt vector */
+ if ((regs[12] & 0x80) == 0)
+ return MXSER_ERR_VECTOR;
+ hwconf->vector = (int)regs[11]; /* interrupt vector */
if (id == 1)
hwconf->vector_mask = 0x00FF;
else
@@ -3007,10 +3108,10 @@ static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf)
for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
if (regs[12] & bits) {
hwconf->baud_base[i] = 921600;
- hwconf->MaxCanSetBaudRate[i] = 921600; // add by Victor Yu. 09-04-2002
+ hwconf->MaxCanSetBaudRate[i] = 921600; /* add by Victor Yu. 09-04-2002 */
} else {
hwconf->baud_base[i] = 115200;
- hwconf->MaxCanSetBaudRate[i] = 115200; // add by Victor Yu. 09-04-2002
+ hwconf->MaxCanSetBaudRate[i] = 115200; /* add by Victor Yu. 09-04-2002 */
}
}
scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
@@ -3030,7 +3131,7 @@ static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf)
hwconf->ports = 4;
request_region(hwconf->ioaddr[0], 8 * hwconf->ports, "mxser(IO)");
request_region(hwconf->vector, 1, "mxser(vector)");
- return (hwconf->ports);
+ return hwconf->ports;
}
#define CHIP_SK 0x01 /* Serial Data Clock in Eprom */
@@ -3053,7 +3154,7 @@ static int mxser_read_register(int port, unsigned short *regs)
id = mxser_program_mode(port);
if (id < 0)
- return (id);
+ return id;
for (i = 0; i < 14; i++) {
k = (i & 0x3F) | 0x180;
for (j = 0x100; j > 0; j >>= 1) {
@@ -3066,7 +3167,7 @@ static int mxser_read_register(int port, unsigned short *regs)
outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */
}
}
- (void) inb(port);
+ (void)inb(port);
value = 0;
for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
outb(CHIP_CS, port);
@@ -3078,28 +3179,33 @@ static int mxser_read_register(int port, unsigned short *regs)
outb(0, port);
}
mxser_normal_mode(port);
- return (id);
+ return id;
}
static int mxser_program_mode(int port)
{
int id, i, j, n;
- //unsigned long flags;
+ /* unsigned long flags; */
spin_lock(&gm_lock);
outb(0, port);
outb(0, port);
outb(0, port);
- (void) inb(port);
- (void) inb(port);
+ (void)inb(port);
+ (void)inb(port);
outb(0, port);
- (void) inb(port);
- //restore_flags(flags);
+ (void)inb(port);
+ /* restore_flags(flags); */
spin_unlock(&gm_lock);
id = inb(port + 1) & 0x1F;
- if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != C102_ASIC_ID) && (id != CI132_ASIC_ID) && (id != CI134_ASIC_ID) && (id != CI104J_ASIC_ID))
- return (-1);
+ if ((id != C168_ASIC_ID) &&
+ (id != C104_ASIC_ID) &&
+ (id != C102_ASIC_ID) &&
+ (id != CI132_ASIC_ID) &&
+ (id != CI134_ASIC_ID) &&
+ (id != CI104J_ASIC_ID))
+ return -1;
for (i = 0, j = 0; i < 4; i++) {
n = inb(port + 2);
if (n == 'M') {
@@ -3112,7 +3218,7 @@ static int mxser_program_mode(int port)
}
if (j != 2)
id = -2;
- return (id);
+ return id;
}
static void mxser_normal_mode(int port)
@@ -3130,7 +3236,7 @@ static void mxser_normal_mode(int port)
if ((n & 0x61) == 0x60)
break;
if ((n & 1) == 1)
- (void) inb(port);
+ (void)inb(port);
}
outb(0x00, port + 4);
}
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index c48de09..203dc2b 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -951,7 +951,8 @@ static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
{
queue_the_message:
- pMsg = kmalloc(sizeof(struct r3964_message), GFP_KERNEL);
+ pMsg = kmalloc(sizeof(struct r3964_message),
+ error_code?GFP_ATOMIC:GFP_KERNEL);
TRACE_M("add_msg - kmalloc %p",pMsg);
if(pMsg==NULL) {
return;
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 0c141c2..17bc8ab 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1582,7 +1582,7 @@ static void mgslpc_put_char(struct tty_struct *tty, unsigned char ch)
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_put_char"))
return;
- if (!tty || !info->tx_buf)
+ if (!info->tx_buf)
return;
spin_lock_irqsave(&info->lock,flags);
@@ -1649,7 +1649,7 @@ static int mgslpc_write(struct tty_struct * tty,
__FILE__,__LINE__,info->device_name,count);
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_write") ||
- !tty || !info->tx_buf)
+ !info->tx_buf)
goto cleanup;
if (info->params.mode == MGSL_MODE_HDLC) {
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 7edc6a4..0708c51 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -324,35 +324,15 @@ static void rp_do_receive(struct r_port *info,
CHANNEL_t * cp, unsigned int ChanStatus)
{
unsigned int CharNStat;
- int ToRecv, wRecv, space = 0, count;
- unsigned char *cbuf, *chead;
- char *fbuf, *fhead;
- struct tty_ldisc *ld;
-
- ld = tty_ldisc_ref(tty);
+ int ToRecv, wRecv, space;
+ unsigned char *cbuf;
ToRecv = sGetRxCnt(cp);
- space = tty->receive_room;
- if (space > 2 * TTY_FLIPBUF_SIZE)
- space = 2 * TTY_FLIPBUF_SIZE;
- count = 0;
#ifdef ROCKET_DEBUG_INTR
- printk(KERN_INFO "rp_do_receive(%d, %d)...", ToRecv, space);
+ printk(KERN_INFO "rp_do_receive(%d)...", ToRecv);
#endif
-
- /*
- * determine how many we can actually read in. If we can't
- * read any in then we have a software overrun condition.
- */
- if (ToRecv > space)
- ToRecv = space;
-
- ToRecv = tty_prepare_flip_string_flags(tty, &chead, &fhead, ToRecv);
- if (ToRecv <= 0)
- goto done;
-
- cbuf = chead;
- fbuf = fhead;
+ if (ToRecv == 0)
+ return;
/*
* if status indicates there are errored characters in the
@@ -380,6 +360,8 @@ static void rp_do_receive(struct r_port *info,
info->read_status_mask);
#endif
while (ToRecv) {
+ char flag;
+
CharNStat = sInW(sGetTxRxDataIO(cp));
#ifdef ROCKET_DEBUG_RECEIVE
printk(KERN_INFO "%x...", CharNStat);
@@ -392,17 +374,16 @@ static void rp_do_receive(struct r_port *info,
}
CharNStat &= info->read_status_mask;
if (CharNStat & STMBREAKH)
- *fbuf++ = TTY_BREAK;
+ flag = TTY_BREAK;
else if (CharNStat & STMPARITYH)
- *fbuf++ = TTY_PARITY;
+ flag = TTY_PARITY;
else if (CharNStat & STMFRAMEH)
- *fbuf++ = TTY_FRAME;
+ flag = TTY_FRAME;
else if (CharNStat & STMRCVROVRH)
- *fbuf++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
else
- *fbuf++ = TTY_NORMAL;
- *cbuf++ = CharNStat & 0xff;
- count++;
+ flag = TTY_NORMAL;
+ tty_insert_flip_char(tty, CharNStat & 0xff, flag);
ToRecv--;
}
@@ -422,20 +403,23 @@ static void rp_do_receive(struct r_port *info,
* characters at time by doing repeated word IO
* transfer.
*/
+ space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
+ if (space < ToRecv) {
+#ifdef ROCKET_DEBUG_RECEIVE
+ printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
+#endif
+ if (space <= 0)
+ return;
+ ToRecv = space;
+ }
wRecv = ToRecv >> 1;
if (wRecv)
sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
if (ToRecv & 1)
cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
- memset(fbuf, TTY_NORMAL, ToRecv);
- cbuf += ToRecv;
- fbuf += ToRecv;
- count += ToRecv;
}
/* Push the data up to the tty layer */
- ld->receive_buf(tty, chead, fhead, count);
-done:
- tty_ldisc_deref(ld);
+ tty_flip_buffer_push(tty);
}
/*
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 5343e9f..1b53302 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1683,7 +1683,7 @@ static int sx_write(struct tty_struct * tty,
bp = port_Board(port);
- if (!tty || !port->xmit_buf || !tmp_buf) {
+ if (!port->xmit_buf || !tmp_buf) {
func_exit();
return 0;
}
@@ -1733,7 +1733,7 @@ static void sx_put_char(struct tty_struct * tty, unsigned char ch)
return;
}
dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
- if (!tty || !port->xmit_buf) {
+ if (!port->xmit_buf) {
func_exit();
return;
}
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index b4d1f4e..4e35d41 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -101,6 +101,7 @@ MODULE_LICENSE("GPL");
static struct pci_device_id pci_table[] = {
{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+ {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{0,}, /* terminate list */
@@ -870,7 +871,7 @@ static int write(struct tty_struct *tty,
goto cleanup;
DBGINFO(("%s write count=%d\n", info->device_name, count));
- if (!tty || !info->tx_buf)
+ if (!info->tx_buf)
goto cleanup;
if (count > info->max_frame_size) {
@@ -924,7 +925,7 @@ static void put_char(struct tty_struct *tty, unsigned char ch)
if (sanity_check(info, tty->name, "put_char"))
return;
DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
- if (!tty || !info->tx_buf)
+ if (!info->tx_buf)
return;
spin_lock_irqsave(&info->lock,flags);
if (!info->tx_active && (info->tx_count < info->max_frame_size))
@@ -2515,7 +2516,8 @@ static int set_txidle(struct slgt_info *info, int idle_mode)
DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode));
spin_lock_irqsave(&info->lock,flags);
info->idle_mode = idle_mode;
- tx_set_idle(info);
+ if (info->params.mode != MGSL_MODE_ASYNC)
+ tx_set_idle(info);
spin_unlock_irqrestore(&info->lock,flags);
return 0;
}
@@ -3076,7 +3078,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
static int alloc_tmp_rbuf(struct slgt_info *info)
{
- info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL);
+ info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL);
if (info->tmp_rbuf == NULL)
return -ENOMEM;
return 0;
@@ -3276,6 +3278,9 @@ static void add_device(struct slgt_info *info)
case SYNCLINK_GT_DEVICE_ID:
devstr = "GT";
break;
+ case SYNCLINK_GT2_DEVICE_ID:
+ devstr = "GT2";
+ break;
case SYNCLINK_GT4_DEVICE_ID:
devstr = "GT4";
break;
@@ -3353,7 +3358,9 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
int i;
int port_count = 1;
- if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
+ if (pdev->device == SYNCLINK_GT2_DEVICE_ID)
+ port_count = 2;
+ else if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
port_count = 4;
/* allocate device instances for all ports */
@@ -3940,8 +3947,6 @@ static void async_mode(struct slgt_info *info)
msc_set_vcr(info);
- tx_set_idle(info);
-
/* SCR (serial control)
*
* 15 1=tx req on FIFO half empty
@@ -4012,7 +4017,7 @@ static void hdlc_mode(struct slgt_info *info)
case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
}
- switch (info->params.crc_type)
+ switch (info->params.crc_type & HDLC_CRC_MASK)
{
case HDLC_CRC_16_CCITT: val |= BIT9; break;
case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
@@ -4073,7 +4078,7 @@ static void hdlc_mode(struct slgt_info *info)
case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
}
- switch (info->params.crc_type)
+ switch (info->params.crc_type & HDLC_CRC_MASK)
{
case HDLC_CRC_16_CCITT: val |= BIT9; break;
case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
@@ -4175,17 +4180,38 @@ static void hdlc_mode(struct slgt_info *info)
*/
static void tx_set_idle(struct slgt_info *info)
{
- unsigned char val = 0xff;
+ unsigned char val;
+ unsigned short tcr;
- switch(info->idle_mode)
- {
- case HDLC_TXIDLE_FLAGS: val = 0x7e; break;
- case HDLC_TXIDLE_ALT_ZEROS_ONES: val = 0xaa; break;
- case HDLC_TXIDLE_ZEROS: val = 0x00; break;
- case HDLC_TXIDLE_ONES: val = 0xff; break;
- case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
- case HDLC_TXIDLE_SPACE: val = 0x00; break;
- case HDLC_TXIDLE_MARK: val = 0xff; break;
+ /* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits
+ * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits
+ */
+ tcr = rd_reg16(info, TCR);
+ if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) {
+ /* disable preamble, set idle size to 16 bits */
+ tcr = (tcr & ~(BIT6 + BIT5)) | BIT4;
+ /* MSB of 16 bit idle specified in tx preamble register (TPR) */
+ wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff));
+ } else if (!(tcr & BIT6)) {
+ /* preamble is disabled, set idle size to 8 bits */
+ tcr &= ~(BIT5 + BIT4);
+ }
+ wr_reg16(info, TCR, tcr);
+
+ if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) {
+ /* LSB of custom tx idle specified in tx idle register */
+ val = (unsigned char)(info->idle_mode & 0xff);
+ } else {
+ /* standard 8 bit idle patterns */
+ switch(info->idle_mode)
+ {
+ case HDLC_TXIDLE_FLAGS: val = 0x7e; break;
+ case HDLC_TXIDLE_ALT_ZEROS_ONES:
+ case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
+ case HDLC_TXIDLE_ZEROS:
+ case HDLC_TXIDLE_SPACE: val = 0x00; break;
+ default: val = 0xff;
+ }
}
wr_reg8(info, TIR, val);
@@ -4313,6 +4339,12 @@ static int rx_get_frame(struct slgt_info *info)
unsigned long flags;
struct tty_struct *tty = info->tty;
unsigned char addr_field = 0xff;
+ unsigned int crc_size = 0;
+
+ switch (info->params.crc_type & HDLC_CRC_MASK) {
+ case HDLC_CRC_16_CCITT: crc_size = 2; break;
+ case HDLC_CRC_32_CCITT: crc_size = 4; break;
+ }
check_again:
@@ -4357,7 +4389,7 @@ check_again:
status = desc_status(info->rbufs[end]);
/* ignore CRC bit if not using CRC (bit is undefined) */
- if (info->params.crc_type == HDLC_CRC_NONE)
+ if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE)
status &= ~BIT1;
if (framesize == 0 ||
@@ -4366,34 +4398,34 @@ check_again:
goto check_again;
}
- if (framesize < 2 || status & (BIT1+BIT0)) {
- if (framesize < 2 || (status & BIT0))
- info->icount.rxshort++;
- else
- info->icount.rxcrc++;
+ if (framesize < (2 + crc_size) || status & BIT0) {
+ info->icount.rxshort++;
framesize = 0;
+ } else if (status & BIT1) {
+ info->icount.rxcrc++;
+ if (!(info->params.crc_type & HDLC_CRC_RETURN_EX))
+ framesize = 0;
+ }
#ifdef CONFIG_HDLC
- {
- struct net_device_stats *stats = hdlc_stats(info->netdev);
- stats->rx_errors++;
- stats->rx_frame_errors++;
- }
-#endif
- } else {
- /* adjust frame size for CRC, if any */
- if (info->params.crc_type == HDLC_CRC_16_CCITT)
- framesize -= 2;
- else if (info->params.crc_type == HDLC_CRC_32_CCITT)
- framesize -= 4;
+ if (framesize == 0) {
+ struct net_device_stats *stats = hdlc_stats(info->netdev);
+ stats->rx_errors++;
+ stats->rx_frame_errors++;
}
+#endif
DBGBH(("%s rx frame status=%04X size=%d\n",
info->device_name, status, framesize));
DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
if (framesize) {
- if (framesize > info->max_frame_size)
+ if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
+ framesize -= crc_size;
+ crc_size = 0;
+ }
+
+ if (framesize > info->max_frame_size + crc_size)
info->icount.rxlong++;
else {
/* copy dma buffer(s) to contiguous temp buffer */
@@ -4413,6 +4445,11 @@ check_again:
i = 0;
}
+ if (info->params.crc_type & HDLC_CRC_RETURN_EX) {
+ *p = (status & BIT1) ? RX_CRC_ERROR : RX_OK;
+ framesize++;
+ }
+
#ifdef CONFIG_HDLC
if (info->netcount)
hdlcdev_rx(info,info->tmp_rbuf, framesize);
@@ -4671,13 +4708,13 @@ static int loopback_test(struct slgt_info *info)
static int adapter_test(struct slgt_info *info)
{
DBGINFO(("testing %s\n", info->device_name));
- if ((info->init_error = register_test(info)) < 0) {
+ if (register_test(info) < 0) {
printk("register test failure %s addr=%08X\n",
info->device_name, info->phys_reg_addr);
- } else if ((info->init_error = irq_test(info)) < 0) {
+ } else if (irq_test(info) < 0) {
printk("IRQ test failure %s IRQ=%d\n",
info->device_name, info->irq_level);
- } else if ((info->init_error = loopback_test(info)) < 0) {
+ } else if (loopback_test(info) < 0) {
printk("loopback test failure %s\n", info->device_name);
}
return info->init_error;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 8587401..21bf15a 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -988,7 +988,7 @@ static int write(struct tty_struct *tty,
if (sanity_check(info, tty->name, "write"))
goto cleanup;
- if (!tty || !info->tx_buf)
+ if (!info->tx_buf)
goto cleanup;
if (info->params.mode == MGSL_MODE_HDLC) {
@@ -1067,7 +1067,7 @@ static void put_char(struct tty_struct *tty, unsigned char ch)
if (sanity_check(info, tty->name, "put_char"))
return;
- if (!tty || !info->tx_buf)
+ if (!info->tx_buf)
return;
spin_lock_irqsave(&info->lock,flags);
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 1e371a5..731c3d5 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -6,8 +6,7 @@
menu "Firmware Drivers"
config EDD
- tristate "BIOS Enhanced Disk Drive calls determine boot disk (EXPERIMENTAL)"
- depends on EXPERIMENTAL
+ tristate "BIOS Enhanced Disk Drive calls determine boot disk"
depends on !IA64
help
Say Y or M here if you want to enable BIOS Enhanced Disk Drive
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 948bd7e..b9e3886 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -255,10 +255,15 @@ void __init dmi_scan_machine(void)
/**
* dmi_check_system - check system DMI data
* @list: array of dmi_system_id structures to match against
+ * All non-null elements of the list must match
+ * their slot's (field index's) data (i.e., each
+ * list string must be a substring of the specified
+ * DMI slot's string data) to be considered a
+ * successful match.
*
* Walk the blacklist table running matching functions until someone
* returns non zero or we hit the end. Callback function is called for
- * each successfull match. Returns the number of matches.
+ * each successful match. Returns the number of matches.
*/
int dmi_check_system(struct dmi_system_id *list)
{
@@ -287,7 +292,7 @@ EXPORT_SYMBOL(dmi_check_system);
/**
* dmi_get_system_info - return DMI data value
- * @field: data index (see enum dmi_filed)
+ * @field: data index (see enum dmi_field)
*
* Returns one DMI data value, can be used to perform
* complex DMI data checks.
@@ -301,13 +306,13 @@ EXPORT_SYMBOL(dmi_get_system_info);
/**
* dmi_find_device - find onboard device by type/name
* @type: device type or %DMI_DEV_TYPE_ANY to match all device types
- * @desc: device name string or %NULL to match all
+ * @name: device name string or %NULL to match all
* @from: previous device found in search, or %NULL for new search.
*
* Iterates through the list of known onboard devices. If a device is
* found with a matching @vendor and @device, a pointer to its device
* structure is returned. Otherwise, %NULL is returned.
- * A new search is initiated by passing %NULL to the @from argument.
+ * A new search is initiated by passing %NULL as the @from argument.
* If @from is not %NULL, searches continue from next device.
*/
struct dmi_device * dmi_find_device(int type, const char *name,
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 6de3cd3..99fa424 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -395,7 +395,8 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
* we cannot reliably check if drive can auto-close
*/
if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
- log = 0;
+ break;
+ log = 1;
break;
case UNIT_ATTENTION:
/*
@@ -417,6 +418,11 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
struct request *failed_command,
struct request_sense *sense)
{
+ unsigned long sector;
+ unsigned long bio_sectors;
+ unsigned long valid;
+ struct cdrom_info *info = drive->driver_data;
+
if (!cdrom_log_sense(drive, failed_command, sense))
return;
@@ -429,6 +435,37 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
if (sense->sense_key == 0x05 && sense->asc == 0x24)
return;
+ if (sense->error_code == 0x70) { /* Current Error */
+ switch(sense->sense_key) {
+ case MEDIUM_ERROR:
+ case VOLUME_OVERFLOW:
+ case ILLEGAL_REQUEST:
+ if (!sense->valid)
+ break;
+ if (failed_command == NULL ||
+ !blk_fs_request(failed_command))
+ break;
+ sector = (sense->information[0] << 24) |
+ (sense->information[1] << 16) |
+ (sense->information[2] << 8) |
+ (sense->information[3]);
+
+ bio_sectors = bio_sectors(failed_command->bio);
+ if (bio_sectors < 4)
+ bio_sectors = 4;
+ if (drive->queue->hardsect_size == 2048)
+ sector <<= 2; /* Device sector size is 2K */
+ sector &= ~(bio_sectors -1);
+ valid = (sector - failed_command->sector) << 9;
+
+ if (valid < 0)
+ valid = 0;
+ if (sector < get_capacity(info->disk) &&
+ drive->probed_capacity - sector < 4 * 75) {
+ set_capacity(info->disk, sector);
+ }
+ }
+ }
#if VERBOSE_IDE_CD_ERRORS
{
int i;
@@ -609,17 +646,23 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
sense = failed->sense;
failed->sense_len = rq->sense_len;
}
-
+ cdrom_analyze_sense_data(drive, failed, sense);
/*
* now end failed request
*/
- spin_lock_irqsave(&ide_lock, flags);
- end_that_request_chunk(failed, 0, failed->data_len);
- end_that_request_last(failed, 0);
- spin_unlock_irqrestore(&ide_lock, flags);
- }
-
- cdrom_analyze_sense_data(drive, failed, sense);
+ if (blk_fs_request(failed)) {
+ if (ide_end_dequeued_request(drive, failed, 0,
+ failed->hard_nr_sectors))
+ BUG();
+ } else {
+ spin_lock_irqsave(&ide_lock, flags);
+ end_that_request_chunk(failed, 0,
+ failed->data_len);
+ end_that_request_last(failed, 0);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ }
+ } else
+ cdrom_analyze_sense_data(drive, NULL, sense);
}
if (!rq->current_nr_sectors && blk_fs_request(rq))
@@ -633,6 +676,13 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
ide_end_request(drive, uptodate, nsectors);
}
+static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
+{
+ if (stat & 0x80)
+ return;
+ ide_dump_status(drive, msg, stat);
+}
+
/* Returns 0 if the request should be continued.
Returns 1 if the request was ended. */
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
@@ -761,16 +811,16 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
sense_key == DATA_PROTECT) {
/* No point in retrying after an illegal
request or data protect error.*/
- ide_dump_status (drive, "command error", stat);
+ ide_dump_status_no_sense (drive, "command error", stat);
do_end_request = 1;
} else if (sense_key == MEDIUM_ERROR) {
/* No point in re-trying a zillion times on a bad
* sector... If we got here the error is not correctable */
- ide_dump_status (drive, "media error (bad sector)", stat);
+ ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
do_end_request = 1;
} else if (sense_key == BLANK_CHECK) {
/* Disk appears blank ?? */
- ide_dump_status (drive, "media error (blank)", stat);
+ ide_dump_status_no_sense (drive, "media error (blank)", stat);
do_end_request = 1;
} else if ((err & ~ABRT_ERR) != 0) {
/* Go to the default handler
@@ -782,13 +832,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
do_end_request = 1;
}
- if (do_end_request)
- cdrom_end_request(drive, 0);
-
- /* If we got a CHECK_CONDITION status,
- queue a request sense command. */
- if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense(drive, NULL, NULL);
+ /* End a request through request sense analysis when we have
+ sense data. We need this in order to perform end of media
+ processing */
+
+ if (do_end_request) {
+ if (stat & ERR_STAT) {
+ unsigned long flags;
+ spin_lock_irqsave(&ide_lock, flags);
+ blkdev_dequeue_request(rq);
+ HWGROUP(drive)->rq = NULL;
+ spin_unlock_irqrestore(&ide_lock, flags);
+
+ cdrom_queue_request_sense(drive, rq->sense, rq);
+ } else
+ cdrom_end_request(drive, 0);
+ } else {
+ /* If we got a CHECK_CONDITION status,
+ queue a request sense command. */
+ if (stat & ERR_STAT)
+ cdrom_queue_request_sense(drive, NULL, NULL);
+ }
} else {
blk_dump_rq_flags(rq, "ide-cd: bad rq");
cdrom_end_request(drive, 0);
@@ -1491,8 +1555,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
}
-static
-int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
{
struct request_sense sense;
int retries = 10;
@@ -2220,6 +2283,9 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->capacity = 0x1fffff;
set_capacity(info->disk, toc->capacity * sectors_per_frame);
+ /* Save a private copy of te TOC capacity for error handling */
+ drive->probed_capacity = toc->capacity * sectors_per_frame;
+
blk_queue_hardsect_size(drive->queue,
sectors_per_frame << SECTOR_BITS);
@@ -2342,6 +2408,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (!stat && (last_written > toc->capacity)) {
toc->capacity = last_written;
set_capacity(info->disk, toc->capacity * sectors_per_frame);
+ drive->probed_capacity = toc->capacity * sectors_per_frame;
}
/* Remember that we've read this stuff. */
@@ -2698,14 +2765,11 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
* any other way to detect this...
*/
if (sense.sense_key == NOT_READY) {
- if (sense.asc == 0x3a) {
- if (sense.ascq == 1)
- return CDS_NO_DISC;
- else if (sense.ascq == 0 || sense.ascq == 2)
- return CDS_TRAY_OPEN;
- }
+ if (sense.asc == 0x3a && sense.ascq == 1)
+ return CDS_NO_DISC;
+ else
+ return CDS_TRAY_OPEN;
}
-
return CDS_DRIVE_NOT_READY;
}
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index a1179e9..4656587 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1284,7 +1284,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n",
rq->rq_status,
- rq->rq_disk ? rq->rq_disk->disk_name ? "?",
+ rq->rq_disk ? rq->rq_disk->disk_name : "?",
rq->flags, rq->errors);
debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
"current_nr_sectors: %d\n", (long)rq->sector,
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 4f2f138..622a55c 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -223,6 +223,63 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
}
/**
+ * ide_end_dequeued_request - complete an IDE I/O
+ * @drive: IDE device for the I/O
+ * @uptodate:
+ * @nr_sectors: number of sectors completed
+ *
+ * Complete an I/O that is no longer on the request queue. This
+ * typically occurs when we pull the request and issue a REQUEST_SENSE.
+ * We must still finish the old request but we must not tamper with the
+ * queue in the meantime.
+ *
+ * NOTE: This path does not handle barrier, but barrier is not supported
+ * on ide-cd anyway.
+ */
+
+int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
+ int uptodate, int nr_sectors)
+{
+ unsigned long flags;
+ int ret = 1;
+
+ spin_lock_irqsave(&ide_lock, flags);
+
+ BUG_ON(!(rq->flags & REQ_STARTED));
+
+ /*
+ * if failfast is set on a request, override number of sectors and
+ * complete the whole request right now
+ */
+ if (blk_noretry_request(rq) && end_io_error(uptodate))
+ nr_sectors = rq->hard_nr_sectors;
+
+ if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+ rq->errors = -EIO;
+
+ /*
+ * decide whether to reenable DMA -- 3 is a random magic for now,
+ * if we DMA timeout more than 3 times, just stay in PIO
+ */
+ if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+ drive->state = 0;
+ HWGROUP(drive)->hwif->ide_dma_on(drive);
+ }
+
+ if (!end_that_request_first(rq, uptodate, nr_sectors)) {
+ add_disk_randomness(rq->rq_disk);
+ if (blk_rq_tagged(rq))
+ blk_queue_end_tag(drive->queue, rq);
+ end_that_request_last(rq, uptodate);
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&ide_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
+
+
+/**
* ide_complete_pm_request - end the current Power Management request
* @drive: target drive
* @rq: request
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index f04791a..09f3a7d 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2646,21 +2646,23 @@ static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape)
return __idetape_kmalloc_stage(tape, 0, 0);
}
-static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
+static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
{
struct idetape_bh *bh = tape->bh;
int count;
+ int ret = 0;
while (n) {
#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_from_user\n");
- return;
+ return 1;
}
#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
- copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count);
+ if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
+ ret = 1;
n -= count;
atomic_add(count, &bh->b_count);
buf += count;
@@ -2671,23 +2673,26 @@ static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t
}
}
tape->bh = bh;
+ return ret;
}
-static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
+static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
{
struct idetape_bh *bh = tape->bh;
int count;
+ int ret = 0;
while (n) {
#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_to_user\n");
- return;
+ return 1;
}
#endif /* IDETAPE_DEBUG_BUGS */
count = min(tape->b_count, n);
- copy_to_user(buf, tape->b_data, count);
+ if (copy_to_user(buf, tape->b_data, count))
+ ret = 1;
n -= count;
tape->b_data += count;
tape->b_count -= count;
@@ -2700,6 +2705,7 @@ static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf,
}
}
}
+ return ret;
}
static void idetape_init_merge_stage (idetape_tape_t *tape)
@@ -3719,6 +3725,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
struct ide_tape_obj *tape = ide_tape_f(file);
ide_drive_t *drive = tape->drive;
ssize_t bytes_read,temp, actually_read = 0, rc;
+ ssize_t ret = 0;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 3)
@@ -3737,7 +3744,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
return (0);
if (tape->merge_stage_size) {
actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count);
- idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read);
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read))
+ ret = -EFAULT;
buf += actually_read;
tape->merge_stage_size -= actually_read;
count -= actually_read;
@@ -3746,7 +3754,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
if (bytes_read <= 0)
goto finish;
- idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read);
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
+ ret = -EFAULT;
buf += bytes_read;
count -= bytes_read;
actually_read += bytes_read;
@@ -3756,7 +3765,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
if (bytes_read <= 0)
goto finish;
temp = min((unsigned long)count, (unsigned long)bytes_read);
- idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp);
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp))
+ ret = -EFAULT;
actually_read += temp;
tape->merge_stage_size = bytes_read-temp;
}
@@ -3769,7 +3779,8 @@ finish:
idetape_space_over_filemarks(drive, MTFSF, 1);
return 0;
}
- return actually_read;
+
+ return (ret) ? ret : actually_read;
}
static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
@@ -3777,7 +3788,8 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
{
struct ide_tape_obj *tape = ide_tape_f(file);
ide_drive_t *drive = tape->drive;
- ssize_t retval, actually_written = 0;
+ ssize_t actually_written = 0;
+ ssize_t ret = 0;
/* The drive is write protected. */
if (tape->write_prot)
@@ -3813,7 +3825,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
* some drives (Seagate STT3401A) will return an error.
*/
if (drive->dsc_overlap) {
- retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
+ ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
if (retval < 0) {
__idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
@@ -3834,12 +3846,14 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
}
#endif /* IDETAPE_DEBUG_BUGS */
actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
- idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written);
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
+ ret = -EFAULT;
buf += actually_written;
tape->merge_stage_size += actually_written;
count -= actually_written;
if (tape->merge_stage_size == tape->stage_size) {
+ ssize_t retval;
tape->merge_stage_size = 0;
retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
if (retval <= 0)
@@ -3847,7 +3861,9 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
}
}
while (count >= tape->stage_size) {
- idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size);
+ ssize_t retval;
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size))
+ ret = -EFAULT;
buf += tape->stage_size;
count -= tape->stage_size;
retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
@@ -3857,10 +3873,11 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
}
if (count) {
actually_written += count;
- idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count);
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count))
+ ret = -EFAULT;
tape->merge_stage_size += count;
}
- return (actually_written);
+ return (ret) ? ret : actually_written;
}
static int idetape_write_filemark (ide_drive_t *drive)
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 79b81be..1867375 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -4,7 +4,7 @@ menu "IEEE 1394 (FireWire) support"
config IEEE1394
tristate "IEEE 1394 (FireWire) support"
- depends on (PCI || BROKEN) && (BROKEN || !FRV)
+ depends on PCI || BROKEN
select NET
help
IEEE 1394 describes a high performance serial bus, which is also
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 948f1b8..50c71e1 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -8,6 +8,7 @@
* directory of the kernel sources for details.
*/
+#include <linux/bitmap.h>
#include <linux/kernel.h>
#include <linux/config.h>
#include <linux/list.h>
@@ -334,10 +335,12 @@ static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribut
static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
+/* tlabels_free, tlabels_allocations, tlabels_mask are read non-atomically
+ * here, therefore displayed values may be occasionally wrong. */
static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf)
{
struct node_entry *ne = container_of(dev, struct node_entry, device);
- return sprintf(buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1);
+ return sprintf(buf, "%d\n", 64 - bitmap_weight(ne->tpool->pool, 64));
}
static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 161afdd..386023c 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -773,8 +773,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
ts->last_msg = m;
- if (request_irq(spi->irq, ads7846_irq,
- SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING,
+ if (request_irq(spi->irq, ads7846_irq, SA_TRIGGER_FALLING,
spi->dev.driver->name, ts)) {
dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
err = -EBUSY;
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
index a18d56b..a595d386 100644
--- a/drivers/input/touchscreen/h3600_ts_input.c
+++ b/drivers/input/touchscreen/h3600_ts_input.c
@@ -399,16 +399,14 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE);
if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler,
- SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
- "h3600_action", &ts->dev)) {
+ SA_SHIRQ | SA_INTERRUPT, "h3600_action", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
err = -EBUSY;
goto fail2;
}
if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
- SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM,
- "h3600_suspend", &ts->dev)) {
+ SA_SHIRQ | SA_INTERRUPT, "h3600_suspend", &ts->dev)) {
printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
err = -EBUSY;
goto fail3;
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index f573d5a..9650998 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -93,5 +93,14 @@ config LEDS_TRIGGER_IDE_DISK
This allows LEDs to be controlled by IDE disk activity.
If unsure, say Y.
+config LEDS_TRIGGER_HEARTBEAT
+ tristate "LED Heartbeat Trigger"
+ depends LEDS_TRIGGERS
+ help
+ This allows LEDs to be controlled by a CPU load average.
+ The flash frequency is a hyperbolic function of the 1-minute
+ load average.
+ If unsure, say Y.
+
endmenu
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index dcea100..88d3b6e 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
+obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
diff --git a/drivers/leds/ledtrig-heartbeat.c b/drivers/leds/ledtrig-heartbeat.c
new file mode 100644
index 0000000..4bf8cec
--- /dev/null
+++ b/drivers/leds/ledtrig-heartbeat.c
@@ -0,0 +1,118 @@
+/*
+ * LED Heartbeat Trigger
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * Based on Richard Purdie's ledtrig-timer.c and some arch's
+ * CONFIG_HEARTBEAT code.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/leds.h>
+#include "leds.h"
+
+struct heartbeat_trig_data {
+ unsigned int phase;
+ unsigned int period;
+ struct timer_list timer;
+};
+
+static void led_heartbeat_function(unsigned long data)
+{
+ struct led_classdev *led_cdev = (struct led_classdev *) data;
+ struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+ unsigned long brightness = LED_OFF;
+ unsigned long delay = 0;
+
+ /* acts like an actual heart beat -- ie thump-thump-pause... */
+ switch (heartbeat_data->phase) {
+ case 0:
+ /*
+ * The hyperbolic function below modifies the
+ * heartbeat period length in dependency of the
+ * current (1min) load. It goes through the points
+ * f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
+ */
+ heartbeat_data->period = 300 +
+ (6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
+ heartbeat_data->period =
+ msecs_to_jiffies(heartbeat_data->period);
+ delay = msecs_to_jiffies(70);
+ heartbeat_data->phase++;
+ brightness = LED_FULL;
+ break;
+ case 1:
+ delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
+ heartbeat_data->phase++;
+ break;
+ case 2:
+ delay = msecs_to_jiffies(70);
+ heartbeat_data->phase++;
+ brightness = LED_FULL;
+ break;
+ default:
+ delay = heartbeat_data->period - heartbeat_data->period / 4 -
+ msecs_to_jiffies(70);
+ heartbeat_data->phase = 0;
+ break;
+ }
+
+ led_set_brightness(led_cdev, brightness);
+ mod_timer(&heartbeat_data->timer, jiffies + delay);
+}
+
+static void heartbeat_trig_activate(struct led_classdev *led_cdev)
+{
+ struct heartbeat_trig_data *heartbeat_data;
+
+ heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
+ if (!heartbeat_data)
+ return;
+
+ led_cdev->trigger_data = heartbeat_data;
+ setup_timer(&heartbeat_data->timer,
+ led_heartbeat_function, (unsigned long) led_cdev);
+ heartbeat_data->phase = 0;
+ led_heartbeat_function(heartbeat_data->timer.data);
+}
+
+static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
+{
+ struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
+
+ if (heartbeat_data) {
+ del_timer_sync(&heartbeat_data->timer);
+ kfree(heartbeat_data);
+ }
+}
+
+static struct led_trigger heartbeat_led_trigger = {
+ .name = "heartbeat",
+ .activate = heartbeat_trig_activate,
+ .deactivate = heartbeat_trig_deactivate,
+};
+
+static int __init heartbeat_trig_init(void)
+{
+ return led_trigger_register(&heartbeat_led_trigger);
+}
+
+static void __exit heartbeat_trig_exit(void)
+{
+ led_trigger_unregister(&heartbeat_led_trigger);
+}
+
+module_init(heartbeat_trig_init);
+module_exit(heartbeat_trig_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Heartbeat LED trigger");
+MODULE_LICENSE("GPL");
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index ccf5df4..37cd6ee 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -99,17 +99,22 @@ config PMAC_MEDIABAY
devices are not fully supported in the bay as I never had one to
try with
-# made a separate option since backlight may end up beeing used
-# on non-powerbook machines (but only on PMU based ones AFAIK)
config PMAC_BACKLIGHT
bool "Backlight control for LCD screens"
depends on ADB_PMU && (BROKEN || !PPC64)
help
- Say Y here to build in code to manage the LCD backlight on a
- Macintosh PowerBook. With this code, the backlight will be turned
- on and off appropriately on power-management and lid-open/lid-closed
- events; also, the PowerBook button device will be enabled so you can
- change the screen brightness.
+ Say Y here to enable Macintosh specific extensions of the generic
+ backlight code. With this enabled, the brightness keys on older
+ PowerBooks will be enabled so you can change the screen brightness.
+ Newer models should use an userspace daemon like pbbuttonsd.
+
+config PMAC_BACKLIGHT_LEGACY
+ bool "Provide legacy ioctl's on /dev/pmu for the backlight"
+ depends on PMAC_BACKLIGHT && (BROKEN || !PPC64)
+ help
+ Say Y if you want to enable legacy ioctl's on /dev/pmu. This is for
+ programs which use this old interface. New and updated programs
+ should use the backlight classes in sysfs.
config ADB_MACIO
bool "Include MacIO (CHRP) ADB driver"
diff --git a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
index 6081acd..8972e53 100644
--- a/drivers/macintosh/Makefile
+++ b/drivers/macintosh/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_INPUT_ADBHID) += adbhid.o
obj-$(CONFIG_ANSLCD) += ans-lcd.o
obj-$(CONFIG_ADB_PMU) += via-pmu.o
+obj-$(CONFIG_PMAC_BACKLIGHT) += via-pmu-backlight.o
obj-$(CONFIG_ADB_CUDA) += via-cuda.o
obj-$(CONFIG_PMAC_APM_EMU) += apm_emu.o
obj-$(CONFIG_PMAC_SMU) += smu.o
diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c
index 394334e..c26e123 100644
--- a/drivers/macintosh/adbhid.c
+++ b/drivers/macintosh/adbhid.c
@@ -503,9 +503,7 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0x1f: /* Powerbook button device */
{
int down = (data[1] == (data[1] & 0xf));
-#ifdef CONFIG_PMAC_BACKLIGHT
- int backlight = get_backlight_level();
-#endif
+
/*
* XXX: Where is the contrast control for the passive?
* -- Cort
@@ -530,29 +528,17 @@ adbhid_buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int auto
case 0xa: /* brightness decrease */
#ifdef CONFIG_PMAC_BACKLIGHT
- if (!disable_kernel_backlight) {
- if (down && backlight >= 0) {
- if (backlight > BACKLIGHT_OFF)
- set_backlight_level(backlight-1);
- else
- set_backlight_level(BACKLIGHT_OFF);
- }
- }
-#endif /* CONFIG_PMAC_BACKLIGHT */
+ if (!disable_kernel_backlight && down)
+ pmac_backlight_key_down();
+#endif
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSDOWN, down);
break;
case 0x9: /* brightness increase */
#ifdef CONFIG_PMAC_BACKLIGHT
- if (!disable_kernel_backlight) {
- if (down && backlight >= 0) {
- if (backlight < BACKLIGHT_MAX)
- set_backlight_level(backlight+1);
- else
- set_backlight_level(BACKLIGHT_MAX);
- }
- }
-#endif /* CONFIG_PMAC_BACKLIGHT */
+ if (!disable_kernel_backlight && down)
+ pmac_backlight_key_up();
+#endif
input_report_key(adbhid[id]->input, KEY_BRIGHTNESSUP, down);
break;
diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
new file mode 100644
index 0000000..b42d05f
--- /dev/null
+++ b/drivers/macintosh/via-pmu-backlight.c
@@ -0,0 +1,150 @@
+/*
+ * Backlight code for via-pmu
+ *
+ * Copyright (C) 1998 Paul Mackerras and Fabio Riccardi.
+ * Copyright (C) 2001-2002 Benjamin Herrenschmidt
+ * Copyright (C) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ */
+
+#include <asm/ptrace.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/backlight.h>
+#include <asm/prom.h>
+
+#define MAX_PMU_LEVEL 0xFF
+
+static struct device_node *vias;
+static struct backlight_properties pmu_backlight_data;
+
+static int pmu_backlight_get_level_brightness(struct fb_info *info,
+ int level)
+{
+ int pmulevel;
+
+ /* Get and convert the value */
+ mutex_lock(&info->bl_mutex);
+ pmulevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_PMU_LEVEL;
+ mutex_unlock(&info->bl_mutex);
+
+ if (pmulevel < 0)
+ pmulevel = 0;
+ else if (pmulevel > MAX_PMU_LEVEL)
+ pmulevel = MAX_PMU_LEVEL;
+
+ return pmulevel;
+}
+
+static int pmu_backlight_update_status(struct backlight_device *bd)
+{
+ struct fb_info *info = class_get_devdata(&bd->class_dev);
+ struct adb_request req;
+ int pmulevel, level = bd->props->brightness;
+
+ if (vias == NULL)
+ return -ENODEV;
+
+ if (bd->props->power != FB_BLANK_UNBLANK ||
+ bd->props->fb_blank != FB_BLANK_UNBLANK)
+ level = 0;
+
+ pmulevel = pmu_backlight_get_level_brightness(info, level);
+
+ pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, pmulevel);
+ pmu_wait_complete(&req);
+
+ pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
+ PMU_POW_BACKLIGHT | (level > 0 ? PMU_POW_ON : PMU_POW_OFF));
+ pmu_wait_complete(&req);
+
+ return 0;
+}
+
+static int pmu_backlight_get_brightness(struct backlight_device *bd)
+{
+ return bd->props->brightness;
+}
+
+static struct backlight_properties pmu_backlight_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = pmu_backlight_get_brightness,
+ .update_status = pmu_backlight_update_status,
+ .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void __init pmu_backlight_init(struct device_node *in_vias)
+{
+ struct backlight_device *bd;
+ struct fb_info *info;
+ char name[10];
+ int level, autosave;
+
+ vias = in_vias;
+
+ /* Special case for the old PowerBook since I can't test on it */
+ autosave =
+ machine_is_compatible("AAPL,3400/2400") ||
+ machine_is_compatible("AAPL,3500");
+
+ if (!autosave &&
+ !pmac_has_backlight_type("pmu") &&
+ !machine_is_compatible("AAPL,PowerBook1998") &&
+ !machine_is_compatible("PowerBook1,1"))
+ return;
+
+ /* Actually, this is a hack, but I don't know of a better way
+ * to get the first framebuffer device.
+ */
+ info = registered_fb[0];
+ if (!info) {
+ printk("pmubl: No framebuffer found\n");
+ goto error;
+ }
+
+ snprintf(name, sizeof(name), "pmubl%d", info->node);
+
+ bd = backlight_device_register(name, info, &pmu_backlight_data);
+ if (IS_ERR(bd)) {
+ printk("pmubl: Backlight registration failed\n");
+ goto error;
+ }
+
+ mutex_lock(&info->bl_mutex);
+ info->bl_dev = bd;
+ fb_bl_default_curve(info, 0x7F, 0x46, 0x0E);
+ mutex_unlock(&info->bl_mutex);
+
+ level = pmu_backlight_data.max_brightness;
+
+ if (autosave) {
+ /* read autosaved value if available */
+ struct adb_request req;
+ pmu_request(&req, NULL, 2, 0xd9, 0);
+ pmu_wait_complete(&req);
+
+ mutex_lock(&info->bl_mutex);
+ level = pmac_backlight_curve_lookup(info,
+ (req.reply[0] >> 4) *
+ pmu_backlight_data.max_brightness / 15);
+ mutex_unlock(&info->bl_mutex);
+ }
+
+ up(&bd->sem);
+ bd->props->brightness = level;
+ bd->props->power = FB_BLANK_UNBLANK;
+ bd->props->update_status(bd);
+ down(&bd->sem);
+
+ mutex_lock(&pmac_backlight_mutex);
+ if (!pmac_backlight)
+ pmac_backlight = bd;
+ mutex_unlock(&pmac_backlight_mutex);
+
+ printk("pmubl: Backlight initialized (%s)\n", name);
+
+ return;
+
+error:
+ return;
+}
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index c63d4e7..2a355ae5 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -144,7 +144,6 @@ static int data_index;
static int data_len;
static volatile int adb_int_pending;
static volatile int disable_poll;
-static struct adb_request bright_req_1, bright_req_2;
static struct device_node *vias;
static int pmu_kind = PMU_UNKNOWN;
static int pmu_fully_inited = 0;
@@ -161,7 +160,7 @@ static int drop_interrupts;
#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
static int option_lid_wakeup = 1;
#endif /* CONFIG_PM && CONFIG_PPC32 */
-#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT)
+#if (defined(CONFIG_PM)&&defined(CONFIG_PPC32))||defined(CONFIG_PMAC_BACKLIGHT_LEGACY)
static int sleep_in_progress;
#endif
static unsigned long async_req_locks;
@@ -208,10 +207,6 @@ static int proc_get_info(char *page, char **start, off_t off,
int count, int *eof, void *data);
static int proc_get_irqstats(char *page, char **start, off_t off,
int count, int *eof, void *data);
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int pmu_set_backlight_level(int level, void* data);
-static int pmu_set_backlight_enable(int on, int level, void* data);
-#endif /* CONFIG_PMAC_BACKLIGHT */
static void pmu_pass_intr(unsigned char *data, int len);
static int proc_get_batt(char *page, char **start, off_t off,
int count, int *eof, void *data);
@@ -292,13 +287,6 @@ static char *pbook_type[] = {
"Core99"
};
-#ifdef CONFIG_PMAC_BACKLIGHT
-static struct backlight_controller pmu_backlight_controller = {
- pmu_set_backlight_enable,
- pmu_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
int __init find_via_pmu(void)
{
u64 taddr;
@@ -417,8 +405,6 @@ static int __init via_pmu_start(void)
if (vias == NULL)
return -ENODEV;
- bright_req_1.complete = 1;
- bright_req_2.complete = 1;
batt_req.complete = 1;
#ifndef CONFIG_PPC_MERGE
@@ -483,9 +469,9 @@ static int __init via_pmu_dev_init(void)
return -ENODEV;
#ifdef CONFIG_PMAC_BACKLIGHT
- /* Enable backlight */
- register_backlight_controller(&pmu_backlight_controller, NULL, "pmu");
-#endif /* CONFIG_PMAC_BACKLIGHT */
+ /* Initialize backlight */
+ pmu_backlight_init(vias);
+#endif
#ifdef CONFIG_PPC32
if (machine_is_compatible("AAPL,3400/2400") ||
@@ -1424,7 +1410,7 @@ next:
#ifdef CONFIG_INPUT_ADBHID
if (!disable_kernel_backlight)
#endif /* CONFIG_INPUT_ADBHID */
- set_backlight_level(data[1] >> 4);
+ pmac_backlight_set_legacy_brightness(data[1] >> 4);
#endif /* CONFIG_PMAC_BACKLIGHT */
}
/* Tick interrupt */
@@ -1674,61 +1660,6 @@ gpio1_interrupt(int irq, void *arg, struct pt_regs *regs)
return IRQ_NONE;
}
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight_to_bright[] = {
- 0x7f, 0x46, 0x42, 0x3e, 0x3a, 0x36, 0x32, 0x2e,
- 0x2a, 0x26, 0x22, 0x1e, 0x1a, 0x16, 0x12, 0x0e
-};
-
-static int
-pmu_set_backlight_enable(int on, int level, void* data)
-{
- struct adb_request req;
-
- if (vias == NULL)
- return -ENODEV;
-
- if (on) {
- pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT,
- backlight_to_bright[level]);
- pmu_wait_complete(&req);
- }
- pmu_request(&req, NULL, 2, PMU_POWER_CTRL,
- PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF));
- pmu_wait_complete(&req);
-
- return 0;
-}
-
-static void
-pmu_bright_complete(struct adb_request *req)
-{
- if (req == &bright_req_1)
- clear_bit(1, &async_req_locks);
- if (req == &bright_req_2)
- clear_bit(2, &async_req_locks);
-}
-
-static int
-pmu_set_backlight_level(int level, void* data)
-{
- if (vias == NULL)
- return -ENODEV;
-
- if (test_and_set_bit(1, &async_req_locks))
- return -EAGAIN;
- pmu_request(&bright_req_1, pmu_bright_complete, 2, PMU_BACKLIGHT_BRIGHT,
- backlight_to_bright[level]);
- if (test_and_set_bit(2, &async_req_locks))
- return -EAGAIN;
- pmu_request(&bright_req_2, pmu_bright_complete, 2, PMU_POWER_CTRL,
- PMU_POW_BACKLIGHT | (level > BACKLIGHT_OFF ?
- PMU_POW_ON : PMU_POW_OFF));
-
- return 0;
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
void
pmu_enable_irled(int on)
{
@@ -2145,9 +2076,8 @@ pmac_suspend_devices(void)
return -EBUSY;
}
- /* Wait for completion of async backlight requests */
- while (!bright_req_1.complete || !bright_req_2.complete ||
- !batt_req.complete)
+ /* Wait for completion of async requests */
+ while (!batt_req.complete)
pmu_poll();
/* Giveup the lazy FPU & vec so we don't have to back them
@@ -2678,26 +2608,34 @@ pmu_ioctl(struct inode * inode, struct file *filp,
return put_user(1, argp);
#endif /* CONFIG_PM && CONFIG_PPC32 */
-#ifdef CONFIG_PMAC_BACKLIGHT
- /* Backlight should have its own device or go via
- * the fbdev
- */
+#ifdef CONFIG_PMAC_BACKLIGHT_LEGACY
+ /* Compatibility ioctl's for backlight */
case PMU_IOC_GET_BACKLIGHT:
+ {
+ int brightness;
+
if (sleep_in_progress)
return -EBUSY;
- error = get_backlight_level();
- if (error < 0)
- return error;
- return put_user(error, argp);
+
+ brightness = pmac_backlight_get_legacy_brightness();
+ if (brightness < 0)
+ return brightness;
+ else
+ return put_user(brightness, argp);
+
+ }
case PMU_IOC_SET_BACKLIGHT:
{
- __u32 value;
+ int brightness;
+
if (sleep_in_progress)
return -EBUSY;
- error = get_user(value, argp);
- if (!error)
- error = set_backlight_level(value);
- break;
+
+ error = get_user(brightness, argp);
+ if (error)
+ return error;
+
+ return pmac_backlight_set_legacy_brightness(brightness);
}
#ifdef CONFIG_INPUT_ADBHID
case PMU_IOC_GRAB_BACKLIGHT: {
@@ -2713,7 +2651,7 @@ pmu_ioctl(struct inode * inode, struct file *filp,
return 0;
}
#endif /* CONFIG_INPUT_ADBHID */
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#endif /* CONFIG_PMAC_BACKLIGHT_LEGACY */
case PMU_IOC_GET_MODEL:
return put_user(pmu_kind, argp);
case PMU_IOC_HAS_ADB:
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 844fa74..2a0d538 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1105,7 +1105,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
return ret;
/* We get a patch from userspace */
- IRDA_MESSAGE("%s(): Received firmware %s (%u bytes)\n",
+ IRDA_MESSAGE("%s(): Received firmware %s (%zu bytes)\n",
__FUNCTION__, stir421x_fw_name, fw->size);
ret = -EINVAL;
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index d4c0002..a2fad50 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -55,7 +55,7 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.ne
/* sun3/60 addr/irq for the lance chip. If your sun is different,
change this. */
#define LANCE_OBIO 0x120000
-#define LANCE_IRQ IRQ3
+#define LANCE_IRQ IRQ_AUTO_3
/* Debug level:
* 0 = silent, print only serious errors
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 22e7940..7628c2d 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -60,9 +60,9 @@
static const char* version = "SDLA driver v0.30, 12 Sep 1996, mike.mclagan@linux.org";
-static unsigned int valid_port[] __initdata = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390};
+static unsigned int valid_port[] = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390};
-static unsigned int valid_mem[] __initdata = {
+static unsigned int valid_mem[] = {
0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000,
0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000,
0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000,
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index b2e8e49..43e521e 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -108,10 +108,10 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v
return 0;
/* FIXME: should we process all CPU buffers ? */
- down(&buffer_sem);
+ mutex_lock(&buffer_mutex);
add_event_entry(ESCAPE_CODE);
add_event_entry(MODULE_LOADED_CODE);
- up(&buffer_sem);
+ mutex_unlock(&buffer_mutex);
#endif
return 0;
}
@@ -501,7 +501,7 @@ void sync_buffer(int cpu)
sync_buffer_state state = sb_buffer_start;
unsigned long available;
- down(&buffer_sem);
+ mutex_lock(&buffer_mutex);
add_cpu_switch(cpu);
@@ -550,5 +550,5 @@ void sync_buffer(int cpu)
mark_done(cpu);
- up(&buffer_sem);
+ mutex_unlock(&buffer_mutex);
}
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index b80318f..04d6417 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -24,7 +24,7 @@
#include "event_buffer.h"
#include "oprofile_stats.h"
-DECLARE_MUTEX(buffer_sem);
+DEFINE_MUTEX(buffer_mutex);
static unsigned long buffer_opened;
static DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
@@ -32,7 +32,7 @@ static unsigned long * event_buffer;
static unsigned long buffer_size;
static unsigned long buffer_watershed;
static size_t buffer_pos;
-/* atomic_t because wait_event checks it outside of buffer_sem */
+/* atomic_t because wait_event checks it outside of buffer_mutex */
static atomic_t buffer_ready = ATOMIC_INIT(0);
/* Add an entry to the event buffer. When we
@@ -60,10 +60,10 @@ void add_event_entry(unsigned long value)
*/
void wake_up_buffer_waiter(void)
{
- down(&buffer_sem);
+ mutex_lock(&buffer_mutex);
atomic_set(&buffer_ready, 1);
wake_up(&buffer_wait);
- up(&buffer_sem);
+ mutex_unlock(&buffer_mutex);
}
@@ -162,7 +162,7 @@ static ssize_t event_buffer_read(struct file * file, char __user * buf,
if (!atomic_read(&buffer_ready))
return -EAGAIN;
- down(&buffer_sem);
+ mutex_lock(&buffer_mutex);
atomic_set(&buffer_ready, 0);
@@ -177,7 +177,7 @@ static ssize_t event_buffer_read(struct file * file, char __user * buf,
buffer_pos = 0;
out:
- up(&buffer_sem);
+ mutex_unlock(&buffer_mutex);
return retval;
}
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 0180236..9241627 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -11,7 +11,7 @@
#define EVENT_BUFFER_H
#include <linux/types.h>
-#include <asm/semaphore.h>
+#include <asm/mutex.h>
int alloc_event_buffer(void);
@@ -46,6 +46,6 @@ extern struct file_operations event_buffer_fops;
/* mutex between sync_cpu_buffers() and the
* file reading code.
*/
-extern struct semaphore buffer_sem;
+extern struct mutex buffer_mutex;
#endif /* EVENT_BUFFER_H */
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
index b3f1cd6..e5162a6 100644
--- a/drivers/oprofile/oprof.c
+++ b/drivers/oprofile/oprof.c
@@ -12,7 +12,7 @@
#include <linux/init.h>
#include <linux/oprofile.h>
#include <linux/moduleparam.h>
-#include <asm/semaphore.h>
+#include <asm/mutex.h>
#include "oprof.h"
#include "event_buffer.h"
@@ -25,7 +25,7 @@ struct oprofile_operations oprofile_ops;
unsigned long oprofile_started;
unsigned long backtrace_depth;
static unsigned long is_setup;
-static DECLARE_MUTEX(start_sem);
+static DEFINE_MUTEX(start_mutex);
/* timer
0 - use performance monitoring hardware if available
@@ -37,7 +37,7 @@ int oprofile_setup(void)
{
int err;
- down(&start_sem);
+ mutex_lock(&start_mutex);
if ((err = alloc_cpu_buffers()))
goto out;
@@ -57,7 +57,7 @@ int oprofile_setup(void)
goto out3;
is_setup = 1;
- up(&start_sem);
+ mutex_unlock(&start_mutex);
return 0;
out3:
@@ -68,7 +68,7 @@ out2:
out1:
free_cpu_buffers();
out:
- up(&start_sem);
+ mutex_unlock(&start_mutex);
return err;
}
@@ -78,7 +78,7 @@ int oprofile_start(void)
{
int err = -EINVAL;
- down(&start_sem);
+ mutex_lock(&start_mutex);
if (!is_setup)
goto out;
@@ -95,7 +95,7 @@ int oprofile_start(void)
oprofile_started = 1;
out:
- up(&start_sem);
+ mutex_unlock(&start_mutex);
return err;
}
@@ -103,7 +103,7 @@ out:
/* echo 0>/dev/oprofile/enable */
void oprofile_stop(void)
{
- down(&start_sem);
+ mutex_lock(&start_mutex);
if (!oprofile_started)
goto out;
oprofile_ops.stop();
@@ -111,20 +111,20 @@ void oprofile_stop(void)
/* wake up the daemon to read what remains */
wake_up_buffer_waiter();
out:
- up(&start_sem);
+ mutex_unlock(&start_mutex);
}
void oprofile_shutdown(void)
{
- down(&start_sem);
+ mutex_lock(&start_mutex);
sync_stop();
if (oprofile_ops.shutdown)
oprofile_ops.shutdown();
is_setup = 0;
free_event_buffer();
free_cpu_buffers();
- up(&start_sem);
+ mutex_unlock(&start_mutex);
}
@@ -132,7 +132,7 @@ int oprofile_set_backtrace(unsigned long val)
{
int err = 0;
- down(&start_sem);
+ mutex_lock(&start_mutex);
if (oprofile_started) {
err = -EBUSY;
@@ -147,7 +147,7 @@ int oprofile_set_backtrace(unsigned long val)
backtrace_depth = val;
out:
- up(&start_sem);
+ mutex_unlock(&start_mutex);
return err;
}
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 4d8dc27..c7fa28a 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -136,6 +136,18 @@ config PARPORT_SUNBPP
found on many Sun machines. Note that many of the newer Ultras
actually have pc style hardware instead.
+config PARPORT_AX88796
+ tristate "AX88796 Parallel Port"
+ depends on PARPORT
+ select PARPORT_NOT_PC
+ help
+ Say Y here if you need support for the parallel port hardware on
+ the AX88796 network controller chip. This code is also available
+ as a module (say M), called parport_ax88796.
+
+ The driver is not dependant on the AX88796 network driver, and
+ should not interfere with the networking functions of the chip.
+
config PARPORT_1284
bool "IEEE 1284 transfer modes"
depends on PARPORT
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile
index a19de35..696b8d4 100644
--- a/drivers/parport/Makefile
+++ b/drivers/parport/Makefile
@@ -17,4 +17,5 @@ obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o
obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o
obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o
obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o
-obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o
+obj-$(CONFIG_PARPORT_AX88796) += parport_ax88796.o
+obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o \ No newline at end of file
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c
index 9ee6732..fd41e28 100644
--- a/drivers/parport/daisy.c
+++ b/drivers/parport/daisy.c
@@ -283,7 +283,7 @@ void parport_close (struct pardevice *dev)
*
* This tries to locate a device on the given parallel port,
* multiplexor port and daisy chain address, and returns its
- * device number or -NXIO if no device with those coordinates
+ * device number or %-ENXIO if no device with those coordinates
* exists.
**/
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c
new file mode 100644
index 0000000..4baa719
--- /dev/null
+++ b/drivers/parport/parport_ax88796.c
@@ -0,0 +1,443 @@
+/* linux/drivers/parport/parport_ax88796.c
+ *
+ * (c) 2005,2006 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/parport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define AX_SPR_BUSY (1<<7)
+#define AX_SPR_ACK (1<<6)
+#define AX_SPR_PE (1<<5)
+#define AX_SPR_SLCT (1<<4)
+#define AX_SPR_ERR (1<<3)
+
+#define AX_CPR_nDOE (1<<5)
+#define AX_CPR_SLCTIN (1<<3)
+#define AX_CPR_nINIT (1<<2)
+#define AX_CPR_ATFD (1<<1)
+#define AX_CPR_STRB (1<<0)
+
+struct ax_drvdata {
+ struct parport *parport;
+ struct parport_state suspend;
+
+ struct device *dev;
+ struct resource *io;
+
+ unsigned char irq_enabled;
+
+ void __iomem *base;
+ void __iomem *spp_data;
+ void __iomem *spp_spr;
+ void __iomem *spp_cpr;
+};
+
+static inline struct ax_drvdata *pp_to_drv(struct parport *p)
+{
+ return p->private_data;
+}
+
+static unsigned char
+parport_ax88796_read_data(struct parport *p)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+
+ return readb(dd->spp_data);
+}
+
+static void
+parport_ax88796_write_data(struct parport *p, unsigned char data)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+
+ writeb(data, dd->spp_data);
+}
+
+static unsigned char
+parport_ax88796_read_control(struct parport *p)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ unsigned int cpr = readb(dd->spp_cpr);
+ unsigned int ret = 0;
+
+ if (!(cpr & AX_CPR_STRB))
+ ret |= PARPORT_CONTROL_STROBE;
+
+ if (!(cpr & AX_CPR_ATFD))
+ ret |= PARPORT_CONTROL_AUTOFD;
+
+ if (cpr & AX_CPR_nINIT)
+ ret |= PARPORT_CONTROL_INIT;
+
+ if (!(cpr & AX_CPR_SLCTIN))
+ ret |= PARPORT_CONTROL_SELECT;
+
+ return ret;
+}
+
+static void
+parport_ax88796_write_control(struct parport *p, unsigned char control)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ unsigned int cpr = readb(dd->spp_cpr);
+
+ cpr &= AX_CPR_nDOE;
+
+ if (!(control & PARPORT_CONTROL_STROBE))
+ cpr |= AX_CPR_STRB;
+
+ if (!(control & PARPORT_CONTROL_AUTOFD))
+ cpr |= AX_CPR_ATFD;
+
+ if (control & PARPORT_CONTROL_INIT)
+ cpr |= AX_CPR_nINIT;
+
+ if (!(control & PARPORT_CONTROL_SELECT))
+ cpr |= AX_CPR_SLCTIN;
+
+ dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr);
+ writeb(cpr, dd->spp_cpr);
+
+ if (parport_ax88796_read_control(p) != control) {
+ dev_err(dd->dev, "write_control: read != set (%02x, %02x)\n",
+ parport_ax88796_read_control(p), control);
+ }
+}
+
+static unsigned char
+parport_ax88796_read_status(struct parport *p)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ unsigned int status = readb(dd->spp_spr);
+ unsigned int ret = 0;
+
+ if (status & AX_SPR_BUSY)
+ ret |= PARPORT_STATUS_BUSY;
+
+ if (status & AX_SPR_ACK)
+ ret |= PARPORT_STATUS_ACK;
+
+ if (status & AX_SPR_ERR)
+ ret |= PARPORT_STATUS_ERROR;
+
+ if (status & AX_SPR_SLCT)
+ ret |= PARPORT_STATUS_SELECT;
+
+ if (status & AX_SPR_PE)
+ ret |= PARPORT_STATUS_PAPEROUT;
+
+ return ret;
+}
+
+static unsigned char
+parport_ax88796_frob_control(struct parport *p, unsigned char mask,
+ unsigned char val)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ unsigned char old = parport_ax88796_read_control(p);
+
+ dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n",
+ mask, val, old);
+
+ parport_ax88796_write_control(p, (old & ~mask) | val);
+ return old;
+}
+
+static void
+parport_ax88796_enable_irq(struct parport *p)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (!dd->irq_enabled) {
+ enable_irq(p->irq);
+ dd->irq_enabled = 1;
+ }
+ local_irq_restore(flags);
+}
+
+static void
+parport_ax88796_disable_irq(struct parport *p)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ if (dd->irq_enabled) {
+ disable_irq(p->irq);
+ dd->irq_enabled = 0;
+ }
+ local_irq_restore(flags);
+}
+
+static void
+parport_ax88796_data_forward(struct parport *p)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ void __iomem *cpr = dd->spp_cpr;
+
+ writeb((readb(cpr) & ~AX_CPR_nDOE), cpr);
+}
+
+static void
+parport_ax88796_data_reverse(struct parport *p)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+ void __iomem *cpr = dd->spp_cpr;
+
+ writeb(readb(cpr) | AX_CPR_nDOE, cpr);
+}
+
+static void
+parport_ax88796_init_state(struct pardevice *d, struct parport_state *s)
+{
+ struct ax_drvdata *dd = pp_to_drv(d->port);
+
+ memset(s, 0, sizeof(struct parport_state));
+
+ dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s);
+ s->u.ax88796.cpr = readb(dd->spp_cpr);
+}
+
+static void
+parport_ax88796_save_state(struct parport *p, struct parport_state *s)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+
+ dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s);
+ s->u.ax88796.cpr = readb(dd->spp_cpr);
+}
+
+static void
+parport_ax88796_restore_state(struct parport *p, struct parport_state *s)
+{
+ struct ax_drvdata *dd = pp_to_drv(p);
+
+ dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s);
+ writeb(s->u.ax88796.cpr, dd->spp_cpr);
+}
+
+static irqreturn_t
+parport_ax88796_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ parport_generic_irq(irq, dev_id, regs);
+ return IRQ_HANDLED;
+}
+
+
+static struct parport_operations parport_ax88796_ops = {
+ .write_data = parport_ax88796_write_data,
+ .read_data = parport_ax88796_read_data,
+
+ .write_control = parport_ax88796_write_control,
+ .read_control = parport_ax88796_read_control,
+ .frob_control = parport_ax88796_frob_control,
+
+ .read_status = parport_ax88796_read_status,
+
+ .enable_irq = parport_ax88796_enable_irq,
+ .disable_irq = parport_ax88796_disable_irq,
+
+ .data_forward = parport_ax88796_data_forward,
+ .data_reverse = parport_ax88796_data_reverse,
+
+ .init_state = parport_ax88796_init_state,
+ .save_state = parport_ax88796_save_state,
+ .restore_state = parport_ax88796_restore_state,
+
+ .epp_write_data = parport_ieee1284_epp_write_data,
+ .epp_read_data = parport_ieee1284_epp_read_data,
+ .epp_write_addr = parport_ieee1284_epp_write_addr,
+ .epp_read_addr = parport_ieee1284_epp_read_addr,
+
+ .ecp_write_data = parport_ieee1284_ecp_write_data,
+ .ecp_read_data = parport_ieee1284_ecp_read_data,
+ .ecp_write_addr = parport_ieee1284_ecp_write_addr,
+
+ .compat_write_data = parport_ieee1284_write_compat,
+ .nibble_read_data = parport_ieee1284_read_nibble,
+ .byte_read_data = parport_ieee1284_read_byte,
+
+ .owner = THIS_MODULE,
+};
+
+static int parport_ax88796_probe(struct platform_device *pdev)
+{
+ struct device *_dev = &pdev->dev;
+ struct ax_drvdata *dd;
+ struct parport *pp = NULL;
+ struct resource *res;
+ unsigned long size;
+ int spacing;
+ int irq;
+ int ret;
+
+ dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL);
+ if (dd == NULL) {
+ dev_err(_dev, "no memory for private data\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(_dev, "no MEM specified\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ size = (res->end - res->start) + 1;
+ spacing = size / 3;
+
+ dd->io = request_mem_region(res->start, size, pdev->name);
+ if (dd->io == NULL) {
+ dev_err(_dev, "cannot reserve memory\n");
+ ret = -ENXIO;
+ goto exit_mem;
+ }
+
+ dd->base = ioremap(res->start, size);
+ if (dd->base == NULL) {
+ dev_err(_dev, "cannot ioremap region\n");
+ ret = -ENXIO;
+ goto exit_res;
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0)
+ irq = PARPORT_IRQ_NONE;
+
+ pp = parport_register_port((unsigned long)dd->base, irq,
+ PARPORT_DMA_NONE,
+ &parport_ax88796_ops);
+
+ if (pp == NULL) {
+ dev_err(_dev, "failed to register parallel port\n");
+ ret = -ENOMEM;
+ goto exit_unmap;
+ }
+
+ pp->private_data = dd;
+ dd->parport = pp;
+ dd->dev = _dev;
+
+ dd->spp_data = dd->base;
+ dd->spp_spr = dd->base + (spacing * 1);
+ dd->spp_cpr = dd->base + (spacing * 2);
+
+ /* initialise the port controls */
+ writeb(AX_CPR_STRB, dd->spp_cpr);
+
+ if (irq >= 0) {
+ /* request irq */
+ ret = request_irq(irq, parport_ax88796_interrupt,
+ SA_TRIGGER_FALLING, pdev->name, pp);
+
+ if (ret < 0)
+ goto exit_port;
+
+ dd->irq_enabled = 1;
+ }
+
+ platform_set_drvdata(pdev, pp);
+
+ dev_info(_dev, "attached parallel port driver\n");
+ parport_announce_port(pp);
+
+ return 0;
+
+ exit_port:
+ parport_remove_port(pp);
+ exit_unmap:
+ iounmap(dd->base);
+ exit_res:
+ release_resource(dd->io);
+ kfree(dd->io);
+ exit_mem:
+ kfree(dd);
+ return ret;
+}
+
+static int parport_ax88796_remove(struct platform_device *pdev)
+{
+ struct parport *p = platform_get_drvdata(pdev);
+ struct ax_drvdata *dd = pp_to_drv(p);
+
+ free_irq(p->irq, p);
+ parport_remove_port(p);
+ iounmap(dd->base);
+ release_resource(dd->io);
+ kfree(dd->io);
+ kfree(dd);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+static int parport_ax88796_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ struct parport *p = platform_get_drvdata(dev);
+ struct ax_drvdata *dd = pp_to_drv(p);
+
+ parport_ax88796_save_state(p, &dd->suspend);
+ writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr);
+ return 0;
+}
+
+static int parport_ax88796_resume(struct platform_device *dev)
+{
+ struct parport *p = platform_get_drvdata(dev);
+ struct ax_drvdata *dd = pp_to_drv(p);
+
+ parport_ax88796_restore_state(p, &dd->suspend);
+ return 0;
+}
+
+#else
+#define parport_ax88796_suspend NULL
+#define parport_ax88796_resume NULL
+#endif
+
+static struct platform_driver axdrv = {
+ .driver = {
+ .name = "ax88796-pp",
+ .owner = THIS_MODULE,
+ },
+ .probe = parport_ax88796_probe,
+ .remove = parport_ax88796_remove,
+ .suspend = parport_ax88796_suspend,
+ .resume = parport_ax88796_resume,
+};
+
+static int __init parport_ax88796_init(void)
+{
+ return platform_driver_register(&axdrv);
+}
+
+static void __exit parport_ax88796_exit(void)
+{
+ platform_driver_unregister(&axdrv);
+}
+
+module_init(parport_ax88796_init)
+module_exit(parport_ax88796_exit)
+
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("AX88796 Parport parallel port driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index bbbfd79..2cb22c8 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -218,7 +218,7 @@ static void free_port (struct parport *port)
* parport_get_port - increment a port's reference count
* @port: the port
*
- * This ensure's that a struct parport pointer remains valid
+ * This ensures that a struct parport pointer remains valid
* until the matching parport_put_port() call.
**/
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index bb19c64..0b4adcb 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -60,30 +60,34 @@ static void card_remove_first(struct pnp_dev * dev)
card_remove(dev);
}
-static int card_probe(struct pnp_card * card, struct pnp_card_driver * drv)
+static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
{
- const struct pnp_card_device_id *id = match_card(drv,card);
- if (id) {
- struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link));
- if (!clink)
- return 0;
- clink->card = card;
- clink->driver = drv;
- clink->pm_state = PMSG_ON;
- if (drv->probe) {
- if (drv->probe(clink, id)>=0)
- return 1;
- else {
- struct pnp_dev * dev;
- card_for_each_dev(card, dev) {
- if (dev->card_link == clink)
- pnp_release_card_device(dev);
- }
- kfree(clink);
- }
- } else
- return 1;
+ const struct pnp_card_device_id *id;
+ struct pnp_card_link *clink;
+ struct pnp_dev *dev;
+
+ if (!drv->probe)
+ return 0;
+ id = match_card(drv,card);
+ if (!id)
+ return 0;
+
+ clink = pnp_alloc(sizeof(*clink));
+ if (!clink)
+ return 0;
+ clink->card = card;
+ clink->driver = drv;
+ clink->pm_state = PMSG_ON;
+
+ if (drv->probe(clink, id) >= 0)
+ return 1;
+
+ /* Recovery */
+ card_for_each_dev(card, dev) {
+ if (dev->card_link == clink)
+ pnp_release_card_device(dev);
}
+ kfree(clink);
return 0;
}
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 65d090d..bccff40 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -73,6 +73,13 @@ config RTC_INTF_DEV
This driver can also be built as a module. If so, the module
will be called rtc-dev.
+config RTC_INTF_DEV_UIE_EMUL
+ bool "RTC UIE emulation on dev interface"
+ depends on RTC_INTF_DEV
+ help
+ Provides an emulation for RTC_UIE if the underlaying rtc chip
+ driver did not provide RTC_UIE ioctls.
+
comment "RTC drivers"
depends on RTC_CLASS
@@ -86,6 +93,34 @@ config RTC_DRV_X1205
This driver can also be built as a module. If so, the module
will be called rtc-x1205.
+config RTC_DRV_DS1307
+ tristate "Dallas/Maxim DS1307 and similar I2C RTC chips"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for various compatible RTC
+ chips (often with battery backup) connected with I2C. This driver
+ should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00,
+ and probably other chips. In some cases the RTC must already
+ have been initialized (by manufacturing or a bootloader).
+
+ The first seven registers on these chips hold an RTC, and other
+ registers may add features such as NVRAM, a trickle charger for
+ the RTC/NVRAM backup power, and alarms. This driver may not
+ expose all those available chip features.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1307.
+
+config RTC_DRV_DS1553
+ tristate "Dallas DS1553"
+ depends on RTC_CLASS
+ help
+ If you say yes here you get support for the
+ Dallas DS1553 timekeeping chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1553.
+
config RTC_DRV_DS1672
tristate "Dallas/Maxim DS1672"
depends on RTC_CLASS && I2C
@@ -96,6 +131,16 @@ config RTC_DRV_DS1672
This driver can also be built as a module. If so, the module
will be called rtc-ds1672.
+config RTC_DRV_DS1742
+ tristate "Dallas DS1742"
+ depends on RTC_CLASS
+ help
+ If you say yes here you get support for the
+ Dallas DS1742 timekeeping chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ds1742.
+
config RTC_DRV_PCF8563
tristate "Philips PCF8563/Epson RTC8564"
depends on RTC_CLASS && I2C
@@ -107,6 +152,16 @@ config RTC_DRV_PCF8563
This driver can also be built as a module. If so, the module
will be called rtc-pcf8563.
+config RTC_DRV_PCF8583
+ tristate "Philips PCF8583"
+ depends on RTC_CLASS && I2C
+ help
+ If you say yes here you get support for the
+ Philips PCF8583 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-pcf8583.
+
config RTC_DRV_RS5C372
tristate "Ricoh RS5C372A/B"
depends on RTC_CLASS && I2C
@@ -157,6 +212,22 @@ config RTC_DRV_VR41XX
To compile this driver as a module, choose M here: the
module will be called rtc-vr41xx.
+config RTC_DRV_PL031
+ tristate "ARM AMBA PL031 RTC"
+ depends on RTC_CLASS && ARM_AMBA
+ help
+ If you say Y here you will get access to ARM AMBA
+ PrimeCell PL031 UART found on certain ARM SOCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called rtc-pl031.
+
+config RTC_DRV_AT91
+ tristate "AT91RM9200"
+ depends on RTC_CLASS && ARCH_AT91RM9200
+ help
+ Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock).
+
config RTC_DRV_TEST
tristate "Test driver/device"
depends on RTC_CLASS
@@ -172,4 +243,24 @@ config RTC_DRV_TEST
This driver can also be built as a module. If so, the module
will be called rtc-test.
+config RTC_DRV_MAX6902
+ tristate "Maxim 6902"
+ depends on RTC_CLASS && SPI
+ help
+ If you say yes here you will get support for the
+ Maxim MAX6902 spi RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-max6902.
+
+config RTC_DRV_V3020
+ tristate "EM Microelectronic V3020"
+ depends on RTC_CLASS
+ help
+ If you say yes here you will get support for the
+ EM Microelectronic v3020 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-v3020.
+
endmenu
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index a9ca0f1..900d210 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -13,10 +13,18 @@ obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
+obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o
obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
+obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
+obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
+obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o
obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
+obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
+obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
+obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
+obj-$(CONFIG_RTC_DRV_AT91) += rtc-at91.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 413c7d5..5396bee 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -69,6 +69,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
rtc->id = id;
rtc->ops = ops;
rtc->owner = owner;
+ rtc->max_user_freq = 64;
rtc->class_dev.dev = dev;
rtc->class_dev.class = rtc_class;
rtc->class_dev.release = rtc_device_release;
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 56e4907..579cd66 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -229,6 +229,9 @@ int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int
unsigned long flags;
struct rtc_device *rtc = to_rtc_device(class_dev);
+ if (rtc->ops->irq_set_state == NULL)
+ return -ENXIO;
+
spin_lock_irqsave(&rtc->irq_task_lock, flags);
if (rtc->irq_task != task)
err = -ENXIO;
@@ -243,25 +246,12 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_state);
int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq)
{
- int err = 0, tmp = 0;
+ int err = 0;
unsigned long flags;
struct rtc_device *rtc = to_rtc_device(class_dev);
- /* allowed range is 2-8192 */
- if (freq < 2 || freq > 8192)
- return -EINVAL;
-/*
- FIXME: this does not belong here, will move where appropriate
- at a later stage. It cannot hurt right now, trust me :)
- if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE)))
- return -EACCES;
-*/
- /* check if freq is a power of 2 */
- while (freq > (1 << tmp))
- tmp++;
-
- if (freq != (1 << tmp))
- return -EINVAL;
+ if (rtc->ops->irq_set_freq == NULL)
+ return -ENXIO;
spin_lock_irqsave(&rtc->irq_task_lock, flags);
if (rtc->irq_task != task)
diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c
new file mode 100644
index 0000000..b676f44
--- /dev/null
+++ b/drivers/rtc/rtc-at91.c
@@ -0,0 +1,407 @@
+/*
+ * Real Time Clock interface for Linux on Atmel AT91RM9200
+ *
+ * Copyright (C) 2002 Rick Bronson
+ *
+ * Converted to RTC class model by Andrew Victor
+ *
+ * Ported to Linux 2.6 by Steven Scholz
+ * Based on s3c2410-rtc.c Simtec Electronics
+ *
+ * Based on sa1100-rtc.c by Nils Faerber
+ * Based on rtc.c by Paul Gortmaker
+ *
+ * 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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/completion.h>
+
+#include <asm/uaccess.h>
+#include <asm/rtc.h>
+
+#include <asm/mach/time.h>
+
+
+#define AT91_RTC_FREQ 1
+#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */
+
+static DECLARE_COMPLETION(at91_rtc_updated);
+static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
+
+/*
+ * Decode time/date into rtc_time structure
+ */
+static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
+ struct rtc_time *tm)
+{
+ unsigned int time, date;
+
+ /* must read twice in case it changes */
+ do {
+ time = at91_sys_read(timereg);
+ date = at91_sys_read(calreg);
+ } while ((time != at91_sys_read(timereg)) ||
+ (date != at91_sys_read(calreg)));
+
+ tm->tm_sec = BCD2BIN((time & AT91_RTC_SEC) >> 0);
+ tm->tm_min = BCD2BIN((time & AT91_RTC_MIN) >> 8);
+ tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16);
+
+ /*
+ * The Calendar Alarm register does not have a field for
+ * the year - so these will return an invalid value. When an
+ * alarm is set, at91_alarm_year wille store the current year.
+ */
+ tm->tm_year = BCD2BIN(date & AT91_RTC_CENT) * 100; /* century */
+ tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8); /* year */
+
+ tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
+ tm->tm_mon = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1;
+ tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24);
+}
+
+/*
+ * Read current time and date in RTC
+ */
+static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
+{
+ at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm);
+ tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+ tm->tm_year = tm->tm_year - 1900;
+
+ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+ 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return 0;
+}
+
+/*
+ * Set current time and date in RTC
+ */
+static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long cr;
+
+ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+ 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ /* Stop Time/Calendar from counting */
+ cr = at91_sys_read(AT91_RTC_CR);
+ at91_sys_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
+
+ at91_sys_write(AT91_RTC_IER, AT91_RTC_ACKUPD);
+ wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */
+ at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
+
+ at91_sys_write(AT91_RTC_TIMR,
+ BIN2BCD(tm->tm_sec) << 0
+ | BIN2BCD(tm->tm_min) << 8
+ | BIN2BCD(tm->tm_hour) << 16);
+
+ at91_sys_write(AT91_RTC_CALR,
+ BIN2BCD((tm->tm_year + 1900) / 100) /* century */
+ | BIN2BCD(tm->tm_year % 100) << 8 /* year */
+ | BIN2BCD(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */
+ | BIN2BCD(tm->tm_wday + 1) << 21 /* day of the week [0-6], Sunday=0 */
+ | BIN2BCD(tm->tm_mday) << 24);
+
+ /* Restart Time/Calendar */
+ cr = at91_sys_read(AT91_RTC_CR);
+ at91_sys_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM));
+
+ return 0;
+}
+
+/*
+ * Read alarm time and date in RTC
+ */
+static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rtc_time *tm = &alrm->time;
+
+ at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
+ tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
+ tm->tm_year = at91_alarm_year - 1900;
+
+ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+ 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ return 0;
+}
+
+/*
+ * Set alarm time and date in RTC
+ */
+static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct rtc_time tm;
+
+ at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);
+
+ at91_alarm_year = tm.tm_year;
+
+ tm.tm_hour = alrm->time.tm_hour;
+ tm.tm_min = alrm->time.tm_min;
+ tm.tm_sec = alrm->time.tm_sec;
+
+ at91_sys_write(AT91_RTC_TIMALR,
+ BIN2BCD(tm.tm_sec) << 0
+ | BIN2BCD(tm.tm_min) << 8
+ | BIN2BCD(tm.tm_hour) << 16
+ | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
+ at91_sys_write(AT91_RTC_CALALR,
+ BIN2BCD(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */
+ | BIN2BCD(tm.tm_mday) << 24
+ | AT91_RTC_DATEEN | AT91_RTC_MTHEN);
+
+ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+ at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
+ tm.tm_min, tm.tm_sec);
+
+ return 0;
+}
+
+/*
+ * Handle commands from user-space
+ */
+static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+
+ pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __FUNCTION__, cmd, arg);
+
+ switch (cmd) {
+ case RTC_AIE_OFF: /* alarm off */
+ at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
+ break;
+ case RTC_AIE_ON: /* alarm on */
+ at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
+ break;
+ case RTC_UIE_OFF: /* update off */
+ case RTC_PIE_OFF: /* periodic off */
+ at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
+ break;
+ case RTC_UIE_ON: /* update on */
+ case RTC_PIE_ON: /* periodic on */
+ at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
+ break;
+ case RTC_IRQP_READ: /* read periodic alarm frequency */
+ ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
+ break;
+ case RTC_IRQP_SET: /* set periodic alarm frequency */
+ if (arg != AT91_RTC_FREQ)
+ ret = -EINVAL;
+ break;
+ default:
+ ret = -ENOIOCTLCMD;
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Provide additional RTC information in /proc/driver/rtc
+ */
+static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+ unsigned long imr = at91_sys_read(AT91_RTC_IMR);
+
+ seq_printf(seq, "alarm_IRQ\t: %s\n",
+ (imr & AT91_RTC_ALARM) ? "yes" : "no");
+ seq_printf(seq, "update_IRQ\t: %s\n",
+ (imr & AT91_RTC_ACKUPD) ? "yes" : "no");
+ seq_printf(seq, "periodic_IRQ\t: %s\n",
+ (imr & AT91_RTC_SECEV) ? "yes" : "no");
+ seq_printf(seq, "periodic_freq\t: %ld\n",
+ (unsigned long) AT91_RTC_FREQ);
+
+ return 0;
+}
+
+/*
+ * IRQ handler for the RTC
+ */
+static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct platform_device *pdev = dev_id;
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+ unsigned int rtsr;
+ unsigned long events = 0;
+
+ rtsr = at91_sys_read(AT91_RTC_SR) & at91_sys_read(AT91_RTC_IMR);
+ if (rtsr) { /* this interrupt is shared! Is it ours? */
+ if (rtsr & AT91_RTC_ALARM)
+ events |= (RTC_AF | RTC_IRQF);
+ if (rtsr & AT91_RTC_SECEV)
+ events |= (RTC_UF | RTC_IRQF);
+ if (rtsr & AT91_RTC_ACKUPD)
+ complete(&at91_rtc_updated);
+
+ at91_sys_write(AT91_RTC_SCCR, rtsr); /* clear status reg */
+
+ rtc_update_irq(&rtc->class_dev, 1, events);
+
+ pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__,
+ events >> 8, events & 0x000000FF);
+
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE; /* not handled */
+}
+
+static struct rtc_class_ops at91_rtc_ops = {
+ .ioctl = at91_rtc_ioctl,
+ .read_time = at91_rtc_readtime,
+ .set_time = at91_rtc_settime,
+ .read_alarm = at91_rtc_readalarm,
+ .set_alarm = at91_rtc_setalarm,
+ .proc = at91_rtc_proc,
+};
+
+/*
+ * Initialize and install RTC driver
+ */
+static int __init at91_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ int ret;
+
+ at91_sys_write(AT91_RTC_CR, 0);
+ at91_sys_write(AT91_RTC_MR, 0); /* 24 hour mode */
+
+ /* Disable all interrupts */
+ at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+ AT91_RTC_SECEV | AT91_RTC_TIMEV |
+ AT91_RTC_CALEV);
+
+ ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
+ SA_SHIRQ, "at91_rtc", pdev);
+ if (ret) {
+ printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n",
+ AT91_ID_SYS);
+ return ret;
+ }
+
+ rtc = rtc_device_register(pdev->name, &pdev->dev,
+ &at91_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ free_irq(AT91_ID_SYS, pdev);
+ return PTR_ERR(rtc);
+ }
+ platform_set_drvdata(pdev, rtc);
+
+ printk(KERN_INFO "AT91 Real Time Clock driver.\n");
+ return 0;
+}
+
+/*
+ * Disable and remove the RTC driver
+ */
+static int __devexit at91_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_device *rtc = platform_get_drvdata(pdev);
+
+ /* Disable all interrupts */
+ at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
+ AT91_RTC_SECEV | AT91_RTC_TIMEV |
+ AT91_RTC_CALEV);
+ free_irq(AT91_ID_SYS, pdev);
+
+ rtc_device_unregister(rtc);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* AT91RM9200 RTC Power management control */
+
+static struct timespec at91_rtc_delta;
+
+static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct rtc_time tm;
+ struct timespec time;
+
+ time.tv_nsec = 0;
+
+ /* calculate time delta for suspend */
+ at91_rtc_readtime(&pdev->dev, &tm);
+ rtc_tm_to_time(&tm, &time.tv_sec);
+ save_time_delta(&at91_rtc_delta, &time);
+
+ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+ 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ return 0;
+}
+
+static int at91_rtc_resume(struct platform_device *pdev)
+{
+ struct rtc_time tm;
+ struct timespec time;
+
+ time.tv_nsec = 0;
+
+ at91_rtc_readtime(&pdev->dev, &tm);
+ rtc_tm_to_time(&tm, &time.tv_sec);
+ restore_time_delta(&at91_rtc_delta, &time);
+
+ pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
+ 1900 + tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ return 0;
+}
+#else
+#define at91_rtc_suspend NULL
+#define at91_rtc_resume NULL
+#endif
+
+static struct platform_driver at91_rtc_driver = {
+ .probe = at91_rtc_probe,
+ .remove = at91_rtc_remove,
+ .suspend = at91_rtc_suspend,
+ .resume = at91_rtc_resume,
+ .driver = {
+ .name = "at91_rtc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init at91_rtc_init(void)
+{
+ return platform_driver_register(&at91_rtc_driver);
+}
+
+static void __exit at91_rtc_exit(void)
+{
+ platform_driver_unregister(&at91_rtc_driver);
+}
+
+module_init(at91_rtc_init);
+module_exit(at91_rtc_exit);
+
+MODULE_AUTHOR("Rick Bronson");
+MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 2011567..61a5825 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -48,6 +48,93 @@ static int rtc_dev_open(struct inode *inode, struct file *file)
return err;
}
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+/*
+ * Routine to poll RTC seconds field for change as often as possible,
+ * after first RTC_UIE use timer to reduce polling
+ */
+static void rtc_uie_task(void *data)
+{
+ struct rtc_device *rtc = data;
+ struct rtc_time tm;
+ int num = 0;
+ int err;
+
+ err = rtc_read_time(&rtc->class_dev, &tm);
+ spin_lock_irq(&rtc->irq_lock);
+ if (rtc->stop_uie_polling || err) {
+ rtc->uie_task_active = 0;
+ } else if (rtc->oldsecs != tm.tm_sec) {
+ num = (tm.tm_sec + 60 - rtc->oldsecs) % 60;
+ rtc->oldsecs = tm.tm_sec;
+ rtc->uie_timer.expires = jiffies + HZ - (HZ/10);
+ rtc->uie_timer_active = 1;
+ rtc->uie_task_active = 0;
+ add_timer(&rtc->uie_timer);
+ } else if (schedule_work(&rtc->uie_task) == 0) {
+ rtc->uie_task_active = 0;
+ }
+ spin_unlock_irq(&rtc->irq_lock);
+ if (num)
+ rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF);
+}
+
+static void rtc_uie_timer(unsigned long data)
+{
+ struct rtc_device *rtc = (struct rtc_device *)data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rtc->irq_lock, flags);
+ rtc->uie_timer_active = 0;
+ rtc->uie_task_active = 1;
+ if ((schedule_work(&rtc->uie_task) == 0))
+ rtc->uie_task_active = 0;
+ spin_unlock_irqrestore(&rtc->irq_lock, flags);
+}
+
+static void clear_uie(struct rtc_device *rtc)
+{
+ spin_lock_irq(&rtc->irq_lock);
+ if (rtc->irq_active) {
+ rtc->stop_uie_polling = 1;
+ if (rtc->uie_timer_active) {
+ spin_unlock_irq(&rtc->irq_lock);
+ del_timer_sync(&rtc->uie_timer);
+ spin_lock_irq(&rtc->irq_lock);
+ rtc->uie_timer_active = 0;
+ }
+ if (rtc->uie_task_active) {
+ spin_unlock_irq(&rtc->irq_lock);
+ flush_scheduled_work();
+ spin_lock_irq(&rtc->irq_lock);
+ }
+ rtc->irq_active = 0;
+ }
+ spin_unlock_irq(&rtc->irq_lock);
+}
+
+static int set_uie(struct rtc_device *rtc)
+{
+ struct rtc_time tm;
+ int err;
+
+ err = rtc_read_time(&rtc->class_dev, &tm);
+ if (err)
+ return err;
+ spin_lock_irq(&rtc->irq_lock);
+ if (!rtc->irq_active) {
+ rtc->irq_active = 1;
+ rtc->stop_uie_polling = 0;
+ rtc->oldsecs = tm.tm_sec;
+ rtc->uie_task_active = 1;
+ if (schedule_work(&rtc->uie_task) == 0)
+ rtc->uie_task_active = 0;
+ }
+ rtc->irq_data = 0;
+ spin_unlock_irq(&rtc->irq_lock);
+ return 0;
+}
+#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */
static ssize_t
rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
@@ -127,6 +214,28 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
struct rtc_wkalrm alarm;
void __user *uarg = (void __user *) arg;
+ /* check that the calles has appropriate permissions
+ * for certain ioctls. doing this check here is useful
+ * to avoid duplicate code in each driver.
+ */
+ switch (cmd) {
+ case RTC_EPOCH_SET:
+ case RTC_SET_TIME:
+ if (!capable(CAP_SYS_TIME))
+ return -EACCES;
+ break;
+
+ case RTC_IRQP_SET:
+ if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE))
+ return -EACCES;
+ break;
+
+ case RTC_PIE_ON:
+ if (!capable(CAP_SYS_RESOURCE))
+ return -EACCES;
+ break;
+ }
+
/* avoid conflicting IRQ users */
if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
spin_lock(&rtc->irq_task_lock);
@@ -185,9 +294,6 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
break;
case RTC_SET_TIME:
- if (!capable(CAP_SYS_TIME))
- return -EACCES;
-
if (copy_from_user(&tm, uarg, sizeof(tm)))
return -EFAULT;
@@ -203,10 +309,6 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
err = -EINVAL;
break;
}
- if (!capable(CAP_SYS_TIME)) {
- err = -EACCES;
- break;
- }
rtc_epoch = arg;
err = 0;
#endif
@@ -232,6 +334,14 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
break;
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+ case RTC_UIE_OFF:
+ clear_uie(rtc);
+ return 0;
+
+ case RTC_UIE_ON:
+ return set_uie(rtc);
+#endif
default:
err = -ENOTTY;
break;
@@ -244,6 +354,9 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
{
struct rtc_device *rtc = to_rtc_device(file->private_data);
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+ clear_uie(rtc);
+#endif
if (rtc->ops->release)
rtc->ops->release(rtc->class_dev.dev);
@@ -284,6 +397,10 @@ static int rtc_dev_add_device(struct class_device *class_dev,
mutex_init(&rtc->char_lock);
spin_lock_init(&rtc->irq_lock);
init_waitqueue_head(&rtc->irq_queue);
+#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
+ INIT_WORK(&rtc->uie_task, rtc_uie_task, rtc);
+ setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc);
+#endif
cdev_init(&rtc->char_dev, &rtc_dev_fops);
rtc->char_dev.owner = rtc->owner;
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
new file mode 100644
index 0000000..e8afb93
--- /dev/null
+++ b/drivers/rtc/rtc-ds1307.c
@@ -0,0 +1,388 @@
+/*
+ * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips.
+ *
+ * Copyright (C) 2005 James Chapman (ds1337 core)
+ * Copyright (C) 2006 David Brownell
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/string.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+
+
+/* We can't determine type by probing, but if we expect pre-Linux code
+ * to have set the chip up as a clock (turning on the oscillator and
+ * setting the date and time), Linux can ignore the non-clock features.
+ * That's a natural job for a factory or repair bench.
+ *
+ * If the I2C "force" mechanism is used, we assume the chip is a ds1337.
+ * (Much better would be board-specific tables of I2C devices, along with
+ * the platform_data drivers would use to sort such issues out.)
+ */
+enum ds_type {
+ unknown = 0,
+ ds_1307, /* or ds1338, ... */
+ ds_1337, /* or ds1339, ... */
+ ds_1340, /* or st m41t00, ... */
+ // rs5c372 too? different address...
+};
+
+static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+
+
+/* RTC registers don't differ much, except for the century flag */
+#define DS1307_REG_SECS 0x00 /* 00-59 */
+# define DS1307_BIT_CH 0x80
+#define DS1307_REG_MIN 0x01 /* 00-59 */
+#define DS1307_REG_HOUR 0x02 /* 00-23, or 1-12{am,pm} */
+# define DS1340_BIT_CENTURY_EN 0x80 /* in REG_HOUR */
+# define DS1340_BIT_CENTURY 0x40 /* in REG_HOUR */
+#define DS1307_REG_WDAY 0x03 /* 01-07 */
+#define DS1307_REG_MDAY 0x04 /* 01-31 */
+#define DS1307_REG_MONTH 0x05 /* 01-12 */
+# define DS1337_BIT_CENTURY 0x80 /* in REG_MONTH */
+#define DS1307_REG_YEAR 0x06 /* 00-99 */
+
+/* Other registers (control, status, alarms, trickle charge, NVRAM, etc)
+ * start at 7, and they differ a lot. Only control and status matter for RTC;
+ * be careful using them.
+ */
+#define DS1307_REG_CONTROL 0x07
+# define DS1307_BIT_OUT 0x80
+# define DS1307_BIT_SQWE 0x10
+# define DS1307_BIT_RS1 0x02
+# define DS1307_BIT_RS0 0x01
+#define DS1337_REG_CONTROL 0x0e
+# define DS1337_BIT_nEOSC 0x80
+# define DS1337_BIT_RS2 0x10
+# define DS1337_BIT_RS1 0x08
+# define DS1337_BIT_INTCN 0x04
+# define DS1337_BIT_A2IE 0x02
+# define DS1337_BIT_A1IE 0x01
+#define DS1337_REG_STATUS 0x0f
+# define DS1337_BIT_OSF 0x80
+# define DS1337_BIT_A2I 0x02
+# define DS1337_BIT_A1I 0x01
+#define DS1339_REG_TRICKLE 0x10
+
+
+
+struct ds1307 {
+ u8 reg_addr;
+ u8 regs[8];
+ enum ds_type type;
+ struct i2c_msg msg[2];
+ struct i2c_client client;
+ struct rtc_device *rtc;
+};
+
+
+static int ds1307_get_time(struct device *dev, struct rtc_time *t)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ int tmp;
+
+ /* read the RTC registers all at once */
+ ds1307->msg[1].flags = I2C_M_RD;
+ ds1307->msg[1].len = 7;
+
+ tmp = i2c_transfer(ds1307->client.adapter, ds1307->msg, 2);
+ if (tmp != 2) {
+ dev_err(dev, "%s error %d\n", "read", tmp);
+ return -EIO;
+ }
+
+ dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+ "read",
+ ds1307->regs[0], ds1307->regs[1],
+ ds1307->regs[2], ds1307->regs[3],
+ ds1307->regs[4], ds1307->regs[5],
+ ds1307->regs[6]);
+
+ t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f);
+ t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+ tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
+ t->tm_hour = BCD2BIN(tmp);
+ t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
+ t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+ tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
+ t->tm_mon = BCD2BIN(tmp) - 1;
+
+ /* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
+ t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100;
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "read", t->tm_sec, t->tm_min,
+ t->tm_hour, t->tm_mday,
+ t->tm_mon, t->tm_year, t->tm_wday);
+
+ return 0;
+}
+
+static int ds1307_set_time(struct device *dev, struct rtc_time *t)
+{
+ struct ds1307 *ds1307 = dev_get_drvdata(dev);
+ int result;
+ int tmp;
+ u8 *buf = ds1307->regs;
+
+ dev_dbg(dev, "%s secs=%d, mins=%d, "
+ "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+ "write", dt->tm_sec, dt->tm_min,
+ dt->tm_hour, dt->tm_mday,
+ dt->tm_mon, dt->tm_year, dt->tm_wday);
+
+ *buf++ = 0; /* first register addr */
+ buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec);
+ buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min);
+ buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour);
+ buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1);
+ buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday);
+ buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1);
+
+ /* assume 20YY not 19YY */
+ tmp = t->tm_year - 100;
+ buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
+
+ if (ds1307->type == ds_1337)
+ buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
+ else if (ds1307->type == ds_1340)
+ buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
+ | DS1340_BIT_CENTURY;
+
+ ds1307->msg[1].flags = 0;
+ ds1307->msg[1].len = 8;
+
+ dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x\n",
+ "write", buf[0], buf[1], buf[2], buf[3],
+ buf[4], buf[5], buf[6]);
+
+ result = i2c_transfer(ds1307->client.adapter, &ds1307->msg[1], 1);
+ if (result != 1) {
+ dev_err(dev, "%s error %d\n", "write", tmp);
+ return -EIO;
+ }
+ return 0;
+}
+
+static struct rtc_class_ops ds13xx_rtc_ops = {
+ .read_time = ds1307_get_time,
+ .set_time = ds1307_set_time,
+};
+
+static struct i2c_driver ds1307_driver;
+
+static int __devinit
+ds1307_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct ds1307 *ds1307;
+ int err = -ENODEV;
+ struct i2c_client *client;
+ int tmp;
+
+ if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ client = &ds1307->client;
+ client->addr = address;
+ client->adapter = adapter;
+ client->driver = &ds1307_driver;
+ client->flags = 0;
+
+ i2c_set_clientdata(client, ds1307);
+
+ ds1307->msg[0].addr = client->addr;
+ ds1307->msg[0].flags = 0;
+ ds1307->msg[0].len = 1;
+ ds1307->msg[0].buf = &ds1307->reg_addr;
+
+ ds1307->msg[1].addr = client->addr;
+ ds1307->msg[1].flags = I2C_M_RD;
+ ds1307->msg[1].len = sizeof(ds1307->regs);
+ ds1307->msg[1].buf = ds1307->regs;
+
+ /* HACK: "force" implies "needs ds1337-style-oscillator setup" */
+ if (kind >= 0) {
+ ds1307->type = ds_1337;
+
+ ds1307->reg_addr = DS1337_REG_CONTROL;
+ ds1307->msg[1].len = 2;
+
+ tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+ if (tmp != 2) {
+ pr_debug("read error %d\n", tmp);
+ err = -EIO;
+ goto exit_free;
+ }
+
+ ds1307->reg_addr = 0;
+ ds1307->msg[1].len = sizeof(ds1307->regs);
+
+ /* oscillator is off; need to turn it on */
+ if ((ds1307->regs[0] & DS1337_BIT_nEOSC)
+ || (ds1307->regs[1] & DS1337_BIT_OSF)) {
+ printk(KERN_ERR "no ds1337 oscillator code\n");
+ goto exit_free;
+ }
+ } else
+ ds1307->type = ds_1307;
+
+read_rtc:
+ /* read RTC registers */
+
+ tmp = i2c_transfer(client->adapter, ds1307->msg, 2);
+ if (tmp != 2) {
+ pr_debug("read error %d\n", tmp);
+ err = -EIO;
+ goto exit_free;
+ }
+
+ /* minimal sanity checking; some chips (like DS1340) don't
+ * specify the extra bits as must-be-zero, but there are
+ * still a few values that are clearly out-of-range.
+ */
+ tmp = ds1307->regs[DS1307_REG_SECS];
+ if (tmp & DS1307_BIT_CH) {
+ if (ds1307->type && ds1307->type != ds_1307) {
+ pr_debug("not a ds1307?\n");
+ goto exit_free;
+ }
+ ds1307->type = ds_1307;
+
+ /* this partial initialization should work for ds1307,
+ * ds1338, ds1340, st m41t00, and more.
+ */
+ dev_warn(&client->dev, "oscillator started; SET TIME!\n");
+ i2c_smbus_write_byte_data(client, 0, 0);
+ goto read_rtc;
+ }
+ tmp = BCD2BIN(tmp & 0x7f);
+ if (tmp > 60)
+ goto exit_free;
+ tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+ if (tmp > 60)
+ goto exit_free;
+
+ tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+ if (tmp == 0 || tmp > 31)
+ goto exit_free;
+
+ tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
+ if (tmp == 0 || tmp > 12)
+ goto exit_free;
+
+ /* force into in 24 hour mode (most chips) or
+ * disable century bit (ds1340)
+ */
+ tmp = ds1307->regs[DS1307_REG_HOUR];
+ if (tmp & (1 << 6)) {
+ if (tmp & (1 << 5))
+ tmp = BCD2BIN(tmp & 0x1f) + 12;
+ else
+ tmp = BCD2BIN(tmp);
+ i2c_smbus_write_byte_data(client,
+ DS1307_REG_HOUR,
+ BIN2BCD(tmp));
+ }
+
+ /* FIXME chips like 1337 can generate alarm irqs too; those are
+ * worth exposing through the API (especially when the irq is
+ * wakeup-capable).
+ */
+
+ switch (ds1307->type) {
+ case unknown:
+ strlcpy(client->name, "unknown", I2C_NAME_SIZE);
+ break;
+ case ds_1307:
+ strlcpy(client->name, "ds1307", I2C_NAME_SIZE);
+ break;
+ case ds_1337:
+ strlcpy(client->name, "ds1337", I2C_NAME_SIZE);
+ break;
+ case ds_1340:
+ strlcpy(client->name, "ds1340", I2C_NAME_SIZE);
+ break;
+ }
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(client)))
+ goto exit_free;
+
+ ds1307->rtc = rtc_device_register(client->name, &client->dev,
+ &ds13xx_rtc_ops, THIS_MODULE);
+ if (IS_ERR(ds1307->rtc)) {
+ err = PTR_ERR(ds1307->rtc);
+ dev_err(&client->dev,
+ "unable to register the class device\n");
+ goto exit_detach;
+ }
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+exit_free:
+ kfree(ds1307);
+exit:
+ return err;
+}
+
+static int __devinit
+ds1307_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
+ return 0;
+ return i2c_probe(adapter, &addr_data, ds1307_detect);
+}
+
+static int __devexit ds1307_detach_client(struct i2c_client *client)
+{
+ int err;
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+
+ rtc_device_unregister(ds1307->rtc);
+ if ((err = i2c_detach_client(client)))
+ return err;
+ kfree(ds1307);
+ return 0;
+}
+
+static struct i2c_driver ds1307_driver = {
+ .driver = {
+ .name = "ds1307",
+ .owner = THIS_MODULE,
+ },
+ .attach_adapter = ds1307_attach_adapter,
+ .detach_client = __devexit_p(ds1307_detach_client),
+};
+
+static int __init ds1307_init(void)
+{
+ return i2c_add_driver(&ds1307_driver);
+}
+module_init(ds1307_init);
+
+static void __exit ds1307_exit(void)
+{
+ i2c_del_driver(&ds1307_driver);
+}
+module_exit(ds1307_exit);
+
+MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
new file mode 100644
index 0000000..ecafbad
--- /dev/null
+++ b/drivers/rtc/rtc-ds1553.c
@@ -0,0 +1,414 @@
+/*
+ * An rtc driver for the Dallas DS1553
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * 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/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "0.1"
+
+#define RTC_REG_SIZE 0x2000
+#define RTC_OFFSET 0x1ff0
+
+#define RTC_FLAGS (RTC_OFFSET + 0)
+#define RTC_SECONDS_ALARM (RTC_OFFSET + 2)
+#define RTC_MINUTES_ALARM (RTC_OFFSET + 3)
+#define RTC_HOURS_ALARM (RTC_OFFSET + 4)
+#define RTC_DATE_ALARM (RTC_OFFSET + 5)
+#define RTC_INTERRUPTS (RTC_OFFSET + 6)
+#define RTC_WATCHDOG (RTC_OFFSET + 7)
+#define RTC_CONTROL (RTC_OFFSET + 8)
+#define RTC_CENTURY (RTC_OFFSET + 8)
+#define RTC_SECONDS (RTC_OFFSET + 9)
+#define RTC_MINUTES (RTC_OFFSET + 10)
+#define RTC_HOURS (RTC_OFFSET + 11)
+#define RTC_DAY (RTC_OFFSET + 12)
+#define RTC_DATE (RTC_OFFSET + 13)
+#define RTC_MONTH (RTC_OFFSET + 14)
+#define RTC_YEAR (RTC_OFFSET + 15)
+
+#define RTC_CENTURY_MASK 0x3f
+#define RTC_SECONDS_MASK 0x7f
+#define RTC_DAY_MASK 0x07
+
+/* Bits in the Control/Century register */
+#define RTC_WRITE 0x80
+#define RTC_READ 0x40
+
+/* Bits in the Seconds register */
+#define RTC_STOP 0x80
+
+/* Bits in the Flags register */
+#define RTC_FLAGS_AF 0x40
+#define RTC_FLAGS_BLF 0x10
+
+/* Bits in the Interrupts register */
+#define RTC_INTS_AE 0x80
+
+struct rtc_plat_data {
+ struct rtc_device *rtc;
+ void __iomem *ioaddr;
+ unsigned long baseaddr;
+ unsigned long last_jiffies;
+ int irq;
+ unsigned int irqen;
+ int alrm_sec;
+ int alrm_min;
+ int alrm_hour;
+ int alrm_mday;
+};
+
+static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ u8 century;
+
+ century = BIN2BCD((tm->tm_year + 1900) / 100);
+
+ writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL);
+
+ writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
+ writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+ writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+ writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
+ writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
+ writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
+ writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+
+ /* RTC_CENTURY and RTC_CONTROL share same register */
+ writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
+ writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+ return 0;
+}
+
+static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ unsigned int year, month, day, hour, minute, second, week;
+ unsigned int century;
+
+ /* give enough time to update RTC in case of continuous read */
+ if (pdata->last_jiffies == jiffies)
+ msleep(1);
+ pdata->last_jiffies = jiffies;
+ writeb(RTC_READ, ioaddr + RTC_CONTROL);
+ second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
+ minute = readb(ioaddr + RTC_MINUTES);
+ hour = readb(ioaddr + RTC_HOURS);
+ day = readb(ioaddr + RTC_DATE);
+ week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
+ month = readb(ioaddr + RTC_MONTH);
+ year = readb(ioaddr + RTC_YEAR);
+ century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+ writeb(0, ioaddr + RTC_CONTROL);
+ tm->tm_sec = BCD2BIN(second);
+ tm->tm_min = BCD2BIN(minute);
+ tm->tm_hour = BCD2BIN(hour);
+ tm->tm_mday = BCD2BIN(day);
+ tm->tm_wday = BCD2BIN(week);
+ tm->tm_mon = BCD2BIN(month) - 1;
+ /* year is 1900 + tm->tm_year */
+ tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+
+ if (rtc_valid_tm(tm) < 0) {
+ dev_err(dev, "retrieved date/time is not valid.\n");
+ rtc_time_to_tm(0, tm);
+ }
+ return 0;
+}
+
+static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
+{
+ void __iomem *ioaddr = pdata->ioaddr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
+ writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
+ 0x80 : BIN2BCD(pdata->alrm_mday),
+ ioaddr + RTC_DATE_ALARM);
+ writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
+ 0x80 : BIN2BCD(pdata->alrm_hour),
+ ioaddr + RTC_HOURS_ALARM);
+ writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
+ 0x80 : BIN2BCD(pdata->alrm_min),
+ ioaddr + RTC_MINUTES_ALARM);
+ writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
+ 0x80 : BIN2BCD(pdata->alrm_sec),
+ ioaddr + RTC_SECONDS_ALARM);
+ writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS);
+ readb(ioaddr + RTC_FLAGS); /* clear interrupts */
+ spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags);
+}
+
+static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+ if (pdata->irq < 0)
+ return -EINVAL;
+ pdata->alrm_mday = alrm->time.tm_mday;
+ pdata->alrm_hour = alrm->time.tm_hour;
+ pdata->alrm_min = alrm->time.tm_min;
+ pdata->alrm_sec = alrm->time.tm_sec;
+ if (alrm->enabled)
+ pdata->irqen |= RTC_AF;
+ ds1553_rtc_update_alarm(pdata);
+ return 0;
+}
+
+static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+ if (pdata->irq < 0)
+ return -EINVAL;
+ alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday;
+ alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour;
+ alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min;
+ alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec;
+ alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0;
+ return 0;
+}
+
+static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct platform_device *pdev = dev_id;
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ unsigned long events = RTC_IRQF;
+
+ /* read and clear interrupt */
+ if (!(readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_AF))
+ return IRQ_NONE;
+ if (readb(ioaddr + RTC_SECONDS_ALARM) & 0x80)
+ events |= RTC_UF;
+ else
+ events |= RTC_AF;
+ rtc_update_irq(&pdata->rtc->class_dev, 1, events);
+ return IRQ_HANDLED;
+}
+
+static void ds1553_rtc_release(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+ if (pdata->irq >= 0) {
+ pdata->irqen = 0;
+ ds1553_rtc_update_alarm(pdata);
+ }
+}
+
+static int ds1553_rtc_ioctl(struct device *dev, unsigned int cmd,
+ unsigned long arg)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+ if (pdata->irq < 0)
+ return -ENOIOCTLCMD;
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ pdata->irqen &= ~RTC_AF;
+ ds1553_rtc_update_alarm(pdata);
+ break;
+ case RTC_AIE_ON:
+ pdata->irqen |= RTC_AF;
+ ds1553_rtc_update_alarm(pdata);
+ break;
+ case RTC_UIE_OFF:
+ pdata->irqen &= ~RTC_UF;
+ ds1553_rtc_update_alarm(pdata);
+ break;
+ case RTC_UIE_ON:
+ pdata->irqen |= RTC_UF;
+ ds1553_rtc_update_alarm(pdata);
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static struct rtc_class_ops ds1553_rtc_ops = {
+ .read_time = ds1553_rtc_read_time,
+ .set_time = ds1553_rtc_set_time,
+ .read_alarm = ds1553_rtc_read_alarm,
+ .set_alarm = ds1553_rtc_set_alarm,
+ .release = ds1553_rtc_release,
+ .ioctl = ds1553_rtc_ioctl,
+};
+
+static ssize_t ds1553_nvram_read(struct kobject *kobj, char *buf,
+ loff_t pos, size_t size)
+{
+ struct platform_device *pdev =
+ to_platform_device(container_of(kobj, struct device, kobj));
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ ssize_t count;
+
+ for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ *buf++ = readb(ioaddr + pos++);
+ return count;
+}
+
+static ssize_t ds1553_nvram_write(struct kobject *kobj, char *buf,
+ loff_t pos, size_t size)
+{
+ struct platform_device *pdev =
+ to_platform_device(container_of(kobj, struct device, kobj));
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ ssize_t count;
+
+ for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ writeb(*buf++, ioaddr + pos++);
+ return count;
+}
+
+static struct bin_attribute ds1553_nvram_attr = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = RTC_OFFSET,
+ .read = ds1553_nvram_read,
+ .write = ds1553_nvram_write,
+};
+
+static int __init ds1553_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ struct resource *res;
+ unsigned int cen, sec;
+ struct rtc_plat_data *pdata = NULL;
+ void __iomem *ioaddr = NULL;
+ int ret = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ pdata->irq = -1;
+ if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ pdata->baseaddr = res->start;
+ ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
+ if (!ioaddr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ pdata->ioaddr = ioaddr;
+ pdata->irq = platform_get_irq(pdev, 0);
+
+ /* turn RTC on if it was not on */
+ sec = readb(ioaddr + RTC_SECONDS);
+ if (sec & RTC_STOP) {
+ sec &= RTC_SECONDS_MASK;
+ cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+ writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+ writeb(sec, ioaddr + RTC_SECONDS);
+ writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+ }
+ if (readb(ioaddr + RTC_FLAGS) & RTC_FLAGS_BLF)
+ dev_warn(&pdev->dev, "voltage-low detected.\n");
+
+ if (pdata->irq >= 0) {
+ writeb(0, ioaddr + RTC_INTERRUPTS);
+ if (request_irq(pdata->irq, ds1553_rtc_interrupt, SA_SHIRQ,
+ pdev->name, pdev) < 0) {
+ dev_warn(&pdev->dev, "interrupt not available.\n");
+ pdata->irq = -1;
+ }
+ }
+
+ rtc = rtc_device_register(pdev->name, &pdev->dev,
+ &ds1553_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ ret = PTR_ERR(rtc);
+ goto out;
+ }
+ pdata->rtc = rtc;
+ pdata->last_jiffies = jiffies;
+ platform_set_drvdata(pdev, pdata);
+ sysfs_create_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+ return 0;
+ out:
+ if (pdata->irq >= 0)
+ free_irq(pdata->irq, pdev);
+ if (ioaddr)
+ iounmap(ioaddr);
+ if (pdata->baseaddr)
+ release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+ kfree(pdata);
+ return ret;
+}
+
+static int __devexit ds1553_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+ sysfs_remove_bin_file(&pdev->dev.kobj, &ds1553_nvram_attr);
+ rtc_device_unregister(pdata->rtc);
+ if (pdata->irq >= 0) {
+ writeb(0, pdata->ioaddr + RTC_INTERRUPTS);
+ free_irq(pdata->irq, pdev);
+ }
+ iounmap(pdata->ioaddr);
+ release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+ kfree(pdata);
+ return 0;
+}
+
+static struct platform_driver ds1553_rtc_driver = {
+ .probe = ds1553_rtc_probe,
+ .remove = __devexit_p(ds1553_rtc_remove),
+ .driver = {
+ .name = "ds1553",
+ .owner = THIS_MODULE,
+ },
+};
+
+static __init int ds1553_init(void)
+{
+ return platform_driver_register(&ds1553_rtc_driver);
+}
+
+static __exit void ds1553_exit(void)
+{
+ return platform_driver_unregister(&ds1553_rtc_driver);
+}
+
+module_init(ds1553_init);
+module_exit(ds1553_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Dallas DS1553 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
new file mode 100644
index 0000000..8e47e5a
--- /dev/null
+++ b/drivers/rtc/rtc-ds1742.c
@@ -0,0 +1,259 @@
+/*
+ * An rtc driver for the Dallas DS1742
+ *
+ * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
+ *
+ * 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/bcd.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#define DRV_VERSION "0.1"
+
+#define RTC_REG_SIZE 0x800
+#define RTC_OFFSET 0x7f8
+
+#define RTC_CONTROL (RTC_OFFSET + 0)
+#define RTC_CENTURY (RTC_OFFSET + 0)
+#define RTC_SECONDS (RTC_OFFSET + 1)
+#define RTC_MINUTES (RTC_OFFSET + 2)
+#define RTC_HOURS (RTC_OFFSET + 3)
+#define RTC_DAY (RTC_OFFSET + 4)
+#define RTC_DATE (RTC_OFFSET + 5)
+#define RTC_MONTH (RTC_OFFSET + 6)
+#define RTC_YEAR (RTC_OFFSET + 7)
+
+#define RTC_CENTURY_MASK 0x3f
+#define RTC_SECONDS_MASK 0x7f
+#define RTC_DAY_MASK 0x07
+
+/* Bits in the Control/Century register */
+#define RTC_WRITE 0x80
+#define RTC_READ 0x40
+
+/* Bits in the Seconds register */
+#define RTC_STOP 0x80
+
+/* Bits in the Day register */
+#define RTC_BATT_FLAG 0x80
+
+struct rtc_plat_data {
+ struct rtc_device *rtc;
+ void __iomem *ioaddr;
+ unsigned long baseaddr;
+ unsigned long last_jiffies;
+};
+
+static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ u8 century;
+
+ century = BIN2BCD((tm->tm_year + 1900) / 100);
+
+ writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+
+ writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
+ writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+ writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+ writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
+ writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
+ writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
+ writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+
+ /* RTC_CENTURY and RTC_CONTROL share same register */
+ writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
+ writeb(century & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+ return 0;
+}
+
+static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ unsigned int year, month, day, hour, minute, second, week;
+ unsigned int century;
+
+ /* give enough time to update RTC in case of continuous read */
+ if (pdata->last_jiffies == jiffies)
+ msleep(1);
+ pdata->last_jiffies = jiffies;
+ writeb(RTC_READ, ioaddr + RTC_CONTROL);
+ second = readb(ioaddr + RTC_SECONDS) & RTC_SECONDS_MASK;
+ minute = readb(ioaddr + RTC_MINUTES);
+ hour = readb(ioaddr + RTC_HOURS);
+ day = readb(ioaddr + RTC_DATE);
+ week = readb(ioaddr + RTC_DAY) & RTC_DAY_MASK;
+ month = readb(ioaddr + RTC_MONTH);
+ year = readb(ioaddr + RTC_YEAR);
+ century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+ writeb(0, ioaddr + RTC_CONTROL);
+ tm->tm_sec = BCD2BIN(second);
+ tm->tm_min = BCD2BIN(minute);
+ tm->tm_hour = BCD2BIN(hour);
+ tm->tm_mday = BCD2BIN(day);
+ tm->tm_wday = BCD2BIN(week);
+ tm->tm_mon = BCD2BIN(month) - 1;
+ /* year is 1900 + tm->tm_year */
+ tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+
+ if (rtc_valid_tm(tm) < 0) {
+ dev_err(dev, "retrieved date/time is not valid.\n");
+ rtc_time_to_tm(0, tm);
+ }
+ return 0;
+}
+
+static struct rtc_class_ops ds1742_rtc_ops = {
+ .read_time = ds1742_rtc_read_time,
+ .set_time = ds1742_rtc_set_time,
+};
+
+static ssize_t ds1742_nvram_read(struct kobject *kobj, char *buf,
+ loff_t pos, size_t size)
+{
+ struct platform_device *pdev =
+ to_platform_device(container_of(kobj, struct device, kobj));
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ ssize_t count;
+
+ for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ *buf++ = readb(ioaddr + pos++);
+ return count;
+}
+
+static ssize_t ds1742_nvram_write(struct kobject *kobj, char *buf,
+ loff_t pos, size_t size)
+{
+ struct platform_device *pdev =
+ to_platform_device(container_of(kobj, struct device, kobj));
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ void __iomem *ioaddr = pdata->ioaddr;
+ ssize_t count;
+
+ for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ writeb(*buf++, ioaddr + pos++);
+ return count;
+}
+
+static struct bin_attribute ds1742_nvram_attr = {
+ .attr = {
+ .name = "nvram",
+ .mode = S_IRUGO | S_IWUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = RTC_OFFSET,
+ .read = ds1742_nvram_read,
+ .write = ds1742_nvram_write,
+};
+
+static int __init ds1742_rtc_probe(struct platform_device *pdev)
+{
+ struct rtc_device *rtc;
+ struct resource *res;
+ unsigned int cen, sec;
+ struct rtc_plat_data *pdata = NULL;
+ void __iomem *ioaddr = NULL;
+ int ret = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ if (!request_mem_region(res->start, RTC_REG_SIZE, pdev->name)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ pdata->baseaddr = res->start;
+ ioaddr = ioremap(pdata->baseaddr, RTC_REG_SIZE);
+ if (!ioaddr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ pdata->ioaddr = ioaddr;
+
+ /* turn RTC on if it was not on */
+ sec = readb(ioaddr + RTC_SECONDS);
+ if (sec & RTC_STOP) {
+ sec &= RTC_SECONDS_MASK;
+ cen = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
+ writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
+ writeb(sec, ioaddr + RTC_SECONDS);
+ writeb(cen & RTC_CENTURY_MASK, ioaddr + RTC_CONTROL);
+ }
+ if (readb(ioaddr + RTC_DAY) & RTC_BATT_FLAG)
+ dev_warn(&pdev->dev, "voltage-low detected.\n");
+
+ rtc = rtc_device_register(pdev->name, &pdev->dev,
+ &ds1742_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ ret = PTR_ERR(rtc);
+ goto out;
+ }
+ pdata->rtc = rtc;
+ pdata->last_jiffies = jiffies;
+ platform_set_drvdata(pdev, pdata);
+ sysfs_create_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+ return 0;
+ out:
+ if (ioaddr)
+ iounmap(ioaddr);
+ if (pdata->baseaddr)
+ release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+ kfree(pdata);
+ return ret;
+}
+
+static int __devexit ds1742_rtc_remove(struct platform_device *pdev)
+{
+ struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+
+ sysfs_remove_bin_file(&pdev->dev.kobj, &ds1742_nvram_attr);
+ rtc_device_unregister(pdata->rtc);
+ iounmap(pdata->ioaddr);
+ release_mem_region(pdata->baseaddr, RTC_REG_SIZE);
+ kfree(pdata);
+ return 0;
+}
+
+static struct platform_driver ds1742_rtc_driver = {
+ .probe = ds1742_rtc_probe,
+ .remove = __devexit_p(ds1742_rtc_remove),
+ .driver = {
+ .name = "ds1742",
+ .owner = THIS_MODULE,
+ },
+};
+
+static __init int ds1742_init(void)
+{
+ return platform_driver_register(&ds1742_rtc_driver);
+}
+
+static __exit void ds1742_exit(void)
+{
+ return platform_driver_unregister(&ds1742_rtc_driver);
+}
+
+module_init(ds1742_init);
+module_exit(ds1742_exit);
+
+MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
+MODULE_DESCRIPTION("Dallas DS1742 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c
index cfedc1d..9812120 100644
--- a/drivers/rtc/rtc-lib.c
+++ b/drivers/rtc/rtc-lib.c
@@ -18,9 +18,19 @@ static const unsigned char rtc_days_in_month[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
+static const unsigned short rtc_ydays[2][13] = {
+ /* Normal years */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
+
#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
+/*
+ * The number of days in the month.
+ */
int rtc_month_days(unsigned int month, unsigned int year)
{
return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1);
@@ -28,6 +38,15 @@ int rtc_month_days(unsigned int month, unsigned int year)
EXPORT_SYMBOL(rtc_month_days);
/*
+ * The number of days since January 1. (0 to 365)
+ */
+int rtc_year_days(unsigned int day, unsigned int month, unsigned int year)
+{
+ return rtc_ydays[LEAP_YEAR(year)][month] + day-1;
+}
+EXPORT_SYMBOL(rtc_year_days);
+
+/*
* Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
*/
void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c
new file mode 100644
index 0000000..2c97395
--- /dev/null
+++ b/drivers/rtc/rtc-max6902.c
@@ -0,0 +1,286 @@
+/* drivers/char/max6902.c
+ *
+ * Copyright (C) 2006 8D Technologies inc.
+ * Copyright (C) 2004 Compulab Ltd.
+ *
+ * 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.
+ *
+ * Driver for MAX6902 spi RTC
+ *
+ * Changelog:
+ *
+ * 24-May-2006: Raphael Assenat <raph@8d.com>
+ * - Major rework
+ * Converted to rtc_device and uses the SPI layer.
+ *
+ * ??-???-2005: Someone at Compulab
+ * - Initial driver creation.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/spi/spi.h>
+#include <linux/bcd.h>
+#include <linux/delay.h>
+
+#define MAX6902_REG_SECONDS 0x01
+#define MAX6902_REG_MINUTES 0x03
+#define MAX6902_REG_HOURS 0x05
+#define MAX6902_REG_DATE 0x07
+#define MAX6902_REG_MONTH 0x09
+#define MAX6902_REG_DAY 0x0B
+#define MAX6902_REG_YEAR 0x0D
+#define MAX6902_REG_CONTROL 0x0F
+#define MAX6902_REG_CENTURY 0x13
+
+#undef MAX6902_DEBUG
+
+struct max6902 {
+ struct rtc_device *rtc;
+ u8 buf[9]; /* Burst read cmd + 8 registers */
+ u8 tx_buf[2];
+ u8 rx_buf[2];
+};
+
+static void max6902_set_reg(struct device *dev, unsigned char address,
+ unsigned char data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ unsigned char buf[2];
+
+ /* MSB must be '0' to write */
+ buf[0] = address & 0x7f;
+ buf[1] = data;
+
+ spi_write(spi, buf, 2);
+}
+
+static int max6902_get_reg(struct device *dev, unsigned char address,
+ unsigned char *data)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct max6902 *chip = dev_get_drvdata(dev);
+ struct spi_message message;
+ struct spi_transfer xfer;
+ int status;
+
+ if (!data)
+ return -EINVAL;
+
+ /* Build our spi message */
+ spi_message_init(&message);
+ memset(&xfer, 0, sizeof(xfer));
+ xfer.len = 2;
+ /* Can tx_buf and rx_buf be equal? The doc in spi.h is not sure... */
+ xfer.tx_buf = chip->tx_buf;
+ xfer.rx_buf = chip->rx_buf;
+
+ /* Set MSB to indicate read */
+ chip->tx_buf[0] = address | 0x80;
+
+ spi_message_add_tail(&xfer, &message);
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0)
+ status = message.status;
+ else
+ return status;
+
+ *data = chip->rx_buf[1];
+
+ return status;
+}
+
+static int max6902_get_datetime(struct device *dev, struct rtc_time *dt)
+{
+ unsigned char tmp;
+ int century;
+ int err;
+ struct spi_device *spi = to_spi_device(dev);
+ struct max6902 *chip = dev_get_drvdata(dev);
+ struct spi_message message;
+ struct spi_transfer xfer;
+ int status;
+
+ err = max6902_get_reg(dev, MAX6902_REG_CENTURY, &tmp);
+ if (err)
+ return err;
+
+ /* build the message */
+ spi_message_init(&message);
+ memset(&xfer, 0, sizeof(xfer));
+ xfer.len = 1 + 7; /* Burst read command + 7 registers */
+ xfer.tx_buf = chip->buf;
+ xfer.rx_buf = chip->buf;
+ chip->buf[0] = 0xbf; /* Burst read */
+ spi_message_add_tail(&xfer, &message);
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0)
+ status = message.status;
+ else
+ return status;
+
+ /* The chip sends data in this order:
+ * Seconds, Minutes, Hours, Date, Month, Day, Year */
+ dt->tm_sec = BCD2BIN(chip->buf[1]);
+ dt->tm_min = BCD2BIN(chip->buf[2]);
+ dt->tm_hour = BCD2BIN(chip->buf[3]);
+ dt->tm_mday = BCD2BIN(chip->buf[4]);
+ dt->tm_mon = BCD2BIN(chip->buf[5] - 1);
+ dt->tm_wday = BCD2BIN(chip->buf[6]);
+ dt->tm_year = BCD2BIN(chip->buf[7]);
+
+ century = BCD2BIN(tmp) * 100;
+
+ dt->tm_year += century;
+ dt->tm_year -= 1900;
+
+#ifdef MAX6902_DEBUG
+ printk("\n%s : Read RTC values\n",__FUNCTION__);
+ printk("tm_hour: %i\n",dt->tm_hour);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_sec : %i\n",dt->tm_sec);
+ printk("tm_year: %i\n",dt->tm_year);
+ printk("tm_mon : %i\n",dt->tm_mon);
+ printk("tm_mday: %i\n",dt->tm_mday);
+ printk("tm_wday: %i\n",dt->tm_wday);
+#endif
+
+ return 0;
+}
+
+static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
+{
+ dt->tm_year = dt->tm_year+1900;
+
+#ifdef MAX6902_DEBUG
+ printk("\n%s : Setting RTC values\n",__FUNCTION__);
+ printk("tm_sec : %i\n",dt->tm_sec);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_hour: %i\n",dt->tm_hour);
+ printk("tm_mday: %i\n",dt->tm_mday);
+ printk("tm_wday: %i\n",dt->tm_wday);
+ printk("tm_year: %i\n",dt->tm_year);
+#endif
+
+ /* Remove write protection */
+ max6902_set_reg(dev, 0xF, 0);
+
+ max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec));
+ max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min));
+ max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour));
+
+ max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday));
+ max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1));
+ max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday));
+ max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100));
+ max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100));
+
+ /* Compulab used a delay here. However, the datasheet
+ * does not mention a delay being required anywhere... */
+ /* delay(2000); */
+
+ /* Write protect */
+ max6902_set_reg(dev, 0xF, 0x80);
+
+ return 0;
+}
+
+static int max6902_read_time(struct device *dev, struct rtc_time *tm)
+{
+ return max6902_get_datetime(dev, tm);
+}
+
+static int max6902_set_time(struct device *dev, struct rtc_time *tm)
+{
+ return max6902_set_datetime(dev, tm);
+}
+
+static struct rtc_class_ops max6902_rtc_ops = {
+ .read_time = max6902_read_time,
+ .set_time = max6902_set_time,
+};
+
+static int __devinit max6902_probe(struct spi_device *spi)
+{
+ struct rtc_device *rtc;
+ unsigned char tmp;
+ struct max6902 *chip;
+ int res;
+
+ rtc = rtc_device_register("max6902",
+ &spi->dev, &max6902_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ spi->mode = SPI_MODE_3;
+ spi->bits_per_word = 8;
+ spi_setup(spi);
+
+ chip = kzalloc(sizeof *chip, GFP_KERNEL);
+ if (!chip) {
+ rtc_device_unregister(rtc);
+ return -ENOMEM;
+ }
+ chip->rtc = rtc;
+ dev_set_drvdata(&spi->dev, chip);
+
+ res = max6902_get_reg(&spi->dev, MAX6902_REG_SECONDS, &tmp);
+ if (res) {
+ rtc_device_unregister(rtc);
+ return res;
+ }
+
+ return 0;
+}
+
+static int __devexit max6902_remove(struct spi_device *spi)
+{
+ struct max6902 *chip = platform_get_drvdata(spi);
+ struct rtc_device *rtc = chip->rtc;
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ kfree(chip);
+
+ return 0;
+}
+
+static struct spi_driver max6902_driver = {
+ .driver = {
+ .name = "max6902",
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = max6902_probe,
+ .remove = __devexit_p(max6902_remove),
+};
+
+static __init int max6902_init(void)
+{
+ printk("max6902 spi driver\n");
+ return spi_register_driver(&max6902_driver);
+}
+module_init(max6902_init);
+
+static __exit void max6902_exit(void)
+{
+ spi_unregister_driver(&max6902_driver);
+}
+module_exit(max6902_exit);
+
+MODULE_DESCRIPTION ("max6902 spi RTC driver");
+MODULE_AUTHOR ("Raphael Assenat");
+MODULE_LICENSE ("GPL");
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
new file mode 100644
index 0000000..b235a30
--- /dev/null
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -0,0 +1,394 @@
+/*
+ * drivers/rtc/rtc-pcf8583.c
+ *
+ * Copyright (C) 2000 Russell King
+ *
+ * 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.
+ *
+ * Driver for PCF8583 RTC & RAM chip
+ *
+ * Converted to the generic RTC susbsystem by G. Liakhovetski (2006)
+ */
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/bcd.h>
+
+struct rtc_mem {
+ unsigned int loc;
+ unsigned int nr;
+ unsigned char *data;
+};
+
+struct pcf8583 {
+ struct i2c_client client;
+ struct rtc_device *rtc;
+ unsigned char ctrl;
+};
+
+#define CTRL_STOP 0x80
+#define CTRL_HOLD 0x40
+#define CTRL_32KHZ 0x00
+#define CTRL_MASK 0x08
+#define CTRL_ALARMEN 0x04
+#define CTRL_ALARM 0x02
+#define CTRL_TIMER 0x01
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Module parameters */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver pcf8583_driver;
+
+#define get_ctrl(x) ((struct pcf8583 *)i2c_get_clientdata(x))->ctrl
+#define set_ctrl(x, v) get_ctrl(x) = v
+
+#define CMOS_YEAR (64 + 128)
+#define CMOS_CHECKSUM (63)
+
+static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+{
+ unsigned char buf[8], addr[1] = { 1 };
+ struct i2c_msg msgs[2] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = addr,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 6,
+ .buf = buf,
+ }
+ };
+ int ret;
+
+ memset(buf, 0, sizeof(buf));
+
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret == 2) {
+ dt->tm_year = buf[4] >> 6;
+ dt->tm_wday = buf[5] >> 5;
+
+ buf[4] &= 0x3f;
+ buf[5] &= 0x1f;
+
+ dt->tm_sec = BCD_TO_BIN(buf[1]);
+ dt->tm_min = BCD_TO_BIN(buf[2]);
+ dt->tm_hour = BCD_TO_BIN(buf[3]);
+ dt->tm_mday = BCD_TO_BIN(buf[4]);
+ dt->tm_mon = BCD_TO_BIN(buf[5]);
+ }
+
+ return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
+{
+ unsigned char buf[8];
+ int ret, len = 6;
+
+ buf[0] = 0;
+ buf[1] = get_ctrl(client) | 0x80;
+ buf[2] = 0;
+ buf[3] = BIN_TO_BCD(dt->tm_sec);
+ buf[4] = BIN_TO_BCD(dt->tm_min);
+ buf[5] = BIN_TO_BCD(dt->tm_hour);
+
+ if (datetoo) {
+ len = 8;
+ buf[6] = BIN_TO_BCD(dt->tm_mday) | (dt->tm_year << 6);
+ buf[7] = BIN_TO_BCD(dt->tm_mon) | (dt->tm_wday << 5);
+ }
+
+ ret = i2c_master_send(client, (char *)buf, len);
+ if (ret != len)
+ return -EIO;
+
+ buf[1] = get_ctrl(client);
+ ret = i2c_master_send(client, (char *)buf, 2);
+
+ return ret == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+ *ctrl = get_ctrl(client);
+ return 0;
+}
+
+static int pcf8583_set_ctrl(struct i2c_client *client, unsigned char *ctrl)
+{
+ unsigned char buf[2];
+
+ buf[0] = 0;
+ buf[1] = *ctrl;
+ set_ctrl(client, *ctrl);
+
+ return i2c_master_send(client, (char *)buf, 2);
+}
+
+static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+ unsigned char addr[1];
+ struct i2c_msg msgs[2] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = addr,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = mem->nr,
+ .buf = mem->data,
+ }
+ };
+
+ if (mem->loc < 8)
+ return -EINVAL;
+
+ addr[0] = mem->loc;
+
+ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem)
+{
+ unsigned char addr[1];
+ struct i2c_msg msgs[2] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = addr,
+ }, {
+ .addr = client->addr,
+ .flags = I2C_M_NOSTART,
+ .len = mem->nr,
+ .buf = mem->data,
+ }
+ };
+
+ if (mem->loc < 8)
+ return -EINVAL;
+
+ addr[0] = mem->loc;
+
+ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
+}
+
+static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned char ctrl, year[2];
+ struct rtc_mem mem = { CMOS_YEAR, sizeof(year), year };
+ int real_year, year_offset, err;
+
+ /*
+ * Ensure that the RTC is running.
+ */
+ pcf8583_get_ctrl(client, &ctrl);
+ if (ctrl & (CTRL_STOP | CTRL_HOLD)) {
+ unsigned char new_ctrl = ctrl & ~(CTRL_STOP | CTRL_HOLD);
+
+ printk(KERN_WARNING "RTC: resetting control %02x -> %02x\n",
+ ctrl, new_ctrl);
+
+ if ((err = pcf8583_set_ctrl(client, &new_ctrl)) < 0)
+ return err;
+ }
+
+ if (pcf8583_get_datetime(client, tm) ||
+ pcf8583_read_mem(client, &mem))
+ return -EIO;
+
+ real_year = year[0];
+
+ /*
+ * The RTC year holds the LSB two bits of the current
+ * year, which should reflect the LSB two bits of the
+ * CMOS copy of the year. Any difference indicates
+ * that we have to correct the CMOS version.
+ */
+ year_offset = tm->tm_year - (real_year & 3);
+ if (year_offset < 0)
+ /*
+ * RTC year wrapped. Adjust it appropriately.
+ */
+ year_offset += 4;
+
+ tm->tm_year = real_year + year_offset + year[1] * 100;
+
+ return 0;
+}
+
+static int pcf8583_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned char year[2], chk;
+ struct rtc_mem cmos_year = { CMOS_YEAR, sizeof(year), year };
+ struct rtc_mem cmos_check = { CMOS_CHECKSUM, 1, &chk };
+ int ret;
+
+ /*
+ * The RTC's own 2-bit year must reflect the least
+ * significant two bits of the CMOS year.
+ */
+
+ ret = pcf8583_set_datetime(client, tm, 1);
+ if (ret)
+ return ret;
+
+ ret = pcf8583_read_mem(client, &cmos_check);
+ if (ret)
+ return ret;
+
+ ret = pcf8583_read_mem(client, &cmos_year);
+ if (ret)
+ return ret;
+
+ chk -= year[1] + year[0];
+
+ year[1] = tm->tm_year / 100;
+ year[0] = tm->tm_year % 100;
+
+ chk += year[1] + year[0];
+
+ ret = pcf8583_write_mem(client, &cmos_year);
+
+ if (ret)
+ return ret;
+
+ ret = pcf8583_write_mem(client, &cmos_check);
+
+ return ret;
+}
+
+static struct rtc_class_ops pcf8583_rtc_ops = {
+ .read_time = pcf8583_rtc_read_time,
+ .set_time = pcf8583_rtc_set_time,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind);
+
+static int pcf8583_attach(struct i2c_adapter *adap)
+{
+ return i2c_probe(adap, &addr_data, pcf8583_probe);
+}
+
+static int pcf8583_detach(struct i2c_client *client)
+{
+ int err;
+ struct pcf8583 *pcf = i2c_get_clientdata(client);
+ struct rtc_device *rtc = pcf->rtc;
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ if ((err = i2c_detach_client(client)))
+ return err;
+
+ kfree(pcf);
+ return 0;
+}
+
+static struct i2c_driver pcf8583_driver = {
+ .driver = {
+ .name = "pcf8583",
+ },
+ .id = I2C_DRIVERID_PCF8583,
+ .attach_adapter = pcf8583_attach,
+ .detach_client = pcf8583_detach,
+};
+
+static int pcf8583_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct pcf8583 *pcf;
+ struct i2c_client *client;
+ struct rtc_device *rtc;
+ unsigned char buf[1], ad[1] = { 0 };
+ int err;
+ struct i2c_msg msgs[2] = {
+ {
+ .addr = addr,
+ .flags = 0,
+ .len = 1,
+ .buf = ad,
+ }, {
+ .addr = addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = buf,
+ }
+ };
+
+ pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
+ if (!pcf)
+ return -ENOMEM;
+
+ client = &pcf->client;
+
+ client->addr = addr;
+ client->adapter = adap;
+ client->driver = &pcf8583_driver;
+
+ strlcpy(client->name, pcf8583_driver.driver.name, I2C_NAME_SIZE);
+
+ if (i2c_transfer(client->adapter, msgs, 2) != 2) {
+ err = -EIO;
+ goto exit_kfree;
+ }
+
+ err = i2c_attach_client(client);
+
+ if (err)
+ goto exit_kfree;
+
+ rtc = rtc_device_register(pcf8583_driver.driver.name, &client->dev,
+ &pcf8583_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc)) {
+ err = PTR_ERR(rtc);
+ goto exit_detach;
+ }
+
+ pcf->rtc = rtc;
+ i2c_set_clientdata(client, pcf);
+ set_ctrl(client, buf[0]);
+
+ return 0;
+
+exit_detach:
+ i2c_detach_client(client);
+
+exit_kfree:
+ kfree(pcf);
+
+ return err;
+}
+
+static __init int pcf8583_init(void)
+{
+ return i2c_add_driver(&pcf8583_driver);
+}
+
+static __exit void pcf8583_exit(void)
+{
+ i2c_del_driver(&pcf8583_driver);
+}
+
+module_init(pcf8583_init);
+module_exit(pcf8583_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("PCF8583 I2C RTC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
new file mode 100644
index 0000000..ee53863
--- /dev/null
+++ b/drivers/rtc/rtc-pl031.c
@@ -0,0 +1,233 @@
+/*
+ * drivers/rtc/rtc-pl031.c
+ *
+ * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
+ *
+ * Author: Deepak Saxena <dsaxena@plexity.net>
+ *
+ * Copyright 2006 (c) MontaVista Software, Inc.
+ *
+ * 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/platform_device.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+
+#include <linux/amba/bus.h>
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/rtc.h>
+
+/*
+ * Register definitions
+ */
+#define RTC_DR 0x00 /* Data read register */
+#define RTC_MR 0x04 /* Match register */
+#define RTC_LR 0x08 /* Data load register */
+#define RTC_CR 0x0c /* Control register */
+#define RTC_IMSC 0x10 /* Interrupt mask and set register */
+#define RTC_RIS 0x14 /* Raw interrupt status register */
+#define RTC_MIS 0x18 /* Masked interrupt status register */
+#define RTC_ICR 0x1c /* Interrupt clear register */
+
+struct pl031_local {
+ struct rtc_device *rtc;
+ void __iomem *base;
+};
+
+static irqreturn_t pl031_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct rtc_device *rtc = dev_id;
+
+ rtc_update_irq(&rtc->class_dev, 1, RTC_AF);
+
+ return IRQ_HANDLED;
+}
+
+static int pl031_open(struct device *dev)
+{
+ /*
+ * We request IRQ in pl031_probe, so nothing to do here...
+ */
+ return 0;
+}
+
+static void pl031_release(struct device *dev)
+{
+}
+
+static int pl031_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct pl031_local *ldata = dev_get_drvdata(dev);
+
+ switch (cmd) {
+ case RTC_AIE_OFF:
+ __raw_writel(1, ldata->base + RTC_MIS);
+ return 0;
+ case RTC_AIE_ON:
+ __raw_writel(0, ldata->base + RTC_MIS);
+ return 0;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static int pl031_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct pl031_local *ldata = dev_get_drvdata(dev);
+
+ rtc_time_to_tm(__raw_readl(ldata->base + RTC_DR), tm);
+
+ return 0;
+}
+
+static int pl031_set_time(struct device *dev, struct rtc_time *tm)
+{
+ unsigned long time;
+ struct pl031_local *ldata = dev_get_drvdata(dev);
+
+ rtc_tm_to_time(tm, &time);
+ __raw_writel(time, ldata->base + RTC_LR);
+
+ return 0;
+}
+
+static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct pl031_local *ldata = dev_get_drvdata(dev);
+
+ rtc_time_to_tm(__raw_readl(ldata->base + RTC_MR), &alarm->time);
+ alarm->pending = __raw_readl(ldata->base + RTC_RIS);
+ alarm->enabled = __raw_readl(ldata->base + RTC_IMSC);
+
+ return 0;
+}
+
+static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct pl031_local *ldata = dev_get_drvdata(dev);
+ unsigned long time;
+
+ rtc_tm_to_time(&alarm->time, &time);
+
+ __raw_writel(time, ldata->base + RTC_MR);
+ __raw_writel(!alarm->enabled, ldata->base + RTC_MIS);
+
+ return 0;
+}
+
+static struct rtc_class_ops pl031_ops = {
+ .open = pl031_open,
+ .release = pl031_release,
+ .ioctl = pl031_ioctl,
+ .read_time = pl031_read_time,
+ .set_time = pl031_set_time,
+ .read_alarm = pl031_read_alarm,
+ .set_alarm = pl031_set_alarm,
+};
+
+static int pl031_remove(struct amba_device *adev)
+{
+ struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
+
+ if (ldata) {
+ dev_set_drvdata(&adev->dev, NULL);
+ free_irq(adev->irq[0], ldata->rtc);
+ rtc_device_unregister(ldata->rtc);
+ iounmap(ldata->base);
+ kfree(ldata);
+ }
+
+ return 0;
+}
+
+static int pl031_probe(struct amba_device *adev, void *id)
+{
+ int ret;
+ struct pl031_local *ldata;
+
+
+ ldata = kmalloc(sizeof(struct pl031_local), GFP_KERNEL);
+ if (!ldata) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ dev_set_drvdata(&adev->dev, ldata);
+
+ ldata->base = ioremap(adev->res.start,
+ adev->res.end - adev->res.start + 1);
+ if (!ldata->base) {
+ ret = -ENOMEM;
+ goto out_no_remap;
+ }
+
+ if (request_irq(adev->irq[0], pl031_interrupt, SA_INTERRUPT,
+ "rtc-pl031", ldata->rtc)) {
+ ret = -EIO;
+ goto out_no_irq;
+ }
+
+ ldata->rtc = rtc_device_register("pl031", &adev->dev, &pl031_ops,
+ THIS_MODULE);
+ if (IS_ERR(ldata->rtc)) {
+ ret = PTR_ERR(ldata->rtc);
+ goto out_no_rtc;
+ }
+
+ return 0;
+
+out_no_rtc:
+ free_irq(adev->irq[0], ldata->rtc);
+out_no_irq:
+ iounmap(ldata->base);
+out_no_remap:
+ dev_set_drvdata(&adev->dev, NULL);
+ kfree(ldata);
+out:
+ return ret;
+}
+
+static struct amba_id pl031_ids[] __initdata = {
+ {
+ .id = 0x00041031,
+ .mask = 0x000fffff, },
+ {0, 0},
+};
+
+static struct amba_driver pl031_driver = {
+ .drv = {
+ .name = "rtc-pl031",
+ },
+ .id_table = pl031_ids,
+ .probe = pl031_probe,
+ .remove = pl031_remove,
+};
+
+static int __init pl031_init(void)
+{
+ return amba_driver_register(&pl031_driver);
+}
+
+static void __exit pl031_exit(void)
+{
+ amba_driver_unregister(&pl031_driver);
+}
+
+module_init(pl031_init);
+module_exit(pl031_exit);
+
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net");
+MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index a997529..ab486fb 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -229,8 +229,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
spin_unlock_irq(&sa1100_rtc_lock);
return 0;
case RTC_PIE_ON:
- if ((rtc_freq > 64) && !capable(CAP_SYS_RESOURCE))
- return -EACCES;
spin_lock_irq(&sa1100_rtc_lock);
OSMR1 = TIMER_FREQ/rtc_freq + OSCR;
OIER |= OIER_E1;
@@ -242,8 +240,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
case RTC_IRQP_SET:
if (arg < 1 || arg > TIMER_FREQ)
return -EINVAL;
- if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
- return -EACCES;
rtc_freq = arg;
return 0;
}
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
new file mode 100644
index 0000000..a40f400
--- /dev/null
+++ b/drivers/rtc/rtc-v3020.c
@@ -0,0 +1,264 @@
+/* drivers/rtc/rtc-v3020.c
+ *
+ * Copyright (C) 2006 8D Technologies inc.
+ * Copyright (C) 2004 Compulab Ltd.
+ *
+ * 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.
+ *
+ * Driver for the V3020 RTC
+ *
+ * Changelog:
+ *
+ * 10-May-2006: Raphael Assenat <raph@8d.com>
+ * - Converted to platform driver
+ * - Use the generic rtc class
+ *
+ * ??-???-2004: Someone at Compulab
+ * - Initial driver creation.
+ *
+ */
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/rtc.h>
+#include <linux/types.h>
+#include <linux/bcd.h>
+#include <linux/rtc-v3020.h>
+
+#include <asm/io.h>
+
+#undef DEBUG
+
+struct v3020 {
+ void __iomem *ioaddress;
+ int leftshift;
+ struct rtc_device *rtc;
+};
+
+static void v3020_set_reg(struct v3020 *chip, unsigned char address,
+ unsigned char data)
+{
+ int i;
+ unsigned char tmp;
+
+ tmp = address;
+ for (i = 0; i < 4; i++) {
+ writel((tmp & 1) << chip->leftshift, chip->ioaddress);
+ tmp >>= 1;
+ }
+
+ /* Commands dont have data */
+ if (!V3020_IS_COMMAND(address)) {
+ for (i = 0; i < 8; i++) {
+ writel((data & 1) << chip->leftshift, chip->ioaddress);
+ data >>= 1;
+ }
+ }
+}
+
+static unsigned char v3020_get_reg(struct v3020 *chip, unsigned char address)
+{
+ unsigned int data=0;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ writel((address & 1) << chip->leftshift, chip->ioaddress);
+ address >>= 1;
+ }
+
+ for (i = 0; i < 8; i++) {
+ data >>= 1;
+ if (readl(chip->ioaddress) & (1 << chip->leftshift))
+ data |= 0x80;
+ }
+
+ return data;
+}
+
+static int v3020_read_time(struct device *dev, struct rtc_time *dt)
+{
+ struct v3020 *chip = dev_get_drvdata(dev);
+ int tmp;
+
+ /* Copy the current time to ram... */
+ v3020_set_reg(chip, V3020_CMD_CLOCK2RAM, 0);
+
+ /* ...and then read constant values. */
+ tmp = v3020_get_reg(chip, V3020_SECONDS);
+ dt->tm_sec = BCD2BIN(tmp);
+ tmp = v3020_get_reg(chip, V3020_MINUTES);
+ dt->tm_min = BCD2BIN(tmp);
+ tmp = v3020_get_reg(chip, V3020_HOURS);
+ dt->tm_hour = BCD2BIN(tmp);
+ tmp = v3020_get_reg(chip, V3020_MONTH_DAY);
+ dt->tm_mday = BCD2BIN(tmp);
+ tmp = v3020_get_reg(chip, V3020_MONTH);
+ dt->tm_mon = BCD2BIN(tmp);
+ tmp = v3020_get_reg(chip, V3020_WEEK_DAY);
+ dt->tm_wday = BCD2BIN(tmp);
+ tmp = v3020_get_reg(chip, V3020_YEAR);
+ dt->tm_year = BCD2BIN(tmp)+100;
+
+#ifdef DEBUG
+ printk("\n%s : Read RTC values\n",__FUNCTION__);
+ printk("tm_hour: %i\n",dt->tm_hour);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_sec : %i\n",dt->tm_sec);
+ printk("tm_year: %i\n",dt->tm_year);
+ printk("tm_mon : %i\n",dt->tm_mon);
+ printk("tm_mday: %i\n",dt->tm_mday);
+ printk("tm_wday: %i\n",dt->tm_wday);
+#endif
+
+ return 0;
+}
+
+
+static int v3020_set_time(struct device *dev, struct rtc_time *dt)
+{
+ struct v3020 *chip = dev_get_drvdata(dev);
+
+#ifdef DEBUG
+ printk("\n%s : Setting RTC values\n",__FUNCTION__);
+ printk("tm_sec : %i\n",dt->tm_sec);
+ printk("tm_min : %i\n",dt->tm_min);
+ printk("tm_hour: %i\n",dt->tm_hour);
+ printk("tm_mday: %i\n",dt->tm_mday);
+ printk("tm_wday: %i\n",dt->tm_wday);
+ printk("tm_year: %i\n",dt->tm_year);
+#endif
+
+ /* Write all the values to ram... */
+ v3020_set_reg(chip, V3020_SECONDS, BIN2BCD(dt->tm_sec));
+ v3020_set_reg(chip, V3020_MINUTES, BIN2BCD(dt->tm_min));
+ v3020_set_reg(chip, V3020_HOURS, BIN2BCD(dt->tm_hour));
+ v3020_set_reg(chip, V3020_MONTH_DAY, BIN2BCD(dt->tm_mday));
+ v3020_set_reg(chip, V3020_MONTH, BIN2BCD(dt->tm_mon));
+ v3020_set_reg(chip, V3020_WEEK_DAY, BIN2BCD(dt->tm_wday));
+ v3020_set_reg(chip, V3020_YEAR, BIN2BCD(dt->tm_year % 100));
+
+ /* ...and set the clock. */
+ v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0);
+
+ /* Compulab used this delay here. I dont know why,
+ * the datasheet does not specify a delay. */
+ /*mdelay(5);*/
+
+ return 0;
+}
+
+static struct rtc_class_ops v3020_rtc_ops = {
+ .read_time = v3020_read_time,
+ .set_time = v3020_set_time,
+};
+
+static int rtc_probe(struct platform_device *pdev)
+{
+ struct v3020_platform_data *pdata = pdev->dev.platform_data;
+ struct v3020 *chip;
+ struct rtc_device *rtc;
+ int retval = -EBUSY;
+ int i;
+ int temp;
+
+ if (pdev->num_resources != 1)
+ return -EBUSY;
+
+ if (pdev->resource[0].flags != IORESOURCE_MEM)
+ return -EBUSY;
+
+ if (pdev == NULL)
+ return -EBUSY;
+
+ chip = kzalloc(sizeof *chip, GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->leftshift = pdata->leftshift;
+ chip->ioaddress = ioremap(pdev->resource[0].start, 1);
+ if (chip->ioaddress == NULL)
+ goto err_chip;
+
+ /* Make sure the v3020 expects a communication cycle
+ * by reading 8 times */
+ for (i = 0; i < 8; i++)
+ temp = readl(chip->ioaddress);
+
+ /* Test chip by doing a write/read sequence
+ * to the chip ram */
+ v3020_set_reg(chip, V3020_SECONDS, 0x33);
+ if(v3020_get_reg(chip, V3020_SECONDS) != 0x33) {
+ retval = -ENODEV;
+ goto err_io;
+ }
+
+ /* Make sure frequency measurment mode, test modes, and lock
+ * are all disabled */
+ v3020_set_reg(chip, V3020_STATUS_0, 0x0);
+
+ dev_info(&pdev->dev, "Chip available at physical address 0x%p,"
+ "data connected to D%d\n",
+ (void*)pdev->resource[0].start,
+ chip->leftshift);
+
+ platform_set_drvdata(pdev, chip);
+
+ rtc = rtc_device_register("v3020",
+ &pdev->dev, &v3020_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc)) {
+ retval = PTR_ERR(rtc);
+ goto err_io;
+ }
+ chip->rtc = rtc;
+
+ return 0;
+
+err_io:
+ iounmap(chip->ioaddress);
+err_chip:
+ kfree(chip);
+
+ return retval;
+}
+
+static int rtc_remove(struct platform_device *dev)
+{
+ struct v3020 *chip = platform_get_drvdata(dev);
+ struct rtc_device *rtc = chip->rtc;
+
+ if (rtc)
+ rtc_device_unregister(rtc);
+
+ iounmap(chip->ioaddress);
+ kfree(chip);
+
+ return 0;
+}
+
+static struct platform_driver rtc_device_driver = {
+ .probe = rtc_probe,
+ .remove = rtc_remove,
+ .driver = {
+ .name = "v3020",
+ .owner = THIS_MODULE,
+ },
+};
+
+static __init int v3020_init(void)
+{
+ return platform_driver_register(&rtc_device_driver);
+}
+
+static __exit void v3020_exit(void)
+{
+ platform_driver_unregister(&rtc_device_driver);
+}
+
+module_init(v3020_init);
+module_exit(v3020_exit);
+
+MODULE_DESCRIPTION("V3020 RTC");
+MODULE_AUTHOR("Raphael Assenat");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 277596c..33e0292 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -81,7 +81,6 @@ MODULE_LICENSE("GPL");
#define RTC_FREQUENCY 32768
#define MAX_PERIODIC_RATE 6553
-#define MAX_USER_PERIODIC_RATE 64
static void __iomem *rtc1_base;
static void __iomem *rtc2_base;
@@ -240,9 +239,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
if (arg > MAX_PERIODIC_RATE)
return -EINVAL;
- if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0)
- return -EACCES;
-
periodic_frequency = arg;
count = RTC_FREQUENCY;
@@ -263,10 +259,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
/* Doesn't support before 1900 */
if (arg < 1900)
return -EINVAL;
-
- if (capable(CAP_SYS_TIME) == 0)
- return -EACCES;
-
epoch = arg;
break;
default:
diff --git a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
index 56fa691..a4c53c1 100644
--- a/drivers/s390/char/sclp_quiesce.c
+++ b/drivers/s390/char/sclp_quiesce.c
@@ -13,6 +13,7 @@
#include <linux/cpumask.h>
#include <linux/smp.h>
#include <linux/init.h>
+#include <linux/reboot.h>
#include <asm/atomic.h>
#include <asm/ptrace.h>
#include <asm/sigp.h>
@@ -66,8 +67,6 @@ do_machine_quiesce(void)
}
#endif
-extern void ctrl_alt_del(void);
-
/* Handler for quiesce event. Start shutdown procedure. */
static void
sclp_quiesce_handler(struct evbuf_header *evbuf)
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index 5ae684c..31b8a5f 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -71,7 +71,6 @@ flash_mmap(struct file *file, struct vm_area_struct *vma)
if (vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT)) > size)
size = vma->vm_end - (vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT));
- vma->vm_flags |= (VM_SHM | VM_LOCKED);
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (io_remap_pfn_range(vma, vma->vm_start, addr, size, vma->vm_page_prot))
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
index dfdd6be..ddcd330 100644
--- a/drivers/sbus/char/vfc_dev.c
+++ b/drivers/sbus/char/vfc_dev.c
@@ -623,7 +623,7 @@ static int vfc_mmap(struct file *file, struct vm_area_struct *vma)
map_size = sizeof(struct vfc_regs);
vma->vm_flags |=
- (VM_SHM | VM_LOCKED | VM_IO | VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
+ (VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE);
map_offset = (unsigned int) (long)dev->phys_regs;
ret = io_remap_pfn_range(vma, vma->vm_start,
MK_IOSPACE_PFN(dev->which_io,
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 2a41963..5ee4755 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -17316,7 +17316,7 @@ AdvWaitEEPCmd(AdvPortAddr iop_base)
/*
* Write the EEPROM from 'cfg_buf'.
*/
-void
+void __init
AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
{
ushort *wbuf;
@@ -17383,7 +17383,7 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf)
/*
* Write the EEPROM from 'cfg_buf'.
*/
-void
+void __init
AdvSet38C0800EEPConfig(AdvPortAddr iop_base,
ADVEEP_38C0800_CONFIG *cfg_buf)
{
@@ -17451,7 +17451,7 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base,
/*
* Write the EEPROM from 'cfg_buf'.
*/
-void
+void __init
AdvSet38C1600EEPConfig(AdvPortAddr iop_base,
ADVEEP_38C1600_CONFIG *cfg_buf)
{
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index e31fadd6..118206d 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -43,9 +43,6 @@
/* #define DEBUG_MAC_ESP */
-#define mac_turnon_irq(x) mac_enable_irq(x)
-#define mac_turnoff_irq(x) mac_disable_irq(x)
-
extern void esp_handle(struct NCR_ESP *esp);
extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
@@ -639,13 +636,13 @@ static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length)
static void dma_ints_off(struct NCR_ESP * esp)
{
- mac_turnoff_irq(esp->irq);
+ disable_irq(esp->irq);
}
static void dma_ints_on(struct NCR_ESP * esp)
{
- mac_turnon_irq(esp->irq);
+ enable_irq(esp->irq);
}
/*
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index 777f9bc..a942a21 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -65,9 +65,6 @@
#define RESET_BOOT
#define DRIVER_SETUP
-#define ENABLE_IRQ() mac_enable_irq( IRQ_MAC_SCSI );
-#define DISABLE_IRQ() mac_disable_irq( IRQ_MAC_SCSI );
-
extern void via_scsi_clear(void);
#ifdef RESET_BOOT
@@ -351,7 +348,7 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." );
/* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
- mac_disable_irq(IRQ_MAC_SCSI);
+ disable_irq(IRQ_MAC_SCSI);
/* get in phase */
NCR5380_write( TARGET_COMMAND_REG,
@@ -369,7 +366,7 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance)
barrier();
/* switch on SCSI IRQ again */
- mac_enable_irq(IRQ_MAC_SCSI);
+ enable_irq(IRQ_MAC_SCSI);
printk(KERN_INFO " done\n" );
}
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index bec1424..b7caf60 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -714,7 +714,7 @@ megaraid_io_detach(adapter_t *adapter)
* . Allocate memory required for all the commands
* . Use internal library of FW routines, build up complete soft state
*/
-static int __init
+static int __devinit
megaraid_init_mbox(adapter_t *adapter)
{
struct pci_dev *pdev;
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index cc990be..2e2c1eb 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -332,11 +332,11 @@ static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
struct scatterlist *sg = sp->SCp.buffer;
while (sz >= 0) {
- sg[sz].dvma_address = dvma_map((unsigned long)page_address(sg[sz].page) +
+ sg[sz].dma_address = dvma_map((unsigned long)page_address(sg[sz].page) +
sg[sz].offset, sg[sz].length);
sz--;
}
- sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address);
+ sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dma_address);
}
static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, Scsi_Cmnd *sp)
@@ -350,14 +350,14 @@ static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, Scsi_Cmnd *sp)
struct scatterlist *sg = (struct scatterlist *)sp->buffer;
while(sz >= 0) {
- dvma_unmap((char *)sg[sz].dvma_address);
+ dvma_unmap((char *)sg[sz].dma_address);
sz--;
}
}
static void dma_advance_sg (Scsi_Cmnd *sp)
{
- sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
+ sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dma_address);
}
static int sun3x_esp_release(struct Scsi_Host *instance)
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index e55f0ee..574955b 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1391,7 +1391,7 @@ static int wd7000_proc_info(struct Scsi_Host *host, char *buffer, char **start,
*
*/
-static int wd7000_detect(struct scsi_host_template *tpnt)
+static __init int wd7000_detect(struct scsi_host_template *tpnt)
{
short present = 0, biosaddr_ptr, sig_ptr, i, pass;
short biosptr[NUM_CONFIGS];
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 5a2840a..168ede7 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -86,6 +86,11 @@ config FB_FIRMWARE_EDID
combination with certain motherboards and monitors are known to
suffer from this problem.
+config FB_BACKLIGHT
+ bool
+ depends on FB
+ default n
+
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
depends on FB
@@ -717,6 +722,16 @@ config FB_NVIDIA_I2C
independently validate video mode parameters, you should say Y
here.
+config FB_NVIDIA_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_NVIDIA && PPC_PMAC
+ select FB_BACKLIGHT
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
config FB_RIVA
tristate "nVidia Riva support"
depends on FB && PCI
@@ -755,6 +770,16 @@ config FB_RIVA_DEBUG
of debugging informations to provide to the maintainer when
something goes wrong.
+config FB_RIVA_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_RIVA && PPC_PMAC
+ select FB_BACKLIGHT
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
config FB_I810
tristate "Intel 810/815 support (EXPERIMENTAL)"
depends on FB && EXPERIMENTAL && PCI && X86_32
@@ -993,6 +1018,7 @@ config FB_RADEON
There is a product page at
http://apps.ati.com/ATIcompare/
+
config FB_RADEON_I2C
bool "DDC/I2C for ATI Radeon support"
depends on FB_RADEON
@@ -1000,6 +1026,16 @@ config FB_RADEON_I2C
help
Say Y here if you want DDC/I2C support for your Radeon board.
+config FB_RADEON_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_RADEON && PPC_PMAC
+ select FB_BACKLIGHT
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
config FB_RADEON_DEBUG
bool "Lots of debug output from Radeon driver"
depends on FB_RADEON
@@ -1024,6 +1060,16 @@ config FB_ATY128
To compile this driver as a module, choose M here: the
module will be called aty128fb.
+config FB_ATY128_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_ATY128 && PPC_PMAC
+ select FB_BACKLIGHT
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
config FB_ATY
tristate "ATI Mach64 display support" if PCI || ATARI
depends on FB && !SPARC32
@@ -1066,6 +1112,16 @@ config FB_ATY_GX
is at
<http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
+config FB_ATY_BACKLIGHT
+ bool "Support for backlight control"
+ depends on FB_ATY && PPC_PMAC
+ select FB_BACKLIGHT
+ select BACKLIGHT_LCD_SUPPORT
+ select BACKLIGHT_CLASS_DEVICE
+ default y
+ help
+ Say Y here if you want to control the backlight of your display.
+
config FB_S3TRIO
bool "S3 Trio display support"
depends on (FB = y) && PPC && BROKEN
diff --git a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
index 1852139..a6cc0e9 100644
--- a/drivers/video/aty/Makefile
+++ b/drivers/video/aty/Makefile
@@ -10,5 +10,6 @@ atyfb-objs := $(atyfb-y)
radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o
radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o
+radeonfb-$(CONFIG_FB_RADEON_BACKLIGHT) += radeon_backlight.o
radeonfb-objs := $(radeonfb-y)
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index f7bbff4..db878fd 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -64,6 +64,7 @@
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/console.h>
+#include <linux/backlight.h>
#include <asm/io.h>
#ifdef CONFIG_PPC_PMAC
@@ -480,16 +481,6 @@ static struct fb_ops aty128fb_ops = {
.fb_imageblit = cfb_imageblit,
};
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int aty128_set_backlight_enable(int on, int level, void* data);
-static int aty128_set_backlight_level(int level, void* data);
-
-static struct backlight_controller aty128_backlight_controller = {
- aty128_set_backlight_enable,
- aty128_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
/*
* Functions to read from/write to the mmio registers
* - endian conversions may possibly be avoided by
@@ -1258,19 +1249,35 @@ static void aty128_set_crt_enable(struct aty128fb_par *par, int on)
static void aty128_set_lcd_enable(struct aty128fb_par *par, int on)
{
u32 reg;
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+#endif
if (on) {
reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION;
reg &= ~LVDS_DISPLAY_DIS;
aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef CONFIG_PMAC_BACKLIGHT
- aty128_set_backlight_enable(get_backlight_enable(),
- get_backlight_level(), par);
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+ mutex_unlock(&info->bl_mutex);
#endif
} else {
-#ifdef CONFIG_PMAC_BACKLIGHT
- aty128_set_backlight_enable(0, 0, par);
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->brightness = 0;
+ info->bl_dev->props->power = FB_BLANK_POWERDOWN;
+ info->bl_dev->props->update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+ mutex_unlock(&info->bl_mutex);
#endif
reg = aty_ld_le32(LVDS_GEN_CNTL);
reg |= LVDS_DISPLAY_DIS;
@@ -1691,6 +1698,184 @@ static int __init aty128fb_setup(char *options)
}
#endif /* MODULE */
+/* Backlight */
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+#define MAX_LEVEL 0xFF
+
+static struct backlight_properties aty128_bl_data;
+
+static int aty128_bl_get_level_brightness(struct aty128fb_par *par,
+ int level)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ int atylevel;
+
+ /* Get and convert the value */
+ mutex_lock(&info->bl_mutex);
+ atylevel = MAX_LEVEL -
+ (info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL);
+ mutex_unlock(&info->bl_mutex);
+
+ if (atylevel < 0)
+ atylevel = 0;
+ else if (atylevel > MAX_LEVEL)
+ atylevel = MAX_LEVEL;
+
+ return atylevel;
+}
+
+/* We turn off the LCD completely instead of just dimming the backlight.
+ * This provides greater power saving and the display is useless without
+ * backlight anyway
+ */
+#define BACKLIGHT_LVDS_OFF
+/* That one prevents proper CRT output with LCD off */
+#undef BACKLIGHT_DAC_OFF
+
+static int aty128_bl_update_status(struct backlight_device *bd)
+{
+ struct aty128fb_par *par = class_get_devdata(&bd->class_dev);
+ unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
+ int level;
+
+ if (bd->props->power != FB_BLANK_UNBLANK ||
+ bd->props->fb_blank != FB_BLANK_UNBLANK ||
+ !par->lcd_on)
+ level = 0;
+ else
+ level = bd->props->brightness;
+
+ reg |= LVDS_BL_MOD_EN | LVDS_BLON;
+ if (level > 0) {
+ reg |= LVDS_DIGION;
+ if (!(reg & LVDS_ON)) {
+ reg &= ~LVDS_BLON;
+ aty_st_le32(LVDS_GEN_CNTL, reg);
+ aty_ld_le32(LVDS_GEN_CNTL);
+ mdelay(10);
+ reg |= LVDS_BLON;
+ aty_st_le32(LVDS_GEN_CNTL, reg);
+ }
+ reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+ reg |= (aty128_bl_get_level_brightness(par, level) << LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+ reg |= LVDS_ON | LVDS_EN;
+ reg &= ~LVDS_DISPLAY_DIS;
+#endif
+ aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+ aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
+#endif
+ } else {
+ reg &= ~LVDS_BL_MOD_LEVEL_MASK;
+ reg |= (aty128_bl_get_level_brightness(par, 0) << LVDS_BL_MOD_LEVEL_SHIFT);
+#ifdef BACKLIGHT_LVDS_OFF
+ reg |= LVDS_DISPLAY_DIS;
+ aty_st_le32(LVDS_GEN_CNTL, reg);
+ aty_ld_le32(LVDS_GEN_CNTL);
+ udelay(10);
+ reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
+#endif
+ aty_st_le32(LVDS_GEN_CNTL, reg);
+#ifdef BACKLIGHT_DAC_OFF
+ aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
+#endif
+ }
+
+ return 0;
+}
+
+static int aty128_bl_get_brightness(struct backlight_device *bd)
+{
+ return bd->props->brightness;
+}
+
+static struct backlight_properties aty128_bl_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = aty128_bl_get_brightness,
+ .update_status = aty128_bl_update_status,
+ .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+static void aty128_bl_init(struct aty128fb_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ struct backlight_device *bd;
+ char name[12];
+
+ /* Could be extended to Rage128Pro LVDS output too */
+ if (par->chip_gen != rage_M3)
+ return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (!pmac_has_backlight_type("ati"))
+ return;
+#endif
+
+ snprintf(name, sizeof(name), "aty128bl%d", info->node);
+
+ bd = backlight_device_register(name, par, &aty128_bl_data);
+ if (IS_ERR(bd)) {
+ info->bl_dev = NULL;
+ printk("aty128: Backlight registration failed\n");
+ goto error;
+ }
+
+ mutex_lock(&info->bl_mutex);
+ info->bl_dev = bd;
+ fb_bl_default_curve(info, 0,
+ 63 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+ 219 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+ mutex_unlock(&info->bl_mutex);
+
+ up(&bd->sem);
+ bd->props->brightness = aty128_bl_data.max_brightness;
+ bd->props->power = FB_BLANK_UNBLANK;
+ bd->props->update_status(bd);
+ down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+ if (!pmac_backlight)
+ pmac_backlight = bd;
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+ printk("aty128: Backlight initialized (%s)\n", name);
+
+ return;
+
+error:
+ return;
+}
+
+static void aty128_bl_exit(struct aty128fb_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+#endif
+
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (pmac_backlight == info->bl_dev)
+ pmac_backlight = NULL;
+#endif
+
+ backlight_device_unregister(info->bl_dev);
+ info->bl_dev = NULL;
+
+ printk("aty128: Backlight unloaded\n");
+ }
+ mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
+#endif /* CONFIG_FB_ATY128_BACKLIGHT */
/*
* Initialisation
@@ -1835,17 +2020,15 @@ static int __init aty128_init(struct pci_dev *pdev, const struct pci_device_id *
if (register_framebuffer(info) < 0)
return 0;
-#ifdef CONFIG_PMAC_BACKLIGHT
- /* Could be extended to Rage128Pro LVDS output too */
- if (par->chip_gen == rage_M3)
- register_backlight_controller(&aty128_backlight_controller, par, "ati");
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
par->pm_reg = pci_find_capability(pdev, PCI_CAP_ID_PM);
par->pdev = pdev;
par->asleep = 0;
par->lock_blank = 0;
-
+
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+ aty128_bl_init(par);
+#endif
+
printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
info->node, info->fix.id, video_card);
@@ -1981,6 +2164,10 @@ static void __devexit aty128_remove(struct pci_dev *pdev)
par = info->par;
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+ aty128_bl_exit(par);
+#endif
+
unregister_framebuffer(info);
#ifdef CONFIG_MTRR
if (par->mtrr.vram_valid)
@@ -2011,10 +2198,14 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
if (par->lock_blank || par->asleep)
return 0;
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (machine_is(powermac) && blank)
- set_backlight_enable(0);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+ if (machine_is(powermac) && blank) {
+ down(&fb->bl_dev->sem);
+ fb->bl_dev->props->power = FB_BLANK_POWERDOWN;
+ fb->bl_dev->props->update_status(fb->bl_dev);
+ up(&fb->bl_dev->sem);
+ }
+#endif
if (blank & FB_BLANK_VSYNC_SUSPEND)
state |= 2;
@@ -2029,10 +2220,14 @@ static int aty128fb_blank(int blank, struct fb_info *fb)
aty128_set_crt_enable(par, par->crt_on && !blank);
aty128_set_lcd_enable(par, par->lcd_on && !blank);
}
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (machine_is(powermac) && !blank)
- set_backlight_enable(1);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#ifdef CONFIG_FB_ATY128_BACKLIGHT
+ if (machine_is(powermac) && !blank) {
+ down(&fb->bl_dev->sem);
+ fb->bl_dev->props->power = FB_BLANK_UNBLANK;
+ fb->bl_dev->props->update_status(fb->bl_dev);
+ up(&fb->bl_dev->sem);
+ }
+#endif
return 0;
}
@@ -2138,73 +2333,6 @@ static int aty128fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
return -EINVAL;
}
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int backlight_conv[] = {
- 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
- 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
-};
-
-/* We turn off the LCD completely instead of just dimming the backlight.
- * This provides greater power saving and the display is useless without
- * backlight anyway
- */
-#define BACKLIGHT_LVDS_OFF
-/* That one prevents proper CRT output with LCD off */
-#undef BACKLIGHT_DAC_OFF
-
-static int aty128_set_backlight_enable(int on, int level, void *data)
-{
- struct aty128fb_par *par = data;
- unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
-
- if (!par->lcd_on)
- on = 0;
- reg |= LVDS_BL_MOD_EN | LVDS_BLON;
- if (on && level > BACKLIGHT_OFF) {
- reg |= LVDS_DIGION;
- if (!(reg & LVDS_ON)) {
- reg &= ~LVDS_BLON;
- aty_st_le32(LVDS_GEN_CNTL, reg);
- (void)aty_ld_le32(LVDS_GEN_CNTL);
- mdelay(10);
- reg |= LVDS_BLON;
- aty_st_le32(LVDS_GEN_CNTL, reg);
- }
- reg &= ~LVDS_BL_MOD_LEVEL_MASK;
- reg |= (backlight_conv[level] << LVDS_BL_MOD_LEVEL_SHIFT);
-#ifdef BACKLIGHT_LVDS_OFF
- reg |= LVDS_ON | LVDS_EN;
- reg &= ~LVDS_DISPLAY_DIS;
-#endif
- aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef BACKLIGHT_DAC_OFF
- aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & (~DAC_PDWN));
-#endif
- } else {
- reg &= ~LVDS_BL_MOD_LEVEL_MASK;
- reg |= (backlight_conv[0] << LVDS_BL_MOD_LEVEL_SHIFT);
-#ifdef BACKLIGHT_LVDS_OFF
- reg |= LVDS_DISPLAY_DIS;
- aty_st_le32(LVDS_GEN_CNTL, reg);
- (void)aty_ld_le32(LVDS_GEN_CNTL);
- udelay(10);
- reg &= ~(LVDS_ON | LVDS_EN | LVDS_BLON | LVDS_DIGION);
-#endif
- aty_st_le32(LVDS_GEN_CNTL, reg);
-#ifdef BACKLIGHT_DAC_OFF
- aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PDWN);
-#endif
- }
-
- return 0;
-}
-
-static int aty128_set_backlight_level(int level, void* data)
-{
- return aty128_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
#if 0
/*
* Accelerated functions
diff --git a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
index e9b7a64..43d2cb5 100644
--- a/drivers/video/aty/atyfb.h
+++ b/drivers/video/aty/atyfb.h
@@ -151,6 +151,7 @@ struct atyfb_par {
int lock_blank;
unsigned long res_start;
unsigned long res_size;
+ struct pci_dev *pdev;
#ifdef __sparc__
struct pci_mmap_map *mmap_map;
u8 mmaped;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index c054bb2..c5185f7 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -66,6 +66,7 @@
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
+#include <linux/backlight.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -2115,45 +2116,142 @@ static int atyfb_pci_resume(struct pci_dev *pdev)
#endif /* defined(CONFIG_PM) && defined(CONFIG_PCI) */
-#ifdef CONFIG_PMAC_BACKLIGHT
+/* Backlight */
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+#define MAX_LEVEL 0xFF
- /*
- * LCD backlight control
- */
+static struct backlight_properties aty_bl_data;
-static int backlight_conv[] = {
- 0x00, 0x3f, 0x4c, 0x59, 0x66, 0x73, 0x80, 0x8d,
- 0x9a, 0xa7, 0xb4, 0xc1, 0xcf, 0xdc, 0xe9, 0xff
-};
+static int aty_bl_get_level_brightness(struct atyfb_par *par, int level)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ int atylevel;
+
+ /* Get and convert the value */
+ mutex_lock(&info->bl_mutex);
+ atylevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
+ mutex_unlock(&info->bl_mutex);
+
+ if (atylevel < 0)
+ atylevel = 0;
+ else if (atylevel > MAX_LEVEL)
+ atylevel = MAX_LEVEL;
-static int aty_set_backlight_enable(int on, int level, void *data)
+ return atylevel;
+}
+
+static int aty_bl_update_status(struct backlight_device *bd)
{
- struct fb_info *info = (struct fb_info *) data;
- struct atyfb_par *par = (struct atyfb_par *) info->par;
+ struct atyfb_par *par = class_get_devdata(&bd->class_dev);
unsigned int reg = aty_ld_lcd(LCD_MISC_CNTL, par);
+ int level;
+
+ if (bd->props->power != FB_BLANK_UNBLANK ||
+ bd->props->fb_blank != FB_BLANK_UNBLANK)
+ level = 0;
+ else
+ level = bd->props->brightness;
reg |= (BLMOD_EN | BIASMOD_EN);
- if (on && level > BACKLIGHT_OFF) {
+ if (level > 0) {
reg &= ~BIAS_MOD_LEVEL_MASK;
- reg |= (backlight_conv[level] << BIAS_MOD_LEVEL_SHIFT);
+ reg |= (aty_bl_get_level_brightness(par, level) << BIAS_MOD_LEVEL_SHIFT);
} else {
reg &= ~BIAS_MOD_LEVEL_MASK;
- reg |= (backlight_conv[0] << BIAS_MOD_LEVEL_SHIFT);
+ reg |= (aty_bl_get_level_brightness(par, 0) << BIAS_MOD_LEVEL_SHIFT);
}
aty_st_lcd(LCD_MISC_CNTL, reg, par);
+
return 0;
}
-static int aty_set_backlight_level(int level, void *data)
+static int aty_bl_get_brightness(struct backlight_device *bd)
{
- return aty_set_backlight_enable(1, level, data);
+ return bd->props->brightness;
}
-static struct backlight_controller aty_backlight_controller = {
- aty_set_backlight_enable,
- aty_set_backlight_level
+static struct backlight_properties aty_bl_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = aty_bl_get_brightness,
+ .update_status = aty_bl_update_status,
+ .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
-#endif /* CONFIG_PMAC_BACKLIGHT */
+
+static void aty_bl_init(struct atyfb_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ struct backlight_device *bd;
+ char name[12];
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (!pmac_has_backlight_type("ati"))
+ return;
+#endif
+
+ snprintf(name, sizeof(name), "atybl%d", info->node);
+
+ bd = backlight_device_register(name, par, &aty_bl_data);
+ if (IS_ERR(bd)) {
+ info->bl_dev = NULL;
+ printk("aty: Backlight registration failed\n");
+ goto error;
+ }
+
+ mutex_lock(&info->bl_mutex);
+ info->bl_dev = bd;
+ fb_bl_default_curve(info, 0,
+ 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL,
+ 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL);
+ mutex_unlock(&info->bl_mutex);
+
+ up(&bd->sem);
+ bd->props->brightness = aty_bl_data.max_brightness;
+ bd->props->power = FB_BLANK_UNBLANK;
+ bd->props->update_status(bd);
+ down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+ if (!pmac_backlight)
+ pmac_backlight = bd;
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+ printk("aty: Backlight initialized (%s)\n", name);
+
+ return;
+
+error:
+ return;
+}
+
+static void aty_bl_exit(struct atyfb_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+#endif
+
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (pmac_backlight == info->bl_dev)
+ pmac_backlight = NULL;
+#endif
+
+ backlight_device_unregister(info->bl_dev);
+
+ printk("aty: Backlight unloaded\n");
+ }
+ mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
+
+#endif /* CONFIG_FB_ATY_BACKLIGHT */
static void __init aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
{
@@ -2513,9 +2611,13 @@ static int __init aty_init(struct fb_info *info, const char *name)
/* these bits let the 101 powerbook wake up from sleep -- paulus */
aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par)
| (USE_F32KHZ | TRISTATE_MEM_EN), par);
- } else if (M64_HAS(MOBIL_BUS))
- register_backlight_controller(&aty_backlight_controller, info, "ati");
-#endif /* CONFIG_PMAC_BACKLIGHT */
+ } else
+#endif
+ if (M64_HAS(MOBIL_BUS)) {
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+ aty_bl_init (par);
+#endif
+ }
memset(&var, 0, sizeof(var));
#ifdef CONFIG_PPC
@@ -2674,8 +2776,16 @@ static int atyfb_blank(int blank, struct fb_info *info)
return 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if (machine_is(powermac) && blank > FB_BLANK_NORMAL)
- set_backlight_enable(0);
+ if (machine_is(powermac) && blank > FB_BLANK_NORMAL) {
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = FB_BLANK_POWERDOWN;
+ info->bl_dev->props->update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+ mutex_unlock(&info->bl_mutex);
+ }
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank > FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -2706,8 +2816,16 @@ static int atyfb_blank(int blank, struct fb_info *info)
aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par);
#ifdef CONFIG_PMAC_BACKLIGHT
- if (machine_is(powermac) && blank <= FB_BLANK_NORMAL)
- set_backlight_enable(1);
+ if (machine_is(powermac) && blank <= FB_BLANK_NORMAL) {
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = FB_BLANK_UNBLANK;
+ info->bl_dev->props->update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
+ }
+ mutex_unlock(&info->bl_mutex);
+ }
#elif defined(CONFIG_FB_ATY_GENERIC_LCD)
if (par->lcd_table && blank <= FB_BLANK_NORMAL &&
(aty_ld_lcd(LCD_GEN_CNTL, par) & LCD_ON)) {
@@ -3440,6 +3558,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi
par->res_start = res_start;
par->res_size = res_size;
par->irq = pdev->irq;
+ par->pdev = pdev;
/* Setup "info" structure */
#ifdef __sparc__
@@ -3571,6 +3690,11 @@ static void __devexit atyfb_remove(struct fb_info *info)
aty_set_crtc(par, &saved_crtc);
par->pll_ops->set_pll(info, &saved_pll);
+#ifdef CONFIG_FB_ATY_BACKLIGHT
+ if (M64_HAS(MOBIL_BUS))
+ aty_bl_exit(par);
+#endif
+
unregister_framebuffer(info);
#ifdef CONFIG_MTRR
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c
new file mode 100644
index 0000000..7de66b8
--- /dev/null
+++ b/drivers/video/aty/radeon_backlight.c
@@ -0,0 +1,247 @@
+/*
+ * Backlight code for ATI Radeon based graphic cards
+ *
+ * Copyright (c) 2000 Ani Joshi <ajoshi@kernel.crashing.org>
+ * Copyright (c) 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * 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 "radeonfb.h"
+#include <linux/backlight.h>
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#define MAX_RADEON_LEVEL 0xFF
+
+static struct backlight_properties radeon_bl_data;
+
+struct radeon_bl_privdata {
+ struct radeonfb_info *rinfo;
+ uint8_t negative;
+};
+
+static int radeon_bl_get_level_brightness(struct radeon_bl_privdata *pdata,
+ int level)
+{
+ struct fb_info *info = pdata->rinfo->info;
+ int rlevel;
+
+ mutex_lock(&info->bl_mutex);
+
+ /* Get and convert the value */
+ rlevel = pdata->rinfo->info->bl_curve[level] *
+ FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL;
+
+ mutex_unlock(&info->bl_mutex);
+
+ if (pdata->negative)
+ rlevel = MAX_RADEON_LEVEL - rlevel;
+
+ if (rlevel < 0)
+ rlevel = 0;
+ else if (rlevel > MAX_RADEON_LEVEL)
+ rlevel = MAX_RADEON_LEVEL;
+
+ return rlevel;
+}
+
+static int radeon_bl_update_status(struct backlight_device *bd)
+{
+ struct radeon_bl_privdata *pdata = class_get_devdata(&bd->class_dev);
+ struct radeonfb_info *rinfo = pdata->rinfo;
+ u32 lvds_gen_cntl, tmpPixclksCntl;
+ int level;
+
+ if (rinfo->mon1_type != MT_LCD)
+ return 0;
+
+ /* We turn off the LCD completely instead of just dimming the
+ * backlight. This provides some greater power saving and the display
+ * is useless without backlight anyway.
+ */
+ if (bd->props->power != FB_BLANK_UNBLANK ||
+ bd->props->fb_blank != FB_BLANK_UNBLANK)
+ level = 0;
+ else
+ level = bd->props->brightness;
+
+ del_timer_sync(&rinfo->lvds_timer);
+ radeon_engine_idle();
+
+ lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
+ if (level > 0) {
+ lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
+ if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
+ lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
+ lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
+ OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+ lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+ lvds_gen_cntl |=
+ (radeon_bl_get_level_brightness(pdata, level) <<
+ LVDS_BL_MOD_LEVEL_SHIFT);
+ lvds_gen_cntl |= LVDS_ON;
+ lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
+ rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+ mod_timer(&rinfo->lvds_timer,
+ jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+ } else {
+ lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
+ lvds_gen_cntl |=
+ (radeon_bl_get_level_brightness(pdata, level) <<
+ LVDS_BL_MOD_LEVEL_SHIFT);
+ OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+ }
+ rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+ rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
+ & LVDS_STATE_MASK;
+ } else {
+ /* Asic bug, when turning off LVDS_ON, we have to make sure
+ RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
+ */
+ tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
+ if (rinfo->is_mobility || rinfo->is_IGP)
+ OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
+ lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
+ lvds_gen_cntl |= (radeon_bl_get_level_brightness(pdata, 0) <<
+ LVDS_BL_MOD_LEVEL_SHIFT);
+ lvds_gen_cntl |= LVDS_DISPLAY_DIS;
+ OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+ udelay(100);
+ lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
+ OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
+ lvds_gen_cntl &= ~(LVDS_DIGON);
+ rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
+ mod_timer(&rinfo->lvds_timer,
+ jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
+ if (rinfo->is_mobility || rinfo->is_IGP)
+ OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
+ }
+ rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
+ rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
+
+ return 0;
+}
+
+static int radeon_bl_get_brightness(struct backlight_device *bd)
+{
+ return bd->props->brightness;
+}
+
+static struct backlight_properties radeon_bl_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = radeon_bl_get_brightness,
+ .update_status = radeon_bl_update_status,
+ .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void radeonfb_bl_init(struct radeonfb_info *rinfo)
+{
+ struct backlight_device *bd;
+ struct radeon_bl_privdata *pdata;
+ char name[12];
+
+ if (rinfo->mon1_type != MT_LCD)
+ return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (!pmac_has_backlight_type("ati") &&
+ !pmac_has_backlight_type("mnca"))
+ return;
+#endif
+
+ pdata = kmalloc(sizeof(struct radeon_bl_privdata), GFP_KERNEL);
+ if (!pdata) {
+ printk("radeonfb: Memory allocation failed\n");
+ goto error;
+ }
+
+ snprintf(name, sizeof(name), "radeonbl%d", rinfo->info->node);
+
+ bd = backlight_device_register(name, pdata, &radeon_bl_data);
+ if (IS_ERR(bd)) {
+ rinfo->info->bl_dev = NULL;
+ printk("radeonfb: Backlight registration failed\n");
+ goto error;
+ }
+
+ pdata->rinfo = rinfo;
+
+ /* Pardon me for that hack... maybe some day we can figure out in what
+ * direction backlight should work on a given panel?
+ */
+ pdata->negative =
+ (rinfo->family != CHIP_FAMILY_RV200 &&
+ rinfo->family != CHIP_FAMILY_RV250 &&
+ rinfo->family != CHIP_FAMILY_RV280 &&
+ rinfo->family != CHIP_FAMILY_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ pdata->negative = pdata->negative ||
+ machine_is_compatible("PowerBook4,3") ||
+ machine_is_compatible("PowerBook6,3") ||
+ machine_is_compatible("PowerBook6,5");
+#endif
+
+ mutex_lock(&rinfo->info->bl_mutex);
+ rinfo->info->bl_dev = bd;
+ fb_bl_default_curve(rinfo->info, 0,
+ 63 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL,
+ 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL);
+ mutex_unlock(&rinfo->info->bl_mutex);
+
+ up(&bd->sem);
+ bd->props->brightness = radeon_bl_data.max_brightness;
+ bd->props->power = FB_BLANK_UNBLANK;
+ bd->props->update_status(bd);
+ down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+ if (!pmac_backlight)
+ pmac_backlight = bd;
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+ printk("radeonfb: Backlight initialized (%s)\n", name);
+
+ return;
+
+error:
+ kfree(pdata);
+ return;
+}
+
+void radeonfb_bl_exit(struct radeonfb_info *rinfo)
+{
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+#endif
+
+ mutex_lock(&rinfo->info->bl_mutex);
+ if (rinfo->info->bl_dev) {
+ struct radeon_bl_privdata *pdata;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (pmac_backlight == rinfo->info->bl_dev)
+ pmac_backlight = NULL;
+#endif
+
+ pdata = class_get_devdata(&rinfo->info->bl_dev->class_dev);
+ backlight_device_unregister(rinfo->info->bl_dev);
+ kfree(pdata);
+ rinfo->info->bl_dev = NULL;
+
+ printk("radeonfb: Backlight unloaded\n");
+ }
+ mutex_unlock(&rinfo->info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index 387a18a..c5ecbb0 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -78,10 +78,6 @@
#include <asm/pci-bridge.h>
#include "../macmodes.h"
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/backlight.h>
-#endif
-
#ifdef CONFIG_BOOTX_TEXT
#include <asm/btext.h>
#endif
@@ -277,20 +273,6 @@ static int nomtrr = 0;
* prototypes
*/
-
-#ifdef CONFIG_PPC_OF
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int radeon_set_backlight_enable(int on, int level, void *data);
-static int radeon_set_backlight_level(int level, void *data);
-static struct backlight_controller radeon_backlight_controller = {
- radeon_set_backlight_enable,
- radeon_set_backlight_level
-};
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-#endif /* CONFIG_PPC_OF */
-
static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev)
{
if (!rinfo->bios_seg)
@@ -1913,116 +1895,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
return 0;
}
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-
-/* TODO: Dbl check these tables, we don't go up to full ON backlight
- * in these, possibly because we noticed MacOS doesn't, but I'd prefer
- * having some more official numbers from ATI
- */
-static int backlight_conv_m6[] = {
- 0xff, 0xc0, 0xb5, 0xaa, 0x9f, 0x94, 0x89, 0x7e,
- 0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
-};
-static int backlight_conv_m7[] = {
- 0x00, 0x3f, 0x4a, 0x55, 0x60, 0x6b, 0x76, 0x81,
- 0x8c, 0x97, 0xa2, 0xad, 0xb8, 0xc3, 0xce, 0xd9
-};
-
-#define BACKLIGHT_LVDS_OFF
-#undef BACKLIGHT_DAC_OFF
-
-/* We turn off the LCD completely instead of just dimming the backlight.
- * This provides some greater power saving and the display is useless
- * without backlight anyway.
- */
-static int radeon_set_backlight_enable(int on, int level, void *data)
-{
- struct radeonfb_info *rinfo = (struct radeonfb_info *)data;
- u32 lvds_gen_cntl, tmpPixclksCntl;
- int* conv_table;
-
- if (rinfo->mon1_type != MT_LCD)
- return 0;
-
- /* Pardon me for that hack... maybe some day we can figure
- * out in what direction backlight should work on a given
- * panel ?
- */
- if ((rinfo->family == CHIP_FAMILY_RV200 ||
- rinfo->family == CHIP_FAMILY_RV250 ||
- rinfo->family == CHIP_FAMILY_RV280 ||
- rinfo->family == CHIP_FAMILY_RV350) &&
- !machine_is_compatible("PowerBook4,3") &&
- !machine_is_compatible("PowerBook6,3") &&
- !machine_is_compatible("PowerBook6,5"))
- conv_table = backlight_conv_m7;
- else
- conv_table = backlight_conv_m6;
-
- del_timer_sync(&rinfo->lvds_timer);
- radeon_engine_idle();
-
- lvds_gen_cntl = INREG(LVDS_GEN_CNTL);
- if (on && (level > BACKLIGHT_OFF)) {
- lvds_gen_cntl &= ~LVDS_DISPLAY_DIS;
- if (!(lvds_gen_cntl & LVDS_BLON) || !(lvds_gen_cntl & LVDS_ON)) {
- lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_DIGON);
- lvds_gen_cntl |= LVDS_BLON | LVDS_EN;
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
- lvds_gen_cntl |= (conv_table[level] <<
- LVDS_BL_MOD_LEVEL_SHIFT);
- lvds_gen_cntl |= LVDS_ON;
- lvds_gen_cntl |= (rinfo->init_state.lvds_gen_cntl & LVDS_BL_MOD_EN);
- rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
- mod_timer(&rinfo->lvds_timer,
- jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
- } else {
- lvds_gen_cntl &= ~LVDS_BL_MOD_LEVEL_MASK;
- lvds_gen_cntl |= (conv_table[level] <<
- LVDS_BL_MOD_LEVEL_SHIFT);
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- }
- rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
- rinfo->init_state.lvds_gen_cntl |= rinfo->pending_lvds_gen_cntl
- & LVDS_STATE_MASK;
- } else {
- /* Asic bug, when turning off LVDS_ON, we have to make sure
- RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
- */
- tmpPixclksCntl = INPLL(PIXCLKS_CNTL);
- if (rinfo->is_mobility || rinfo->is_IGP)
- OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
- lvds_gen_cntl &= ~(LVDS_BL_MOD_LEVEL_MASK | LVDS_BL_MOD_EN);
- lvds_gen_cntl |= (conv_table[0] <<
- LVDS_BL_MOD_LEVEL_SHIFT);
- lvds_gen_cntl |= LVDS_DISPLAY_DIS;
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- udelay(100);
- lvds_gen_cntl &= ~(LVDS_ON | LVDS_EN);
- OUTREG(LVDS_GEN_CNTL, lvds_gen_cntl);
- lvds_gen_cntl &= ~(LVDS_DIGON);
- rinfo->pending_lvds_gen_cntl = lvds_gen_cntl;
- mod_timer(&rinfo->lvds_timer,
- jiffies + msecs_to_jiffies(rinfo->panel_info.pwr_delay));
- if (rinfo->is_mobility || rinfo->is_IGP)
- OUTPLL(PIXCLKS_CNTL, tmpPixclksCntl);
- }
- rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
- rinfo->init_state.lvds_gen_cntl |= (lvds_gen_cntl & LVDS_STATE_MASK);
-
- return 0;
-}
-
-
-static int radeon_set_backlight_level(int level, void *data)
-{
- return radeon_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-
/*
* This reconfigure the card's internal memory map. In theory, we'd like
* to setup the card's memory at the same address as it's PCI bus address,
@@ -2477,14 +2349,7 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
MTRR_TYPE_WRCOMB, 1);
#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (rinfo->mon1_type == MT_LCD) {
- register_backlight_controller(&radeon_backlight_controller,
- rinfo, "ati");
- register_backlight_controller(&radeon_backlight_controller,
- rinfo, "mnca");
- }
-#endif
+ radeonfb_bl_init(rinfo);
printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name);
@@ -2528,7 +2393,8 @@ static void __devexit radeonfb_pci_unregister (struct pci_dev *pdev)
if (!rinfo)
return;
-
+
+ radeonfb_bl_exit(rinfo);
radeonfb_pm_exit(rinfo);
if (rinfo->mon1_EDID)
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
index 217e00a..1645943 100644
--- a/drivers/video/aty/radeonfb.h
+++ b/drivers/video/aty/radeonfb.h
@@ -625,4 +625,13 @@ extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_
extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
int reg_only);
+/* Backlight functions */
+#ifdef CONFIG_FB_RADEON_BACKLIGHT
+extern void radeonfb_bl_init(struct radeonfb_info *rinfo);
+extern void radeonfb_bl_exit(struct radeonfb_info *rinfo);
+#else
+static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {}
+static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {}
+#endif
+
#endif /* __RADEONFB_H__ */
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index 72ff6bf..d76bbfac 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -148,9 +148,24 @@ static int chipsfb_set_par(struct fb_info *info)
static int chipsfb_blank(int blank, struct fb_info *info)
{
#ifdef CONFIG_PMAC_BACKLIGHT
- // used to disable backlight only for blank > 1, but it seems
- // useful at blank = 1 too (saves battery, extends backlight life)
- set_backlight_enable(!blank);
+ mutex_lock(&pmac_backlight_mutex);
+
+ if (pmac_backlight) {
+ down(&pmac_backlight->sem);
+
+ /* used to disable backlight only for blank > 1, but it seems
+ * useful at blank = 1 too (saves battery, extends backlight
+ * life)
+ */
+ if (blank)
+ pmac_backlight->props->power = FB_BLANK_POWERDOWN;
+ else
+ pmac_backlight->props->power = FB_BLANK_UNBLANK;
+ pmac_backlight->props->update_status(pmac_backlight);
+ up(&pmac_backlight->sem);
+ }
+
+ mutex_unlock(&pmac_backlight_mutex);
#endif /* CONFIG_PMAC_BACKLIGHT */
return 1; /* get fb_blank to set the colormap to all black */
@@ -401,7 +416,14 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
#ifdef CONFIG_PMAC_BACKLIGHT
/* turn on the backlight */
- set_backlight_enable(1);
+ mutex_lock(&pmac_backlight_mutex);
+ if (pmac_backlight) {
+ down(&pmac_backlight->sem);
+ pmac_backlight->props->power = FB_BLANK_UNBLANK;
+ pmac_backlight->props->update_status(pmac_backlight);
+ up(&pmac_backlight->sem);
+ }
+ mutex_unlock(&pmac_backlight_mutex);
#endif /* CONFIG_PMAC_BACKLIGHT */
#ifdef CONFIG_PPC
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index 34e0739..3ceb8c1 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <linux/fb.h>
#include <linux/console.h>
+#include <linux/module.h>
/**
* framebuffer_alloc - creates a new frame buffer info structure
@@ -55,6 +56,10 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
info->device = dev;
+#ifdef CONFIG_FB_BACKLIGHT
+ mutex_init(&info->bl_mutex);
+#endif
+
return info;
#undef PADDING
#undef BYTES_PER_LONG
@@ -414,6 +419,65 @@ static ssize_t show_fbstate(struct class_device *class_device, char *buf)
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
}
+#ifdef CONFIG_FB_BACKLIGHT
+static ssize_t store_bl_curve(struct class_device *class_device,
+ const char *buf, size_t count)
+{
+ struct fb_info *fb_info = class_get_devdata(class_device);
+ u8 tmp_curve[FB_BACKLIGHT_LEVELS];
+ unsigned int i;
+
+ if (count != (FB_BACKLIGHT_LEVELS / 8 * 24))
+ return -EINVAL;
+
+ for (i = 0; i < (FB_BACKLIGHT_LEVELS / 8); ++i)
+ if (sscanf(&buf[i * 24],
+ "%2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx %2hhx\n",
+ &tmp_curve[i * 8 + 0],
+ &tmp_curve[i * 8 + 1],
+ &tmp_curve[i * 8 + 2],
+ &tmp_curve[i * 8 + 3],
+ &tmp_curve[i * 8 + 4],
+ &tmp_curve[i * 8 + 5],
+ &tmp_curve[i * 8 + 6],
+ &tmp_curve[i * 8 + 7]) != 8)
+ return -EINVAL;
+
+ /* If there has been an error in the input data, we won't
+ * reach this loop.
+ */
+ mutex_lock(&fb_info->bl_mutex);
+ for (i = 0; i < FB_BACKLIGHT_LEVELS; ++i)
+ fb_info->bl_curve[i] = tmp_curve[i];
+ mutex_unlock(&fb_info->bl_mutex);
+
+ return count;
+}
+
+static ssize_t show_bl_curve(struct class_device *class_device, char *buf)
+{
+ struct fb_info *fb_info = class_get_devdata(class_device);
+ ssize_t len = 0;
+ unsigned int i;
+
+ mutex_lock(&fb_info->bl_mutex);
+ for (i = 0; i < FB_BACKLIGHT_LEVELS; i += 8)
+ len += snprintf(&buf[len], PAGE_SIZE,
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ fb_info->bl_curve[i + 0],
+ fb_info->bl_curve[i + 1],
+ fb_info->bl_curve[i + 2],
+ fb_info->bl_curve[i + 3],
+ fb_info->bl_curve[i + 4],
+ fb_info->bl_curve[i + 5],
+ fb_info->bl_curve[i + 6],
+ fb_info->bl_curve[i + 7]);
+ mutex_unlock(&fb_info->bl_mutex);
+
+ return len;
+}
+#endif
+
/* When cmap is added back in it should be a binary attribute
* not a text one. Consideration should also be given to converting
* fbdev to use configfs instead of sysfs */
@@ -432,6 +496,9 @@ static struct class_device_attribute class_device_attrs[] = {
__ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate),
__ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all),
__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
+#ifdef CONFIG_FB_BACKLIGHT
+ __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
+#endif
};
int fb_init_class_device(struct fb_info *fb_info)
@@ -454,4 +521,25 @@ void fb_cleanup_class_device(struct fb_info *fb_info)
&class_device_attrs[i]);
}
+#ifdef CONFIG_FB_BACKLIGHT
+/* This function generates a linear backlight curve
+ *
+ * 0: off
+ * 1-7: min
+ * 8-127: linear from min to max
+ */
+void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max)
+{
+ unsigned int i, flat, count, range = (max - min);
+
+ fb_info->bl_curve[0] = off;
+ for (flat = 1; flat < (FB_BACKLIGHT_LEVELS / 16); ++flat)
+ fb_info->bl_curve[flat] = min;
+
+ count = FB_BACKLIGHT_LEVELS * 15 / 16;
+ for (i = 0; i < count; ++i)
+ fb_info->bl_curve[flat + i] = min + (range * (i + 1) / count);
+}
+EXPORT_SYMBOL_GPL(fb_bl_default_curve);
+#endif
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c
index 6b88050..8a0c2d3 100644
--- a/drivers/video/igafb.c
+++ b/drivers/video/igafb.c
@@ -232,9 +232,6 @@ static int igafb_mmap(struct fb_info *info,
size = vma->vm_end - vma->vm_start;
- /* To stop the swapper from even considering these pages. */
- vma->vm_flags |= (VM_SHM | VM_LOCKED);
-
/* Each page, see which map applies */
for (page = 0; page < size; ) {
map_size = 0;
diff --git a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile
index 690d37e..ca47432 100644
--- a/drivers/video/nvidia/Makefile
+++ b/drivers/video/nvidia/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_FB_NVIDIA) += nvidiafb.o
nvidiafb-y := nvidia.o nv_hw.o nv_setup.o \
nv_accel.o
nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
+nvidiafb-$(CONFIG_FB_NVIDIA_BACKLIGHT) += nv_backlight.o
nvidiafb-$(CONFIG_PPC_OF) += nv_of.o
-nvidiafb-objs := $(nvidiafb-y) \ No newline at end of file
+nvidiafb-objs := $(nvidiafb-y)
diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/nvidia/nv_backlight.c
new file mode 100644
index 0000000..1c1c10c
--- /dev/null
+++ b/drivers/video/nvidia/nv_backlight.c
@@ -0,0 +1,175 @@
+/*
+ * Backlight code for nVidia based graphic cards
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ * Copyright (c) 2006 Michael Hanselmann <linux-kernel@hansmi.ch>
+ *
+ * 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/backlight.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#include <asm/machdep.h>
+#endif
+
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
+
+static struct backlight_properties nvidia_bl_data;
+
+static int nvidia_bl_get_level_brightness(struct nvidia_par *par,
+ int level)
+{
+ struct fb_info *info = pci_get_drvdata(par->pci_dev);
+ int nlevel;
+
+ /* Get and convert the value */
+ mutex_lock(&info->bl_mutex);
+ nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
+ mutex_unlock(&info->bl_mutex);
+
+ if (nlevel < 0)
+ nlevel = 0;
+ else if (nlevel < MIN_LEVEL)
+ nlevel = MIN_LEVEL;
+ else if (nlevel > MAX_LEVEL)
+ nlevel = MAX_LEVEL;
+
+ return nlevel;
+}
+
+static int nvidia_bl_update_status(struct backlight_device *bd)
+{
+ struct nvidia_par *par = class_get_devdata(&bd->class_dev);
+ u32 tmp_pcrt, tmp_pmc, fpcontrol;
+ int level;
+
+ if (!par->FlatPanel)
+ return 0;
+
+ if (bd->props->power != FB_BLANK_UNBLANK ||
+ bd->props->fb_blank != FB_BLANK_UNBLANK)
+ level = 0;
+ else
+ level = bd->props->brightness;
+
+ tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
+ tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
+ fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
+
+ if (level > 0) {
+ tmp_pcrt |= 0x1;
+ tmp_pmc |= (1 << 31); /* backlight bit */
+ tmp_pmc |= nvidia_bl_get_level_brightness(par, level) << 16;
+ fpcontrol |= par->fpSyncs;
+ } else
+ fpcontrol |= 0x20000022;
+
+ NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
+ NV_WR32(par->PMC, 0x10F0, tmp_pmc);
+ NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
+
+ return 0;
+}
+
+static int nvidia_bl_get_brightness(struct backlight_device *bd)
+{
+ return bd->props->brightness;
+}
+
+static struct backlight_properties nvidia_bl_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = nvidia_bl_get_brightness,
+ .update_status = nvidia_bl_update_status,
+ .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
+};
+
+void nvidia_bl_init(struct nvidia_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pci_dev);
+ struct backlight_device *bd;
+ char name[12];
+
+ if (!par->FlatPanel)
+ return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (!machine_is(powermac) ||
+ !pmac_has_backlight_type("mnca"))
+ return;
+#endif
+
+ snprintf(name, sizeof(name), "nvidiabl%d", info->node);
+
+ bd = backlight_device_register(name, par, &nvidia_bl_data);
+ if (IS_ERR(bd)) {
+ info->bl_dev = NULL;
+ printk("nvidia: Backlight registration failed\n");
+ goto error;
+ }
+
+ mutex_lock(&info->bl_mutex);
+ info->bl_dev = bd;
+ fb_bl_default_curve(info, 0,
+ 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+ 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+ mutex_unlock(&info->bl_mutex);
+
+ up(&bd->sem);
+ bd->props->brightness = nvidia_bl_data.max_brightness;
+ bd->props->power = FB_BLANK_UNBLANK;
+ bd->props->update_status(bd);
+ down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+ if (!pmac_backlight)
+ pmac_backlight = bd;
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+ printk("nvidia: Backlight initialized (%s)\n", name);
+
+ return;
+
+error:
+ return;
+}
+
+void nvidia_bl_exit(struct nvidia_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pci_dev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+#endif
+
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (pmac_backlight == info->bl_dev)
+ pmac_backlight = NULL;
+#endif
+
+ backlight_device_unregister(info->bl_dev);
+
+ printk("nvidia: Backlight unloaded\n");
+ }
+ mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
index b149a69..6fba656 100644
--- a/drivers/video/nvidia/nv_proto.h
+++ b/drivers/video/nvidia/nv_proto.h
@@ -63,4 +63,14 @@ extern void nvidiafb_imageblit(struct fb_info *info,
const struct fb_image *image);
extern int nvidiafb_sync(struct fb_info *info);
extern u8 byte_rev[256];
+
+/* in nv_backlight.h */
+#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
+extern void nvidia_bl_init(struct nvidia_par *par);
+extern void nvidia_bl_exit(struct nvidia_par *par);
+#else
+static inline void nvidia_bl_init(struct nvidia_par *par) {}
+static inline void nvidia_bl_exit(struct nvidia_par *par) {}
+#endif
+
#endif /* __NV_PROTO_H__ */
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 093ab99..03a7c1e 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/console.h>
+#include <linux/backlight.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
@@ -29,10 +30,6 @@
#include <asm/prom.h>
#include <asm/pci-bridge.h>
#endif
-#ifdef CONFIG_PMAC_BACKLIGHT
-#include <asm/machdep.h>
-#include <asm/backlight.h>
-#endif
#include "nv_local.h"
#include "nv_type.h"
@@ -470,75 +467,6 @@ static struct fb_var_screeninfo __devinitdata nvidiafb_default_var = {
.vmode = FB_VMODE_NONINTERLACED
};
-/*
- * Backlight control
- */
-#ifdef CONFIG_PMAC_BACKLIGHT
-
-static int nvidia_backlight_levels[] = {
- 0x158,
- 0x192,
- 0x1c6,
- 0x200,
- 0x234,
- 0x268,
- 0x2a2,
- 0x2d6,
- 0x310,
- 0x344,
- 0x378,
- 0x3b2,
- 0x3e6,
- 0x41a,
- 0x454,
- 0x534,
-};
-
-/* ------------------------------------------------------------------------- *
- *
- * Backlight operations
- *
- * ------------------------------------------------------------------------- */
-
-static int nvidia_set_backlight_enable(int on, int level, void *data)
-{
- struct nvidia_par *par = data;
- u32 tmp_pcrt, tmp_pmc, fpcontrol;
-
- tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
- tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
- fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
-
- if (on && (level > BACKLIGHT_OFF)) {
- tmp_pcrt |= 0x1;
- tmp_pmc |= (1 << 31); // backlight bit
- tmp_pmc |= nvidia_backlight_levels[level - 1] << 16;
- }
-
- if (on)
- fpcontrol |= par->fpSyncs;
- else
- fpcontrol |= 0x20000022;
-
- NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
- NV_WR32(par->PMC, 0x10F0, tmp_pmc);
- NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
-
- return 0;
-}
-
-static int nvidia_set_backlight_level(int level, void *data)
-{
- return nvidia_set_backlight_enable(1, level, data);
-}
-
-static struct backlight_controller nvidia_backlight_controller = {
- nvidia_set_backlight_enable,
- nvidia_set_backlight_level
-};
-
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
u16 bg, u16 fg, u32 w, u32 h)
{
@@ -1355,10 +1283,15 @@ static int nvidiafb_blank(int blank, struct fb_info *info)
NVWriteSeq(par, 0x01, tmp);
NVWriteCrtc(par, 0x1a, vesa);
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (par->FlatPanel && machine_is(powermac)) {
- set_backlight_enable(!blank);
+#ifdef CONFIG_FB_NVIDIA_BACKLIGHT
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = blank;
+ info->bl_dev->props->update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
}
+ mutex_unlock(&info->bl_mutex);
#endif
NVTRACE_LEAVE();
@@ -1741,11 +1674,9 @@ static int __devinit nvidiafb_probe(struct pci_dev *pd,
"PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
info->fix.id,
par->FbMapSize / (1024 * 1024), info->fix.smem_start);
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (par->FlatPanel && machine_is(powermac))
- register_backlight_controller(&nvidia_backlight_controller,
- par, "mnca");
-#endif
+
+ nvidia_bl_init(par);
+
NVTRACE_LEAVE();
return 0;
@@ -1775,6 +1706,8 @@ static void __exit nvidiafb_remove(struct pci_dev *pd)
NVTRACE_ENTER();
+ nvidia_bl_exit(par);
+
unregister_framebuffer(info);
#ifdef CONFIG_MTRR
if (par->mtrr.vram_valid)
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 3e9308f..d4384ab 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -41,6 +41,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/backlight.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
@@ -272,34 +273,154 @@ static const struct riva_regs reg_template = {
/*
* Backlight control
*/
-#ifdef CONFIG_PMAC_BACKLIGHT
+#ifdef CONFIG_FB_RIVA_BACKLIGHT
+/* We do not have any information about which values are allowed, thus
+ * we used safe values.
+ */
+#define MIN_LEVEL 0x158
+#define MAX_LEVEL 0x534
-static int riva_backlight_levels[] = {
- 0x158,
- 0x192,
- 0x1c6,
- 0x200,
- 0x234,
- 0x268,
- 0x2a2,
- 0x2d6,
- 0x310,
- 0x344,
- 0x378,
- 0x3b2,
- 0x3e6,
- 0x41a,
- 0x454,
- 0x534,
-};
+static struct backlight_properties riva_bl_data;
+
+static int riva_bl_get_level_brightness(struct riva_par *par,
+ int level)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ int nlevel;
+
+ /* Get and convert the value */
+ mutex_lock(&info->bl_mutex);
+ nlevel = info->bl_curve[level] * FB_BACKLIGHT_MAX / MAX_LEVEL;
+ mutex_unlock(&info->bl_mutex);
+
+ if (nlevel < 0)
+ nlevel = 0;
+ else if (nlevel < MIN_LEVEL)
+ nlevel = MIN_LEVEL;
+ else if (nlevel > MAX_LEVEL)
+ nlevel = MAX_LEVEL;
+
+ return nlevel;
+}
+
+static int riva_bl_update_status(struct backlight_device *bd)
+{
+ struct riva_par *par = class_get_devdata(&bd->class_dev);
+ U032 tmp_pcrt, tmp_pmc;
+ int level;
+
+ if (bd->props->power != FB_BLANK_UNBLANK ||
+ bd->props->fb_blank != FB_BLANK_UNBLANK)
+ level = 0;
+ else
+ level = bd->props->brightness;
+
+ tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
+ tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
+ if(level > 0) {
+ tmp_pcrt |= 0x1;
+ tmp_pmc |= (1 << 31); /* backlight bit */
+ tmp_pmc |= riva_bl_get_level_brightness(par, level) << 16; /* level */
+ }
+ par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
+ par->riva.PMC[0x10F0/4] = tmp_pmc;
+
+ return 0;
+}
+
+static int riva_bl_get_brightness(struct backlight_device *bd)
+{
+ return bd->props->brightness;
+}
-static int riva_set_backlight_enable(int on, int level, void *data);
-static int riva_set_backlight_level(int level, void *data);
-static struct backlight_controller riva_backlight_controller = {
- riva_set_backlight_enable,
- riva_set_backlight_level
+static struct backlight_properties riva_bl_data = {
+ .owner = THIS_MODULE,
+ .get_brightness = riva_bl_get_brightness,
+ .update_status = riva_bl_update_status,
+ .max_brightness = (FB_BACKLIGHT_LEVELS - 1),
};
-#endif /* CONFIG_PMAC_BACKLIGHT */
+
+static void riva_bl_init(struct riva_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+ struct backlight_device *bd;
+ char name[12];
+
+ if (!par->FlatPanel)
+ return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (!machine_is(powermac) ||
+ !pmac_has_backlight_type("mnca"))
+ return;
+#endif
+
+ snprintf(name, sizeof(name), "rivabl%d", info->node);
+
+ bd = backlight_device_register(name, par, &riva_bl_data);
+ if (IS_ERR(bd)) {
+ info->bl_dev = NULL;
+ printk("riva: Backlight registration failed\n");
+ goto error;
+ }
+
+ mutex_lock(&info->bl_mutex);
+ info->bl_dev = bd;
+ fb_bl_default_curve(info, 0,
+ 0x158 * FB_BACKLIGHT_MAX / MAX_LEVEL,
+ 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL);
+ mutex_unlock(&info->bl_mutex);
+
+ up(&bd->sem);
+ bd->props->brightness = riva_bl_data.max_brightness;
+ bd->props->power = FB_BLANK_UNBLANK;
+ bd->props->update_status(bd);
+ down(&bd->sem);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+ if (!pmac_backlight)
+ pmac_backlight = bd;
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+
+ printk("riva: Backlight initialized (%s)\n", name);
+
+ return;
+
+error:
+ return;
+}
+
+static void riva_bl_exit(struct riva_par *par)
+{
+ struct fb_info *info = pci_get_drvdata(par->pdev);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_lock(&pmac_backlight_mutex);
+#endif
+
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+#ifdef CONFIG_PMAC_BACKLIGHT
+ if (pmac_backlight == info->bl_dev)
+ pmac_backlight = NULL;
+#endif
+
+ backlight_device_unregister(info->bl_dev);
+
+ printk("riva: Backlight unloaded\n");
+ }
+ mutex_unlock(&info->bl_mutex);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+ mutex_unlock(&pmac_backlight_mutex);
+#endif
+}
+#else
+static inline void riva_bl_init(struct riva_par *par) {}
+static inline void riva_bl_exit(struct riva_par *par) {}
+#endif /* CONFIG_FB_RIVA_BACKLIGHT */
/* ------------------------------------------------------------------------- *
*
@@ -973,36 +1094,6 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
/* ------------------------------------------------------------------------- *
*
- * Backlight operations
- *
- * ------------------------------------------------------------------------- */
-
-#ifdef CONFIG_PMAC_BACKLIGHT
-static int riva_set_backlight_enable(int on, int level, void *data)
-{
- struct riva_par *par = data;
- U032 tmp_pcrt, tmp_pmc;
-
- tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
- tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
- if(on && (level > BACKLIGHT_OFF)) {
- tmp_pcrt |= 0x1;
- tmp_pmc |= (1 << 31); // backlight bit
- tmp_pmc |= riva_backlight_levels[level-1] << 16; // level
- }
- par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
- par->riva.PMC[0x10F0/4] = tmp_pmc;
- return 0;
-}
-
-static int riva_set_backlight_level(int level, void *data)
-{
- return riva_set_backlight_enable(1, level, data);
-}
-#endif /* CONFIG_PMAC_BACKLIGHT */
-
-/* ------------------------------------------------------------------------- *
- *
* framebuffer operations
*
* ------------------------------------------------------------------------- */
@@ -1247,10 +1338,15 @@ static int rivafb_blank(int blank, struct fb_info *info)
SEQout(par, 0x01, tmp);
CRTCout(par, 0x1a, vesa);
-#ifdef CONFIG_PMAC_BACKLIGHT
- if ( par->FlatPanel && machine_is(powermac)) {
- set_backlight_enable(!blank);
+#ifdef CONFIG_FB_RIVA_BACKLIGHT
+ mutex_lock(&info->bl_mutex);
+ if (info->bl_dev) {
+ down(&info->bl_dev->sem);
+ info->bl_dev->props->power = blank;
+ info->bl_dev->props->update_status(info->bl_dev);
+ up(&info->bl_dev->sem);
}
+ mutex_unlock(&info->bl_mutex);
#endif
NVTRACE_LEAVE();
@@ -2037,11 +2133,9 @@ static int __devinit rivafb_probe(struct pci_dev *pd,
RIVAFB_VERSION,
info->fix.smem_len / (1024 * 1024),
info->fix.smem_start);
-#ifdef CONFIG_PMAC_BACKLIGHT
- if (default_par->FlatPanel && machine_is(powermac))
- register_backlight_controller(&riva_backlight_controller,
- default_par, "mnca");
-#endif
+
+ riva_bl_init(info->par);
+
NVTRACE_LEAVE();
return 0;
@@ -2074,6 +2168,8 @@ static void __exit rivafb_remove(struct pci_dev *pd)
NVTRACE_ENTER();
+ riva_bl_exit(par);
+
#ifdef CONFIG_FB_RIVA_I2C
riva_delete_i2c_busses(par);
kfree(par->EDID);
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 9ac2d31..41f8c2d 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -551,7 +551,7 @@ static inline void enable_mmio(void)
#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
/* Return flat panel's maximum x resolution */
-static int __init get_nativex(void)
+static int __devinit get_nativex(void)
{
int x,y,tmp;
@@ -658,7 +658,7 @@ static void set_number_of_lines(int lines)
* If we see that FP is active we assume we have one.
* Otherwise we have a CRT display.User can override.
*/
-static unsigned int __init get_displaytype(void)
+static unsigned int __devinit get_displaytype(void)
{
if (fp)
return DISPLAY_FP;
@@ -668,7 +668,7 @@ static unsigned int __init get_displaytype(void)
}
/* Try detecting the video memory size */
-static unsigned int __init get_memsize(void)
+static unsigned int __devinit get_memsize(void)
{
unsigned char tmp, tmp2;
unsigned int k;
OpenPOWER on IntegriCloud